diff --git a/esphome/esp-6buttontest-pmb.yaml b/esphome/esp-6buttontest-pmb.yaml index 0e7f045..49ce213 100644 --- a/esphome/esp-6buttontest-pmb.yaml +++ b/esphome/esp-6buttontest-pmb.yaml @@ -3,40 +3,67 @@ # PMB Electronics 6 Button ESP32 Switch # V1.0 2025-08-04 Initial Version ########################################################################################## -# PMB Details Page https://rcbeacon.com/blog/?p=5488 +# PMB Product Details Page https://rcbeacon.com/blog/?p=5488 +# +# DEVICE GPIO +# +# OPERATION (as set up at V1.0) +# 1. There are 4 buttons that toggle a virtual relay and turn on the +# associated LED when pressed. Inputs are debounced. +# 2. Button 5 does the same, but also if double pressed, a different V relay switches on +# and the LED slowly pulses. If held down for 2 seconds, a 3rd V relay switches on and the +# LED fast pulses (the 3 relays are exclusive, ie interlocked) +# 3. The knob gives a reported value of 0-100% when turned (as well as the adc value). +# this is calibratable +# 4. The system supply voltage is reported (10-20V) anbd is also calibratable. +# # NOTES # 1. To Flash via ESPHome, you likely have to connect to the computer, start the flash -# process then hold down the I00 button. I think GPIO12 is preventing the flash process +# then hold down I00 button. I think GPIO12 connection is preventing the flash process. # 2. OTA flash to an Existing Tasmota device is likely a bit hard with and ESP32 as they # expect a signed Tasmota binary... and partition layout needs to be fixed anyway # 3. EspHome warns on compiling: "legacy adc driver is deprecated, please migrate to use # esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode -# drivers respectively" [-Wcpp]"" +# drivers respectively" [-Wcpp]" (I'm not bothered with this) +# 4. Normally I'd include SNTP for timing functions, and uptime diagnostics etc. +# I have commented this out in the packages section as not sure it is really needed here # ########################################################################################## ########################################################################################## ########################################################################################## # SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +# USUALLY YOU WILL ONLY NEED TO CHANGE VALUES UNDER THIS SECTION # If NOT using a secrets file, just replace "!secret my_key" with the password etc (in quotes) ########################################################################################## substitutions: # Device Naming - device_name: "esp-6buttontest-pmb" #the filename should be the device_name.yaml + device_name: "esp-6buttontest-pmb" # the filename should be the device_name.yaml friendly_name: "PMB Light Switch Test" - description_comment: "Multi Button Wallswitch in standard AU/NZ flush size. 5 Buttons with LEDs and one Knob" + description_comment: "Multi Button Wallswitch in standard AU/NZ flush size. In this case 5 Buttons with LEDs and one Knob" device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + # Wifi details + wifi_ssid: !secret ha_wifi_ssid + wifi_password: !secret ha_wifi_password + fallback_ap_password: !secret fallback_ap_password # if it doesn't connect, it will create its own AP + # Passwords api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-6buttontest-pmb_ip + + # Add these if we are giving it a static ip, or remove them in the Wifi section + static_ip_subnet: !secret ha_wifi_subnet + static_ip_gateway: !secret ha_wifi_gateway + static_ip_dns1: !secret ha_wifi_dns1 + static_ip_dns2: !secret ha_wifi_dns2 - # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - pwm_freq: "1000Hz" - ledc_bits: "12" + # MQTT Settings + mqtt_server: !secret ha_mqtt_server + mqtt_username: !secret ha_mqtt_username + mqtt_password: !secret ha_mqtt_password + mqtt_topic: "esphome" # main topic for the mqtt server, call it what you like # Switch Naming switch_1_name: "Red" @@ -51,39 +78,180 @@ substitutions: variable_1_full_scale: "3.14" # ADC reading when at 100% (adjust after calibration) variable_1_min_scale: "0.14" # volts at ADC for 0% (adjust after calibration) + # Device Settings + log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for for general sensors etc + pwm_freq: "1000Hz" # espHome default is 1000Hz, but will go much higher... (not much point for a switch LED) + ledc_bits: "12" # espHome default resolution is 12 bits + + # Network reconnect every x hours to ensure best access point + # This is my own script. No need to use if only one AP or it is always fixed. + base_interval_hours: "23" # Base interval in hours + random_offset_max_minutes: "59" # Max random offset in minutes + + # Enables faster network connections, with last connected SSID being connected to and + # no full scan for SSID being undertaken + wifi_fast_connect: "false" + + # Define a domain for this device to use. i.e. iot.home.lan (so device will appear as + # athom-smart-plug-v2.iot.home.lan in DNS/DHCP logs) + dns_domain: ".local" + + # Automatically add the mac address to the name eg so you can use a single firmware for all devices + # I don't tend to like doing this, but good for many identical devices + add_mac_suffix: "false" + + # Enable or disable the use of IPv6 networking on the device + ipv6_enable: "false" + ########################################################################################## # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html ########################################################################################## -packages: - common_wifi: !include - file: common/network_common.yaml - vars: - local_device_name: "${device_name}" - local_static_ip_address: "${static_ip_address}" - local_ota_pass: "${ota_pass}" - common_api: !include - file: common/api_common.yaml - vars: - local_api_key: "${api_key}" +# NOTE: ALL COMMENTED AS FOR THIS TEST EVERYTHING IS IN ONE YAML FILE (except no SNTP) +########################################################################################## +#packages: + #common_wifi: !include + # file: common/network_common.yaml + # vars: + # local_device_name: "${device_name}" + # local_static_ip_address: "${static_ip_address}" + # local_ota_pass: "${ota_pass}" + #common_api: !include + # file: common/api_common.yaml + # vars: + # local_api_key: "${api_key}" #common_webportal: !include # file: common/webportal_common.yaml - common_mqtt: !include - file: common/mqtt_common.yaml - vars: - local_device_name: "${device_name}" - common_sntp: !include - file: common/sntp_common.yaml - common_general_sensors: !include - file: common/sensors_common.yaml - vars: - local_friendly_name: "${friendly_name}" - local_update_interval: "${update_interval}" + #common_mqtt: !include + # file: common/mqtt_common.yaml + # vars: + # local_device_name: "${device_name}" + #common_sntp: !include + # file: common/sntp_common.yaml + #common_general_sensors: !include + # file: common/sensors_common.yaml + # vars: + # local_friendly_name: "${friendly_name}" + # local_update_interval: "${update_interval}" -############################################# +########################################################################################## +# Common Wifi Settings +# https://esphome.io/components/wifi.html +# +# Power Save mode (can reduce wifi reliability) +# NONE (least power saving, Default for ESP8266) +# LIGHT (Default for ESP32) +# HIGH (most power saving) +########################################################################################## +wifi: + ssid: ${wifi_ssid} + password: ${wifi_password} + #enable_rrm: true # (ESP32 only) enable 802.11k Radio Resource Management + #enable_btm: true # (ESP32 only) enable 802.11v BSS Transition Management + #power_save_mode: LIGHT # https://esphome.io/components/wifi.html#wifi-power-save-mode + manual_ip: # optional static IP address + static_ip: ${static_ip_address} + gateway: ${static_ip_gateway} + subnet: ${static_ip_subnet} + dns1: ${static_ip_dns1} + dns2: ${static_ip_dns2} + ap: # Details for fallback hotspot in case wifi connection fails https://esphome.io/components/wifi.html#access-point-mode + ssid: ${device_name} AP + password: ${fallback_ap_password} + ap_timeout: 10min # Time until it brings up fallback AP. default is 1min + # Allow rapid re-connection to previously connect WiFi SSID, skipping scan of all SSID + fast_connect: "${wifi_fast_connect}" + # Define dns domain / suffix to add to hostname + domain: "${dns_domain}" + +#captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails + +########################################################################################## +# Enable Over the Air Update Capability +# https://esphome.io/components/ota.html?highlight=ota +########################################################################################## +ota: + - platform: esphome + password: ${ota_pass} + version: 2 + +########################################################################################## +# Safe Mode +# Safe mode will detect boot loops +# https://esphome.io/components/safe_mode +########################################################################################## +safe_mode: + +########################################################################################## +# Network +# global configuration for all types of networks +# https://esphome.io/components/network.html +########################################################################################## +network: + enable_ipv6: ${ipv6_enable} + +########################################################################################## +# SCRIPT +# Restart Networking every x hours + rand mins. Starts on reboot and always runs +# This ensure that the device is connected to the best AP, but no need for it +# if one AP and it is always reliable. +########################################################################################## +script: + - id: random_reconnect + mode: restart + then: + - lambda: |- + // Compute total delay: base hours + random offset minutes + uint32_t extra; + #if defined(ESP32) + // ESP32 (both Arduino & IDF builds) uses esp_random() + extra = esp_random() % (${random_offset_max_minutes} + 1); + #elif defined(ESP8266) + // ESP8266 Arduino core + extra = os_random() % (${random_offset_max_minutes} + 1); + #else + // Fallback to esp_random() on other platforms + extra = esp_random() % (${random_offset_max_minutes} + 1); + #endif + uint32_t total_s = ${base_interval_hours} * 3600 + extra * 60; + ESP_LOGI("random_reconnect", "Next reconnect in %u seconds", total_s); + // Delay inside lambda (blocks script execution but OK for reconnect timing) + delay(total_s * 1000); + - logger.log: "network_check: performing reconnect" + - wifi.disable: {} + - delay: 1s + - wifi.enable: {} + - script.execute: random_reconnect + +########################################################################################## +# MQTT Monitoring +# https://esphome.io/components/mqtt.html?highlight=mqtt +# MUST also have api enabled if you enable MQTT! +########################################################################################## +mqtt: + broker: ${mqtt_server} + topic_prefix: ${mqtt_topic}/${device_name} + username: ${mqtt_username} + password: ${mqtt_password} + discovery: False # enable entity discovery (true is default) + discover_ip: False # enable device discovery (true is default) + id: mqtt_client + reboot_timeout: 0s # same for MQTT + +########################################################################################## +# Enable the Home Assistant API +# https://esphome.io/components/api.html +########################################################################################## +api: + encryption: + key: ${api_key} + reboot_timeout: 0s # disables watchdog reboot on API failure + +########################################################################################## # ESPHome # https://esphome.io/components/esphome.html -############################################# +########################################################################################## esphome: name: ${device_name} friendly_name: ${friendly_name} @@ -106,9 +274,12 @@ esp32: preferences: flash_write_interval: 5min # not too important but anything written for reboot mem will wear the flash - ########################################################################################## -# GLOBALS - State storage for vrelays +# GLOBAL VARIABLES +# https://esphome.io/components/globals.html +########################################################################################## +# We are using globals here to store the states of the virtual relays +# They will also be restored on power loss. ########################################################################################## globals: - id: vrelay_1_state @@ -140,10 +311,10 @@ globals: restore_value: yes initial_value: 'false' -############################################# +########################################################################################## # ESPHome Logging Enable # https://esphome.io/components/logger.html -############################################# +########################################################################################## logger: level: ${log_level} #INFO Level suggested, or DEBUG for testing @@ -180,7 +351,6 @@ binary_sensor: - delayed_off: 50ms on_press: - switch.toggle: vrelay_1 - - platform: gpio pin: number: GPIO35 @@ -192,7 +362,6 @@ binary_sensor: - delayed_off: 50ms on_press: - switch.toggle: vrelay_2 - - platform: gpio pin: number: GPIO05 @@ -204,7 +373,6 @@ binary_sensor: - delayed_off: 50ms on_press: - switch.toggle: vrelay_3 - - platform: gpio pin: number: GPIO33 @@ -216,7 +384,6 @@ binary_sensor: - delayed_off: 50ms on_press: - switch.toggle: vrelay_4 - - platform: gpio pin: number: GPIO16 @@ -231,13 +398,11 @@ binary_sensor: - ON for 50ms to 500ms then: - switch.toggle: vrelay_5b - # Hold - timing: - ON for at least 2s then: - switch.toggle: vrelay_5c - # Single click - timing: - ON for 50ms to 500ms @@ -245,6 +410,7 @@ binary_sensor: then: - switch.toggle: vrelay_5 + # FUTURE: Board allows for 6 buttons #- platform: gpio # pin: # number: GPIO12 @@ -257,6 +423,12 @@ binary_sensor: # on_press: # - switch.toggle: vrelay_6 + ## DIAGNOSTIC ONLY SENSORS BELOW ## + - platform: status + name: "Network Status" + icon: mdi:check-network-outline + entity_category: "diagnostic" + ########################################################################################## # OUTPUT COMPONENT # https://esphome.io/components/light/index.html @@ -287,6 +459,12 @@ output: pin: GPIO17 frequency: ${pwm_freq} + # FUTURE: Board allows for 6 buttons + #- platform: ledc + # id: led6_output + # pin: GPIOXX + # frequency: ${pwm_freq} + ########################################################################################## # LIGHT COMPONENT # https://esphome.io/components/light/index.html @@ -325,6 +503,12 @@ light: - state: OFF duration: 500ms + # FUTURE: Board allows for 6 buttons + #- platform: monochromatic + # id: led6 + # output: led6_output + # name: "LED 6: ${switch_6_name}" + ########################################################################################## # SWITCH COMPONENT # https://esphome.io/components/switch/ @@ -437,25 +621,33 @@ switch: - lambda: |- id(vrelay_5c_state) = false; #- switch.turn_off: vrelay_5 - + + # FUTURE: Board allows for 6 buttons #- platform: template # name: "Output 6: ${switch_6_name}" # id: vrelay_6 - # restore_mode: RESTORE_DEFAULT_OFF - # optimistic: false + # lambda: |- + # return id(vrelay_6_state); # turn_on_action: # - light.turn_on: led6 + # - lambda: |- + # id(vrelay_6_state) = true; # turn_off_action: # - light.turn_off: led6 + # - lambda: |- + # id(vrelay_6_state) = false; - - +########################################################################################## +# SENSOR COMPONENT +# https://esphome.io/components/sensor/ +########################################################################################## sensor: # Raw ADC reading from GPIO36 + # ADC Component https://esphome.io/components/sensor/adc.html - platform: adc pin: GPIO36 id: dimmer_raw - name: "Dimmer Raw" + name: "${variable_1_name} Raw" attenuation: 11db update_interval: 0.5s on_value: @@ -463,28 +655,22 @@ sensor: - lambda: |- // Convert raw ADC (x) to volts float volts = x; - // Apply min/max calibration float min_v = ${variable_1_min_scale}; float max_v = ${variable_1_full_scale}; - // Calculate percentage between min and max float pct = ((volts - min_v) / (max_v - min_v)) * 100.0; - // Clamp result between 0 and 100 if (pct > 100.0) pct = 100.0; if (pct < 0.0) pct = 0.0; - // Publish to percentage sensor id(dimmer_percent).publish_state(pct); - # Percentage sensor derived from raw ADC - platform: template id: dimmer_percent name: "${variable_1_name}" unit_of_measurement: "%" accuracy_decimals: 0 - # External supply voltage from GPIO39 - platform: adc pin: GPIO39 @@ -493,10 +679,79 @@ sensor: attenuation: 11db # Up to ~3.9V at ADC pin update_interval: 2s filters: - - calibrate_linear: + - calibrate_linear: # https://esphome.io/components/sensor/#calibrate-linear # Format: raw_value -> real_voltage_at_pin - - 00.66 -> 10.00 # Example: ADC reads 0.80 when pin is actually 3.20V - - 00.99 -> 15.00 # Example: ADC reads 1.00 when pin is actually 4.00V - - 01.30 -> 20.00 # Example: ADC reads 0.90 when pin is actually 3.60V + - 00.66 -> 10.00 # Example: ADC reads X when pin is -> actually Y + - 00.99 -> 15.00 + - 01.30 -> 20.00 #- multiply: 4.00 # Voltage divider ratio - unit_of_measurement: "V" \ No newline at end of file + unit_of_measurement: "V" + + ## DIAGNOSTIC ONLY SENSORS BELOW ## + - platform: uptime # Uptime for this device in seconds + name: "Uptime (s):" + update_interval: ${update_interval} + id: uptime_sensor + entity_category: "diagnostic" + - platform: wifi_signal # Wifi Strength + name: "Wifi (dB):" + id: wifi_signal_db + update_interval: ${update_interval} + entity_category: "diagnostic" + - platform: copy # Reports the WiFi signal strength in % + source_id: wifi_signal_db + name: "WiFi (%):" + filters: + - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0); + unit_of_measurement: "% Max" + entity_category: "diagnostic" + device_class: "" + +########################################################################################## +# Text Sensors +# https://esphome.io/components/text_sensor/index.html +########################################################################################## +text_sensor: + ## DIAGNOSTIC ONLY SENSORS BELOW ## + - platform: version + name: "Version:" + entity_category: "diagnostic" + - platform: wifi_info + ip_address: + icon: mdi:ip-network + entity_category: diagnostic + name: "IP Address:" + ssid: + name: "Connected SSID" + icon: mdi:wifi-strength-2 + entity_category: diagnostic + mac_address: + name: "MAC Address:" + icon: mdi:network-pos + entity_category: diagnostic + - platform: uptime # Uptime for this device human readable + name: "Uptime:" + icon: mdi:clock-start + update_interval: ${update_interval} + entity_category: "diagnostic" + +########################################################################################## +# BUTTON COMPONENT +# https://esphome.io/components/button/ +########################################################################################## +# Diagnostic buttons ued here and non-active, activated if needed in HA +########################################################################################## +button: + ## DIAGNOSTIC ONLY BUTTONS BELOW ## + - platform: safe_mode + name: "Safe Mode Restart:" + entity_category: "diagnostic" + disabled_by_default: true + - platform: restart + name: "Restart:" + entity_category: "diagnostic" + disabled_by_default: true + - platform: factory_reset + name: "FACTORY RESET:" + entity_category: "diagnostic" + disabled_by_default: true \ No newline at end of file