From 53807bdbae7c5502af0665f17b211e2ab84cb4d4 Mon Sep 17 00:00:00 2001 From: Aiden Date: Sat, 3 Oct 2026 18:30:32 +0800 Subject: [PATCH] Add new device --- athom-usb-switch.yaml | 355 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 athom-usb-switch.yaml diff --git a/athom-usb-switch.yaml b/athom-usb-switch.yaml new file mode 100644 index 0000000..b28c5b5 --- /dev/null +++ b/athom-usb-switch.yaml @@ -0,0 +1,355 @@ +substitutions: + # Default name + name: "athom-usb-switch" + # Default friendly name + friendly_name: "Athom USB Switch" + # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. Typically used for areas such as 'Lounge Room', 'Kitchen' etc + room: "" + # Description as appears in ESPHome & top of webserver page + device_description: "athom esp32-c6 smart usb switch" + # Project Name + project_name: "China Athom Technology.Athom USB Switch" + # Projection version denotes the release version of the yaml file, allowing checking of deployed vs latest version + project_version: "v2.0.0" + # Restore the relay (GPO switch) upon reboot to state: + relay_restore_mode: RESTORE_DEFAULT_ON + # 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" + # Set timezone of the smart plug. Useful if the plug is in a location different to the HA server. Can be entered in unix Country/Area format (i.e. "Australia/Sydney") + timezone: "" + # Set the duration between the sntp service polling ntp.org servers for an update + sntp_update_interval: 6h + # Network time servers for your region, enter from lowest to highest priority. To use local servers update as per zones or countries at: https://www.ntppool.org/zone/@ + sntp_server_1: "0.pool.ntp.org" + sntp_server_2: "1.pool.ntp.org" + sntp_server_3: "2.pool.ntp.org" + # Enables faster network connections, with last connected SSID being connected to and no full scan for SSID being undertaken + wifi_fast_connect: "false" + # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + log_level: "DEBUG" + # Enable or disable the use of IPv6 networking on the device + ipv6_enable: "false" + + power_type: "usb" +########################## End of Substitutions ######################### + +#############################ESP32C6########################### + + relay_pin: GPIO7 + button_pin: GPIO15 + led_pin: GPIO3 +#############################ESP32C6######################## + + +esphome: + name: "${name}" + friendly_name: "${friendly_name}" + comment: "${device_description}" + area: "${room}" + name_add_mac_suffix: true + min_version: 2026.8.0 + project: + name: "${project_name}" + version: "${project_version}" + platformio_options: + board_build.mcu: esp32c6 + board_build.variant: esp32c6 + board_build.flash_mode: dio + on_boot: + - priority: 600 + then: + - select.set_index: + id: power_mode + index: !lambda |- + return id(restore_mode)-1; + - lambda: |- + switch(id(restore_mode)) + { + case 1:{ + id(relay).turn_off(); + break; + } + case 2:{ + id(relay).turn_on(); + break; + } + default:{ + break; + } + } + + +esp32: + board: esp32-c6-devkitm-1 + flash_size: 4MB + variant: ESP32C6 + framework: + type: esp-idf + version: recommended + sdkconfig_options: + # @grigi found in testing that these options resulted in better responsiveness. + # BLE 4.2 is supported by ALL ESP32 boards that have bluetooth, the original and derivatives. + CONFIG_BT_BLE_42_FEATURES_SUPPORTED: y + # Also enable this on any derivative boards (S2, C3 etc) but not the original ESP32. + CONFIG_BT_BLE_50_FEATURES_SUPPORTED: y + # Extend the watchdog timeout, so the device reboots if the device appears locked up for over 10 seconds. + CONFIG_ESP_TASK_WDT_TIMEOUT_S: "10" + +preferences: + flash_write_interval: 5min + +api: + # reboot_timeout: 0s + # Only enable BLE tracking when wifi is up and api is connected + # Gives single-core ESP32-C3 devices time to manage wifi and authenticate with api + on_client_connected: + - esp32_ble_tracker.start_scan: + continuous: true + # Disable BLE tracking when there are no api connections live + on_client_disconnected: + if: + condition: + not: + api.connected: + then: + - esp32_ble_tracker.stop_scan: + +ota: + - platform: esphome + id: ota_esphome + # Enables OTA firmware flashing from a URL (used by the update component below) + - platform: http_request + id: ota_http_request + +# Required by the ota http_request platform and the update component. +# verify_ssl: false skips TLS cert validation to reduce heap/RAM pressure during +# the download; the manifest's MD5 still verifies firmware integrity before flashing. +http_request: + id: http_request_component + verify_ssl: false + +update: + # Managed updates via HTTP request: periodically checks the published manifest + # and exposes a "Firmware Update" entity, pointing at this device's GitHub Pages + # manifest. Pages URLs avoid the redirect/buffer issues of Release download URLs. + - platform: http_request + id: update_http_request + name: "Firmware Update" + source: https://athom-tech.github.io/esp32-configs/firmware/athom-usb-switch.manifest.json + # update_interval defaults to 6h (how often it checks, not installs) + +logger: + baud_rate: 0 # 0 Enables logging, but disables serial-port logging to free CPU and memory + level: ${log_level} + +mdns: + disabled: false + +web_server: + port: 80 + +network: + enable_ipv6: ${ipv6_enable} + +wifi: + # This spawns an AP with the device name and mac address with no password. + ap: {} + # 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: + +esp32_improv: + authorizer: none + +esp32_ble_tracker: + scan_parameters: + # Don't auto start BLE scanning, we control it in the `api` block's automation. + continuous: false + active: true # send scan-request packets to gather more info, like device name for some devices. + interval: 320ms # default 320ms - how long to spend on each advert channel + window: 300ms # default 30ms - how long to actually "listen" in each interval. Reduce this if device is unstable. + # If the device cannot keep up or becomes unstable, reduce the "window" setting. This may be + # required if your device is controlling other sensors or doing PWM for lights etc. + +bluetooth_proxy: + active: true + +dashboard_import: + package_import_url: github://athom-tech/esp32-configs/athom-usb-switch.yaml + +globals: + - id: restore_mode + type: int + restore_value: yes + initial_value: "2" # 0 = Always_Off. 1 = Restore_Power_Off. 2 = Always_On. + +select: + - platform: template + name: "Power On State" + id: "power_mode" + optimistic: true + icon: mdi:electric-switch + options: + - Always Off + - Always On + - Restore Power Off State + on_value: + then: + - lambda: |- + id(restore_mode)=i+1; + +binary_sensor: + - platform: status + name: "Status" + id: id_status + icon: mdi:check-network-outline + entity_category: diagnostic + + - platform: gpio + pin: + number: ${button_pin} + mode: INPUT_PULLUP + inverted: true + name: "Power Button" + id: power_button + disabled_by_default: true + filters: + - delayed_on_off: 20ms + on_multi_click: + - timing: + - ON for at most 1s + - OFF for at least 0.2s + then: + # Ignore short press when child lock is on, to stop kids toggling the socket + - if: + condition: + switch.is_off: child_lock + then: + - switch.toggle: relay + - timing: + - ON for at least 4s + then: + # Ignore long press when child lock is on, to prevent accidental factory reset + - if: + condition: + switch.is_off: child_lock + then: + - button.press: Reset + +sensor: + - platform: uptime + name: "Uptime Sensor" + id: uptime_sensor + type: + timestamp + entity_category: "diagnostic" + + - platform: wifi_signal + name: "WiFi Signal dB" + id: wifi_signal_db + update_interval: 60s + entity_category: "diagnostic" + + - platform: copy + source_id: wifi_signal_db + name: "WiFi Signal Percent" + id: wifi_signal_percent + filters: + - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0); + unit_of_measurement: "Signal %" + entity_category: "diagnostic" + device_class: "" + +button: + - platform: restart + name: "Restart" + id: id_restart + entity_category: config + + - platform: factory_reset + name: "Factory Reset" + id: Reset + entity_category: config + + - platform: safe_mode + name: "Safe Mode" + id: id_safe_mode + internal: false + entity_category: config + +switch: + - platform: gpio + name: "Switch" + pin: ${relay_pin} + id: relay + restore_mode: ${relay_restore_mode} + icon: mdi:${power_type} + + # Child lock: when on, ignore physical button short/long press, but keep remote (HA/web) control working + - platform: template + name: "Child Lock" + id: child_lock + icon: mdi:lock + optimistic: true + restore_mode: RESTORE_DEFAULT_OFF # Keep last state after power loss/reboot, default off on first boot + entity_category: config + +light: + - platform: status_led + name: "Status LED" + id: blue_led + icon: mdi:lightbulb-outline + disabled_by_default: true + pin: + inverted: true + number: ${led_pin} + +text_sensor: + - platform: wifi_info + ip_address: + name: "IP Address" + icon: mdi:ip-network + entity_category: diagnostic + ssid: + name: "Connected SSID" + icon: mdi:wifi-strength-2 + entity_category: diagnostic + mac_address: + name: "Mac Address" + icon: mdi:network-pos + entity_category: diagnostic + + # Creates a sensor showing when the device was last restarted + - platform: template + name: 'Last Restart' + id: device_last_restart + icon: mdi:clock + entity_category: diagnostic +# device_class: timestamp + +time: + - platform: sntp + id: sntp_time + # Define the timezone of the device + timezone: "${timezone}" + # Change sync interval from default 5min to 6 hours (or as set in substitutions) + update_interval: ${sntp_update_interval} + # Set specific sntp servers to use + servers: + - "${sntp_server_1}" + - "${sntp_server_2}" + - "${sntp_server_3}" + # Publish the time the device was last restarted + on_time_sync: + then: + # Update last restart time, but only once. + - if: + condition: + lambda: 'return id(device_last_restart).state == "";' + then: + - text_sensor.template.publish: + id: device_last_restart + state: !lambda 'return id(sntp_time).now().strftime("%a %d %b %Y - %I:%M:%S %p");'