CYD HAMon Config Generator

Configure your Cheap Yellow Display Home Assistant Monitor

Device Settings

Sensor Configuration

HAMon Device Preview

CYD device preview

Generated YAML

# ==============================================================================
#  CYD 2.8" HAMon - Home Assistant Monitor
#  A customisable clock & sensor dashboard for the ESP32 Cheap Yellow Display
#
#  Generated by CYD HAMon Config Generator
#  https://github.com/element-software/CYD-ESPHome-HA-Monitor
#
#  License: MIT
# ==============================================================================
#
#  SUBSTITUTIONS - Customise your dashboard by editing the values below.
#  Passwords and keys should be stored in your secrets.yaml file.
#
# ==============================================================================
substitutions:
  # --- Device ---
  device_name: "hamon"
  friendly_name: "HAMon"

  # --- Icon Glyphs ---
  # List each unique icon ONCE here. If you use the same icon multiple times below,
  # only include it once in this list to avoid "duplicate glyph" errors.
  icon_glyphs: "\uea0b\ueffc\ue1ff\ue559\ue7fd\ue0f0"

  # --- Row 1, Column 1 ---
  r1c1_entity: "sensor.whole_home_energy_usage"
  r1c1_type: "sensor"
  r1c1_label: "Energy"
  r1c1_icon: "\uea0b"
  r1c1_icon_color: "0xFFA500"
  r1c1_format: '%.0fW'
  r1c1_color_thresh_high: "5000"
  r1c1_color_thresh_mid: "3000"
  r1c1_color_thresh_low: "1000"
  r1c1_color_high: "0xFF0000"
  r1c1_color_mid: "0xFFA500"
  r1c1_color_low: "0x32CD32"

  # --- Row 1, Column 2 ---
  r1c2_entity: "binary_sensor.front_door_sensor_contact"
  r1c2_type: "binary"
  r1c2_label: "Front Door"
  r1c2_icon: "\ueffc"
  r1c2_icon_color: "0x32CD32"
  r1c2_state_on: "Open"
  r1c2_state_off: "Closed"
  r1c2_icon_on: "\ueffc"
  r1c2_icon_off: "\ueffc"
  r1c2_color_on: "0xFF0000"
  r1c2_color_off: "0x32CD32"

  # --- Row 2, Column 1 ---
  r2c1_entity: "sensor.office_presence_one_temperature"
  r2c1_type: "sensor"
  r2c1_label: "Office"
  r2c1_icon: "\ue1ff"
  r2c1_icon_color: "0x00BFFF"
  r2c1_format: '%.1f°C'
  r2c1_color_thresh_high: "30"
  r2c1_color_thresh_mid: "25"
  r2c1_color_thresh_low: "15"
  r2c1_color_high: "0xFF0000"
  r2c1_color_mid: "0xFFA500"
  r2c1_color_low: "0x32CD32"

  # --- Row 2, Column 2 ---
  r2c2_entity: "binary_sensor.gate_door_contact"
  r2c2_type: "binary"
  r2c2_label: "Gate"
  r2c2_icon: "\ue559"
  r2c2_icon_color: "0x32CD32"
  r2c2_state_on: "Open"
  r2c2_state_off: "Closed"
  r2c2_icon_on: "\ue559"
  r2c2_icon_off: "\ue559"
  r2c2_color_on: "0xFF0000"
  r2c2_color_off: "0x32CD32"

  # --- Row 3, Column 1 ---
  r3c1_entity: "binary_sensor.garden_pano_person_occupancy"
  r3c1_type: "binary"
  r3c1_label: "Garden"
  r3c1_icon: "\ue7fd"
  r3c1_icon_color: "0x32CD32"
  r3c1_state_on: "Detected"
  r3c1_state_off: "Clear"
  r3c1_icon_on: "\ue7fd"
  r3c1_icon_off: "\ue7fd"
  r3c1_color_on: "0xFF0000"
  r3c1_color_off: "0x32CD32"

  # --- Row 3, Column 2 ---
  r3c2_entity: "light.kitchen_downlights"
  r3c2_type: "light"
  r3c2_label: "Kitchen"
  r3c2_icon: "\ue0f0"
  r3c2_icon_color: "0x000000"
  r3c2_state_on: "On"
  r3c2_state_off: "Off"
  r3c2_icon_on: "\ue0f0"
  r3c2_icon_off: "\ue0f0"
  r3c2_color_on: "0xFFFFFF"
  r3c2_color_off: "0x000000"

