OLED Display lambda function read home assistant sensor

Hey,
I have a working config that i’m struggling to expand.
An oled screen is showing various img’s and mqtt values, rotating between pages.

The final page i’m adding has been stumped, im pulling in sensor data from home assistant (temp / hum) and looking to display it but im hitting issues, i believe with the data type.
I’ve tried chaning %s, %d and removing the .state.c_str() at the end of the line - all with varying levels of fail, none just pass the value which is currently 26.1.

Can anyone shed any light on how i should be pulling in this sensor data?

sensor:
  - platform: homeassistant
    id: officetemp
    name: "Office Temp"
    entity_id: sensor.4_in_1_multisensor_air_temperature
    internal: true
    attribute: state
  - platform: homeassistant
    id: officehumid
    name: "Office Humidity"
    entity_id: sensor.4_in_1_multisensor_humidity
    internal: true
    attribute: state
text_sensor:
  - platform: mqtt_subscribe
    name: "OLED1_Text"
    id: oled1_text
    topic: oled1/notify
  - platform: mqtt_subscribe
    name: "OLED1_Text2"
    id: oled1_text2
    topic: oled1/notify2
  - platform: mqtt_subscribe
    name: "OLED1_Icon"
    id: oled1_icon
    topic: oled1/icon

font:
  - file: 'arial.ttf'
    id: font1
    size: 15
  - file: 'FontAwesome.ttf'
    id: font2
    size: 24

i2c:
  sda: D2
  scl: D1
  scan: True
  
time:
  - platform: homeassistant
    id: homeassistant_time

image:
  - file: "bell-regular.png"
    id: bell
    resize: 32x32
    type: TRANSPARENT_BINARY
  - file: "down-cloud.jpg"
    id: downcloud
    resize: 32x32
    type: TRANSPARENT_BINARY
  - file: "plex.png"
    id: plex
    resize: 32x32
  - file: "down-cloud2.jpg"
    id: downcloud2
    resize: 32x32

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x32"
    id: oled1
    pages:
      - id: page1 # Plex currently viewing
        lambda: |-
          it.image(0, 0, id(plex));
          it.printf(38, 8, id(font1), "%s", id(oled1_text).state.c_str());
      - id: page2 # Home Assistant time / date
        lambda: |-
          it.strftime(0, 0, id(font1), "%H:%M", id(homeassistant_time).now());
          it.strftime(0, 16, id(font1), "%d.%m.%Y", id(homeassistant_time).now());
      - id: page3 # SabNZBd download rate
        lambda: |-
          it.image(0, 0, id(downcloud2));
          it.printf(38, 8, id(font1), "%s", id(oled1_text2).state.c_str());
      - id: page4 # Office Temp / Hum
        lambda: |-
          it.printf(0, 0, id(font1), "%s", id(officetemp).state.c_str());
          it.printf(0, 16, id(font1), "%s", id(officehumid).state.c_str());
interval:
  - interval: 15s
    then:
      - display.page.show_next: oled1
      - component.update: oled1

Build error:

/config/oled1.yaml: In lambda function:
/config/oled1.yaml:114:54: error: request for member 'c_str' in 'officetemp->esphome::homeassistant::HomeassistantSensor::<anonymous>.esphome::sensor::Sensor::state', which is of non-class type 'float'
  114 |           it.printf(0, 0, id(font1), "%s", id(officetemp).state.c_str());
      |                                                      ^~~~~
/config/oled1.yaml:115:56: error: request for member 'c_str' in 'officehumid->esphome::homeassistant::HomeassistantSensor::<anonymous>.esphome::sensor::Sensor::state', which is of non-class type 'float'
  115 |           it.printf(0, 16, id(font1), "%s", id(officehumid).state.c_str());
      |                                                        ^~~~~
*** [.pioenvs/oled1/src/main.cpp.o] Error 1
1 Like
      - id: page4 # Office Temp / Hum
        lambda: |-
          it.printf(0, 0, id(font1), "%.1f", id(officetemp).state);
          it.printf(0, 16, id(font1), "%.1f", id(officehumid).state);

by changing to the above - %.1f instead of %s or %d, and removing c_str() now lets it build without error, but the display shows nan - for both entries (not a number).

