From 6631430bae409f7d2ad864f964884c7827718a3c Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Tue, 13 Oct 2026 14:17:14 -0400 Subject: [PATCH 01/30] Add LED strip test config on exposed IO1 header Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 1 + Integrations/ESPHome/led_strip.yaml | 86 +++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 Integrations/ESPHome/led_strip.yaml diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 5243f92..d478127 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -8,6 +8,7 @@ substitutions: packages: wizmote: !include wizmote.yaml + led_strip: !include led_strip.yaml esphome: friendly_name: Apollo CAST-1 diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml new file mode 100644 index 0000000..b492630 --- /dev/null +++ b/Integrations/ESPHome/led_strip.yaml @@ -0,0 +1,86 @@ +# External LED strip on the exposed 5V / GND / IO1 header; included by Core.yaml +# Test config: set the count and chipset to match the strip being tested + +substitutions: + LED_STRIP_PIN: GPIO1 + LED_STRIP_NUM_LEDS: "30" + LED_STRIP_CHIPSET: WS2812 + LED_STRIP_COLOR_ORDER: GRB + +light: + - platform: esp32_rmt_led_strip + id: led_strip + name: "LED Strip" + pin: ${LED_STRIP_PIN} + chipset: ${LED_STRIP_CHIPSET} + num_leds: ${LED_STRIP_NUM_LEDS} + channel_colors: ${LED_STRIP_COLOR_ORDER} + default_transition_length: 0s + restore_mode: ALWAYS_OFF + effects: + - addressable_rainbow: + name: "Rainbow" + - addressable_color_wipe: + name: "Color Wipe" + - addressable_scan: + name: "Scan" + - addressable_twinkle: + name: "Twinkle" + - strobe: + name: "Strobe" + +button: + # Steps the strip through red, green, blue, white, then a rainbow so a bad + # channel, wrong color order, or dead pixel shows up at a glance + - platform: template + name: "LED Strip Test" + id: led_strip_test_button + icon: mdi:led-strip-variant + entity_category: diagnostic + on_press: + - script.execute: led_strip_test + +script: + - id: led_strip_test + mode: restart + then: + - logger.log: "LED strip test: red" + - light.turn_on: + id: led_strip + brightness: 50% + red: 100% + green: 0% + blue: 0% + effect: none + - delay: 2s + - logger.log: "LED strip test: green" + - light.turn_on: + id: led_strip + red: 0% + green: 100% + blue: 0% + - delay: 2s + - logger.log: "LED strip test: blue" + - light.turn_on: + id: led_strip + red: 0% + green: 0% + blue: 100% + - delay: 2s + # Low brightness: full white on a long strip can overdraw the 5V rail + - logger.log: "LED strip test: white" + - light.turn_on: + id: led_strip + brightness: 25% + red: 100% + green: 100% + blue: 100% + - delay: 2s + - logger.log: "LED strip test: rainbow" + - light.turn_on: + id: led_strip + brightness: 50% + effect: "Rainbow" + - delay: 5s + - light.turn_off: led_strip + - logger.log: "LED strip test: done" From a19290cf3655a545b725089c598ae9332b5bcb5d Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Tue, 13 Oct 2026 16:24:54 -0400 Subject: [PATCH 02/30] Add LED strip controls, Music Mode and runtime strip settings LED count, max brightness, color order and chipset are now Home Assistant entities applied at runtime, so end users never need to recompile. Music Mode runs a chosen effect while the player is playing. Bump version to 26.10.13.1. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 2 +- Integrations/ESPHome/led_strip.yaml | 267 ++++++++++++++++++++++++++-- 2 files changed, 252 insertions(+), 17 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index d478127..8334ba5 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.9.21.1" + version: "26.10.13.1" stable_manifest_base: "https://apolloautomation.github.io/CAST-1" beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml index b492630..08ae734 100644 --- a/Integrations/ESPHome/led_strip.yaml +++ b/Integrations/ESPHome/led_strip.yaml @@ -1,22 +1,43 @@ -# External LED strip on the exposed 5V / GND / IO1 header; included by Core.yaml -# Test config: set the count and chipset to match the strip being tested +# Addressable LED strip on the exposed 5V / GND / IO1 header; included by Core.yaml +# Count, color order, chipset and brightness cap are set from Home Assistant substitutions: LED_STRIP_PIN: GPIO1 - LED_STRIP_NUM_LEDS: "30" - LED_STRIP_CHIPSET: WS2812 - LED_STRIP_COLOR_ORDER: GRB + # Buffers are sized for this many LEDs; the LED Strip Count entity picks how many are driven + LED_STRIP_MAX_LEDS: "300" + LED_STRIP_DEFAULT_LEDS: "30" + +esphome: + on_boot: + # Apply the saved strip settings before the light's first write + # Must run after the strip and the restored entities set up (800) + - priority: 600 + then: + - lambda: |- + id(led_strip_output)->set_num_leds((uint16_t) id(led_strip_count).state); + - script.execute: + id: led_strip_apply_color_order + order: !lambda "return std::string(id(led_strip_color_order).current_option());" + - script.execute: + id: led_strip_apply_chipset + chipset: !lambda "return std::string(id(led_strip_chipset).current_option());" + - script.execute: + id: led_strip_apply_max_brightness + percent: !lambda "return id(led_strip_max_brightness).state;" light: - platform: esp32_rmt_led_strip id: led_strip + output_id: led_strip_output name: "LED Strip" + icon: mdi:led-strip-variant pin: ${LED_STRIP_PIN} - chipset: ${LED_STRIP_CHIPSET} - num_leds: ${LED_STRIP_NUM_LEDS} - channel_colors: ${LED_STRIP_COLOR_ORDER} - default_transition_length: 0s - restore_mode: ALWAYS_OFF + # Timings and color order are swapped at runtime by the select entities + chipset: WS2812 + channel_colors: GRB + num_leds: ${LED_STRIP_MAX_LEDS} + default_transition_length: 1s + restore_mode: RESTORE_DEFAULT_OFF effects: - addressable_rainbow: name: "Rainbow" @@ -26,36 +47,251 @@ light: name: "Scan" - addressable_twinkle: name: "Twinkle" + - addressable_random_twinkle: + name: "Random Twinkle" + - addressable_fireworks: + name: "Fireworks" + - addressable_flicker: + name: "Flicker" + - pulse: + name: "Pulse" - strobe: name: "Strobe" +number: + - platform: template + id: led_strip_count + name: "LED Strip Count" + icon: mdi:counter + entity_category: config + mode: box + min_value: 1 + max_value: ${LED_STRIP_MAX_LEDS} + step: 1 + optimistic: true + restore_value: true + initial_value: ${LED_STRIP_DEFAULT_LEDS} + set_action: + - script.execute: + id: led_strip_apply_count + count: !lambda "return (int) x;" + + # Caps every channel so a long strip can't overdraw the header's 5V rail + - platform: template + id: led_strip_max_brightness + name: "LED Strip Max Brightness" + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + mode: slider + min_value: 10 + max_value: 100 + step: 5 + optimistic: true + restore_value: true + initial_value: 50 + set_action: + - script.execute: + id: led_strip_apply_max_brightness + percent: !lambda "return x;" + +select: + - platform: template + id: led_strip_color_order + name: "LED Strip Color Order" + icon: mdi:palette + entity_category: config + optimistic: true + restore_value: true + options: + - "GRB" + - "RGB" + - "BRG" + - "RBG" + - "GBR" + - "BGR" + initial_option: "GRB" + set_action: + - script.execute: + id: led_strip_apply_color_order + order: !lambda "return std::string(x);" + + - platform: template + id: led_strip_chipset + name: "LED Strip Chipset" + icon: mdi:chip + entity_category: config + optimistic: true + restore_value: true + options: + - "WS2812" + - "SK6812" + - "WS2811" + - "APA106" + - "SM16703" + initial_option: "WS2812" + set_action: + - script.execute: + id: led_strip_apply_chipset + chipset: !lambda "return std::string(x);" + + - platform: template + id: led_strip_music_effect + name: "LED Strip Music Effect" + icon: mdi:music-circle + entity_category: config + optimistic: true + restore_value: true + options: + - "Rainbow" + - "Color Wipe" + - "Scan" + - "Twinkle" + - "Random Twinkle" + - "Fireworks" + - "Flicker" + - "Pulse" + initial_option: "Rainbow" + +switch: + # Music Mode: the strip turns on with the Music Effect while audio plays and + # off once playback has stopped for 10s + - platform: template + id: led_strip_music_mode + name: "LED Strip Music Mode" + icon: mdi:music-note + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + - if: + condition: + binary_sensor.is_on: led_strip_music_playing + then: + - script.execute: led_strip_music_start + on_turn_off: + - if: + condition: + binary_sensor.is_on: led_strip_music_playing + then: + - light.turn_off: led_strip + +binary_sensor: + - platform: template + id: led_strip_music_playing + internal: true + condition: + media_player.is_playing: external_media_player + filters: + # Bridge track changes and rebuffering so the strip doesn't blink off + - delayed_off: 10s + on_press: + - if: + condition: + switch.is_on: led_strip_music_mode + then: + - script.execute: led_strip_music_start + on_release: + - if: + condition: + switch.is_on: led_strip_music_mode + then: + - light.turn_off: led_strip + button: # Steps the strip through red, green, blue, white, then a rainbow so a bad # channel, wrong color order, or dead pixel shows up at a glance - platform: template - name: "LED Strip Test" id: led_strip_test_button + name: "LED Strip Test" icon: mdi:led-strip-variant entity_category: diagnostic on_press: - script.execute: led_strip_test script: + - id: led_strip_apply_count + mode: queued + parameters: + count: int + then: + - lambda: |- + auto *out = id(led_strip_output); + // Blank every pixel the buffers cover, so LEDs past a lowered count go dark + out->set_num_leds(${LED_STRIP_MAX_LEDS}); + for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; + out->write_state(id(led_strip)); + out->set_num_leds((uint16_t) count); + out->clear_effect_data(); + // Repaint the current color at the new length (effects repaint themselves) + out->update_state(id(led_strip)); + ESP_LOGI("led_strip", "Driving %d LEDs", count); + + - id: led_strip_apply_max_brightness + parameters: + percent: float + then: + - lambda: |- + const float scale = percent / 100.0f; + id(led_strip_output)->set_correction(scale, scale, scale); + id(led_strip_output)->update_state(id(led_strip)); + + - id: led_strip_apply_color_order + parameters: + order: string + then: + - lambda: |- + // Each letter's position is that color's byte offset on the wire; + // all options are 3-byte, so the allocated buffers still fit + id(led_strip_output)->set_channel_colors(light::ChannelColors{ + (uint8_t) order.find('R'), (uint8_t) order.find('G'), (uint8_t) order.find('B'), + light::ChannelColors::NO_WHITE}); + id(led_strip_output)->update_state(id(led_strip)); + + - id: led_strip_apply_chipset + parameters: + chipset: string + then: + - lambda: |- + // Bit timings in ns, matching ESPHome's esp32_rmt_led_strip chipset table + auto *out = id(led_strip_output); + if (chipset == "SK6812") { + out->set_led_params(300, 900, 600, 600, 0, 0); + } else if (chipset == "WS2811") { + out->set_led_params(300, 1090, 1090, 320, 0, 300000); + } else if (chipset == "APA106") { + out->set_led_params(350, 1360, 1360, 350, 0, 0); + } else if (chipset == "SM16703") { + out->set_led_params(300, 900, 900, 300, 0, 0); + } else { + out->set_led_params(400, 1000, 1000, 400, 0, 0); + } + out->schedule_show(); + + - id: led_strip_music_start + then: + - light.turn_on: + id: led_strip + effect: !lambda "return std::string(id(led_strip_music_effect).current_option());" + - id: led_strip_test mode: restart then: - logger.log: "LED strip test: red" + - light.control: + id: led_strip + effect: none - light.turn_on: id: led_strip - brightness: 50% + transition_length: 0s + brightness: 100% red: 100% green: 0% blue: 0% - effect: none - delay: 2s - logger.log: "LED strip test: green" - light.turn_on: id: led_strip + transition_length: 0s red: 0% green: 100% blue: 0% @@ -63,15 +299,15 @@ script: - logger.log: "LED strip test: blue" - light.turn_on: id: led_strip + transition_length: 0s red: 0% green: 0% blue: 100% - delay: 2s - # Low brightness: full white on a long strip can overdraw the 5V rail - logger.log: "LED strip test: white" - light.turn_on: id: led_strip - brightness: 25% + transition_length: 0s red: 100% green: 100% blue: 100% @@ -79,7 +315,6 @@ script: - logger.log: "LED strip test: rainbow" - light.turn_on: id: led_strip - brightness: 50% effect: "Rainbow" - delay: 5s - light.turn_off: led_strip From be4dd798d66bd12c14627e44b1a0e509ac487660 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Tue, 13 Oct 2026 16:39:39 -0400 Subject: [PATCH 03/30] Move LED strip into Core.yaml, disable by default, split RMT memory All LED strip entities are now in Core.yaml and disabled by default in Home Assistant. Both strips defaulted to all 192 RMT TX symbols, so whichever set up second failed: the onboard LED stopped working with the strip in use, or the strip hit RMT TX timeouts. Give the onboard LED 48 and the strip 144. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 323 +++++++++++++++++++++++++++- Integrations/ESPHome/led_strip.yaml | 321 --------------------------- 2 files changed, 322 insertions(+), 322 deletions(-) delete mode 100644 Integrations/ESPHome/led_strip.yaml diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 8334ba5..8df53af 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -4,11 +4,15 @@ substitutions: beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" beta_manifest_file: "manifest.json" + # LED strip on the exposed 5V / GND / IO1 header + LED_STRIP_PIN: GPIO1 + # Buffers are sized for this many LEDs; the LED Strip Count entity picks how many are driven + LED_STRIP_MAX_LEDS: "300" + LED_STRIP_DEFAULT_LEDS: "30" packages: wizmote: !include wizmote.yaml - led_strip: !include led_strip.yaml esphome: friendly_name: Apollo CAST-1 @@ -39,6 +43,21 @@ esphome: - lambda: |- id(wifi_1).set_enable_on_boot(false); id(espnow_component).set_wifi_channel(1); + # Apply the saved LED strip settings before the light's first write + # Must run after the strip and the restored entities set up (800) + - priority: 600 + then: + - lambda: |- + id(led_strip_output)->set_num_leds((uint16_t) id(led_strip_count).state); + - script.execute: + id: led_strip_apply_color_order + order: !lambda "return std::string(id(led_strip_color_order).current_option());" + - script.execute: + id: led_strip_apply_chipset + chipset: !lambda "return std::string(id(led_strip_chipset).current_option());" + - script.execute: + id: led_strip_apply_max_brightness + percent: !lambda "return id(led_strip_max_brightness).state;" # Park the W5500 helper task when no HAT is present, so it stops polling a # floating SPI bus and panicking the device every ~100s # Must run after ethernet setup (250) @@ -327,6 +346,17 @@ button: - delay: 5s - lambda: id(update_http_request).perform(true); + # Steps the strip through red, green, blue, white, then a rainbow so a bad + # channel, wrong color order, or dead pixel shows up at a glance + - platform: template + id: led_strip_test_button + name: "LED Strip Test" + disabled_by_default: true + icon: mdi:led-strip-variant + entity_category: diagnostic + on_press: + - script.execute: led_strip_test + binary_sensor: - platform: status name: Online @@ -360,6 +390,27 @@ binary_sensor: id(testScript).execute(); } + - platform: template + id: led_strip_music_playing + internal: true + condition: + media_player.is_playing: external_media_player + filters: + # Bridge track changes and rebuffering so the strip doesn't blink off + - delayed_off: 10s + on_press: + - if: + condition: + switch.is_on: led_strip_music_mode + then: + - script.execute: led_strip_music_start + on_release: + - if: + condition: + switch.is_on: led_strip_music_mode + then: + - light.turn_off: led_strip + sensor: - platform: internal_temperature name: "ESP Temperature" @@ -394,6 +445,28 @@ switch: on_turn_off: - esp32_ble_tracker.stop_scan: + # Music Mode: the strip turns on with the Music Effect while audio plays and + # off once playback has stopped for 10s + - platform: template + id: led_strip_music_mode + name: "LED Strip Music Mode" + disabled_by_default: true + icon: mdi:music-note + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + - if: + condition: + binary_sensor.is_on: led_strip_music_playing + then: + - script.execute: led_strip_music_start + on_turn_off: + - if: + condition: + binary_sensor.is_on: led_strip_music_playing + then: + - light.turn_off: led_strip + text_sensor: # Which path is carrying the device, for troubleshooting and HA notifications - platform: template @@ -459,6 +532,9 @@ light: default_transition_length: 0s chipset: WS2812 num_leds: 4 + # The S3 has 192 RMT TX symbols in total and each strip defaults to all of + # them, so split them or the second strip's channel fails + rmt_symbols: 48 channel_colors: GRB effects: - pulse: @@ -474,6 +550,41 @@ light: min_brightness: 50% max_brightness: 100% + - platform: esp32_rmt_led_strip + id: led_strip + output_id: led_strip_output + name: "LED Strip" + disabled_by_default: true + icon: mdi:led-strip-variant + pin: ${LED_STRIP_PIN} + # Timings and color order are swapped at runtime by the select entities + chipset: WS2812 + channel_colors: GRB + num_leds: ${LED_STRIP_MAX_LEDS} + # The rest of the RMT TX memory after the onboard light's 48 + rmt_symbols: 144 + default_transition_length: 1s + restore_mode: RESTORE_DEFAULT_OFF + effects: + - addressable_rainbow: + name: "Rainbow" + - addressable_color_wipe: + name: "Color Wipe" + - addressable_scan: + name: "Scan" + - addressable_twinkle: + name: "Twinkle" + - addressable_random_twinkle: + name: "Random Twinkle" + - addressable_fireworks: + name: "Fireworks" + - addressable_flicker: + name: "Flicker" + - pulse: + name: "Pulse" + - strobe: + name: "Strobe" + select: - platform: template id: firmware_channel @@ -490,6 +601,105 @@ select: then: - script.execute: apply_ota_source + - platform: template + id: led_strip_color_order + name: "LED Strip Color Order" + disabled_by_default: true + icon: mdi:palette + entity_category: config + optimistic: true + restore_value: true + options: + - "GRB" + - "RGB" + - "BRG" + - "RBG" + - "GBR" + - "BGR" + initial_option: "GRB" + set_action: + - script.execute: + id: led_strip_apply_color_order + order: !lambda "return std::string(x);" + + - platform: template + id: led_strip_chipset + name: "LED Strip Chipset" + disabled_by_default: true + icon: mdi:chip + entity_category: config + optimistic: true + restore_value: true + options: + - "WS2812" + - "SK6812" + - "WS2811" + - "APA106" + - "SM16703" + initial_option: "WS2812" + set_action: + - script.execute: + id: led_strip_apply_chipset + chipset: !lambda "return std::string(x);" + + - platform: template + id: led_strip_music_effect + name: "LED Strip Music Effect" + disabled_by_default: true + icon: mdi:music-circle + entity_category: config + optimistic: true + restore_value: true + options: + - "Rainbow" + - "Color Wipe" + - "Scan" + - "Twinkle" + - "Random Twinkle" + - "Fireworks" + - "Flicker" + - "Pulse" + initial_option: "Rainbow" + +number: + - platform: template + id: led_strip_count + name: "LED Strip Count" + disabled_by_default: true + icon: mdi:counter + entity_category: config + mode: box + min_value: 1 + max_value: ${LED_STRIP_MAX_LEDS} + step: 1 + optimistic: true + restore_value: true + initial_value: ${LED_STRIP_DEFAULT_LEDS} + set_action: + - script.execute: + id: led_strip_apply_count + count: !lambda "return (int) x;" + + # Caps every channel so a long strip can't overdraw the header's 5V rail + - platform: template + id: led_strip_max_brightness + name: "LED Strip Max Brightness" + disabled_by_default: true + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + mode: slider + min_value: 10 + max_value: 100 + step: 5 + optimistic: true + restore_value: true + initial_value: 50 + set_action: + - script.execute: + id: led_strip_apply_max_brightness + percent: !lambda "return x;" + audio_dac: - platform: pcm5122 id: external_dac @@ -771,3 +981,114 @@ script: blue: 0% - light.turn_off: id: rgb_light + + - id: led_strip_apply_count + mode: queued + parameters: + count: int + then: + - lambda: |- + auto *out = id(led_strip_output); + // Blank every pixel the buffers cover, so LEDs past a lowered count go dark + out->set_num_leds(${LED_STRIP_MAX_LEDS}); + for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; + out->write_state(id(led_strip)); + out->set_num_leds((uint16_t) count); + out->clear_effect_data(); + // Repaint the current color at the new length (effects repaint themselves) + out->update_state(id(led_strip)); + ESP_LOGI("led_strip", "Driving %d LEDs", count); + + - id: led_strip_apply_max_brightness + parameters: + percent: float + then: + - lambda: |- + const float scale = percent / 100.0f; + id(led_strip_output)->set_correction(scale, scale, scale); + id(led_strip_output)->update_state(id(led_strip)); + + - id: led_strip_apply_color_order + parameters: + order: string + then: + - lambda: |- + // Each letter's position is that color's byte offset on the wire; + // all options are 3-byte, so the allocated buffers still fit + id(led_strip_output)->set_channel_colors(light::ChannelColors{ + (uint8_t) order.find('R'), (uint8_t) order.find('G'), (uint8_t) order.find('B'), + light::ChannelColors::NO_WHITE}); + id(led_strip_output)->update_state(id(led_strip)); + + - id: led_strip_apply_chipset + parameters: + chipset: string + then: + - lambda: |- + // Bit timings in ns, matching ESPHome's esp32_rmt_led_strip chipset table + auto *out = id(led_strip_output); + if (chipset == "SK6812") { + out->set_led_params(300, 900, 600, 600, 0, 0); + } else if (chipset == "WS2811") { + out->set_led_params(300, 1090, 1090, 320, 0, 300000); + } else if (chipset == "APA106") { + out->set_led_params(350, 1360, 1360, 350, 0, 0); + } else if (chipset == "SM16703") { + out->set_led_params(300, 900, 900, 300, 0, 0); + } else { + out->set_led_params(400, 1000, 1000, 400, 0, 0); + } + out->schedule_show(); + + - id: led_strip_music_start + then: + - light.turn_on: + id: led_strip + effect: !lambda "return std::string(id(led_strip_music_effect).current_option());" + + - id: led_strip_test + mode: restart + then: + - logger.log: "LED strip test: red" + - light.control: + id: led_strip + effect: none + - light.turn_on: + id: led_strip + transition_length: 0s + brightness: 100% + red: 100% + green: 0% + blue: 0% + - delay: 2s + - logger.log: "LED strip test: green" + - light.turn_on: + id: led_strip + transition_length: 0s + red: 0% + green: 100% + blue: 0% + - delay: 2s + - logger.log: "LED strip test: blue" + - light.turn_on: + id: led_strip + transition_length: 0s + red: 0% + green: 0% + blue: 100% + - delay: 2s + - logger.log: "LED strip test: white" + - light.turn_on: + id: led_strip + transition_length: 0s + red: 100% + green: 100% + blue: 100% + - delay: 2s + - logger.log: "LED strip test: rainbow" + - light.turn_on: + id: led_strip + effect: "Rainbow" + - delay: 5s + - light.turn_off: led_strip + - logger.log: "LED strip test: done" diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml deleted file mode 100644 index 08ae734..0000000 --- a/Integrations/ESPHome/led_strip.yaml +++ /dev/null @@ -1,321 +0,0 @@ -# Addressable LED strip on the exposed 5V / GND / IO1 header; included by Core.yaml -# Count, color order, chipset and brightness cap are set from Home Assistant - -substitutions: - LED_STRIP_PIN: GPIO1 - # Buffers are sized for this many LEDs; the LED Strip Count entity picks how many are driven - LED_STRIP_MAX_LEDS: "300" - LED_STRIP_DEFAULT_LEDS: "30" - -esphome: - on_boot: - # Apply the saved strip settings before the light's first write - # Must run after the strip and the restored entities set up (800) - - priority: 600 - then: - - lambda: |- - id(led_strip_output)->set_num_leds((uint16_t) id(led_strip_count).state); - - script.execute: - id: led_strip_apply_color_order - order: !lambda "return std::string(id(led_strip_color_order).current_option());" - - script.execute: - id: led_strip_apply_chipset - chipset: !lambda "return std::string(id(led_strip_chipset).current_option());" - - script.execute: - id: led_strip_apply_max_brightness - percent: !lambda "return id(led_strip_max_brightness).state;" - -light: - - platform: esp32_rmt_led_strip - id: led_strip - output_id: led_strip_output - name: "LED Strip" - icon: mdi:led-strip-variant - pin: ${LED_STRIP_PIN} - # Timings and color order are swapped at runtime by the select entities - chipset: WS2812 - channel_colors: GRB - num_leds: ${LED_STRIP_MAX_LEDS} - default_transition_length: 1s - restore_mode: RESTORE_DEFAULT_OFF - effects: - - addressable_rainbow: - name: "Rainbow" - - addressable_color_wipe: - name: "Color Wipe" - - addressable_scan: - name: "Scan" - - addressable_twinkle: - name: "Twinkle" - - addressable_random_twinkle: - name: "Random Twinkle" - - addressable_fireworks: - name: "Fireworks" - - addressable_flicker: - name: "Flicker" - - pulse: - name: "Pulse" - - strobe: - name: "Strobe" - -number: - - platform: template - id: led_strip_count - name: "LED Strip Count" - icon: mdi:counter - entity_category: config - mode: box - min_value: 1 - max_value: ${LED_STRIP_MAX_LEDS} - step: 1 - optimistic: true - restore_value: true - initial_value: ${LED_STRIP_DEFAULT_LEDS} - set_action: - - script.execute: - id: led_strip_apply_count - count: !lambda "return (int) x;" - - # Caps every channel so a long strip can't overdraw the header's 5V rail - - platform: template - id: led_strip_max_brightness - name: "LED Strip Max Brightness" - icon: mdi:brightness-percent - entity_category: config - unit_of_measurement: "%" - mode: slider - min_value: 10 - max_value: 100 - step: 5 - optimistic: true - restore_value: true - initial_value: 50 - set_action: - - script.execute: - id: led_strip_apply_max_brightness - percent: !lambda "return x;" - -select: - - platform: template - id: led_strip_color_order - name: "LED Strip Color Order" - icon: mdi:palette - entity_category: config - optimistic: true - restore_value: true - options: - - "GRB" - - "RGB" - - "BRG" - - "RBG" - - "GBR" - - "BGR" - initial_option: "GRB" - set_action: - - script.execute: - id: led_strip_apply_color_order - order: !lambda "return std::string(x);" - - - platform: template - id: led_strip_chipset - name: "LED Strip Chipset" - icon: mdi:chip - entity_category: config - optimistic: true - restore_value: true - options: - - "WS2812" - - "SK6812" - - "WS2811" - - "APA106" - - "SM16703" - initial_option: "WS2812" - set_action: - - script.execute: - id: led_strip_apply_chipset - chipset: !lambda "return std::string(x);" - - - platform: template - id: led_strip_music_effect - name: "LED Strip Music Effect" - icon: mdi:music-circle - entity_category: config - optimistic: true - restore_value: true - options: - - "Rainbow" - - "Color Wipe" - - "Scan" - - "Twinkle" - - "Random Twinkle" - - "Fireworks" - - "Flicker" - - "Pulse" - initial_option: "Rainbow" - -switch: - # Music Mode: the strip turns on with the Music Effect while audio plays and - # off once playback has stopped for 10s - - platform: template - id: led_strip_music_mode - name: "LED Strip Music Mode" - icon: mdi:music-note - optimistic: true - restore_mode: RESTORE_DEFAULT_OFF - on_turn_on: - - if: - condition: - binary_sensor.is_on: led_strip_music_playing - then: - - script.execute: led_strip_music_start - on_turn_off: - - if: - condition: - binary_sensor.is_on: led_strip_music_playing - then: - - light.turn_off: led_strip - -binary_sensor: - - platform: template - id: led_strip_music_playing - internal: true - condition: - media_player.is_playing: external_media_player - filters: - # Bridge track changes and rebuffering so the strip doesn't blink off - - delayed_off: 10s - on_press: - - if: - condition: - switch.is_on: led_strip_music_mode - then: - - script.execute: led_strip_music_start - on_release: - - if: - condition: - switch.is_on: led_strip_music_mode - then: - - light.turn_off: led_strip - -button: - # Steps the strip through red, green, blue, white, then a rainbow so a bad - # channel, wrong color order, or dead pixel shows up at a glance - - platform: template - id: led_strip_test_button - name: "LED Strip Test" - icon: mdi:led-strip-variant - entity_category: diagnostic - on_press: - - script.execute: led_strip_test - -script: - - id: led_strip_apply_count - mode: queued - parameters: - count: int - then: - - lambda: |- - auto *out = id(led_strip_output); - // Blank every pixel the buffers cover, so LEDs past a lowered count go dark - out->set_num_leds(${LED_STRIP_MAX_LEDS}); - for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; - out->write_state(id(led_strip)); - out->set_num_leds((uint16_t) count); - out->clear_effect_data(); - // Repaint the current color at the new length (effects repaint themselves) - out->update_state(id(led_strip)); - ESP_LOGI("led_strip", "Driving %d LEDs", count); - - - id: led_strip_apply_max_brightness - parameters: - percent: float - then: - - lambda: |- - const float scale = percent / 100.0f; - id(led_strip_output)->set_correction(scale, scale, scale); - id(led_strip_output)->update_state(id(led_strip)); - - - id: led_strip_apply_color_order - parameters: - order: string - then: - - lambda: |- - // Each letter's position is that color's byte offset on the wire; - // all options are 3-byte, so the allocated buffers still fit - id(led_strip_output)->set_channel_colors(light::ChannelColors{ - (uint8_t) order.find('R'), (uint8_t) order.find('G'), (uint8_t) order.find('B'), - light::ChannelColors::NO_WHITE}); - id(led_strip_output)->update_state(id(led_strip)); - - - id: led_strip_apply_chipset - parameters: - chipset: string - then: - - lambda: |- - // Bit timings in ns, matching ESPHome's esp32_rmt_led_strip chipset table - auto *out = id(led_strip_output); - if (chipset == "SK6812") { - out->set_led_params(300, 900, 600, 600, 0, 0); - } else if (chipset == "WS2811") { - out->set_led_params(300, 1090, 1090, 320, 0, 300000); - } else if (chipset == "APA106") { - out->set_led_params(350, 1360, 1360, 350, 0, 0); - } else if (chipset == "SM16703") { - out->set_led_params(300, 900, 900, 300, 0, 0); - } else { - out->set_led_params(400, 1000, 1000, 400, 0, 0); - } - out->schedule_show(); - - - id: led_strip_music_start - then: - - light.turn_on: - id: led_strip - effect: !lambda "return std::string(id(led_strip_music_effect).current_option());" - - - id: led_strip_test - mode: restart - then: - - logger.log: "LED strip test: red" - - light.control: - id: led_strip - effect: none - - light.turn_on: - id: led_strip - transition_length: 0s - brightness: 100% - red: 100% - green: 0% - blue: 0% - - delay: 2s - - logger.log: "LED strip test: green" - - light.turn_on: - id: led_strip - transition_length: 0s - red: 0% - green: 100% - blue: 0% - - delay: 2s - - logger.log: "LED strip test: blue" - - light.turn_on: - id: led_strip - transition_length: 0s - red: 0% - green: 0% - blue: 100% - - delay: 2s - - logger.log: "LED strip test: white" - - light.turn_on: - id: led_strip - transition_length: 0s - red: 100% - green: 100% - blue: 100% - - delay: 2s - - logger.log: "LED strip test: rainbow" - - light.turn_on: - id: led_strip - effect: "Rainbow" - - delay: 5s - - light.turn_off: led_strip - - logger.log: "LED strip test: done" From c39b17b158fc7e3e21f7ce36e6b1963c08c7539b Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Tue, 13 Oct 2026 17:58:11 -0400 Subject: [PATCH 04/30] Make Music Mode follow stop quickly and stop stray LEDs staying lit Music Mode watched the main player, which only goes idle ~10s after stop while its buffers drain, then waited 10s more. Watch Sendspin's player and the HTTP source instead, which report stop at once, and bridge gaps for 3s. Keep the strip's RMT buffers in internal RAM and re-send the settled frame, so a frame cut short under audio load can't leave LEDs lit after turn-off. Bump version to 26.10.13.2. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 8df53af..66e27ec 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.10.13.1" + version: "26.10.13.2" stable_manifest_base: "https://apolloautomation.github.io/CAST-1" beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" @@ -393,11 +393,14 @@ binary_sensor: - platform: template id: led_strip_music_playing internal: true - condition: - media_player.is_playing: external_media_player + # Sendspin's player and the HTTP source report stop at once; the main + # player only goes idle ~10s later, once its buffers drain + lambda: |- + return id(sendspin_group_media_player).state == media_player::MEDIA_PLAYER_STATE_PLAYING || + id(http_media_source)->get_state() == media_source::MediaSourceState::PLAYING; filters: # Bridge track changes and rebuffering so the strip doesn't blink off - - delayed_off: 10s + - delayed_off: 3s on_press: - if: condition: @@ -563,8 +566,15 @@ light: num_leds: ${LED_STRIP_MAX_LEDS} # The rest of the RMT TX memory after the onboard light's 48 rmt_symbols: 144 + # The RMT interrupt refills from these buffers mid-frame; PSRAM reads can + # stall it under audio load and cut the frame short + use_psram: false default_transition_length: 1s restore_mode: RESTORE_DEFAULT_OFF + # Re-send the settled frame once, so a frame cut short by a late refill + # can't leave stray LEDs lit when nothing else will redraw the strip + on_state: + - script.execute: led_strip_refresh effects: - addressable_rainbow: name: "Rainbow" @@ -1040,6 +1050,12 @@ script: } out->schedule_show(); + - id: led_strip_refresh + mode: restart + then: + - delay: 1500ms + - lambda: "id(led_strip_output)->schedule_show();" + - id: led_strip_music_start then: - light.turn_on: From edfcc4048e4dc29baa26d1c313736cbb34fc60eb Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Tue, 13 Oct 2026 18:09:55 -0400 Subject: [PATCH 05/30] Clear the whole strip at boot and after turn-off LEDs past the LED Strip Count are never written, so on a strip longer than the count they kept colors latched from IO1 noise during reboots. Blank every pixel the buffers cover at boot and once the strip is off. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 66e27ec..a16dc7a 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -49,6 +49,7 @@ esphome: then: - lambda: |- id(led_strip_output)->set_num_leds((uint16_t) id(led_strip_count).state); + - script.execute: led_strip_blank_all - script.execute: id: led_strip_apply_color_order order: !lambda "return std::string(id(led_strip_color_order).current_option());" @@ -571,8 +572,7 @@ light: use_psram: false default_transition_length: 1s restore_mode: RESTORE_DEFAULT_OFF - # Re-send the settled frame once, so a frame cut short by a late refill - # can't leave stray LEDs lit when nothing else will redraw the strip + # Re-send the settled frame once, and clear the whole strip after turn-off on_state: - script.execute: led_strip_refresh effects: @@ -1054,7 +1054,26 @@ script: mode: restart then: - delay: 1500ms - - lambda: "id(led_strip_output)->schedule_show();" + - if: + condition: + light.is_off: led_strip + then: + - script.execute: led_strip_blank_all + else: + - lambda: "id(led_strip_output)->schedule_show();" + + - id: led_strip_blank_all + then: + - lambda: |- + // Clear every pixel the buffers cover, so LEDs past the LED Strip Count + // (never written otherwise) can't keep colors latched from IO1 noise + // during a reboot or an earlier, longer count + auto *out = id(led_strip_output); + const uint16_t count = out->size(); + out->set_num_leds(${LED_STRIP_MAX_LEDS}); + for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; + out->write_state(id(led_strip)); + out->set_num_leds(count); - id: led_strip_music_start then: From 6938926d32530ae36033fbe1f70eae42649c4c7d Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Tue, 13 Oct 2026 18:26:10 -0400 Subject: [PATCH 06/30] Add CAST-1 product photo to the README Co-Authored-By: Claude Opus 5.5 --- CAST_Card.jpg | Bin 0 -> 422436 bytes README.md | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 CAST_Card.jpg diff --git a/CAST_Card.jpg b/CAST_Card.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8ed5364e24a89f6745b9486a81c9a2c5104ea7a3 GIT binary patch literal 422436 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 >K(F8jWAs7Tu)0$7EREa+ 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≦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 bkM_;p7{3HkK-M>dwGGHfSwL9tzsCO?cNhnD literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 8cd99c7..9dce8ca 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Apollo CAST-1 - -![Apollo CAST-1](https://placehold.co/800x400?text=CAST-1) +Apollo CAST-1 Easily make your speakers smart and cast to multiple devices using Music Assistant and Sendspin! From b1ea4586853b38e31d79178b806a5948e1e57cc4 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Tue, 13 Oct 2026 18:32:53 -0400 Subject: [PATCH 07/30] Center the README product photo Co-Authored-By: Claude Opus 5.5 --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9dce8ca..db318ad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Apollo CAST-1 -Apollo CAST-1 +

+ Apollo CAST-1 +

