# Generated by ESPHome for Buttonplus # Options: # - device: buttonplus # - version: 1 # - bars: 3 # - pages: Start, Music, Lights, Security esphome: name: buttonplus friendly_name: buttonplus on_boot: priority: -100 then: - script.execute: setup_bar_displays - script.execute: test_all_leds - script.execute: bar1_left_script_update - script.execute: bar1_right_script_update - script.execute: bar2_left_script_update - script.execute: bar2_right_script_update - script.execute: bar3_left_script_update - script.execute: bar3_right_script_update esp32: variant: ESP32S3 board: esp32-s3-devkitc1-n16r8 flash_size: 16MB framework: type: esp-idf psram: mode: octal speed: 80MHz wifi: ssid: !secret 'wifi_ssid' password: !secret 'wifi_password' logger: level: DEBUG ota: - platform: esphome password: !secret 'ota_password' api: encryption: key: !secret 'encryption_key' actions: - action: notification variables: flash_leds: bool message: string then: - globals.set: id: internal_notify value: !lambda "return message;" - script.execute: display_script_update - while: condition: lambda: return (flash_leds && id(internal_notify).size() > 0); then: - light.turn_on: id: internal_notification_rgb brightness: 100% red: 100% green: 100% blue: 100% flash_length: 1s - delay: 2s - wait_until: condition: lambda: return id(internal_notify).size() == 0; - light.control: id: bar1_left_back_rgb_led - light.control: id: bar1_right_back_rgb_led - action: notification_clear then: - globals.set: id: internal_notify value: !lambda "return std::string();" - script.execute: display_script_update - action: toast variables: timeout: int message: string then: - globals.set: id: internal_toast value: !lambda "return message;" - script.execute: display_script_update - delay: !lambda "return timeout * 1000;" - globals.set: id: internal_toast value: !lambda "return std::string();" - script.execute: display_script_update - action: set_page_led variables: led: string page_name: string r: float g: float b: float brightness: float effect: string then: - if: condition: lambda: |- // Validate page_name if provided auto it = std::find(id(page_names).begin(), id(page_names).end(), page_name); if (it == id(page_names).end()) return true; return false; then: - api.respond: success: false error_message: Invalid page_name (not found). else: - if: condition: lambda: return id(internal_page_leds_r).find(led) == id(internal_page_leds_r).end(); then: - api.respond: success: false error_message: The requested LED does not exist. else: - lambda: |- // Resolve final page index auto it = std::find(id(page_names).begin(), id(page_names).end(), page_name); int page_num = std::distance(id(page_names).begin(), it); id(internal_page_leds_r)[led][page_num] = r; id(internal_page_leds_g)[led][page_num] = g; id(internal_page_leds_b)[led][page_num] = b; id(internal_page_leds_brightness)[led][page_num] = brightness; id(internal_page_leds_effect)[led][page_num] = effect; - api.respond: success: true - if: condition: lambda: |- auto it = std::find(id(page_names).begin(), id(page_names).end(), page_name); int page_num = std::distance(id(page_names).begin(), it); return page_num == id(active_page_nr); then: - script.execute: update_all_page_leds - action: get_page_info supports_response: only then: - api.respond: data: !lambda | root["num_pages"] = id(nr_of_pages); JsonArray pages = root["page_names"].to(); for(const std::string& page_name : id(page_names)){ pages.add(page_name); } JsonArray leds = root["leds"].to(); leds.add("bar1_left_front_rgb_led"); leds.add("bar1_right_front_rgb_led"); leds.add("bar1_left_back_rgb_led"); leds.add("bar1_right_back_rgb_led"); leds.add("bar2_left_front_rgb_led"); leds.add("bar2_right_front_rgb_led"); leds.add("bar2_left_back_rgb_led"); leds.add("bar2_right_back_rgb_led"); leds.add("bar3_left_front_rgb_led"); leds.add("bar3_right_front_rgb_led"); leds.add("bar3_left_back_rgb_led"); leds.add("bar3_right_back_rgb_led"); color: - id: accent hex: FF0000 - id: white hex: FFFFFF - id: black hex: '000000' - id: grey hex: A6A6A6 font: - file: url: https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf type: web id: font_arial20 size: 20 bpp: 4 globals: - id: nr_of_pages type: int initial_value: '4' - id: page_names type: std::vector initial_value: '{"Start", "Music", "Lights", "Security"}' - id: active_page_nr type: int initial_value: '0' - id: active_page_name type: std::string initial_value: '' - id: internal_notify type: std::string initial_value: '' - id: internal_toast type: std::string initial_value: '' - id: internal_page_leds_r type: std::unordered_map> initial_value: '{{"bar1_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}}' - id: internal_page_leds_g type: std::unordered_map> initial_value: '{{"bar1_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}}' - id: internal_page_leds_b type: std::unordered_map> initial_value: '{{"bar1_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}}' - id: internal_page_leds_brightness type: std::unordered_map> initial_value: '{{"bar1_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar1_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar2_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_left_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_right_front_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_left_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}, {"bar3_right_back_rgb_led", {0.0, 0.0, 0.0, 0.0}}}' - id: internal_page_leds_effect type: std::unordered_map> initial_value: '{{"bar1_left_front_rgb_led", {"", "", "", ""}}, {"bar1_right_front_rgb_led", {"", "", "", ""}}, {"bar1_left_back_rgb_led", {"", "", "", ""}}, {"bar1_right_back_rgb_led", {"", "", "", ""}}, {"bar2_left_front_rgb_led", {"", "", "", ""}}, {"bar2_right_front_rgb_led", {"", "", "", ""}}, {"bar2_left_back_rgb_led", {"", "", "", ""}}, {"bar2_right_back_rgb_led", {"", "", "", ""}}, {"bar3_left_front_rgb_led", {"", "", "", ""}}, {"bar3_right_front_rgb_led", {"", "", "", ""}}, {"bar3_left_back_rgb_led", {"", "", "", ""}}, {"bar3_right_back_rgb_led", {"", "", "", ""}}}' sensor: - platform: template name: Active Page Number icon: mdi:order-numeric-ascending id: active_page_nr_ha update_interval: never accuracy_decimals: 0 - platform: sts3x address: 74 id: buttonplus_temperature i2c_id: sensors name: Temperature update_interval: 10s unit_of_measurement: "\xB0C" icon: mdi:thermometer device_class: temperature state_class: measurement accuracy_decimals: 1 - platform: ltr_als_ps address: 41 i2c_id: sensors update_interval: 10s type: ALS auto_mode: false gain: 96x ambient_light: name: Ambient Light id: buttonplus_ambientlight unit_of_measurement: lx icon: mdi:brightness-6 device_class: illuminance state_class: measurement accuracy_decimals: 1 text_sensor: - platform: template name: Active Page Name icon: mdi:order-alphabetical-ascending id: active_page_name_ha update_interval: never number: - platform: template name: Page Selector id: pageselector optimistic: true min_value: 0 max_value: 3 step: 1 on_value: then: - lambda: |- if(id(pageselector).state >= id(nr_of_pages)) { id(active_page_nr) = id(nr_of_pages)-1; } else { id(active_page_nr) = id(pageselector).state; } - script.execute: set_page script: - id: next_page then: - if: condition: - lambda: !lambda "return id(internal_notify).size() > 0;" then: - globals.set: id: internal_notify value: !lambda "return std::string();" - script.execute: display_script_update - script.stop: next_page - lambda: |- id(active_page_nr) = id(active_page_nr) + 1; if(id(active_page_nr) >= id(nr_of_pages)) { id(active_page_nr) = 0; } - script.execute: update_page - id: prev_page then: - if: condition: - lambda: !lambda "return id(internal_notify).size() > 0;" then: - globals.set: id: internal_notify value: !lambda "return std::string();" - script.execute: display_script_update - script.stop: next_page - lambda: |- id(active_page_nr) = id(active_page_nr) - 1; if(id(active_page_nr) < 0) { id(active_page_nr) = id(nr_of_pages) - 1; } - script.execute: update_page - id: set_page then: - lambda: id(active_page_name) = id(page_names)[id(active_page_nr)]; - sensor.template.publish: id: active_page_nr_ha state: !lambda "return id(active_page_nr);" - text_sensor.template.publish: id: active_page_name_ha state: !lambda "return id(active_page_name);" - script.execute: update_all - script.execute: update_all_page_leds - id: update_page then: - number.set: id: pageselector value: !lambda "return id(active_page_nr);" - script.execute: set_page - id: test_all_leds then: - delay: 1000ms - light.turn_on: id: internal_all_rgb red: 100% green: 0% blue: 0% flash_length: 100ms - delay: 200ms - light.turn_on: id: internal_all_rgb red: 0% green: 100% blue: 0% flash_length: 100ms - delay: 200ms - light.turn_on: id: internal_all_rgb red: 0% green: 0% blue: 100% flash_length: 100ms - id: update_all mode: restart then: - script.execute: bars_script_update - delay: 0.1s - script.execute: display_script_update - id: display_script_update then: - component.update: display_disp - id: display_script_draw then: - lambda: | // All pages id(display_disp).image(0, 235, id(icon_prev_page), ImageAlign::BOTTOM_LEFT, id(grey)); id(display_disp).image(320, 235, id(icon_next_page), ImageAlign::BOTTOM_RIGHT, id(grey)); id(display_disp).print(160, 235, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER, id(active_page_name).c_str()); id(display_disp).strftime(160, 5, id(font_arial20), TextAlign::TOP_CENTER, "%H:%M", id(datetime).now()); id(display_disp).strftime(160, 80, id(font_arial20), TextAlign::TOP_CENTER, "%d-%m-%Y", id(datetime).now()); switch (id(active_page_nr)){ // Page 0 - Start case 0: break; // Page 1 - Music case 1: break; // Page 2 - Lights case 2: break; // Page 3 - Security case 3: break; } - lambda: | if(id(internal_notify).size() > 0){ // Draw white box over existing text id(display_disp).filled_rectangle(0, 200, 320, 40, white); id(display_disp).rectangle(0, 200, 320, 40, accent); // Show notification message id(display_disp).print(160, 235, id(font_arial20), id(black), TextAlign::BOTTOM_CENTER, id(internal_notify).c_str()); } - lambda: | if(id(internal_toast).size() > 0){ // Draw white box over existing text id(display_disp).filled_rectangle(0, 200, 320, 40, white); // Show toast message id(display_disp).print(160, 235, id(font_arial20), id(black), TextAlign::BOTTOM_CENTER, id(internal_toast).c_str()); } - id: bar1_left_script_update then: - lambda: |- id(bar1_left_cs_pin).turn_on(); id(bar1_right_cs_pin).turn_off(); id(bar2_left_cs_pin).turn_off(); id(bar2_right_cs_pin).turn_off(); id(bar3_left_cs_pin).turn_off(); id(bar3_right_cs_pin).turn_off(); id(bar_display).clear(); id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_270_DEGREES); id(bar1_left_script_draw).execute(); id(bar_display).update(); delay(1); id(bar1_left_cs_pin).turn_off(); - id: bar1_right_script_update then: - lambda: |- id(bar1_left_cs_pin).turn_off(); id(bar1_right_cs_pin).turn_on(); id(bar2_left_cs_pin).turn_off(); id(bar2_right_cs_pin).turn_off(); id(bar3_left_cs_pin).turn_off(); id(bar3_right_cs_pin).turn_off(); id(bar_display).clear(); id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_90_DEGREES); id(bar1_right_script_draw).execute(); id(bar_display).update(); delay(1); id(bar1_right_cs_pin).turn_off(); - id: bar2_left_script_update then: - lambda: |- id(bar1_left_cs_pin).turn_off(); id(bar1_right_cs_pin).turn_off(); id(bar2_left_cs_pin).turn_on(); id(bar2_right_cs_pin).turn_off(); id(bar3_left_cs_pin).turn_off(); id(bar3_right_cs_pin).turn_off(); id(bar_display).clear(); id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_270_DEGREES); id(bar2_left_script_draw).execute(); id(bar_display).update(); delay(1); id(bar2_left_cs_pin).turn_off(); - id: bar2_right_script_update then: - lambda: |- id(bar1_left_cs_pin).turn_off(); id(bar1_right_cs_pin).turn_off(); id(bar2_left_cs_pin).turn_off(); id(bar2_right_cs_pin).turn_on(); id(bar3_left_cs_pin).turn_off(); id(bar3_right_cs_pin).turn_off(); id(bar_display).clear(); id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_90_DEGREES); id(bar2_right_script_draw).execute(); id(bar_display).update(); delay(1); id(bar2_right_cs_pin).turn_off(); - id: bar3_left_script_update then: - lambda: |- id(bar1_left_cs_pin).turn_off(); id(bar1_right_cs_pin).turn_off(); id(bar2_left_cs_pin).turn_off(); id(bar2_right_cs_pin).turn_off(); id(bar3_left_cs_pin).turn_on(); id(bar3_right_cs_pin).turn_off(); id(bar_display).clear(); id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_270_DEGREES); id(bar3_left_script_draw).execute(); id(bar_display).update(); delay(1); id(bar3_left_cs_pin).turn_off(); - id: bar3_right_script_update then: - lambda: |- id(bar1_left_cs_pin).turn_off(); id(bar1_right_cs_pin).turn_off(); id(bar2_left_cs_pin).turn_off(); id(bar2_right_cs_pin).turn_off(); id(bar3_left_cs_pin).turn_off(); id(bar3_right_cs_pin).turn_on(); id(bar_display).clear(); id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_90_DEGREES); id(bar3_right_script_draw).execute(); id(bar_display).update(); delay(1); id(bar3_right_cs_pin).turn_off(); - id: setup_bar_displays then: - lambda: | id(bar1_left_cs_pin).turn_on(); id(bar_display).setup(); delay(5); id(bar1_left_cs_pin).turn_off(); id(bar1_right_cs_pin).turn_on(); id(bar_display).setup(); delay(5); id(bar1_right_cs_pin).turn_off(); id(bar2_left_cs_pin).turn_on(); id(bar_display).setup(); delay(5); id(bar2_left_cs_pin).turn_off(); id(bar2_right_cs_pin).turn_on(); id(bar_display).setup(); delay(5); id(bar2_right_cs_pin).turn_off(); id(bar3_left_cs_pin).turn_on(); id(bar_display).setup(); delay(5); id(bar3_left_cs_pin).turn_off(); id(bar3_right_cs_pin).turn_on(); id(bar_display).setup(); delay(5); id(bar3_right_cs_pin).turn_off(); - id: bar1_left_script_draw then: - lambda: | switch (id(active_page_nr)){ // Page 0 - Start case 0: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 1 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Start"); break; // Page 1 - Music case 1: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 1 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Music"); break; // Page 2 - Lights case 2: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 1 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Lights"); break; // Page 3 - Security case 3: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 1 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Security"); break; } - id: bar1_right_script_draw then: - lambda: | switch (id(active_page_nr)){ // Page 0 - Start case 0: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 1 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Start"); break; // Page 1 - Music case 1: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 1 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Music"); break; // Page 2 - Lights case 2: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 1 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Lights"); break; // Page 3 - Security case 3: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 1 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Security"); break; } - id: bar2_left_script_draw then: - lambda: | switch (id(active_page_nr)){ // Page 0 - Start case 0: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 2 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Start"); break; // Page 1 - Music case 1: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 2 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Music"); break; // Page 2 - Lights case 2: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 2 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Lights"); break; // Page 3 - Security case 3: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 2 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Security"); break; } - id: bar2_right_script_draw then: - lambda: | switch (id(active_page_nr)){ // Page 0 - Start case 0: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 2 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Start"); break; // Page 1 - Music case 1: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 2 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Music"); break; // Page 2 - Lights case 2: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 2 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Lights"); break; // Page 3 - Security case 3: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 2 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Security"); break; } - id: bar3_left_script_draw then: - lambda: | switch (id(active_page_nr)){ // Page 0 - Start case 0: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 3 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Start"); break; // Page 1 - Music case 1: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 3 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Music"); break; // Page 2 - Lights case 2: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 3 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Lights"); break; // Page 3 - Security case 3: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 3 left"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Security"); break; } - id: bar3_right_script_draw then: - lambda: | switch (id(active_page_nr)){ // Page 0 - Start case 0: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 3 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Start"); break; // Page 1 - Music case 1: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 3 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Music"); break; // Page 2 - Lights case 2: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 3 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Lights"); break; // Page 3 - Security case 3: id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar 3 right"); id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Security"); break; } - id: bars_script_update then: - script.execute: bar1_left_script_update - delay: 0.1s - script.execute: bar1_right_script_update - delay: 0.1s - script.execute: bar2_left_script_update - delay: 0.1s - script.execute: bar2_right_script_update - delay: 0.1s - script.execute: bar3_left_script_update - delay: 0.1s - script.execute: bar3_right_script_update - id: event_trigger_feedback parameters: event_id: esphome::template_::TemplateEvent* event_msg: std::string led_id: light::LightState* r: float g: float b: float then: - lambda: |- event_id->trigger(event_msg); if(led_id != nullptr){ auto call = led_id->make_call(); call.set_state(true); call.set_rgb(r, g, b); call.set_brightness(1.0); call.set_flash_length(200); // Returns to previous state automatically call.perform(); } - id: update_all_page_leds then: - lambda: | id(update_single_led).execute("bar1_left_front_rgb_led", id(bar1_left_front_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar1_right_front_rgb_led", id(bar1_right_front_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar1_left_back_rgb_led", id(bar1_left_back_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar1_right_back_rgb_led", id(bar1_right_back_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar2_left_front_rgb_led", id(bar2_left_front_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar2_right_front_rgb_led", id(bar2_right_front_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar2_left_back_rgb_led", id(bar2_left_back_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar2_right_back_rgb_led", id(bar2_right_back_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar3_left_front_rgb_led", id(bar3_left_front_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar3_right_front_rgb_led", id(bar3_right_front_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar3_left_back_rgb_led", id(bar3_left_back_rgb_led), id(active_page_nr)); id(update_single_led).execute("bar3_right_back_rgb_led", id(bar3_right_back_rgb_led), id(active_page_nr)); - id: update_single_led parameters: led_name: string led_id: light::LightState* page: int then: - lambda: |- if(led_id != nullptr){ float r = id(internal_page_leds_r)[led_name][page]; float g = id(internal_page_leds_g)[led_name][page]; float b = id(internal_page_leds_b)[led_name][page]; float br = id(internal_page_leds_brightness)[led_name][page]; std::string effect = id(internal_page_leds_effect)[led_name][page]; if(r > 1.5) r = r / 255.0; if(g > 1.5) g = g / 255.0; if(b > 1.5) b = b / 255.0; if(br > 1.5) br = br / 255.0; auto call = led_id->make_call(); call.set_transition_length(10); if(br <= 0.0001) { call.set_state(false); } else { call.set_state(true); call.set_rgb(r,g,b); call.set_brightness(br); call.set_effect(effect); } call.perform(); } image: - file: mdi:chevron-right id: icon_next_page resize: 30x30 type: BINARY - file: mdi:chevron-left id: icon_prev_page resize: 30x30 type: BINARY time: - platform: homeassistant id: datetime i2c: - id: buttons sda: GPIO1 scl: GPIO2 frequency: 50khz - id: sensors sda: GPIO47 scl: GPIO48 frequency: 50khz spi: clk_pin: GPIO6 mosi_pin: GPIO5 light: - platform: esp32_rmt_led_strip id: neopixels rgb_order: RGB chipset: ws2812 pin: GPIO4 num_leds: 13 internal: true - platform: partition id: internal_all_rgb internal: true segments: - id: neopixels from: 0 to: 12 - platform: monochromatic output: display_backlight_pwm gamma_correct: 2.2 name: Main Display Backlight id: display_backlight restore_mode: ALWAYS_ON - platform: partition id: internal_notification_rgb internal: true segments: - id: neopixels from: 1 to: 1 - id: neopixels from: 3 to: 3 - platform: monochromatic output: bars_backlight_pwm gamma_correct: 2.2 name: Bars Display Backlight id: bars_backlight restore_mode: ALWAYS_ON - platform: partition name: BAR 1 Left RGB Front id: bar1_left_front_rgb_led segments: - id: neopixels from: 0 to: 0 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 1 Left RGB Back id: bar1_left_back_rgb_led segments: - id: neopixels from: 1 to: 1 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 1 Right RGB Front id: bar1_right_front_rgb_led segments: - id: neopixels from: 2 to: 2 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 1 Right RGB Back id: bar1_right_back_rgb_led segments: - id: neopixels from: 3 to: 3 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 2 Left RGB Front id: bar2_left_front_rgb_led segments: - id: neopixels from: 4 to: 4 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 2 Left RGB Back id: bar2_left_back_rgb_led segments: - id: neopixels from: 5 to: 5 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 2 Right RGB Front id: bar2_right_front_rgb_led segments: - id: neopixels from: 6 to: 6 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 2 Right RGB Back id: bar2_right_back_rgb_led segments: - id: neopixels from: 7 to: 7 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 3 Left RGB Front id: bar3_left_front_rgb_led segments: - id: neopixels from: 8 to: 8 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 3 Left RGB Back id: bar3_left_back_rgb_led segments: - id: neopixels from: 9 to: 9 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 3 Right RGB Front id: bar3_right_front_rgb_led segments: - id: neopixels from: 10 to: 10 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms - platform: partition name: BAR 3 Right RGB Back id: bar3_right_back_rgb_led segments: - id: neopixels from: 11 to: 11 effects: - pulse: name: Breathe transition_length: 1s update_interval: 1.5s min_brightness: 20% max_brightness: 100% - pulse: name: Blink transition_length: 50ms update_interval: 500ms output: - platform: ledc pin: GPIO3 id: display_backlight_pwm inverted: true max_power: 1 frequency: 500Hz - platform: ledc pin: GPIO46 id: bars_backlight_pwm inverted: true max_power: 0.6 frequency: 500Hz - platform: gpio id: bar1_left_cs_pin pin: mcp23xxx: base_J1 number: 5 mode: output: true inverted: true - platform: gpio id: bar1_right_cs_pin pin: mcp23xxx: base_J1 number: 1 mode: output: true inverted: true - platform: gpio id: bar2_left_cs_pin pin: mcp23xxx: base_J2 number: 5 mode: output: true inverted: true - platform: gpio id: bar2_right_cs_pin pin: mcp23xxx: base_J2 number: 1 mode: output: true inverted: true - platform: gpio id: bar3_left_cs_pin pin: mcp23xxx: base_J3 number: 5 mode: output: true inverted: true - platform: gpio id: bar3_right_cs_pin pin: mcp23xxx: base_J3 number: 1 mode: output: true inverted: true display: - id: display_disp platform: ili9xxx model: ili9341 invert_colors: false color_order: rgb update_interval: 30s dc_pin: number: GPIO7 allow_other_uses: true cs_pin: mcp23xxx: base_J0 number: 5 mode: output: true inverted: false show_test_card: false dimensions: height: 240 width: 320 rotation: 180 lambda: id(display_script_draw).execute(); - id: bar_display platform: ili9xxx model: ST7735 color_order: bgr update_interval: never dc_pin: number: GPIO7 allow_other_uses: true invert_colors: false show_test_card: false auto_clear_enabled: false dimensions: height: 160 width: 80 offset_width: 24 mcp23008: - id: base_J0 i2c_id: buttons address: '32' - id: base_J3 i2c_id: buttons address: 35 - id: base_J2 i2c_id: buttons address: 34 - id: base_J1 i2c_id: buttons address: 33 binary_sensor: - platform: gpio id: display_left_btn name: Main Display button Left internal: true pin: mcp23xxx: base_J0 number: 6 mode: INPUT_PULLUP inverted: true filters: - delayed_off: 10ms on_multi_click: - timing: - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: prev_page - timing: - ON for at most 300ms - OFF for at most 0.2s - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: display_left_btn_event led_id: !lambda "return nullptr;" r: 0 g: 0 b: 255 event_msg: !lambda "return \"double_click \" + id(active_page_name);" - timing: - ON for at least 1s - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: display_left_btn_event led_id: !lambda "return nullptr;" r: 255 g: 0 b: 255 event_msg: !lambda "return \"hold \" + id(active_page_name);" - platform: gpio id: display_right_btn name: Main Display button Right internal: true pin: mcp23xxx: base_J0 number: 2 mode: INPUT_PULLUP inverted: true filters: - delayed_off: 10ms on_multi_click: - timing: - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: next_page - timing: - ON for at most 300ms - OFF for at most 0.2s - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: display_right_btn_event led_id: !lambda "return nullptr;" r: 0 g: 0 b: 255 event_msg: !lambda "return \"double_click \" + id(active_page_name);" - timing: - ON for at least 1s - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: display_right_btn_event led_id: !lambda "return nullptr;" r: 255 g: 0 b: 255 event_msg: !lambda "return \"hold \" + id(active_page_name);" - platform: gpio id: bar1_left_btn name: BAR 1 button Left internal: true pin: mcp23xxx: base_J1 number: 6 mode: INPUT_PULLUP inverted: true filters: - delayed_off: 10ms on_multi_click: - timing: - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar1_left_btn_event led_id: bar1_left_front_rgb_led r: 0 g: 255 b: 0 event_msg: !lambda "return \"click \" + id(active_page_name);" - timing: - ON for at most 300ms - OFF for at most 0.2s - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar1_left_btn_event led_id: bar1_left_front_rgb_led r: 0 g: 0 b: 255 event_msg: !lambda "return \"double_click \" + id(active_page_name);" - timing: - ON for at least 1s - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar1_left_btn_event led_id: bar1_left_front_rgb_led r: 255 g: 0 b: 255 event_msg: !lambda "return \"hold \" + id(active_page_name);" - platform: gpio id: bar1_right_btn name: BAR 1 button Right internal: true pin: mcp23xxx: base_J1 number: 2 mode: INPUT_PULLUP inverted: true filters: - delayed_off: 10ms on_multi_click: - timing: - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar1_right_btn_event led_id: bar1_right_front_rgb_led r: 0 g: 255 b: 0 event_msg: !lambda "return \"click \" + id(active_page_name);" - timing: - ON for at most 300ms - OFF for at most 0.2s - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar1_right_btn_event led_id: bar1_right_front_rgb_led r: 0 g: 0 b: 255 event_msg: !lambda "return \"double_click \" + id(active_page_name);" - timing: - ON for at least 1s - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar1_right_btn_event led_id: bar1_right_front_rgb_led r: 255 g: 0 b: 255 event_msg: !lambda "return \"hold \" + id(active_page_name);" - platform: gpio id: bar2_left_btn name: BAR 2 button Left internal: true pin: mcp23xxx: base_J2 number: 6 mode: INPUT_PULLUP inverted: true filters: - delayed_off: 10ms on_multi_click: - timing: - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar2_left_btn_event led_id: bar2_left_front_rgb_led r: 0 g: 255 b: 0 event_msg: !lambda "return \"click \" + id(active_page_name);" - timing: - ON for at most 300ms - OFF for at most 0.2s - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar2_left_btn_event led_id: bar2_left_front_rgb_led r: 0 g: 0 b: 255 event_msg: !lambda "return \"double_click \" + id(active_page_name);" - timing: - ON for at least 1s - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar2_left_btn_event led_id: bar2_left_front_rgb_led r: 255 g: 0 b: 255 event_msg: !lambda "return \"hold \" + id(active_page_name);" - platform: gpio id: bar2_right_btn name: BAR 2 button Right internal: true pin: mcp23xxx: base_J2 number: 2 mode: INPUT_PULLUP inverted: true filters: - delayed_off: 10ms on_multi_click: - timing: - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar2_right_btn_event led_id: bar2_right_front_rgb_led r: 0 g: 255 b: 0 event_msg: !lambda "return \"click \" + id(active_page_name);" - timing: - ON for at most 300ms - OFF for at most 0.2s - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar2_right_btn_event led_id: bar2_right_front_rgb_led r: 0 g: 0 b: 255 event_msg: !lambda "return \"double_click \" + id(active_page_name);" - timing: - ON for at least 1s - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar2_right_btn_event led_id: bar2_right_front_rgb_led r: 255 g: 0 b: 255 event_msg: !lambda "return \"hold \" + id(active_page_name);" - platform: gpio id: bar3_left_btn name: BAR 3 button Left internal: true pin: mcp23xxx: base_J3 number: 6 mode: INPUT_PULLUP inverted: true filters: - delayed_off: 10ms on_multi_click: - timing: - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar3_left_btn_event led_id: bar3_left_front_rgb_led r: 0 g: 255 b: 0 event_msg: !lambda "return \"click \" + id(active_page_name);" - timing: - ON for at most 300ms - OFF for at most 0.2s - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar3_left_btn_event led_id: bar3_left_front_rgb_led r: 0 g: 0 b: 255 event_msg: !lambda "return \"double_click \" + id(active_page_name);" - timing: - ON for at least 1s - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar3_left_btn_event led_id: bar3_left_front_rgb_led r: 255 g: 0 b: 255 event_msg: !lambda "return \"hold \" + id(active_page_name);" - platform: gpio id: bar3_right_btn name: BAR 3 button Right internal: true pin: mcp23xxx: base_J3 number: 2 mode: INPUT_PULLUP inverted: true filters: - delayed_off: 10ms on_multi_click: - timing: - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar3_right_btn_event led_id: bar3_right_front_rgb_led r: 0 g: 255 b: 0 event_msg: !lambda "return \"click \" + id(active_page_name);" - timing: - ON for at most 300ms - OFF for at most 0.2s - ON for at most 300ms - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar3_right_btn_event led_id: bar3_right_front_rgb_led r: 0 g: 0 b: 255 event_msg: !lambda "return \"double_click \" + id(active_page_name);" - timing: - ON for at least 1s - OFF for at least 0.2s then: - script.execute: id: event_trigger_feedback event_id: bar3_right_btn_event led_id: bar3_right_front_rgb_led r: 255 g: 0 b: 255 event_msg: !lambda "return \"hold \" + id(active_page_name);" substitutions: button_events: - click Start - double_click Start - hold Start - click Music - double_click Music - hold Music - click Lights - double_click Lights - hold Lights - click Security - double_click Security - hold Security event: - platform: template id: display_left_btn_event name: DISPLAY Button Left device_class: button event_types: ${button_events} - platform: template id: display_right_btn_event name: DISPLAY Button Right device_class: button event_types: ${button_events} - platform: template id: bar1_left_btn_event name: BAR 1 Button Left device_class: button event_types: ${button_events} - platform: template id: bar1_right_btn_event name: BAR 1 Button Right device_class: button event_types: ${button_events} - platform: template id: bar2_left_btn_event name: BAR 2 Button Left device_class: button event_types: ${button_events} - platform: template id: bar2_right_btn_event name: BAR 2 Button Right device_class: button event_types: ${button_events} - platform: template id: bar3_left_btn_event name: BAR 3 Button Left device_class: button event_types: ${button_events} - platform: template id: bar3_right_btn_event name: BAR 3 Button Right device_class: button event_types: ${button_events}