Pretty sure this is down to the string or data type, but im clearly out of my depth.

      - id: page4 # Office Temp / Hum
        lambda: |-
          it.printf(0, 0, id(font1), "%.1f", id(officetemp).state);
          it.printf(0, 16, id(font1), "%.1f", id(officehumid).state);

ok got it :slight_smile:

Let’s break %.1f down:

  • % - initiate the format string
  • .1 - round the decimal number to 1 digits after the decimal point.
  • f - the specifier which tells printf the data type of the argument. Here it is a f(loat).

For example, if you would like to print a sensor value with two digits of accuracy, you would write %.2f and with zero digits of accuracy (without a decimal) %.0f.

Sometimes you just need to talk to yourself on a public forum to work stuff out :stuck_out_tongue:

1 Like

You should mark post 3 as the solution. You’ll get brownie points for that!

2 Likes

I display the picture (file .png) on oled, but it not full. can you get me some advice, please, bros

Start a new topic. This is unrelated to the current topic. Give more details: see How to help us help you - or How to ask a good question

2 Likes

Thx for the example code. I managed to build a simple temp and air quality station with this. Learned a lot about getting the right values on the oled screen. Now printing a small case for the node mcu . Here is the code i use:

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    address: 0x3C
    id: my_display

    pages:
      - id: page1
        lambda: |-
          it.rectangle(0, 0, 128, 64);
          if (id(temperature_sensor).has_state()) {
            it.printf(64, 0, id(My_custom_font1), TextAlign::TOP_CENTER , "%.1f C", id(temperature_sensor).state);
          }
          it.print(64, 62, id(My_custom_font2), TextAlign::BOTTOM_CENTER, "Buiten Temp");

      - id: page2
        lambda: |-
          it.rectangle(0, 0, 128, 64);
          if (id(pm_2_5_sensor).has_state()) {
            it.printf(64, 0, id(My_custom_font1), TextAlign::TOP_CENTER , "%.1f Um", id(pm_2_5_sensor).state);
          }
          it.print(64, 62, id(My_custom_font2), TextAlign::BOTTOM_CENTER, "part 2,5 sensor");

      - id: page3
        lambda: |-
          it.rectangle(0, 0, 128, 64);
          if (id(pm_10_0_sensor).has_state()) {
            it.printf(64, 0, id(My_custom_font1), TextAlign::TOP_CENTER , "%.1f Um", id(pm_10_0_sensor).state);
          }
          it.print(64, 62, id(My_custom_font2), TextAlign::BOTTOM_CENTER, "part 10 sensor");

      - id: page4
        lambda: |-
          it.rectangle(0, 0, 128, 64);
          if (id(humidity_sensor).has_state()) {
            it.printf(64, 0, id(My_custom_font1), TextAlign::TOP_CENTER , "%.1f", id(humidity_sensor).state);
          }
          it.print(64, 62, id(My_custom_font2), TextAlign::BOTTOM_CENTER, "humidity_sensor");

      - id: page5
        lambda: |-
          it.rectangle(0, 0, 128, 64);
          it.strftime(64, 0, id(My_custom_font2), TextAlign::TOP_CENTER , "%Y-%m-%d", id(current_time).now());
          it.strftime(64, 31, id(My_custom_font2), TextAlign::CENTER , "%H:%M:%S", id(current_time).now());
          it.print(64, 62, id(My_custom_font2), TextAlign::BOTTOM_CENTER, "Datum en Tijd");


interval:
  - interval: 3s
    then:
      - display.page.show_next: my_display
      - component.update: my_display

time:
  - platform: homeassistant
    id: current_time

sensor:
  - platform: homeassistant
    id: pm_2_5_sensor
    entity_id: sensor.esphome_web_8b3ce4_particulate_matter_2_5_m_concentration
  - platform: homeassistant
    id: pm_10_0_sensor
    entity_id: sensor.esphome_web_8b3ce4_particulate_matter_10_0_m_concentration
  - platform: homeassistant
    id: temperature_sensor
    entity_id: sensor.buiten_temp_temperatuur
  - platform: homeassistant
    id: humidity_sensor
    entity_id: sensor.buiten_temp_luchtvochtigheid