Plotting using NodeMCU ESP8285

Luego de flashear nuestro ESP8285 si que seria interesante darle otro uso que solo prender o apagar un simple led.

Que tal si graficamos la temperatura y humedad con el? asΓ­ como cualquier otro sensor que reaccione a esos cambios ambientales.

Si que necesitamos que el corra el siguiente cΓ³digo para habilitar los enpoints que consumiremos con WebClient de Spring WebFlux (el cliente reactivo de spring construido sobre project reactor).

La animaciΓ³n siguiente muestra un Grid y un Chart donde se grafican nuestros dos sensores en tiempo real, si que toca darle crΓ©ditos a @Detlef Boehm por los tips a la hora de graficar.

private static final String FORMATTER_TIMESTAMP = "function (value, timestamp) {\n" +
        "  var date = new Date(timestamp);" +
        "  var hours = date.getHours();\n" +
        "  var minutes = date.getMinutes();\n" + 
        "  var seconds = date.getSeconds();" +
        "  var ampm = hours >= 12 ? "pm" : "am";\n" +
        "  hours = hours % 12;\n" +
        "  hours = hours ? hours : 12; // the hour "0" should be "12"\n" +
        "  minutes = minutes < 10 ? "0"+minutes : minutes;\n" +
        "  return hours + ":" + minutes + ":" + ("0"+seconds).slice(-2) + " " + ampm;\n" +
        "}";

Con WebClient tenemos una configuracion por defecto con la URL base SensorWebClientBuilderConfiguration que usamos en dos lugares uno para consumir el endpoint de los sensores y el otro para encender el led.

WebClient usa internamente una conexiΓ³n por defecto con reactor netty, entonces cuando no tengamos respuesta de nuestro micro, el error se muestra al cliente luego de esperar 30 segundos.

Para notificar al cliente mΓ‘s rapido nuestro bean quedarΓ‘ de la siguiente manera:

@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();
}
  • Se configura una instancia del cliente reactor netty
  • Timeout de 2 segundos
  • ReadTimeout con 2 segundos como mΓ­nimo.
  • Se establece el cliente de reactor netty en el WebClient

Endpoint de los sensores

this.webClient
    .get()
    .uri(DHT_22)
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(SensorDht22Mapper.class)
    .delaySubscription(Duration.ofSeconds(2)) 
    .repeat()
    .doOnError((Throwable throwable) -> { 
        log.warn("Error {}", throwable);
        ui.access(() -> this.showError(throwable.getMessage()));
    })
    .retryWhen(Retry.indefinitely()); 
  • Si que debemos hacer un delay de 2 segundos y repetir la suscripciΓ³n para obtener los datos actualizados.
  • En caso de error notificar al usuario gracias al uso del operador doOnError.
  • Nos resuscribirnos con retryWhen indefinidamente en caso de error.

Endpoint del led

Hacemos un put con las query-parameters necesarias ?id=2&status={on/off}

this.webClient
    .put()
    .uri(functionQueryParameters) 
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(SensorDht22.class)
  .doOnError(error -> ui.access(() -> Notification.show(error.getMessage())))
    .subscribe(sensorDht22 -> {
        ui.access(() -> {
            Notification.show(sensorDht22.getStatus());
        });
    });
  • Es la funciΓ³n que nos permite crear la query por medio de un builder.
  • Si hay error notificamos al cliente.

Vista principal de los sensores πŸ”₯

image

Notificar si el micro se cae.

Simulando que el micro no este disponible, lo hacemos quitandole la tensiΓ³n y despuΓ©s de 2 segundos sin respuesta, el backend desde Vaadin notificara al cliente.

image


  • Esta pendiente exportar los datos del grid a otros formatos, pdf-excell-txt-csv etc…

  • source

Comments