diff --git a/esphome/master_bedroom_remote.yaml b/esphome/master_bedroom_remote.yaml new file mode 100644 index 0000000..d66d4f7 --- /dev/null +++ b/esphome/master_bedroom_remote.yaml @@ -0,0 +1,238 @@ +substitutions: + name: mbr-ha-remote + friendly_name: "Master HA Remote" + + # Home Assistant entity IDs - UPDATE THESE TO MATCH YOUR SETUP + light_1_entity: switch.pollys_light + light_2_entity: switch.joshuas_light + fan_entity: switch.parents_ceiling_fan + # For "all" toggle, we'll control these three entities + +esphome: + name: ${name} + friendly_name: ${friendly_name} + +esp32: + board: esp32dev + framework: + type: arduino + +logger: + +api: + encryption: + key: !secret api_encryption_key + +ota: + - platform: esphome + password: !secret ota_password + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + ap: + ssid: "${name} Fallback" + password: !secret ap_password + +captive_portal: + +# ----------------------------- +# CYD Display Configuration +# ----------------------------- + +# SPI for display and touchscreen +spi: + - id: tft_spi + clk_pin: GPIO14 + mosi_pin: GPIO13 + miso_pin: GPIO12 + +# ILI9341 Display (2.8" 320x240) +display: + - platform: ili9xxx + model: ili9341 + spi_id: tft_spi + cs_pin: GPIO15 + dc_pin: GPIO2 + rotation: 0 + id: my_display + lambda: |- + // Background + it.fill(Color(0x1a, 0x1a, 0x2e)); + + // Title + it.print(160, 20, id(title_font), Color(0xff, 0xff, 0xff), TextAlign::TOP_CENTER, "Room Remote"); + + // Draw buttons (2x2 grid) + // Button 1: All Toggle (top-left) + auto all_color = id(all_state) ? Color(0x4c, 0xaf, 0x50) : Color(0x42, 0x42, 0x42); + it.filled_rectangle(20, 50, 130, 80, all_color); + it.print(85, 90, id(button_font), Color::WHITE, TextAlign::CENTER, "ALL"); + + // Button 2: Light 1 (top-right) + auto light1_color = id(light1_state) ? Color(0xff, 0xc1, 0x07) : Color(0x42, 0x42, 0x42); + it.filled_rectangle(170, 50, 130, 80, light1_color); + it.print(235, 90, id(button_font), Color::WHITE, TextAlign::CENTER, "Light 1"); + + // Button 3: Light 2 (bottom-left) + auto light2_color = id(light2_state) ? Color(0xff, 0xc1, 0x07) : Color(0x42, 0x42, 0x42); + it.filled_rectangle(20, 150, 130, 80, light2_color); + it.print(85, 190, id(button_font), Color::WHITE, TextAlign::CENTER, "Light 2"); + + // Button 4: Fan (bottom-right) + auto fan_color = id(fan_state) ? Color(0x21, 0x96, 0xf3) : Color(0x42, 0x42, 0x42); + it.filled_rectangle(170, 150, 130, 80, fan_color); + it.print(235, 190, id(button_font), Color::WHITE, TextAlign::CENTER, "Fan"); + +# XPT2046 Touchscreen +touchscreen: + - platform: xpt2046 + spi_id: tft_spi + cs_pin: GPIO33 + interrupt_pin: GPIO36 + calibration: + x_min: 280 + x_max: 3860 + y_min: 340 + y_max: 3860 + on_touch: + - lambda: |- + int x = touch.x; + int y = touch.y; + + // Button 1: ALL (20-150, 50-130) + if (x >= 20 && x <= 150 && y >= 50 && y <= 130) { + id(btn_all).press(); + } + // Button 2: Light 1 (170-300, 50-130) + else if (x >= 170 && x <= 300 && y >= 50 && y <= 130) { + id(btn_light1).press(); + } + // Button 3: Light 2 (20-150, 150-230) + else if (x >= 20 && x <= 150 && y >= 150 && y <= 230) { + id(btn_light2).press(); + } + // Button 4: Fan (170-300, 150-230) + else if (x >= 170 && x <= 300 && y >= 150 && y <= 230) { + id(btn_fan).press(); + } + on_release: + - lambda: |- + id(btn_all).release(); + id(btn_light1).release(); + id(btn_light2).release(); + id(btn_fan).release(); + +# Backlight control +output: + - platform: ledc + pin: GPIO21 + id: backlight_pwm + +light: + - platform: monochromatic + output: backlight_pwm + name: "Display Backlight" + id: backlight + restore_mode: ALWAYS_ON + +# Fonts +font: + - file: "gfonts://Roboto" + id: title_font + size: 24 + - file: "gfonts://Roboto" + id: button_font + size: 20 + +# Global state tracking +globals: + - id: all_state + type: bool + initial_value: 'false' + - id: light1_state + type: bool + initial_value: 'false' + - id: light2_state + type: bool + initial_value: 'false' + - id: fan_state + type: bool + initial_value: 'false' + +# Binary sensors for touch buttons +binary_sensor: + - platform: template + id: btn_all + name: "Toggle All" + on_press: + then: + - homeassistant.service: + service: switch.toggle + data: + entity_id: ${light_1_entity} + - homeassistant.service: + service: switch.toggle + data: + entity_id: ${light_2_entity} + - homeassistant.service: + service: switch.toggle + data: + entity_id: ${fan_entity} + + - platform: template + id: btn_light1 + name: "Polly's Light" + on_press: + then: + - homeassistant.service: + service: switch.toggle + data: + entity_id: ${light_1_entity} + + - platform: template + id: btn_light2 + name: "Joshua's Light" + on_press: + then: + - homeassistant.service: + service: switch.toggle + data: + entity_id: ${light_2_entity} + + - platform: template + id: btn_fan + name: "Ceiling Fan" + on_press: + then: + - homeassistant.service: + service: switch.toggle + data: + entity_id: ${fan_entity} + +# Import states from Home Assistant +text_sensor: + - platform: homeassistant + entity_id: ${light_1_entity} + id: ha_light1_state + on_value: + then: + - lambda: |- + id(light1_state) = (x == "on"); + + - platform: homeassistant + entity_id: ${light_2_entity} + id: ha_light2_state + on_value: + then: + - lambda: |- + id(light2_state) = (x == "on"); + + - platform: homeassistant + entity_id: ${fan_entity} + id: ha_fan_state + on_value: + then: + - lambda: |- + id(fan_state) = (x == "on"); + id(all_state) = id(light1_state) && id(light2_state) && id(fan_state); \ No newline at end of file