Esphome alarm system

This is the beauty of this implemention, we can each have it to our exact individual preferences. Your suggestion however will cause clashes when for example the motion detector goes off first (immediately triggering the alarm) then the door is opened. When the door opens, it will go back to pending. You should create scripts to make sure that only one is running at a time.

I should have tested my code too before posting. I do not like using the template text sensor as a complete slave to the global state_int like in my example. The template text sensor has to poll the state of the state_int, so the change isnā€™t instant. I like your approach now of setting both the state_int and the template text sensor when the state changes. I need to scrub my config file of all identifying info and then I will post it.

I forgot to point out the lag time. The code looks a little messy, but the change is right away. My previous vesion had a numeric sensor also slave of the state_int global just to check it in Home Assistant, but it would update once in 60 seconds per default.

I donā€™t really know the reason of this delay, anyone knows?

As I alluded to above, the templates only poll their template values with a default of 60s. You can reduce the poll rate, but this isnā€™t ideal.

I updated the gist with my current code. The gobal integer restore on the esp32 works well after a hard power reset. I found that the update to the global integer introduced a small but noticeable lag when trying to observe state update, so it seems to work better when it is the last action in a sequence.

I made significant changes to your project ā€¦ Thanks for sharing it ā€¦ As soon as possible I create a new post with everything you need to make it happen ā€¦ By sharing the link in this topic. See you soon

I would love to see.

My PR to include pending in the possible states for the template alarm control panel is available in v0.108. now there is no longer an error temporarily.

I anticipate the news. Addition of led ws2812b to indicate the node status, and specifically the status LED of the on / off sensors at the passage if disarmed, while fixed if armed and in alarm to identify the sensors that have detected the presence, LED for API connection status and wifi, armed / disarmed alarm status led, triggered status led flashing and fixed in alarm. All this even in case of recovery

Iā€™m doing something very similar to this, though not as complex. Thread here. Iā€™m also using an ESP32 but Iā€™m using a TTGO T-Call board with integrated SIM800L so I can text arm/disarm and get notifications if it triggers. Basically my kit is all over the house so I canā€™t UPS it all so I also need a self contained alarm panel in the event the perp flicks off the power to the house.

Just lately Iā€™ve lost interest as itā€™s gotten way more complex than Iā€™d hoped and Iā€™ve run into this conundrum as well. Are you saying that it seems to reconnect to wifi OK without the board rebooting? I havenā€™t had the chance to test. Mineā€™s coded to trigger the relay for the sirens/strobes then silence the sirens after 20 minutes. The board is connected to the battery backup of the alarm panel so power outs are not an issue but obviously wifi drops are. If youā€™re getting reliable reconnections, why do you need to restore states/in what scenario will your board power cycle? Canā€™t you just set reboot_timeout to 0 and forget about it?

Thanks for sharing.

The use case is if I go on vacation and the power goes out long enough to deplete the backup battery. Then, the system reboots into the correct state when power returns.

Got it - so youā€™re looking for it to stay armed in this situation. Note your bell box will likely have sung itself to death in this scenario - hopefully any neighbours havenā€™t decided to ignore if it goes off again!

I reckon Iā€™ll have mine restore armed/disarmed state but not triggered state and will set the reboot_timeout to something a bit longer than the default 15 mins, just to reduce the likelihood of it resetting and turning off the triggered state soon after it becoming triggered.

Mine presents template switches for armed/disarmed and triggered. I havenā€™t really thought about how to keep both HA and the ESPā€™s armed/disarmed state in sync yet.

My code restores whatever state it was on prior to power cut. The alarm siren wonā€™t go off unless it was previously going off. I also have a timer for the alarm siren so it stops after x hrs. If my neighbors donā€™t call me by thenā€¦

If you donā€™t want it to reset into triggered, reset it into armed and it can retrigger if the disturbance is still detected. I thought about this too, and in fact, it may be what I have programmed on my live system.

