ESPHome Weather Station LCD with Nextion 2.4 inch display and WeMos D1 Mini

Hello ESPHome lovers, today i have great news for everyone of you.

Thanks to Vaclav who kindly shared his process on how to build an esphome lcd weather station, i have been able to make a tutorial video available on youtube.

If you want to make a big step forward in the future of home automation this integration should definitely help you.

The video is in french but if you are familiar to ESPHome you will quickly understand.

I never posted a link on any of my videos about Home Assistant on this forum before, so if you like my work please subscribe to my channel it will help me to grow faster.

Thanks les Homies !

5 Likes

Thank you for the share.
I have been playing with my nextion for a long time but am not able to get it to work with any programming.
The only thing i do get is:
[W][nextion:083]: Sending command ‘inside.txt=“23.8”’ failed because no ACK was receivede
I did change the pins around in the software and physical but nothing works
I am using a 5" display but that should not really care i guess

I think Nextion does not send ACKs by it self. I had a similar issue with buttons and I was able to get rid of the issue by enabling “Send Component ID” for both touch press and release events of the button. I am not sure how to send component ids for text boxes.

There is an ack solution here. https://github.com/bruxy70/Home-Assistant-ESPHome-Weather-Station/blob/9e4a55b66b799ca3f77b34a5954459f797563265/display_weather.yaml

I have the same issue when I try to use the Nextion display with esphome and D1 Wemo. Anyone get it to work without these error: 21:34:13][W][nextion:037]: Waiting for ACK timed out!
[21:34:13](Message skipped because it was too big to fit in TCP buffer - This is only cosmetic)
[21:34:19][W][nextion:037]: Waiting for ACK timed out!
[21:34:19][W][nextion:084]: Sending command ‘dim=30’ failed because no ACK was received

Read up one post.

This is first thing I did is follow the video and steps by steps but the display only show the tft file screen. No numbers update from the esphome shows up. I even reverse the tx and rx pins still not working. What I did wrong?? I been debugging and try various examples for whole 2 weeks and not working. Only examples that works is the HASwitch plate using MQTT but it create many automation on the HA that I do not like. I like the esphome method. Any hint on what I did wrong?

Yepp, same here. Tried to replicate the above project but as @MrTeaIOT told, I’m only get the TFT shown on the screen without any sensor input. As if there is no value at all from the sensors in homeassistant.
Tried to check some sensors on other nodes at they work flawlessly. Now I try to figure out which part is actually wrong in the code provided.

Here is my updated config:

# This is ESPHome configuration file. This goes to the esphome folder
# You need to provide your WiFi ssis/password and passwords for API and OTA (or put them in your esphome/secrets.yaml)
esphome:
  name: station_meteo_lcd
  platform: ESP8266
  board: d1_mini_pro

wifi:
  ssid: YOURS
  password: !secret wifi_password
  fast_connect: true

api:

ota:

logger:
  baud_rate: 0     # Disable UART logging (pins GPIO1/3 are used for Nextion communication)

uart:
  rx_pin: D1
  tx_pin: D6
  baud_rate: 9600

time:
  - platform: sntp
    id: sntp_time

sensor:
  - platform: homeassistant   # Inside temperature
    id: temperature_inside
    entity_id: sensor.netatmo_indoor_temperature
  - platform: homeassistant   # Outside temperature
    id: temperature_outside    
    entity_id: sensor.saint_tropez_temperature
  - platform: homeassistant   # Swimming pool
    id: temperature_pool
    entity_id: sensor.cpu_temp
  - platform: homeassistant   # Forecast minimal temperature
    id: today_min
    entity_id: sensor.saint_tropez_temperature_minimale_pour_demain
  - platform: homeassistant   # Forecast maximal temperature
    id: today_max
    entity_id: sensor.saint_tropez_temperature_maximale_pour_demain
  - platform: homeassistant   # Forecast precipitation
    id: today_rain
    entity_id: sensor.saint_tropez_rain_chance
  - platform: homeassistant   # Forecast icon
    id: today_icon
    entity_id: sensor.today_icon

