Hi, with help of https://github.com/EwoutBergsma/OTA-Update-OpenThread-ESPHome I’ve got my ESP32-H2 (no wifi, only thread and BLE) working.
Please find below my config.
---
# esp32h2-c # this device has no WIFI !, only Thread over IPv6, BLE (and Zigbee if compiled into it)
substitutions:
devname: "esp32h2-c"
esphome:
name: ${devname}
friendly_name: ${devname}
min_version: 2025.9.0
name_add_mac_suffix: false
on_boot:
- priority: 500
then:
- logger.log: "* prevent deep sleep during boot/wake-up"
- deep_sleep.prevent: deep_sleep_control
- if:
condition:
lambda: return esp_sleep_get_wakeup_cause()==0;
then:
- logger.log: "* normal boot"
- light.turn_on: red
- wait_until:
condition:
api.connected:
state_subscription_only: true
- logger.log: 'Home Assistant is connected!'
- light.turn_off: red
- script.execute: fast_blink_green
- homeassistant.event:
event: esphome.device_booted
else:
- logger.log: "* wake-up event"
- script.execute: fast_blink_orange
- deep_sleep.allow: deep_sleep_control
esp32:
variant: ESP32H2
framework:
type: esp-idf
deep_sleep:
id: deep_sleep_control
run_duration: 1 minutes
sleep_duration: 1 minutes
# Enable logging
logger:
hardware_uart: USB_SERIAL_JTAG
level: INFO
baud_rate: 115200
# Enable Home Assistant API
api:
encryption:
key: !secret esphome_api_key
# Allow Over-The-Air updates
ota:
- platform: esphome
id: my_ota
on_begin:
then:
- logger.log: "OTA start"
- deep_sleep.prevent: deep_sleep_control
on_end:
then:
- logger.log: "OTA end"
- deep_sleep.allow: deep_sleep_control
time:
- platform: homeassistant
id: homeassistant_time
network:
enable_ipv6: true
openthread:
device_type: FTD
tlv: [YOUR TLV]
force_dataset: true
###################################
globals:
- id: dim_set
type: float
restore_value: yes
initial_value: '100'
output:
- platform: ledc
pin: GPIO10
id: gpio_10
- platform: ledc
pin: GPIO11
id: gpio_11
- platform: ledc
pin: GPIO12
id: gpio_12
light:
- platform: monochromatic
output: gpio_10
default_transition_length: 0s
name: "Red"
id: 'red'
on_turn_on:
then:
- light.turn_off: green
- light.turn_off: orange
- script.execute:
id: dim_light
effects: !include common/esphome_light_effects.yaml
- platform: monochromatic
output: gpio_11
default_transition_length: 0s
name: "Orange"
id: 'orange'
on_turn_on:
then:
- light.turn_off: red
- light.turn_off: green
- script.execute:
id: dim_light
effects: !include common/esphome_light_effects.yaml
- platform: monochromatic
output: gpio_12
default_transition_length: 0s
name: "Green"
id: 'green'
on_turn_on:
then:
- light.turn_off: red
- light.turn_off: orange
- script.execute:
id: dim_light
effects: !include common/esphome_light_effects.yaml
# - platform: esp32_rmt_led_strip
# rgb_order: GRB
# pin: GPIO08
# num_leds: 1
# chipset: ws2812
# name: "sobRGB"
text_sensor:
- platform: openthread_info
ip_address:
name: "Thread IP Address"
channel:
name: "Thread Channel"
role:
name: "Thread Device Role"
rloc16:
name: "Thread RLOC16"
ext_addr:
name: "Thread Extended Address"
eui64:
name: "Thread EUI64"
network_name:
name: "Thread Network Name"
network_key:
name: "Thread Network Key"
pan_id:
name: "Thread PAN ID"
ext_pan_id:
name: "Thread Extended PAN ID"
binary_sensor:
- platform: status
name: ${devname}_status
- platform: gpio
pin:
number: GPIO13
mode:
input: true
pulldown: true
name: ${devname}_sensor_a
interrupt_type: ANY
- platform: gpio
pin:
number: GPIO14
mode:
input: true
pulldown: true
name: ${devname}_sensor_b
interrupt_type: ANY
switch:
- platform: restart
id: restart_switch
name: ${devname}_restart
- platform: safe_mode
id: safe_mode_switch
name: ${devname}_safe
- platform: template
name: Dimmer
optimistic: True
id: dim
turn_on_action:
then:
- globals.set:
id: dim_set
value: '20'
- script.execute:
id: dim_light
- logger.log: 'Dimmer on'
turn_off_action:
then:
- globals.set:
id: dim_set
value: '100'
- script.execute:
id: dim_light
- logger.log: 'Dimmer off'
- platform: template
id: deep_sleep_enter
name: Enter DeepSleep
turn_on_action:
then:
- deep_sleep.enter: deep_sleep_control
- platform: template
id: deep_sleep_prevent
name: Prevent DeepSleep
turn_on_action:
then:
- deep_sleep.prevent: deep_sleep_control
sensor:
- platform: uptime
name: ${devname}_uptime
- platform: template
name: "Wakeup Cause"
id: wuc
accuracy_decimals: 0
lambda: return esp_sleep_get_wakeup_cause();
script:
- id: fast_blink_green
then:
- repeat:
count: 3
then:
- light.turn_on: green
- delay: 250ms
- light.turn_off: green
- delay: 200ms
- id: fast_blink_orange
then:
- repeat:
count: 3
then:
- light.turn_on: orange
- delay: 250ms
- light.turn_off: orange
- delay: 200ms
- id: fast_blink_red
then:
- repeat:
count: 3
then:
- light.turn_on: red
- delay: 250ms
- light.turn_off: red
- delay: 200ms
- id: dim_light
then:
- if:
condition:
light.is_on:
id: red
then:
- light.turn_on:
id: red
brightness: !lambda |-
// output value must be in range 0 - 1.0
return id(dim_set) / 100.0;
- if:
condition:
light.is_on:
id: orange
then:
- light.turn_on:
id: orange
brightness: !lambda |-
// output value must be in range 0 - 1.0
return id(dim_set) / 100.0;
- if:
condition:
light.is_on:
id: green
then:
- light.turn_on:
id: green
brightness: !lambda |-
// output value must be in range 0 - 1.0
return id(dim_set) / 100.0;
and common/esphome_light_effects.yaml for completeness
- strobe:
name: pulse
colors:
- state: true
brightness: 100%
duration: 5ms
- state: false
duration: 2995ms
- lambda:
name: Breathing
update_interval: 16s
lambda: |-
static int state = 0;
static int color = 1;
auto call = id(red).turn_on(); //the id of your light
call.set_transition_length(5000);
if (state == 0)
{
call.set_brightness(1.0);
}
else if (state == 1)
{
call.set_brightness(0.01);
}
call.perform();
state ++;
if (state == 2){
state = 0;
}