Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- esphome:
- name: cheap-yellow-display
- esp32:
- board: esp32dev
- framework:
- type: arduino
- logger:
- wifi:
- ssid: "Nelley Kelson"
- password: "1234567890"
- power_save_mode: none
- api:
- ota:
- platform: esphome
- # Backlight (GPIO21)
- output:
- - platform: ledc
- pin: 21
- id: backlight_pwm
- light:
- - platform: monochromatic
- id: backlight
- name: "CYD Backlight"
- output: backlight_pwm
- restore_mode: ALWAYS_ON
- # SPI — HSPI (write-only)
- spi:
- clk_pin: 14
- mosi_pin: 13
- # ===== Music info from Home Assistant =====
- text_sensor:
- - platform: homeassistant
- id: song_artist
- entity_id: media_player.bedroom_homepod_mini_2
- attribute: media_artist
- on_value:
- - component.update: my_display
- - platform: homeassistant
- id: song_title
- entity_id: media_player.bedroom_homepod_mini_2
- attribute: media_title
- on_value:
- - component.update: my_display
- - platform: homeassistant
- id: album_name
- entity_id: media_player.bedroom_homepod_mini_2
- attribute: media_album_name
- on_value:
- - component.update: my_display
- - platform: homeassistant
- id: player_state
- entity_id: media_player.bedroom_homepod_mini_2
- on_value:
- - component.update: my_display
- - platform: homeassistant
- id: temp_unit
- entity_id: sensor.average_temperature
- attribute: unit_of_measurement
- on_value:
- - component.update: my_display
- - platform: homeassistant
- id: hum_unit
- entity_id: sensor.average_humidity
- attribute: unit_of_measurement
- on_value:
- - component.update: my_display
- sensor:
- - platform: homeassistant
- id: avg_temp
- entity_id: sensor.average_temperature
- on_value:
- - component.update: my_display
- - platform: homeassistant
- id: avg_humidity
- entity_id: sensor.average_humidity
- on_value:
- - component.update: my_display
- # ===== Time sync =====
- time:
- - platform: homeassistant
- id: ha_time
- # ===== Fonts =====
- font:
- - file: "gfonts://Roboto"
- id: f_artist_big
- size: 28
- - file: "gfonts://Roboto"
- id: f_title
- size: 20
- - file: "gfonts://Roboto"
- id: f_album
- size: 16
- - file: "gfonts://Roboto"
- id: f_temp
- size: 16
- - file: "gfonts://Roboto"
- id: f_hum
- size: 16
- - file: "gfonts://Roboto"
- id: f_time
- size: 60 # Very large time
- - file: "gfonts://Roboto"
- id: f_date
- size: 18 # Smaller font for day/date
- # ===== Display — ILI9341 on CYD =====
- display:
- - platform: ili9xxx
- id: my_display
- model: ILI9341
- cs_pin: 15
- dc_pin: 2
- reset_pin: 33
- spi_mode: MODE3
- data_rate: 10MHz
- color_order: RGB
- invert_colors: false
- rotation: 180
- color_palette: 8BIT
- update_interval: 1s
- dimensions:
- width: 320
- height: 240
- offset_width: 0
- offset_height: 0
- lambda: |-
- using esphome::Color;
- using esphome::display::TextAlign;
- const int W = 320, H = 240;
- it.fill(Color::BLACK);
- std::string artist = id(song_artist).state.c_str();
- std::string title = id(song_title).state.c_str();
- std::string album = id(album_name).state.c_str();
- if (artist.empty()) artist = "—";
- if (title.empty()) title = "—";
- if (album.empty()) album = "";
- auto fit_to_width = [&](std::string s, esphome::display::BaseFont *fnt, int maxw) -> std::string {
- int bx, by, bw, bh;
- it.get_text_bounds(0, 0, s.c_str(), fnt, TextAlign::TOP_LEFT, &bx, &by, &bw, &bh);
- if (bw <= maxw) return s;
- std::string base = s;
- while (base.size() > 1) {
- base.pop_back();
- std::string cand = base + "…";
- it.get_text_bounds(0, 0, cand.c_str(), fnt, TextAlign::TOP_LEFT, &bx, &by, &bw, &bh);
- if (bw <= maxw) return cand;
- }
- return "…";
- };
- const int MAX_W = W - 10;
- artist = fit_to_width(artist, id(f_artist_big), MAX_W);
- title = fit_to_width(title, id(f_title), MAX_W);
- if (!album.empty()) album = fit_to_width(album, id(f_album), MAX_W);
- const int ARTIST_TOP = 8;
- const int TITLE_TOP = 36;
- const int ALBUM_TOP = 56;
- it.printf(W/2, ARTIST_TOP, id(f_artist_big), TextAlign::TOP_CENTER, "%s", artist.c_str());
- it.printf(W/2, ARTIST_TOP + 1, id(f_artist_big), TextAlign::TOP_CENTER, "%s", artist.c_str());
- it.printf(W/2, TITLE_TOP, id(f_title), TextAlign::TOP_CENTER, "%s", title.c_str());
- int redbar_top_y = 0;
- if (!album.empty()) {
- it.printf(W/2, ALBUM_TOP, id(f_album), TextAlign::TOP_CENTER, "%s", album.c_str());
- const int RBAR_MARGIN = 10;
- const int RBAR_W = W - RBAR_MARGIN*2;
- const int RBAR_H = 3;
- redbar_top_y = ALBUM_TOP + 18;
- it.filled_rectangle(RBAR_MARGIN, redbar_top_y, RBAR_W, RBAR_H, Color(255, 0, 0));
- }
- // Bottom-left temperature
- float t = id(avg_temp).state;
- std::string tu = id(temp_unit).state.c_str();
- if (tu.empty()) tu = "°";
- if (isfinite(t)) {
- char tbuf[24];
- if (fabsf(t) < 100.0f) snprintf(tbuf, sizeof(tbuf), "%.1f%s", t, tu.c_str());
- else snprintf(tbuf, sizeof(tbuf), "%.0f%s", t, tu.c_str());
- it.printf(4, H - 4, id(f_temp), TextAlign::BOTTOM_LEFT, "%s", tbuf);
- }
- // Bottom-right humidity
- float h = id(avg_humidity).state;
- std::string hu = id(hum_unit).state.c_str();
- if (hu.empty()) hu = "%";
- if (isfinite(h)) {
- char hbuf[24];
- snprintf(hbuf, sizeof(hbuf), "%.0f%s", h, hu.c_str());
- it.printf(W - 4, H - 4, id(f_hum), TextAlign::BOTTOM_RIGHT, "%s", hbuf);
- }
- // Second red bar just above "Indoor Avg"
- const int RBAR_MARGIN = 10;
- const int RBAR_W = W - RBAR_MARGIN*2;
- const int RBAR_H = 3;
- const int RBAR_BOTTOM_Y = H - 30;
- it.filled_rectangle(RBAR_MARGIN, RBAR_BOTTOM_Y, RBAR_W, RBAR_H, Color(255, 0, 0));
- // Bottom label
- it.printf(W/2, H - 4, id(f_album), TextAlign::BOTTOM_CENTER, "Indoor Avg");
- // Time block (with day and date)
- auto now = id(ha_time).now();
- if (now.is_valid()) {
- int mid_y = (redbar_top_y + RBAR_BOTTOM_Y) / 2;
- // Day of week above time
- it.strftime(W/2, mid_y - 40, id(f_date), TextAlign::BOTTOM_CENTER, "%A", now);
- // Big time
- it.strftime(W/2, mid_y, id(f_time), TextAlign::CENTER, "%I:%M %p", now);
- // Date below time
- it.strftime(W/2, mid_y + 40, id(f_date), TextAlign::TOP_CENTER, "%b %d, %Y", now);
- }
Advertisement
Add Comment
Please, Sign In to add comment