Hi all,
I’m a bit lost here. I have just updated the configuration on my shelly 2pm. With respect to the previous working configuration, I have added the following:
#bluetooth
bluetooth_proxy:
# BLE tracker setup
esp32_ble_tracker:
- platform: wifi_signal
name: ${node_name} WiFi Signal
update_interval: 180s
entity_category: 'diagnostic'
text_sensor:
# # Expose ESPHome version as sensor.
- platform: version
name: ${node_name} ESPHome Version
entity_category: 'diagnostic'
# # Expose WiFi information as sensors.
- platform: wifi_info
ip_address:
name: ${node_name} IP
entity_category: 'diagnostic'
ssid:
name: ${node_name} SSID
entity_category: 'diagnostic'
Now the device will no longer connect to the network, Nor does it respond to the button presses on the physical device. Since the device is mounted inside a very tight wall socket, I’m not very keen of taking it out every time this happens, so I was hoping to get some understanding of why this has seemingly ‘bricked’ the device.
Full configuration:
# change yaml name: https://esphome.io/changelog/2022.5.0.html
substitutions:
IP: 192.168.178.24
node_name: "shelly-plus-2pm"
output_name_1: "${node_name} Output 1"
output_name_2: "${node_name} Output 2"
input_name_1: "${node_name} Input 1"
input_name_2: "${node_name} Input 2"
friendly_name_short: "sprinkler"
max_temp: "70.0"
# For Single Core ESP32
esphome:
name: ${node_name}
comment: "${IP}: Control Lighting / sprinklers terras"
platformio_options:
board_build.f_cpu: 160000000L
esp32:
board: esp32doit-devkit-v1
framework:
type: esp-idf
sdkconfig_options:
CONFIG_FREERTOS_UNICORE: y
CONFIG_ESP32_DEFAULT_CPU_FREQ_160: y
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ: "160"
logger:
# Enable Home Assistant API
api:
encryption:
key: !secret encryption_key
services:
- service: start_sprinkler
variables:
duration: int
then:
- globals.set:
id: glbl_timeout_length_ticks
value: !lambda 'return duration;'
- logger.log:
format: "service called for %d seconds, arming status is: %d"
args: [ 'id(glbl_timeout_length_ticks)', 'id(glbl_timeout_armed)' ]
- if:
condition:
# If the countdown timer is armed
lambda: 'return id(glbl_timeout_armed);'
then:
- switch.turn_on: sprinkler_1
else:
- logger.log:
format: "service called for %d seconds, arming status is: %d"
args: [ 'id(glbl_timeout_length_ticks)', 'id(glbl_timeout_armed)' ]
ota:
password: "****"
wifi:
networks:
- ssid: !secret wifi_ssid3
password: !secret wifi_password3
- ssid: !secret wifi_ssid2
password: !secret wifi_password2
- ssid: !secret wifi_ssid
password: !secret wifi_password
# Optional manual IP
manual_ip:
static_ip: ${IP}
gateway: 192.168.178.1
subnet: 255.255.255.0
#use_address: 192.168.178.236 #old adress for OTA upload
#bluetooth
bluetooth_proxy:
# BLE tracker setup
#esp32_ble_tracker:
#define functionality
i2c: #not used?
sda: GPIO26
scl: GPIO25
output:
- platform: gpio
id: "relay_output_1"
pin: GPIO12
- platform: gpio
id: "relay_output_2" #sprinkler
pin: GPIO13
switch:
- platform: output
id: "relay_1"
name: "${output_name_1}"
output: "relay_output_1"
- platform: output
id: sprinkler_1
output: relay_output_2
# Resume last state on boot if possible. Else, off
restore_mode: RESTORE_DEFAULT_OFF
# Wire in the count down timer automation if enabled
on_turn_on: #always do this when the 'sprinkler' is switched on
then:
- script.execute: _timer_tick
- logger.log:
level: DEBUG
format: "sprinkler turned on, countdown timer started"
# This can be called by the natural end of the timer OR manually through any other source.
# Regardless of the source, we just need to stop the ticking if it's running.
on_turn_off:
then:
- if:
condition:
lambda: 'return id(_timer_tick).is_running();'
then:
- script.execute: on_timer_stop
else:
- logger.log:
level: DEBUG
format: "sprinkler turned off, countdown timer not armed"
# UI toggle for the arm/disarm of the auto-off/timeout functionality
- name: "${friendly_name_short} Automation Arm"
platform: template
id: sw_timeout_arm
device_class: "switch"
entity_category: "config"
lambda: |-
if (id(glbl_timeout_armed)) {
return true;
} else {
return false;
}
turn_on_action:
then:
# Update the global to store the new state
# If the sprinkler is already on, also start the timer
- lambda: |-
id(glbl_timeout_armed) = true;
auto TAG = "template.Timeout Automation.turn_on_action";
if ( id(sprinkler_1).state ) {
id(_timer_tick).execute();
} else {
ESP_LOGD(TAG, "Timeout Automation ARMED, sprinkler NOT on. Nothing to do!");
}
turn_off_action:
then:
# Update the global and stop the ticking timer if needed
- lambda: |-
// Set the global to OFF, it will be checked next time the _tick fires if the on_timer_stop doesn't
// kill the ticking
id(glbl_timeout_armed) = false;
id(on_timer_stop).execute();
# Give the user a graphical control over the timeout
# See: https://esphome.io/components/number/template.html
number:
- name: "${friendly_name_short} Timeout"
id: timeout_length
platform: template
entity_category: "config"
# TODO: maybe it's a better UX to do this in minutes and do the conversion in esphome
unit_of_measurement: seconds
mode: box
min_value: 2
max_value: 21600
step: 1
lambda: |-
return (int) id(glbl_timeout_length_ticks);
set_action:
then:
- globals.set:
id: glbl_timeout_length_ticks
value: !lambda |-
// TODO: we're relying on HA to pass an integer; perhaps we should do atoi() and catch any exceptions
return (int) x;
binary_sensor:
# Button on device
- platform: gpio
name: "${node_name} Button"
pin:
number: GPIO4
inverted: yes
mode:
input: true
pullup: true
internal: true
# Input 1
- platform: gpio
name: "${input_name_1}"
pin: GPIO5
filters:
- delayed_on_off: 50ms
on_press:
then:
- switch.toggle: relay_1
on_release:
then:
- switch.toggle: relay_1
internal: false
# Input 2 (sprinkler)
- platform: gpio
name: "${input_name_2}"
pin: GPIO18
filters:
- delayed_on_off: 50ms
on_state: #when state is changed (since a toggle switch is used)
then:
- if:
# if the output is on
condition:
switch.is_on: sprinkler_1
then:
- switch.turn_off: sprinkler_1
- switch.turn_off: sw_timeout_arm #disable the sw_timeout_arm
- globals.set: # reset the state of the timer (set _glbl_timeout_ticks to glbl_timeout_length_ticks),
id: _glbl_timeout_ticks
value: !lambda "return id(glbl_timeout_length_ticks);"
- logger.log:
level: DEBUG
format: "Button1 pressed, output switched off. sw_timeout_arm disabled"
else:
- switch.turn_on: sprinkler_1 #logic if sprinkler is allowed to be turned on is contained within the sprinkler
- logger.log:
level: DEBUG
format: "Button1 pressed, output was off before, is now turned on."
internal: false
sensor:
# Power Sensor
- platform: ade7953
irq_pin: GPIO27
voltage:
name: "${node_name} Voltage"
current_a:
name: "${output_name_2} Current"
active_power_a:
name: "${output_name_2} Power"
id: power_channel_2
filters:
- multiply: -1
current_b:
name: "${output_name_1} Current"
active_power_b:
name: "${output_name_1} Power"
id: power_channel_1
update_interval: 10s
# Internal NTC Temperature sensor
- platform: ntc
sensor: temp_resistance_reading
name: "${node_name} Temperature"
unit_of_measurement: "°C"
accuracy_decimals: 1
icon: "mdi:thermometer"
entity_category: 'diagnostic'
calibration:
b_constant: 3350
reference_resistance: 4.7kOhm
reference_temperature: 298.15K
on_value_range:
- above: ${max_temp}
then:
- homeassistant.event:
event: esphome.overheat
data:
title: "${node_name} has overheated."
# Required for NTC sensor
- platform: resistance
id: temp_resistance_reading
sensor: temp_analog_reading
configuration: DOWNSTREAM
resistor: 5.6kOhm
# Required for NTC sensor
- platform: adc
id: temp_analog_reading
pin: GPIO35
attenuation: 11db
update_interval: 10s
# WiFi Signal sensor.
- platform: wifi_signal
name: ${node_name} WiFi Signal
update_interval: 180s
entity_category: 'diagnostic'
# Text sensors with general information.
text_sensor:
# # Expose ESPHome version as sensor.
- platform: version
name: ${node_name} ESPHome Version
entity_category: 'diagnostic'
# # Expose WiFi information as sensors.
- platform: wifi_info
ip_address:
name: ${node_name} IP
entity_category: 'diagnostic'
ssid:
name: ${node_name} SSID
entity_category: 'diagnostic'
globals:
# For the auto-off automation
- id: glbl_timeout_armed
type: bool
restore_value: yes
initial_value: "true"
- id: glbl_timeout_length_ticks
type: int
restore_value: yes
# 5 min * 60 seconds = 300
initial_value: "300"
# We ALSO need to keep track of the number of 'ticks'
# add _prefix to indicate 'internal'
- id: _glbl_timeout_ticks
type: int
restore_value: no
initial_value: "0"
script:
# End meaning the natural conclusion of the timer. Do whatever we're supposed to do when the timer fires off
- id: on_timer_end
mode: single
then:
- switch.turn_off: sprinkler_1
- logger.log: "on_timer_end: output should be off!"
# Stop meaning the pre-mature ending of the timer
- id: on_timer_stop
# Do not start a new run. Issue a warning.
mode: single
then:
# For now, just clean up the globals and stop the ticking.
# This hook could be used to do so much more, though.
##
- lambda: |-
auto TAG = "script.on_timer_stop";
id(_timer_tick).stop();
id(_glbl_timeout_ticks) = 0;
ESP_LOGD(TAG, "_timer_tick now stopped and _glbl_timeout_ticks is %d", id(_glbl_timeout_ticks));
- id: _timer_tick
# Start a new run after previous runs completes. This will happen until timer.stop() is called on us
##
mode: queued
then:
# A single 'tick' is 1 second long
- delay: 1s
- lambda: |-
auto TAG = "lambda._timer_tick";
// First, update the number of ticks
id(_glbl_timeout_ticks) += 1;
// Then check if we have timed out
if (id(_glbl_timeout_ticks) >= id(glbl_timeout_length_ticks) ) {
// If we have timed out, run the script to handle the timer expiration
// It's cleaner to call out to a script rather than put all the "what no?" code in here!
id(on_timer_end).execute();
ESP_LOGD(TAG, "_glbl_timeout_ticks is >= glbl_timeout_length_ticks %d >= %d ", id(_glbl_timeout_ticks), id(glbl_timeout_length_ticks) );
// And then re-set the internal counter
id(_glbl_timeout_ticks) = 0;
// And finally, stop the ticking timer
id(_timer_tick).stop();
ESP_LOGD(TAG, "_timer_tick now stopped!");
} else {
ESP_LOGD(TAG, "_glbl_timeout_ticks is < glbl_timeout_length_ticks %d < %d ", id(_glbl_timeout_ticks), id(glbl_timeout_length_ticks) );
// make sure we run again.. unless we're not supposed to
if( id(glbl_timeout_armed) ) {
id(_timer_tick).execute();
}
}