Skip to content

Commit 552562d

Browse files
authored
Merge branch 'current' into patch-4
2 parents d0ca505 + 029954b commit 552562d

File tree

105 files changed

+2970
-252
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+2970
-252
lines changed

all_automations.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
"grove_tb6612fng.run",
137137
"grove_tb6612fng.standby",
138138
"grove_tb6612fng.stop",
139+
"hc8.calibrate",
139140
"homeassistant.action",
140141
"homeassistant.event",
141142
"homeassistant.service",

content/automations/all_actions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ title: ""
3131
- **fingerprint_grow:** `aura_led_control`, `cancel_enroll`, `delete`, `delete_all`, `enroll`, `led_control`
3232
- **globals:** `set`
3333
- **grove_tb6612fng:** `break`, `change_address`, `no_standby`, `run`, `standby`, `stop`
34+
- **hc8:** `calibrate`
3435
- **homeassistant:** `event`, `service`, `tag_scanned`
3536
- **http_request:** `get`, `post`, `send`
3637
- **htu21d:** `set_heater`, `set_heater_level`

content/changelog/2023.12.0.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ duplicate pin definitions. See the [Pin Schema](/guides/configuration-types#pin-
3636

3737
## Touchscreen internal changes
3838

39-
The touchscreen compoenent code has had a big overhaul which breaks any external components or open PRs for
39+
The touchscreen component code has had a big overhaul which breaks any external components or open PRs for
4040
new touchscreens. See {{< pr number="4596" repo="esphome" >}} for details if this affects you.
4141

4242
## MCP3008 breaking changes
4343

44-
The MCP3008 has has a restructure of the code and at the same time the default update interval has been changed
44+
The MCP3008 has had a restructure of the code and at the same time the default update interval has been changed
4545
to 60 seconds, the units, device class and state class default have also been set to sane defaults expected for
4646
a voltage sensor.
4747

content/changelog/2024.12.0.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ ESPHome has now updated the core ESP32 code to use [ESP-IDF](https://github.com/
2020
This is a major upgrade and should bring more features, chip support (Most notably the ESP32-C6 that people
2121
keep raving on about) and in general more stability.
2222

23-
To acommodate this change, ESPHome has moved away from the "official" platformio provided ESP32 platform,
23+
To accommodate this change, ESPHome has moved away from the "official" platformio provided ESP32 platform,
2424
and is now using a community fork [pioarduino/platform-espressif32](https://github.com/pioarduino/platform-espressif32)
2525
as platformio has decided to stop providing ESP-IDF updates to their platform for Espressif chips. As a user,
2626
you should not notice any difference.

content/changelog/2025.12.0.md

Lines changed: 654 additions & 0 deletions
Large diffs are not rendered by default.

content/changelog/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ description: "Changelog"
33
title: "Changelog"
44
---
55

6-
{{< redirect url="/changelog/2025.11.0.html" >}}
6+
{{< redirect url="/changelog/2025.12.0.html" >}}

content/components/_index.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ Create update entities simplifying management of OTA updates.
169169
"SPI Bus","components/spi","spi.svg",""
170170
"TinyUSB","components/tinyusb","usb.svg","dark-invert"
171171
"UART","components/uart","uart.svg",""
172+
"USB CDC-ACM","components/usb_cdc_acm","usb.svg","dark-invert"
172173
"USB Host","components/usb_host","usb.svg","dark-invert"
173174
"USB UART","components/usb_uart","usb.svg","dark-invert"
174175
{{< /imgtable >}}
@@ -240,6 +241,7 @@ Sensors are organized into categories; if a given sensor fits into more than one
240241
"GCJA5","components/sensor/gcja5","gcja5.svg","Particulate","",""
241242
"GP2Y1010AU0F","components/sensor/gp2y1010au0f","gp2y1010au0f.png","Particulate","",""
242243
"Grove Multichannel Gas V2","components/sensor/grove_gas_mc_v2","grove-gas-mc-v2.png","NO₂ & CO & Ethanol & Volatile organics","",""
244+
"HC8","components/sensor/hc8","hc8.png","CO₂","",""
243245
"HM3301","components/sensor/hm3301","hm3301.jpg","Particulate","",""
244246
"iAQ-Core","components/sensor/iaqcore","iaqcore.jpg","eCO₂ & Volatile organics","",""
245247
"MH-Z19","components/sensor/mhz19","mhz19.jpg","CO₂ & Temperature","",""
@@ -291,6 +293,7 @@ Sensors are organized into categories; if a given sensor fits into more than one
291293
"Mopeka Pro Check LP","components/sensor/mopeka_pro_check","mopeka_pro_check.jpg","Tank level"
292294
"Mopeka Standard Check LP","components/sensor/mopeka_std_check","mopeka_std_check.jpg","Tank level"
293295
"RuuviTag","components/sensor/ruuvitag","ruuvitag.jpg","Temperature & Humidity & Accelerometer"
296+
"ThermoPro BLE","components/sensor/thermopro_ble","thermopro_tp357.jpg","Temperature & Humidity"
294297
"Xiaomi BLE","components/sensor/xiaomi_ble","xiaomi_mijia_logo.jpg","Various"
295298
{{< /imgtable >}}
296299

@@ -335,6 +338,7 @@ Sensors are organized into categories; if a given sensor fits into more than one
335338
"Daly BMS","components/sensor/daly_bms","daly_bms.jpg","Voltage & Current & Power"
336339
"DSMR","components/sensor/dsmr","dsmr.svg","Electrical counter"
337340
"HLW8012","components/sensor/hlw8012","hlw8012.svg","Voltage & Current & Power"
341+
"HLW8032","components/sensor/hlw8032","hlw8032.png","Voltage & Current & Power"
338342
"INA219","components/sensor/ina219","ina219.jpg","DC Current"
339343
"INA226","components/sensor/ina226","ina226.jpg","DC Current & Power"
340344
"INA228","components/sensor/ina2xx","ina228.jpg","DC Voltage & Current & Power & Charge"
@@ -380,6 +384,7 @@ Sensors are organized into categories; if a given sensor fits into more than one
380384
"EMC2101","components/emc2101","emc2101.jpg","Temperature",""
381385
"ENS160","components/sensor/ens160","ens160.jpg","eCO₂ & Air Quality",""
382386
"ENS210","components/sensor/ens210","ens210.jpg","Temperature & Humidity",""
387+
"HC8","components/sensor/hc8","hc8.png","CO₂",""
383388
"HDC1080","components/sensor/hdc1080","hdc1080.jpg","Temperature & Humidity",""
384389
"HDC2010","components/sensor/hdc2010","hdc2010.png","Temperature & Humidity",""
385390
"HHCCJCY10 (MiFlora Pink)","components/sensor/xiaomi_hhccjcy10","xiaomi_hhccjcy10.jpg","Soil moisture & Temperature & Light",""
@@ -416,6 +421,7 @@ Sensors are organized into categories; if a given sensor fits into more than one
416421
"SHTCx","components/sensor/shtcx","shtc3.jpg","Temperature & Humidity",""
417422
"SMT100","components/sensor/smt100","smt100.jpg","Moisture & Temperature",""
418423
"STS3X","components/sensor/sts3x","sts3x.jpg","Temperature",""
424+
"STTS22H","components/sensor/stts22h","stts22h.jpg","Temperature",""
419425
"TC74","components/sensor/tc74","tc74.jpg","Temperature",""
420426
"TEE501","components/sensor/tee501","TEE501.png","Temperature",""
421427
"TE-M3200","components/sensor/tem3200","tem3200.jpg","Temperature & Pressure",""
@@ -739,6 +745,7 @@ Often known as "tag" or "card" readers within the community.
739745
"ILI9486","components/display/ili9xxx","ili9341.jpg"
740746
"ILI9488","components/display/ili9xxx","ili9488.svg"
741747
"WSPICOLCD","components/display/ili9xxx","ili9488.svg"
748+
"HUB75 LED Matrix","components/display/hub75","hub75.svg"
742749
"Inkplate","components/display/inkplate","inkplate6.jpg"
743750
"LCD Display","components/display/lcd_display","lcd.jpg"
744751
"MAX7219 Dot Matrix","components/display/max7219digit","max7219digit.jpg"
@@ -999,6 +1006,7 @@ at the {{< docref "light/fastled" "FastLED Light" >}}.
9991006

10001007
{{< imgtable >}}
10011008
"Time Core","components/time/index","clock-outline.svg","dark-invert"
1009+
"BM8563 RTC","components/time/bm8563","bm8563.svg",""
10021010
"DS1307 RTC","components/time/ds1307","clock-outline.svg","dark-invert"
10031011
"RX8130 RTC","components/time/rx8130","clock-outline.svg","dark-invert"
10041012
"GPS Time","components/time/gps","crosshairs-gps.svg","dark-invert"
@@ -1037,6 +1045,7 @@ Used for creating infrared (IR) or radio frequency (RF) remote control transmitt
10371045
ESPHome to cellular networks. **Does not encompass Wi-Fi.**
10381046

10391047
{{< imgtable >}}
1048+
"CC1101","components/cc1101","cc1101.webp",""
10401049
"IR Remote Climate","components/climate/climate_ir","air-conditioner-ir.svg","dark-invert"
10411050
"Remote Receiver","components/remote_receiver","remote.svg","dark-invert"
10421051
"Remote Transmitter","components/remote_transmitter","remote.svg","dark-invert"

content/components/alarm_control_panel/template.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ control panel is armed, a fault on this type of zone will cause the alarm to go
8484
The `instant_always` trigger mode is typically used for tamper inputs. Irrespective of whether the alarm control panel
8585
is armed, a fault will always cause the alarm to go directly to the `triggered` state.
8686

87-
The `delayed_follower` trigger mode is typically specifed for interior passive infared (PIR) or microwave sensors. One
87+
The `delayed_follower` trigger mode is typically specified for interior passive infrared (PIR) or microwave sensors. One
8888
of two things happen when a `delayed_follower` zone is faulted:
8989

9090
1. When the alarm panel is in the armed state, a fault on a zone with `delayed_follower` specified will cause the alarm
@@ -95,7 +95,7 @@ of two things happen when a `delayed_follower` zone is faulted:
9595

9696
The `delayed_follower` trigger mode offers better protection if someone enters a premises via an unprotected window
9797
or door. If there is a PIR guarding the main hallway, it will cause an instant trigger of the alarm panel as someone
98-
entered the premises in a unusual manner. Likewise, if someone enters the premises though a door set to the `delayed`
98+
entered the premises in an unusual manner. Likewise, if someone enters the premises through a door set to the `delayed`
9999
trigger mode, and then triggers the PIR, the alarm will stay in the `pending` state until either they disarm the alarm,
100100
or the pending timer expires.
101101

content/components/api.md

Lines changed: 180 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ api:
5858
> The defaults are set to balance memory usage with allowing multiple simultaneous connections.
5959

6060
- **max_send_queue** (*Optional*, int): The maximum number of messages that can be queued for sending per connection before the connection is dropped. Must be between 1 and 64.
61-
Defaults to `5` for ESP8266/RP2040, `8` for ESP32/BK72xx/RTL87xx/LN882x, `16` for host platform. This prevents memory exhaustion when a client is slow or network-stalled.
61+
Defaults to:
62+
- `5` for ESP8266/RP2040,
63+
- `8` for ESP32/BK72xx/LN882x/nRF52/RTL87xx,
64+
- `16` for host platform.
65+
66+
This prevents memory exhaustion when a client is slow or network-stalled.
6267
Each queued message uses approximately 8-12 bytes of overhead plus the message size.
6368

6469
> [!NOTE]
@@ -104,7 +109,7 @@ api:
104109

105110
- **id** (*Optional*, [ID](/guides/configuration-types#id)): Manually specify the ID used for code generation.
106111
- **password** (*Optional*, **Deprecated**, string): The password to protect the API Server with. Defaults
107-
to no password. It is recommended to use the `encryption` -> `key` above instead of the the `password`.
112+
to no password. It is recommended to use the `encryption` -> `key` above instead of the `password`.
108113

109114
- **on_client_connected** (*Optional*, [Action](/automations/actions#all-actions)): An automation to perform when a client
110115
connects to the API. See [`on_client_connected` Trigger](#api-on_client_connected_trigger).
@@ -385,25 +390,51 @@ api:
385390
- logger.log: "API client disconnected!"
386391
```
387392

393+
## Conditions
394+
388395
{{< anchor "api-connected_condition" >}}
389396

390-
## `api.connected` Condition
397+
### `api.connected` Condition
398+
399+
This [Condition](/automations/actions#all-conditions) checks if at least one client is connected to the ESPHome native API.
400+
401+
#### Configuration variables
402+
403+
- **state_subscription_only** (*Optional*, boolean): If enabled, only counts clients that have subscribed to entity state updates. This filters out logger-only connections (such as `esphome logs` command), which can cause false positives when waiting for Home Assistant. Defaults to `false`.
391404

392-
This [Condition](/automations/actions#all-conditions) checks if at least one client is connected to the ESPHome
393-
native API. Please note client not only includes Home Assistant, but also ESPHome's OTA log output
394-
if logs are shown remotely.
405+
**Check if any client is connected:**
395406

396407
```yaml
397408
on_...:
398409
if:
399410
condition:
400411
api.connected:
401412
then:
402-
- logger.log: API is connected!
413+
- logger.log: Client is connected to API!
403414
```
404415

405416
The lambda equivalent for this is `id(api_id).is_connected()`.
406417

418+
**Check if a client subscribed to entity states is connected (typically Home Assistant):**
419+
420+
```yaml
421+
on_boot:
422+
- wait_until:
423+
condition:
424+
api.connected:
425+
state_subscription_only: true
426+
- logger.log: Home Assistant is connected!
427+
- homeassistant.event:
428+
event: esphome.device_booted
429+
```
430+
431+
The lambda equivalent for this is `id(api_id).is_connected(true)`.
432+
433+
**Use Cases:**
434+
435+
- Use `state_subscription_only: false` (default) to detect any API connection
436+
- Use `state_subscription_only: true` when you need to ensure Home Assistant (or other connections that subscribe to states) is connected before sending events or calling services, preventing errors from logger-only connections
437+
407438
{{< anchor "api-device-actions" >}}
408439

409440
## User-defined Actions
@@ -412,6 +443,10 @@ It is also possible to get data from Home Assistant to ESPHome with user-defined
412443
When you declare actions in your ESPHome YAML file, they will automatically show up in
413444
Home Assistant and you can call them directly.
414445

446+
> [!NOTE]
447+
> User-defined actions can also send responses back to the calling client using the `api.respond` action.
448+
> See [Action Responses](#action-responses) for details.
449+
415450
```yaml
416451
# Example configuration entry
417452
api:
@@ -471,6 +506,144 @@ Each of these also exist in array form:
471506
- bool[]: An array of boolean values. C++ type: `std::vector<bool>`
472507
- ... - Same for other types.
473508

509+
### Action Responses
510+
511+
User-defined actions can send responses back to the calling client (such as Home Assistant). This enables
512+
bidirectional communication where actions can report success/error status or return structured JSON data.
513+
514+
#### Response Modes
515+
516+
The response behavior is controlled by the `supports_response` option, which can be set explicitly or
517+
auto-detected based on your action configuration:
518+
519+
- **none** (default): No response is sent. The action is "fire and forget".
520+
- **status**: Reports success/error status without data. Auto-detected when `api.respond` is used without `data:`.
521+
- **optional**: Returns JSON data when the client requests it. Auto-detected when `api.respond` is used with `data:`.
522+
- **only**: Always returns JSON data. Must be set explicitly. Use this for query-type actions.
523+
524+
#### Configuration variables
525+
526+
- **supports_response** (*Optional*, string): The response mode for this action. One of `none`, `status`,
527+
`optional`, or `only`. If not specified, the mode is auto-detected based on `api.respond` usage in the action.
528+
529+
#### Trigger variables
530+
531+
When `supports_response` is not `none`, the following variables are available in the action:
532+
533+
- **call_id** (`uint32_t`): A unique identifier for this action call. Used internally by `api.respond`.
534+
- **return_response** (`bool`): Only available in `optional` mode. Indicates whether the client requested
535+
a response. You don't typically need to check this - `api.respond` handles it automatically.
536+
537+
### `api.respond` Action
538+
539+
This action sends a response back to the client that called the user-defined action. It can report
540+
success/error status and optionally include JSON data.
541+
542+
#### Configuration variables
543+
544+
- **success** (*Optional*, boolean, [templatable](/automations/templates)): Whether the action succeeded.
545+
Defaults to `true`.
546+
- **error_message** (*Optional*, string, [templatable](/automations/templates)): An error message to include
547+
when `success` is `false`. Defaults to an empty string.
548+
- **data** (*Optional*, [lambda](/automations/templates#config-lambda)): A lambda that populates a JSON object
549+
with response data. The lambda receives a `root` variable of type [`JsonObject`](https://arduinojson.org/v7/api/jsonobject/)
550+
that you can populate with key-value pairs.
551+
552+
#### Status Response Example
553+
554+
Report success or error without returning data:
555+
556+
```yaml
557+
api:
558+
actions:
559+
- action: validate_input
560+
variables:
561+
value: int
562+
then:
563+
- if:
564+
condition:
565+
lambda: 'return value < 0;'
566+
then:
567+
- api.respond:
568+
success: false
569+
error_message: "Value must be positive"
570+
else:
571+
- api.respond:
572+
success: true
573+
```
574+
575+
#### Data Response Example
576+
577+
Return structured JSON data to the caller:
578+
579+
```yaml
580+
api:
581+
actions:
582+
- action: get_sensor_data
583+
variables:
584+
sensor_name: string
585+
then:
586+
- api.respond:
587+
data: !lambda |-
588+
root["sensor"] = sensor_name;
589+
root["value"] = id(my_sensor).state;
590+
root["unit"] = "°C";
591+
root["timestamp"] = id(homeassistant_time).now().timestamp;
592+
```
593+
594+
This action will be auto-detected as `optional` mode because it uses `api.respond` with `data:`.
595+
596+
#### Query Action Example
597+
598+
For actions that always return data (like queries), explicitly set `supports_response: only`:
599+
600+
```yaml
601+
api:
602+
actions:
603+
- action: get_device_info
604+
supports_response: only
605+
then:
606+
- api.respond:
607+
data: !lambda |-
608+
root["hostname"] = App.get_name();
609+
root["version"] = ESPHOME_VERSION;
610+
root["uptime"] = millis() / 1000;
611+
```
612+
613+
#### Nested JSON Data
614+
615+
You can create complex nested JSON structures:
616+
617+
```yaml
618+
api:
619+
actions:
620+
- action: get_full_status
621+
supports_response: only
622+
then:
623+
- api.respond:
624+
data: !lambda |-
625+
root["device"]["name"] = "living_room";
626+
root["device"]["version"] = 1;
627+
root["sensors"]["temperature"] = id(temp_sensor).state;
628+
root["sensors"]["humidity"] = id(humidity_sensor).state;
629+
```
630+
631+
#### Calling from Home Assistant
632+
633+
Actions with response support appear in Home Assistant with their response mode indicated. You can call
634+
them and receive the response data:
635+
636+
```yaml
637+
# Home Assistant automation example
638+
action: esphome.device_get_sensor_data
639+
data:
640+
sensor_name: "living_room"
641+
response_variable: sensor_response
642+
```
643+
644+
The response will be available in the `sensor_response` variable with the structure you defined in the
645+
`data:` lambda.
646+
474647
## Advantages over MQTT
475648

476649
The ESPHome native API has many advantages over using MQTT for communication with Home

content/components/binary_sensor/analog_threshold.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@ binary_sensor:
3434
threshold: 0.5
3535
```
3636
37+
Alternatively, you can achieve similar functionality using a
38+
[Template Binary Sensor](/components/binary_sensor/template) with the `condition` option:
39+
40+
```yaml
41+
# Alternative using template binary sensor
42+
binary_sensor:
43+
- platform: template
44+
name: "Engine Running"
45+
condition:
46+
sensor.in_range:
47+
id: motor_current_sensor
48+
above: 0.5
49+
```
50+
51+
> [!NOTE]
52+
> The template approach does not support hysteresis. Use `analog_threshold` if you need
53+
> different upper and lower thresholds to reduce noise.
54+
3755
## Configuration variables
3856

3957
- **sensor_id** (**Required**, [ID](/guides/configuration-types#id)): The ID of the source sensor.

0 commit comments

Comments
 (0)