the code that I will present now, is made with vaadin and the ApexChart addon, I simply want to update the line-type graph in real time, I have the @Push
annotation in the MainView and a ScheduledExecutorService that runs every second
Vaadin version is 14.1.27
Apexcharts Addon
<dependency>
<groupId> com.github.appreciated </groupId>
<artifactId> apexcharts </artifactId>
<version> 2.0.0.beta9 </version>
</dependency>
Apache Tomcat/9.0.27
I make a simple request, then within the access(()-> )
method, finally invokes chart.updateSeries()
Code
public void updateChar() {
final ApexCharts chart = ApexChartsBuilder.get().withChart(ChartBuilder.get()
.withType(Type.line)
.withAnimations(AnimationsBuilder.get()
.withEnabled(true)
.withEasing(Easing.linear)
.withDynamicAnimation(DynamicAnimationBuilder.get()
.withSpeed(1000)
.build())
.build())
.build())
.withDataLabels(DataLabelsBuilder.get()
.withEnabled(false)
.build())
.withSeries(new Series<>(0))
.withXaxis(XAxisBuilder.get()
.withCategories()
.withMax(10.0)
.build())
.build();
chart.setHeight("400px");
chart.setWidth("400px");
schedule.scheduleAtFixedRate(() -> {
try {
final CompletableFuture<String> cf = HttpClient
.newBuilder()
.build()
.sendAsync(HttpRequest
.newBuilder(new URI(HUMIDITY))
.GET()
.version(HttpClient.Version.HTTP_2)
.build(),
HttpResponse.BodyHandlers.ofString())
.thenApplyAsync(HttpResponse::body);
cf.whenCompleteAsync((data, error) -> {
if (getUI().isEmpty()) return;
if (Objects.nonNull(error)) {
cf.completeExceptionally(error);
getUI().get().access(() -> {
Notification.show("Error: " + error);
});
} else {
if (getUI().isEmpty()) return;
getUI().get().access(() -> {
final SecureRandom random = new SecureRandom();
final Series<Double> series = new Series<>(25.2, 30.2, 25.77, 45.66, 60.00, 55.5);
final Series<Double> serie1 = new Series<>(30.3, 34.10, 20.11, 12.15, 55.66, 82.5, 64.35, 100.4, 77.66, 14.32, 25.77);
final Series<Double> serie2 = new Series<>(25.5, 55.3, 44.5, 99.6, 10.3, 44.6, 36.6);
final Series[] randomSeries = new Series[]{series, serie1, serie2, series};
//chart.updateSeries(radomSeries[SECURE_RANDOM.nextInt(randomSeries .length)]);
chart.updateSeries(new Series<>(data));
});
}
}, EXEC)
.join();
} catch (URISyntaxException e) {
throw new RuntimeException();
}
}, 1, 1, TimeUnit.SECONDS);
}
unfortunately the result is not as expected, with the same code, I am able to update TextFields
Updated
The current solution I have, is to use list to store the Timestamps and double values of the sensors.
this constant is very important for resolution in seconds.
Also under background I use WebClient
and changed the default configuration of reactor-netty to retry every 2 seconds.
@Bean
public WebClient sensorWebClientBuilder(final WebClient.Builder webClient) {
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
.doOnConnected((Connection connection) ->
connection.addHandlerLast(new ReadTimeoutHandler(2000, TimeUnit.MILLISECONDS)));
return webClient
.clientConnector(new ReactorClientHttpConnector(httpClient))
.baseUrl(BASE_URL)
.build();
}