binary_sensor:
  - platform: homeassistant
    id: somebody_home
    entity_id: binary_sensor.somebody_home

globals:
 - id: first_page             # First page of the display?
   type: bool
   restore_value: no
 - id: display_on             # Is display on?
   type: bool
   restore_value: no
   
display:
  - platform: nextion
    id: teplomer
    update_interval: 5s
    lambda: |-
      // Turn display on when somebody is home. Only update when display on.
      if (id(somebody_home).state) {
        if (!id(display_on)) {
          it.set_backlight_brightness(50);
          id(display_on)=true;
        }
        // Swich first/second page on each update (every 5 seconds)
        if (id(first_page)) {
          it.goto_page("forecast");
          it.send_command_printf("%s.pic=%.0f", "weather",id(today_icon).state);
          it.set_component_text_printf("minmax","%.0f/%.0f",id(today_min).state,id(today_max).state);
          if (isnan(id(today_rain).state)) {
            it.set_component_text("rain","-");
          } else {
            it.set_component_text_printf("rain","%.0f",id(today_rain).state);
          }
          auto time = id(sntp_time).now();
          it.set_component_text_printf("hour","%02d",time.hour);
          it.set_component_text_printf("minute","%02d",time.minute);
        } else {
          it.goto_page("temperature");
          it.set_component_text_printf("inside","%2.1f",id(temperature_inside).state);
          it.set_component_text_printf("outside","%2.1f",id(temperature_outside).state);
          it.set_component_text_printf("pool","%2.1f",id(temperature_pool).state);
        }
        id(first_page) = !id(first_page);  // Switch page
      } else {
        // Turn off the display if nobody is home. 
        if (id(display_on)) {
          it.set_backlight_brightness(0);
          id(display_on)=false;
        }
      }

It’s working perfectly for me. Follow the process shown in the video and you should be good.

Hi
I used your code on my project with nextion and esphome, managed to go back and forth on two pages.Is there any way to make a loop on more pages,like 4 or 5?

This example has multiple pages https://github.com/Andoramb/Nextion-wall-mount/blob/799f5ffd5a192171a7928900041d2d9c601b64e4/YAML/NextionDisplay.yaml

Hi, I tried this project, but I can’t really get it to work properly.

This display works, if I change the brightness in the code, the brightness of my display changes, but it’s not receiving any (weather) data, though the HA sensors do have data.

My configs:

esphome:

esphome:
  name: esp_weather01
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: !secret esphome_wifi_ssid
  password: !secret esphome_wifi_password

api:
  password: !secret esphome_api_password

ota:
  password: !secret esphome_ota_password
  
web_server:
  port: 80

logger:
  baud_rate: 0     # Disable UART logging (pins GPIO1/3 are used for Nextion communication)

uart:
  rx_pin: D1
  tx_pin: D2
  baud_rate: 9600

time:
  - platform: sntp
    id: sntp_time

sensor:
  - platform: homeassistant   # Inside temperature
    id: temperature_inside
    entity_id: sensor.woonkamer_temperatuur
  - platform: homeassistant   # Outside temperature
    id: temperature_outside    
    entity_id: sensor.nefit_outdoor_temperature
  - platform: homeassistant   # Swimming pool
    id: temperature_pool
    entity_id: sensor.hue_outdoor_sensor_carport_temperature
  - platform: homeassistant   # Forecast minimal temperature
    id: today_min
    entity_id: sensor.today_min
  - platform: homeassistant   # Forecast maximal temperature
    id: today_max
    entity_id: sensor.today_max
  - platform: homeassistant   # Forecast precipitation
    id: today_rain
    entity_id: sensor.today_rain
  - platform: homeassistant   # Forecast icon
    id: today_icon
    entity_id: sensor.today_icon

binary_sensor:
  - platform: homeassistant
    id: somebody_home
    entity_id: sensor.anybody_home_binary

globals:
 - id: first_page             # First page of the display?
   type: bool
   restore_value: no
 - id: display_on             # Is display on?
   type: bool
   restore_value: no
   
