ESPHome Spotify OLED Display

July 8, 2019

Background

I've created an OLED Display that cycles through the time, what's playing on Spotify, and the current temperature based on other ESP8266 sensors in the room. All of this is possible with ESPHome to program the ESP8266 microcontroller (in this case a Wemos D1 Mini) connected to Home-Assistant.

I later added a feature to make the screen turn blank when a switch on the Home-Assistant Dashboard is flipped, so the screen wouldn't illuminate my room at night. Please check the code for the Template Switch at the bottom.

Instructions

  • upload the .tff fonts like arial.tff and the others into the esphome directory on your Home-Assistant instance.

    • they can be pulled from your windows font directory or downloaded from the internet.
  • create sensor.spotify_song and sensor.spotify_artist sensors using this yaml and your already configured spotify media player integration.

Spotify Sensor YAML Code:

spotify_song:
  friendly_name: "Spotify Song"
  value_template: "{{ state_attr('media_player.spotify', 'media_title') }}"
spotify_artist:
  friendly_name: "Spotify Artist"
  value_template: "{{ state_attr('media_player.spotify', 'media_artist') }}"

ESPHome YAML Code

wifi:
  ssid: "wifi_network"
  password: "wifi_password"
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "OLED Display01 Fallback Hotspot"
    password: "password"
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
time:
  - platform: homeassistant
    id: time1
text_sensor:
  - platform: homeassistant
    id: spotify_song
    entity_id: sensor.spotify_song
    internal: true
 
  - platform: homeassistant
    id: spotify_artist
    entity_id: sensor.spotify_artist
    internal: true
   
sensor:
### temp sensors
  - platform: homeassistant
    id: room_temperature
    entity_id: sensor.sn1_temperature
    internal: true
  - platform: homeassistant
    id: stereo_temperature
    entity_id: sensor.stereo_amp_temperature
    internal: true
 
switch:
  - platform: template
    name: "OLED_Display01 Screen"
    id: oled_display01_dnd
    optimistic: True
    # inverted: True
    on_turn_on:
      - logger.log: "Switch Turned On!"
      # - delay: 2s
      - display.page.show: page4
      # - delay: 2s
      - component.update: my_display
font:
  - file: 'arial.ttf' #'slkscr.ttf'
    id: font1
    size: 12
 
  - file: 'BebasNeue-Regular.ttf'
    id: font2
    size: 48
 
  - file: 'arial.ttf'
    id: font3
    size: 18
   
  - file: 'arialbd.ttf'
    id: font4
    size: 14
   
  - file: 'arial.ttf'
    id: font5
    size: 20
 
i2c:
  # sda: D1
  # scl: D2
  # scan: False
  # swap for Wemos D1 Mini
  sda: D2
  scl: D1
  scan: False
 
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    reset_pin: D0
    address: 0x3C
    id: my_display
    pages:
      - id: page1
        lambda: |-
          // Print time in HH:MM format
          it.strftime(0, 60, id(font2), TextAlign::BASELINE_LEFT, "%l:%M", id(time1).now());
          // Print AM/PM
          it.strftime(127, 60, id(font5), TextAlign::BASELINE_RIGHT, "%P", id(time1).now());
      - id: page2
        lambda: |-
          // it.print(0, 10, id(font1), "This is page 2!");
          // Print "Spotify Song" in top center.
          if (id(spotify_artist).has_state()) {
            it.printf(0, 8, id(font5), TextAlign::TOP_LEFT, "%s", id(spotify_artist).state.c_str());
          }
          if (id(spotify_song).has_state()) {
            it.printf(0, 55, id(font5), TextAlign::BASELINE_LEFT, "%s", id(spotify_song).state.c_str());
          }
      - id: page3
        lambda: |-
          // it.print(0, 10, id(font1), "This is page 3!");
          // Print room temperature (from homeassistant sensor)
          if (id(room_temperature).has_state()) {
            it.printf(0, 15, id(font5), TextAlign::TOP_LEFT, "Room: %.1f°", id(room_temperature).state);
          }
          // Print stereo temperature (from homeassistant sensor)
          if (id(stereo_temperature).has_state()) {
            it.printf(0, 60, id(font5), TextAlign::BASELINE_LEFT, "Stereo: %.1f°", id(stereo_temperature).state);
          }
      - id: page4
        lambda: |-
          it.print(0, 10, id(font1), "");
 
interval:
  - interval: 3s
    then:
      if:
        condition:
          lambda: return !id(oled_display01_dnd).state;
        then:
          - display.page.show: !lambda |-
              static int pagenum = 0;
              static display::DisplayPage* pages[] = {id(page1), id(page2), id(page3)};
              auto page = pages[pagenum++];
              if (pagenum >= 3)
                pagenum = 0;
              return page;
          - component.update: my_display

Template Sensor

This template sensor inverses the ESPHome Switch. I couldn't find a way to invert it natively in ESPHome, so I went this route. Please let me know if you've figured out a better way!

### template switch to reverse the oled_display01 switch
  - platform: template
    switches:
      oled_display01_inverted:
        friendly_name: "OLED Display"
        value_template: "{{ is_state('switch.oled_display01_screen', 'off') }}"
        turn_on:
          service: switch.turn_off
          data:
            entity_id: switch.oled_display01_screen
        turn_off:
          service: switch.turn_on
          data:
            entity_id: switch.oled_display01_screen
        icon_template: "{% if is_state('switch.oled_display01_screen', 'on') %}mdi:flash-outline{% else %}mdi:flash{% endif %}"

Final Product

ESPHome OLED Display - Temperature

ESPHome OLED Display - Spotify

Share: