Addressable LED Project Idea - Visual Notification - Need help on direction

I have been busy getting my alarm system setup and so far pretty happy with it, going to mount a tablet at the front door as soon as the wall mount is delivered. I am using the MQTT Alarm App for that. As I put this together I realized there is no good way to know other than to check Home Assistant if the Alarm is set which results with the alarm going off when letting out the dog. Since the front door is pretty visible from most areas of the first floor I thought of mounting an addressable LED strip in the top moulding. The idea then would be to turn one LED on as Red when the alarm is set. I could also do a visual countdown over 30 seconds for the exit delay (all on to off). When the alarm goes off I could flash the LEDS Red and Blue. Other ideas include turning one led on (Blue) if mail was delivered, another could be to turn on less if motion was detected on one of the security cameras (turn on several but slowly turn them off as time passes).

So I have been searching the internet for ideas or example on how to put this together. I would prefer to use ESPHOME as I am getting comfortable with it. So could use the FASTLED platform. One of the key considerations is to control the light from Home Assistant. Wondering what the best way to accomplish this. I had considering creating effects but not sure that would work for situations where I would want to show multiple notifications (alarm on and motion detected).

Examples are always welcome if someone can point me in the right direction.

1 Like

did you found a solution?

I never got a response on this thread but did put something together which I included here. Some of my ideas didn’t make it (like the visual countdown) But most of the others did. This configuration is far from perfect but it works.

esphome:
  name: frontdoorledsrip
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_pswd
  power_save_mode: none
  fast_connect: true
  manual_ip:
    static_ip: !secret frontdoorledsrip_ip
    gateway: !secret gateway
    subnet: !secret subnet
  ap:
    ssid: " Front Door Hotspot"
    password: !secret esphome_pswd

captive_portal:

logger:
  level: DEBUG
  esp8266_store_log_strings_in_flash: False

api:
  password: !secret esphome_pswd

ota:
  password: !secret esphome_pswd

web_server:
  port: 80

globals:
  - id: trigger_status
    type: int
    restore_value: no
    initial_value: '0'

light:
  - platform: fastled_clockless
    id: fastled_clockless_led
    chipset: WS2812B
    pin: D4
    num_leds: 300
    rgb_order: GRB
    name: "Front Door Light Strip"
    internal: true

  - platform: partition
    name: "Mail Status"
    id: mail_status
    restore_mode: ALWAYS_OFF
    segments:
      - id: fastled_clockless_led
        from: 93
        to: 94

  - platform: partition
    name: "Alarm Status"
    id: alarm_status_light
    restore_mode: ALWAYS_OFF
    segments:
      - id: fastled_clockless_led
        from: 91
        to: 92

  - platform: partition
    name: "Motion Event"
    id: motion_event
    restore_mode: ALWAYS_OFF
    segments:
      - id: fastled_clockless_led
        from: 70
        to: 90
    effects:
      - addressable_lambda:
          name: "Wipe Out"
          update_interval: 20ms
          lambda: |-
            static int x = 0;
            if (initial_run) {
              x = 0;
            }
            if (x < it.size()) {
              it[x] = ESPColor::BLACK;
              x += 1;
            }
      - addressable_lambda:
          name: "Wipe In"
          update_interval: 20ms
          lambda: |-
            static int x = 0;
            if (initial_run) {
              x = it.size();
              it.all() = ESPColor::BLACK;
            }
            if (x > 0) {
              x -= 1; 
              it[x] = current_color;
            }

  - platform: partition
    name: "Alarm Event"
    id: alarm_event
    restore_mode: ALWAYS_OFF
    segments:
      - id: fastled_clockless_led
        from: 0
        to: 90
    effects:
      - addressable_lambda:
          name: "Alarm Event Triggered"
          update_interval: 2ms
          lambda:
            static int step = 0;
            static int direction = 1;
            if(initial_run){
              step = 0;
            }
            it[step] = ESPColor(255,0,0);
            if(step >0 && step < it.size()){
            it[step + (direction * -1)] = ESPColor::BLACK;
            }
            step = step + direction;
            if(step >= it.size() || step < 0){
             direction = direction * -1;
             step = step + (direction * 2);
            }

  - platform: partition
    name: "Temperature"
    id: temp_status
    restore_mode: ALWAYS_OFF
    segments:
      - id: fastled_clockless_led
        from: 0
        to: 69
    effects:
      - addressable_lambda:
          name: "Temperature Effect"
          update_interval: 3600ms
          lambda: |-
            int range_from;
            int range_to;
            int red_color;
            int green_color;
            int blue_color;
            if (id(outside_temp).state >= 0) {
               range_from = 40 - id(outside_temp).state;
               range_to = 40;
            } else {
               range_to = 41 + (id(outside_temp).state * -1);
               range_from = 41;
            }
       
            it.all() = ESPColor::BLACK;
            for (int i = range_from; i < range_to; i+=1) {
                if (id(outside_temp).state >= 0) {
                  red_color = (39 - i) * (255 / 40);
                  green_color = 0;
                  blue_color = (255 / 40) * i + 1;
                } else {
                  red_color = 0;
                  green_color = (i - 40) * (255 / 30);
                  blue_color = 255 - ((255 / 30) * (i - 40));
                }
                // ESP_LOGD("custom", "Value of I: %i. Colour Red %i,  Green %i, Blue %i", i, red_color, green_color, blue_color);
                it[i] = light::ESPColor(red_color, green_color, blue_color);
            }
            it[40] = light::ESPColor(255, 190, 0);

binary_sensor:
  - platform: homeassistant
    name: "Outside Motion"
    id: outside_motion
    entity_id: group.outside_motion
    internal: True
    on_state:
      then:
        - if:
            condition:
              lambda: 'return id(trigger_status) == 0;'
            then:
              - script.execute: motion_status_script  

  - platform: homeassistant
    name: "all sensors"
    id: all_sensors
    entity_id: group.monitored_sensors
    internal: True
    on_state:
      then:
      - script.execute: sensor_open_check

  - platform: gpio
    pin: 
      number: 14  
#      inverted: True    
      mode: INPUT_PULLUP
    filters:
      - delayed_on: 1000ms
    name: "Front Door"
    device_class: door

sensor:
  - platform: homeassistant
    name: "Outside Temperature"
    id: outside_temp
    entity_id: sensor.rear_porch_temperature_measurement
    internal: True
    on_value:
      then:
        - if:
            condition:
              and:
                - lambda: 'return id(trigger_status) == 0;'
                - lambda: 'return id(outside_temp).state <= 40;'
                - lambda: 'return id(outside_temp).state >= -30;'
            then:
              - light.turn_on:
                  id: temp_status
                  effect: "Temperature Effect"
                  brightness: 50%

text_sensor:
  - platform: homeassistant
    name: "Alarm Panel Status"
    id: alarm_panel_status
    entity_id: alarm_control_panel.ha_alarm
    internal: True
    on_value:
      then:
      - script.execute: alarm_status_script   
      - script.execute: sensor_open_check

script:
  - id: motion_status_script
    then:
    - if:
        condition:
          lambda: 'return id(outside_motion).state;'
        then:
          - light.turn_on:
              id: motion_event
              effect: "Wipe In"
              brightness: 25%
              red: 43%
              green: 100%
              blue: 85%
        else:
          - light.turn_on:
              id: motion_event
              effect: "Wipe Out"
              brightness: 25%

  - id: alarm_status_script
    then:
    - if:
        condition:
          lambda: 'return id(alarm_panel_status).state == "armed_home";'
        then:
          - light.turn_on:
              id: alarm_status_light
              brightness: 50%  
              red: 100%
              green: 0%
              blue: 0%
    - if:
        condition:
          lambda: 'return id(alarm_panel_status).state == "armed_away";'
        then:
          - light.turn_on:
              id: alarm_status_light
              brightness: 50%  
              red: 100%
              green: 0%
              blue: 0%
    - if:
        condition:
          lambda: 'return id(alarm_panel_status).state == "pending";'
        then:
          - light.turn_on:
              id: alarm_status_light
              brightness: 50%  
              red: 100%
              green: 57%
              blue: 14%
    - if:
        condition:
          lambda: 'return id(alarm_panel_status).state == "triggered";'
        then:
          - light.turn_on:
              id: alarm_event
              brightness: 100%  
              effect: "Alarm Event Triggered"
          - globals.set:
              id: trigger_status
              value: '1'
        else:
          - if:
              condition:
                lambda: 'return id(trigger_status) == 1;'
              then:
               - globals.set:
                   id: trigger_status
                   value: '0'
               - light.turn_off:
                   id: alarm_event
  - id: sensor_open_check
    then:
    - if:
        condition:
          lambda: 'return id(alarm_panel_status).state == "disarmed";'
        then:
          - if:
              condition:
                lambda: 'return id(all_sensors).state;'
              then:
                - light.turn_on:
                    id: alarm_status_light
                    brightness: 25%
                    red: 100%
                    green: 75%
                    blue: 0%
              else:
                - light.turn_off:
                    id: alarm_status_light