# ==============================================================================
esphome:
  name: ${device_name}
  friendly_name: ${friendly_name}

esp32:
  board: esp32dev
  framework:
    type: esp-idf

logger:

# Replace with the API encryption key provided by your ESPHome instance
api:
  encryption:
    key: !secret hamon_api_key

# Replace with the OTA password provided by your ESPHome instance
ota:
  - platform: esphome
    password: !secret hamon_ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "${friendly_name} Fallback"
    password: !secret hamon_ap_password

captive_portal:

output:
  - platform: ledc
    pin: GPIO21
    id: backlight_pwm

spi:
  - id: tft
    clk_pin: GPIO14
    mosi_pin: GPIO13
    miso_pin: GPIO12
  - id: touch
    clk_pin: GPIO25
    mosi_pin: GPIO32
    miso_pin: GPIO39

display:
  - platform: ili9xxx
    id: my_display
    model: ILI9341
    spi_id: tft
    cs_pin: GPIO15
    dc_pin: GPIO2
    auto_clear_enabled: false
    invert_colors: false
    color_order: RGB
    dimensions:
      width: 240
      height: 320
    transform:
      swap_xy: true
      mirror_y: true
      mirror_x: true

touchscreen:
  platform: xpt2046
  id: my_touchscreen
  spi_id: touch
  cs_pin: GPIO33
  calibration:
    x_min: 220
    x_max: 3756
    y_min: 394
    y_max: 3749
  transform:
    swap_xy: false
    mirror_x: true
    mirror_y: false
  on_touch:
    - lambda: |-
        ESP_LOGI("touch", "Touch at LVGL (%d, %d)", touch.x, touch.y);

# --- FONTS ---
font:
  - file: "gfonts://Roboto"
    id: clock_font
    size: 48
    glyphs: '0123456789: '
  - file: "gfonts://Roboto"
    id: date_font
    size: 20
    glyphs: "0123456789/- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  - file: "gfonts://Material Icons"
    id: icon_font
    size: 28
    glyphs: "${icon_glyphs}"
  - file: "gfonts://Roboto"
    id: state_font
    size: 18
    glyphs: '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz .°%W-'
  - file: "gfonts://Roboto"
    id: label_font
    size: 11
    glyphs: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz .°%-"

