shelly-scripts/1PM-gen4/detached-script.js

424 lines
No EOL
12 KiB
JavaScript

# ============================================================
# ESPHome - Shelly 1PM Gen4
# Gira System 55 aan-uit schakelaar
# ============================================================
#
# Schakelmodi:
# - Detached: Schakelaar stuurt events naar HA, relay wordt
# door HA-automations aangestuurd.
# - Toggle: Elke schakelactie togglet de lamp.
# - Volgen: Schakelaarstand = lampstatus (aan/uit).
#
# Fallback:
# Wanneer er GEEN verbinding is met Home Assistant (geen WiFi
# of API), valt de schakelaar automatisch terug op Toggle-modus
# zodat de lamp altijd lokaal bedienbaar blijft.
#
# Beveiliging:
# Overtemperatuur (>75°C) en overstroom (>16A) schakelen
# het relay automatisch uit.
#
# ============================================================
# PINOUT Shelly 1PM Gen4 (ESP32-C6)
# ============================================================
# GPIO0 - Status LED (inverted)
# GPIO1 - Deviceknop (op de Shelly zelf)
# GPIO3 - NTC temperatuursensor
# GPIO4 - Relay
# GPIO6 - UART TX (BL0942 energiemeting)
# GPIO7 - UART RX (BL0942 energiemeting)
# GPIO10 - Switch input (wandschakelaar)
# GPIO12 - Add-on module Digital in
# GPIO16 - Add-on module Data in
# GPIO9 - Add-on module Data out
# GPIO17 - Add-on module Analog in
#
# Bron: https://devices.esphome.io/devices/shelly-1pm-gen-4/
# ============================================================
substitutions:
device_name: "shelly-1pm-gen4"
friendly_name: "Shelly 1PM Gen4"
# Pas onderstaande aan per kamer/locatie:
light_name: "Lamp"
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
esp32:
variant: esp32c6
flash_size: 8MB
framework:
type: esp-idf
# ------------------------------------------------------------
# Logging
# ------------------------------------------------------------
logger:
baud_rate: 0 # Disable UART logging (UART wordt gebruikt voor BL0942)
# ------------------------------------------------------------
# WiFi
# ------------------------------------------------------------
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Fallback Access Point als WiFi wegvalt
ap:
ssid: "${friendly_name} AP"
password: !secret ap_password
fast_connect: true
power_save_mode: LIGHT
# Captive portal voor fallback AP
captive_portal:
# ------------------------------------------------------------
# Home Assistant API
# ------------------------------------------------------------
api:
encryption:
key: !secret api_key
# ------------------------------------------------------------
# OTA Updates
# ------------------------------------------------------------
ota:
- platform: esphome
password: !secret ota_password
# ------------------------------------------------------------
# Webserver (optioneel, handig voor debugging)
# ------------------------------------------------------------
web_server:
port: 80
# ------------------------------------------------------------
# Globale variabelen
# ------------------------------------------------------------
globals:
# Schakelmodus: 0 = Detached, 1 = Toggle, 2 = Volgen
- id: switch_mode
type: int
restore_value: yes
initial_value: "0"
# ------------------------------------------------------------
# Relay output
# ------------------------------------------------------------
output:
- platform: gpio
id: relay_output
pin: GPIO4
# ------------------------------------------------------------
# Lamp (als Light-entity voor volledige HA-integratie)
# ------------------------------------------------------------
light:
- platform: binary
id: lamp
name: "${light_name}"
output: relay_output
restore_mode: RESTORE_DEFAULT_OFF
# ------------------------------------------------------------
# UART voor BL0942 energiemeting
# ------------------------------------------------------------
uart:
id: bl0942_uart
tx_pin: GPIO6
rx_pin:
number: GPIO7
mode:
pullup: true
input: true
baud_rate: 9600
stop_bits: 1
# ------------------------------------------------------------
# Wandschakelaar (Gira System 55 aan-uit schakelaar)
# ------------------------------------------------------------
# Een aan-uit schakelaar heeft twee stabiele standen.
# Bij elke standswijziging (hooglaag of laaghoog) wordt
# een actie getriggerd. We gebruiken on_state zodat BEIDE
# overgangen als schakelmoment werken.
# ------------------------------------------------------------
binary_sensor:
- platform: gpio
id: wall_switch
name: "${light_name} Schakelaar"
pin:
number: GPIO10
mode:
input: true
pullup: true
inverted: true
filters:
- delayed_on: 30ms
- delayed_off: 30ms
on_state:
then:
- lambda: |-
// -----------------------------------------------
// FALLBACK: Geen API-verbinding → altijd Toggle
// -----------------------------------------------
if (!id(ha_connected).state) {
auto call = id(lamp).toggle();
call.perform();
ESP_LOGD("switch", "Geen HA-verbinding → fallback toggle");
return;
}
// -----------------------------------------------
// DETACHED (modus 0)
// -----------------------------------------------
if (id(switch_mode) == 0) {
// Stuur event naar HA; HA bepaalt wat er gebeurt
// De schakelaarstand wordt als binary_sensor zichtbaar
ESP_LOGD("switch", "Detached → event naar HA");
return;
}
// -----------------------------------------------
// TOGGLE (modus 1)
// -----------------------------------------------
if (id(switch_mode) == 1) {
auto call = id(lamp).toggle();
call.perform();
ESP_LOGD("switch", "Toggle → lamp omgeschakeld");
return;
}
// -----------------------------------------------
// VOLGEN (modus 2)
// -----------------------------------------------
if (id(switch_mode) == 2) {
if (x) {
auto call = id(lamp).turn_on();
call.perform();
} else {
auto call = id(lamp).turn_off();
call.perform();
}
ESP_LOGD("switch", "Volgen → lamp volgt schakelaar");
return;
}
# Knop op de Shelly zelf
- platform: gpio
id: device_button
name: "${light_name} Knop"
pin:
number: GPIO1
mode:
input: true
pullup: true
inverted: true
filters:
- delayed_on: 30ms
- delayed_off: 30ms
on_press:
then:
- light.toggle: lamp
# HA-verbindingsstatus (voor fallback-logica)
- platform: status
id: ha_connected
name: "${friendly_name} Status"
internal: true
# Overtemperatuur-beveiliging (latching)
- platform: template
id: error_overtemp
name: "${friendly_name} Oververhitting"
device_class: problem
entity_category: diagnostic
lambda: |-
if (id(error_overtemp).state) return true;
if (!isnan(id(temperature).state) && id(temperature).state > 75.0) return true;
return false;
on_press:
then:
- light.turn_off: lamp
- logger.log:
level: WARN
format: "BEVEILIGING: Oververhitting gedetecteerd (>75°C) → lamp uit"
# Overstroom-beveiliging (latching)
- platform: template
id: error_overpower
name: "${friendly_name} Overstroom"
device_class: problem
entity_category: diagnostic
lambda: |-
if (id(error_overpower).state) return true;
if (!isnan(id(sensor_current).state) && id(sensor_current).state > 16.0) return true;
return false;
on_press:
then:
- light.turn_off: lamp
- logger.log:
level: WARN
format: "BEVEILIGING: Overstroom gedetecteerd (>16A) → lamp uit"
# ------------------------------------------------------------
# Schakelmodus selector (instelbaar vanuit HA)
# ------------------------------------------------------------
select:
- platform: template
id: switch_mode_select
name: "${light_name} Schakelmodus"
icon: "mdi:light-switch"
options:
- "Detached"
- "Toggle"
- "Volgen"
initial_option: "Detached"
optimistic: true
restore_value: true
set_action:
- lambda: |-
if (x == "Detached") {
id(switch_mode) = 0;
ESP_LOGI("mode", "Schakelmodus → Detached");
} else if (x == "Toggle") {
id(switch_mode) = 1;
ESP_LOGI("mode", "Schakelmodus → Toggle");
} else if (x == "Volgen") {
id(switch_mode) = 2;
ESP_LOGI("mode", "Schakelmodus → Volgen");
}
# ------------------------------------------------------------
# Sensoren
# ------------------------------------------------------------
sensor:
# NTC Temperatuur (GPIO3)
- platform: ntc
id: temperature
name: "${friendly_name} Temperatuur"
sensor: temperature_resistance
icon: mdi:thermometer
entity_category: diagnostic
unit_of_measurement: "°C"
accuracy_decimals: 1
calibration:
b_constant: 3350
reference_resistance: 10kOhm
reference_temperature: 25°C
- platform: resistance
id: temperature_resistance
sensor: temperature_voltage
configuration: DOWNSTREAM
resistor: 10kOhm
- platform: adc
id: temperature_voltage
pin: GPIO3
attenuation: 11db
# BL0942 Energiemeting
- platform: bl0942
uart_id: bl0942_uart
update_interval: 10s
line_frequency: 50Hz # EU netfrequentie
voltage:
name: "${light_name} Spanning"
id: sensor_voltage
unit_of_measurement: "V"
accuracy_decimals: 1
entity_category: diagnostic
filters:
- sliding_window_moving_average:
window_size: 5
send_every: 5
current:
name: "${light_name} Stroom"
id: sensor_current
unit_of_measurement: "A"
accuracy_decimals: 3
filters:
- sliding_window_moving_average:
window_size: 5
send_every: 5
power:
name: "${light_name} Vermogen"
id: sensor_power
unit_of_measurement: "W"
accuracy_decimals: 1
filters:
- sliding_window_moving_average:
window_size: 5
send_every: 5
energy:
name: "${light_name} Energie"
id: sensor_energy
unit_of_measurement: "kWh"
accuracy_decimals: 3
entity_category: diagnostic
device_class: energy
state_class: total_increasing
frequency:
name: "${light_name} Frequentie"
id: sensor_frequency
unit_of_measurement: "Hz"
accuracy_decimals: 2
entity_category: diagnostic
# WiFi signaalsterkte
- platform: wifi_signal
name: "${friendly_name} WiFi Signaal"
update_interval: 60s
# Uptime
- platform: uptime
name: "${friendly_name} Uptime"
update_interval: 300s
# ------------------------------------------------------------
# Status LED
# ------------------------------------------------------------
status_led:
pin:
number: GPIO0
inverted: true
# ------------------------------------------------------------
# Diagnostische tekst-sensoren
# ------------------------------------------------------------
text_sensor:
- platform: wifi_info
ip_address:
name: "${friendly_name} IP"
ssid:
name: "${friendly_name} SSID"
- platform: version
name: "${friendly_name} ESPHome Versie"
# ------------------------------------------------------------
# Knoppen vanuit HA
# ------------------------------------------------------------
button:
- platform: restart
name: "${friendly_name} Herstart"
icon: "mdi:restart"
- platform: safe_mode
name: "${friendly_name} Safe Mode"
icon: "mdi:shield-bug"
# Reset beveiligings-latches
- platform: template
name: "${friendly_name} Reset Beveiliging"
icon: "mdi:shield-refresh"
on_press:
then:
- lambda: |-
id(error_overtemp).publish_state(false);
id(error_overpower).publish_state(false);
ESP_LOGI("protection", "Beveiligingen gereset");