You can use a template alarm control panel.

1 Like

I havenā€™t yet gotten my head around the template alarm control panel or why I would need it - right now Iā€™ve got a manual alarm control panel set up.

Thanks for that - Iā€™ve now implemented similar, however I have my strobe set up to restore state and continue indefinitely, until the system is disarmed.

So in the scenario that your panel loses AC and its battery goes dead (hence the need for restore states) your bell box wonā€™t go off/flatten itself? Other thing - Are you UK based? If so, heads up - Iā€™m told that bell boxes shouldnā€™t ring more than 20 minutes to avoid nuisance. Apparently neighbours/the council are within their rights to disconnect/smash it off the wall if itā€™s going off longer!

For anyone interested, my code below (itā€™s come on a bit since my other thread, ā€˜Virtual Siren/Strobeā€™ are temporary and just for testing).

esphome:
  name: tcall
  platform: ESP32
  board: esp32dev

wifi:
  ssid: !secret ssid
  password: !secret wpa2
  reboot_timeout: 60min

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "tcall Fallback Hotspot"
    password: !secret hotspotpass

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:
  password: !secret apipass
  reboot_timeout: 60min
  services:
  - service: send_sms
    variables:
      recipient: string
      message: string
    then:
    - sim800l.send_sms:
        recipient: !lambda 'return recipient;'
        message: !lambda 'return message;'

ota:
  password: !secret apipass
  
switch:
  - platform: gpio
    id: "SIM800_PWKEY"
    pin: 4
    restore_mode: ALWAYS_OFF
  - platform: gpio
    id: "SIM800_RST"
    pin: 5
    restore_mode: ALWAYS_ON
  - platform: gpio
    id: "SIM800_POWER"
    pin: 23
    restore_mode: ALWAYS_ON
  - platform: gpio
    inverted: true
    pin: GPIO33
    name: "Siren Relay"
    id: "siren"
    restore_mode: always_off
  - platform: gpio
    inverted: false
    pin: GPIO32
    name: "Strobe Relay"
    id: "strobe"
    restore_mode: restore_default_off
  - platform: template
    id: "armdisarm"
    name: "Arm/Disarm"
    restore_state: true
    optimistic: true
    on_turn_off:
      then:
      - switch.turn_off: "alarmtriggered"
      - switch.turn_off: "vstrobe" 
  - platform: template
    id: "alarmtriggered"
    name: "Alarm Triggered"
    restore_state: false
    optimistic: true
    on_turn_on:
      - if:
          condition:
          - wifi.connected:
          then:
          else:
          - sim800l.send_sms:
              recipient: !secret mobjr
              message: ALARM HAS BEEN TRIGGERED! WIFI CONNECTION UNAVAILABLE. REPLY DISARM TO STOP.
      - switch.turn_on: "vsiren"
      - switch.turn_on: "vstrobe"
      - delay: 20min
      - switch.turn_off: "alarmtriggered"
    on_turn_off:
      - switch.turn_off: "vsiren"
  - platform: template
    id: "vsiren"
    name: "Virtual Siren"
    restore_state: false
    optimistic: true
  - platform: template
    id: "vstrobe"
    name: "Virtual Strobe"
    restore_state: true
    optimistic: true
    
uart:
  baud_rate: 9600
  tx_pin: 27
  rx_pin: 26

sim800l:
  on_sms_received:
  - lambda: |-
      id(sms_sender).publish_state(sender);
      id(sms_message).publish_state(message);
      
text_sensor:
- platform: template
  id: sms_sender
  name: "SMS Sender"