Easily make your speakers smart and cast to multiple devices using Music Assistant and Sendspin! From e27ad3c302aa337014a0b6dfcb762219b3f89294 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Wed, 14 Oct 2026 07:21:39 -0400 Subject: [PATCH 08/30] Auto-assign new PRs and issues to WestwardWinds bharvey88 is no longer on the team, so every auto-assign run failed. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/autoassign.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/autoassign.yml b/.github/workflows/autoassign.yml index 03b36f5..4ab87e1 100644 --- a/.github/workflows/autoassign.yml +++ b/.github/workflows/autoassign.yml @@ -17,5 +17,5 @@ jobs: auto-assign: uses: ApolloAutomation/Workflows/.github/workflows/autoassign.yml@main with: - assignees: bharvey88 + assignees: WestwardWinds num-of-assignees: 1 From 2f9a2f91a1074dbd038630af3b57856c56494cd7 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Wed, 14 Oct 2026 10:01:15 -0400 Subject: [PATCH 09/30] Use native ESP32 options, fix WizMote log format, pin release ESPHome - Replace the ignored PlatformIO flash_mode with esp32 flash_mode: dio and the manual PSRAM sdkconfig options with execute_from_psram (identical sdkconfig and memory use; see #92) - Log the WizMote sequence as uint32 and build it from widened bytes - Pin release builds to ESPHome 2026.9.1 until a 2026.10+ build is confirmed to connect to Music Assistant over Sendspin - Bump esphome/workflows to 2026.9.0 for the beta build (from #79) and point Dependabot at beta - Bump version to 26.10.14.1 Co-Authored-By: Claude Opus 5.5 --- .github/dependabot.yml | 2 ++ .github/workflows/build-beta.yml | 7 +++++-- .github/workflows/build.yml | 5 ++++- Integrations/ESPHome/Core.yaml | 10 ++++------ Integrations/ESPHome/wizmote.yaml | 5 +++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2f8e2dd..89330b8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,6 +5,8 @@ version: 2 updates: - package-ecosystem: "github-actions" directory: "/" + # Changes reach main through beta, so updates land there first + target-branch: "beta" schedule: interval: "monthly" commit-message: diff --git a/.github/workflows/build-beta.yml b/.github/workflows/build-beta.yml index c71b8c7..b984182 100644 --- a/.github/workflows/build-beta.yml +++ b/.github/workflows/build-beta.yml @@ -44,10 +44,13 @@ jobs: matrix: include: - { yaml: Integrations/ESPHome/CAST-1.yaml, name: firmware } - uses: esphome/workflows/.github/workflows/build.yml@9f6577fd37b5cf773ab1b9be929714a0dcd15661 # 2026.7.0 + uses: esphome/workflows/.github/workflows/build.yml@cc3e76de337dc59bc1cba8da58d963cd23b873f1 # 2026.9.0 with: files: ${{ matrix.yaml }} - esphome-version: stable + # Pinned: ESPHome 2026.10's Sendspin library uses a new handshake that the + # Music Assistant server we test against rejects, so the player drops out. + # Unpin once a 2026.10+ build is confirmed to connect to Music Assistant. + esphome-version: "2026.9.1" combined-name: ${{ matrix.name }} release-version: ${{ needs.version.outputs.v }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37655f3..42081bf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,10 @@ jobs: # pattern key is everything after the last dash of the filename). firmware-names: "1:firmware" core-yaml-path: Integrations/ESPHome/Core.yaml - esphome-version: stable + # Pinned: ESPHome 2026.10's Sendspin library uses a new handshake that the + # Music Assistant server we test against rejects, so the player drops out. + # Unpin once a 2026.10+ build is confirmed to connect to Music Assistant. + esphome-version: "2026.9.1" # Bypass check if manually triggered with bypass option check-yaml-changes: ${{ !(github.event_name == 'workflow_dispatch' && github.event.inputs.bypass-yaml-check == 'true') }} publish-to-pages: true diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index a16dc7a..6e5bc90 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.10.13.2" + version: "26.10.14.1" stable_manifest_base: "https://apolloautomation.github.io/CAST-1" beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" @@ -20,8 +20,6 @@ esphome: name_add_mac_suffix: true # network: priority: (WiFi + Ethernet in one firmware) needs 2026.8 min_version: 2026.8.0 - platformio_options: - board_build.flash_mode: dio # List form so package on_boot entries (wizmote.yaml) merge on_boot: - priority: 800 @@ -237,18 +235,18 @@ esp32_improv: esp32: variant: ESP32S3 flash_size: 8MB + flash_mode: dio cpu_frequency: 240MHz framework: type: esp-idf version: recommended + advanced: + execute_from_psram: true sdkconfig_options: CONFIG_ESP32S3_DATA_CACHE_32KB: "y" CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y" CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB: "y" - CONFIG_SPIRAM_RODATA: "y" - CONFIG_SPIRAM_FETCH_INSTRUCTIONS: "y" - # Allocate BT in PSRAM so internal RAM stays free for audio CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" diff --git a/Integrations/ESPHome/wizmote.yaml b/Integrations/ESPHome/wizmote.yaml index 538b7ac..2994da1 100644 --- a/Integrations/ESPHome/wizmote.yaml +++ b/Integrations/ESPHome/wizmote.yaml @@ -464,13 +464,14 @@ espnow: // Lets ETH channel-scan lock on id(wizmote_last_packet_ms) = millis(); - uint32_t sequence = (data[4] << 24) | (data[3] << 16) | (data[2] << 8) | data[1]; + uint32_t sequence = ((uint32_t) data[4] << 24) | ((uint32_t) data[3] << 16) | + ((uint32_t) data[2] << 8) | data[1]; uint8_t button = data[6]; if (sequence == id(wizmote_last_sequence)) return; id(wizmote_last_sequence) = sequence; - ESP_LOGI("wizmote", "Button: %d seq=%d from %s", button, sequence, sender_mac.c_str()); + ESP_LOGI("wizmote", "Button: %u seq=%" PRIu32 " from %s", button, sequence, sender_mac.c_str()); id(process_wizmote_button).execute(button); esphome: From 37ab0072ccfad1689779cc2e907ef5ad681bf9b5 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Wed, 14 Oct 2026 10:26:21 -0400 Subject: [PATCH 10/30] Unpin release ESPHome and keep Dependabot on main Co-Authored-By: Claude Opus 5.5 --- .github/dependabot.yml | 2 -- .github/workflows/build-beta.yml | 5 +---- .github/workflows/build.yml | 5 +---- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 89330b8..2f8e2dd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,8 +5,6 @@ version: 2 updates: - package-ecosystem: "github-actions" directory: "/" - # Changes reach main through beta, so updates land there first - target-branch: "beta" schedule: interval: "monthly" commit-message: diff --git a/.github/workflows/build-beta.yml b/.github/workflows/build-beta.yml index b984182..e88f4b7 100644 --- a/.github/workflows/build-beta.yml +++ b/.github/workflows/build-beta.yml @@ -47,10 +47,7 @@ jobs: uses: esphome/workflows/.github/workflows/build.yml@cc3e76de337dc59bc1cba8da58d963cd23b873f1 # 2026.9.0 with: files: ${{ matrix.yaml }} - # Pinned: ESPHome 2026.10's Sendspin library uses a new handshake that the - # Music Assistant server we test against rejects, so the player drops out. - # Unpin once a 2026.10+ build is confirmed to connect to Music Assistant. - esphome-version: "2026.9.1" + esphome-version: stable combined-name: ${{ matrix.name }} release-version: ${{ needs.version.outputs.v }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 42081bf..37655f3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,10 +30,7 @@ jobs: # pattern key is everything after the last dash of the filename). firmware-names: "1:firmware" core-yaml-path: Integrations/ESPHome/Core.yaml - # Pinned: ESPHome 2026.10's Sendspin library uses a new handshake that the - # Music Assistant server we test against rejects, so the player drops out. - # Unpin once a 2026.10+ build is confirmed to connect to Music Assistant. - esphome-version: "2026.9.1" + esphome-version: stable # Bypass check if manually triggered with bypass option check-yaml-changes: ${{ !(github.event_name == 'workflow_dispatch' && github.event.inputs.bypass-yaml-check == 'true') }} publish-to-pages: true From d3cd6aa8f5be3841771f43606eaf7bc27d5830f6 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Wed, 14 Oct 2026 11:00:36 -0400 Subject: [PATCH 11/30] Restore the Voice PE flash mode and PSRAM options Keeps the config matching the Home Assistant Voice PE template, as Trevor asked. Bump version to 26.10.14.2. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 6e5bc90..ad72c04 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.10.14.1" + version: "26.10.14.2" stable_manifest_base: "https://apolloautomation.github.io/CAST-1" beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" @@ -20,6 +20,8 @@ esphome: name_add_mac_suffix: true # network: priority: (WiFi + Ethernet in one firmware) needs 2026.8 min_version: 2026.8.0 + platformio_options: + board_build.flash_mode: dio # List form so package on_boot entries (wizmote.yaml) merge on_boot: - priority: 800 @@ -235,18 +237,18 @@ esp32_improv: esp32: variant: ESP32S3 flash_size: 8MB - flash_mode: dio cpu_frequency: 240MHz framework: type: esp-idf version: recommended - advanced: - execute_from_psram: true sdkconfig_options: CONFIG_ESP32S3_DATA_CACHE_32KB: "y" CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y" CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB: "y" + CONFIG_SPIRAM_RODATA: "y" + CONFIG_SPIRAM_FETCH_INSTRUCTIONS: "y" + # Allocate BT in PSRAM so internal RAM stays free for audio CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" From 25e5d7ca2a7015389762ebc4a9abeaeac861aef1 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Wed, 14 Oct 2026 12:14:01 -0400 Subject: [PATCH 12/30] Revert auto-assign change from #96 Not ready to change auto-assign yet. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/autoassign.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/autoassign.yml b/.github/workflows/autoassign.yml index 4ab87e1..03b36f5 100644 --- a/.github/workflows/autoassign.yml +++ b/.github/workflows/autoassign.yml @@ -17,5 +17,5 @@ jobs: auto-assign: uses: ApolloAutomation/Workflows/.github/workflows/autoassign.yml@main with: - assignees: WestwardWinds + assignees: bharvey88 num-of-assignees: 1 From 603e6127f7106721101526a9db30bb6083f777e3 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Wed, 14 Oct 2026 12:24:39 -0400 Subject: [PATCH 13/30] Move LED strip code into led_strip.yaml and auto-assign to Trevor Inlines the LED strip values instead of substitutions. Bump version to 26.10.14.3. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/autoassign.yml | 2 +- Integrations/ESPHome/Core.yaml | 357 +-------------------------- Integrations/ESPHome/led_strip.yaml | 359 ++++++++++++++++++++++++++++ 3 files changed, 362 insertions(+), 356 deletions(-) create mode 100644 Integrations/ESPHome/led_strip.yaml diff --git a/.github/workflows/autoassign.yml b/.github/workflows/autoassign.yml index 03b36f5..9a84ac5 100644 --- a/.github/workflows/autoassign.yml +++ b/.github/workflows/autoassign.yml @@ -17,5 +17,5 @@ jobs: auto-assign: uses: ApolloAutomation/Workflows/.github/workflows/autoassign.yml@main with: - assignees: bharvey88 + assignees: TrevorSchirmer num-of-assignees: 1 diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index ad72c04..a34a147 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,18 +1,14 @@ substitutions: - version: "26.10.14.2" + version: "26.10.14.3" stable_manifest_base: "https://apolloautomation.github.io/CAST-1" beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" beta_manifest_file: "manifest.json" - # LED strip on the exposed 5V / GND / IO1 header - LED_STRIP_PIN: GPIO1 - # Buffers are sized for this many LEDs; the LED Strip Count entity picks how many are driven - LED_STRIP_MAX_LEDS: "300" - LED_STRIP_DEFAULT_LEDS: "30" packages: wizmote: !include wizmote.yaml + led_strip: !include led_strip.yaml esphome: friendly_name: Apollo CAST-1 @@ -43,22 +39,6 @@ esphome: - lambda: |- id(wifi_1).set_enable_on_boot(false); id(espnow_component).set_wifi_channel(1); - # Apply the saved LED strip settings before the light's first write - # Must run after the strip and the restored entities set up (800) - - priority: 600 - then: - - lambda: |- - id(led_strip_output)->set_num_leds((uint16_t) id(led_strip_count).state); - - script.execute: led_strip_blank_all - - script.execute: - id: led_strip_apply_color_order - order: !lambda "return std::string(id(led_strip_color_order).current_option());" - - script.execute: - id: led_strip_apply_chipset - chipset: !lambda "return std::string(id(led_strip_chipset).current_option());" - - script.execute: - id: led_strip_apply_max_brightness - percent: !lambda "return id(led_strip_max_brightness).state;" # Park the W5500 helper task when no HAT is present, so it stops polling a # floating SPI bus and panicking the device every ~100s # Must run after ethernet setup (250) @@ -347,17 +327,6 @@ button: - delay: 5s - lambda: id(update_http_request).perform(true); - # Steps the strip through red, green, blue, white, then a rainbow so a bad - # channel, wrong color order, or dead pixel shows up at a glance - - platform: template - id: led_strip_test_button - name: "LED Strip Test" - disabled_by_default: true - icon: mdi:led-strip-variant - entity_category: diagnostic - on_press: - - script.execute: led_strip_test - binary_sensor: - platform: status name: Online @@ -391,30 +360,6 @@ binary_sensor: id(testScript).execute(); } - - platform: template - id: led_strip_music_playing - internal: true - # Sendspin's player and the HTTP source report stop at once; the main - # player only goes idle ~10s later, once its buffers drain - lambda: |- - return id(sendspin_group_media_player).state == media_player::MEDIA_PLAYER_STATE_PLAYING || - id(http_media_source)->get_state() == media_source::MediaSourceState::PLAYING; - filters: - # Bridge track changes and rebuffering so the strip doesn't blink off - - delayed_off: 3s - on_press: - - if: - condition: - switch.is_on: led_strip_music_mode - then: - - script.execute: led_strip_music_start - on_release: - - if: - condition: - switch.is_on: led_strip_music_mode - then: - - light.turn_off: led_strip - sensor: - platform: internal_temperature name: "ESP Temperature" @@ -449,28 +394,6 @@ switch: on_turn_off: - esp32_ble_tracker.stop_scan: - # Music Mode: the strip turns on with the Music Effect while audio plays and - # off once playback has stopped for 10s - - platform: template - id: led_strip_music_mode - name: "LED Strip Music Mode" - disabled_by_default: true - icon: mdi:music-note - optimistic: true - restore_mode: RESTORE_DEFAULT_OFF - on_turn_on: - - if: - condition: - binary_sensor.is_on: led_strip_music_playing - then: - - script.execute: led_strip_music_start - on_turn_off: - - if: - condition: - binary_sensor.is_on: led_strip_music_playing - then: - - light.turn_off: led_strip - text_sensor: # Which path is carrying the device, for troubleshooting and HA notifications - platform: template @@ -554,47 +477,6 @@ light: min_brightness: 50% max_brightness: 100% - - platform: esp32_rmt_led_strip - id: led_strip - output_id: led_strip_output - name: "LED Strip" - disabled_by_default: true - icon: mdi:led-strip-variant - pin: ${LED_STRIP_PIN} - # Timings and color order are swapped at runtime by the select entities - chipset: WS2812 - channel_colors: GRB - num_leds: ${LED_STRIP_MAX_LEDS} - # The rest of the RMT TX memory after the onboard light's 48 - rmt_symbols: 144 - # The RMT interrupt refills from these buffers mid-frame; PSRAM reads can - # stall it under audio load and cut the frame short - use_psram: false - default_transition_length: 1s - restore_mode: RESTORE_DEFAULT_OFF - # Re-send the settled frame once, and clear the whole strip after turn-off - on_state: - - script.execute: led_strip_refresh - effects: - - addressable_rainbow: - name: "Rainbow" - - addressable_color_wipe: - name: "Color Wipe" - - addressable_scan: - name: "Scan" - - addressable_twinkle: - name: "Twinkle" - - addressable_random_twinkle: - name: "Random Twinkle" - - addressable_fireworks: - name: "Fireworks" - - addressable_flicker: - name: "Flicker" - - pulse: - name: "Pulse" - - strobe: - name: "Strobe" - select: - platform: template id: firmware_channel @@ -611,105 +493,6 @@ select: then: - script.execute: apply_ota_source - - platform: template - id: led_strip_color_order - name: "LED Strip Color Order" - disabled_by_default: true - icon: mdi:palette - entity_category: config - optimistic: true - restore_value: true - options: - - "GRB" - - "RGB" - - "BRG" - - "RBG" - - "GBR" - - "BGR" - initial_option: "GRB" - set_action: - - script.execute: - id: led_strip_apply_color_order - order: !lambda "return std::string(x);" - - - platform: template - id: led_strip_chipset - name: "LED Strip Chipset" - disabled_by_default: true - icon: mdi:chip - entity_category: config - optimistic: true - restore_value: true - options: - - "WS2812" - - "SK6812" - - "WS2811" - - "APA106" - - "SM16703" - initial_option: "WS2812" - set_action: - - script.execute: - id: led_strip_apply_chipset - chipset: !lambda "return std::string(x);" - - - platform: template - id: led_strip_music_effect - name: "LED Strip Music Effect" - disabled_by_default: true - icon: mdi:music-circle - entity_category: config - optimistic: true - restore_value: true - options: - - "Rainbow" - - "Color Wipe" - - "Scan" - - "Twinkle" - - "Random Twinkle" - - "Fireworks" - - "Flicker" - - "Pulse" - initial_option: "Rainbow" - -number: - - platform: template - id: led_strip_count - name: "LED Strip Count" - disabled_by_default: true - icon: mdi:counter - entity_category: config - mode: box - min_value: 1 - max_value: ${LED_STRIP_MAX_LEDS} - step: 1 - optimistic: true - restore_value: true - initial_value: ${LED_STRIP_DEFAULT_LEDS} - set_action: - - script.execute: - id: led_strip_apply_count - count: !lambda "return (int) x;" - - # Caps every channel so a long strip can't overdraw the header's 5V rail - - platform: template - id: led_strip_max_brightness - name: "LED Strip Max Brightness" - disabled_by_default: true - icon: mdi:brightness-percent - entity_category: config - unit_of_measurement: "%" - mode: slider - min_value: 10 - max_value: 100 - step: 5 - optimistic: true - restore_value: true - initial_value: 50 - set_action: - - script.execute: - id: led_strip_apply_max_brightness - percent: !lambda "return x;" - audio_dac: - platform: pcm5122 id: external_dac @@ -991,139 +774,3 @@ script: blue: 0% - light.turn_off: id: rgb_light - - - id: led_strip_apply_count - mode: queued - parameters: - count: int - then: - - lambda: |- - auto *out = id(led_strip_output); - // Blank every pixel the buffers cover, so LEDs past a lowered count go dark - out->set_num_leds(${LED_STRIP_MAX_LEDS}); - for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; - out->write_state(id(led_strip)); - out->set_num_leds((uint16_t) count); - out->clear_effect_data(); - // Repaint the current color at the new length (effects repaint themselves) - out->update_state(id(led_strip)); - ESP_LOGI("led_strip", "Driving %d LEDs", count); - - - id: led_strip_apply_max_brightness - parameters: - percent: float - then: - - lambda: |- - const float scale = percent / 100.0f; - id(led_strip_output)->set_correction(scale, scale, scale); - id(led_strip_output)->update_state(id(led_strip)); - - - id: led_strip_apply_color_order - parameters: - order: string - then: - - lambda: |- - // Each letter's position is that color's byte offset on the wire; - // all options are 3-byte, so the allocated buffers still fit - id(led_strip_output)->set_channel_colors(light::ChannelColors{ - (uint8_t) order.find('R'), (uint8_t) order.find('G'), (uint8_t) order.find('B'), - light::ChannelColors::NO_WHITE}); - id(led_strip_output)->update_state(id(led_strip)); - - - id: led_strip_apply_chipset - parameters: - chipset: string - then: - - lambda: |- - // Bit timings in ns, matching ESPHome's esp32_rmt_led_strip chipset table - auto *out = id(led_strip_output); - if (chipset == "SK6812") { - out->set_led_params(300, 900, 600, 600, 0, 0); - } else if (chipset == "WS2811") { - out->set_led_params(300, 1090, 1090, 320, 0, 300000); - } else if (chipset == "APA106") { - out->set_led_params(350, 1360, 1360, 350, 0, 0); - } else if (chipset == "SM16703") { - out->set_led_params(300, 900, 900, 300, 0, 0); - } else { - out->set_led_params(400, 1000, 1000, 400, 0, 0); - } - out->schedule_show(); - - - id: led_strip_refresh - mode: restart - then: - - delay: 1500ms - - if: - condition: - light.is_off: led_strip - then: - - script.execute: led_strip_blank_all - else: - - lambda: "id(led_strip_output)->schedule_show();" - - - id: led_strip_blank_all - then: - - lambda: |- - // Clear every pixel the buffers cover, so LEDs past the LED Strip Count - // (never written otherwise) can't keep colors latched from IO1 noise - // during a reboot or an earlier, longer count - auto *out = id(led_strip_output); - const uint16_t count = out->size(); - out->set_num_leds(${LED_STRIP_MAX_LEDS}); - for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; - out->write_state(id(led_strip)); - out->set_num_leds(count); - - - id: led_strip_music_start - then: - - light.turn_on: - id: led_strip - effect: !lambda "return std::string(id(led_strip_music_effect).current_option());" - - - id: led_strip_test - mode: restart - then: - - logger.log: "LED strip test: red" - - light.control: - id: led_strip - effect: none - - light.turn_on: - id: led_strip - transition_length: 0s - brightness: 100% - red: 100% - green: 0% - blue: 0% - - delay: 2s - - logger.log: "LED strip test: green" - - light.turn_on: - id: led_strip - transition_length: 0s - red: 0% - green: 100% - blue: 0% - - delay: 2s - - logger.log: "LED strip test: blue" - - light.turn_on: - id: led_strip - transition_length: 0s - red: 0% - green: 0% - blue: 100% - - delay: 2s - - logger.log: "LED strip test: white" - - light.turn_on: - id: led_strip - transition_length: 0s - red: 100% - green: 100% - blue: 100% - - delay: 2s - - logger.log: "LED strip test: rainbow" - - light.turn_on: - id: led_strip - effect: "Rainbow" - - delay: 5s - - light.turn_off: led_strip - - logger.log: "LED strip test: done" diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml new file mode 100644 index 0000000..4ca66f6 --- /dev/null +++ b/Integrations/ESPHome/led_strip.yaml @@ -0,0 +1,359 @@ +# LED strip on the exposed 5V / GND / IO1 header; included by Core.yaml + +esphome: + on_boot: + # Apply the saved LED strip settings before the light's first write + # Must run after the strip and the restored entities set up (800) + - priority: 600 + then: + - lambda: |- + id(led_strip_output)->set_num_leds((uint16_t) id(led_strip_count).state); + - script.execute: led_strip_blank_all + - script.execute: + id: led_strip_apply_color_order + order: !lambda "return std::string(id(led_strip_color_order).current_option());" + - script.execute: + id: led_strip_apply_chipset + chipset: !lambda "return std::string(id(led_strip_chipset).current_option());" + - script.execute: + id: led_strip_apply_max_brightness + percent: !lambda "return id(led_strip_max_brightness).state;" + +light: + - platform: esp32_rmt_led_strip + id: led_strip + output_id: led_strip_output + name: "LED Strip" + disabled_by_default: true + icon: mdi:led-strip-variant + pin: GPIO1 + # Timings and color order are swapped at runtime by the select entities + chipset: WS2812 + channel_colors: GRB + num_leds: 300 + # The rest of the RMT TX memory after the onboard light's 48 + rmt_symbols: 144 + # The RMT interrupt refills from these buffers mid-frame; PSRAM reads can + # stall it under audio load and cut the frame short + use_psram: false + default_transition_length: 1s + restore_mode: RESTORE_DEFAULT_OFF + # Re-send the settled frame once, and clear the whole strip after turn-off + on_state: + - script.execute: led_strip_refresh + effects: + - addressable_rainbow: + name: "Rainbow" + - addressable_color_wipe: + name: "Color Wipe" + - addressable_scan: + name: "Scan" + - addressable_twinkle: + name: "Twinkle" + - addressable_random_twinkle: + name: "Random Twinkle" + - addressable_fireworks: + name: "Fireworks" + - addressable_flicker: + name: "Flicker" + - pulse: + name: "Pulse" + - strobe: + name: "Strobe" + +number: + - platform: template + id: led_strip_count + name: "LED Strip Count" + disabled_by_default: true + icon: mdi:counter + entity_category: config + mode: box + min_value: 1 + max_value: 300 + step: 1 + optimistic: true + restore_value: true + initial_value: 30 + set_action: + - script.execute: + id: led_strip_apply_count + count: !lambda "return (int) x;" + + # Caps every channel so a long strip can't overdraw the header's 5V rail + - platform: template + id: led_strip_max_brightness + name: "LED Strip Max Brightness" + disabled_by_default: true + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + mode: slider + min_value: 10 + max_value: 100 + step: 5 + optimistic: true + restore_value: true + initial_value: 50 + set_action: + - script.execute: + id: led_strip_apply_max_brightness + percent: !lambda "return x;" + +select: + - platform: template + id: led_strip_color_order + name: "LED Strip Color Order" + disabled_by_default: true + icon: mdi:palette + entity_category: config + optimistic: true + restore_value: true + options: + - "GRB" + - "RGB" + - "BRG" + - "RBG" + - "GBR" + - "BGR" + initial_option: "GRB" + set_action: + - script.execute: + id: led_strip_apply_color_order + order: !lambda "return std::string(x);" + + - platform: template + id: led_strip_chipset + name: "LED Strip Chipset" + disabled_by_default: true + icon: mdi:chip + entity_category: config + optimistic: true + restore_value: true + options: + - "WS2812" + - "SK6812" + - "WS2811" + - "APA106" + - "SM16703" + initial_option: "WS2812" + set_action: + - script.execute: + id: led_strip_apply_chipset + chipset: !lambda "return std::string(x);" + + - platform: template + id: led_strip_music_effect + name: "LED Strip Music Effect" + disabled_by_default: true + icon: mdi:music-circle + entity_category: config + optimistic: true + restore_value: true + options: + - "Rainbow" + - "Color Wipe" + - "Scan" + - "Twinkle" + - "Random Twinkle" + - "Fireworks" + - "Flicker" + - "Pulse" + initial_option: "Rainbow" + +switch: + # Music Mode: the strip turns on with the Music Effect while audio plays and + # off once playback has stopped for 10s + - platform: template + id: led_strip_music_mode + name: "LED Strip Music Mode" + disabled_by_default: true + icon: mdi:music-note + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF + on_turn_on: + - if: + condition: + binary_sensor.is_on: led_strip_music_playing + then: + - script.execute: led_strip_music_start + on_turn_off: + - if: + condition: + binary_sensor.is_on: led_strip_music_playing + then: + - light.turn_off: led_strip + +binary_sensor: + - platform: template + id: led_strip_music_playing + internal: true + # Sendspin's player and the HTTP source report stop at once; the main + # player only goes idle ~10s later, once its buffers drain + lambda: |- + return id(sendspin_group_media_player).state == media_player::MEDIA_PLAYER_STATE_PLAYING || + id(http_media_source)->get_state() == media_source::MediaSourceState::PLAYING; + filters: + # Bridge track changes and rebuffering so the strip doesn't blink off + - delayed_off: 3s + on_press: + - if: + condition: + switch.is_on: led_strip_music_mode + then: + - script.execute: led_strip_music_start + on_release: + - if: + condition: + switch.is_on: led_strip_music_mode + then: + - light.turn_off: led_strip + +button: + # Steps the strip through red, green, blue, white, then a rainbow so a bad + # channel, wrong color order, or dead pixel shows up at a glance + - platform: template + id: led_strip_test_button + name: "LED Strip Test" + disabled_by_default: true + icon: mdi:led-strip-variant + entity_category: diagnostic + on_press: + - script.execute: led_strip_test + +script: + - id: led_strip_apply_count + mode: queued + parameters: + count: int + then: + - lambda: |- + auto *out = id(led_strip_output); + // Blank every pixel the buffers cover, so LEDs past a lowered count go dark + out->set_num_leds(300); + for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; + out->write_state(id(led_strip)); + out->set_num_leds((uint16_t) count); + out->clear_effect_data(); + // Repaint the current color at the new length (effects repaint themselves) + out->update_state(id(led_strip)); + ESP_LOGI("led_strip", "Driving %d LEDs", count); + + - id: led_strip_apply_max_brightness + parameters: + percent: float + then: + - lambda: |- + const float scale = percent / 100.0f; + id(led_strip_output)->set_correction(scale, scale, scale); + id(led_strip_output)->update_state(id(led_strip)); + + - id: led_strip_apply_color_order + parameters: + order: string + then: + - lambda: |- + // Each letter's position is that color's byte offset on the wire; + // all options are 3-byte, so the allocated buffers still fit + id(led_strip_output)->set_channel_colors(light::ChannelColors{ + (uint8_t) order.find('R'), (uint8_t) order.find('G'), (uint8_t) order.find('B'), + light::ChannelColors::NO_WHITE}); + id(led_strip_output)->update_state(id(led_strip)); + + - id: led_strip_apply_chipset + parameters: + chipset: string + then: + - lambda: |- + // Bit timings in ns, matching ESPHome's esp32_rmt_led_strip chipset table + auto *out = id(led_strip_output); + if (chipset == "SK6812") { + out->set_led_params(300, 900, 600, 600, 0, 0); + } else if (chipset == "WS2811") { + out->set_led_params(300, 1090, 1090, 320, 0, 300000); + } else if (chipset == "APA106") { + out->set_led_params(350, 1360, 1360, 350, 0, 0); + } else if (chipset == "SM16703") { + out->set_led_params(300, 900, 900, 300, 0, 0); + } else { + out->set_led_params(400, 1000, 1000, 400, 0, 0); + } + out->schedule_show(); + + - id: led_strip_refresh + mode: restart + then: + - delay: 1500ms + - if: + condition: + light.is_off: led_strip + then: + - script.execute: led_strip_blank_all + else: + - lambda: "id(led_strip_output)->schedule_show();" + + - id: led_strip_blank_all + then: + - lambda: |- + // Clear every pixel the buffers cover, so LEDs past the LED Strip Count + // (never written otherwise) can't keep colors latched from IO1 noise + // during a reboot or an earlier, longer count + auto *out = id(led_strip_output); + const uint16_t count = out->size(); + out->set_num_leds(300); + for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; + out->write_state(id(led_strip)); + out->set_num_leds(count); + + - id: led_strip_music_start + then: + - light.turn_on: + id: led_strip + effect: !lambda "return std::string(id(led_strip_music_effect).current_option());" + + - id: led_strip_test + mode: restart + then: + - logger.log: "LED strip test: red" + - light.control: + id: led_strip + effect: none + - light.turn_on: + id: led_strip + transition_length: 0s + brightness: 100% + red: 100% + green: 0% + blue: 0% + - delay: 2s + - logger.log: "LED strip test: green" + - light.turn_on: + id: led_strip + transition_length: 0s + red: 0% + green: 100% + blue: 0% + - delay: 2s + - logger.log: "LED strip test: blue" + - light.turn_on: + id: led_strip + transition_length: 0s + red: 0% + green: 0% + blue: 100% + - delay: 2s + - logger.log: "LED strip test: white" + - light.turn_on: + id: led_strip + transition_length: 0s + red: 100% + green: 100% + blue: 100% + - delay: 2s + - logger.log: "LED strip test: rainbow" + - light.turn_on: + id: led_strip + effect: "Rainbow" + - delay: 5s + - light.turn_off: led_strip + - logger.log: "LED strip test: done" From c9343bf39a123d9fc5f68eba78feddaa9127559c Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Fri, 16 Oct 2026 19:09:44 -0400 Subject: [PATCH 14/30] Use the AUTO_ASSIGNEE org variable for auto-assign Matches main (#102), so new PRs go to WestwardWinds instead of a hard-coded TrevorSchirmer. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/autoassign.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/autoassign.yml b/.github/workflows/autoassign.yml index 9a84ac5..270236f 100644 --- a/.github/workflows/autoassign.yml +++ b/.github/workflows/autoassign.yml @@ -1,8 +1,8 @@ name: Auto Assign - -# pull_request_target (not pull_request) so auto-assign works on -# fork-submitted PRs; fork pull_request runs only get a read-only token. +# pull_request_target (not pull_request) so assignment works on +# fork-submitted PRs; fork pull_request runs get a read-only token. # Safe because this workflow never checks out or executes PR code. +# The assignee comes from the AUTO_ASSIGNEE organization variable. on: issues: types: [opened] @@ -16,6 +16,3 @@ permissions: jobs: auto-assign: uses: ApolloAutomation/Workflows/.github/workflows/autoassign.yml@main - with: - assignees: TrevorSchirmer - num-of-assignees: 1 From cc05286f8e9a283becd446dbbbbffdecf1645e32 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Sun, 25 Oct 2026 12:26:52 -0400 Subject: [PATCH 15/30] Build on ESPHome 2026.10 and rename esp32_improv to improv_ble Requires ESPHome 2026.10.0. Bump version to 26.10.25.1. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index a34a147..be19e5d 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.10.14.3" + version: "26.10.25.1" stable_manifest_base: "https://apolloautomation.github.io/CAST-1" beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" @@ -14,8 +14,8 @@ esphome: friendly_name: Apollo CAST-1 comment: Apollo CAST-1 name_add_mac_suffix: true - # network: priority: (WiFi + Ethernet in one firmware) needs 2026.8 - min_version: 2026.8.0 + # improv_ble (renamed from esp32_improv) needs 2026.10 + min_version: 2026.10.0 platformio_options: board_build.flash_mode: dio # List form so package on_boot entries (wizmote.yaml) merge @@ -210,8 +210,8 @@ captive_portal: improv_serial: id: improv_serial_1 -esp32_improv: - id: esp32_improv_1 +improv_ble: + id: improv_ble_1 authorizer: none esp32: From 595d0e97f35d81b7dc721e8dfe31073858d3cad6 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Sun, 25 Oct 2026 14:03:44 -0400 Subject: [PATCH 16/30] Unmute before WizMote Volume Up ESPHome 2026.10 no longer clears mute when the volume changes, so a muted CAST-1 stayed silent when Volume Up was pressed on the WizMote. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/wizmote.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Integrations/ESPHome/wizmote.yaml b/Integrations/ESPHome/wizmote.yaml index 2994da1..c5e2122 100644 --- a/Integrations/ESPHome/wizmote.yaml +++ b/Integrations/ESPHome/wizmote.yaml @@ -268,6 +268,8 @@ script: condition: lambda: 'return action == "Volume Up";' then: + # Volume no longer clears mute on its own (ESPHome 2026.10) + - media_player.unmute: external_media_player - media_player.volume_up: external_media_player - logger.log: tag: wizmote From 362b6622b129e38552342544834384b84e2a9068 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Tue, 27 Oct 2026 15:21:00 -0400 Subject: [PATCH 17/30] led support initial testing of LED changes --- Integrations/ESPHome/led_strip.yaml | 395 +++++++++++++++++++++++++++- README.md | 16 ++ 2 files changed, 403 insertions(+), 8 deletions(-) diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml index 4ca66f6..9fcc620 100644 --- a/Integrations/ESPHome/led_strip.yaml +++ b/Integrations/ESPHome/led_strip.yaml @@ -19,13 +19,22 @@ esphome: id: led_strip_apply_max_brightness percent: !lambda "return id(led_strip_max_brightness).state;" +# Every LED strip entity sits under one header on the device's web page +web_server: + sorting_groups: + - id: sg_led_strip + name: "External LED Strip" + sorting_weight: 10 + light: - platform: esp32_rmt_led_strip id: led_strip output_id: led_strip_output name: "LED Strip" - disabled_by_default: true icon: mdi:led-strip-variant + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 1 pin: GPIO1 # Timings and color order are swapped at runtime by the select entities chipset: WS2812 @@ -41,6 +50,7 @@ light: # Re-send the settled frame once, and clear the whole strip after turn-off on_state: - script.execute: led_strip_refresh + # New effects go at the end: the light restores its effect by position effects: - addressable_rainbow: name: "Rainbow" @@ -61,13 +71,110 @@ light: - strobe: name: "Strobe" + # Effect A and Effect B run the pattern their Pattern select picks, at + # their own Speed and Intensity, on the segments whose switch is on + - addressable_lambda: + name: "Effect A" + # About one frame per main-loop pass (~16 ms); the lambda keeps its + # own clock, so this only caps how often the strip is re-sent + update_interval: 15ms + lambda: &led_strip_slot_effect |- + // Effect A and Effect B share this body; each copy keeps its own statics + static float level[8]; + static float target[8]; + static uint32_t next_ms = 0; + static uint32_t cycle_start = 0; + const uint32_t now = millis(); + + const bool slot_b = strcmp(id(led_strip).get_effect_name().c_str(), "Effect B") == 0; + auto *pattern = slot_b ? id(led_strip_effect_b_pattern) : id(led_strip_effect_a_pattern); + const float speed = clamp(slot_b ? id(led_strip_effect_b_speed).state + : id(led_strip_effect_a_speed).state, 1.0f, 100.0f); + const float intensity = clamp((slot_b ? id(led_strip_effect_b_intensity).state + : id(led_strip_effect_a_intensity).state) / 100.0f, 0.0f, 1.0f); + // Speed 1-100 on a log curve: 1 = 1000 ms, 50 = 176 ms, 100 = 30 ms + const uint32_t period = (uint32_t) (1000.0f * powf(0.03f, (speed - 1.0f) / 99.0f)); + + if (initial_run) { + for (auto &l : level) l = 1.0f; + for (auto &t : target) t = 1.0f; + next_ms = now; + cycle_start = now; + } + + // Split the strip into segments; the last one takes the leftover LEDs + const int32_t n = it.size(); + if (n <= 0) return; + const int32_t segs = std::max(1, std::min((int32_t) id(led_strip_segments).state, + std::min(8, n))); + const int32_t base = n / segs; + const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, + id(led_strip_segment_3).state, id(led_strip_segment_4).state, + id(led_strip_segment_5).state, id(led_strip_segment_6).state, + id(led_strip_segment_7).state, id(led_strip_segment_8).state}; + + if (pattern->active_index().value_or(0) == 1) { + // Strobe: one flash every 2 x period, lit for the Intensity share of it + const uint32_t cycle = period * 2; + if (now - cycle_start >= cycle) cycle_start = now - (now - cycle_start) % cycle; + const uint32_t on_ms = (uint32_t) (cycle * clamp(intensity, 0.05f, 0.95f)); + const Color c = (now - cycle_start) < on_ms ? current_color : Color::BLACK; + for (int32_t s = 0; s < segs; s++) { + const int32_t from = s * base; + const int32_t to = (s == segs - 1) ? n : from + base; + it.range(from, to) = seg_on[s] ? c : Color::BLACK; + } + } else { + // Flicker: every period each segment picks a new random level, no + // lower than 1 - Intensity, and eases toward it within a few frames + const int32_t late = (int32_t) (now - next_ms); + // A raised Speed pulls in a change that was scheduled further out + if (late >= 0 || -late > (int32_t) period) { + for (int32_t s = 0; s < segs; s++) target[s] = 1.0f - intensity * random_float(); + next_ms = (late >= 0 && late < (int32_t) period) ? next_ms + period : now + period; + } + for (int32_t s = 0; s < segs; s++) { + level[s] += (target[s] - level[s]) * 0.6f; + const int32_t from = s * base; + const int32_t to = (s == segs - 1) ? n : from + base; + it.range(from, to) = seg_on[s] ? current_color * (uint8_t) (level[s] * 255.0f) : Color::BLACK; + } + } + - addressable_lambda: + name: "Effect B" + update_interval: 15ms + lambda: *led_strip_slot_effect + + # Solid color on each segment whose switch is on; a plain color paints + # every LED, so the segment switches move the strip onto this effect + - addressable_lambda: + name: "Segments" + update_interval: 50ms + lambda: |- + const int32_t n = it.size(); + if (n <= 0) return; + const int32_t segs = std::max(1, std::min((int32_t) id(led_strip_segments).state, + std::min(8, n))); + const int32_t base = n / segs; + const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, + id(led_strip_segment_3).state, id(led_strip_segment_4).state, + id(led_strip_segment_5).state, id(led_strip_segment_6).state, + id(led_strip_segment_7).state, id(led_strip_segment_8).state}; + for (int32_t s = 0; s < segs; s++) { + const int32_t from = s * base; + const int32_t to = (s == segs - 1) ? n : from + base; + it.range(from, to) = seg_on[s] ? current_color : Color::BLACK; + } + number: - platform: template id: led_strip_count name: "LED Strip Count" - disabled_by_default: true icon: mdi:counter entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 20 mode: box min_value: 1 max_value: 300 @@ -84,9 +191,11 @@ number: - platform: template id: led_strip_max_brightness name: "LED Strip Max Brightness" - disabled_by_default: true icon: mdi:brightness-percent entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 21 unit_of_measurement: "%" mode: slider min_value: 10 @@ -100,13 +209,104 @@ number: id: led_strip_apply_max_brightness percent: !lambda "return x;" + # How many equal segments the strip splits into; Segment switches past this + # count do nothing + - platform: template + id: led_strip_segments + name: "LED Strip Segments" + icon: mdi:view-split-vertical + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 2 + mode: box + min_value: 1 + max_value: 8 + step: 1 + optimistic: true + restore_value: true + initial_value: 1 + on_value: + - script.execute: led_strip_segments_changed + + # Speed 1-100 maps on a log curve from 1 s (1) to 30 ms (100) between changes + - platform: template + id: led_strip_effect_a_speed + name: "LED Strip Effect A Speed" + icon: mdi:speedometer + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 12 + mode: slider + min_value: 1 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 50 + + # Flicker: how far a segment can dip (0 = steady); Strobe: share of each + # flash the strip is lit + - platform: template + id: led_strip_effect_a_intensity + name: "LED Strip Effect A Intensity" + icon: mdi:tune-vertical + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 13 + unit_of_measurement: "%" + mode: slider + min_value: 0 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 70 + + - platform: template + id: led_strip_effect_b_speed + name: "LED Strip Effect B Speed" + icon: mdi:speedometer + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 15 + mode: slider + min_value: 1 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 80 + + - platform: template + id: led_strip_effect_b_intensity + name: "LED Strip Effect B Intensity" + icon: mdi:tune-vertical + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 16 + unit_of_measurement: "%" + mode: slider + min_value: 0 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 50 + select: - platform: template id: led_strip_color_order name: "LED Strip Color Order" - disabled_by_default: true icon: mdi:palette entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 22 optimistic: true restore_value: true options: @@ -125,9 +325,11 @@ select: - platform: template id: led_strip_chipset name: "LED Strip Chipset" - disabled_by_default: true icon: mdi:chip entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 23 optimistic: true restore_value: true options: @@ -145,9 +347,11 @@ select: - platform: template id: led_strip_music_effect name: "LED Strip Music Effect" - disabled_by_default: true icon: mdi:music-circle entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 24 optimistic: true restore_value: true options: @@ -161,14 +365,48 @@ select: - "Pulse" initial_option: "Rainbow" + # Patterns for the Effect A / Effect B slots; the slot effect picks the + # pattern by position, so new patterns go at the end + - platform: template + id: led_strip_effect_a_pattern + name: "LED Strip Effect A Pattern" + icon: mdi:animation-play + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 11 + optimistic: true + restore_value: true + options: + - "Flicker" + - "Strobe" + initial_option: "Flicker" + + - platform: template + id: led_strip_effect_b_pattern + name: "LED Strip Effect B Pattern" + icon: mdi:animation-play + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 14 + optimistic: true + restore_value: true + options: + - "Flicker" + - "Strobe" + initial_option: "Strobe" + switch: # Music Mode: the strip turns on with the Music Effect while audio plays and # off once playback has stopped for 10s - platform: template id: led_strip_music_mode name: "LED Strip Music Mode" - disabled_by_default: true icon: mdi:music-note + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 25 optimistic: true restore_mode: RESTORE_DEFAULT_OFF on_turn_on: @@ -184,6 +422,120 @@ switch: then: - light.turn_off: led_strip + # Segment switches: Effect A, Effect B and Segments leave a segment dark + # while its switch is off + - platform: template + id: led_strip_segment_1 + name: "LED Strip Segment 1" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 3 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_2 + name: "LED Strip Segment 2" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 4 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_3 + name: "LED Strip Segment 3" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 5 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_4 + name: "LED Strip Segment 4" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 6 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_5 + name: "LED Strip Segment 5" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 7 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_6 + name: "LED Strip Segment 6" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 8 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_7 + name: "LED Strip Segment 7" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 9 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_8 + name: "LED Strip Segment 8" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 10 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + binary_sensor: - platform: template id: led_strip_music_playing @@ -215,9 +567,11 @@ button: - platform: template id: led_strip_test_button name: "LED Strip Test" - disabled_by_default: true icon: mdi:led-strip-variant entity_category: diagnostic + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 30 on_press: - script.execute: led_strip_test @@ -305,6 +659,31 @@ script: out->write_state(id(led_strip)); out->set_num_leds(count); + # A plain color paints every LED, so when a segment is switched off while the + # strip shows one, move the strip onto the Segments effect to mask it + - id: led_strip_segments_changed + mode: queued + then: + - if: + condition: + and: + - light.is_on: led_strip + - lambda: |- + if (strcmp(id(led_strip).get_effect_name().c_str(), "None") != 0) return false; + const int32_t segs = std::min((int32_t) id(led_strip_segments).state, 8); + const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, + id(led_strip_segment_3).state, id(led_strip_segment_4).state, + id(led_strip_segment_5).state, id(led_strip_segment_6).state, + id(led_strip_segment_7).state, id(led_strip_segment_8).state}; + for (int32_t s = 0; s < segs; s++) { + if (!seg_on[s]) return true; + } + return false; + then: + - light.turn_on: + id: led_strip + effect: "Segments" + - id: led_strip_music_start then: - light.turn_on: diff --git a/README.md b/README.md index db318ad..6dcdd3c 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,22 @@ Configure every button without leaving Home Assistant using the [CAST-1 WizMote [![Import Blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FBlueprints%2Fblob%2Fmain%2FCAST-1%2FCAST-1-WizMote.yaml) +## External LED Strip + +The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). Every setting lives in Home Assistant and under **External LED Strip** on the device's web page — no YAML edits needed. + +- **LED Strip Count** and **LED Strip Segments** set how many LEDs you have and how many equal segments they split into (1–8). Leftover LEDs go to the last segment, so 22 LEDs in 3 segments are 7 / 7 / 8. +- **LED Strip Segment 1–8** switch each segment on or off. Switches past the Segments count do nothing. +- **Effect A** and **Effect B** are two effect slots on the LED Strip light. Each has a **Pattern** (Flicker or Strobe), a **Speed** (1 = one change per second, 100 = one every 30 ms, on a log curve) and an **Intensity** (Flicker: how deep it dips; Strobe: how much of each flash is lit). Changes apply live while the effect runs. +- The **Segments** effect shows a solid color on the segments that are on. Switching a segment off while the strip shows a plain color moves it onto this effect automatically. + +In automations, set the pattern, speed and segments with `select.select_option`, `number.set_value` and `switch.turn_on` / `switch.turn_off`, then call `light.turn_on` with `effect: "Effect A"` (add `transition: 0` for an instant start). + +> [!WARNING] +> **Photosensitivity:** Strobe flashes faster than 3 times per second from about Speed 50 up, and reaches about 16 flashes per second at Speed 100. Flashing in this range can trigger seizures in people with photosensitive epilepsy. + +Power long strips from their own 5V supply with a shared ground; the header can't supply a full-brightness strip, and **LED Strip Max Brightness** (default 50%) caps the draw. + Links: \ Discord (Support/feedback/discussion/future products): [http://dsc.gg/ApolloAutomation](http://dsc.gg/ApolloAutomation) \ Shop: [https://apolloautomation.com](https://apolloautomation.com) \ From 25761d6d5870e999c70f27654a396a0db3178cca Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Tue, 27 Oct 2026 15:21:00 -0400 Subject: [PATCH 18/30] led support initial testing of LED changes --- Integrations/ESPHome/led_strip.yaml | 395 +++++++++++++++++++++++++++- README.md | 16 ++ 2 files changed, 403 insertions(+), 8 deletions(-) diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml index 4ca66f6..9fcc620 100644 --- a/Integrations/ESPHome/led_strip.yaml +++ b/Integrations/ESPHome/led_strip.yaml @@ -19,13 +19,22 @@ esphome: id: led_strip_apply_max_brightness percent: !lambda "return id(led_strip_max_brightness).state;" +# Every LED strip entity sits under one header on the device's web page +web_server: + sorting_groups: + - id: sg_led_strip + name: "External LED Strip" + sorting_weight: 10 + light: - platform: esp32_rmt_led_strip id: led_strip output_id: led_strip_output name: "LED Strip" - disabled_by_default: true icon: mdi:led-strip-variant + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 1 pin: GPIO1 # Timings and color order are swapped at runtime by the select entities chipset: WS2812 @@ -41,6 +50,7 @@ light: # Re-send the settled frame once, and clear the whole strip after turn-off on_state: - script.execute: led_strip_refresh + # New effects go at the end: the light restores its effect by position effects: - addressable_rainbow: name: "Rainbow" @@ -61,13 +71,110 @@ light: - strobe: name: "Strobe" + # Effect A and Effect B run the pattern their Pattern select picks, at + # their own Speed and Intensity, on the segments whose switch is on + - addressable_lambda: + name: "Effect A" + # About one frame per main-loop pass (~16 ms); the lambda keeps its + # own clock, so this only caps how often the strip is re-sent + update_interval: 15ms + lambda: &led_strip_slot_effect |- + // Effect A and Effect B share this body; each copy keeps its own statics + static float level[8]; + static float target[8]; + static uint32_t next_ms = 0; + static uint32_t cycle_start = 0; + const uint32_t now = millis(); + + const bool slot_b = strcmp(id(led_strip).get_effect_name().c_str(), "Effect B") == 0; + auto *pattern = slot_b ? id(led_strip_effect_b_pattern) : id(led_strip_effect_a_pattern); + const float speed = clamp(slot_b ? id(led_strip_effect_b_speed).state + : id(led_strip_effect_a_speed).state, 1.0f, 100.0f); + const float intensity = clamp((slot_b ? id(led_strip_effect_b_intensity).state + : id(led_strip_effect_a_intensity).state) / 100.0f, 0.0f, 1.0f); + // Speed 1-100 on a log curve: 1 = 1000 ms, 50 = 176 ms, 100 = 30 ms + const uint32_t period = (uint32_t) (1000.0f * powf(0.03f, (speed - 1.0f) / 99.0f)); + + if (initial_run) { + for (auto &l : level) l = 1.0f; + for (auto &t : target) t = 1.0f; + next_ms = now; + cycle_start = now; + } + + // Split the strip into segments; the last one takes the leftover LEDs + const int32_t n = it.size(); + if (n <= 0) return; + const int32_t segs = std::max(1, std::min((int32_t) id(led_strip_segments).state, + std::min(8, n))); + const int32_t base = n / segs; + const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, + id(led_strip_segment_3).state, id(led_strip_segment_4).state, + id(led_strip_segment_5).state, id(led_strip_segment_6).state, + id(led_strip_segment_7).state, id(led_strip_segment_8).state}; + + if (pattern->active_index().value_or(0) == 1) { + // Strobe: one flash every 2 x period, lit for the Intensity share of it + const uint32_t cycle = period * 2; + if (now - cycle_start >= cycle) cycle_start = now - (now - cycle_start) % cycle; + const uint32_t on_ms = (uint32_t) (cycle * clamp(intensity, 0.05f, 0.95f)); + const Color c = (now - cycle_start) < on_ms ? current_color : Color::BLACK; + for (int32_t s = 0; s < segs; s++) { + const int32_t from = s * base; + const int32_t to = (s == segs - 1) ? n : from + base; + it.range(from, to) = seg_on[s] ? c : Color::BLACK; + } + } else { + // Flicker: every period each segment picks a new random level, no + // lower than 1 - Intensity, and eases toward it within a few frames + const int32_t late = (int32_t) (now - next_ms); + // A raised Speed pulls in a change that was scheduled further out + if (late >= 0 || -late > (int32_t) period) { + for (int32_t s = 0; s < segs; s++) target[s] = 1.0f - intensity * random_float(); + next_ms = (late >= 0 && late < (int32_t) period) ? next_ms + period : now + period; + } + for (int32_t s = 0; s < segs; s++) { + level[s] += (target[s] - level[s]) * 0.6f; + const int32_t from = s * base; + const int32_t to = (s == segs - 1) ? n : from + base; + it.range(from, to) = seg_on[s] ? current_color * (uint8_t) (level[s] * 255.0f) : Color::BLACK; + } + } + - addressable_lambda: + name: "Effect B" + update_interval: 15ms + lambda: *led_strip_slot_effect + + # Solid color on each segment whose switch is on; a plain color paints + # every LED, so the segment switches move the strip onto this effect + - addressable_lambda: + name: "Segments" + update_interval: 50ms + lambda: |- + const int32_t n = it.size(); + if (n <= 0) return; + const int32_t segs = std::max(1, std::min((int32_t) id(led_strip_segments).state, + std::min(8, n))); + const int32_t base = n / segs; + const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, + id(led_strip_segment_3).state, id(led_strip_segment_4).state, + id(led_strip_segment_5).state, id(led_strip_segment_6).state, + id(led_strip_segment_7).state, id(led_strip_segment_8).state}; + for (int32_t s = 0; s < segs; s++) { + const int32_t from = s * base; + const int32_t to = (s == segs - 1) ? n : from + base; + it.range(from, to) = seg_on[s] ? current_color : Color::BLACK; + } + number: - platform: template id: led_strip_count name: "LED Strip Count" - disabled_by_default: true icon: mdi:counter entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 20 mode: box min_value: 1 max_value: 300 @@ -84,9 +191,11 @@ number: - platform: template id: led_strip_max_brightness name: "LED Strip Max Brightness" - disabled_by_default: true icon: mdi:brightness-percent entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 21 unit_of_measurement: "%" mode: slider min_value: 10 @@ -100,13 +209,104 @@ number: id: led_strip_apply_max_brightness percent: !lambda "return x;" + # How many equal segments the strip splits into; Segment switches past this + # count do nothing + - platform: template + id: led_strip_segments + name: "LED Strip Segments" + icon: mdi:view-split-vertical + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 2 + mode: box + min_value: 1 + max_value: 8 + step: 1 + optimistic: true + restore_value: true + initial_value: 1 + on_value: + - script.execute: led_strip_segments_changed + + # Speed 1-100 maps on a log curve from 1 s (1) to 30 ms (100) between changes + - platform: template + id: led_strip_effect_a_speed + name: "LED Strip Effect A Speed" + icon: mdi:speedometer + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 12 + mode: slider + min_value: 1 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 50 + + # Flicker: how far a segment can dip (0 = steady); Strobe: share of each + # flash the strip is lit + - platform: template + id: led_strip_effect_a_intensity + name: "LED Strip Effect A Intensity" + icon: mdi:tune-vertical + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 13 + unit_of_measurement: "%" + mode: slider + min_value: 0 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 70 + + - platform: template + id: led_strip_effect_b_speed + name: "LED Strip Effect B Speed" + icon: mdi:speedometer + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 15 + mode: slider + min_value: 1 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 80 + + - platform: template + id: led_strip_effect_b_intensity + name: "LED Strip Effect B Intensity" + icon: mdi:tune-vertical + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 16 + unit_of_measurement: "%" + mode: slider + min_value: 0 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 50 + select: - platform: template id: led_strip_color_order name: "LED Strip Color Order" - disabled_by_default: true icon: mdi:palette entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 22 optimistic: true restore_value: true options: @@ -125,9 +325,11 @@ select: - platform: template id: led_strip_chipset name: "LED Strip Chipset" - disabled_by_default: true icon: mdi:chip entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 23 optimistic: true restore_value: true options: @@ -145,9 +347,11 @@ select: - platform: template id: led_strip_music_effect name: "LED Strip Music Effect" - disabled_by_default: true icon: mdi:music-circle entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 24 optimistic: true restore_value: true options: @@ -161,14 +365,48 @@ select: - "Pulse" initial_option: "Rainbow" + # Patterns for the Effect A / Effect B slots; the slot effect picks the + # pattern by position, so new patterns go at the end + - platform: template + id: led_strip_effect_a_pattern + name: "LED Strip Effect A Pattern" + icon: mdi:animation-play + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 11 + optimistic: true + restore_value: true + options: + - "Flicker" + - "Strobe" + initial_option: "Flicker" + + - platform: template + id: led_strip_effect_b_pattern + name: "LED Strip Effect B Pattern" + icon: mdi:animation-play + entity_category: config + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 14 + optimistic: true + restore_value: true + options: + - "Flicker" + - "Strobe" + initial_option: "Strobe" + switch: # Music Mode: the strip turns on with the Music Effect while audio plays and # off once playback has stopped for 10s - platform: template id: led_strip_music_mode name: "LED Strip Music Mode" - disabled_by_default: true icon: mdi:music-note + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 25 optimistic: true restore_mode: RESTORE_DEFAULT_OFF on_turn_on: @@ -184,6 +422,120 @@ switch: then: - light.turn_off: led_strip + # Segment switches: Effect A, Effect B and Segments leave a segment dark + # while its switch is off + - platform: template + id: led_strip_segment_1 + name: "LED Strip Segment 1" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 3 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_2 + name: "LED Strip Segment 2" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 4 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_3 + name: "LED Strip Segment 3" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 5 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_4 + name: "LED Strip Segment 4" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 6 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_5 + name: "LED Strip Segment 5" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 7 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_6 + name: "LED Strip Segment 6" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 8 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_7 + name: "LED Strip Segment 7" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 9 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + + - platform: template + id: led_strip_segment_8 + name: "LED Strip Segment 8" + icon: mdi:led-strip + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 10 + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - script.execute: led_strip_segments_changed + on_turn_off: + - script.execute: led_strip_segments_changed + binary_sensor: - platform: template id: led_strip_music_playing @@ -215,9 +567,11 @@ button: - platform: template id: led_strip_test_button name: "LED Strip Test" - disabled_by_default: true icon: mdi:led-strip-variant entity_category: diagnostic + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 30 on_press: - script.execute: led_strip_test @@ -305,6 +659,31 @@ script: out->write_state(id(led_strip)); out->set_num_leds(count); + # A plain color paints every LED, so when a segment is switched off while the + # strip shows one, move the strip onto the Segments effect to mask it + - id: led_strip_segments_changed + mode: queued + then: + - if: + condition: + and: + - light.is_on: led_strip + - lambda: |- + if (strcmp(id(led_strip).get_effect_name().c_str(), "None") != 0) return false; + const int32_t segs = std::min((int32_t) id(led_strip_segments).state, 8); + const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, + id(led_strip_segment_3).state, id(led_strip_segment_4).state, + id(led_strip_segment_5).state, id(led_strip_segment_6).state, + id(led_strip_segment_7).state, id(led_strip_segment_8).state}; + for (int32_t s = 0; s < segs; s++) { + if (!seg_on[s]) return true; + } + return false; + then: + - light.turn_on: + id: led_strip + effect: "Segments" + - id: led_strip_music_start then: - light.turn_on: diff --git a/README.md b/README.md index db318ad..6dcdd3c 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,22 @@ Configure every button without leaving Home Assistant using the [CAST-1 WizMote [![Import Blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FBlueprints%2Fblob%2Fmain%2FCAST-1%2FCAST-1-WizMote.yaml) +## External LED Strip + +The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). Every setting lives in Home Assistant and under **External LED Strip** on the device's web page — no YAML edits needed. + +- **LED Strip Count** and **LED Strip Segments** set how many LEDs you have and how many equal segments they split into (1–8). Leftover LEDs go to the last segment, so 22 LEDs in 3 segments are 7 / 7 / 8. +- **LED Strip Segment 1–8** switch each segment on or off. Switches past the Segments count do nothing. +- **Effect A** and **Effect B** are two effect slots on the LED Strip light. Each has a **Pattern** (Flicker or Strobe), a **Speed** (1 = one change per second, 100 = one every 30 ms, on a log curve) and an **Intensity** (Flicker: how deep it dips; Strobe: how much of each flash is lit). Changes apply live while the effect runs. +- The **Segments** effect shows a solid color on the segments that are on. Switching a segment off while the strip shows a plain color moves it onto this effect automatically. + +In automations, set the pattern, speed and segments with `select.select_option`, `number.set_value` and `switch.turn_on` / `switch.turn_off`, then call `light.turn_on` with `effect: "Effect A"` (add `transition: 0` for an instant start). + +> [!WARNING] +> **Photosensitivity:** Strobe flashes faster than 3 times per second from about Speed 50 up, and reaches about 16 flashes per second at Speed 100. Flashing in this range can trigger seizures in people with photosensitive epilepsy. + +Power long strips from their own 5V supply with a shared ground; the header can't supply a full-brightness strip, and **LED Strip Max Brightness** (default 50%) caps the draw. + Links: \ Discord (Support/feedback/discussion/future products): [http://dsc.gg/ApolloAutomation](http://dsc.gg/ApolloAutomation) \ Shop: [https://apolloautomation.com](https://apolloautomation.com) \ From 0e7068e956229b68a1ea91eb1b6b89312df18860 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Tue, 27 Oct 2026 15:47:44 -0400 Subject: [PATCH 19/30] fix cast error --- Integrations/ESPHome/led_strip.yaml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml index 9fcc620..67b10d9 100644 --- a/Integrations/ESPHome/led_strip.yaml +++ b/Integrations/ESPHome/led_strip.yaml @@ -87,11 +87,16 @@ light: const uint32_t now = millis(); const bool slot_b = strcmp(id(led_strip).get_effect_name().c_str(), "Effect B") == 0; - auto *pattern = slot_b ? id(led_strip_effect_b_pattern) : id(led_strip_effect_a_pattern); - const float speed = clamp(slot_b ? id(led_strip_effect_b_speed).state - : id(led_strip_effect_a_speed).state, 1.0f, 100.0f); - const float intensity = clamp((slot_b ? id(led_strip_effect_b_intensity).state - : id(led_strip_effect_a_intensity).state) / 100.0f, 0.0f, 1.0f); + // Each template select is its own type (it carries its initial option), + // so pick through the shared base classes + select::Select *pattern = slot_b ? static_cast(id(led_strip_effect_b_pattern)) + : static_cast(id(led_strip_effect_a_pattern)); + number::Number *speed_num = slot_b ? static_cast(id(led_strip_effect_b_speed)) + : static_cast(id(led_strip_effect_a_speed)); + number::Number *intensity_num = slot_b ? static_cast(id(led_strip_effect_b_intensity)) + : static_cast(id(led_strip_effect_a_intensity)); + const float speed = clamp(speed_num->state, 1.0f, 100.0f); + const float intensity = clamp(intensity_num->state / 100.0f, 0.0f, 1.0f); // Speed 1-100 on a log curve: 1 = 1000 ms, 50 = 176 ms, 100 = 30 ms const uint32_t period = (uint32_t) (1000.0f * powf(0.03f, (speed - 1.0f) / 99.0f)); From 6ad0e3df05a03ff78f4eb96bf089247d2cf028c4 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Tue, 27 Oct 2026 16:00:24 -0400 Subject: [PATCH 20/30] Move LED segments and count into the device YAML Segments are now partition lights the user adds to their device YAML, so drop the Segments number, the eight Segment switches, the Segments effect and its script. Effect A and Effect B render through one shared helper (led_strip_slot_effect) that partition lights can list too, all driven by the same Pattern, Speed and Intensity entities. The LED count is now the led_strip_num_leds substitution (default 30) instead of the runtime LED Strip Count entity, since partitions need it at build time. Speed 100 is now 32 ms, two ~16 ms main-loop passes. The README documents the substitution and a partition example. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/led_strip.yaml | 383 ++++++---------------------- README.md | 65 ++++- 2 files changed, 142 insertions(+), 306 deletions(-) diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml index 67b10d9..21302f6 100644 --- a/Integrations/ESPHome/led_strip.yaml +++ b/Integrations/ESPHome/led_strip.yaml @@ -1,13 +1,16 @@ # LED strip on the exposed 5V / GND / IO1 header; included by Core.yaml +substitutions: + # How many LEDs the strip has; set led_strip_num_leds in the device YAML's + # substitutions to override it (partitions must fit inside it) + led_strip_num_leds: "30" + esphome: on_boot: # Apply the saved LED strip settings before the light's first write # Must run after the strip and the restored entities set up (800) - priority: 600 then: - - lambda: |- - id(led_strip_output)->set_num_leds((uint16_t) id(led_strip_count).state); - script.execute: led_strip_blank_all - script.execute: id: led_strip_apply_color_order @@ -39,7 +42,7 @@ light: # Timings and color order are swapped at runtime by the select entities chipset: WS2812 channel_colors: GRB - num_leds: 300 + num_leds: ${led_strip_num_leds} # The rest of the RMT TX memory after the onboard light's 48 rmt_symbols: 144 # The RMT interrupt refills from these buffers mid-frame; PSRAM reads can @@ -72,126 +75,90 @@ light: name: "Strobe" # Effect A and Effect B run the pattern their Pattern select picks, at - # their own Speed and Intensity, on the segments whose switch is on + # their own Speed and Intensity. Partition lights in the device YAML can + # list the same two entries (see the README) - addressable_lambda: name: "Effect A" - # About one frame per main-loop pass (~16 ms); the lambda keeps its + # About one frame per main-loop pass (~16 ms); the helper keeps its # own clock, so this only caps how often the strip is re-sent update_interval: 15ms - lambda: &led_strip_slot_effect |- - // Effect A and Effect B share this body; each copy keeps its own statics - static float level[8]; - static float target[8]; - static uint32_t next_ms = 0; - static uint32_t cycle_start = 0; - const uint32_t now = millis(); - - const bool slot_b = strcmp(id(led_strip).get_effect_name().c_str(), "Effect B") == 0; - // Each template select is its own type (it carries its initial option), - // so pick through the shared base classes - select::Select *pattern = slot_b ? static_cast(id(led_strip_effect_b_pattern)) - : static_cast(id(led_strip_effect_a_pattern)); - number::Number *speed_num = slot_b ? static_cast(id(led_strip_effect_b_speed)) - : static_cast(id(led_strip_effect_a_speed)); - number::Number *intensity_num = slot_b ? static_cast(id(led_strip_effect_b_intensity)) - : static_cast(id(led_strip_effect_a_intensity)); - const float speed = clamp(speed_num->state, 1.0f, 100.0f); - const float intensity = clamp(intensity_num->state / 100.0f, 0.0f, 1.0f); - // Speed 1-100 on a log curve: 1 = 1000 ms, 50 = 176 ms, 100 = 30 ms - const uint32_t period = (uint32_t) (1000.0f * powf(0.03f, (speed - 1.0f) / 99.0f)); - - if (initial_run) { - for (auto &l : level) l = 1.0f; - for (auto &t : target) t = 1.0f; - next_ms = now; - cycle_start = now; - } - - // Split the strip into segments; the last one takes the leftover LEDs - const int32_t n = it.size(); - if (n <= 0) return; - const int32_t segs = std::max(1, std::min((int32_t) id(led_strip_segments).state, - std::min(8, n))); - const int32_t base = n / segs; - const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, - id(led_strip_segment_3).state, id(led_strip_segment_4).state, - id(led_strip_segment_5).state, id(led_strip_segment_6).state, - id(led_strip_segment_7).state, id(led_strip_segment_8).state}; - - if (pattern->active_index().value_or(0) == 1) { - // Strobe: one flash every 2 x period, lit for the Intensity share of it - const uint32_t cycle = period * 2; - if (now - cycle_start >= cycle) cycle_start = now - (now - cycle_start) % cycle; - const uint32_t on_ms = (uint32_t) (cycle * clamp(intensity, 0.05f, 0.95f)); - const Color c = (now - cycle_start) < on_ms ? current_color : Color::BLACK; - for (int32_t s = 0; s < segs; s++) { - const int32_t from = s * base; - const int32_t to = (s == segs - 1) ? n : from + base; - it.range(from, to) = seg_on[s] ? c : Color::BLACK; - } - } else { - // Flicker: every period each segment picks a new random level, no - // lower than 1 - Intensity, and eases toward it within a few frames - const int32_t late = (int32_t) (now - next_ms); - // A raised Speed pulls in a change that was scheduled further out - if (late >= 0 || -late > (int32_t) period) { - for (int32_t s = 0; s < segs; s++) target[s] = 1.0f - intensity * random_float(); - next_ms = (late >= 0 && late < (int32_t) period) ? next_ms + period : now + period; - } - for (int32_t s = 0; s < segs; s++) { - level[s] += (target[s] - level[s]) * 0.6f; - const int32_t from = s * base; - const int32_t to = (s == segs - 1) ? n : from + base; - it.range(from, to) = seg_on[s] ? current_color * (uint8_t) (level[s] * 255.0f) : Color::BLACK; - } - } + lambda: "id(led_strip_slot_effect)(it, current_color, initial_run, 0);" - addressable_lambda: name: "Effect B" update_interval: 15ms - lambda: *led_strip_slot_effect - - # Solid color on each segment whose switch is on; a plain color paints - # every LED, so the segment switches move the strip onto this effect - - addressable_lambda: - name: "Segments" - update_interval: 50ms - lambda: |- - const int32_t n = it.size(); - if (n <= 0) return; - const int32_t segs = std::max(1, std::min((int32_t) id(led_strip_segments).state, - std::min(8, n))); - const int32_t base = n / segs; - const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, - id(led_strip_segment_3).state, id(led_strip_segment_4).state, - id(led_strip_segment_5).state, id(led_strip_segment_6).state, - id(led_strip_segment_7).state, id(led_strip_segment_8).state}; - for (int32_t s = 0; s < segs; s++) { - const int32_t from = s * base; - const int32_t to = (s == segs - 1) ? n : from + base; - it.range(from, to) = seg_on[s] ? current_color : Color::BLACK; - } + lambda: "id(led_strip_slot_effect)(it, current_color, initial_run, 1);" + +globals: + # Renders Effect A (slot 0) and Effect B (slot 1) for any addressable light, + # so the LED Strip and partition lights share one copy and one set of + # Pattern / Speed / Intensity entities. A globals initializer is plain C++, + # so it names the entities directly instead of through id() + - id: led_strip_slot_effect + type: std::function + restore_value: no + initial_value: |- + [](light::AddressableLight &it, Color color, bool initial_run, int slot) { + struct SlotState { + float level; + float target; + uint32_t next_ms; + uint32_t cycle_start; + }; + // One state per light, since a light runs one effect at a time + static const light::AddressableLight *owners[16] = {}; + static SlotState states[16]; + int i = 0; + while (i < 16 && owners[i] != nullptr && owners[i] != &it) i++; + if (i == 16) return; + if (owners[i] == nullptr) { + owners[i] = ⁢ + initial_run = true; + } + SlotState &st = states[i]; + const uint32_t now = millis(); + + // Each template select is its own type (it carries its initial option), + // so pick through the shared base classes + select::Select *pattern = slot == 1 ? static_cast(led_strip_effect_b_pattern) + : static_cast(led_strip_effect_a_pattern); + number::Number *speed_num = slot == 1 ? static_cast(led_strip_effect_b_speed) + : static_cast(led_strip_effect_a_speed); + number::Number *intensity_num = slot == 1 ? static_cast(led_strip_effect_b_intensity) + : static_cast(led_strip_effect_a_intensity); + const float speed = clamp(speed_num->state, 1.0f, 100.0f); + const float intensity = clamp(intensity_num->state / 100.0f, 0.0f, 1.0f); + // Speed 1-100 on a log curve: 1 = 1000 ms, 50 = 182 ms, 100 = 32 ms, + // so the fastest step lands on two ~16 ms main-loop passes + const uint32_t period = (uint32_t) (1000.0f * powf(0.032f, (speed - 1.0f) / 99.0f)); + + if (initial_run) { + st.level = 1.0f; + st.target = 1.0f; + st.next_ms = now; + st.cycle_start = now; + } + + if (pattern->active_index().value_or(0) == 1) { + // Strobe: one flash every 2 x period, lit for the Intensity share of it + const uint32_t cycle = period * 2; + if (now - st.cycle_start >= cycle) st.cycle_start = now - (now - st.cycle_start) % cycle; + const uint32_t on_ms = (uint32_t) (cycle * clamp(intensity, 0.05f, 0.95f)); + it.all() = (now - st.cycle_start) < on_ms ? color : Color::BLACK; + } else { + // Flicker: every period the light picks a new random level, no lower + // than 1 - Intensity, and eases toward it within a few frames + const int32_t late = (int32_t) (now - st.next_ms); + // A raised Speed pulls in a change that was scheduled further out + if (late >= 0 || -late > (int32_t) period) { + st.target = 1.0f - intensity * random_float(); + st.next_ms = (late >= 0 && late < (int32_t) period) ? st.next_ms + period : now + period; + } + st.level += (st.target - st.level) * 0.6f; + it.all() = color * (uint8_t) (st.level * 255.0f); + } + } number: - - platform: template - id: led_strip_count - name: "LED Strip Count" - icon: mdi:counter - entity_category: config - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 20 - mode: box - min_value: 1 - max_value: 300 - step: 1 - optimistic: true - restore_value: true - initial_value: 30 - set_action: - - script.execute: - id: led_strip_apply_count - count: !lambda "return (int) x;" - # Caps every channel so a long strip can't overdraw the header's 5V rail - platform: template id: led_strip_max_brightness @@ -214,27 +181,7 @@ number: id: led_strip_apply_max_brightness percent: !lambda "return x;" - # How many equal segments the strip splits into; Segment switches past this - # count do nothing - - platform: template - id: led_strip_segments - name: "LED Strip Segments" - icon: mdi:view-split-vertical - entity_category: config - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 2 - mode: box - min_value: 1 - max_value: 8 - step: 1 - optimistic: true - restore_value: true - initial_value: 1 - on_value: - - script.execute: led_strip_segments_changed - - # Speed 1-100 maps on a log curve from 1 s (1) to 30 ms (100) between changes + # Speed 1-100 maps on a log curve from 1 s (1) to 32 ms (100) between changes - platform: template id: led_strip_effect_a_speed name: "LED Strip Effect A Speed" @@ -251,7 +198,7 @@ number: restore_value: true initial_value: 50 - # Flicker: how far a segment can dip (0 = steady); Strobe: share of each + # Flicker: how far the light can dip (0 = steady); Strobe: share of each # flash the strip is lit - platform: template id: led_strip_effect_a_intensity @@ -427,120 +374,6 @@ switch: then: - light.turn_off: led_strip - # Segment switches: Effect A, Effect B and Segments leave a segment dark - # while its switch is off - - platform: template - id: led_strip_segment_1 - name: "LED Strip Segment 1" - icon: mdi:led-strip - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 3 - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: led_strip_segments_changed - on_turn_off: - - script.execute: led_strip_segments_changed - - - platform: template - id: led_strip_segment_2 - name: "LED Strip Segment 2" - icon: mdi:led-strip - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 4 - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: led_strip_segments_changed - on_turn_off: - - script.execute: led_strip_segments_changed - - - platform: template - id: led_strip_segment_3 - name: "LED Strip Segment 3" - icon: mdi:led-strip - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 5 - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: led_strip_segments_changed - on_turn_off: - - script.execute: led_strip_segments_changed - - - platform: template - id: led_strip_segment_4 - name: "LED Strip Segment 4" - icon: mdi:led-strip - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 6 - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: led_strip_segments_changed - on_turn_off: - - script.execute: led_strip_segments_changed - - - platform: template - id: led_strip_segment_5 - name: "LED Strip Segment 5" - icon: mdi:led-strip - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 7 - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: led_strip_segments_changed - on_turn_off: - - script.execute: led_strip_segments_changed - - - platform: template - id: led_strip_segment_6 - name: "LED Strip Segment 6" - icon: mdi:led-strip - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 8 - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: led_strip_segments_changed - on_turn_off: - - script.execute: led_strip_segments_changed - - - platform: template - id: led_strip_segment_7 - name: "LED Strip Segment 7" - icon: mdi:led-strip - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 9 - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: led_strip_segments_changed - on_turn_off: - - script.execute: led_strip_segments_changed - - - platform: template - id: led_strip_segment_8 - name: "LED Strip Segment 8" - icon: mdi:led-strip - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 10 - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - on_turn_on: - - script.execute: led_strip_segments_changed - on_turn_off: - - script.execute: led_strip_segments_changed - binary_sensor: - platform: template id: led_strip_music_playing @@ -581,23 +414,6 @@ button: - script.execute: led_strip_test script: - - id: led_strip_apply_count - mode: queued - parameters: - count: int - then: - - lambda: |- - auto *out = id(led_strip_output); - // Blank every pixel the buffers cover, so LEDs past a lowered count go dark - out->set_num_leds(300); - for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; - out->write_state(id(led_strip)); - out->set_num_leds((uint16_t) count); - out->clear_effect_data(); - // Repaint the current color at the new length (effects repaint themselves) - out->update_state(id(led_strip)); - ESP_LOGI("led_strip", "Driving %d LEDs", count); - - id: led_strip_apply_max_brightness parameters: percent: float @@ -654,40 +470,11 @@ script: - id: led_strip_blank_all then: - lambda: |- - // Clear every pixel the buffers cover, so LEDs past the LED Strip Count - // (never written otherwise) can't keep colors latched from IO1 noise - // during a reboot or an earlier, longer count + // Clear every pixel, so none keeps a color latched from IO1 noise + // during a reboot auto *out = id(led_strip_output); - const uint16_t count = out->size(); - out->set_num_leds(300); for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; out->write_state(id(led_strip)); - out->set_num_leds(count); - - # A plain color paints every LED, so when a segment is switched off while the - # strip shows one, move the strip onto the Segments effect to mask it - - id: led_strip_segments_changed - mode: queued - then: - - if: - condition: - and: - - light.is_on: led_strip - - lambda: |- - if (strcmp(id(led_strip).get_effect_name().c_str(), "None") != 0) return false; - const int32_t segs = std::min((int32_t) id(led_strip_segments).state, 8); - const bool seg_on[8] = {id(led_strip_segment_1).state, id(led_strip_segment_2).state, - id(led_strip_segment_3).state, id(led_strip_segment_4).state, - id(led_strip_segment_5).state, id(led_strip_segment_6).state, - id(led_strip_segment_7).state, id(led_strip_segment_8).state}; - for (int32_t s = 0; s < segs; s++) { - if (!seg_on[s]) return true; - } - return false; - then: - - light.turn_on: - id: led_strip - effect: "Segments" - id: led_strip_music_start then: diff --git a/README.md b/README.md index 6dcdd3c..35fa719 100644 --- a/README.md +++ b/README.md @@ -35,14 +35,63 @@ Configure every button without leaving Home Assistant using the [CAST-1 WizMote ## External LED Strip -The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). Every setting lives in Home Assistant and under **External LED Strip** on the device's web page — no YAML edits needed. - -- **LED Strip Count** and **LED Strip Segments** set how many LEDs you have and how many equal segments they split into (1–8). Leftover LEDs go to the last segment, so 22 LEDs in 3 segments are 7 / 7 / 8. -- **LED Strip Segment 1–8** switch each segment on or off. Switches past the Segments count do nothing. -- **Effect A** and **Effect B** are two effect slots on the LED Strip light. Each has a **Pattern** (Flicker or Strobe), a **Speed** (1 = one change per second, 100 = one every 30 ms, on a log curve) and an **Intensity** (Flicker: how deep it dips; Strobe: how much of each flash is lit). Changes apply live while the effect runs. -- The **Segments** effect shows a solid color on the segments that are on. Switching a segment off while the strip shows a plain color moves it onto this effect automatically. - -In automations, set the pattern, speed and segments with `select.select_option`, `number.set_value` and `switch.turn_on` / `switch.turn_off`, then call `light.turn_on` with `effect: "Effect A"` (add `transition: 0` for an instant start). +The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). Set how many LEDs it has in your device YAML in ESPHome Device Builder (the default is 30), then install: + +```yaml +substitutions: + led_strip_num_leds: "21" +``` + +The rest of the strip's settings live in Home Assistant and under **External LED Strip** on the device's web page: + +- **Chipset**, **Color Order** and **Max Brightness** describe your strip. +- **Effect A** and **Effect B** are two effect slots. Each has a **Pattern** (Flicker or Strobe), a **Speed** (1 = one change per second, 100 = one every 32 ms, on a log curve) and an **Intensity** (Flicker: how deep it dips; Strobe: how much of each flash is lit). Changes apply live while the effect runs. + +In automations, set the pattern and speed with `select.select_option` and `number.set_value`, then call `light.turn_on` with `effect: "Effect A"` (add `transition: 0` for an instant start). + +### Splitting the strip into segments + +To turn parts of the strip on and off on their own, add [partition lights](https://esphome.io/components/light/partition/) to your device YAML in ESPHome Device Builder and install it. Each partition becomes its own light in Home Assistant, with its own on/off, color, brightness and effect. List Effect A and Effect B on a partition to use the shared Pattern, Speed and Intensity settings. + +For 21 LEDs in 3 segments of 7 (`to` is inclusive, and the first LED is 0): + +```yaml +light: + - platform: partition + name: "LED Segment 1" + segments: + - id: led_strip + from: 0 + to: 6 + default_transition_length: 0s + effects: &led_segment_effects + - addressable_lambda: + name: "Effect A" + update_interval: 15ms + lambda: "id(led_strip_slot_effect)(it, current_color, initial_run, 0);" + - addressable_lambda: + name: "Effect B" + update_interval: 15ms + lambda: "id(led_strip_slot_effect)(it, current_color, initial_run, 1);" + - platform: partition + name: "LED Segment 2" + segments: + - id: led_strip + from: 7 + to: 13 + default_transition_length: 0s + effects: *led_segment_effects + - platform: partition + name: "LED Segment 3" + segments: + - id: led_strip + from: 14 + to: 20 + default_transition_length: 0s + effects: *led_segment_effects +``` + +Every partition has to fit inside `led_strip_num_leds`; the install fails if one doesn't. Partitions share the strip's pixels, so control either the partitions or the main **LED Strip** light, not both at once — turning the main light off clears the whole strip. > [!WARNING] > **Photosensitivity:** Strobe flashes faster than 3 times per second from about Speed 50 up, and reaches about 16 flashes per second at Speed 100. Flashing in this range can trigger seizures in people with photosensitive epilepsy. From 1255db3da2bdc331a2a0626dc54772d053c034e5 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Tue, 27 Oct 2026 16:14:16 -0400 Subject: [PATCH 21/30] Remove the Intensity setting from the LED effects Intensity didn't make a visible difference and was confusing, so drop the Effect A / Effect B Intensity numbers. Flicker now always dips to random levels between full and 30% brightness, and Strobe is on for one period and off for the next. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/led_strip.yaml | 52 ++++------------------------- README.md | 4 +-- 2 files changed, 8 insertions(+), 48 deletions(-) diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml index 21302f6..480acc5 100644 --- a/Integrations/ESPHome/led_strip.yaml +++ b/Integrations/ESPHome/led_strip.yaml @@ -75,7 +75,7 @@ light: name: "Strobe" # Effect A and Effect B run the pattern their Pattern select picks, at - # their own Speed and Intensity. Partition lights in the device YAML can + # their own Speed. Partition lights in the device YAML can # list the same two entries (see the README) - addressable_lambda: name: "Effect A" @@ -91,7 +91,7 @@ light: globals: # Renders Effect A (slot 0) and Effect B (slot 1) for any addressable light, # so the LED Strip and partition lights share one copy and one set of - # Pattern / Speed / Intensity entities. A globals initializer is plain C++, + # Pattern / Speed entities. A globals initializer is plain C++, # so it names the entities directly instead of through id() - id: led_strip_slot_effect type: std::function @@ -123,10 +123,7 @@ globals: : static_cast(led_strip_effect_a_pattern); number::Number *speed_num = slot == 1 ? static_cast(led_strip_effect_b_speed) : static_cast(led_strip_effect_a_speed); - number::Number *intensity_num = slot == 1 ? static_cast(led_strip_effect_b_intensity) - : static_cast(led_strip_effect_a_intensity); const float speed = clamp(speed_num->state, 1.0f, 100.0f); - const float intensity = clamp(intensity_num->state / 100.0f, 0.0f, 1.0f); // Speed 1-100 on a log curve: 1 = 1000 ms, 50 = 182 ms, 100 = 32 ms, // so the fastest step lands on two ~16 ms main-loop passes const uint32_t period = (uint32_t) (1000.0f * powf(0.032f, (speed - 1.0f) / 99.0f)); @@ -139,18 +136,17 @@ globals: } if (pattern->active_index().value_or(0) == 1) { - // Strobe: one flash every 2 x period, lit for the Intensity share of it + // Strobe: on for one period, off for the next const uint32_t cycle = period * 2; if (now - st.cycle_start >= cycle) st.cycle_start = now - (now - st.cycle_start) % cycle; - const uint32_t on_ms = (uint32_t) (cycle * clamp(intensity, 0.05f, 0.95f)); - it.all() = (now - st.cycle_start) < on_ms ? color : Color::BLACK; + it.all() = (now - st.cycle_start) < period ? color : Color::BLACK; } else { // Flicker: every period the light picks a new random level, no lower - // than 1 - Intensity, and eases toward it within a few frames + // than 30%, and eases toward it within a few frames const int32_t late = (int32_t) (now - st.next_ms); // A raised Speed pulls in a change that was scheduled further out if (late >= 0 || -late > (int32_t) period) { - st.target = 1.0f - intensity * random_float(); + st.target = 1.0f - 0.7f * random_float(); st.next_ms = (late >= 0 && late < (int32_t) period) ? st.next_ms + period : now + period; } st.level += (st.target - st.level) * 0.6f; @@ -198,25 +194,6 @@ number: restore_value: true initial_value: 50 - # Flicker: how far the light can dip (0 = steady); Strobe: share of each - # flash the strip is lit - - platform: template - id: led_strip_effect_a_intensity - name: "LED Strip Effect A Intensity" - icon: mdi:tune-vertical - entity_category: config - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 13 - unit_of_measurement: "%" - mode: slider - min_value: 0 - max_value: 100 - step: 1 - optimistic: true - restore_value: true - initial_value: 70 - - platform: template id: led_strip_effect_b_speed name: "LED Strip Effect B Speed" @@ -233,23 +210,6 @@ number: restore_value: true initial_value: 80 - - platform: template - id: led_strip_effect_b_intensity - name: "LED Strip Effect B Intensity" - icon: mdi:tune-vertical - entity_category: config - web_server: - sorting_group_id: sg_led_strip - sorting_weight: 16 - unit_of_measurement: "%" - mode: slider - min_value: 0 - max_value: 100 - step: 1 - optimistic: true - restore_value: true - initial_value: 50 - select: - platform: template id: led_strip_color_order diff --git a/README.md b/README.md index 35fa719..f5879f4 100644 --- a/README.md +++ b/README.md @@ -45,13 +45,13 @@ substitutions: The rest of the strip's settings live in Home Assistant and under **External LED Strip** on the device's web page: - **Chipset**, **Color Order** and **Max Brightness** describe your strip. -- **Effect A** and **Effect B** are two effect slots. Each has a **Pattern** (Flicker or Strobe), a **Speed** (1 = one change per second, 100 = one every 32 ms, on a log curve) and an **Intensity** (Flicker: how deep it dips; Strobe: how much of each flash is lit). Changes apply live while the effect runs. +- **Effect A** and **Effect B** are two effect slots. Each has a **Pattern** (Flicker or Strobe) and a **Speed** (1 = one change per second, 100 = one every 32 ms, on a log curve). Flicker dips to random levels between full and 30% brightness; Strobe is on for one period and off for the next. Changes apply live while the effect runs. In automations, set the pattern and speed with `select.select_option` and `number.set_value`, then call `light.turn_on` with `effect: "Effect A"` (add `transition: 0` for an instant start). ### Splitting the strip into segments -To turn parts of the strip on and off on their own, add [partition lights](https://esphome.io/components/light/partition/) to your device YAML in ESPHome Device Builder and install it. Each partition becomes its own light in Home Assistant, with its own on/off, color, brightness and effect. List Effect A and Effect B on a partition to use the shared Pattern, Speed and Intensity settings. +To turn parts of the strip on and off on their own, add [partition lights](https://esphome.io/components/light/partition/) to your device YAML in ESPHome Device Builder and install it. Each partition becomes its own light in Home Assistant, with its own on/off, color, brightness and effect. List Effect A and Effect B on a partition to use the shared Pattern and Speed settings. For 21 LEDs in 3 segments of 7 (`to` is inclusive, and the first LED is 0): From 5cba2f6dd2c595286abd989218dca20b91f3fe69 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Tue, 27 Oct 2026 21:51:26 -0400 Subject: [PATCH 22/30] Make announcement ducking and LED brightness configurable Add the announcement_ducking_db and announcement_led_brightness substitutions to Core.yaml, so the device YAML can override how far music ducks during an announcement and how bright the onboard LED is. Document both in the README. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 9 +++++++-- README.md | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index a34a147..6b47959 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -4,6 +4,11 @@ substitutions: beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" beta_manifest_file: "manifest.json" + # How far music drops (in dB) while an announcement plays; set in the + # device YAML's substitutions to override it (0 = no ducking) + announcement_ducking_db: "40" + # Onboard LED brightness while an announcement plays (0%-100%) + announcement_led_brightness: "50%" packages: @@ -597,10 +602,10 @@ media_player: blue: 100% red: 0% green: 100% - brightness: 50% + brightness: ${announcement_led_brightness} - mixer_speaker.apply_ducking: id: media_mixer_input - decibel_reduction: 40 + decibel_reduction: ${announcement_ducking_db} duration: 0.0s - wait_until: media_player.is_announcing: external_media_player diff --git a/README.md b/README.md index f5879f4..f3cb3f6 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,16 @@ Configure every button without leaving Home Assistant using the [CAST-1 WizMote [![Import Blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FBlueprints%2Fblob%2Fmain%2FCAST-1%2FCAST-1-WizMote.yaml) +## Announcements + +While an announcement plays, music ducks and the onboard LED lights up. Change either in your device YAML in ESPHome Device Builder, then install: + +```yaml +substitutions: + announcement_ducking_db: "20" # how far music drops, in dB (default 40; 0 = no ducking) + announcement_led_brightness: "25%" # onboard LED brightness during announcements (default 50%) +``` + ## External LED Strip The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). Set how many LEDs it has in your device YAML in ESPHome Device Builder (the default is 30), then install: From 6745b104b89750b5fd62135a9716c7df31892305 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Wed, 28 Oct 2026 01:10:02 -0400 Subject: [PATCH 23/30] Make the external LED strip an opt-in package Core.yaml no longer includes led_strip.yaml. A device YAML adds the strip by listing led_strip.yaml in its packages; the README shows how. Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 3 ++- README.md | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 6b47959..e205313 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -13,7 +13,8 @@ substitutions: packages: wizmote: !include wizmote.yaml - led_strip: !include led_strip.yaml + # The external LED strip (led_strip.yaml) is opt-in: add it to the + # package files in the device YAML esphome: friendly_name: Apollo CAST-1 diff --git a/README.md b/README.md index f3cb3f6..eaaf502 100644 --- a/README.md +++ b/README.md @@ -45,13 +45,19 @@ substitutions: ## External LED Strip -The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). Set how many LEDs it has in your device YAML in ESPHome Device Builder (the default is 30), then install: +The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). The strip is opt-in: add `led_strip.yaml` to the packages in your device YAML in ESPHome Device Builder, set how many LEDs it has (the default is 30), then install: ```yaml substitutions: led_strip_num_leds: "21" + +packages: + cast_1: github://ApolloAutomation/CAST-1/Integrations/ESPHome/CAST-1.yaml@main + led_strip: github://ApolloAutomation/CAST-1/Integrations/ESPHome/led_strip.yaml@main ``` +Remove the `led_strip` line to drop the strip again. Any partitions you added have to go with it, since they use the strip. + The rest of the strip's settings live in Home Assistant and under **External LED Strip** on the device's web page: - **Chipset**, **Color Order** and **Max Brightness** describe your strip. From 7865e96246ddd44b1ec908bdbe64eb2b177f7fb1 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Wed, 28 Oct 2026 01:13:05 -0400 Subject: [PATCH 24/30] Added blueprints for 3 different sensors and README --- Blueprints/Light-Sequence-Distance-Based.yaml | 837 ++++++++++++++++ Blueprints/Light-Sequence-Motion-Based.yaml | 903 ++++++++++++++++++ .../Light-Sequence-Porch-Zone-Based.yaml | 781 +++++++++++++++ Blueprints/README.md | 74 ++ 4 files changed, 2595 insertions(+) create mode 100644 Blueprints/Light-Sequence-Distance-Based.yaml create mode 100644 Blueprints/Light-Sequence-Motion-Based.yaml create mode 100644 Blueprints/Light-Sequence-Porch-Zone-Based.yaml create mode 100644 Blueprints/README.md diff --git a/Blueprints/Light-Sequence-Distance-Based.yaml b/Blueprints/Light-Sequence-Distance-Based.yaml new file mode 100644 index 0000000..53f56a9 --- /dev/null +++ b/Blueprints/Light-Sequence-Distance-Based.yaml @@ -0,0 +1,837 @@ +blueprint: + name: Light Sequence (Distance-Based) + description: >- + Lights a path in stages as a visitor walks toward the door, using one + radar distance reading instead of separate zones. Made for LD2410 and + LD2412 style sensors (an Apollo R PRO-1, for example) mounted by the door + and facing out, so the distance shrinks as a visitor walks up. + + + Each stage turns on when the visitor comes within its distance, and the + earlier stages stay on. Coming within the finale distance switches every + lit light to the finale look, then all of them go to the resting state. + If the visitor doesn't get closer in time, the lit lights go to the + resting state early. + + + Stages only advance toward the door. Someone stepping out of the door and + walking away doesn't start a sequence. + + + Works with any Home Assistant lights. Sounds play as announcements, so + music playing on the same speaker ducks under them instead of stopping. + domain: automation + author: Apollo Automation + homeassistant: + min_version: 2025.7.0 + input: + sensor_section: + name: Radar sensor + icon: mdi:radar + collapsed: false + input: + distance_sensor: + name: Distance sensor + description: >- + The radar's distance to the visitor. Moving Distance works best, + since it ignores still objects such as plants or a parked car. + Detection Distance also works. The distances you enter below use + this sensor's unit (in, cm, ft or m), whatever it shows in Home Assistant. + # Any sensor: many radars' distance entities, such as the R PRO-1's + # LD2412 ones, have no distance device class + selector: + entity: + filter: + - domain: sensor + presence_sensor: + name: Target sensor (recommended) + description: >- + On while the radar sees anyone, moving or still, such as the + radar's Presence or Target sensor. It tells a visitor walking up + apart from a distance left over by someone earlier, and distances + only move a sequence forward while it's on. Without it, a reading + of 0 counts as nobody there, and the reading just before a + visitor crosses the first stage must be at most 30 s old. + default: "" + selector: + entity: + filter: &target_filter + - domain: binary_sensor + device_class: + - occupancy + - presence + - motion + + stages_section: + name: Stages + icon: mdi:walk + collapsed: false + input: + stages: + name: Stages + description: >- + Add one stage per light group. Each stage turns on when the + visitor comes within its distance of the sensor, in the sensor's + unit (inches or cm, for example). The stage with the largest distance starts the + sequence, so the order you add them in doesn't matter. A sequence + starts when a visitor walks in across that distance, so keep it a + little inside the radar's range, where it can see them coming. + + + LD2410 sensors measure in gates of about 75 cm (30 in), so space the + stages at least a gate apart; 150 cm (60 in) or more is more reliable. If + a visitor passes several stages between readings, those stages + turn on together. + + + Each stage uses the shared Stage look and Stage sound unless you + set its own color, brightness, effect or sound. + default: [] + selector: + object: + multiple: true + label_field: distance + fields: + distance: + label: Turns on within this distance (in the sensor's unit) + required: true + selector: + number: &distance_select + min: 0 + max: 10000 + step: any + mode: box + lights: + label: Lights + required: true + selector: + entity: + multiple: true + filter: + - domain: light + sound: + label: Sound (leave empty for the shared Stage sound) + selector: + media: + color_mode: + label: Color (leave empty for the Stage look) + selector: + select: &color_mode_select + mode: dropdown + options: + - label: RGB color + value: rgb + - label: Color temperature (white) + value: kelvin + - label: Don't change the color + value: none + rgb: + label: RGB color + selector: + color_rgb: + kelvin: + label: Color temperature + selector: + color_temp: &kelvin_select + unit: kelvin + min: 2000 + max: 6500 + brightness: + label: Brightness (leave empty for the Stage look) + selector: + number: &brightness_select + min: 1 + max: 100 + step: 1 + unit_of_measurement: "%" + mode: slider + effect: + label: Effect (leave empty for the Stage look) + selector: + select: &effect_select + mode: dropdown + custom_value: true + options: + - None + - Flicker + - Pulse + - Strobe + - Rainbow + - Color Wipe + - Scan + - Twinkle + - Random Twinkle + - Fireworks + - Effect A + - Effect B + - candle + - fire + - prism + - sparkle + - opal + - glisten + - underwater + - cosmos + - sunbeam + - enchant + + finale_section: + name: Finale + icon: mdi:door + collapsed: false + input: + finale_distance: + name: Finale distance + description: >- + Coming within this distance of the sensor plays the finale. Use + the sensor's unit and keep it below every stage distance. + default: 40 + selector: + number: *distance_select + finale_extra_lights: + name: Extra finale lights (optional) + description: >- + Lights that join the finale on top of the stage lights, such as a + porch light. + default: [] + selector: + entity: + multiple: true + filter: + - domain: light + finale_duration: + name: Finale length + description: How long the finale look stays on before the resting state. + default: 10 + selector: + number: + min: 1 + max: 300 + step: 1 + unit_of_measurement: s + mode: box + finale_sound: + name: Finale sound (optional) + default: {} + selector: + media: + finale_color_mode: + name: Finale color + default: rgb + selector: + select: *color_mode_select + finale_rgb: + name: Finale RGB color + description: Used when the color is set to RGB color. + default: [0, 0, 255] + selector: + color_rgb: + finale_kelvin: + name: Finale color temperature + description: Used when the color is set to Color temperature. + default: 3000 + selector: + color_temp: *kelvin_select + finale_brightness: + name: Finale brightness + default: 80 + selector: + number: *brightness_select + finale_effect: + name: Finale effect + description: &effect_description >- + Pick one or type the name exactly as the light lists it. Each light + only gets an effect it supports; the others just change color and + brightness. None stops a running effect. Strobe-style effects + faster than 3 flashes per second can trigger seizures in people + with photosensitive epilepsy. + default: Pulse + selector: + select: *effect_select + + stage_look_section: + name: Stage look and sound + icon: mdi:palette + description: How every stage looks and sounds, unless the stage sets its own. + collapsed: true + input: + stage_color_mode: + name: Stage color + default: rgb + selector: + select: *color_mode_select + stage_rgb: + name: Stage RGB color + description: Used when the color is set to RGB color. + default: [255, 100, 0] + selector: + color_rgb: + stage_kelvin: + name: Stage color temperature + description: Used when the color is set to Color temperature. + default: 3000 + selector: + color_temp: *kelvin_select + stage_brightness: + name: Stage brightness + default: 75 + selector: + number: *brightness_select + stage_effect: + name: Stage effect + description: *effect_description + default: Flicker + selector: + select: *effect_select + stage_sound: + name: Stage sound (optional) + description: Played each time a stage turns on, unless the stage has its own sound. + default: {} + selector: + media: + + end_section: + name: Resting state + icon: mdi:sleep + description: What the lights do after the finale, or after a visitor turns back. + collapsed: true + input: + end_mode: + name: Resting state + default: "off" + selector: + select: + options: + - label: Turn off + value: "off" + - label: Show the resting look below + value: look + - label: Go back to how they were before the sequence + value: restore + abandon_sound: + name: Turned-back sound (optional) + description: Played when a visitor leaves before reaching the finale. + default: {} + selector: + media: + end_color_mode: + name: Resting color + default: kelvin + selector: + select: *color_mode_select + end_rgb: + name: Resting RGB color + description: Used when the color is set to RGB color. + default: [255, 160, 60] + selector: + color_rgb: + end_kelvin: + name: Resting color temperature + description: Used when the color is set to Color temperature. + default: 2700 + selector: + color_temp: *kelvin_select + end_brightness: + name: Resting brightness + default: 40 + selector: + number: *brightness_select + end_effect: + name: Resting effect + description: *effect_description + default: None + selector: + select: *effect_select + + timing_section: + name: Timing + icon: mdi:timer-outline + collapsed: true + input: + step_timeout: + name: Time to reach the next stage + description: >- + After each stage turns on, the visitor has this long to come + within a later stage's distance. If they don't, the lit lights go + to the resting state. + default: 30 + selector: + number: + min: 5 + max: 600 + step: 1 + unit_of_measurement: s + mode: box + cooldown: + name: Cooldown + description: After a sequence ends, wait this long before another can start. + default: 10 + selector: + number: + min: 0 + max: 600 + step: 1 + unit_of_measurement: s + mode: box + transition: + name: Transition + description: Fade time when lights change. 0 changes them instantly. + default: 0 + selector: + number: + min: 0 + max: 10 + step: 0.5 + unit_of_measurement: s + mode: box + sound_delay: + name: Light delay after a sound + description: >- + Speakers take a moment to start a sound. When a step has a sound, + its lights wait this long after the sound is sent so the two land + together. Tune it by ear; 0 changes the lights right away. + default: 0 + selector: + number: + min: 0 + max: 3000 + step: 50 + unit_of_measurement: ms + mode: slider + + options_section: + name: Sound player and options + icon: mdi:cog + collapsed: true + input: + sound_player: + name: Sound player + description: >- + Plays every sound. Leave empty to use the player each sound was + picked from. With Music Assistant, pick the speaker's own player + rather than the Music Assistant one, so music ducks under the + sound instead of pausing. + default: "" + selector: + entity: + filter: + - domain: media_player + set_volume: + name: Set the volume during a sequence + description: >- + Sets the sound player's volume when a sequence starts and puts it + back when the sequence ends. This is the player's only volume, so + music playing on it changes too. Needs a Sound player above. + default: false + selector: + boolean: + sound_volume: + name: Sequence volume + default: 60 + selector: + number: + min: 0 + max: 100 + step: 1 + unit_of_measurement: "%" + mode: slider + enable_entity: + name: Enable switch (optional) + description: >- + Sequences only start while this is on, for example a Halloween + mode toggle. Leave empty to always run. + default: "" + selector: + entity: + filter: + - domain: + - input_boolean + - switch + - binary_sensor + pause_entities: + name: Switches to pause during a sequence (optional) + description: >- + Turned off while a sequence runs and back on afterwards if they + were on, for example a CAST-1's LED Strip Music Mode, which + otherwise takes over the strip when music starts or stops. + default: [] + selector: + entity: + multiple: true + filter: + - domain: + - switch + - input_boolean + +mode: single +max_exceeded: silent + +triggers: + # Every new distance reading; the conditions decide whether it starts one + - trigger: state + entity_id: !input distance_sensor + +variables: + stage_inputs: !input stages + dist_sensor: !input distance_sensor + presence_sensor: !input presence_sensor + finale_distance: !input finale_distance + finale_extra_lights: !input finale_extra_lights + finale_sound: !input finale_sound + stage_sound: !input stage_sound + abandon_sound: !input abandon_sound + end_mode: !input end_mode + transition_s: !input transition + sound_delay: !input sound_delay + sound_player: !input sound_player + set_volume: !input set_volume + sound_volume: !input sound_volume + enable_entity: !input enable_entity + pause_entities: !input pause_entities + stage_look: + color_mode: !input stage_color_mode + rgb: !input stage_rgb + kelvin: !input stage_kelvin + brightness: !input stage_brightness + effect: !input stage_effect + finale_look: + color_mode: !input finale_color_mode + rgb: !input finale_rgb + kelvin: !input finale_kelvin + brightness: !input finale_brightness + effect: !input finale_effect + end_look: + color_mode: !input end_color_mode + rgb: !input end_rgb + kelvin: !input end_kelvin + brightness: !input end_brightness + effect: !input end_effect + # Stages with a distance and lights, farthest first, each with its look + # filled in from the Stage look and its sound resolved to {id, type, player} + stages: >- + {%- set ns = namespace(out=[]) -%} + {%- for s in stage_inputs if s is mapping -%} + {%- set lights = s.get('lights') or [] -%} + {%- set lights = [lights] if lights is string else lights | list -%} + {%- set dist = s.get('distance') | float(0) -%} + {%- if dist > 0 and lights | count > 0 -%} + {%- set own_color = s.get('color_mode') not in [none, ''] -%} + {%- set effect = s.get('effect') -%} + {%- set look = { + 'color_mode': s.get('color_mode') if own_color else stage_look.color_mode, + 'rgb': s.get('rgb') if own_color and s.get('rgb') else stage_look.rgb, + 'kelvin': s.get('kelvin') if own_color and s.get('kelvin') else stage_look.kelvin, + 'brightness': s.get('brightness') if s.get('brightness') is number else stage_look.brightness, + 'effect': effect if effect is string and effect | trim != '' else stage_look.effect + } -%} + {%- set snd = s.get('sound') -%} + {%- set snd = snd if snd is mapping and snd.get('media_content_id') else stage_sound -%} + {%- set snd = snd if snd is mapping else {} -%} + {%- set ns.out = ns.out + [{ + 'distance': dist, + 'lights': lights, + 'look': look, + 'sound': { + 'id': snd.get('media_content_id') or '', + 'type': snd.get('media_content_type') or 'music', + 'player': sound_player or snd.get('entity_id') or '' + } + }] -%} + {%- endif -%} + {%- endfor -%} + {{ ns.out | sort(attribute='distance', reverse=true) }} + # light.turn_on data for the finale, resting state and each stage, in that + # order; the effect is added per light when the look is applied + look_data: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in [finale_look, end_look] + stages | map(attribute='look') | list -%} + {#- Only send a fade when one is set: ESPHome warns when an effect comes with any transition, even 0 -#} + {%- set d = {'brightness_pct': l.brightness | int(100)} -%} + {%- if transition_s | float(0) > 0 -%} + {%- set d = dict(d, transition=transition_s | float(0)) -%} + {%- endif -%} + {%- if l.color_mode == 'rgb' and l.rgb -%} + {%- set d = dict(d, rgb_color=l.rgb | list) -%} + {%- elif l.color_mode == 'kelvin' and l.kelvin -%} + {%- set d = dict(d, color_temp_kelvin=l.kelvin | int) -%} + {%- endif -%} + {%- set ns.out = ns.out + [d] -%} + {%- endfor -%} + {{ ns.out }} + all_lights: >- + {{ (stages | map(attribute='lights') | sum(start=[]) + finale_extra_lights) | unique | list }} + snapshot_scene: "porch_distance_sequence_{{ this.entity_id.split('.')[1] }}" + +conditions: + - condition: template + value_template: "{{ enable_entity == '' or is_state(enable_entity, 'on') }}" + - condition: template + value_template: "{{ stages | count > 0 and finale_distance | float(0) > 0 }}" + # Only a visitor walking in starts a sequence: the last reading was beyond + # the first stage and this one is inside it but short of the finale. + # Someone appearing at the door or walking away never reads that way. The + # far reading must also belong to this visitor, not be left over from an + # earlier one: the target sensor has stayed on since it was taken, or + # without one, it's at most 30 s old + - condition: template + value_template: >- + {%- set prev = trigger.from_state.state | float(0) if trigger.from_state else 0 -%} + {%- set cur = trigger.to_state.state | float(0) if trigger.to_state else 0 -%} + {%- set target = expand([presence_sensor]) | first if presence_sensor != '' else none -%} + {%- if not trigger.from_state or not trigger.to_state -%} + {%- set fresh = false -%} + {%- elif target -%} + {#- 2 s of slack: the target and distance readings can arrive in either order -#} + {%- set fresh = target.state == 'on' + and (target.last_changed - trigger.from_state.last_changed).total_seconds() <= 2 -%} + {%- else -%} + {%- set fresh = (trigger.to_state.last_changed - trigger.from_state.last_changed).total_seconds() <= 30 -%} + {%- endif -%} + {{ fresh and prev > stages[0].distance and 0 < cur <= stages[0].distance + and cur > finale_distance | float(0) }} + +actions: + - variables: + paused: >- + {{ expand(pause_entities) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }} + prev_volume: >- + {{ state_attr(sound_player, 'volume_level') if set_volume and sound_player != '' else none }} + - if: + - condition: template + value_template: "{{ paused | count > 0 }}" + then: + - action: homeassistant.turn_off + target: + entity_id: "{{ paused }}" + - if: + - condition: template + value_template: "{{ set_volume and sound_player != '' }}" + then: + - action: media_player.volume_set + target: + entity_id: "{{ sound_player }}" + data: + volume_level: "{{ (sound_volume | float(60)) / 100 }}" + continue_on_error: true + - if: + - condition: template + value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" + then: + - action: scene.create + data: + scene_id: "{{ snapshot_scene }}" + snapshot_entities: "{{ all_lights }}" + + # idx is the last lit stage (-1 before the first); outcome becomes finale + # or abandon. The first pass lights the first stage without waiting. + # A reading counts only while it's above 0 and the target sensor is on + - variables: + idx: -1 + outcome: "" + - repeat: + while: + - condition: template + value_template: "{{ outcome == '' }}" + sequence: + - wait_template: >- + {%- set d = states(dist_sensor) | float(0) -%} + {%- set ok = d > 0 and (presence_sensor == '' or is_state(presence_sensor, 'on')) -%} + {%- set nxt = stages[idx + 1].distance if idx + 1 < stages | count else finale_distance | float(0) -%} + {{ idx < 0 or (ok and d <= nxt) }} + timeout: !input step_timeout + continue_on_timeout: true + - variables: + reading: >- + {%- set d = states(dist_sensor) | float(0) -%} + {{ d if d > 0 and (presence_sensor == '' or is_state(presence_sensor, 'on')) else 0 }} + - choose: + - conditions: + - condition: template + value_template: "{{ not wait.completed }}" + sequence: + - variables: + outcome: abandon + - conditions: + - condition: template + value_template: "{{ idx >= 0 and reading > 0 and reading <= finale_distance | float(0) }}" + sequence: + # Skipped stages join the finale directly + - variables: + idx: "{{ stages | count - 1 }}" + outcome: finale + default: + # Jump to the closest stage the visitor is within, lighting any + # skipped ones. The first pass always lights at least the first + - variables: + target_idx: >- + {%- set ns = namespace(j=[idx, 0] | max) -%} + {%- if reading > 0 -%} + {%- for s in stages -%} + {%- if loop.index0 > idx and reading <= s.distance -%} + {%- set ns.j = loop.index0 -%} + {%- endif -%} + {%- endfor -%} + {%- endif -%} + {{ ns.j }} + - if: + - condition: template + value_template: "{{ target_idx > idx }}" + then: + - variables: + snd: "{{ stages[target_idx].sound }}" + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for i in range(idx + 1, target_idx + 1) -%} + {%- for l in stages[i].lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[i + 2], 'effect': stages[i].look.effect}] -%} + {%- endfor -%} + {%- endfor -%} + {{ ns.out }} + # play_media can hold the run until the sound ends, so the + # sound gets its own branch and the lights don't wait for it + - parallel: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - action: media_player.play_media + target: + entity_id: "{{ snd.player }}" + data: + media_content_id: "{{ snd.id }}" + media_content_type: "{{ snd.type }}" + announce: true + continue_on_error: true + - sequence: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - delay: + milliseconds: "{{ sound_delay | int(0) }}" + - repeat: &apply_jobs + for_each: "{{ jobs }}" + sequence: + # The look's effect, matched to the name this light uses + # for it; None picks the light's own "None" or "off" + - action: light.turn_on + target: + entity_id: "{{ repeat.item.light }}" + data: >- + {%- set fx = state_attr(repeat.item.light, 'effect_list') or [] -%} + {%- set want = (repeat.item.effect or 'None') | string | trim | lower -%} + {%- set names = ['none', 'off'] if want in ['', 'none', 'off'] else [want] -%} + {%- set ns = namespace(e='') -%} + {%- for f in fx -%} + {%- if ns.e == '' and (f | string | lower) in names -%} + {%- set ns.e = f -%} + {%- endif -%} + {%- endfor -%} + {{ dict(repeat.item.data, effect=ns.e) if ns.e else repeat.item.data }} + continue_on_error: true + - variables: + idx: "{{ target_idx }}" + + - variables: + lit_lights: >- + {{ stages[:idx + 1] | map(attribute='lights') | sum(start=[]) | unique | list }} + raw_sound: "{{ finale_sound if outcome == 'finale' else abandon_sound }}" + - variables: + end_lights: >- + {{ (lit_lights + finale_extra_lights) | unique | list if outcome == 'finale' else lit_lights }} + snd: + id: "{{ (raw_sound.get('media_content_id') if raw_sound is mapping else '') or '' }}" + type: "{{ (raw_sound.get('media_content_type') if raw_sound is mapping else '') or 'music' }}" + player: >- + {{ sound_player or (raw_sound.get('entity_id') if raw_sound is mapping else '') or '' }} + + # The finale or turned-back sound plays in its own branch while the lights + # run the finale and resting state + - parallel: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - action: media_player.play_media + target: + entity_id: "{{ snd.player }}" + data: + media_content_id: "{{ snd.id }}" + media_content_type: "{{ snd.type }}" + announce: true + continue_on_error: true + - sequence: + - if: + - condition: template + value_template: "{{ outcome == 'finale' and snd.id != '' and snd.player != '' }}" + then: + - delay: + milliseconds: "{{ sound_delay | int(0) }}" + - if: + - condition: template + value_template: "{{ outcome == 'finale' }}" + then: + - variables: + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in end_lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[0], 'effect': finale_look.effect}] -%} + {%- endfor -%} + {{ ns.out }} + - repeat: *apply_jobs + - delay: !input finale_duration + + # Resting state + - choose: + - conditions: + - condition: template + value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" + sequence: + - action: scene.turn_on + target: + entity_id: "scene.{{ snapshot_scene }}" + data: + transition: "{{ transition_s | float(0) }}" + continue_on_error: true + - conditions: + - condition: template + value_template: "{{ end_mode == 'look' }}" + sequence: + - variables: + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in end_lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[1], 'effect': end_look.effect}] -%} + {%- endfor -%} + {{ ns.out }} + - repeat: *apply_jobs + default: + - if: + - condition: template + value_template: "{{ end_lights | count > 0 }}" + then: + - action: light.turn_off + target: + entity_id: "{{ end_lights }}" + data: + transition: "{{ transition_s | float(0) }}" + continue_on_error: true + + - if: + - condition: template + value_template: "{{ paused | count > 0 }}" + then: + - action: homeassistant.turn_on + target: + entity_id: "{{ paused }}" + - if: + - condition: template + value_template: "{{ prev_volume is number }}" + then: + - action: media_player.volume_set + target: + entity_id: "{{ sound_player }}" + data: + volume_level: "{{ prev_volume }}" + continue_on_error: true + - delay: !input cooldown diff --git a/Blueprints/Light-Sequence-Motion-Based.yaml b/Blueprints/Light-Sequence-Motion-Based.yaml new file mode 100644 index 0000000..afecb91 --- /dev/null +++ b/Blueprints/Light-Sequence-Motion-Based.yaml @@ -0,0 +1,903 @@ +blueprint: + name: Light Sequence (Motion-Based) + description: >- + Lights a path in stages when a motion sensor (PIR) sees a visitor. With + one sensor the whole show runs on timers: motion starts it, each stage + turns on a set time after the one before, then the finale plays and all + the lights go to the resting state. + + + With more sensors along the path, any stage or the finale can wait for + its own sensor instead of a timer. If the visitor doesn't reach that + sensor in time, the lit lights go to the resting state early. + + + With more than one sensor, sequences only start when the visitor walks + toward the door: someone setting off the door-side sensors first, on the + way out, doesn't start one. + + + Works with any Home Assistant lights and any on/off motion or occupancy + sensor. Sounds play as announcements, so music playing on the same + speaker ducks under them instead of stopping. + domain: automation + author: Apollo Automation + homeassistant: + min_version: 2025.7.0 + input: + start_section: + name: Start + icon: mdi:motion-sensor + collapsed: false + input: + start_sensors: + name: Start motion sensor + description: >- + Motion here starts a sequence. Usually the sensor farthest from the + door. Pick more than one to start from any of them. + selector: + entity: + multiple: true + filter: &motion_filter + - domain: binary_sensor + device_class: + - motion + - occupancy + - presence + + stages_section: + name: Stages + icon: mdi:walk + collapsed: false + input: + stages: + name: Stages + description: >- + Add one stage per light group, in the order they should turn on. + A stage with a motion sensor waits for that sensor. A stage without + one turns on after its wait time: for the first stage, counted from + the start motion; for the others, from the stage before. An empty + wait time uses the First stage or Later stage wait time under + Timing. + + + If a later stage's sensor sees the visitor first, the stages in + between turn on with it. Use a different sensor for each stage; + a sensor that's still on from an earlier stage moves the sequence + on straight away. + + + Each stage uses the shared Stage look and Stage sound unless you + set its own color, brightness, effect or sound. + default: [] + selector: + object: + multiple: true + label_field: lights + fields: + lights: + label: Lights + required: true + selector: + entity: + multiple: true + filter: + - domain: light + sensor: + label: Wait for this motion sensor (leave empty to use a timer) + selector: + entity: + filter: *motion_filter + delay: + label: Wait time when there's no sensor (leave empty for the default) + selector: + number: &delay_select + min: 0 + max: 600 + step: 0.5 + unit_of_measurement: s + mode: box + sound: + label: Sound (leave empty for the shared Stage sound) + selector: + media: + color_mode: + label: Color (leave empty for the Stage look) + selector: + select: &color_mode_select + mode: dropdown + options: + - label: RGB color + value: rgb + - label: Color temperature (white) + value: kelvin + - label: Don't change the color + value: none + rgb: + label: RGB color + selector: + color_rgb: + kelvin: + label: Color temperature + selector: + color_temp: &kelvin_select + unit: kelvin + min: 2000 + max: 6500 + brightness: + label: Brightness (leave empty for the Stage look) + selector: + number: &brightness_select + min: 1 + max: 100 + step: 1 + unit_of_measurement: "%" + mode: slider + effect: + label: Effect (leave empty for the Stage look) + selector: + select: &effect_select + mode: dropdown + custom_value: true + options: + - None + - Flicker + - Pulse + - Strobe + - Rainbow + - Color Wipe + - Scan + - Twinkle + - Random Twinkle + - Fireworks + - Effect A + - Effect B + - candle + - fire + - prism + - sparkle + - opal + - glisten + - underwater + - cosmos + - sunbeam + - enchant + + finale_section: + name: Finale + icon: mdi:door + collapsed: false + input: + finale_sensor: + name: Finale motion sensor (optional) + description: >- + The finale waits for this sensor, usually the one by the door. + Leave empty to play the finale on a timer after the last stage. + default: "" + selector: + entity: + filter: *motion_filter + finale_delay: + name: Finale wait time + description: >- + Without a finale sensor, the finale plays this long after the last + stage turns on. + default: 5 + selector: + number: *delay_select + finale_extra_lights: + name: Extra finale lights (optional) + description: >- + Lights that join the finale on top of the stage lights, such as a + porch light. + default: [] + selector: + entity: + multiple: true + filter: + - domain: light + finale_duration: + name: Finale length + description: How long the finale look stays on before the resting state. + default: 10 + selector: + number: + min: 1 + max: 300 + step: 1 + unit_of_measurement: s + mode: box + finale_sound: + name: Finale sound (optional) + default: {} + selector: + media: + finale_color_mode: + name: Finale color + default: rgb + selector: + select: *color_mode_select + finale_rgb: + name: Finale RGB color + description: Used when the color is set to RGB color. + default: [0, 0, 255] + selector: + color_rgb: + finale_kelvin: + name: Finale color temperature + description: Used when the color is set to Color temperature. + default: 3000 + selector: + color_temp: *kelvin_select + finale_brightness: + name: Finale brightness + default: 80 + selector: + number: *brightness_select + finale_effect: + name: Finale effect + description: &effect_description >- + Pick one or type the name exactly as the light lists it. Each light + only gets an effect it supports; the others just change color and + brightness. None stops a running effect. Strobe-style effects + faster than 3 flashes per second can trigger seizures in people + with photosensitive epilepsy. + default: Pulse + selector: + select: *effect_select + + stage_look_section: + name: Stage look and sound + icon: mdi:palette + description: How every stage looks and sounds, unless the stage sets its own. + collapsed: true + input: + stage_color_mode: + name: Stage color + default: rgb + selector: + select: *color_mode_select + stage_rgb: + name: Stage RGB color + description: Used when the color is set to RGB color. + default: [255, 100, 0] + selector: + color_rgb: + stage_kelvin: + name: Stage color temperature + description: Used when the color is set to Color temperature. + default: 3000 + selector: + color_temp: *kelvin_select + stage_brightness: + name: Stage brightness + default: 75 + selector: + number: *brightness_select + stage_effect: + name: Stage effect + description: *effect_description + default: Flicker + selector: + select: *effect_select + stage_sound: + name: Stage sound (optional) + description: Played each time a stage turns on, unless the stage has its own sound. + default: {} + selector: + media: + + end_section: + name: Resting state + icon: mdi:sleep + description: What the lights do after the finale, or after a visitor turns back. + collapsed: true + input: + end_mode: + name: Resting state + default: "off" + selector: + select: + options: + - label: Turn off + value: "off" + - label: Show the resting look below + value: look + - label: Go back to how they were before the sequence + value: restore + abandon_sound: + name: Turned-back sound (optional) + description: >- + Played when a visitor doesn't reach a stage's or the finale's + sensor in time. + default: {} + selector: + media: + end_color_mode: + name: Resting color + default: kelvin + selector: + select: *color_mode_select + end_rgb: + name: Resting RGB color + description: Used when the color is set to RGB color. + default: [255, 160, 60] + selector: + color_rgb: + end_kelvin: + name: Resting color temperature + description: Used when the color is set to Color temperature. + default: 2700 + selector: + color_temp: *kelvin_select + end_brightness: + name: Resting brightness + default: 40 + selector: + number: *brightness_select + end_effect: + name: Resting effect + description: *effect_description + default: None + selector: + select: *effect_select + + timing_section: + name: Timing + icon: mdi:timer-outline + collapsed: true + input: + first_delay: + name: First stage wait time + description: >- + How long after the start motion the first stage turns on, when it + has no sensor and doesn't set its own wait time. 0 turns it on + right away. + default: 0 + selector: + number: *delay_select + default_delay: + name: Later stage wait time + description: >- + How long each later stage without a sensor waits after the stage + before it, unless it sets its own wait time. + default: 3 + selector: + number: *delay_select + step_timeout: + name: Time to reach a sensor + description: >- + How long a stage or the finale waits for its own sensor. If the + visitor doesn't set it off in time, the lit lights go to the + resting state. + default: 30 + selector: + number: + min: 5 + max: 600 + step: 1 + unit_of_measurement: s + mode: box + start_guard: + name: Reverse walk guard + description: >- + A sequence only starts if every stage and finale sensor has been + clear for at least this long, so someone walking away from the + door doesn't set it off on the way out. Set it to roughly the time + it takes to walk from the door to the start sensor. Only works + with more than one sensor. + default: 15 + selector: + number: + min: 0 + max: 120 + step: 1 + unit_of_measurement: s + mode: box + rearm: + name: Quiet time before a new show + description: >- + The start sensor must have seen no motion for this long before it + can start another show. A visitor waiting at the door keeps moving + now and then, and each new motion would otherwise replay the + show. The sensor's own hold time after motion counts as motion. + default: 20 + selector: + number: + min: 0 + max: 600 + step: 1 + unit_of_measurement: s + mode: box + cooldown: + name: Cooldown + description: After a sequence ends, wait this long before another can start. + default: 10 + selector: + number: + min: 0 + max: 600 + step: 1 + unit_of_measurement: s + mode: box + transition: + name: Transition + description: Fade time when lights change. 0 changes them instantly. + default: 0 + selector: + number: + min: 0 + max: 10 + step: 0.5 + unit_of_measurement: s + mode: box + sound_delay: + name: Light delay after a sound + description: >- + Speakers take a moment to start a sound. When a step has a sound, + its lights wait this long after the sound is sent so the two land + together. Tune it by ear; 0 changes the lights right away. + default: 0 + selector: + number: + min: 0 + max: 3000 + step: 50 + unit_of_measurement: ms + mode: slider + + options_section: + name: Sound player and options + icon: mdi:cog + collapsed: true + input: + sound_player: + name: Sound player + description: >- + Plays every sound. Leave empty to use the player each sound was + picked from. With Music Assistant, pick the speaker's own player + rather than the Music Assistant one, so music ducks under the + sound instead of pausing. + default: "" + selector: + entity: + filter: + - domain: media_player + set_volume: + name: Set the volume during a sequence + description: >- + Sets the sound player's volume when a sequence starts and puts it + back when the sequence ends. This is the player's only volume, so + music playing on it changes too. Needs a Sound player above. + default: false + selector: + boolean: + sound_volume: + name: Sequence volume + default: 60 + selector: + number: + min: 0 + max: 100 + step: 1 + unit_of_measurement: "%" + mode: slider + enable_entity: + name: Enable switch (optional) + description: >- + Sequences only start while this is on, for example a Halloween + mode toggle. Leave empty to always run. + default: "" + selector: + entity: + filter: + - domain: + - input_boolean + - switch + - binary_sensor + pause_entities: + name: Switches to pause during a sequence (optional) + description: >- + Turned off while a sequence runs and back on afterwards if they + were on, for example a CAST-1's LED Strip Music Mode, which + otherwise takes over the strip when music starts or stops. + default: [] + selector: + entity: + multiple: true + filter: + - domain: + - switch + - input_boolean + +mode: single +max_exceeded: silent + +triggers: + - trigger: state + entity_id: !input start_sensors + from: "off" + to: "on" + +variables: + start_input: !input start_sensors + stage_inputs: !input stages + finale_sensor: !input finale_sensor + finale_delay: !input finale_delay + first_delay: !input first_delay + default_delay: !input default_delay + finale_extra_lights: !input finale_extra_lights + finale_sound: !input finale_sound + stage_sound: !input stage_sound + abandon_sound: !input abandon_sound + end_mode: !input end_mode + start_guard: !input start_guard + rearm: !input rearm + step_timeout: !input step_timeout + transition_s: !input transition + sound_delay: !input sound_delay + sound_player: !input sound_player + set_volume: !input set_volume + sound_volume: !input sound_volume + enable_entity: !input enable_entity + pause_entities: !input pause_entities + stage_look: + color_mode: !input stage_color_mode + rgb: !input stage_rgb + kelvin: !input stage_kelvin + brightness: !input stage_brightness + effect: !input stage_effect + finale_look: + color_mode: !input finale_color_mode + rgb: !input finale_rgb + kelvin: !input finale_kelvin + brightness: !input finale_brightness + effect: !input finale_effect + end_look: + color_mode: !input end_color_mode + rgb: !input end_rgb + kelvin: !input end_kelvin + brightness: !input end_brightness + effect: !input end_effect + start_list: "{{ [start_input] if start_input is string else start_input | list }}" + # Stages with lights, each with its sensor and wait time, its look filled + # in from the Stage look and its sound resolved to {id, type, player} + stages: >- + {%- set ns = namespace(out=[]) -%} + {%- for s in stage_inputs if s is mapping -%} + {%- set lights = s.get('lights') or [] -%} + {%- set lights = [lights] if lights is string else lights | list -%} + {%- if lights | count > 0 -%} + {%- set own_color = s.get('color_mode') not in [none, ''] -%} + {%- set effect = s.get('effect') -%} + {%- set look = { + 'color_mode': s.get('color_mode') if own_color else stage_look.color_mode, + 'rgb': s.get('rgb') if own_color and s.get('rgb') else stage_look.rgb, + 'kelvin': s.get('kelvin') if own_color and s.get('kelvin') else stage_look.kelvin, + 'brightness': s.get('brightness') if s.get('brightness') is number else stage_look.brightness, + 'effect': effect if effect is string and effect | trim != '' else stage_look.effect + } -%} + {%- set snd = s.get('sound') -%} + {%- set snd = snd if snd is mapping and snd.get('media_content_id') else stage_sound -%} + {%- set snd = snd if snd is mapping else {} -%} + {%- set ns.out = ns.out + [{ + 'sensor': s.get('sensor') or '', + 'delay': s.get('delay') if s.get('delay') is number + else (first_delay if ns.out | count == 0 else default_delay) | float(0), + 'lights': lights, + 'look': look, + 'sound': { + 'id': snd.get('media_content_id') or '', + 'type': snd.get('media_content_type') or 'music', + 'player': sound_player or snd.get('entity_id') or '' + } + }] -%} + {%- endif -%} + {%- endfor -%} + {{ ns.out }} + # The sensor of each step, stages then the finale; '' for a timed step + step_sensors: "{{ stages | map(attribute='sensor') | list + [finale_sensor or ''] }}" + # light.turn_on data for the finale, resting state and each stage, in that + # order; the effect is added per light when the look is applied + look_data: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in [finale_look, end_look] + stages | map(attribute='look') | list -%} + {#- Only send a fade when one is set: ESPHome warns when an effect comes with any transition, even 0 -#} + {%- set d = {'brightness_pct': l.brightness | int(100)} -%} + {%- if transition_s | float(0) > 0 -%} + {%- set d = dict(d, transition=transition_s | float(0)) -%} + {%- endif -%} + {%- if l.color_mode == 'rgb' and l.rgb -%} + {%- set d = dict(d, rgb_color=l.rgb | list) -%} + {%- elif l.color_mode == 'kelvin' and l.kelvin -%} + {%- set d = dict(d, color_temp_kelvin=l.kelvin | int) -%} + {%- endif -%} + {%- set ns.out = ns.out + [d] -%} + {%- endfor -%} + {{ ns.out }} + all_lights: >- + {{ (stages | map(attribute='lights') | sum(start=[]) + finale_extra_lights) | unique | list }} + snapshot_scene: "porch_motion_sequence_{{ this.entity_id.split('.')[1] }}" + +conditions: + - condition: template + value_template: "{{ enable_entity == '' or is_state(enable_entity, 'on') }}" + - condition: template + value_template: "{{ stages | count > 0 }}" + # The start sensor was clear long enough before this motion: a new arrival, + # not a visitor still waiting at the door + - condition: template + value_template: >- + {{ not trigger.from_state or not trigger.to_state + or (trigger.to_state.last_changed - trigger.from_state.last_changed).total_seconds() + >= rearm | float(0) }} + # Reverse walk guard: every stage and finale sensor other than the start + # sensors has been clear for a while, so the visitor didn't come from the door + - condition: template + value_template: >- + {%- set others = step_sensors | reject('eq', '') | reject('in', start_list) | unique | list -%} + {%- set ns = namespace(ok=true) -%} + {%- for s in expand(others) -%} + {%- if s.state == 'on' or (now() - s.last_changed).total_seconds() < start_guard | float(0) -%} + {%- set ns.ok = false -%} + {%- endif -%} + {%- endfor -%} + {{ ns.ok }} + +actions: + # Pausing switches, the volume and the snapshot wait until the first lights + # change, so a passerby who never reaches a first-stage sensor touches nothing + - variables: + started: false + paused: [] + prev_volume: null + + # idx is the last lit stage (-1 before the first). Each pass waits for the + # next step (the next stage, or the finale after the last one): for its + # sensor, or for its wait time when it has none. A later step's sensor + # going on ends the wait early and jumps ahead. outcome becomes finale or + # abandon + - variables: + idx: -1 + outcome: "" + - repeat: + while: + - condition: template + value_template: "{{ outcome == '' }}" + sequence: + - variables: + nstep: "{{ idx + 1 }}" + next_sensor: "{{ step_sensors[idx + 1] }}" + next_delay: >- + {{ (stages[idx + 1].delay if idx + 1 < stages | count else finale_delay) | float(0) }} + later_sensors: "{{ step_sensors[idx + 1:] | reject('eq', '') | unique | list }}" + - wait_template: >- + {{ (next_sensor == '' and next_delay <= 0) + or expand(later_sensors) | selectattr('state', 'eq', 'on') | list | count > 0 }} + timeout: + seconds: "{{ step_timeout if next_sensor != '' else next_delay }}" + continue_on_timeout: true + - choose: + - conditions: + - condition: template + value_template: "{{ not wait.completed and next_sensor != '' }}" + sequence: + - variables: + outcome: abandon + default: + # The furthest step whose sensor is on, or the next step when + # its timer ran out + - variables: + target: >- + {%- set ns = namespace(t=nstep) -%} + {%- for s in step_sensors -%} + {%- if loop.index0 > nstep and s != '' and is_state(s, 'on') -%} + {%- set ns.t = loop.index0 -%} + {%- endif -%} + {%- endfor -%} + {{ ns.t }} + - if: + - condition: template + value_template: "{{ not started }}" + then: + - variables: + started: true + paused: >- + {{ expand(pause_entities) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }} + prev_volume: >- + {{ state_attr(sound_player, 'volume_level') if set_volume and sound_player != '' else none }} + - if: + - condition: template + value_template: "{{ paused | count > 0 }}" + then: + - action: homeassistant.turn_off + target: + entity_id: "{{ paused }}" + - if: + - condition: template + value_template: "{{ set_volume and sound_player != '' }}" + then: + - action: media_player.volume_set + target: + entity_id: "{{ sound_player }}" + data: + volume_level: "{{ (sound_volume | float(60)) / 100 }}" + continue_on_error: true + - if: + - condition: template + value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" + then: + - action: scene.create + data: + scene_id: "{{ snapshot_scene }}" + snapshot_entities: "{{ all_lights }}" + - if: + - condition: template + value_template: "{{ target >= stages | count }}" + then: + # Skipped stages join the finale directly + - variables: + idx: "{{ stages | count - 1 }}" + outcome: finale + else: + - variables: + snd: "{{ stages[target].sound }}" + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for i in range(idx + 1, target + 1) -%} + {%- for l in stages[i].lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[i + 2], 'effect': stages[i].look.effect}] -%} + {%- endfor -%} + {%- endfor -%} + {{ ns.out }} + # play_media can hold the run until the sound ends, so the + # sound gets its own branch and the lights don't wait for it + - parallel: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - action: media_player.play_media + target: + entity_id: "{{ snd.player }}" + data: + media_content_id: "{{ snd.id }}" + media_content_type: "{{ snd.type }}" + announce: true + continue_on_error: true + - sequence: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - delay: + milliseconds: "{{ sound_delay | int(0) }}" + - repeat: &apply_jobs + for_each: "{{ jobs }}" + sequence: + # The look's effect, matched to the name this light uses + # for it; None picks the light's own "None" or "off" + - action: light.turn_on + target: + entity_id: "{{ repeat.item.light }}" + data: >- + {%- set fx = state_attr(repeat.item.light, 'effect_list') or [] -%} + {%- set want = (repeat.item.effect or 'None') | string | trim | lower -%} + {%- set names = ['none', 'off'] if want in ['', 'none', 'off'] else [want] -%} + {%- set ns = namespace(e='') -%} + {%- for f in fx -%} + {%- if ns.e == '' and (f | string | lower) in names -%} + {%- set ns.e = f -%} + {%- endif -%} + {%- endfor -%} + {{ dict(repeat.item.data, effect=ns.e) if ns.e else repeat.item.data }} + continue_on_error: true + - variables: + idx: "{{ target }}" + + - variables: + lit_lights: >- + {{ stages[:idx + 1] | map(attribute='lights') | sum(start=[]) | unique | list }} + - variables: + # No turned-back sound when the visitor never reached the first stage + raw_sound: >- + {{ finale_sound if outcome == 'finale' else (abandon_sound if lit_lights | count > 0 else {}) }} + end_lights: >- + {{ (lit_lights + finale_extra_lights) | unique | list if outcome == 'finale' else lit_lights }} + - variables: + snd: + id: "{{ (raw_sound.get('media_content_id') if raw_sound is mapping else '') or '' }}" + type: "{{ (raw_sound.get('media_content_type') if raw_sound is mapping else '') or 'music' }}" + player: >- + {{ sound_player or (raw_sound.get('entity_id') if raw_sound is mapping else '') or '' }} + + # The finale or turned-back sound plays in its own branch while the lights + # run the finale and resting state + - parallel: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - action: media_player.play_media + target: + entity_id: "{{ snd.player }}" + data: + media_content_id: "{{ snd.id }}" + media_content_type: "{{ snd.type }}" + announce: true + continue_on_error: true + - sequence: + - if: + - condition: template + value_template: "{{ outcome == 'finale' and snd.id != '' and snd.player != '' }}" + then: + - delay: + milliseconds: "{{ sound_delay | int(0) }}" + - if: + - condition: template + value_template: "{{ outcome == 'finale' }}" + then: + - variables: + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in end_lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[0], 'effect': finale_look.effect}] -%} + {%- endfor -%} + {{ ns.out }} + - repeat: *apply_jobs + - delay: !input finale_duration + + # Resting state + - choose: + - conditions: + - condition: template + value_template: "{{ end_mode == 'restore' and started and all_lights | count > 0 }}" + sequence: + - action: scene.turn_on + target: + entity_id: "scene.{{ snapshot_scene }}" + data: + transition: "{{ transition_s | float(0) }}" + continue_on_error: true + - conditions: + - condition: template + value_template: "{{ end_mode == 'look' }}" + sequence: + - variables: + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in end_lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[1], 'effect': end_look.effect}] -%} + {%- endfor -%} + {{ ns.out }} + - repeat: *apply_jobs + default: + - if: + - condition: template + value_template: "{{ end_lights | count > 0 }}" + then: + - action: light.turn_off + target: + entity_id: "{{ end_lights }}" + data: + transition: "{{ transition_s | float(0) }}" + continue_on_error: true + + - if: + - condition: template + value_template: "{{ paused | count > 0 }}" + then: + - action: homeassistant.turn_on + target: + entity_id: "{{ paused }}" + - if: + - condition: template + value_template: "{{ prev_volume is number }}" + then: + - action: media_player.volume_set + target: + entity_id: "{{ sound_player }}" + data: + volume_level: "{{ prev_volume }}" + continue_on_error: true + - delay: !input cooldown diff --git a/Blueprints/Light-Sequence-Porch-Zone-Based.yaml b/Blueprints/Light-Sequence-Porch-Zone-Based.yaml new file mode 100644 index 0000000..65fc162 --- /dev/null +++ b/Blueprints/Light-Sequence-Porch-Zone-Based.yaml @@ -0,0 +1,781 @@ +blueprint: + name: Light Sequence (Zone-Based) + description: >- + Lights a path in stages as a visitor walks through presence zones toward + the door. Each zone can be any on/off occupancy sensor, such as a radar + zone (LD2450 with Zone Mapper, for example) or a motion sensor. + + + Entering the first stage's zone turns on its lights. Each later zone + turns on its own lights while the earlier ones stay on. Reaching the + finale zone switches every lit light to the finale look, then all of + them go to the resting state. If the visitor doesn't reach the next zone + in time, the lit lights go to the resting state early. + + + Stages only advance toward the door. Walking out through the zones in + reverse doesn't start a sequence. + + + Works with any Home Assistant lights. Sounds play as announcements, so + music playing on the same speaker ducks under them instead of stopping. + domain: automation + author: Apollo Automation + homeassistant: + min_version: 2025.7.0 + input: + stages_section: + name: Stages + icon: mdi:walk + collapsed: false + input: + stages: + name: Stages + description: >- + Add one stage per zone, in the order a visitor walks through them + toward the door. The first stage's zone starts the sequence. If a + visitor reaches a later zone first, the stages in between turn on + with it. + + + Each stage uses the shared Stage look and Stage sound unless you + set its own color, brightness, effect or sound. + default: [] + selector: + object: + multiple: true + label_field: zone + fields: + zone: + label: Zone + required: true + selector: + entity: + filter: &zone_filter + - domain: binary_sensor + device_class: + - occupancy + - presence + - motion + lights: + label: Lights + required: true + selector: + entity: + multiple: true + filter: + - domain: light + sound: + label: Sound (leave empty for the shared Stage sound) + selector: + media: + color_mode: + label: Color (leave empty for the Stage look) + selector: + select: &color_mode_select + mode: dropdown + options: + - label: RGB color + value: rgb + - label: Color temperature (white) + value: kelvin + - label: Don't change the color + value: none + rgb: + label: RGB color + selector: + color_rgb: + kelvin: + label: Color temperature + selector: + color_temp: &kelvin_select + unit: kelvin + min: 2000 + max: 6500 + brightness: + label: Brightness (leave empty for the Stage look) + selector: + number: &brightness_select + min: 1 + max: 100 + step: 1 + unit_of_measurement: "%" + mode: slider + effect: + label: Effect (leave empty for the Stage look) + selector: + select: &effect_select + mode: dropdown + custom_value: true + options: + - None + - Flicker + - Pulse + - Strobe + - Rainbow + - Color Wipe + - Scan + - Twinkle + - Random Twinkle + - Fireworks + - Effect A + - Effect B + - candle + - fire + - prism + - sparkle + - opal + - glisten + - underwater + - cosmos + - sunbeam + - enchant + + finale_section: + name: Finale + icon: mdi:door + collapsed: false + input: + finale_zone: + name: Finale zone + description: The zone by the door. Entering it plays the finale. + default: "" + selector: + entity: + filter: *zone_filter + finale_extra_lights: + name: Extra finale lights (optional) + description: >- + Lights that join the finale on top of the stage lights, such as a + porch light. + default: [] + selector: + entity: + multiple: true + filter: + - domain: light + finale_duration: + name: Finale length + description: How long the finale look stays on before the resting state. + default: 10 + selector: + number: + min: 1 + max: 300 + step: 1 + unit_of_measurement: s + mode: box + finale_sound: + name: Finale sound (optional) + default: {} + selector: + media: + finale_color_mode: + name: Finale color + default: rgb + selector: + select: *color_mode_select + finale_rgb: + name: Finale RGB color + description: Used when the color is set to RGB color. + default: [0, 0, 255] + selector: + color_rgb: + finale_kelvin: + name: Finale color temperature + description: Used when the color is set to Color temperature. + default: 3000 + selector: + color_temp: *kelvin_select + finale_brightness: + name: Finale brightness + default: 80 + selector: + number: *brightness_select + finale_effect: + name: Finale effect + description: &effect_description >- + Pick one or type the name exactly as the light lists it. Each light + only gets an effect it supports; the others just change color and + brightness. None stops a running effect. Strobe-style effects + faster than 3 flashes per second can trigger seizures in people + with photosensitive epilepsy. + default: Pulse + selector: + select: *effect_select + + stage_look_section: + name: Stage look and sound + icon: mdi:palette + description: How every stage looks and sounds, unless the stage sets its own. + collapsed: true + input: + stage_color_mode: + name: Stage color + default: rgb + selector: + select: *color_mode_select + stage_rgb: + name: Stage RGB color + description: Used when the color is set to RGB color. + default: [255, 100, 0] + selector: + color_rgb: + stage_kelvin: + name: Stage color temperature + description: Used when the color is set to Color temperature. + default: 3000 + selector: + color_temp: *kelvin_select + stage_brightness: + name: Stage brightness + default: 75 + selector: + number: *brightness_select + stage_effect: + name: Stage effect + description: *effect_description + default: Flicker + selector: + select: *effect_select + stage_sound: + name: Stage sound (optional) + description: Played each time a stage turns on, unless the stage has its own sound. + default: {} + selector: + media: + + end_section: + name: Resting state + icon: mdi:sleep + description: What the lights do after the finale, or after a visitor turns back. + collapsed: true + input: + end_mode: + name: Resting state + default: "off" + selector: + select: + options: + - label: Turn off + value: "off" + - label: Show the resting look below + value: look + - label: Go back to how they were before the sequence + value: restore + abandon_sound: + name: Turned-back sound (optional) + description: Played when a visitor leaves before reaching the finale. + default: {} + selector: + media: + end_color_mode: + name: Resting color + default: kelvin + selector: + select: *color_mode_select + end_rgb: + name: Resting RGB color + description: Used when the color is set to RGB color. + default: [255, 160, 60] + selector: + color_rgb: + end_kelvin: + name: Resting color temperature + description: Used when the color is set to Color temperature. + default: 2700 + selector: + color_temp: *kelvin_select + end_brightness: + name: Resting brightness + default: 40 + selector: + number: *brightness_select + end_effect: + name: Resting effect + description: *effect_description + default: None + selector: + select: *effect_select + + timing_section: + name: Timing + icon: mdi:timer-outline + collapsed: true + input: + step_timeout: + name: Time to reach the next zone + description: >- + After each stage turns on, the visitor has this long to reach a + later zone. If they don't, the lit lights go to the resting state. + default: 30 + selector: + number: + min: 5 + max: 600 + step: 1 + unit_of_measurement: s + mode: box + start_guard: + name: Reverse walk guard + description: >- + The first zone only starts a sequence if the next zone has been + clear for at least this long, so someone walking away from the + door doesn't set it off on the way out. + default: 3 + selector: + number: + min: 0 + max: 60 + step: 1 + unit_of_measurement: s + mode: box + cooldown: + name: Cooldown + description: After a sequence ends, wait this long before another can start. + default: 10 + selector: + number: + min: 0 + max: 600 + step: 1 + unit_of_measurement: s + mode: box + transition: + name: Transition + description: Fade time when lights change. 0 changes them instantly. + default: 0 + selector: + number: + min: 0 + max: 10 + step: 0.5 + unit_of_measurement: s + mode: box + sound_delay: + name: Light delay after a sound + description: >- + Speakers take a moment to start a sound. When a step has a sound, + its lights wait this long after the sound is sent so the two land + together. Tune it by ear; 0 changes the lights right away. + default: 0 + selector: + number: + min: 0 + max: 3000 + step: 50 + unit_of_measurement: ms + mode: slider + + options_section: + name: Sound player and options + icon: mdi:cog + collapsed: true + input: + sound_player: + name: Sound player + description: >- + Plays every sound. Leave empty to use the player each sound was + picked from. + default: "" + selector: + entity: + filter: + - domain: media_player + set_volume: + name: Set the volume during a sequence + description: >- + Sets the sound player's volume when a sequence starts and puts it + back when the sequence ends. This is the player's only volume, so + music playing on it changes too. Needs a Sound player above. + default: false + selector: + boolean: + sound_volume: + name: Sequence volume + default: 60 + selector: + number: + min: 0 + max: 100 + step: 1 + unit_of_measurement: "%" + mode: slider + enable_entity: + name: Enable switch (optional) + description: >- + Sequences only start while this is on, for example a Halloween + mode toggle. Leave empty to always run. + default: "" + selector: + entity: + filter: + - domain: + - input_boolean + - switch + - binary_sensor + pause_entities: + name: Switches to pause during a sequence (optional) + description: >- + Turned off while a sequence runs and back on afterwards if they + were on, for example a CAST-1's LED Strip Music Mode, which + otherwise takes over the strip when music starts or stops. + default: [] + selector: + entity: + multiple: true + filter: + - domain: + - switch + - input_boolean + +mode: single +max_exceeded: silent + +trigger_variables: + trigger_stages: !input stages + +triggers: + # The first stage's zone turning on + - trigger: template + value_template: >- + {{ trigger_stages | count > 0 and is_state(trigger_stages[0].zone, 'on') }} + +variables: + stage_inputs: !input stages + finale_zone: !input finale_zone + finale_extra_lights: !input finale_extra_lights + finale_sound: !input finale_sound + stage_sound: !input stage_sound + abandon_sound: !input abandon_sound + end_mode: !input end_mode + start_guard: !input start_guard + transition_s: !input transition + sound_delay: !input sound_delay + sound_player: !input sound_player + set_volume: !input set_volume + sound_volume: !input sound_volume + enable_entity: !input enable_entity + pause_entities: !input pause_entities + stage_look: + color_mode: !input stage_color_mode + rgb: !input stage_rgb + kelvin: !input stage_kelvin + brightness: !input stage_brightness + effect: !input stage_effect + finale_look: + color_mode: !input finale_color_mode + rgb: !input finale_rgb + kelvin: !input finale_kelvin + brightness: !input finale_brightness + effect: !input finale_effect + end_look: + color_mode: !input end_color_mode + rgb: !input end_rgb + kelvin: !input end_kelvin + brightness: !input end_brightness + effect: !input end_effect + # Stages with a zone and lights, each with its look filled in from the + # Stage look and its sound resolved to {id, type, player} + stages: >- + {%- set ns = namespace(out=[]) -%} + {%- for s in stage_inputs if s is mapping -%} + {%- set lights = s.get('lights') or [] -%} + {%- set lights = [lights] if lights is string else lights | list -%} + {%- if s.get('zone') and lights | count > 0 -%} + {%- set own_color = s.get('color_mode') not in [none, ''] -%} + {%- set effect = s.get('effect') -%} + {%- set look = { + 'color_mode': s.get('color_mode') if own_color else stage_look.color_mode, + 'rgb': s.get('rgb') if own_color and s.get('rgb') else stage_look.rgb, + 'kelvin': s.get('kelvin') if own_color and s.get('kelvin') else stage_look.kelvin, + 'brightness': s.get('brightness') if s.get('brightness') is number else stage_look.brightness, + 'effect': effect if effect is string and effect | trim != '' else stage_look.effect + } -%} + {%- set snd = s.get('sound') -%} + {%- set snd = snd if snd is mapping and snd.get('media_content_id') else stage_sound -%} + {%- set snd = snd if snd is mapping else {} -%} + {%- set ns.out = ns.out + [{ + 'zone': s.get('zone'), + 'lights': lights, + 'look': look, + 'sound': { + 'id': snd.get('media_content_id') or '', + 'type': snd.get('media_content_type') or 'music', + 'player': sound_player or snd.get('entity_id') or '' + } + }] -%} + {%- endif -%} + {%- endfor -%} + {{ ns.out }} + # light.turn_on data for the finale, resting state and each stage, in that + # order; the effect is added per light when the look is applied + look_data: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in [finale_look, end_look] + stages | map(attribute='look') | list -%} + {#- Only send a fade when one is set: ESPHome warns when an effect comes with any transition, even 0 -#} + {%- set d = {'brightness_pct': l.brightness | int(100)} -%} + {%- if transition_s | float(0) > 0 -%} + {%- set d = dict(d, transition=transition_s | float(0)) -%} + {%- endif -%} + {%- if l.color_mode == 'rgb' and l.rgb -%} + {%- set d = dict(d, rgb_color=l.rgb | list) -%} + {%- elif l.color_mode == 'kelvin' and l.kelvin -%} + {%- set d = dict(d, color_temp_kelvin=l.kelvin | int) -%} + {%- endif -%} + {%- set ns.out = ns.out + [d] -%} + {%- endfor -%} + {{ ns.out }} + # The zone after the first stage, used by the reverse walk guard + next_zone: "{{ stages[1].zone if stages | count > 1 else finale_zone }}" + all_lights: >- + {{ (stages | map(attribute='lights') | sum(start=[]) + finale_extra_lights) | unique | list }} + snapshot_scene: "porch_zone_sequence_{{ this.entity_id.split('.')[1] }}" + +conditions: + - condition: template + value_template: "{{ enable_entity == '' or is_state(enable_entity, 'on') }}" + - condition: template + value_template: "{{ stages | count > 0 and finale_zone != '' }}" + - condition: template + value_template: >- + {%- set nxt = expand([next_zone]) | first -%} + {{ nxt is not defined or (nxt.state != 'on' + and (now() - nxt.last_changed).total_seconds() >= start_guard | float(0)) }} + +actions: + - variables: + paused: >- + {{ expand(pause_entities) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }} + prev_volume: >- + {{ state_attr(sound_player, 'volume_level') if set_volume and sound_player != '' else none }} + - if: + - condition: template + value_template: "{{ paused | count > 0 }}" + then: + - action: homeassistant.turn_off + target: + entity_id: "{{ paused }}" + - if: + - condition: template + value_template: "{{ set_volume and sound_player != '' }}" + then: + - action: media_player.volume_set + target: + entity_id: "{{ sound_player }}" + data: + volume_level: "{{ (sound_volume | float(60)) / 100 }}" + continue_on_error: true + - if: + - condition: template + value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" + then: + - action: scene.create + data: + scene_id: "{{ snapshot_scene }}" + snapshot_entities: "{{ all_lights }}" + + # idx is the last lit stage (-1 before the first); outcome becomes finale + # or abandon. The first pass lights the first stage without waiting + - variables: + idx: -1 + outcome: "" + - repeat: + while: + - condition: template + value_template: "{{ outcome == '' }}" + sequence: + - wait_template: >- + {{ idx < 0 or is_state(finale_zone, 'on') + or expand(stages[idx + 1:] | map(attribute='zone') | list) + | selectattr('state', 'eq', 'on') | list | count > 0 }} + timeout: !input step_timeout + continue_on_timeout: true + - choose: + - conditions: + - condition: template + value_template: "{{ not wait.completed }}" + sequence: + - variables: + outcome: abandon + - conditions: + - condition: template + value_template: "{{ idx >= 0 and is_state(finale_zone, 'on') }}" + sequence: + # Skipped stages join the finale directly + - variables: + idx: "{{ stages | count - 1 }}" + outcome: finale + default: + # Jump to the furthest occupied stage, lighting any skipped ones + - variables: + target_idx: >- + {%- set ns = namespace(j=[idx, 0] | max) -%} + {%- for s in stages -%} + {%- if loop.index0 > idx and is_state(s.zone, 'on') -%} + {%- set ns.j = loop.index0 -%} + {%- endif -%} + {%- endfor -%} + {{ ns.j }} + - if: + - condition: template + value_template: "{{ target_idx > idx }}" + then: + - variables: + snd: "{{ stages[target_idx].sound }}" + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for i in range(idx + 1, target_idx + 1) -%} + {%- for l in stages[i].lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[i + 2], 'effect': stages[i].look.effect}] -%} + {%- endfor -%} + {%- endfor -%} + {{ ns.out }} + # play_media can hold the run until the sound ends, so the + # sound gets its own branch and the lights don't wait for it + - parallel: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - action: media_player.play_media + target: + entity_id: "{{ snd.player }}" + data: + media_content_id: "{{ snd.id }}" + media_content_type: "{{ snd.type }}" + announce: true + continue_on_error: true + - sequence: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - delay: + milliseconds: "{{ sound_delay | int(0) }}" + - repeat: &apply_jobs + for_each: "{{ jobs }}" + sequence: + # The look's effect, matched to the name this light uses + # for it; None picks the light's own "None" or "off" + - action: light.turn_on + target: + entity_id: "{{ repeat.item.light }}" + data: >- + {%- set fx = state_attr(repeat.item.light, 'effect_list') or [] -%} + {%- set want = (repeat.item.effect or 'None') | string | trim | lower -%} + {%- set names = ['none', 'off'] if want in ['', 'none', 'off'] else [want] -%} + {%- set ns = namespace(e='') -%} + {%- for f in fx -%} + {%- if ns.e == '' and (f | string | lower) in names -%} + {%- set ns.e = f -%} + {%- endif -%} + {%- endfor -%} + {{ dict(repeat.item.data, effect=ns.e) if ns.e else repeat.item.data }} + continue_on_error: true + - variables: + idx: "{{ target_idx }}" + + - variables: + lit_lights: >- + {{ stages[:idx + 1] | map(attribute='lights') | sum(start=[]) | unique | list }} + raw_sound: "{{ finale_sound if outcome == 'finale' else abandon_sound }}" + - variables: + end_lights: >- + {{ (lit_lights + finale_extra_lights) | unique | list if outcome == 'finale' else lit_lights }} + snd: + id: "{{ (raw_sound.get('media_content_id') if raw_sound is mapping else '') or '' }}" + type: "{{ (raw_sound.get('media_content_type') if raw_sound is mapping else '') or 'music' }}" + player: >- + {{ sound_player or (raw_sound.get('entity_id') if raw_sound is mapping else '') or '' }} + + # The finale or turned-back sound plays in its own branch while the lights + # run the finale and resting state + - parallel: + - if: + - condition: template + value_template: "{{ snd.id != '' and snd.player != '' }}" + then: + - action: media_player.play_media + target: + entity_id: "{{ snd.player }}" + data: + media_content_id: "{{ snd.id }}" + media_content_type: "{{ snd.type }}" + announce: true + continue_on_error: true + - sequence: + - if: + - condition: template + value_template: "{{ outcome == 'finale' and snd.id != '' and snd.player != '' }}" + then: + - delay: + milliseconds: "{{ sound_delay | int(0) }}" + - if: + - condition: template + value_template: "{{ outcome == 'finale' }}" + then: + - variables: + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in end_lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[0], 'effect': finale_look.effect}] -%} + {%- endfor -%} + {{ ns.out }} + - repeat: *apply_jobs + - delay: !input finale_duration + + # Resting state + - choose: + - conditions: + - condition: template + value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" + sequence: + - action: scene.turn_on + target: + entity_id: "scene.{{ snapshot_scene }}" + data: + transition: "{{ transition_s | float(0) }}" + continue_on_error: true + - conditions: + - condition: template + value_template: "{{ end_mode == 'look' }}" + sequence: + - variables: + jobs: >- + {%- set ns = namespace(out=[]) -%} + {%- for l in end_lights -%} + {%- set ns.out = ns.out + [{'light': l, 'data': look_data[1], 'effect': end_look.effect}] -%} + {%- endfor -%} + {{ ns.out }} + - repeat: *apply_jobs + default: + - if: + - condition: template + value_template: "{{ end_lights | count > 0 }}" + then: + - action: light.turn_off + target: + entity_id: "{{ end_lights }}" + data: + transition: "{{ transition_s | float(0) }}" + continue_on_error: true + + - if: + - condition: template + value_template: "{{ paused | count > 0 }}" + then: + - action: homeassistant.turn_on + target: + entity_id: "{{ paused }}" + - if: + - condition: template + value_template: "{{ prev_volume is number }}" + then: + - action: media_player.volume_set + target: + entity_id: "{{ sound_player }}" + data: + volume_level: "{{ prev_volume }}" + continue_on_error: true + - delay: !input cooldown diff --git a/Blueprints/README.md b/Blueprints/README.md new file mode 100644 index 0000000..28b4b8c --- /dev/null +++ b/Blueprints/README.md @@ -0,0 +1,74 @@ +# Porch Light Sequence Blueprints + +Home Assistant blueprints for a Halloween porch display. As a visitor walks up to the door, lights turn on in stages along the path. Each stage can play a sound, and the visitor reaching the door plays a finale. Afterwards the lights go to a resting state. If the visitor turns back partway, the lights go to the resting state on their own instead of staying on. + +They work with any Home Assistant lights (a CAST-1 LED strip, Hue bulbs and so on) and any speaker. Pick the blueprint that matches your sensors: + +| Blueprint | Sensors | Import | +| --- | --- | --- | +| **Zone-Based** | Presence zones, such as LD2450 radar zones made with Zone Mapper, or any on/off occupancy sensors | [![Import](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Zone-Based.yaml) | +| **Distance-Based** | One radar distance reading, such as an LD2410 or LD2412 (Apollo R PRO-1) mounted by the door | [![Import](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Distance-Based.yaml) | +| **Motion-Based** | One or more PIR motion sensors, such as the ESPHome Starter Kit | [![Import](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Motion-Based.yaml) | + +All three need Home Assistant 2025.7 or newer. + +## Install + +1. Click **Import** next to the blueprint you want, then click **Preview** and **Import blueprint** in Home Assistant. +2. Go to **Settings → Automations & scenes → Blueprints**, select the blueprint, and fill it in. The steps below explain each section. +3. Save the automation. + +To install by hand instead, copy the `.yaml` file into `config/blueprints/automation/apollo/` in Home Assistant. Then go to **Developer tools → YAML** and click **Automations** under reload. + +## Set up the stages + +Each stage is a group of lights that turns on as the visitor gets closer. Click **Add** under **Stages** for each one. Stages that are already on stay on as later ones light up. + +- **Lights:** one or more lights per stage. With a CAST-1 strip, use [partition lights](../README.md#splitting-the-strip-into-segments) to give each stage its own section of the strip. +- **Look:** every stage uses the shared **Stage look** (color, brightness and effect) unless you set its own. +- **Effects:** pick an effect from the list or type the name exactly as your light shows it. Each light only gets effects it supports; other lights just change color and brightness. +- **Sounds:** the optional **Stage sound** plays as each stage turns on. A stage can also have its own sound. + +> [!WARNING] +> Strobe-style effects faster than 3 flashes per second can trigger seizures in people with photosensitive epilepsy. + +**Finale:** the finale switches every lit light, plus any **Extra finale lights** such as a porch light, to the finale look for the **Finale length**. Then the lights go to the **Resting state**. The resting state can turn them off, show a resting look, or put them back the way they were before the sequence. + +**Turned back:** if the visitor doesn't reach the next stage within the time limit, the lit lights go to the resting state. The optional **Turned-back sound** plays then. In Motion-Based, this only applies to a stage or finale that waits for its own sensor; a show running on timers always plays through. + +## Zone-Based + +- Add one stage per zone, in the order a visitor walks through them, and set the **Finale zone** to the zone by the door. Zones can be any on/off occupancy, presence or motion sensor. +- If a visitor enters a later zone first, the stages in between turn on with it. +- Stages only move toward the door. The **Reverse walk guard** stops someone walking out of the house from starting a sequence. + +## Distance-Based + +- Mount the radar by the door, facing out, so the distance shrinks as a visitor walks up. +- **Distance sensor:** use the radar's **Moving Distance**, which ignores still objects such as plants or parked cars. +- **Target sensor:** use the radar's overall presence or target sensor, which stays on for people standing still. +- **Distances:** give each stage the distance at which it turns on, and set a smaller **Finale distance**. Use the unit your sensor shows in Home Assistant, such as inches or cm. Stages can be added in any order; they're sorted farthest first. +- **Spacing:** LD2410 radars measure in steps of about 75 cm (30 in), so space stages at least that far apart. +- **Starting:** a sequence starts when a visitor walks in across the first stage's distance. Keep that distance a little inside the radar's range so it sees visitors coming. + +## Motion-Based + +- **Start motion sensor:** motion here starts the sequence. +- **Each stage and the finale:** each either waits for its own motion sensor or turns on after a wait time. + - **One sensor:** leave the stage and finale sensors empty, and the whole show runs on timers. The first stage turns on after the **First stage wait time** (0 s by default). Each later stage follows after the **Later stage wait time**, and the finale after the **Finale wait time**. + - **More sensors:** give a stage or the finale its own sensor and it waits for that sensor instead. Use a different sensor for each. +- **Quiet time before a new show:** stops a visitor waiting at the door from replaying the show every time they move. +- **Reverse walk guard:** with more than one sensor, it stops someone leaving the house from starting a show. Set it to about how long the walk from the door to the start sensor takes. + +## Sound and music + +- **Sound player:** set it under **Sound player and options** to play every sound on one speaker. If you play music through Music Assistant, pick the speaker's own media player, not the Music Assistant one. Otherwise Music Assistant pauses the music for each sound instead of playing over it. +- **Ducking on a CAST-1:** music ducks under each sound, by 40 dB by default. Set `announcement_ducking_db` in your device YAML to keep the music louder (see [Announcements](../README.md#announcements)). +- **Light delay after a sound:** if your speaker starts sounds late, this makes the lights wait so they land together. +- **Volume:** **Set the volume during a sequence** changes the speaker's volume while a sequence runs, then puts it back. +- **CAST-1 Music Mode:** add the strip's **LED Strip Music Mode** switch to **Switches to pause during a sequence**. Otherwise music starting or stopping can take over the strip mid-show. It's turned back on afterwards. +- **Enable switch:** set one, such as a Halloween mode toggle, to turn the display on and off without editing the automation. + +## Troubleshooting + +If something doesn't happen as expected, open the automation, click **Traces** and select the run. The conditions step shows why a sequence didn't start, and each step shows what the lights and speaker were sent. From 088de87fd147e9816d3e26614919b128c09ccc2f Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Thu, 29 Oct 2026 14:29:41 -0400 Subject: [PATCH 25/30] Enlarge the blueprint import buttons in the README GitHub shrank the Markdown badges to fit the table column, so they're now HTML images with a fixed height. Co-Authored-By: Claude Opus 5.5 --- Blueprints/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Blueprints/README.md b/Blueprints/README.md index 28b4b8c..19b29cf 100644 --- a/Blueprints/README.md +++ b/Blueprints/README.md @@ -6,9 +6,9 @@ They work with any Home Assistant lights (a CAST-1 LED strip, Hue bulbs and so o | Blueprint | Sensors | Import | | --- | --- | --- | -| **Zone-Based** | Presence zones, such as LD2450 radar zones made with Zone Mapper, or any on/off occupancy sensors | [![Import](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Zone-Based.yaml) | -| **Distance-Based** | One radar distance reading, such as an LD2410 or LD2412 (Apollo R PRO-1) mounted by the door | [![Import](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Distance-Based.yaml) | -| **Motion-Based** | One or more PIR motion sensors, such as the ESPHome Starter Kit | [![Import](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Motion-Based.yaml) | +| **Zone-Based** | Presence zones, such as LD2450 radar zones made with Zone Mapper, or any on/off occupancy sensors |
Import blueprint | +| **Distance-Based** | One radar distance reading, such as an LD2410 or LD2412 (Apollo R PRO-1) mounted by the door | Import blueprint | +| **Motion-Based** | One or more PIR motion sensors, such as the ESPHome Starter Kit | Import blueprint | All three need Home Assistant 2025.7 or newer. From f04dc2ba40a149fb116b142510d799a7536009af Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Thu, 29 Oct 2026 14:31:08 -0400 Subject: [PATCH 26/30] Move the blueprint import buttons out of the README table GitHub shrinks images to fit table cells, so the buttons were tiny even with a fixed height. Each blueprint now has its button on its own line. Co-Authored-By: Claude Opus 5.5 --- Blueprints/README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Blueprints/README.md b/Blueprints/README.md index 19b29cf..795c3ac 100644 --- a/Blueprints/README.md +++ b/Blueprints/README.md @@ -4,11 +4,17 @@ Home Assistant blueprints for a Halloween porch display. As a visitor walks up t They work with any Home Assistant lights (a CAST-1 LED strip, Hue bulbs and so on) and any speaker. Pick the blueprint that matches your sensors: -| Blueprint | Sensors | Import | -| --- | --- | --- | -| **Zone-Based** | Presence zones, such as LD2450 radar zones made with Zone Mapper, or any on/off occupancy sensors | Import blueprint | -| **Distance-Based** | One radar distance reading, such as an LD2410 or LD2412 (Apollo R PRO-1) mounted by the door | Import blueprint | -| **Motion-Based** | One or more PIR motion sensors, such as the ESPHome Starter Kit | Import blueprint | +**Zone-Based**: Presence zones, such as LD2450 radar zones made with Zone Mapper, or any on/off occupancy sensors + +[![Import blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Zone-Based.yaml) + +**Distance-Based**: One radar distance reading, such as an LD2410 or LD2412 (Apollo R PRO-1) mounted by the door + +[![Import blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Distance-Based.yaml) + +**Motion-Based**: One or more PIR motion sensors, such as the ESPHome Starter Kit + +[![Import blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Motion-Based.yaml) All three need Home Assistant 2025.7 or newer. From 938e21aa79f4b333d67fe24f805de1b037e6c014 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Thu, 29 Oct 2026 17:27:27 -0400 Subject: [PATCH 27/30] Add step-by-step instructions for adding the LED strip package Co-Authored-By: Claude Opus 5.5 --- README.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eaaf502..3eeae6a 100644 --- a/README.md +++ b/README.md @@ -45,18 +45,30 @@ substitutions: ## External LED Strip -The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). The strip is opt-in: add `led_strip.yaml` to the packages in your device YAML in ESPHome Device Builder, set how many LEDs it has (the default is 30), then install: +The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). The strip is opt-in. To add it: + +1. In ESPHome Device Builder, click **Edit** on your CAST-1. +2. Find the `packages:` section. An adopted CAST-1 already has one line there that points at `CAST-1.yaml`. +3. Add a `led_strip` line under it that points at `led_strip.yaml`. Keep the same repository and the same `@` branch as the existing line, if it has one. +4. Set how many LEDs the strip has with `led_strip_num_leds` (the default is 30). Add it to the existing `substitutions:` section rather than starting a second one. +5. Click **Save**, then **Install**. + +Your device YAML ends up looking like this (other lines left out): ```yaml substitutions: + name: apollo-cast-1-abc123 + friendly_name: Apollo CAST-1 led_strip_num_leds: "21" packages: - cast_1: github://ApolloAutomation/CAST-1/Integrations/ESPHome/CAST-1.yaml@main - led_strip: github://ApolloAutomation/CAST-1/Integrations/ESPHome/led_strip.yaml@main + ApolloAutomation.CAST-1: github://ApolloAutomation/CAST-1/Integrations/ESPHome/CAST-1.yaml + led_strip: github://ApolloAutomation/CAST-1/Integrations/ESPHome/led_strip.yaml ``` -Remove the `led_strip` line to drop the strip again. Any partitions you added have to go with it, since they use the strip. +Device Builder keeps a copy of each package for a day, so a new firmware release can take up to a day to show up in an install. + +To drop the strip again, delete the `led_strip` line and install. Delete any partitions you added at the same time, since they use the strip. The rest of the strip's settings live in Home Assistant and under **External LED Strip** on the device's web page: From 53fda69f1cd39eb2ae21c9395ed1060ff7f0f141 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Fri, 30 Oct 2026 13:14:55 -0400 Subject: [PATCH 28/30] Expose LED strip and announcement settings in Home Assistant - Include led_strip.yaml from Core.yaml again - Bring back the LED Strip Count number; led_strip_num_leds is now the maximum (default 300) for longer strips and partitions - Disable the LED strip entities by default - Replace the announcement substitutions with Announcement Ducking and Announcement LED Brightness sliders - Add Rainbow, Color Wipe, Scan, Twinkle, Pulse and Fireworks to the Effect A/B patterns - Update the README; the partition and device YAML notes move to a separate repo Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 43 ++++-- Integrations/ESPHome/led_strip.yaml | 211 +++++++++++++++++++++++++--- README.md | 93 +++--------- 3 files changed, 238 insertions(+), 109 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index e205313..ceceade 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -4,17 +4,11 @@ substitutions: beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" beta_manifest_file: "manifest.json" - # How far music drops (in dB) while an announcement plays; set in the - # device YAML's substitutions to override it (0 = no ducking) - announcement_ducking_db: "40" - # Onboard LED brightness while an announcement plays (0%-100%) - announcement_led_brightness: "50%" packages: wizmote: !include wizmote.yaml - # The external LED strip (led_strip.yaml) is opt-in: add it to the - # package files in the device YAML + led_strip: !include led_strip.yaml esphome: friendly_name: Apollo CAST-1 @@ -483,6 +477,37 @@ light: min_brightness: 50% max_brightness: 100% +number: + # How far music drops while an announcement plays (0 = no ducking) + - platform: template + id: announcement_ducking + name: "Announcement Ducking" + icon: mdi:volume-minus + entity_category: config + unit_of_measurement: "dB" + mode: slider + min_value: -80 + max_value: 0 + step: 1 + optimistic: true + restore_value: true + initial_value: -40 + + # Onboard LED brightness while an announcement plays (0 = LED stays off) + - platform: template + id: announcement_led_brightness + name: "Announcement LED Brightness" + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + mode: slider + min_value: 0 + max_value: 100 + step: 1 + optimistic: true + restore_value: true + initial_value: 100 + select: - platform: template id: firmware_channel @@ -603,10 +628,10 @@ media_player: blue: 100% red: 0% green: 100% - brightness: ${announcement_led_brightness} + brightness: !lambda "return id(announcement_led_brightness).state / 100.0f;" - mixer_speaker.apply_ducking: id: media_mixer_input - decibel_reduction: ${announcement_ducking_db} + decibel_reduction: !lambda "return (uint8_t) -id(announcement_ducking).state;" duration: 0.0s - wait_until: media_player.is_announcing: external_media_player diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml index 480acc5..f8d2729 100644 --- a/Integrations/ESPHome/led_strip.yaml +++ b/Integrations/ESPHome/led_strip.yaml @@ -1,9 +1,10 @@ # LED strip on the exposed 5V / GND / IO1 header; included by Core.yaml substitutions: - # How many LEDs the strip has; set led_strip_num_leds in the device YAML's - # substitutions to override it (partitions must fit inside it) - led_strip_num_leds: "30" + # The most LEDs the LED Strip Count can be set to (its buffers are sized + # for this many at compile time); set led_strip_num_leds in the device + # YAML's substitutions to raise it. Partitions must fit inside it + led_strip_num_leds: "300" esphome: on_boot: @@ -11,6 +12,9 @@ esphome: # Must run after the strip and the restored entities set up (800) - priority: 600 then: + - lambda: |- + id(led_strip_output)->set_num_leds( + (uint16_t) clamp(id(led_strip_count).state, 1.0f, ${led_strip_num_leds})); - script.execute: led_strip_blank_all - script.execute: id: led_strip_apply_color_order @@ -35,6 +39,7 @@ light: output_id: led_strip_output name: "LED Strip" icon: mdi:led-strip-variant + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 1 @@ -99,10 +104,12 @@ globals: initial_value: |- [](light::AddressableLight &it, Color color, bool initial_run, int slot) { struct SlotState { + int pattern; float level; float target; uint32_t next_ms; uint32_t cycle_start; + uint32_t pos; }; // One state per light, since a light runs one effect at a time static const light::AddressableLight *owners[16] = {}; @@ -116,51 +123,166 @@ globals: } SlotState &st = states[i]; const uint32_t now = millis(); + const int32_t n = it.size(); + if (n <= 0) return; // Each template select is its own type (it carries its initial option), // so pick through the shared base classes - select::Select *pattern = slot == 1 ? static_cast(led_strip_effect_b_pattern) - : static_cast(led_strip_effect_a_pattern); + select::Select *pattern_sel = slot == 1 ? static_cast(led_strip_effect_b_pattern) + : static_cast(led_strip_effect_a_pattern); number::Number *speed_num = slot == 1 ? static_cast(led_strip_effect_b_speed) : static_cast(led_strip_effect_a_speed); + const int pattern = (int) pattern_sel->active_index().value_or(0); const float speed = clamp(speed_num->state, 1.0f, 100.0f); // Speed 1-100 on a log curve: 1 = 1000 ms, 50 = 182 ms, 100 = 32 ms, // so the fastest step lands on two ~16 ms main-loop passes const uint32_t period = (uint32_t) (1000.0f * powf(0.032f, (speed - 1.0f) / 99.0f)); - if (initial_run) { + // A pattern change mid-effect starts the new pattern fresh + if (initial_run || pattern != st.pattern) { + st.pattern = pattern; st.level = 1.0f; st.target = 1.0f; st.next_ms = now; st.cycle_start = now; + st.pos = 0; + for (int32_t p = 0; p < n; p++) it[p].set_effect_data(0); } - if (pattern->active_index().value_or(0) == 1) { - // Strobe: on for one period, off for the next - const uint32_t cycle = period * 2; - if (now - st.cycle_start >= cycle) st.cycle_start = now - (now - st.cycle_start) % cycle; - it.all() = (now - st.cycle_start) < period ? color : Color::BLACK; - } else { - // Flicker: every period the light picks a new random level, no lower - // than 30%, and eases toward it within a few frames - const int32_t late = (int32_t) (now - st.next_ms); - // A raised Speed pulls in a change that was scheduled further out - if (late >= 0 || -late > (int32_t) period) { - st.target = 1.0f - 0.7f * random_float(); - st.next_ms = (late >= 0 && late < (int32_t) period) ? st.next_ms + period : now + period; + // Steps due since the last frame, one per period. After a stall the + // pattern skips ahead instead of racing to catch up + uint32_t steps = 0; + const int32_t late = (int32_t) (now - st.next_ms); + if (late >= 0) { + steps = 1 + (uint32_t) late / period; + st.next_ms += steps * period; + if (steps > 4) { + steps = 4; + st.next_ms = now + period; + } + } else if (-late > (int32_t) period) { + // A raised Speed pulls in a step that was scheduled further out + st.next_ms = now + period; + } + + switch (pattern) { + case 1: { + // Strobe: on for one period, off for the next + const uint32_t cycle = period * 2; + if (now - st.cycle_start >= cycle) st.cycle_start = now - (now - st.cycle_start) % cycle; + it.all() = (now - st.cycle_start) < period ? color : Color::BLACK; + break; + } + case 2: { + // Rainbow: one rainbow spans about 50 LEDs and shifts a hue step + // every period (it ignores the light's color) + st.pos += steps * 4; + for (int32_t p = 0; p < n; p++) + it[p] = light::ESPHSVColor((uint8_t) (st.pos + p * 5), 255, 255).to_rgb(); + break; + } + case 3: { + // Color Wipe: fills one more LED each period, then clears them + // one at a time from the start + st.pos = (st.pos + steps) % (uint32_t) (2 * n); + const int32_t q = (int32_t) st.pos; + for (int32_t p = 0; p < n; p++) it[p] = (q < n ? p <= q : p > q - n) ? color : Color::BLACK; + break; + } + case 4: { + // Scan: one lit LED moves a step each period and bounces at the ends + const uint32_t span = n > 1 ? (uint32_t) (2 * n - 2) : 1; + st.pos = (st.pos + steps) % span; + const int32_t q = (int32_t) st.pos; + it.all() = Color::BLACK; + it[q < n ? q : (int32_t) span - q] = color; + break; + } + case 5: { + // Twinkle: random LEDs fade in and out over 8 periods; each LED's + // effect data holds how far along its twinkle is (0 = dark) + for (uint32_t s = 0; s < steps; s++) { + for (int32_t p = 0; p < n; p++) { + uint8_t d = it[p].get_effect_data(); + if (d != 0) { + d = d >= 224 ? 0 : d + 32; + } else if (random_float() < 0.05f) { + d = 1; + } + it[p].set_effect_data(d); + } + } + for (int32_t p = 0; p < n; p++) { + const uint8_t d = it[p].get_effect_data(); + it[p] = color * (uint8_t) (d < 128 ? d * 2 : (255 - d) * 2); + } + break; + } + case 6: { + // Pulse: fades smoothly from off to full and back every 4 periods + const uint32_t cycle = period * 4; + if (now - st.cycle_start >= cycle) st.cycle_start = now - (now - st.cycle_start) % cycle; + const float t = (float) (now - st.cycle_start) / (float) cycle; + it.all() = color * (uint8_t) ((0.5f - 0.5f * cosf(6.2831853f * t)) * 255.0f); + break; + } + case 7: { + // Fireworks: sparks light at random each period, then fade while + // spreading to their neighbours; effect data holds each LED's level + for (uint32_t s = 0; s < steps; s++) { + uint8_t prev = 0; + for (int32_t p = 0; p < n; p++) { + const uint8_t cur = it[p].get_effect_data(); + const uint8_t next = p + 1 < n ? it[p + 1].get_effect_data() : 0; + it[p].set_effect_data((uint8_t) std::max(cur * 3 / 5, (prev + next) * 3 / 10)); + prev = cur; + } + if (random_float() < 0.15f) it[random_uint32() % (uint32_t) n].set_effect_data(255); + } + for (int32_t p = 0; p < n; p++) it[p] = color * it[p].get_effect_data(); + break; + } + default: { + // Flicker: every period the light picks a new random level, no lower + // than 30%, and eases toward it within a few frames + if (steps > 0) st.target = 1.0f - 0.7f * random_float(); + st.level += (st.target - st.level) * 0.6f; + it.all() = color * (uint8_t) (st.level * 255.0f); + break; } - st.level += (st.target - st.level) * 0.6f; - it.all() = color * (uint8_t) (st.level * 255.0f); } } number: + # How many LEDs are driven; LEDs past it are left dark + - platform: template + id: led_strip_count + name: "LED Strip Count" + icon: mdi:counter + entity_category: config + disabled_by_default: true + web_server: + sorting_group_id: sg_led_strip + sorting_weight: 20 + mode: box + min_value: 1 + max_value: ${led_strip_num_leds} + step: 1 + optimistic: true + restore_value: true + initial_value: 30 + set_action: + - script.execute: + id: led_strip_apply_count + count: !lambda "return (int) x;" + # Caps every channel so a long strip can't overdraw the header's 5V rail - platform: template id: led_strip_max_brightness name: "LED Strip Max Brightness" icon: mdi:brightness-percent entity_category: config + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 21 @@ -183,6 +305,7 @@ number: name: "LED Strip Effect A Speed" icon: mdi:speedometer entity_category: config + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 12 @@ -199,6 +322,7 @@ number: name: "LED Strip Effect B Speed" icon: mdi:speedometer entity_category: config + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 15 @@ -216,6 +340,7 @@ select: name: "LED Strip Color Order" icon: mdi:palette entity_category: config + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 22 @@ -239,6 +364,7 @@ select: name: "LED Strip Chipset" icon: mdi:chip entity_category: config + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 23 @@ -261,6 +387,7 @@ select: name: "LED Strip Music Effect" icon: mdi:music-circle entity_category: config + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 24 @@ -284,6 +411,7 @@ select: name: "LED Strip Effect A Pattern" icon: mdi:animation-play entity_category: config + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 11 @@ -292,6 +420,12 @@ select: options: - "Flicker" - "Strobe" + - "Rainbow" + - "Color Wipe" + - "Scan" + - "Twinkle" + - "Pulse" + - "Fireworks" initial_option: "Flicker" - platform: template @@ -299,6 +433,7 @@ select: name: "LED Strip Effect B Pattern" icon: mdi:animation-play entity_category: config + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 14 @@ -307,6 +442,12 @@ select: options: - "Flicker" - "Strobe" + - "Rainbow" + - "Color Wipe" + - "Scan" + - "Twinkle" + - "Pulse" + - "Fireworks" initial_option: "Strobe" switch: @@ -316,6 +457,7 @@ switch: id: led_strip_music_mode name: "LED Strip Music Mode" icon: mdi:music-note + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 25 @@ -367,6 +509,7 @@ button: name: "LED Strip Test" icon: mdi:led-strip-variant entity_category: diagnostic + disabled_by_default: true web_server: sorting_group_id: sg_led_strip sorting_weight: 30 @@ -374,6 +517,24 @@ button: - script.execute: led_strip_test script: + - id: led_strip_apply_count + mode: queued + parameters: + count: int + then: + - lambda: |- + auto *out = id(led_strip_output); + // Blank every pixel the buffers cover, so LEDs past a lowered count go dark + out->set_num_leds(${led_strip_num_leds}); + for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; + out->write_state(id(led_strip)); + // Never past the buffers, even if a count was saved under a larger maximum + out->set_num_leds((uint16_t) clamp(count, 1, ${led_strip_num_leds})); + out->clear_effect_data(); + // Repaint the current color at the new length (effects repaint themselves) + out->update_state(id(led_strip)); + ESP_LOGI("led_strip", "Driving %d LEDs", (int) out->size()); + - id: led_strip_apply_max_brightness parameters: percent: float @@ -430,11 +591,15 @@ script: - id: led_strip_blank_all then: - lambda: |- - // Clear every pixel, so none keeps a color latched from IO1 noise - // during a reboot + // Clear every pixel the buffers cover, so LEDs past the LED Strip Count + // (never written otherwise) can't keep colors latched from IO1 noise + // during a reboot or an earlier, longer count auto *out = id(led_strip_output); + const uint16_t count = out->size(); + out->set_num_leds(${led_strip_num_leds}); for (int32_t i = 0; i < out->size(); i++) (*out)[i] = Color::BLACK; out->write_state(id(led_strip)); + out->set_num_leds(count); - id: led_strip_music_start then: diff --git a/README.md b/README.md index 3eeae6a..eb3a462 100644 --- a/README.md +++ b/README.md @@ -35,94 +35,33 @@ Configure every button without leaving Home Assistant using the [CAST-1 WizMote ## Announcements -While an announcement plays, music ducks and the onboard LED lights up. Change either in your device YAML in ESPHome Device Builder, then install: +While an announcement plays, music ducks and the onboard LED lights up. Two sliders in Home Assistant set how much: -```yaml -substitutions: - announcement_ducking_db: "20" # how far music drops, in dB (default 40; 0 = no ducking) - announcement_led_brightness: "25%" # onboard LED brightness during announcements (default 50%) -``` +- **Announcement Ducking** (−80 to 0 dB, default −40) is how far the music drops. 0 turns ducking off. +- **Announcement LED Brightness** (0–100%, default 100%) is how bright the onboard LED is. 0 keeps the LED off. ## External LED Strip -The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). The strip is opt-in. To add it: +The 5V / GND / IO1 header drives an addressable LED strip (WS2812, SK6812, WS2811, APA106 or SM16703). The firmware supports it out of the box, but its entities are disabled by default, since most CAST-1s don't have a strip connected. To use one, open the CAST-1's device page in Home Assistant and enable the **LED Strip** entities. -1. In ESPHome Device Builder, click **Edit** on your CAST-1. -2. Find the `packages:` section. An adopted CAST-1 already has one line there that points at `CAST-1.yaml`. -3. Add a `led_strip` line under it that points at `led_strip.yaml`. Keep the same repository and the same `@` branch as the existing line, if it has one. -4. Set how many LEDs the strip has with `led_strip_num_leds` (the default is 30). Add it to the existing `substitutions:` section rather than starting a second one. -5. Click **Save**, then **Install**. - -Your device YAML ends up looking like this (other lines left out): - -```yaml -substitutions: - name: apollo-cast-1-abc123 - friendly_name: Apollo CAST-1 - led_strip_num_leds: "21" - -packages: - ApolloAutomation.CAST-1: github://ApolloAutomation/CAST-1/Integrations/ESPHome/CAST-1.yaml - led_strip: github://ApolloAutomation/CAST-1/Integrations/ESPHome/led_strip.yaml -``` - -Device Builder keeps a copy of each package for a day, so a new firmware release can take up to a day to show up in an install. - -To drop the strip again, delete the `led_strip` line and install. Delete any partitions you added at the same time, since they use the strip. - -The rest of the strip's settings live in Home Assistant and under **External LED Strip** on the device's web page: +The strip's settings live in Home Assistant and under **External LED Strip** on the device's web page: +- **Count** is how many LEDs the strip has (up to 300, default 30). - **Chipset**, **Color Order** and **Max Brightness** describe your strip. -- **Effect A** and **Effect B** are two effect slots. Each has a **Pattern** (Flicker or Strobe) and a **Speed** (1 = one change per second, 100 = one every 32 ms, on a log curve). Flicker dips to random levels between full and 30% brightness; Strobe is on for one period and off for the next. Changes apply live while the effect runs. +- **Effect A** and **Effect B** are two effect slots. Each has a **Pattern** and a **Speed** (1 = one step per second, 100 = one step every 32 ms, on a log curve). Changes apply live while the effect runs. The patterns: + - **Flicker** dips to random levels between full and 30% brightness. + - **Strobe** is on for one step and off for the next. + - **Rainbow** moves a rainbow along the strip. It ignores the light's color. + - **Color Wipe** fills the strip one LED at a time, then clears it the same way. + - **Scan** moves one lit LED back and forth. + - **Twinkle** fades random LEDs in and out. + - **Pulse** fades the whole strip from off to full and back. + - **Fireworks** lights random sparks that spread and fade. In automations, set the pattern and speed with `select.select_option` and `number.set_value`, then call `light.turn_on` with `effect: "Effect A"` (add `transition: 0` for an instant start). -### Splitting the strip into segments - -To turn parts of the strip on and off on their own, add [partition lights](https://esphome.io/components/light/partition/) to your device YAML in ESPHome Device Builder and install it. Each partition becomes its own light in Home Assistant, with its own on/off, color, brightness and effect. List Effect A and Effect B on a partition to use the shared Pattern and Speed settings. - -For 21 LEDs in 3 segments of 7 (`to` is inclusive, and the first LED is 0): - -```yaml -light: - - platform: partition - name: "LED Segment 1" - segments: - - id: led_strip - from: 0 - to: 6 - default_transition_length: 0s - effects: &led_segment_effects - - addressable_lambda: - name: "Effect A" - update_interval: 15ms - lambda: "id(led_strip_slot_effect)(it, current_color, initial_run, 0);" - - addressable_lambda: - name: "Effect B" - update_interval: 15ms - lambda: "id(led_strip_slot_effect)(it, current_color, initial_run, 1);" - - platform: partition - name: "LED Segment 2" - segments: - - id: led_strip - from: 7 - to: 13 - default_transition_length: 0s - effects: *led_segment_effects - - platform: partition - name: "LED Segment 3" - segments: - - id: led_strip - from: 14 - to: 20 - default_transition_length: 0s - effects: *led_segment_effects -``` - -Every partition has to fit inside `led_strip_num_leds`; the install fails if one doesn't. Partitions share the strip's pixels, so control either the partitions or the main **LED Strip** light, not both at once — turning the main light off clears the whole strip. - > [!WARNING] -> **Photosensitivity:** Strobe flashes faster than 3 times per second from about Speed 50 up, and reaches about 16 flashes per second at Speed 100. Flashing in this range can trigger seizures in people with photosensitive epilepsy. +> **Photosensitivity:** Strobe flashes faster than 3 times per second from about Speed 50 up, and reaches about 16 flashes per second at Speed 100. Pulse passes 3 per second from about Speed 75. Flashing in this range can trigger seizures in people with photosensitive epilepsy. Power long strips from their own 5V supply with a shared ground; the header can't supply a full-brightness strip, and **LED Strip Max Brightness** (default 50%) caps the draw. From 5d9d9fddeb06604cb265a8f9721fa90bce5b0822 Mon Sep 17 00:00:00 2001 From: WestwardWinds <34014603+WestwardWinds@users.noreply.github.com> Date: Fri, 30 Oct 2026 13:43:40 -0400 Subject: [PATCH 29/30] Move the porch blueprints to the ApolloAutomation/Projects repo They now live in Projects/Halloween2026 with the example device YAML. Co-Authored-By: Claude Opus 5.5 --- Blueprints/Light-Sequence-Distance-Based.yaml | 837 ---------------- Blueprints/Light-Sequence-Motion-Based.yaml | 903 ------------------ .../Light-Sequence-Porch-Zone-Based.yaml | 781 --------------- Blueprints/README.md | 80 -- 4 files changed, 2601 deletions(-) delete mode 100644 Blueprints/Light-Sequence-Distance-Based.yaml delete mode 100644 Blueprints/Light-Sequence-Motion-Based.yaml delete mode 100644 Blueprints/Light-Sequence-Porch-Zone-Based.yaml delete mode 100644 Blueprints/README.md diff --git a/Blueprints/Light-Sequence-Distance-Based.yaml b/Blueprints/Light-Sequence-Distance-Based.yaml deleted file mode 100644 index 53f56a9..0000000 --- a/Blueprints/Light-Sequence-Distance-Based.yaml +++ /dev/null @@ -1,837 +0,0 @@ -blueprint: - name: Light Sequence (Distance-Based) - description: >- - Lights a path in stages as a visitor walks toward the door, using one - radar distance reading instead of separate zones. Made for LD2410 and - LD2412 style sensors (an Apollo R PRO-1, for example) mounted by the door - and facing out, so the distance shrinks as a visitor walks up. - - - Each stage turns on when the visitor comes within its distance, and the - earlier stages stay on. Coming within the finale distance switches every - lit light to the finale look, then all of them go to the resting state. - If the visitor doesn't get closer in time, the lit lights go to the - resting state early. - - - Stages only advance toward the door. Someone stepping out of the door and - walking away doesn't start a sequence. - - - Works with any Home Assistant lights. Sounds play as announcements, so - music playing on the same speaker ducks under them instead of stopping. - domain: automation - author: Apollo Automation - homeassistant: - min_version: 2025.7.0 - input: - sensor_section: - name: Radar sensor - icon: mdi:radar - collapsed: false - input: - distance_sensor: - name: Distance sensor - description: >- - The radar's distance to the visitor. Moving Distance works best, - since it ignores still objects such as plants or a parked car. - Detection Distance also works. The distances you enter below use - this sensor's unit (in, cm, ft or m), whatever it shows in Home Assistant. - # Any sensor: many radars' distance entities, such as the R PRO-1's - # LD2412 ones, have no distance device class - selector: - entity: - filter: - - domain: sensor - presence_sensor: - name: Target sensor (recommended) - description: >- - On while the radar sees anyone, moving or still, such as the - radar's Presence or Target sensor. It tells a visitor walking up - apart from a distance left over by someone earlier, and distances - only move a sequence forward while it's on. Without it, a reading - of 0 counts as nobody there, and the reading just before a - visitor crosses the first stage must be at most 30 s old. - default: "" - selector: - entity: - filter: &target_filter - - domain: binary_sensor - device_class: - - occupancy - - presence - - motion - - stages_section: - name: Stages - icon: mdi:walk - collapsed: false - input: - stages: - name: Stages - description: >- - Add one stage per light group. Each stage turns on when the - visitor comes within its distance of the sensor, in the sensor's - unit (inches or cm, for example). The stage with the largest distance starts the - sequence, so the order you add them in doesn't matter. A sequence - starts when a visitor walks in across that distance, so keep it a - little inside the radar's range, where it can see them coming. - - - LD2410 sensors measure in gates of about 75 cm (30 in), so space the - stages at least a gate apart; 150 cm (60 in) or more is more reliable. If - a visitor passes several stages between readings, those stages - turn on together. - - - Each stage uses the shared Stage look and Stage sound unless you - set its own color, brightness, effect or sound. - default: [] - selector: - object: - multiple: true - label_field: distance - fields: - distance: - label: Turns on within this distance (in the sensor's unit) - required: true - selector: - number: &distance_select - min: 0 - max: 10000 - step: any - mode: box - lights: - label: Lights - required: true - selector: - entity: - multiple: true - filter: - - domain: light - sound: - label: Sound (leave empty for the shared Stage sound) - selector: - media: - color_mode: - label: Color (leave empty for the Stage look) - selector: - select: &color_mode_select - mode: dropdown - options: - - label: RGB color - value: rgb - - label: Color temperature (white) - value: kelvin - - label: Don't change the color - value: none - rgb: - label: RGB color - selector: - color_rgb: - kelvin: - label: Color temperature - selector: - color_temp: &kelvin_select - unit: kelvin - min: 2000 - max: 6500 - brightness: - label: Brightness (leave empty for the Stage look) - selector: - number: &brightness_select - min: 1 - max: 100 - step: 1 - unit_of_measurement: "%" - mode: slider - effect: - label: Effect (leave empty for the Stage look) - selector: - select: &effect_select - mode: dropdown - custom_value: true - options: - - None - - Flicker - - Pulse - - Strobe - - Rainbow - - Color Wipe - - Scan - - Twinkle - - Random Twinkle - - Fireworks - - Effect A - - Effect B - - candle - - fire - - prism - - sparkle - - opal - - glisten - - underwater - - cosmos - - sunbeam - - enchant - - finale_section: - name: Finale - icon: mdi:door - collapsed: false - input: - finale_distance: - name: Finale distance - description: >- - Coming within this distance of the sensor plays the finale. Use - the sensor's unit and keep it below every stage distance. - default: 40 - selector: - number: *distance_select - finale_extra_lights: - name: Extra finale lights (optional) - description: >- - Lights that join the finale on top of the stage lights, such as a - porch light. - default: [] - selector: - entity: - multiple: true - filter: - - domain: light - finale_duration: - name: Finale length - description: How long the finale look stays on before the resting state. - default: 10 - selector: - number: - min: 1 - max: 300 - step: 1 - unit_of_measurement: s - mode: box - finale_sound: - name: Finale sound (optional) - default: {} - selector: - media: - finale_color_mode: - name: Finale color - default: rgb - selector: - select: *color_mode_select - finale_rgb: - name: Finale RGB color - description: Used when the color is set to RGB color. - default: [0, 0, 255] - selector: - color_rgb: - finale_kelvin: - name: Finale color temperature - description: Used when the color is set to Color temperature. - default: 3000 - selector: - color_temp: *kelvin_select - finale_brightness: - name: Finale brightness - default: 80 - selector: - number: *brightness_select - finale_effect: - name: Finale effect - description: &effect_description >- - Pick one or type the name exactly as the light lists it. Each light - only gets an effect it supports; the others just change color and - brightness. None stops a running effect. Strobe-style effects - faster than 3 flashes per second can trigger seizures in people - with photosensitive epilepsy. - default: Pulse - selector: - select: *effect_select - - stage_look_section: - name: Stage look and sound - icon: mdi:palette - description: How every stage looks and sounds, unless the stage sets its own. - collapsed: true - input: - stage_color_mode: - name: Stage color - default: rgb - selector: - select: *color_mode_select - stage_rgb: - name: Stage RGB color - description: Used when the color is set to RGB color. - default: [255, 100, 0] - selector: - color_rgb: - stage_kelvin: - name: Stage color temperature - description: Used when the color is set to Color temperature. - default: 3000 - selector: - color_temp: *kelvin_select - stage_brightness: - name: Stage brightness - default: 75 - selector: - number: *brightness_select - stage_effect: - name: Stage effect - description: *effect_description - default: Flicker - selector: - select: *effect_select - stage_sound: - name: Stage sound (optional) - description: Played each time a stage turns on, unless the stage has its own sound. - default: {} - selector: - media: - - end_section: - name: Resting state - icon: mdi:sleep - description: What the lights do after the finale, or after a visitor turns back. - collapsed: true - input: - end_mode: - name: Resting state - default: "off" - selector: - select: - options: - - label: Turn off - value: "off" - - label: Show the resting look below - value: look - - label: Go back to how they were before the sequence - value: restore - abandon_sound: - name: Turned-back sound (optional) - description: Played when a visitor leaves before reaching the finale. - default: {} - selector: - media: - end_color_mode: - name: Resting color - default: kelvin - selector: - select: *color_mode_select - end_rgb: - name: Resting RGB color - description: Used when the color is set to RGB color. - default: [255, 160, 60] - selector: - color_rgb: - end_kelvin: - name: Resting color temperature - description: Used when the color is set to Color temperature. - default: 2700 - selector: - color_temp: *kelvin_select - end_brightness: - name: Resting brightness - default: 40 - selector: - number: *brightness_select - end_effect: - name: Resting effect - description: *effect_description - default: None - selector: - select: *effect_select - - timing_section: - name: Timing - icon: mdi:timer-outline - collapsed: true - input: - step_timeout: - name: Time to reach the next stage - description: >- - After each stage turns on, the visitor has this long to come - within a later stage's distance. If they don't, the lit lights go - to the resting state. - default: 30 - selector: - number: - min: 5 - max: 600 - step: 1 - unit_of_measurement: s - mode: box - cooldown: - name: Cooldown - description: After a sequence ends, wait this long before another can start. - default: 10 - selector: - number: - min: 0 - max: 600 - step: 1 - unit_of_measurement: s - mode: box - transition: - name: Transition - description: Fade time when lights change. 0 changes them instantly. - default: 0 - selector: - number: - min: 0 - max: 10 - step: 0.5 - unit_of_measurement: s - mode: box - sound_delay: - name: Light delay after a sound - description: >- - Speakers take a moment to start a sound. When a step has a sound, - its lights wait this long after the sound is sent so the two land - together. Tune it by ear; 0 changes the lights right away. - default: 0 - selector: - number: - min: 0 - max: 3000 - step: 50 - unit_of_measurement: ms - mode: slider - - options_section: - name: Sound player and options - icon: mdi:cog - collapsed: true - input: - sound_player: - name: Sound player - description: >- - Plays every sound. Leave empty to use the player each sound was - picked from. With Music Assistant, pick the speaker's own player - rather than the Music Assistant one, so music ducks under the - sound instead of pausing. - default: "" - selector: - entity: - filter: - - domain: media_player - set_volume: - name: Set the volume during a sequence - description: >- - Sets the sound player's volume when a sequence starts and puts it - back when the sequence ends. This is the player's only volume, so - music playing on it changes too. Needs a Sound player above. - default: false - selector: - boolean: - sound_volume: - name: Sequence volume - default: 60 - selector: - number: - min: 0 - max: 100 - step: 1 - unit_of_measurement: "%" - mode: slider - enable_entity: - name: Enable switch (optional) - description: >- - Sequences only start while this is on, for example a Halloween - mode toggle. Leave empty to always run. - default: "" - selector: - entity: - filter: - - domain: - - input_boolean - - switch - - binary_sensor - pause_entities: - name: Switches to pause during a sequence (optional) - description: >- - Turned off while a sequence runs and back on afterwards if they - were on, for example a CAST-1's LED Strip Music Mode, which - otherwise takes over the strip when music starts or stops. - default: [] - selector: - entity: - multiple: true - filter: - - domain: - - switch - - input_boolean - -mode: single -max_exceeded: silent - -triggers: - # Every new distance reading; the conditions decide whether it starts one - - trigger: state - entity_id: !input distance_sensor - -variables: - stage_inputs: !input stages - dist_sensor: !input distance_sensor - presence_sensor: !input presence_sensor - finale_distance: !input finale_distance - finale_extra_lights: !input finale_extra_lights - finale_sound: !input finale_sound - stage_sound: !input stage_sound - abandon_sound: !input abandon_sound - end_mode: !input end_mode - transition_s: !input transition - sound_delay: !input sound_delay - sound_player: !input sound_player - set_volume: !input set_volume - sound_volume: !input sound_volume - enable_entity: !input enable_entity - pause_entities: !input pause_entities - stage_look: - color_mode: !input stage_color_mode - rgb: !input stage_rgb - kelvin: !input stage_kelvin - brightness: !input stage_brightness - effect: !input stage_effect - finale_look: - color_mode: !input finale_color_mode - rgb: !input finale_rgb - kelvin: !input finale_kelvin - brightness: !input finale_brightness - effect: !input finale_effect - end_look: - color_mode: !input end_color_mode - rgb: !input end_rgb - kelvin: !input end_kelvin - brightness: !input end_brightness - effect: !input end_effect - # Stages with a distance and lights, farthest first, each with its look - # filled in from the Stage look and its sound resolved to {id, type, player} - stages: >- - {%- set ns = namespace(out=[]) -%} - {%- for s in stage_inputs if s is mapping -%} - {%- set lights = s.get('lights') or [] -%} - {%- set lights = [lights] if lights is string else lights | list -%} - {%- set dist = s.get('distance') | float(0) -%} - {%- if dist > 0 and lights | count > 0 -%} - {%- set own_color = s.get('color_mode') not in [none, ''] -%} - {%- set effect = s.get('effect') -%} - {%- set look = { - 'color_mode': s.get('color_mode') if own_color else stage_look.color_mode, - 'rgb': s.get('rgb') if own_color and s.get('rgb') else stage_look.rgb, - 'kelvin': s.get('kelvin') if own_color and s.get('kelvin') else stage_look.kelvin, - 'brightness': s.get('brightness') if s.get('brightness') is number else stage_look.brightness, - 'effect': effect if effect is string and effect | trim != '' else stage_look.effect - } -%} - {%- set snd = s.get('sound') -%} - {%- set snd = snd if snd is mapping and snd.get('media_content_id') else stage_sound -%} - {%- set snd = snd if snd is mapping else {} -%} - {%- set ns.out = ns.out + [{ - 'distance': dist, - 'lights': lights, - 'look': look, - 'sound': { - 'id': snd.get('media_content_id') or '', - 'type': snd.get('media_content_type') or 'music', - 'player': sound_player or snd.get('entity_id') or '' - } - }] -%} - {%- endif -%} - {%- endfor -%} - {{ ns.out | sort(attribute='distance', reverse=true) }} - # light.turn_on data for the finale, resting state and each stage, in that - # order; the effect is added per light when the look is applied - look_data: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in [finale_look, end_look] + stages | map(attribute='look') | list -%} - {#- Only send a fade when one is set: ESPHome warns when an effect comes with any transition, even 0 -#} - {%- set d = {'brightness_pct': l.brightness | int(100)} -%} - {%- if transition_s | float(0) > 0 -%} - {%- set d = dict(d, transition=transition_s | float(0)) -%} - {%- endif -%} - {%- if l.color_mode == 'rgb' and l.rgb -%} - {%- set d = dict(d, rgb_color=l.rgb | list) -%} - {%- elif l.color_mode == 'kelvin' and l.kelvin -%} - {%- set d = dict(d, color_temp_kelvin=l.kelvin | int) -%} - {%- endif -%} - {%- set ns.out = ns.out + [d] -%} - {%- endfor -%} - {{ ns.out }} - all_lights: >- - {{ (stages | map(attribute='lights') | sum(start=[]) + finale_extra_lights) | unique | list }} - snapshot_scene: "porch_distance_sequence_{{ this.entity_id.split('.')[1] }}" - -conditions: - - condition: template - value_template: "{{ enable_entity == '' or is_state(enable_entity, 'on') }}" - - condition: template - value_template: "{{ stages | count > 0 and finale_distance | float(0) > 0 }}" - # Only a visitor walking in starts a sequence: the last reading was beyond - # the first stage and this one is inside it but short of the finale. - # Someone appearing at the door or walking away never reads that way. The - # far reading must also belong to this visitor, not be left over from an - # earlier one: the target sensor has stayed on since it was taken, or - # without one, it's at most 30 s old - - condition: template - value_template: >- - {%- set prev = trigger.from_state.state | float(0) if trigger.from_state else 0 -%} - {%- set cur = trigger.to_state.state | float(0) if trigger.to_state else 0 -%} - {%- set target = expand([presence_sensor]) | first if presence_sensor != '' else none -%} - {%- if not trigger.from_state or not trigger.to_state -%} - {%- set fresh = false -%} - {%- elif target -%} - {#- 2 s of slack: the target and distance readings can arrive in either order -#} - {%- set fresh = target.state == 'on' - and (target.last_changed - trigger.from_state.last_changed).total_seconds() <= 2 -%} - {%- else -%} - {%- set fresh = (trigger.to_state.last_changed - trigger.from_state.last_changed).total_seconds() <= 30 -%} - {%- endif -%} - {{ fresh and prev > stages[0].distance and 0 < cur <= stages[0].distance - and cur > finale_distance | float(0) }} - -actions: - - variables: - paused: >- - {{ expand(pause_entities) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }} - prev_volume: >- - {{ state_attr(sound_player, 'volume_level') if set_volume and sound_player != '' else none }} - - if: - - condition: template - value_template: "{{ paused | count > 0 }}" - then: - - action: homeassistant.turn_off - target: - entity_id: "{{ paused }}" - - if: - - condition: template - value_template: "{{ set_volume and sound_player != '' }}" - then: - - action: media_player.volume_set - target: - entity_id: "{{ sound_player }}" - data: - volume_level: "{{ (sound_volume | float(60)) / 100 }}" - continue_on_error: true - - if: - - condition: template - value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" - then: - - action: scene.create - data: - scene_id: "{{ snapshot_scene }}" - snapshot_entities: "{{ all_lights }}" - - # idx is the last lit stage (-1 before the first); outcome becomes finale - # or abandon. The first pass lights the first stage without waiting. - # A reading counts only while it's above 0 and the target sensor is on - - variables: - idx: -1 - outcome: "" - - repeat: - while: - - condition: template - value_template: "{{ outcome == '' }}" - sequence: - - wait_template: >- - {%- set d = states(dist_sensor) | float(0) -%} - {%- set ok = d > 0 and (presence_sensor == '' or is_state(presence_sensor, 'on')) -%} - {%- set nxt = stages[idx + 1].distance if idx + 1 < stages | count else finale_distance | float(0) -%} - {{ idx < 0 or (ok and d <= nxt) }} - timeout: !input step_timeout - continue_on_timeout: true - - variables: - reading: >- - {%- set d = states(dist_sensor) | float(0) -%} - {{ d if d > 0 and (presence_sensor == '' or is_state(presence_sensor, 'on')) else 0 }} - - choose: - - conditions: - - condition: template - value_template: "{{ not wait.completed }}" - sequence: - - variables: - outcome: abandon - - conditions: - - condition: template - value_template: "{{ idx >= 0 and reading > 0 and reading <= finale_distance | float(0) }}" - sequence: - # Skipped stages join the finale directly - - variables: - idx: "{{ stages | count - 1 }}" - outcome: finale - default: - # Jump to the closest stage the visitor is within, lighting any - # skipped ones. The first pass always lights at least the first - - variables: - target_idx: >- - {%- set ns = namespace(j=[idx, 0] | max) -%} - {%- if reading > 0 -%} - {%- for s in stages -%} - {%- if loop.index0 > idx and reading <= s.distance -%} - {%- set ns.j = loop.index0 -%} - {%- endif -%} - {%- endfor -%} - {%- endif -%} - {{ ns.j }} - - if: - - condition: template - value_template: "{{ target_idx > idx }}" - then: - - variables: - snd: "{{ stages[target_idx].sound }}" - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for i in range(idx + 1, target_idx + 1) -%} - {%- for l in stages[i].lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[i + 2], 'effect': stages[i].look.effect}] -%} - {%- endfor -%} - {%- endfor -%} - {{ ns.out }} - # play_media can hold the run until the sound ends, so the - # sound gets its own branch and the lights don't wait for it - - parallel: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - action: media_player.play_media - target: - entity_id: "{{ snd.player }}" - data: - media_content_id: "{{ snd.id }}" - media_content_type: "{{ snd.type }}" - announce: true - continue_on_error: true - - sequence: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - delay: - milliseconds: "{{ sound_delay | int(0) }}" - - repeat: &apply_jobs - for_each: "{{ jobs }}" - sequence: - # The look's effect, matched to the name this light uses - # for it; None picks the light's own "None" or "off" - - action: light.turn_on - target: - entity_id: "{{ repeat.item.light }}" - data: >- - {%- set fx = state_attr(repeat.item.light, 'effect_list') or [] -%} - {%- set want = (repeat.item.effect or 'None') | string | trim | lower -%} - {%- set names = ['none', 'off'] if want in ['', 'none', 'off'] else [want] -%} - {%- set ns = namespace(e='') -%} - {%- for f in fx -%} - {%- if ns.e == '' and (f | string | lower) in names -%} - {%- set ns.e = f -%} - {%- endif -%} - {%- endfor -%} - {{ dict(repeat.item.data, effect=ns.e) if ns.e else repeat.item.data }} - continue_on_error: true - - variables: - idx: "{{ target_idx }}" - - - variables: - lit_lights: >- - {{ stages[:idx + 1] | map(attribute='lights') | sum(start=[]) | unique | list }} - raw_sound: "{{ finale_sound if outcome == 'finale' else abandon_sound }}" - - variables: - end_lights: >- - {{ (lit_lights + finale_extra_lights) | unique | list if outcome == 'finale' else lit_lights }} - snd: - id: "{{ (raw_sound.get('media_content_id') if raw_sound is mapping else '') or '' }}" - type: "{{ (raw_sound.get('media_content_type') if raw_sound is mapping else '') or 'music' }}" - player: >- - {{ sound_player or (raw_sound.get('entity_id') if raw_sound is mapping else '') or '' }} - - # The finale or turned-back sound plays in its own branch while the lights - # run the finale and resting state - - parallel: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - action: media_player.play_media - target: - entity_id: "{{ snd.player }}" - data: - media_content_id: "{{ snd.id }}" - media_content_type: "{{ snd.type }}" - announce: true - continue_on_error: true - - sequence: - - if: - - condition: template - value_template: "{{ outcome == 'finale' and snd.id != '' and snd.player != '' }}" - then: - - delay: - milliseconds: "{{ sound_delay | int(0) }}" - - if: - - condition: template - value_template: "{{ outcome == 'finale' }}" - then: - - variables: - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in end_lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[0], 'effect': finale_look.effect}] -%} - {%- endfor -%} - {{ ns.out }} - - repeat: *apply_jobs - - delay: !input finale_duration - - # Resting state - - choose: - - conditions: - - condition: template - value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" - sequence: - - action: scene.turn_on - target: - entity_id: "scene.{{ snapshot_scene }}" - data: - transition: "{{ transition_s | float(0) }}" - continue_on_error: true - - conditions: - - condition: template - value_template: "{{ end_mode == 'look' }}" - sequence: - - variables: - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in end_lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[1], 'effect': end_look.effect}] -%} - {%- endfor -%} - {{ ns.out }} - - repeat: *apply_jobs - default: - - if: - - condition: template - value_template: "{{ end_lights | count > 0 }}" - then: - - action: light.turn_off - target: - entity_id: "{{ end_lights }}" - data: - transition: "{{ transition_s | float(0) }}" - continue_on_error: true - - - if: - - condition: template - value_template: "{{ paused | count > 0 }}" - then: - - action: homeassistant.turn_on - target: - entity_id: "{{ paused }}" - - if: - - condition: template - value_template: "{{ prev_volume is number }}" - then: - - action: media_player.volume_set - target: - entity_id: "{{ sound_player }}" - data: - volume_level: "{{ prev_volume }}" - continue_on_error: true - - delay: !input cooldown diff --git a/Blueprints/Light-Sequence-Motion-Based.yaml b/Blueprints/Light-Sequence-Motion-Based.yaml deleted file mode 100644 index afecb91..0000000 --- a/Blueprints/Light-Sequence-Motion-Based.yaml +++ /dev/null @@ -1,903 +0,0 @@ -blueprint: - name: Light Sequence (Motion-Based) - description: >- - Lights a path in stages when a motion sensor (PIR) sees a visitor. With - one sensor the whole show runs on timers: motion starts it, each stage - turns on a set time after the one before, then the finale plays and all - the lights go to the resting state. - - - With more sensors along the path, any stage or the finale can wait for - its own sensor instead of a timer. If the visitor doesn't reach that - sensor in time, the lit lights go to the resting state early. - - - With more than one sensor, sequences only start when the visitor walks - toward the door: someone setting off the door-side sensors first, on the - way out, doesn't start one. - - - Works with any Home Assistant lights and any on/off motion or occupancy - sensor. Sounds play as announcements, so music playing on the same - speaker ducks under them instead of stopping. - domain: automation - author: Apollo Automation - homeassistant: - min_version: 2025.7.0 - input: - start_section: - name: Start - icon: mdi:motion-sensor - collapsed: false - input: - start_sensors: - name: Start motion sensor - description: >- - Motion here starts a sequence. Usually the sensor farthest from the - door. Pick more than one to start from any of them. - selector: - entity: - multiple: true - filter: &motion_filter - - domain: binary_sensor - device_class: - - motion - - occupancy - - presence - - stages_section: - name: Stages - icon: mdi:walk - collapsed: false - input: - stages: - name: Stages - description: >- - Add one stage per light group, in the order they should turn on. - A stage with a motion sensor waits for that sensor. A stage without - one turns on after its wait time: for the first stage, counted from - the start motion; for the others, from the stage before. An empty - wait time uses the First stage or Later stage wait time under - Timing. - - - If a later stage's sensor sees the visitor first, the stages in - between turn on with it. Use a different sensor for each stage; - a sensor that's still on from an earlier stage moves the sequence - on straight away. - - - Each stage uses the shared Stage look and Stage sound unless you - set its own color, brightness, effect or sound. - default: [] - selector: - object: - multiple: true - label_field: lights - fields: - lights: - label: Lights - required: true - selector: - entity: - multiple: true - filter: - - domain: light - sensor: - label: Wait for this motion sensor (leave empty to use a timer) - selector: - entity: - filter: *motion_filter - delay: - label: Wait time when there's no sensor (leave empty for the default) - selector: - number: &delay_select - min: 0 - max: 600 - step: 0.5 - unit_of_measurement: s - mode: box - sound: - label: Sound (leave empty for the shared Stage sound) - selector: - media: - color_mode: - label: Color (leave empty for the Stage look) - selector: - select: &color_mode_select - mode: dropdown - options: - - label: RGB color - value: rgb - - label: Color temperature (white) - value: kelvin - - label: Don't change the color - value: none - rgb: - label: RGB color - selector: - color_rgb: - kelvin: - label: Color temperature - selector: - color_temp: &kelvin_select - unit: kelvin - min: 2000 - max: 6500 - brightness: - label: Brightness (leave empty for the Stage look) - selector: - number: &brightness_select - min: 1 - max: 100 - step: 1 - unit_of_measurement: "%" - mode: slider - effect: - label: Effect (leave empty for the Stage look) - selector: - select: &effect_select - mode: dropdown - custom_value: true - options: - - None - - Flicker - - Pulse - - Strobe - - Rainbow - - Color Wipe - - Scan - - Twinkle - - Random Twinkle - - Fireworks - - Effect A - - Effect B - - candle - - fire - - prism - - sparkle - - opal - - glisten - - underwater - - cosmos - - sunbeam - - enchant - - finale_section: - name: Finale - icon: mdi:door - collapsed: false - input: - finale_sensor: - name: Finale motion sensor (optional) - description: >- - The finale waits for this sensor, usually the one by the door. - Leave empty to play the finale on a timer after the last stage. - default: "" - selector: - entity: - filter: *motion_filter - finale_delay: - name: Finale wait time - description: >- - Without a finale sensor, the finale plays this long after the last - stage turns on. - default: 5 - selector: - number: *delay_select - finale_extra_lights: - name: Extra finale lights (optional) - description: >- - Lights that join the finale on top of the stage lights, such as a - porch light. - default: [] - selector: - entity: - multiple: true - filter: - - domain: light - finale_duration: - name: Finale length - description: How long the finale look stays on before the resting state. - default: 10 - selector: - number: - min: 1 - max: 300 - step: 1 - unit_of_measurement: s - mode: box - finale_sound: - name: Finale sound (optional) - default: {} - selector: - media: - finale_color_mode: - name: Finale color - default: rgb - selector: - select: *color_mode_select - finale_rgb: - name: Finale RGB color - description: Used when the color is set to RGB color. - default: [0, 0, 255] - selector: - color_rgb: - finale_kelvin: - name: Finale color temperature - description: Used when the color is set to Color temperature. - default: 3000 - selector: - color_temp: *kelvin_select - finale_brightness: - name: Finale brightness - default: 80 - selector: - number: *brightness_select - finale_effect: - name: Finale effect - description: &effect_description >- - Pick one or type the name exactly as the light lists it. Each light - only gets an effect it supports; the others just change color and - brightness. None stops a running effect. Strobe-style effects - faster than 3 flashes per second can trigger seizures in people - with photosensitive epilepsy. - default: Pulse - selector: - select: *effect_select - - stage_look_section: - name: Stage look and sound - icon: mdi:palette - description: How every stage looks and sounds, unless the stage sets its own. - collapsed: true - input: - stage_color_mode: - name: Stage color - default: rgb - selector: - select: *color_mode_select - stage_rgb: - name: Stage RGB color - description: Used when the color is set to RGB color. - default: [255, 100, 0] - selector: - color_rgb: - stage_kelvin: - name: Stage color temperature - description: Used when the color is set to Color temperature. - default: 3000 - selector: - color_temp: *kelvin_select - stage_brightness: - name: Stage brightness - default: 75 - selector: - number: *brightness_select - stage_effect: - name: Stage effect - description: *effect_description - default: Flicker - selector: - select: *effect_select - stage_sound: - name: Stage sound (optional) - description: Played each time a stage turns on, unless the stage has its own sound. - default: {} - selector: - media: - - end_section: - name: Resting state - icon: mdi:sleep - description: What the lights do after the finale, or after a visitor turns back. - collapsed: true - input: - end_mode: - name: Resting state - default: "off" - selector: - select: - options: - - label: Turn off - value: "off" - - label: Show the resting look below - value: look - - label: Go back to how they were before the sequence - value: restore - abandon_sound: - name: Turned-back sound (optional) - description: >- - Played when a visitor doesn't reach a stage's or the finale's - sensor in time. - default: {} - selector: - media: - end_color_mode: - name: Resting color - default: kelvin - selector: - select: *color_mode_select - end_rgb: - name: Resting RGB color - description: Used when the color is set to RGB color. - default: [255, 160, 60] - selector: - color_rgb: - end_kelvin: - name: Resting color temperature - description: Used when the color is set to Color temperature. - default: 2700 - selector: - color_temp: *kelvin_select - end_brightness: - name: Resting brightness - default: 40 - selector: - number: *brightness_select - end_effect: - name: Resting effect - description: *effect_description - default: None - selector: - select: *effect_select - - timing_section: - name: Timing - icon: mdi:timer-outline - collapsed: true - input: - first_delay: - name: First stage wait time - description: >- - How long after the start motion the first stage turns on, when it - has no sensor and doesn't set its own wait time. 0 turns it on - right away. - default: 0 - selector: - number: *delay_select - default_delay: - name: Later stage wait time - description: >- - How long each later stage without a sensor waits after the stage - before it, unless it sets its own wait time. - default: 3 - selector: - number: *delay_select - step_timeout: - name: Time to reach a sensor - description: >- - How long a stage or the finale waits for its own sensor. If the - visitor doesn't set it off in time, the lit lights go to the - resting state. - default: 30 - selector: - number: - min: 5 - max: 600 - step: 1 - unit_of_measurement: s - mode: box - start_guard: - name: Reverse walk guard - description: >- - A sequence only starts if every stage and finale sensor has been - clear for at least this long, so someone walking away from the - door doesn't set it off on the way out. Set it to roughly the time - it takes to walk from the door to the start sensor. Only works - with more than one sensor. - default: 15 - selector: - number: - min: 0 - max: 120 - step: 1 - unit_of_measurement: s - mode: box - rearm: - name: Quiet time before a new show - description: >- - The start sensor must have seen no motion for this long before it - can start another show. A visitor waiting at the door keeps moving - now and then, and each new motion would otherwise replay the - show. The sensor's own hold time after motion counts as motion. - default: 20 - selector: - number: - min: 0 - max: 600 - step: 1 - unit_of_measurement: s - mode: box - cooldown: - name: Cooldown - description: After a sequence ends, wait this long before another can start. - default: 10 - selector: - number: - min: 0 - max: 600 - step: 1 - unit_of_measurement: s - mode: box - transition: - name: Transition - description: Fade time when lights change. 0 changes them instantly. - default: 0 - selector: - number: - min: 0 - max: 10 - step: 0.5 - unit_of_measurement: s - mode: box - sound_delay: - name: Light delay after a sound - description: >- - Speakers take a moment to start a sound. When a step has a sound, - its lights wait this long after the sound is sent so the two land - together. Tune it by ear; 0 changes the lights right away. - default: 0 - selector: - number: - min: 0 - max: 3000 - step: 50 - unit_of_measurement: ms - mode: slider - - options_section: - name: Sound player and options - icon: mdi:cog - collapsed: true - input: - sound_player: - name: Sound player - description: >- - Plays every sound. Leave empty to use the player each sound was - picked from. With Music Assistant, pick the speaker's own player - rather than the Music Assistant one, so music ducks under the - sound instead of pausing. - default: "" - selector: - entity: - filter: - - domain: media_player - set_volume: - name: Set the volume during a sequence - description: >- - Sets the sound player's volume when a sequence starts and puts it - back when the sequence ends. This is the player's only volume, so - music playing on it changes too. Needs a Sound player above. - default: false - selector: - boolean: - sound_volume: - name: Sequence volume - default: 60 - selector: - number: - min: 0 - max: 100 - step: 1 - unit_of_measurement: "%" - mode: slider - enable_entity: - name: Enable switch (optional) - description: >- - Sequences only start while this is on, for example a Halloween - mode toggle. Leave empty to always run. - default: "" - selector: - entity: - filter: - - domain: - - input_boolean - - switch - - binary_sensor - pause_entities: - name: Switches to pause during a sequence (optional) - description: >- - Turned off while a sequence runs and back on afterwards if they - were on, for example a CAST-1's LED Strip Music Mode, which - otherwise takes over the strip when music starts or stops. - default: [] - selector: - entity: - multiple: true - filter: - - domain: - - switch - - input_boolean - -mode: single -max_exceeded: silent - -triggers: - - trigger: state - entity_id: !input start_sensors - from: "off" - to: "on" - -variables: - start_input: !input start_sensors - stage_inputs: !input stages - finale_sensor: !input finale_sensor - finale_delay: !input finale_delay - first_delay: !input first_delay - default_delay: !input default_delay - finale_extra_lights: !input finale_extra_lights - finale_sound: !input finale_sound - stage_sound: !input stage_sound - abandon_sound: !input abandon_sound - end_mode: !input end_mode - start_guard: !input start_guard - rearm: !input rearm - step_timeout: !input step_timeout - transition_s: !input transition - sound_delay: !input sound_delay - sound_player: !input sound_player - set_volume: !input set_volume - sound_volume: !input sound_volume - enable_entity: !input enable_entity - pause_entities: !input pause_entities - stage_look: - color_mode: !input stage_color_mode - rgb: !input stage_rgb - kelvin: !input stage_kelvin - brightness: !input stage_brightness - effect: !input stage_effect - finale_look: - color_mode: !input finale_color_mode - rgb: !input finale_rgb - kelvin: !input finale_kelvin - brightness: !input finale_brightness - effect: !input finale_effect - end_look: - color_mode: !input end_color_mode - rgb: !input end_rgb - kelvin: !input end_kelvin - brightness: !input end_brightness - effect: !input end_effect - start_list: "{{ [start_input] if start_input is string else start_input | list }}" - # Stages with lights, each with its sensor and wait time, its look filled - # in from the Stage look and its sound resolved to {id, type, player} - stages: >- - {%- set ns = namespace(out=[]) -%} - {%- for s in stage_inputs if s is mapping -%} - {%- set lights = s.get('lights') or [] -%} - {%- set lights = [lights] if lights is string else lights | list -%} - {%- if lights | count > 0 -%} - {%- set own_color = s.get('color_mode') not in [none, ''] -%} - {%- set effect = s.get('effect') -%} - {%- set look = { - 'color_mode': s.get('color_mode') if own_color else stage_look.color_mode, - 'rgb': s.get('rgb') if own_color and s.get('rgb') else stage_look.rgb, - 'kelvin': s.get('kelvin') if own_color and s.get('kelvin') else stage_look.kelvin, - 'brightness': s.get('brightness') if s.get('brightness') is number else stage_look.brightness, - 'effect': effect if effect is string and effect | trim != '' else stage_look.effect - } -%} - {%- set snd = s.get('sound') -%} - {%- set snd = snd if snd is mapping and snd.get('media_content_id') else stage_sound -%} - {%- set snd = snd if snd is mapping else {} -%} - {%- set ns.out = ns.out + [{ - 'sensor': s.get('sensor') or '', - 'delay': s.get('delay') if s.get('delay') is number - else (first_delay if ns.out | count == 0 else default_delay) | float(0), - 'lights': lights, - 'look': look, - 'sound': { - 'id': snd.get('media_content_id') or '', - 'type': snd.get('media_content_type') or 'music', - 'player': sound_player or snd.get('entity_id') or '' - } - }] -%} - {%- endif -%} - {%- endfor -%} - {{ ns.out }} - # The sensor of each step, stages then the finale; '' for a timed step - step_sensors: "{{ stages | map(attribute='sensor') | list + [finale_sensor or ''] }}" - # light.turn_on data for the finale, resting state and each stage, in that - # order; the effect is added per light when the look is applied - look_data: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in [finale_look, end_look] + stages | map(attribute='look') | list -%} - {#- Only send a fade when one is set: ESPHome warns when an effect comes with any transition, even 0 -#} - {%- set d = {'brightness_pct': l.brightness | int(100)} -%} - {%- if transition_s | float(0) > 0 -%} - {%- set d = dict(d, transition=transition_s | float(0)) -%} - {%- endif -%} - {%- if l.color_mode == 'rgb' and l.rgb -%} - {%- set d = dict(d, rgb_color=l.rgb | list) -%} - {%- elif l.color_mode == 'kelvin' and l.kelvin -%} - {%- set d = dict(d, color_temp_kelvin=l.kelvin | int) -%} - {%- endif -%} - {%- set ns.out = ns.out + [d] -%} - {%- endfor -%} - {{ ns.out }} - all_lights: >- - {{ (stages | map(attribute='lights') | sum(start=[]) + finale_extra_lights) | unique | list }} - snapshot_scene: "porch_motion_sequence_{{ this.entity_id.split('.')[1] }}" - -conditions: - - condition: template - value_template: "{{ enable_entity == '' or is_state(enable_entity, 'on') }}" - - condition: template - value_template: "{{ stages | count > 0 }}" - # The start sensor was clear long enough before this motion: a new arrival, - # not a visitor still waiting at the door - - condition: template - value_template: >- - {{ not trigger.from_state or not trigger.to_state - or (trigger.to_state.last_changed - trigger.from_state.last_changed).total_seconds() - >= rearm | float(0) }} - # Reverse walk guard: every stage and finale sensor other than the start - # sensors has been clear for a while, so the visitor didn't come from the door - - condition: template - value_template: >- - {%- set others = step_sensors | reject('eq', '') | reject('in', start_list) | unique | list -%} - {%- set ns = namespace(ok=true) -%} - {%- for s in expand(others) -%} - {%- if s.state == 'on' or (now() - s.last_changed).total_seconds() < start_guard | float(0) -%} - {%- set ns.ok = false -%} - {%- endif -%} - {%- endfor -%} - {{ ns.ok }} - -actions: - # Pausing switches, the volume and the snapshot wait until the first lights - # change, so a passerby who never reaches a first-stage sensor touches nothing - - variables: - started: false - paused: [] - prev_volume: null - - # idx is the last lit stage (-1 before the first). Each pass waits for the - # next step (the next stage, or the finale after the last one): for its - # sensor, or for its wait time when it has none. A later step's sensor - # going on ends the wait early and jumps ahead. outcome becomes finale or - # abandon - - variables: - idx: -1 - outcome: "" - - repeat: - while: - - condition: template - value_template: "{{ outcome == '' }}" - sequence: - - variables: - nstep: "{{ idx + 1 }}" - next_sensor: "{{ step_sensors[idx + 1] }}" - next_delay: >- - {{ (stages[idx + 1].delay if idx + 1 < stages | count else finale_delay) | float(0) }} - later_sensors: "{{ step_sensors[idx + 1:] | reject('eq', '') | unique | list }}" - - wait_template: >- - {{ (next_sensor == '' and next_delay <= 0) - or expand(later_sensors) | selectattr('state', 'eq', 'on') | list | count > 0 }} - timeout: - seconds: "{{ step_timeout if next_sensor != '' else next_delay }}" - continue_on_timeout: true - - choose: - - conditions: - - condition: template - value_template: "{{ not wait.completed and next_sensor != '' }}" - sequence: - - variables: - outcome: abandon - default: - # The furthest step whose sensor is on, or the next step when - # its timer ran out - - variables: - target: >- - {%- set ns = namespace(t=nstep) -%} - {%- for s in step_sensors -%} - {%- if loop.index0 > nstep and s != '' and is_state(s, 'on') -%} - {%- set ns.t = loop.index0 -%} - {%- endif -%} - {%- endfor -%} - {{ ns.t }} - - if: - - condition: template - value_template: "{{ not started }}" - then: - - variables: - started: true - paused: >- - {{ expand(pause_entities) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }} - prev_volume: >- - {{ state_attr(sound_player, 'volume_level') if set_volume and sound_player != '' else none }} - - if: - - condition: template - value_template: "{{ paused | count > 0 }}" - then: - - action: homeassistant.turn_off - target: - entity_id: "{{ paused }}" - - if: - - condition: template - value_template: "{{ set_volume and sound_player != '' }}" - then: - - action: media_player.volume_set - target: - entity_id: "{{ sound_player }}" - data: - volume_level: "{{ (sound_volume | float(60)) / 100 }}" - continue_on_error: true - - if: - - condition: template - value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" - then: - - action: scene.create - data: - scene_id: "{{ snapshot_scene }}" - snapshot_entities: "{{ all_lights }}" - - if: - - condition: template - value_template: "{{ target >= stages | count }}" - then: - # Skipped stages join the finale directly - - variables: - idx: "{{ stages | count - 1 }}" - outcome: finale - else: - - variables: - snd: "{{ stages[target].sound }}" - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for i in range(idx + 1, target + 1) -%} - {%- for l in stages[i].lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[i + 2], 'effect': stages[i].look.effect}] -%} - {%- endfor -%} - {%- endfor -%} - {{ ns.out }} - # play_media can hold the run until the sound ends, so the - # sound gets its own branch and the lights don't wait for it - - parallel: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - action: media_player.play_media - target: - entity_id: "{{ snd.player }}" - data: - media_content_id: "{{ snd.id }}" - media_content_type: "{{ snd.type }}" - announce: true - continue_on_error: true - - sequence: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - delay: - milliseconds: "{{ sound_delay | int(0) }}" - - repeat: &apply_jobs - for_each: "{{ jobs }}" - sequence: - # The look's effect, matched to the name this light uses - # for it; None picks the light's own "None" or "off" - - action: light.turn_on - target: - entity_id: "{{ repeat.item.light }}" - data: >- - {%- set fx = state_attr(repeat.item.light, 'effect_list') or [] -%} - {%- set want = (repeat.item.effect or 'None') | string | trim | lower -%} - {%- set names = ['none', 'off'] if want in ['', 'none', 'off'] else [want] -%} - {%- set ns = namespace(e='') -%} - {%- for f in fx -%} - {%- if ns.e == '' and (f | string | lower) in names -%} - {%- set ns.e = f -%} - {%- endif -%} - {%- endfor -%} - {{ dict(repeat.item.data, effect=ns.e) if ns.e else repeat.item.data }} - continue_on_error: true - - variables: - idx: "{{ target }}" - - - variables: - lit_lights: >- - {{ stages[:idx + 1] | map(attribute='lights') | sum(start=[]) | unique | list }} - - variables: - # No turned-back sound when the visitor never reached the first stage - raw_sound: >- - {{ finale_sound if outcome == 'finale' else (abandon_sound if lit_lights | count > 0 else {}) }} - end_lights: >- - {{ (lit_lights + finale_extra_lights) | unique | list if outcome == 'finale' else lit_lights }} - - variables: - snd: - id: "{{ (raw_sound.get('media_content_id') if raw_sound is mapping else '') or '' }}" - type: "{{ (raw_sound.get('media_content_type') if raw_sound is mapping else '') or 'music' }}" - player: >- - {{ sound_player or (raw_sound.get('entity_id') if raw_sound is mapping else '') or '' }} - - # The finale or turned-back sound plays in its own branch while the lights - # run the finale and resting state - - parallel: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - action: media_player.play_media - target: - entity_id: "{{ snd.player }}" - data: - media_content_id: "{{ snd.id }}" - media_content_type: "{{ snd.type }}" - announce: true - continue_on_error: true - - sequence: - - if: - - condition: template - value_template: "{{ outcome == 'finale' and snd.id != '' and snd.player != '' }}" - then: - - delay: - milliseconds: "{{ sound_delay | int(0) }}" - - if: - - condition: template - value_template: "{{ outcome == 'finale' }}" - then: - - variables: - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in end_lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[0], 'effect': finale_look.effect}] -%} - {%- endfor -%} - {{ ns.out }} - - repeat: *apply_jobs - - delay: !input finale_duration - - # Resting state - - choose: - - conditions: - - condition: template - value_template: "{{ end_mode == 'restore' and started and all_lights | count > 0 }}" - sequence: - - action: scene.turn_on - target: - entity_id: "scene.{{ snapshot_scene }}" - data: - transition: "{{ transition_s | float(0) }}" - continue_on_error: true - - conditions: - - condition: template - value_template: "{{ end_mode == 'look' }}" - sequence: - - variables: - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in end_lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[1], 'effect': end_look.effect}] -%} - {%- endfor -%} - {{ ns.out }} - - repeat: *apply_jobs - default: - - if: - - condition: template - value_template: "{{ end_lights | count > 0 }}" - then: - - action: light.turn_off - target: - entity_id: "{{ end_lights }}" - data: - transition: "{{ transition_s | float(0) }}" - continue_on_error: true - - - if: - - condition: template - value_template: "{{ paused | count > 0 }}" - then: - - action: homeassistant.turn_on - target: - entity_id: "{{ paused }}" - - if: - - condition: template - value_template: "{{ prev_volume is number }}" - then: - - action: media_player.volume_set - target: - entity_id: "{{ sound_player }}" - data: - volume_level: "{{ prev_volume }}" - continue_on_error: true - - delay: !input cooldown diff --git a/Blueprints/Light-Sequence-Porch-Zone-Based.yaml b/Blueprints/Light-Sequence-Porch-Zone-Based.yaml deleted file mode 100644 index 65fc162..0000000 --- a/Blueprints/Light-Sequence-Porch-Zone-Based.yaml +++ /dev/null @@ -1,781 +0,0 @@ -blueprint: - name: Light Sequence (Zone-Based) - description: >- - Lights a path in stages as a visitor walks through presence zones toward - the door. Each zone can be any on/off occupancy sensor, such as a radar - zone (LD2450 with Zone Mapper, for example) or a motion sensor. - - - Entering the first stage's zone turns on its lights. Each later zone - turns on its own lights while the earlier ones stay on. Reaching the - finale zone switches every lit light to the finale look, then all of - them go to the resting state. If the visitor doesn't reach the next zone - in time, the lit lights go to the resting state early. - - - Stages only advance toward the door. Walking out through the zones in - reverse doesn't start a sequence. - - - Works with any Home Assistant lights. Sounds play as announcements, so - music playing on the same speaker ducks under them instead of stopping. - domain: automation - author: Apollo Automation - homeassistant: - min_version: 2025.7.0 - input: - stages_section: - name: Stages - icon: mdi:walk - collapsed: false - input: - stages: - name: Stages - description: >- - Add one stage per zone, in the order a visitor walks through them - toward the door. The first stage's zone starts the sequence. If a - visitor reaches a later zone first, the stages in between turn on - with it. - - - Each stage uses the shared Stage look and Stage sound unless you - set its own color, brightness, effect or sound. - default: [] - selector: - object: - multiple: true - label_field: zone - fields: - zone: - label: Zone - required: true - selector: - entity: - filter: &zone_filter - - domain: binary_sensor - device_class: - - occupancy - - presence - - motion - lights: - label: Lights - required: true - selector: - entity: - multiple: true - filter: - - domain: light - sound: - label: Sound (leave empty for the shared Stage sound) - selector: - media: - color_mode: - label: Color (leave empty for the Stage look) - selector: - select: &color_mode_select - mode: dropdown - options: - - label: RGB color - value: rgb - - label: Color temperature (white) - value: kelvin - - label: Don't change the color - value: none - rgb: - label: RGB color - selector: - color_rgb: - kelvin: - label: Color temperature - selector: - color_temp: &kelvin_select - unit: kelvin - min: 2000 - max: 6500 - brightness: - label: Brightness (leave empty for the Stage look) - selector: - number: &brightness_select - min: 1 - max: 100 - step: 1 - unit_of_measurement: "%" - mode: slider - effect: - label: Effect (leave empty for the Stage look) - selector: - select: &effect_select - mode: dropdown - custom_value: true - options: - - None - - Flicker - - Pulse - - Strobe - - Rainbow - - Color Wipe - - Scan - - Twinkle - - Random Twinkle - - Fireworks - - Effect A - - Effect B - - candle - - fire - - prism - - sparkle - - opal - - glisten - - underwater - - cosmos - - sunbeam - - enchant - - finale_section: - name: Finale - icon: mdi:door - collapsed: false - input: - finale_zone: - name: Finale zone - description: The zone by the door. Entering it plays the finale. - default: "" - selector: - entity: - filter: *zone_filter - finale_extra_lights: - name: Extra finale lights (optional) - description: >- - Lights that join the finale on top of the stage lights, such as a - porch light. - default: [] - selector: - entity: - multiple: true - filter: - - domain: light - finale_duration: - name: Finale length - description: How long the finale look stays on before the resting state. - default: 10 - selector: - number: - min: 1 - max: 300 - step: 1 - unit_of_measurement: s - mode: box - finale_sound: - name: Finale sound (optional) - default: {} - selector: - media: - finale_color_mode: - name: Finale color - default: rgb - selector: - select: *color_mode_select - finale_rgb: - name: Finale RGB color - description: Used when the color is set to RGB color. - default: [0, 0, 255] - selector: - color_rgb: - finale_kelvin: - name: Finale color temperature - description: Used when the color is set to Color temperature. - default: 3000 - selector: - color_temp: *kelvin_select - finale_brightness: - name: Finale brightness - default: 80 - selector: - number: *brightness_select - finale_effect: - name: Finale effect - description: &effect_description >- - Pick one or type the name exactly as the light lists it. Each light - only gets an effect it supports; the others just change color and - brightness. None stops a running effect. Strobe-style effects - faster than 3 flashes per second can trigger seizures in people - with photosensitive epilepsy. - default: Pulse - selector: - select: *effect_select - - stage_look_section: - name: Stage look and sound - icon: mdi:palette - description: How every stage looks and sounds, unless the stage sets its own. - collapsed: true - input: - stage_color_mode: - name: Stage color - default: rgb - selector: - select: *color_mode_select - stage_rgb: - name: Stage RGB color - description: Used when the color is set to RGB color. - default: [255, 100, 0] - selector: - color_rgb: - stage_kelvin: - name: Stage color temperature - description: Used when the color is set to Color temperature. - default: 3000 - selector: - color_temp: *kelvin_select - stage_brightness: - name: Stage brightness - default: 75 - selector: - number: *brightness_select - stage_effect: - name: Stage effect - description: *effect_description - default: Flicker - selector: - select: *effect_select - stage_sound: - name: Stage sound (optional) - description: Played each time a stage turns on, unless the stage has its own sound. - default: {} - selector: - media: - - end_section: - name: Resting state - icon: mdi:sleep - description: What the lights do after the finale, or after a visitor turns back. - collapsed: true - input: - end_mode: - name: Resting state - default: "off" - selector: - select: - options: - - label: Turn off - value: "off" - - label: Show the resting look below - value: look - - label: Go back to how they were before the sequence - value: restore - abandon_sound: - name: Turned-back sound (optional) - description: Played when a visitor leaves before reaching the finale. - default: {} - selector: - media: - end_color_mode: - name: Resting color - default: kelvin - selector: - select: *color_mode_select - end_rgb: - name: Resting RGB color - description: Used when the color is set to RGB color. - default: [255, 160, 60] - selector: - color_rgb: - end_kelvin: - name: Resting color temperature - description: Used when the color is set to Color temperature. - default: 2700 - selector: - color_temp: *kelvin_select - end_brightness: - name: Resting brightness - default: 40 - selector: - number: *brightness_select - end_effect: - name: Resting effect - description: *effect_description - default: None - selector: - select: *effect_select - - timing_section: - name: Timing - icon: mdi:timer-outline - collapsed: true - input: - step_timeout: - name: Time to reach the next zone - description: >- - After each stage turns on, the visitor has this long to reach a - later zone. If they don't, the lit lights go to the resting state. - default: 30 - selector: - number: - min: 5 - max: 600 - step: 1 - unit_of_measurement: s - mode: box - start_guard: - name: Reverse walk guard - description: >- - The first zone only starts a sequence if the next zone has been - clear for at least this long, so someone walking away from the - door doesn't set it off on the way out. - default: 3 - selector: - number: - min: 0 - max: 60 - step: 1 - unit_of_measurement: s - mode: box - cooldown: - name: Cooldown - description: After a sequence ends, wait this long before another can start. - default: 10 - selector: - number: - min: 0 - max: 600 - step: 1 - unit_of_measurement: s - mode: box - transition: - name: Transition - description: Fade time when lights change. 0 changes them instantly. - default: 0 - selector: - number: - min: 0 - max: 10 - step: 0.5 - unit_of_measurement: s - mode: box - sound_delay: - name: Light delay after a sound - description: >- - Speakers take a moment to start a sound. When a step has a sound, - its lights wait this long after the sound is sent so the two land - together. Tune it by ear; 0 changes the lights right away. - default: 0 - selector: - number: - min: 0 - max: 3000 - step: 50 - unit_of_measurement: ms - mode: slider - - options_section: - name: Sound player and options - icon: mdi:cog - collapsed: true - input: - sound_player: - name: Sound player - description: >- - Plays every sound. Leave empty to use the player each sound was - picked from. - default: "" - selector: - entity: - filter: - - domain: media_player - set_volume: - name: Set the volume during a sequence - description: >- - Sets the sound player's volume when a sequence starts and puts it - back when the sequence ends. This is the player's only volume, so - music playing on it changes too. Needs a Sound player above. - default: false - selector: - boolean: - sound_volume: - name: Sequence volume - default: 60 - selector: - number: - min: 0 - max: 100 - step: 1 - unit_of_measurement: "%" - mode: slider - enable_entity: - name: Enable switch (optional) - description: >- - Sequences only start while this is on, for example a Halloween - mode toggle. Leave empty to always run. - default: "" - selector: - entity: - filter: - - domain: - - input_boolean - - switch - - binary_sensor - pause_entities: - name: Switches to pause during a sequence (optional) - description: >- - Turned off while a sequence runs and back on afterwards if they - were on, for example a CAST-1's LED Strip Music Mode, which - otherwise takes over the strip when music starts or stops. - default: [] - selector: - entity: - multiple: true - filter: - - domain: - - switch - - input_boolean - -mode: single -max_exceeded: silent - -trigger_variables: - trigger_stages: !input stages - -triggers: - # The first stage's zone turning on - - trigger: template - value_template: >- - {{ trigger_stages | count > 0 and is_state(trigger_stages[0].zone, 'on') }} - -variables: - stage_inputs: !input stages - finale_zone: !input finale_zone - finale_extra_lights: !input finale_extra_lights - finale_sound: !input finale_sound - stage_sound: !input stage_sound - abandon_sound: !input abandon_sound - end_mode: !input end_mode - start_guard: !input start_guard - transition_s: !input transition - sound_delay: !input sound_delay - sound_player: !input sound_player - set_volume: !input set_volume - sound_volume: !input sound_volume - enable_entity: !input enable_entity - pause_entities: !input pause_entities - stage_look: - color_mode: !input stage_color_mode - rgb: !input stage_rgb - kelvin: !input stage_kelvin - brightness: !input stage_brightness - effect: !input stage_effect - finale_look: - color_mode: !input finale_color_mode - rgb: !input finale_rgb - kelvin: !input finale_kelvin - brightness: !input finale_brightness - effect: !input finale_effect - end_look: - color_mode: !input end_color_mode - rgb: !input end_rgb - kelvin: !input end_kelvin - brightness: !input end_brightness - effect: !input end_effect - # Stages with a zone and lights, each with its look filled in from the - # Stage look and its sound resolved to {id, type, player} - stages: >- - {%- set ns = namespace(out=[]) -%} - {%- for s in stage_inputs if s is mapping -%} - {%- set lights = s.get('lights') or [] -%} - {%- set lights = [lights] if lights is string else lights | list -%} - {%- if s.get('zone') and lights | count > 0 -%} - {%- set own_color = s.get('color_mode') not in [none, ''] -%} - {%- set effect = s.get('effect') -%} - {%- set look = { - 'color_mode': s.get('color_mode') if own_color else stage_look.color_mode, - 'rgb': s.get('rgb') if own_color and s.get('rgb') else stage_look.rgb, - 'kelvin': s.get('kelvin') if own_color and s.get('kelvin') else stage_look.kelvin, - 'brightness': s.get('brightness') if s.get('brightness') is number else stage_look.brightness, - 'effect': effect if effect is string and effect | trim != '' else stage_look.effect - } -%} - {%- set snd = s.get('sound') -%} - {%- set snd = snd if snd is mapping and snd.get('media_content_id') else stage_sound -%} - {%- set snd = snd if snd is mapping else {} -%} - {%- set ns.out = ns.out + [{ - 'zone': s.get('zone'), - 'lights': lights, - 'look': look, - 'sound': { - 'id': snd.get('media_content_id') or '', - 'type': snd.get('media_content_type') or 'music', - 'player': sound_player or snd.get('entity_id') or '' - } - }] -%} - {%- endif -%} - {%- endfor -%} - {{ ns.out }} - # light.turn_on data for the finale, resting state and each stage, in that - # order; the effect is added per light when the look is applied - look_data: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in [finale_look, end_look] + stages | map(attribute='look') | list -%} - {#- Only send a fade when one is set: ESPHome warns when an effect comes with any transition, even 0 -#} - {%- set d = {'brightness_pct': l.brightness | int(100)} -%} - {%- if transition_s | float(0) > 0 -%} - {%- set d = dict(d, transition=transition_s | float(0)) -%} - {%- endif -%} - {%- if l.color_mode == 'rgb' and l.rgb -%} - {%- set d = dict(d, rgb_color=l.rgb | list) -%} - {%- elif l.color_mode == 'kelvin' and l.kelvin -%} - {%- set d = dict(d, color_temp_kelvin=l.kelvin | int) -%} - {%- endif -%} - {%- set ns.out = ns.out + [d] -%} - {%- endfor -%} - {{ ns.out }} - # The zone after the first stage, used by the reverse walk guard - next_zone: "{{ stages[1].zone if stages | count > 1 else finale_zone }}" - all_lights: >- - {{ (stages | map(attribute='lights') | sum(start=[]) + finale_extra_lights) | unique | list }} - snapshot_scene: "porch_zone_sequence_{{ this.entity_id.split('.')[1] }}" - -conditions: - - condition: template - value_template: "{{ enable_entity == '' or is_state(enable_entity, 'on') }}" - - condition: template - value_template: "{{ stages | count > 0 and finale_zone != '' }}" - - condition: template - value_template: >- - {%- set nxt = expand([next_zone]) | first -%} - {{ nxt is not defined or (nxt.state != 'on' - and (now() - nxt.last_changed).total_seconds() >= start_guard | float(0)) }} - -actions: - - variables: - paused: >- - {{ expand(pause_entities) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }} - prev_volume: >- - {{ state_attr(sound_player, 'volume_level') if set_volume and sound_player != '' else none }} - - if: - - condition: template - value_template: "{{ paused | count > 0 }}" - then: - - action: homeassistant.turn_off - target: - entity_id: "{{ paused }}" - - if: - - condition: template - value_template: "{{ set_volume and sound_player != '' }}" - then: - - action: media_player.volume_set - target: - entity_id: "{{ sound_player }}" - data: - volume_level: "{{ (sound_volume | float(60)) / 100 }}" - continue_on_error: true - - if: - - condition: template - value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" - then: - - action: scene.create - data: - scene_id: "{{ snapshot_scene }}" - snapshot_entities: "{{ all_lights }}" - - # idx is the last lit stage (-1 before the first); outcome becomes finale - # or abandon. The first pass lights the first stage without waiting - - variables: - idx: -1 - outcome: "" - - repeat: - while: - - condition: template - value_template: "{{ outcome == '' }}" - sequence: - - wait_template: >- - {{ idx < 0 or is_state(finale_zone, 'on') - or expand(stages[idx + 1:] | map(attribute='zone') | list) - | selectattr('state', 'eq', 'on') | list | count > 0 }} - timeout: !input step_timeout - continue_on_timeout: true - - choose: - - conditions: - - condition: template - value_template: "{{ not wait.completed }}" - sequence: - - variables: - outcome: abandon - - conditions: - - condition: template - value_template: "{{ idx >= 0 and is_state(finale_zone, 'on') }}" - sequence: - # Skipped stages join the finale directly - - variables: - idx: "{{ stages | count - 1 }}" - outcome: finale - default: - # Jump to the furthest occupied stage, lighting any skipped ones - - variables: - target_idx: >- - {%- set ns = namespace(j=[idx, 0] | max) -%} - {%- for s in stages -%} - {%- if loop.index0 > idx and is_state(s.zone, 'on') -%} - {%- set ns.j = loop.index0 -%} - {%- endif -%} - {%- endfor -%} - {{ ns.j }} - - if: - - condition: template - value_template: "{{ target_idx > idx }}" - then: - - variables: - snd: "{{ stages[target_idx].sound }}" - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for i in range(idx + 1, target_idx + 1) -%} - {%- for l in stages[i].lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[i + 2], 'effect': stages[i].look.effect}] -%} - {%- endfor -%} - {%- endfor -%} - {{ ns.out }} - # play_media can hold the run until the sound ends, so the - # sound gets its own branch and the lights don't wait for it - - parallel: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - action: media_player.play_media - target: - entity_id: "{{ snd.player }}" - data: - media_content_id: "{{ snd.id }}" - media_content_type: "{{ snd.type }}" - announce: true - continue_on_error: true - - sequence: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - delay: - milliseconds: "{{ sound_delay | int(0) }}" - - repeat: &apply_jobs - for_each: "{{ jobs }}" - sequence: - # The look's effect, matched to the name this light uses - # for it; None picks the light's own "None" or "off" - - action: light.turn_on - target: - entity_id: "{{ repeat.item.light }}" - data: >- - {%- set fx = state_attr(repeat.item.light, 'effect_list') or [] -%} - {%- set want = (repeat.item.effect or 'None') | string | trim | lower -%} - {%- set names = ['none', 'off'] if want in ['', 'none', 'off'] else [want] -%} - {%- set ns = namespace(e='') -%} - {%- for f in fx -%} - {%- if ns.e == '' and (f | string | lower) in names -%} - {%- set ns.e = f -%} - {%- endif -%} - {%- endfor -%} - {{ dict(repeat.item.data, effect=ns.e) if ns.e else repeat.item.data }} - continue_on_error: true - - variables: - idx: "{{ target_idx }}" - - - variables: - lit_lights: >- - {{ stages[:idx + 1] | map(attribute='lights') | sum(start=[]) | unique | list }} - raw_sound: "{{ finale_sound if outcome == 'finale' else abandon_sound }}" - - variables: - end_lights: >- - {{ (lit_lights + finale_extra_lights) | unique | list if outcome == 'finale' else lit_lights }} - snd: - id: "{{ (raw_sound.get('media_content_id') if raw_sound is mapping else '') or '' }}" - type: "{{ (raw_sound.get('media_content_type') if raw_sound is mapping else '') or 'music' }}" - player: >- - {{ sound_player or (raw_sound.get('entity_id') if raw_sound is mapping else '') or '' }} - - # The finale or turned-back sound plays in its own branch while the lights - # run the finale and resting state - - parallel: - - if: - - condition: template - value_template: "{{ snd.id != '' and snd.player != '' }}" - then: - - action: media_player.play_media - target: - entity_id: "{{ snd.player }}" - data: - media_content_id: "{{ snd.id }}" - media_content_type: "{{ snd.type }}" - announce: true - continue_on_error: true - - sequence: - - if: - - condition: template - value_template: "{{ outcome == 'finale' and snd.id != '' and snd.player != '' }}" - then: - - delay: - milliseconds: "{{ sound_delay | int(0) }}" - - if: - - condition: template - value_template: "{{ outcome == 'finale' }}" - then: - - variables: - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in end_lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[0], 'effect': finale_look.effect}] -%} - {%- endfor -%} - {{ ns.out }} - - repeat: *apply_jobs - - delay: !input finale_duration - - # Resting state - - choose: - - conditions: - - condition: template - value_template: "{{ end_mode == 'restore' and all_lights | count > 0 }}" - sequence: - - action: scene.turn_on - target: - entity_id: "scene.{{ snapshot_scene }}" - data: - transition: "{{ transition_s | float(0) }}" - continue_on_error: true - - conditions: - - condition: template - value_template: "{{ end_mode == 'look' }}" - sequence: - - variables: - jobs: >- - {%- set ns = namespace(out=[]) -%} - {%- for l in end_lights -%} - {%- set ns.out = ns.out + [{'light': l, 'data': look_data[1], 'effect': end_look.effect}] -%} - {%- endfor -%} - {{ ns.out }} - - repeat: *apply_jobs - default: - - if: - - condition: template - value_template: "{{ end_lights | count > 0 }}" - then: - - action: light.turn_off - target: - entity_id: "{{ end_lights }}" - data: - transition: "{{ transition_s | float(0) }}" - continue_on_error: true - - - if: - - condition: template - value_template: "{{ paused | count > 0 }}" - then: - - action: homeassistant.turn_on - target: - entity_id: "{{ paused }}" - - if: - - condition: template - value_template: "{{ prev_volume is number }}" - then: - - action: media_player.volume_set - target: - entity_id: "{{ sound_player }}" - data: - volume_level: "{{ prev_volume }}" - continue_on_error: true - - delay: !input cooldown diff --git a/Blueprints/README.md b/Blueprints/README.md deleted file mode 100644 index 795c3ac..0000000 --- a/Blueprints/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Porch Light Sequence Blueprints - -Home Assistant blueprints for a Halloween porch display. As a visitor walks up to the door, lights turn on in stages along the path. Each stage can play a sound, and the visitor reaching the door plays a finale. Afterwards the lights go to a resting state. If the visitor turns back partway, the lights go to the resting state on their own instead of staying on. - -They work with any Home Assistant lights (a CAST-1 LED strip, Hue bulbs and so on) and any speaker. Pick the blueprint that matches your sensors: - -**Zone-Based**: Presence zones, such as LD2450 radar zones made with Zone Mapper, or any on/off occupancy sensors - -[![Import blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Zone-Based.yaml) - -**Distance-Based**: One radar distance reading, such as an LD2410 or LD2412 (Apollo R PRO-1) mounted by the door - -[![Import blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Distance-Based.yaml) - -**Motion-Based**: One or more PIR motion sensors, such as the ESPHome Starter Kit - -[![Import blueprint](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https%3A%2F%2Fgithub.com%2FApolloAutomation%2FCAST-1%2Fblob%2Fmain%2FBlueprints%2FCAST-1-Porch-Motion-Based.yaml) - -All three need Home Assistant 2025.7 or newer. - -## Install - -1. Click **Import** next to the blueprint you want, then click **Preview** and **Import blueprint** in Home Assistant. -2. Go to **Settings → Automations & scenes → Blueprints**, select the blueprint, and fill it in. The steps below explain each section. -3. Save the automation. - -To install by hand instead, copy the `.yaml` file into `config/blueprints/automation/apollo/` in Home Assistant. Then go to **Developer tools → YAML** and click **Automations** under reload. - -## Set up the stages - -Each stage is a group of lights that turns on as the visitor gets closer. Click **Add** under **Stages** for each one. Stages that are already on stay on as later ones light up. - -- **Lights:** one or more lights per stage. With a CAST-1 strip, use [partition lights](../README.md#splitting-the-strip-into-segments) to give each stage its own section of the strip. -- **Look:** every stage uses the shared **Stage look** (color, brightness and effect) unless you set its own. -- **Effects:** pick an effect from the list or type the name exactly as your light shows it. Each light only gets effects it supports; other lights just change color and brightness. -- **Sounds:** the optional **Stage sound** plays as each stage turns on. A stage can also have its own sound. - -> [!WARNING] -> Strobe-style effects faster than 3 flashes per second can trigger seizures in people with photosensitive epilepsy. - -**Finale:** the finale switches every lit light, plus any **Extra finale lights** such as a porch light, to the finale look for the **Finale length**. Then the lights go to the **Resting state**. The resting state can turn them off, show a resting look, or put them back the way they were before the sequence. - -**Turned back:** if the visitor doesn't reach the next stage within the time limit, the lit lights go to the resting state. The optional **Turned-back sound** plays then. In Motion-Based, this only applies to a stage or finale that waits for its own sensor; a show running on timers always plays through. - -## Zone-Based - -- Add one stage per zone, in the order a visitor walks through them, and set the **Finale zone** to the zone by the door. Zones can be any on/off occupancy, presence or motion sensor. -- If a visitor enters a later zone first, the stages in between turn on with it. -- Stages only move toward the door. The **Reverse walk guard** stops someone walking out of the house from starting a sequence. - -## Distance-Based - -- Mount the radar by the door, facing out, so the distance shrinks as a visitor walks up. -- **Distance sensor:** use the radar's **Moving Distance**, which ignores still objects such as plants or parked cars. -- **Target sensor:** use the radar's overall presence or target sensor, which stays on for people standing still. -- **Distances:** give each stage the distance at which it turns on, and set a smaller **Finale distance**. Use the unit your sensor shows in Home Assistant, such as inches or cm. Stages can be added in any order; they're sorted farthest first. -- **Spacing:** LD2410 radars measure in steps of about 75 cm (30 in), so space stages at least that far apart. -- **Starting:** a sequence starts when a visitor walks in across the first stage's distance. Keep that distance a little inside the radar's range so it sees visitors coming. - -## Motion-Based - -- **Start motion sensor:** motion here starts the sequence. -- **Each stage and the finale:** each either waits for its own motion sensor or turns on after a wait time. - - **One sensor:** leave the stage and finale sensors empty, and the whole show runs on timers. The first stage turns on after the **First stage wait time** (0 s by default). Each later stage follows after the **Later stage wait time**, and the finale after the **Finale wait time**. - - **More sensors:** give a stage or the finale its own sensor and it waits for that sensor instead. Use a different sensor for each. -- **Quiet time before a new show:** stops a visitor waiting at the door from replaying the show every time they move. -- **Reverse walk guard:** with more than one sensor, it stops someone leaving the house from starting a show. Set it to about how long the walk from the door to the start sensor takes. - -## Sound and music - -- **Sound player:** set it under **Sound player and options** to play every sound on one speaker. If you play music through Music Assistant, pick the speaker's own media player, not the Music Assistant one. Otherwise Music Assistant pauses the music for each sound instead of playing over it. -- **Ducking on a CAST-1:** music ducks under each sound, by 40 dB by default. Set `announcement_ducking_db` in your device YAML to keep the music louder (see [Announcements](../README.md#announcements)). -- **Light delay after a sound:** if your speaker starts sounds late, this makes the lights wait so they land together. -- **Volume:** **Set the volume during a sequence** changes the speaker's volume while a sequence runs, then puts it back. -- **CAST-1 Music Mode:** add the strip's **LED Strip Music Mode** switch to **Switches to pause during a sequence**. Otherwise music starting or stopping can take over the strip mid-show. It's turned back on afterwards. -- **Enable switch:** set one, such as a Halloween mode toggle, to turn the display on and off without editing the automation. - -## Troubleshooting - -If something doesn't happen as expected, open the automation, click **Traces** and select the run. The conditions step shows why a sequence didn't start, and each step shows what the lights and speaker were sent. From 7d6163be8c34528c9396798e6b248f45a5f2d975 Mon Sep 17 00:00:00 2001 From: Justin Bunton <130115204+Bunton33@users.noreply.github.com> Date: Fri, 30 Oct 2026 14:20:10 -0400 Subject: [PATCH 30/30] Fix review findings and bump to 26.10.30.1 - Keep the announcement LED at 50% by default, and keep it off at 0 - Unmute once at volume 0 for devices older firmware auto-muted - Slow Effect B's default strobe to under 3 flashes per second - Fix stale comments and README notes Co-Authored-By: Claude Opus 5.5 --- Integrations/ESPHome/Core.yaml | 40 ++++++++++++++++++++++------- Integrations/ESPHome/led_strip.yaml | 7 ++--- README.md | 6 ++--- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index b5c8757..4329ef8 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.10.25.1" + version: "26.10.30.1" stable_manifest_base: "https://apolloautomation.github.io/CAST-1" beta_manifest_base: "https://github.com/ApolloAutomation/CAST-1/releases/download/beta-fw" stable_manifest_dir: "firmware" @@ -18,7 +18,7 @@ esphome: min_version: 2026.10.0 platformio_options: board_build.flash_mode: dio - # List form so package on_boot entries (wizmote.yaml) merge + # List form so package on_boot entries (wizmote.yaml, led_strip.yaml) merge on_boot: - priority: 800 then: @@ -62,6 +62,19 @@ esphome: - priority: -100 then: - script.execute: apply_ota_source + # Firmware before ESPHome 2026.10 saved volume 0 as muted, and volume no + # longer clears mute; unmute that once (silent at volume 0) + - priority: -100 + then: + - if: + condition: + and: + - lambda: "return !id(zero_volume_mute_fixed);" + - media_player.is_muted: external_media_player + - lambda: "return id(external_media_player).volume < 0.001f;" + then: + - media_player.unmute: external_media_player + - lambda: "id(zero_volume_mute_fixed) = true;" # Ethernet never came up, so bring WiFi back for rejoin or provisioning - priority: -100 then: @@ -252,6 +265,11 @@ api: encryption: globals: + # Set after the one-time volume-0 unmute check on first boot + - id: zero_volume_mute_fixed + type: bool + restore_value: yes + initial_value: 'false' - id: cycleCounter type: int restore_value: no @@ -506,7 +524,7 @@ number: step: 1 optimistic: true restore_value: true - initial_value: 100 + initial_value: 50 select: - platform: template @@ -623,12 +641,16 @@ media_player: - lambda: return (!id(announcement_triggered)); then: - lambda: id(announcement_triggered) = true; - - light.turn_on: - id: rgb_light - blue: 100% - red: 0% - green: 100% - brightness: !lambda "return id(announcement_led_brightness).state / 100.0f;" + - if: + condition: + lambda: "return id(announcement_led_brightness).state > 0;" + then: + - light.turn_on: + id: rgb_light + blue: 100% + red: 0% + green: 100% + brightness: !lambda "return id(announcement_led_brightness).state / 100.0f;" - mixer_speaker.apply_ducking: id: media_mixer_input decibel_reduction: !lambda "return (uint8_t) -id(announcement_ducking).state;" diff --git a/Integrations/ESPHome/led_strip.yaml b/Integrations/ESPHome/led_strip.yaml index f8d2729..06ce7cc 100644 --- a/Integrations/ESPHome/led_strip.yaml +++ b/Integrations/ESPHome/led_strip.yaml @@ -81,7 +81,7 @@ light: # Effect A and Effect B run the pattern their Pattern select picks, at # their own Speed. Partition lights in the device YAML can - # list the same two entries (see the README) + # list the same two entries (https://esphome.io/components/light/partition/) - addressable_lambda: name: "Effect A" # About one frame per main-loop pass (~16 ms); the helper keeps its @@ -332,7 +332,8 @@ number: step: 1 optimistic: true restore_value: true - initial_value: 80 + # Strobe at 45 flashes about twice a second, under the 3 Hz photosensitivity limit + initial_value: 45 select: - platform: template @@ -452,7 +453,7 @@ select: switch: # Music Mode: the strip turns on with the Music Effect while audio plays and - # off once playback has stopped for 10s + # off 3 s after playback stops - platform: template id: led_strip_music_mode name: "LED Strip Music Mode" diff --git a/README.md b/README.md index eb3a462..ae84912 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Configure every button without leaving Home Assistant using the [CAST-1 WizMote While an announcement plays, music ducks and the onboard LED lights up. Two sliders in Home Assistant set how much: - **Announcement Ducking** (−80 to 0 dB, default −40) is how far the music drops. 0 turns ducking off. -- **Announcement LED Brightness** (0–100%, default 100%) is how bright the onboard LED is. 0 keeps the LED off. +- **Announcement LED Brightness** (0–100%, default 50%) is how bright the onboard LED is. 0 keeps the LED off. ## External LED Strip @@ -58,12 +58,12 @@ The strip's settings live in Home Assistant and under **External LED Strip** on - **Pulse** fades the whole strip from off to full and back. - **Fireworks** lights random sparks that spread and fade. -In automations, set the pattern and speed with `select.select_option` and `number.set_value`, then call `light.turn_on` with `effect: "Effect A"` (add `transition: 0` for an instant start). +In automations, set the pattern and speed with `select.select_option` and `number.set_value`, then call `light.turn_on` with `effect: "Effect A"`. > [!WARNING] > **Photosensitivity:** Strobe flashes faster than 3 times per second from about Speed 50 up, and reaches about 16 flashes per second at Speed 100. Pulse passes 3 per second from about Speed 75. Flashing in this range can trigger seizures in people with photosensitive epilepsy. -Power long strips from their own 5V supply with a shared ground; the header can't supply a full-brightness strip, and **LED Strip Max Brightness** (default 50%) caps the draw. +Power long strips from their own 5V supply with a shared ground; the header can't supply a full-brightness strip, and **LED Strip Max Brightness** (default 50%) caps the draw. It doesn't reach partition lights, so give each partition its own `color_correct`. Links: \ Discord (Support/feedback/discussion/future products): [http://dsc.gg/ApolloAutomation](http://dsc.gg/ApolloAutomation) \