display:
  - platform: nextion
    id: teplomer
    update_interval: 5s
    lambda: |-
      // Turn display on when somebody is home. Only update when display on.
      if (id(somebody_home).state) {
        if (!id(display_on)) {
          it.set_backlight_brightness(50);
          id(display_on)=true;
        }
        // Swich first/second page on each update (every 5 seconds)
        if (id(first_page)) {
          it.goto_page("forecast");
          it.send_command_printf("%s.pic=%.0f", "weather",id(today_icon).state);
          it.set_component_text_printf("minmax","%.0f/%.0f",id(today_min).state,id(today_max).state);
          if (isnan(id(today_rain).state)) {
            it.set_component_text("rain","-");
          } else {
            it.set_component_text_printf("rain","%.0f",id(today_rain).state);
          }
          auto time = id(sntp_time).now();
          it.set_component_text_printf("hour","%02d",time.hour);
          it.set_component_text_printf("minute","%02d",time.minute);
        } else {
          it.goto_page("temperature");
          it.set_component_text_printf("inside","%2.1f",id(temperature_inside).state);
          it.set_component_text_printf("outside","%2.1f",id(temperature_outside).state);
          it.set_component_text_printf("pool","%2.1f",id(temperature_pool).state);
        }
        id(first_page) = !id(first_page);  // Switch page
      } else {
        // Turn off the display if nobody is home. 
        if (id(display_on)) {
          it.set_backlight_brightness(0);
          id(display_on)=false;
        }
      }

HA:

weather:
  - platform: darksky
    api_key: !secret darksky_api_key
    mode: daily
    
sensor:
######## darksky #########
  - platform: darksky
    api_key: !secret darksky_api_key
    monitored_conditions:
      - precip_probability
      - precip_intensity
      - precip_intensity_max
      - nearest_storm_distance
      - nearest_storm_bearing
      - temperature
      - apparent_temperature_high
      - temperature_high  

  - platform: template
    sensors:
      sun_elevation:
        friendly_name: "Sun Elevation"
        unit_of_measurement: 'degrees'
        value_template: "{{ state_attr('sun.sun', 'elevation') }}"

  - platform: template
    sensors:
      today_min:
        value_template: "{{ state_attr('weather.dark_sky','forecast')[0].templow | default('0') }}"
        friendly_name: Today's maximal temperature
      today_max:
        value_template: "{{ state_attr('weather.dark_sky','forecast')[0].temperature | default('0') }}"
        friendly_name: Today's minimal temperature
      today_rain:
        value_template: "{{ state_attr('weather.dark_sky','forecast')[0].precipitation | default('0') }}"
        friendly_name: Today's rain forecast
      today_icon:
        value_template: >-
          {% if state_attr("weather.dark_sky","forecast")[0].condition =='clear-night' %}
            3
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='cloudy' %}
            5
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='fog' %}
            16
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='hail' %}
            6
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='lightning' %}
            13
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='lightning-rainy' %}
            17
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='partlycloudy' %}
            8
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='pouring' %}
            18
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='rainy' %}
            9
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='snowy' %}
            11
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='snowy-rainy' %}
            7
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='windy' %}
            14
          {% elif state_attr("weather.dark_sky","forecast")[0].condition =='windy-variant' %}
            14
          {% else %}
            12
          {% endif %}
        friendly_name: Today weather forecast

Try with the yellow cable on pin D6.

Thanks, but I don;t think the communication with the display is the issue here since as I wrote, changing the display brightness in de esphome config does work and actually changes brightness.

Anyway I have tried your suggestion and changed the config to:

uart:
  rx_pin: D1
  tx_pin: D6
  baud_rate: 9600

And moved the yellow wire to D6, but no change. Still no weather data and the pages do not change every 5 seconds.

Still can’t get it to work.
Because it looks like all sensor data is not available, i created a template switch to dump all values in the log:

