# ============================================================ # 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 (hoog→laag of laag→hoog) 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");