- platform: template
  id: sms_message
  name: "SMS Message"
  on_value:
    - if:
        condition:
          and:
            - text_sensor.state:
                id: sms_message
                state: 'ARM'
            - text_sensor.state:
                id: sms_sender
                state: !secret mobjr
        then:
          - sim800l.send_sms:
              recipient: !secret mobjr
              message: System armed successfully.
          - switch.turn_on: "armdisarm"
          - delay: 30s
          - text_sensor.template.publish:
              id: sms_sender
              state: "Erased"
          - text_sensor.template.publish:
              id: sms_message
              state: "Erased" 
    - if:
        condition:
          and:
            - text_sensor.state:
                id: sms_message
                state: 'DISARM'
            - text_sensor.state:
                id: sms_sender
                state: !secret mobjr
        then:
          - sim800l.send_sms:
              recipient: !secret mobjr
              message: System disarmed successfully.
          - switch.turn_off: "armdisarm"
          - delay: 30s
          - text_sensor.template.publish:
              id: sms_sender
              state: "Erased"
          - text_sensor.template.publish:
              id: sms_message
              state: "Erased" 

binary_sensor:
  - platform: gpio
    name: "AC Power Detector"
    id: acpower
    pin:
      number: GPIO25
      inverted: true
    device_class: power
    on_state:
      then:
      - if:
          condition:
            and:
              - binary_sensor.is_off: "acpower"
              - switch.is_on: "armdisarm"
          then:
          - sim800l.send_sms:
              recipient: !secret mobjr
              message: AC POWER FAILURE.  ALARM STILL ARMED.  GARAGE UNPROTECTED.  TEXT DISARM TO DISARM.
      - if:
          condition:
            and:
              - binary_sensor.is_off: "acpower"
              - switch.is_off: "armdisarm"
          then:
          - sim800l.send_sms:
              recipient: !secret mobjr
              message: AC power failure.  To arm alarm in power-off state, text ARM.
      - if:
          condition:
          - binary_sensor.is_on: "acpower"
          then:
          - sim800l.send_sms:
              recipient: !secret mobjr
              message: Power restored.  Normal operation will be resumed shortly.

  - platform: gpio
    name: "Lounge PIR"
    pin:
      number: GPIO19
      mode: INPUT_PULLUP
    device_class: motion
    on_press:
      then:
      - if:
          condition:
          - switch.is_on: "armdisarm"
          then:
          - switch.turn_on: "alarmtriggered"

  - platform: gpio
    name: "Hall PIR"
    pin:
      number: GPIO13
      mode: INPUT_PULLUP
    device_class: motion
    on_press:
      then:
      - if:
          condition:
          - switch.is_on: "armdisarm"
          then:
          - switch.turn_on: "alarmtriggered"

You have the alarm logic in HA then in some form. I have the alarm logic in the esp unit and the template alarm control panel is just a representation of the alarm system that allows you to interact with it, but there is no alarm logic.

Iā€™ve programmed my system to not turn on the siren in this case. My old commercial system worked the same way, the power for the bell shared power work the panel, so when the battery died, everything is down.

I can turn my alarm on and off remotely through the wonders of home assistant!

Aaaah got it, thanks!

Wow Great Projectā€¦

I have some question, If you make it with tm1638, Pin is available to make it.

But tm1638 custom component should be made for ESPHOME.

thx again for your great project sharing.

In the initial code which I thank for sharing, an important condition has not been implemented. If a door or window is open or some PIR sensor is active because someone is still at home, and the alarm is armed, it will enter an armed state because to activate the trigger it is expected the change of state. I modified qursto by checking the state of the sensors. If these are in the on state because I use on_state and not on_press the alarm enters the delay by triggering the siren, or you can decide not to arm the system

Good point! The alarm should trigger the siren or not arm if a sensor is on.

My understanding of on_state is that it is a combination of on_press and on_release, so Iā€™m not sure how it helps here. We also want to catch the case where a door is open during arming and stays open for example.

Edit: This case will not fire any of the on events I think.

where can I find your updated code, with the restoration of the previous state?

sorry being Italian with the help of a translator, I did not understand your request well.

on_state combined with an ā€œifā€ if the binary sensor is on then the door or window is open, instead of arming it triggers or disarms.