switch:
  - platform: template
    name: "log switch"
    turn_on_action:
      - lambda: |-
          ESP_LOGI("main", "Value of temperature_inside: %f", id(temperature_inside).state);
          ESP_LOGI("main", "Value of temperature_outside: %f", id(temperature_outside).state);
          ESP_LOGI("main", "Value of temperature_pool: %f", id(temperature_pool).state);
          ESP_LOGI("main", "Value of today_min: %f", id(today_min).state);
          ESP_LOGI("main", "Value of today_max: %f", id(today_max).state);
          ESP_LOGI("main", "Value of today_rain: %f", id(today_rain).state);
          ESP_LOGI("main", "Value of somebody_home: %f", id(somebody_home).state);

this outputs:

[D][switch:029]: ‘log switch’ Toggling ON.e
[I][main:369]: Value of temperature_inside: nane
[I][main:370]: Value of temperature_outside: nane
[I][main:371]: Value of temperature_pool: nane
[I][main:372]: Value of today_min: nane
[I][main:373]: Value of today_max: nane
[I][main:374]: Value of today_rain: nane
[I][main:375]: Value of somebody_home: 0.000000e

which does not correspond to my HA data at all:

What am I missing here?

The missing data turned out to be a API issue.

I now have data, but the data is still not visible on the display.

[I][main:369]: Value of temperature_inside: 21.600000e
[I][main:370]: Value of temperature_outside: 11.000000e
[I][main:371]: Value of temperature_pool: 12.000000e
[I][main:372]: Value of today_min: 1.600000e
[I][main:373]: Value of today_max: 12.400000e
[I][main:374]: Value of today_rain: nane
[I][main:375]: Value of somebody_home: 0.000000e

I don’t know how to debug this any further. The lambda programming is not my thing.

Anybody willing to share their thoughts or configs?

Try changing your sensor to text_sensor. This is how I have mine to feed data to a small oled display -

text_sensor:
  - platform: homeassistant
    name: "PM 2.5"
    id: pm25
    entity_id: sensor.particulate_matter_2_5um_concentration
    
  - platform: homeassistant
    name: "PM 10"
    id: pm10
    entity_id: sensor.particulate_matter_10_0um_concentration
    

Thanks, but that does not help either.

Debug log:

[D][api.connection:604]: Client 'Home Assistant 2021.3.4 (192.168.207.101)' connected successfully!e
[W][homeassistant.binary_sensor:016]: Can't convert '1' to binary state!e
[D][homeassistant.sensor:019]: 'sensor.woonkamer_temperatuur': Got state 21.15e
[D][sensor:092]: 'Inside temperature': Sending state 21.15000  with 1 decimals of accuracye
[D][homeassistant.sensor:019]: 'sensor.nefit_outdoor_temperature': Got state 7.00e
[D][sensor:092]: 'Outside temperature': Sending state 7.00000  with 1 decimals of accuracye
[D][homeassistant.sensor:019]: 'sensor.hue_outdoor_sensor_carport_temperature': Got state 8.18e
[D][sensor:092]: 'Pool temperature': Sending state 8.18000  with 1 decimals of accuracye
[D][homeassistant.sensor:019]: 'sensor.today_min': Got state 4.90e
[D][sensor:092]: 'Minimum temperature': Sending state 4.90000  with 1 decimals of accuracye
[D][homeassistant.sensor:019]: 'sensor.today_max': Got state 12.20e
[D][sensor:092]: 'Maximum temperature': Sending state 12.20000  with 1 decimals of accuracye
[D][homeassistant.sensor:019]: 'sensor.today_rain': Got state 0.10e
[D][sensor:092]: 'Rain today': Sending state 0.10000  with 1 decimals of accuracye
[D][homeassistant.sensor:019]: 'sensor.today_icon': Got state 8.00e
[D][sensor:092]: 'Icon': Sending state 8.00000  with 1 decimals of accuracye
[D][sntp:056]: Synchronized time: Sun Apr  4 11:39:05 2021e

What kind of value is expected from the “somebody home” sensor?
I am now feeding it either “1” (somebody home) or “0” (nobody home)

It works. I had to change the “somebody_home” sensor from binary_sensor to sensor.

What do u mean by api issue? How did u manage to show sensor data?