# --- TIME ---
time:
  - platform: homeassistant
    id: esptime
    on_time:
      - seconds: 0
        then:
          - lvgl.label.update:
              id: label_clock
              text: !lambda 'return id(esptime).now().strftime("%H:%M");'
          - lvgl.label.update:
              id: label_date
              text: !lambda |-
                static const char *const dias[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
                auto now = id(esptime).now();
                return str_sprintf("%s %02d/%02d", dias[now.day_of_week - 1], now.day_of_month, now.month);

# --- DISPLAY PAGE CONFIG ---
lvgl:
  displays:
    - my_display
  touchscreens:
    - my_touchscreen
  pages:
    - id: main_page
      bg_color: 0x000000
      widgets:
        - label:
            id: label_clock
            text: "--:--"
            text_font: clock_font
            text_color: 0xFFFFFF
            align: TOP_MID
            y: 15
        - label:
            id: label_date
            text: "--- --/--"
            text_font: date_font
            text_color: 0xAAAAAA
            align: TOP_MID
            y: 65

        # ====== ROW 1 ======
        - button:
            x: 2
            y: 100
            id: button_r1c1
            width: 117
            height: 68
            bg_opa: TRANSP
            border_width: 0
            shadow_width: 0
            radius: 0
            scrollbar_mode: "OFF"
            
            widgets:
              - label:
                  id: icon_r1c1
                  text: "${r1c1_icon}"
                  text_font: icon_font
                  text_color: ${r1c1_icon_color}
                  align: LEFT_MID
                  x: 0
                  clickable: false
              - label:
                  id: lbl_r1c1
                  text: "${r1c1_label}"
                  text_font: label_font
                  text_color: 0xAAAAAA
                  align: LEFT_MID
                  x: 32
                  y: -10
                  clickable: false
              - label:
                  id: val_r1c1
                  text: "--"
                  text_font: state_font
                  text_color: 0xFFFFFF
                  align: LEFT_MID
                  x: 32
                  y: 10
                  clickable: false

        - button:
            x: 121
            y: 100
            id: button_r1c2
            width: 117
            height: 68
            bg_opa: TRANSP
            border_width: 0
            shadow_width: 0
            radius: 0
            scrollbar_mode: "OFF"
            
            widgets:
              - label:
                  id: icon_r1c2
                  text: "${r1c2_icon}"
                  text_font: icon_font
                  text_color: ${r1c2_icon_color}
                  align: LEFT_MID
                  x: 0
                  clickable: false
              - label:
                  id: lbl_r1c2
                  text: "${r1c2_label}"
                  text_font: label_font
                  text_color: 0xAAAAAA
                  align: LEFT_MID
                  x: 32
                  y: -10
                  clickable: false
              - label:
                  id: val_r1c2
                  text: "--"
                  text_font: state_font
                  text_color: 0xFFFFFF
                  align: LEFT_MID
                  x: 32
                  y: 10
                  clickable: false

        # ====== ROW 2 ======
        - button:
            x: 2
            y: 170
            id: button_r2c1
            width: 117
            height: 68
            bg_opa: TRANSP
            border_width: 0
            shadow_width: 0
            radius: 0
            scrollbar_mode: "OFF"
            
            widgets:
              - label:
                  id: icon_r2c1
                  text: "${r2c1_icon}"
                  text_font: icon_font
                  text_color: ${r2c1_icon_color}
                  align: LEFT_MID
                  x: 0
                  clickable: false
              - label:
                  id: lbl_r2c1
                  text: "${r2c1_label}"
                  text_font: label_font
                  text_color: 0xAAAAAA
                  align: LEFT_MID
                  x: 32
                  y: -10
                  clickable: false
              - label:
                  id: val_r2c1
                  text: "--"
                  text_font: state_font
                  text_color: 0xFFFFFF
                  align: LEFT_MID
                  x: 32
                  y: 10
                  clickable: false

        - button:
            x: 121
            y: 170
            id: button_r2c2
            width: 117
            height: 68
            bg_opa: TRANSP
            border_width: 0
            shadow_width: 0
            radius: 0
            scrollbar_mode: "OFF"
            
            widgets:
              - label:
                  id: icon_r2c2
                  text: "${r2c2_icon}"
                  text_font: icon_font
                  text_color: ${r2c2_icon_color}
                  align: LEFT_MID
                  x: 0
                  clickable: false
              - label:
                  id: lbl_r2c2
                  text: "${r2c2_label}"
                  text_font: label_font
                  text_color: 0xAAAAAA
                  align: LEFT_MID
                  x: 32
                  y: -10
                  clickable: false
              - label:
                  id: val_r2c2
                  text: "--"
                  text_font: state_font
                  text_color: 0xFFFFFF
                  align: LEFT_MID
                  x: 32
                  y: 10
                  clickable: false

        # ====== ROW 3 ======
        - button:
            x: 2
            y: 240
            id: button_r3c1
            width: 117
            height: 68
            bg_opa: TRANSP
            border_width: 0
            shadow_width: 0
            radius: 0
            scrollbar_mode: "OFF"
            
            widgets:
              - label:
                  id: icon_r3c1
                  text: "${r3c1_icon}"
                  text_font: icon_font
                  text_color: ${r3c1_icon_color}
                  align: LEFT_MID
                  x: 0
                  clickable: false
              - label:
                  id: lbl_r3c1
                  text: "${r3c1_label}"
                  text_font: label_font
                  text_color: 0xAAAAAA
                  align: LEFT_MID
                  x: 32
                  y: -10
                  clickable: false
              - label:
                  id: val_r3c1
                  text: "--"
                  text_font: state_font
                  text_color: 0xFFFFFF
                  align: LEFT_MID
                  x: 32
                  y: 10
                  clickable: false

        - button:
            x: 121
            y: 240
            id: button_r3c2
            width: 117
            height: 68
            bg_opa: TRANSP
            border_width: 0
            shadow_width: 0
            radius: 0
            scrollbar_mode: "OFF"
            on_click:
              - homeassistant.action:
                  action: light.toggle
                  data:
                    entity_id: "light.kitchen_downlights"
            checked:
              bg_color: 0xFFA500
              bg_opa: COVER
            widgets:
              - label:
                  id: icon_r3c2
                  text: "${r3c2_icon}"
                  text_font: icon_font
                  text_color: ${r3c2_icon_color}
                  align: LEFT_MID
                  x: 0
                  clickable: false
              - label:
                  id: lbl_r3c2
                  text: "${r3c2_label}"
                  text_font: label_font
                  text_color: 0xAAAAAA
                  align: LEFT_MID
                  x: 32
                  y: -10
                  clickable: false
              - label:
                  id: val_r3c2
                  text: "--"
                  text_font: state_font
                  text_color: 0xFFFFFF
                  align: LEFT_MID
                  x: 32
                  y: 10
                  clickable: false

# --- BINARY SENSOR & LIGHT ENTITY STATE ---
# Binary sensors and HA light entities (on/off state); icon color follows state (color_on / color_off).
binary_sensor:
  - platform: homeassistant
    id: ha_r1c2
    entity_id: ${r1c2_entity}
    trigger_on_initial_state: true
    on_state:
      then:
        - lvgl.label.update:
            id: icon_r1c2
            text: !lambda |-
              if (id(ha_r1c2).state) return "${r1c2_icon_on}";
              return "${r1c2_icon_off}";
        - lvgl.widget.update:
            id: icon_r1c2
            text_color: !lambda |-
              if (id(ha_r1c2).state) return lv_color_hex((uint32_t)${r1c2_color_on});
              return lv_color_hex((uint32_t)${r1c2_color_off});
        - lvgl.label.update:
            id: val_r1c2
            text: !lambda |-
              if (id(ha_r1c2).state) return "${r1c2_state_on}";
              return "${r1c2_state_off}";
        - lvgl.widget.update:
            id: val_r1c2
            text_color: !lambda |-
              if (id(ha_r1c2).state) return lv_color_hex((uint32_t)${r1c2_color_on});
              return lv_color_hex((uint32_t)${r1c2_color_off});

  - platform: homeassistant
    id: ha_r2c2
    entity_id: ${r2c2_entity}
    trigger_on_initial_state: true
    on_state:
      then:
        - lvgl.label.update:
            id: icon_r2c2
            text: !lambda |-
              if (id(ha_r2c2).state) return "${r2c2_icon_on}";
              return "${r2c2_icon_off}";
        - lvgl.widget.update:
            id: icon_r2c2
            text_color: !lambda |-
              if (id(ha_r2c2).state) return lv_color_hex((uint32_t)${r2c2_color_on});
              return lv_color_hex((uint32_t)${r2c2_color_off});
        - lvgl.label.update:
            id: val_r2c2
            text: !lambda |-
              if (id(ha_r2c2).state) return "${r2c2_state_on}";
              return "${r2c2_state_off}";
        - lvgl.widget.update:
            id: val_r2c2
            text_color: !lambda |-
              if (id(ha_r2c2).state) return lv_color_hex((uint32_t)${r2c2_color_on});
              return lv_color_hex((uint32_t)${r2c2_color_off});

  - platform: homeassistant
    id: ha_r3c1
    entity_id: ${r3c1_entity}
    trigger_on_initial_state: true
    on_state:
      then:
        - lvgl.label.update:
            id: icon_r3c1
            text: !lambda |-
              if (id(ha_r3c1).state) return "${r3c1_icon_on}";
              return "${r3c1_icon_off}";
        - lvgl.widget.update:
            id: icon_r3c1
            text_color: !lambda |-
              if (id(ha_r3c1).state) return lv_color_hex((uint32_t)${r3c1_color_on});
              return lv_color_hex((uint32_t)${r3c1_color_off});
        - lvgl.label.update:
            id: val_r3c1
            text: !lambda |-
              if (id(ha_r3c1).state) return "${r3c1_state_on}";
              return "${r3c1_state_off}";
        - lvgl.widget.update:
            id: val_r3c1
            text_color: !lambda |-
              if (id(ha_r3c1).state) return lv_color_hex((uint32_t)${r3c1_color_on});
              return lv_color_hex((uint32_t)${r3c1_color_off});

  - platform: homeassistant
    id: ha_r3c2
    entity_id: ${r3c2_entity}
    trigger_on_initial_state: true
    on_state:
      then:
        - lvgl.label.update:
            id: icon_r3c2
            text: !lambda |-
              if (id(ha_r3c2).state) return "${r3c2_icon_on}";
              return "${r3c2_icon_off}";
        - lvgl.widget.update:
            id: icon_r3c2
            text_color: !lambda |-
              if (id(ha_r3c2).state) return lv_color_hex(0x000000);
              return lv_color_hex(0xFFFFFF);
        - lvgl.label.update:
            id: val_r3c2
            text: !lambda |-
              if (id(ha_r3c2).state) return "${r3c2_state_on}";
              return "${r3c2_state_off}";
        - lvgl.widget.update:
            id: val_r3c2
            text_color: !lambda |-
              if (id(ha_r3c2).state) return lv_color_hex(0x000000);
              return lv_color_hex(0xFFFFFF);
        - lvgl.widget.update:
            id: lbl_r3c2
            text_color: !lambda |-
              if (id(ha_r3c2).state) return lv_color_hex(0x000000);
              return lv_color_hex(0xFFFFFF);
        - lvgl.widget.update:
            id: button_r3c2
            state:
              checked: !lambda return id(ha_r3c2).state;


# --- LIGHT CONFIG (display backlight) ---
light:
  - platform: monochromatic
    output: backlight_pwm
    name: Display Backlight
    id: backlight
    restore_mode: ALWAYS_ON
    default_transition_length: 0.5s

# --- NUMERIC SENSOR CONFIG ---
sensor:
  - platform: homeassistant
    id: ha_r1c1
    entity_id: ${r1c1_entity}
    on_value:
      then:
        - lvgl.label.update:
            id: val_r1c1
            text: !lambda |-
              return str_sprintf("${r1c1_format}", x);
        - lvgl.label.update:
            id: icon_r1c1
            text_color: !lambda |-
              if (x > ${r1c1_color_thresh_high}) return lv_color_hex(${r1c1_color_high});
              if (x > ${r1c1_color_thresh_mid}) return lv_color_hex(${r1c1_color_mid});
              if (x > ${r1c1_color_thresh_low}) return lv_color_hex(${r1c1_color_low});
              return lv_color_hex(${r1c1_color_low});

  - platform: homeassistant
    id: ha_r2c1
    entity_id: ${r2c1_entity}
    on_value:
      then:
        - lvgl.label.update:
            id: val_r2c1
            text: !lambda |-
              return str_sprintf("${r2c1_format}", x);
        - lvgl.label.update:
            id: icon_r2c1
            text_color: !lambda |-
              if (x > ${r2c1_color_thresh_high}) return lv_color_hex(${r2c1_color_high});
              if (x > ${r2c1_color_thresh_mid}) return lv_color_hex(${r2c1_color_mid});
              if (x > ${r2c1_color_thresh_low}) return lv_color_hex(${r2c1_color_low});
              return lv_color_hex(${r2c1_color_low});