No worries, I think I understand now. Thanks for the additional info.
The code is in the gist in the first post, and again here for convenience:
No worries, I think I understand now. Thanks for the additional info.
The code is in the gist in the first post, and again here for convenience:
I donāt see any changes compared to the post initial code to maintain the state in case of reboot.
This is what I am using
#allarme esphome - home assistant
#ws2812b
#led 1 sensore 1
#led 2 sensore 2
#led 3 stato connessione api con home assistant
#led 4 stato connessione wifi
#led 5 stato allarme armato/disarmato
#led 6 stato allarme triggered
#GPIO4 D2 display 16x2 sda
#GPIO5 D1 display 16x2 scl
#GPIO2 D4 led onboard stato esp
#GPIO16 D0 pir/zona 1
#GPIO13 D7 pir/zona 2
#GPIO15 D8 buzzer
#GPIO12 D6 sirena
#GPIO0 D3 ws2812b led status
substitutions:
alarm_code: "xxxxxxx"
disarmed_id: "0"
pending_id: "1"
triggered_id: "2"
armed_home_id: "3"
esphome:
name: antifurto_nodemcu
platform: ESP8266
board: nodemcu
# restore state
# if trigger sequence reset to armed for now.
# should it retrigger sequence?
on_boot:
then:
- lambda: |-
if (id(state_int) == ${disarmed_id}) {
id(alarm_condition).publish_state("disarmed");
} else if (id(state_int) == ${pending_id}){
id(alarm_condition).publish_state("armed_home");
id(state_int) = ${armed_home_id};
} else if (id(state_int) == ${triggered_id}){
id(alarm_condition).publish_state("armed_home");
id(state_int) = ${armed_home_id};
} else if (id(state_int) == ${armed_home_id}){
id(alarm_condition).publish_state("armed_home");
} else{
id(alarm_condition).publish_state("disarmed");
id(state_int) = ${disarmed_id};
}
- light.turn_on:
id: my_light
- delay: 3s
- light.addressable_set:
id: my_light
range_from: 0
range_to: 5
red: 0%
green: 0%
blue: 0%
- script.execute: boot_state
wifi:
ssid: "xxxxxx"
password: "xxxxxx"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Antifurto Nodemcu"
password: "xxxxxx"
# Example configuration entry
web_server:
port: 80
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
# add arm and disarm services to ha
services:
- service: arm_home
variables:
code: string
then:
- if:
condition:
lambda: "return code == \"${alarm_code}\";"
then:
- script.execute: alarm_arm
- if:
condition:
lambda: "return id(pir_cucina).state;"
then:
- script.execute: trigger_alarm
- if:
condition:
lambda: "return id(pir_corridoio).state;"
then:
- script.execute: trigger_alarm
- service: disarm
variables:
code: string
then:
- if:
condition:
lambda: "return code == \"${alarm_code}\";"
then:
- script.execute: alarm_disarm
ota:
# global for state restore
i2c:
sda: GPIO4
scl: GPIO5
display:
- platform: lcd_pcf8574
dimensions: 16x2
address: 0x27
id: lcd
lambda: |-
it.strftime( "%H:%M %d.%m.%Y", id(my_time).now());
if (id(state_int) == ${disarmed_id}) {
it.print(0, 1,"Stato disarmato");
}
if (id(state_int) == ${armed_home_id}) {
it.print(0, 1,"Stato armato");
}
if (id(state_int) == ${pending_id}) {
it.print(0, 1,"Stato innescato");
}
if (id(state_int) == ${triggered_id}) {
it.print(0, 1,"Stato in allarme");
}
time:
- platform: sntp
id: my_time
globals:
- id: state_int
type: int
restore_value: yes
initial_value: '0'
# Example configuration entrlight:
light:
- platform: fastled_clockless
chipset: WS2811
pin: D3
num_leds: 6
internal: true
rgb_order: GRB
id: my_light
name: "FastLED WS2811 Light"
sensor:
- platform: uptime
name: Uptime Sensor
- platform: wifi_signal
name: "WiFi Signal"
update_interval: 60s
status_led:
pin: GPIO2
binary_sensor:
- platform: status
name: "ESP ANTIFURTO"
- platform: gpio
pin:
number: D0
mode: INPUT_PULLUP
name: "Pir corridoio"
id: pir_corridoio
device_class: door
on_state:
then:
- if:
condition:
binary_sensor.is_on: pir_corridoio
then:
- script.execute: trigger_alarm
- if:
condition:
- and:
binary_sensor.is_on: pir_corridoio
- lambda: |-
return id(state_int) == ${disarmed_id};
then:
- light.addressable_set:
id: my_light
range_from: 0
range_to: 0
red: 50%
green: 50%
blue: 0%
- if:
condition:
- and:
binary_sensor.is_off: pir_corridoio
- lambda: |-
return id(state_int) == ${disarmed_id};
then:
- light.addressable_set:
id: my_light
range_from: 0
range_to: 0
red: 0%
green: 0%
blue: 0%
- if:
condition:
- and:
binary_sensor.is_on: pir_corridoio
- lambda: |-
return id(state_int) == ${pending_id};
then:
- light.addressable_set:
id: my_light
range_from: 0
range_to: 0
red: 50%
green: 50%
blue: 0%
- platform: gpio
pin:
number: D7
mode: INPUT_PULLUP
name: "Pir cucina"
id: pir_cucina
device_class: door
on_state:
then:
- if:
condition:
binary_sensor.is_on: pir_cucina
then:
- script.execute: trigger_alarm
- if:
condition:
- and:
binary_sensor.is_on: pir_cucina
- lambda: |-
return id(state_int) == ${disarmed_id};
then:
- light.addressable_set:
id: my_light
range_from: 1
range_to: 1
red: 50%
green: 50%
blue: 0%
- if:
condition:
- and:
binary_sensor.is_off: pir_cucina
- lambda: |-
return id(state_int) == ${disarmed_id};
then:
- light.addressable_set:
id: my_light
range_from: 1
range_to: 1
red: 0%
green: 0%
blue: 0%
- if:
condition:
- and:
binary_sensor.is_on: pir_cucina
- lambda: |-
return id(state_int) == ${pending_id};
then:
- light.addressable_set:
id: my_light
range_from: 1
range_to: 1
red: 50%
green: 50%
blue: 0%
interval:
- interval: 10s
then:
- if:
condition:
wifi.connected:
then:
- light.addressable_set:
id: my_light
range_from: 3
range_to: 3
red: 0%
green: 0%
blue: 100%
else:
- light.addressable_set:
id: my_light
range_from: 3
range_to: 3
red: 0%
green: 0%
blue: 0%
- if:
condition:
api.connected:
then:
- light.addressable_set:
id: my_light
range_from: 2
range_to: 2
red: 0%
green: 0%
blue: 100%
else:
- light.addressable_set:
id: my_light
range_from: 2
range_to: 2
red: 0%
green: 0%
blue: 0%
output:
- platform: gpio
pin: D8
id: output_buzzer_front_door
- platform: gpio
pin: D6
id: output_sirena
# warning chirp when pending
switch:
- platform: template
turn_on_action:
- switch.template.publish:
id: buzzer_front_door
state: ON
- while:
condition:
switch.is_on: buzzer_front_door
then:
- light.addressable_set:
id: my_light
range_from: 5
range_to: 5
red: 100%
green: 0%
blue: 0%
- output.turn_on: output_buzzer_front_door
- delay: 10ms
- light.addressable_set:
id: my_light
range_from: 5
range_to: 5
red: 0%
green: 0%
blue: 0%
- output.turn_off: output_buzzer_front_door
- delay: 990ms
turn_off_action:
- switch.template.publish:
id: buzzer_front_door
state: OFF
- output.turn_off: output_buzzer_front_door
id: buzzer_front_door
# holds alarm condition for arm/disarm/pending/triggered
text_sensor:
- platform: template
name: "Alarm Condition"
id: "alarm_condition"
script:
# when arming and disarming, turn off all sirens and buzzers
# also, cancel any trigger sequence
- id: alarm_arm
then:
- text_sensor.template.publish:
id: alarm_condition
state: "armed_home"
- script.stop: trigger_alarm_execute
- switch.turn_off: buzzer_front_door
- output.turn_off: output_sirena
- light.addressable_set:
id: my_light
range_from: 5
range_to: 5
red: 0%
green: 0%
blue: 0%
- light.addressable_set:
id: my_light
range_from: 4
range_to: 4
red: 100%
green: 0%
blue: 0%
- lambda: |-
id(state_int) = ${armed_home_id};
- id: alarm_disarm
then:
- text_sensor.template.publish:
id: alarm_condition
state: "disarmed"
- script.stop: trigger_alarm_execute
- switch.turn_off: buzzer_front_door
- output.turn_off: output_sirena
- lambda: |-
id(state_int) = ${disarmed_id};
- light.addressable_set:
id: my_light
range_from: 5
range_to: 5
red: 0%
green: 0%
blue: 0%
- light.addressable_set:
id: my_light
range_from: 4
range_to: 4
red: 0%
green: 100%
blue: 0%
# triggering sequence
- id: trigger_alarm_execute
then:
- text_sensor.template.publish:
id: alarm_condition
state: "pending"
- switch.turn_on: buzzer_front_door
- lambda: |-
id(state_int) = ${pending_id};
- delay: 30s
- text_sensor.template.publish:
id: alarm_condition
state: "triggered"
- switch.turn_off: buzzer_front_door
- output.turn_on: output_sirena
- light.addressable_set:
id: my_light
range_from: 5
range_to: 5
red: 100%
green: 0%
blue: 0%
- lambda: |-
id(state_int) = ${triggered_id};
- delay: 3600s
# TODO: turn on siren
# only execute triggering if armed and not already running
- id: trigger_alarm
then:
if:
condition:
and:
- not:
script.is_running: trigger_alarm_execute
- lambda: |-
return id(state_int) == ${armed_home_id};
then:
script.execute: trigger_alarm_execute
- id: boot_state
then:
- if:
condition:
or:
- lambda: |-
return id(state_int) == ${pending_id};
- lambda: |-
return id(state_int) == ${triggered_id};
- lambda: |-
return id(state_int) == ${armed_home_id};
then:
- light.addressable_set:
id: my_light
range_from: 4
range_to: 4
red: 100%
green: 0%
blue: 0%
else:
- light.addressable_set:
id: my_light
range_from: 4
range_to: 4
red: 0%
green: 100%
blue: 0%
The on_boot
section does the restore state logic. On an esp8266 you have to enable restoring from flash or it wonāt survive a power cycle. But, beware! My understanding is that this can wear the flash memory. For an alarm system there shouldnāt be too many writes too flash, but I want to highlight that.
Or maybe I dontā understand your question. Your code looks OK from quick inspection for restoring from a normal reboot (I think this can be caused by lack of wifi connection sometimes depending on settings).
Also I like your usage of lights to indicate different states etc and a display. This is on my todo list.
Are you telling me I have to enable this? esp8266_restore_from_flash ā¦ My code is working right now. You have dealt with the speech of the restoration and I understood that with this code that I published the restoration occurs by reading the text sensor from the home assistant, and if the server is turned off it cannot be restored. Or am I wrong?
The code you have posted resets state based on the last state on the esp unit itself. It is my understanding that your version wonāt work across power cycles without that esp8266_restore_from_flash
option enabled. I have only tested esp32 which only writes to flash as part of esphome as far as I know.
Sorry but I donāt want to get confused. restore_value: equals esp8266_restore_from_flash
Are you telling me that HA restores based on the global esphome? So in case of power failure and then reboot you how do you restore the esp to the initial state? Can you confirm that the restore_value has 100,000 write cycles?
I use the template alarm control panel in home assistant, it purely follows whatever the esp unit state is. There is no logic in home assistant other than reading the state and sending arm and disarm commands.
There esp unit restores based on the global variable written to itās own flash memory. I donāt know about the number of cycles and the way it works isnāt super straightforward when I looked into it.
I studied your code before putting it into practice. Its logic is based on esp, and thatās clear and itās a great choice. I donāt understand if the restore_value: yes, inserted in the global variable allows esp to restore the previous state in case of loss of power
This needs to be enabled on my understanding to restore state after power cycle.
We seem to be responding to older posts before a new one comes in, I think this hasnāt helped communications. The restore_value: yes
will restore the value of the global variable. My understanding is that this happens from RTC memory on esp8266 in esphome by default. This kind of memory does not store data when power is lost. The esp8266_restore_from_flash
makes this behavior happen in the flash memory which does survive power cycle
I donāt need the esp8266 option because Iām using esp32.
I read some documentation. Youāre right, the function is the one you indicated.
I purchased an esp32 and am waiting for it to arrive. How does this mode work on esp32?
There is no option in esphome for RTC vs flash in esp32 as far as I know. It only writes to flash. This isnāt in the documentation, but I was told this in the esphome discord.
Hey, awesome project!
Iāll modify this to work with my current boardā¦ and use it to arm/disarm itā¦
In HASS, I canāt get it to arm/disarmā¦ ie type code - nothing happensā¦
canāt seem to figure out why (very new to HASS)ā¦
any tips or tricks?
This is a complex set of code on the ESP unit and in home assistant. I would recommend first making sure you can arm and disarm the system using services from home assistant. To debug this, you need to use the logs on the ESP unit itself in addition to the logs in home assistant.