Compare commits

..
Author SHA1 Message Date
J. Nick Koston 92b515e615 [cover] Pack the cover traits flags into one byte 2026-10-21 15:57:17 -10:00
01b29dbf53 [cover] Add stop tilt support (#20248)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-10-21 15:49:07 -10:00
esphome[bot] e15797c18b Bump aioesphomeapi from 46.17.0 to 46.18.0 (#21332) 2026-10-22 01:46:31 +00:00
J. Nick Koston 3c6b1e66e7 [ci] Add the MQTT TLS, udp.write and entity icon flows to the hardware-test skill (#21264) 2026-10-21 15:30:27 -10:00
J. Nick Koston 179f9ed395 [mt6701_i2c][opentherm][const] Move CONF_OUT_PIN to the shared component constants (#21329) 2026-10-21 15:25:39 -10:00
J. Nick Koston 2f7105fa54 [core] Fix the findings of clang-tidy 23 (#21301) 2026-10-21 21:20:54 -04:00
J. Nick Koston e3590bdac7 [ci] Label pull requests that change api.proto (#21294) 2026-10-21 15:15:43 -10:00
Jonathan Swoboda 54440a3559 [pulse_counter] Attach the software interrupt to the counted edges only (#21271) 2026-10-21 20:46:48 -04:00
J. Nick Koston 45c7fd5214 [cdc_acm_uart][serial_proxy][const] Move CONF_DTR_PIN and CONF_RTS_PIN to the shared component constants (#21325) 2026-10-22 00:41:12 +00:00
Jesse Hills bfcefbb896 [core] Assert sub-device relations in integration test (#21326) 2026-10-21 14:40:46 -10:00
J. Nick Koston 40a58e1d3c [mt6701_i2c][as5600][const] Move CONF_PWM_FREQUENCY to the shared component constants (#21324) 2026-10-21 14:37:39 -10:00
Jesse Hills 07f24708b4 [core] Add relation option to sub-devices (#21232) 2026-10-22 00:27:38 +00:00
Jesse Hills c26967f623 [core] Add unit tests for core modules and test the pure-Python YAML loader (#21314) 2026-10-22 13:13:45 +13:00
esphome[bot] 9ff76f4d79 Bump aioesphomeapi from 46.16.0 to 46.17.0 (#21322) 2026-10-21 14:09:14 -10:00
J. Nick Koston e17e386dea [core] Read entity icons and device classes straight from flash (#21111) 2026-10-22 00:01:44 +00:00
Jesse Hills 7133d02d4c [core] Remove dead generated_files logic from copy_src_tree (#21312) 2026-10-22 11:52:03 +13:00
J. Nick Koston e2d261e744 [web_server] Read flash state strings PROGMEM-aware on ESP8266 (#21316) 2026-10-21 12:06:44 -10:00
Darafei PraliaskouskiandJ. Nick Koston 6e054555ac [const][heatpumpir][mitsubishi] Move horizontal_default/vertical_default to shared constants (#21309)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-21 21:47:22 +00:00
esphome[bot] 4fd3e41ee7 Bump aioesphomeapi from 46.15.1 to 46.16.0 (#21311) 2026-10-21 21:47:16 +00:00
J. Nick Koston 4280ac9659 [core] Move the remaining components to flash-safe entity names and deprecate get_name() (#20615) 2026-10-22 10:07:14 +13:00
J. Nick Kostonandpre-commit-ci-lite[bot] 211dcfa325 [core] Keep entity names in flash on ESP8266 (#20423)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-10-22 10:07:14 +13:00
c74a9da996 [veml6040] Add VEML6040 RGBW colour sensor (#20812)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-21 10:54:25 -10:00
Jonathan Swoboda b67ac5d0be [esp32_hosted] Keep the OTA watchdog timeout through the coprocessor end call (#21300) 2026-10-21 16:41:28 -04:00
9c4edc767b [core] Update paho-mqtt to v2.1.0 (#18402)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-21 10:30:55 -10:00
esphome[bot] 04432d3fd7 Bump aioesphomeapi from 46.14.0 to 46.15.1 (#21298) 2026-10-21 20:23:00 +00:00
J. Nick Koston 63b610bf17 [tests] Wait for the ld2410 query ACK log line instead of asserting it arrived (#21191) 2026-10-21 10:13:22 -10:00
J. Nick Koston 62c9e05541 [tests] Wait for the template sensor's first reading before the Home Assistant service tests (#21302) 2026-10-21 09:56:20 -10:00
esphome[bot] 671ac3e0bc Bump bundled esphome-device-builder to 1.26.0 (#21299) 2026-10-21 09:45:18 -10:00
dependabot[bot] 6671ded245 Bump platformdirs from 4.13.3 to 4.13.4 (#21297)
Signed-off-by: dependabot[bot] <support@github.com>
2026-10-21 19:32:36 +00:00
dependabot[bot] 9010c4bb2e Bump filelock from 4.2.1 to 4.2.2 (#21295)
Signed-off-by: dependabot[bot] <support@github.com>
2026-10-21 19:32:16 +00:00
J. Nick Koston e0a48ff683 [waveshare_epaper] Set removal of the deprecated component for 2027.5.0 (#20692) 2026-10-21 19:06:38 +00:00
e3d7b957a7 [mqtt] increase TLS options and compatibility (#14318)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-21 19:02:31 +00:00
J. Nick Koston 9ab230f98d [speaker] Build the pipeline task names on the stack (#21203) 2026-10-21 08:41:59 -10:00
261 changed files with 5198 additions and 1376 deletions
+5 -2
View File
@@ -115,7 +115,7 @@ Per-topic scripts, each described in the matching `reference/recipes/<component>
(host driver, Zephyr driver probe), `rtsp_server/` (protocol client, raw rate reader, measurement set,
API image grab), `cse7766/` (API observer with ping), `zephyr_coredump/` (reader flow, decode with the
Zephyr tools), `libretiny_prefs/` (rtc preference harness header), `libretiny_crash/` (BK72xx crash probe header and
capture decoder), `api_outgoing/` (wake cycle and Wi-Fi drop timing readers), `ld2450/` (zone number driver), `dfrobot_sen0395/` (API driver and case runner), `homeassistant_light/` (direct bulb driver, held-report case driver), `usb_audio/` (URL player), `speaker_media_player/` (API player driver, pipeline task case runner), `web_server/` (SSE client, request mix, SSE and HTTPD case runners), `mqtt/` (broker config with WebSocket listeners, test CA, transport case runner).
capture decoder), `api_outgoing/` (wake cycle and Wi-Fi drop timing readers), `ld2450/` (zone number driver), `dfrobot_sen0395/` (API driver and case runner), `homeassistant_light/` (direct bulb driver, held-report case driver), `usb_audio/` (URL player), `speaker_media_player/` (API player driver, pipeline task case runner), `web_server/` (SSE client, request mix, SSE and HTTPD case runners), `mqtt/` (broker config with TLS, client-certificate and WebSocket listeners, test CA with server and client certificates, transport case runner, flash-and-drive runner, CLI TLS check without a board), `udp/` (datagram recorder, `udp.write` payload checker and case driver), `entity_icons/` (icon and device class readback over the API, MQTT discovery, web_server and dump_config, with a comparer).
## Templates in `$SKILL/templates`
@@ -132,11 +132,14 @@ capture decoder), `api_outgoing/` (wake cycle and Wi-Fi drop timing readers), `l
`globals-storage-dut.yaml`, `usb-audio-waveshare-s3-eth-dut.yaml`, `usb-audio-sendspin-s3-eth-dut.yaml`,
`cast-pro-1-sendspin-control.yaml`, `aux-2-preprod-stock-dut.yaml`, `aux-2-preprod-usb-audio-dut.yaml`,
`dfrobot-sen0395-dut.yaml`, `aux-2-preprod-speaker-player-dut.yaml`, `web-server-sse-dut.yaml`,
`mqtt-transport-dut.yaml`.
`mqtt-transport-dut.yaml`, `mqtt-tls-dut.yaml`, `udp-write-dut.yaml`, `entity-icon-dut.yaml`.
## When something looks wrong
- A capture stopped early or a line is missing: check the timestamps before trusting it.
- A script that pipes into `tee` never ends although its work is done: a background command written as
`(cd dir && server & echo $!)` backgrounds the whole `cd && server` list, so a shell stays behind holding the
pipe open and `$!` is that shell, not the server. Write `(cd dir && exec server > out 2>&1 < /dev/null) &`.
- The client never joins the AP: another board may still run an AP with the same SSID, or the device
booted with saved credentials because the name was reused. One AP device at a time on the bench.
- Builds come out byte-identical between branches: the wrong tree was imported (rule 3). The reverse
@@ -11,14 +11,14 @@ One file per component, named after it:
- [`hdmi_cec.md`](hdmi_cec.md): two-board wire
- [`ld2450.md`](ld2450.md): polygon zones, zone number round trip through the radar's readback
- [`libretiny.md`](libretiny.md): rtc preference emulation, BK72xx crash report on the next boot
- [`mqtt.md`](mqtt.md): broker bench, QoS, reconnect, crash log over MQTT, WebSocket transports with a local and a public broker
- [`mqtt.md`](mqtt.md): broker bench, QoS, reconnect, crash log over MQTT, WebSocket transports with a local and a public broker, TLS trust sources (own CA, client certificate, certificate bundle, no verification) with the CLI check
- [`nrf52.md`](nrf52.md): dongle board support
- [`online_image.md`](online_image.md): stalled and malformed downloads
- [`openthread.md`](openthread.md): border router on the S3 host plus H2 RCP
- [`ota.md`](ota.md): overlap and lock, timeouts, deflate
- [`rtsp_server.md`](rtsp_server.md): camera streaming on the Waveshare ESP32-S3-ETH
- [`scheduler.md`](scheduler.md): loop wake A/B
- [`udp.md`](udp.md): datagrams, multicast, sockets
- [`udp.md`](udp.md): datagrams, multicast, sockets, `udp.write` payload shapes
- [`usb_cdc_acm.md`](usb_cdc_acm.md): nRF52840 dongle host driver
- [`wifi.md`](wifi.md): reboot_timeout with a fallback AP, DHCP lease cache, Easy Connect (DPP)
- [`zephyr.md`](zephyr.md): preferences on the nRF52840 dongle
@@ -29,4 +29,4 @@ One file per component, named after it:
- [`usb_audio.md`](usb_audio.md): USB audio speaker and microphone, the usb_host FIFO split, and Music Assistant playback through sendspin
- [`dfrobot_sen0395.md`](dfrobot_sen0395.md): SEN0395 mmWave command flow, module quirks and overlong lines through its error reply
- [`speaker.md`](speaker.md): media player pipeline tasks on the Connect AUX-2 with the `speaker` platform player
- [`web_server.md`](web_server.md): state SSE stress and the HTTPD task stack on web_server_idf
- [`web_server.md`](web_server.md): state SSE stress and the HTTPD task stack on web_server_idf, entity icon and device class readback
@@ -20,7 +20,7 @@ the TLS listener's certificate, both run in the scratch directory so keys, logs
to `NAME/#`, sends a switch command and an `on_message` topic, presses the 3000 byte publish button over the API,
restarts the local broker when the last argument is `restart` (the PID in `mosquitto.pid`, written when the broker
was started with `mosquitto -c mosquitto-ws.conf & echo $! > mosquitto.pid` in the working directory next to the
certificates), checks its three ports answer again, and prints the broker's message counts with the device log. `mosquitto_sub` cannot speak
certificates), checks every listener in the broker config answers again, and prints the broker's message counts with the device log. `mosquitto_sub` cannot speak
WebSocket, so it subscribes on the plain listener of the same broker. Cases: `tcp` on 1883, `ws` on 9001, `wss` on
9002 with `certificate_authority` (the certificate names an address, so `skip_cert_cn_check: true`), `wss` to
test.mosquitto.org on 8081 with no CA for the certificate bundle, and two negatives that must never connect: a
@@ -29,3 +29,25 @@ different CA (`mbedtls_ssl_handshake returned -0x2700`) and the self-signed serv
default in the generated sdkconfig. The TLS session costs about 29 kB of internal heap while connected; the public
broker carries other devices' `esphome/discover` traffic, which is noise. Results:
https://github.com/esphome/esphome/pull/16056#issuecomment-6301034019
## TLS trust sources on ESP-IDF (#14318)
One build per trust source from `templates/mqtt-tls-dut.yaml`: broker only (port must resolve to 1883),
`certificate_authority` with no port (must resolve to 8883), `verify_ssl: false` with no CA, the CA plus
`client_certificate` and `client_certificate_key` on the 8884 listener that requires one, `transport: wss` with the CA,
`tls: true` to test.mosquitto.org on 8886 for the certificate bundle, and `tls: true` to the local self-signed broker as
the negative. `scripts/mqtt/mosquitto-ws.conf` now has the 8883 and 8884 listeners and `scripts/mqtt/make_test_ca.sh`
also writes `client.crt`/`client.key`. Before flashing, check each build's `src/esphome/core/defines.h` for
`USE_MQTT_TLS`, `USE_MQTT_CERT_BUNDLE` and `USE_MQTT_TLS_INSECURE` and its `sdkconfig.<name>` for
`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE` and `CONFIG_ESP_TLS_INSECURE`: only the bundle builds may carry the bundle and only
the unverified build the insecure flags. `scripts/mqtt/flash_and_drive.sh TREE YAML PORT KEY BROKER_HOST
local|public|neg` runs one build end to end (flash, bounded capture, `cases.sh` with a restart for the local broker,
counts and the broker's per-listener connection lines) and prints the config dump's `TLS:` line (`CA certificate`,
`certificate bundle` or `no verification`). The CLI side (`esphome/mqtt.py`) is covered without a board by
`scripts/mqtt/cli_tls_check.sh TREE [neg] YAML...`, which runs `esphome clean-mqtt` under a timeout: status 124
after `Connected to MQTT broker!` is a pass, and with `neg` each config must instead fail with
`CERTIFICATE_VERIFY_FAILED` and never connect. Python's default SSL
context rejects a CA that lacks a `keyUsage` extension (`CA cert does not include key usage extension`) while mbedTLS
on the device accepts it, which is why the test CA carries `basicConstraints` and `keyUsage`. A broker kill shows as one
`Last esp-tls error: 0x8008` on every build, TLS or not. Results:
https://github.com/esphome/esphome/pull/14318#issuecomment-6311863827
@@ -9,3 +9,18 @@ listener. Broadcast to boards is lossy under power save, unicast is not. Flood a
reconnect on the Pico keeps IGMP membership. Set a long loop interval from `wifi.on_connect`
(`App.set_loop_interval(20000)`), not `on_boot`, or Wi-Fi connect crawls. The `logger.log` action
rejects `%.*s`; use a lambda.
## udp.write payload shapes (#21263, ApplyBytes)
`templates/udp-write-dut.yaml` puts every payload shape behind a template button (constant 4 bytes twice, 3, 9, 0,
128, 129 and 600 bytes, a 300 byte lambda, a simple value, a string) plus an `on_receive` that replies with the
received bytes reversed. `scripts/udp/write_cases.sh DEVICE_IP KEY` records the device's datagrams with
`udp_listen.py` on the test host, presses the buttons two seconds apart, sends one unicast datagram for the echo and
compares everything byte for byte with `check.py`; a missing datagram shifts every later one, so read the first
mismatch. Before flashing, check the generated `main.cpp`: on ESP8266 a constant payload is copied out of its
`PROGMEM` table into `uint8_t esphome__bytes[N]` up to the stack limit and into `std::make_unique<uint8_t[]>` beyond,
identical payloads share one table, a lambda is sent from its vector. An empty constant payload is generated as
`send_packet(nullptr, 0)`, and the raw lwIP UDP `sendto` used on ESP8266 rejected a null buffer with `EINVAL`
(`sendto() error 22` in the log, no datagram) until it accepted `nullptr` with a zero length; the old
`TemplatableBytes::visit` had passed a zero length stack buffer instead. Compare sizes against the stacked PR's own
head when the PR is stacked, not against dev. Results: https://github.com/esphome/esphome/pull/21263
@@ -29,3 +29,32 @@ clients. Entity URLs use the entity name, URL encoded, not an object id. The HTT
request of the boot; compare after the mix and after the SSE round, with two boots when the numbers are close.
Results: https://github.com/esphome/esphome/pull/21109#issuecomment-6300582328 and
https://github.com/esphome/esphome/pull/21038#issuecomment-6301310182
## Entity icon and device class readback (#21111)
Covers every path that reads an entity's icon or device class: the native API listing, MQTT discovery, the web_server
`/events` listing and REST endpoints, and `dump_config`. `templates/entity-icon-dut.yaml` (ESP8266 board with wifi,
encrypted api, ota, web_server and mqtt against a local broker) carries a sensor with a 63 character icon, one with no
icon or device class, an internal sensor, and binary_sensor, switch, button, text_sensor, number, select, event, cover
and text entities with icons and device classes. The per-run file supplies `name` and `broker_ip` through
substitutions. Flash the PR and base builds under different names, then from the scratch directory:
```sh
scripts/entity_icons/readback.sh DEVICE_IP KEY NAME BROKER_HOST cap-NAME.txt # once per build
scripts/entity_icons/compare.sh ic-base ic-pr # api, web, mqttn, dump all identical
```
`readback.sh` takes about 25 s once the device is on the network: 12 s of `mosquitto_sub` on `homeassistant/#` and
`NAME/#`, the API listing (`api_list.py`, one JSON line per entity with icon, device class, unit, options and event
types) and `web_dump.py` (6 s on `/events`, keeping only the listing rows that carry `domain`, then a GET of each
listed id with `?detail=all` and one retry, because the ESP8266 async server occasionally leaves a request unanswered
within 5 s). The web ids are `domain/Name`, not object ids, and `/event/<name>` has no GET handler (404 on every
build). `mqtt_norm.py` drops the `dev` block (compile time) and the `NAME/debug` topic (heap probe), so a clean run
differs in nothing. `dump_config` prints icons and device classes only for some domains; button, event and
binary_sensor icons never appear there.
Found with this flow on 2026-10-21: since #19577 every ESP8266 `web_server` build that lists a cover, climate, lock,
valve, update, alarm_control_panel or water_heater entity reboots with `Exception (3) LoadStoreErr` in
`json::linked(const char *)` (the ROM `strlen` on a flash address), fixed by #21316. The cover in the template keeps
that path covered; before #21316 is merged, apply its one line change to both trees or the web_server comparison
cannot run.
@@ -0,0 +1,56 @@
"""List every entity over the native API with its icon, device class and unit: one sorted JSON line each.
usage: api_list.py HOST KEY OUT
"""
import asyncio
import json
import pathlib
import sys
from aioesphomeapi import APIClient
HOST, KEY, OUT = sys.argv[1], sys.argv[2], sys.argv[3]
async def main() -> None:
c = APIClient(HOST, 6053, None, noise_psk=KEY)
await c.connect(login=True)
ents, _ = await c.list_entities_services()
rows = []
for e in ents:
row = {
"type": type(e).__name__,
"name": e.name,
"object_id": e.object_id,
"icon": e.icon,
}
for k in (
"device_class",
"unit_of_measurement",
"event_types",
"options",
"mode",
):
if hasattr(e, k):
v = getattr(e, k)
row[k] = (
list(v)
if isinstance(v, (list, tuple))
else (v.name if hasattr(v, "name") else v)
)
row["entity_category"] = (
e.entity_category.name
if hasattr(e.entity_category, "name")
else e.entity_category
)
row["disabled_by_default"] = e.disabled_by_default
rows.append(row)
rows.sort(key=lambda r: (r["type"], r["name"]))
with pathlib.Path(OUT).open("w", encoding="utf-8") as f:
f.writelines(json.dumps(r, sort_keys=True) + "\n" for r in rows)
print(f"{len(rows)} entities listed")
await c.disconnect()
asyncio.run(main())
@@ -0,0 +1,13 @@
#!/bin/sh
# compare.sh NAME_A NAME_B : diff the readback.sh outputs of two device names (api, web, mqttn and, when present, dump)
# after replacing each name with DEV. Exit 1 when any pair differs; the diffs stay in cmp-KIND.diff.
A=$1; B=$2; rc=0
[ -n "$A" ] && [ -n "$B" ] || { echo "usage: compare.sh NAME_A NAME_B"; exit 2; }
for k in api web mqttn dump; do
ext=jsonl; [ $k = dump ] && ext=txt
[ -f "$PWD/$k-$A.$ext" ] && [ -f "$PWD/$k-$B.$ext" ] || { echo "$k: missing"; [ $k = dump ] || rc=1; continue; }
sed "s/$A/DEV/g; s/$(echo "$A" | tr - _)/DEV/g" "$PWD/$k-$A.$ext" > "$PWD/cmp-$k-a.txt"
sed "s/$B/DEV/g; s/$(echo "$B" | tr - _)/DEV/g" "$PWD/$k-$B.$ext" > "$PWD/cmp-$k-b.txt"
if diff -u "$PWD/cmp-$k-a.txt" "$PWD/cmp-$k-b.txt" > "$PWD/cmp-$k.diff"; then echo "$k: identical ($(wc -l < "$PWD/cmp-$k-b.txt" | tr -d ' ') lines)"; else echo "$k: DIFFERS"; head -20 "$PWD/cmp-$k.diff"; rc=1; fi
done
exit $rc
@@ -0,0 +1,37 @@
"""Normalise mosquitto_sub output (topic TAB payload) for one device: drop other devices, replace the name, drop dev block.
usage: mqtt_norm.py IN NAME OUT
"""
import json
import pathlib
import sys
IN, NAME, OUT = sys.argv[1], sys.argv[2], sys.argv[3]
rows = {}
with pathlib.Path(IN).open(encoding="utf-8") as f:
for line in f:
topic, _, payload = line.rstrip("\n").partition("\t")
if (
f"/{NAME}/" not in topic and not topic.startswith(f"{NAME}/")
) or topic == f"{NAME}/debug":
continue
topic = topic.replace(NAME, "DEV")
try:
obj = json.loads(payload)
except ValueError:
rows[topic] = payload.replace(NAME, "DEV")
continue
if isinstance(obj, dict):
obj.pop("dev", None)
obj = {
k: (v.replace(NAME, "DEV") if isinstance(v, str) else v)
for k, v in obj.items()
}
rows[topic] = obj
with pathlib.Path(OUT).open("w", encoding="utf-8") as f:
f.writelines(
json.dumps({"topic": t, "payload": rows[t]}, sort_keys=True) + "\n"
for t in sorted(rows)
)
print(f"{len(rows)} topics for {NAME}")
@@ -0,0 +1,18 @@
#!/bin/sh
# readback.sh DEVICE_IP KEY NAME BROKER_HOST [CAPTURE] : record how a device built from templates/entity-icon-dut.yaml
# reports its entity icons and device classes: the native API listing (api-NAME.jsonl), the retained MQTT discovery
# payloads and states (mqtt-NAME.txt, normalised to mqttn-NAME.jsonl with the device name replaced and the debug topic
# dropped), the web_server /events listing plus every REST endpoint with ?detail=all (web-NAME.jsonl) and, when a
# serial CAPTURE is given, the dump_config Icon and Device Class lines (dump-NAME.txt, timestamps and line numbers
# removed). KEY as for api_button.py. Outputs go to the working directory; compare two names with compare.sh.
HERE=$(cd "$(dirname "$0")" && pwd); PY=${PYTHON:-python3}; DEV=$1; KEY=$2; N=$3; B=$4; CAP=$5; rc=0; TAB=$(printf '\t')
[ -n "$DEV" ] && [ -n "$KEY" ] && [ -n "$N" ] && [ -n "$B" ] || { echo "usage: readback.sh DEVICE_IP KEY NAME BROKER_HOST [CAPTURE]"; exit 2; }
timeout 12 mosquitto_sub -h "$B" -v -t 'homeassistant/#' -t "$N/#" -F "%t$TAB%p" > "$PWD/mqtt-$N.txt" 2> "$PWD/mqtt-$N.err"
$PY "$HERE/mqtt_norm.py" "$PWD/mqtt-$N.txt" "$N" "$PWD/mqttn-$N.jsonl" || rc=1
$PY "$HERE/api_list.py" "$DEV" "$KEY" "$PWD/api-$N.jsonl" || { echo "API listing failed"; rc=1; }
$PY "$HERE/web_dump.py" "$DEV" "$PWD/web-$N.jsonl" || { echo "web_server dump failed"; rc=1; }
if [ -n "$CAP" ]; then
LC_ALL=C grep -a '\]: Icon: \|\]: Device Class: ' "$CAP" | LC_ALL=C sed 's/\x1b\[[0-9;]*m//g; s/^\[[^]]*\]//; s/:[0-9]*\]:/]:/' | sort > "$PWD/dump-$N.txt"
echo "dump_config icon lines $(grep -c 'Icon:' "$PWD/dump-$N.txt"), device class lines $(grep -c 'Device Class:' "$PWD/dump-$N.txt")"
fi
exit $rc
@@ -0,0 +1,99 @@
"""Dump the web_server view of every entity: the /events listing (detail all) and each REST endpoint with ?detail=all.
usage: web_dump.py HOST OUT
"""
import json
import pathlib
import socket
import sys
import time
import urllib.parse
import urllib.request
HOST, OUT = sys.argv[1], sys.argv[2]
def sse_listing(seconds: float) -> list[dict]:
s = socket.create_connection((HOST, 80), timeout=5)
s.sendall(
b"GET /events HTTP/1.1\r\nHost: %s\r\nAccept: text/event-stream\r\n\r\n"
% HOST.encode()
)
buf = b""
deadline = time.monotonic() + seconds
s.settimeout(1.0)
while time.monotonic() < deadline:
try:
data = s.recv(65536)
except TimeoutError:
continue
if not data:
break
buf += data
s.close()
head, _, body = buf.partition(b"\r\n\r\n")
if b"chunked" in head.lower():
out = b""
while True:
i = body.find(b"\r\n")
if i < 0:
break
size = int(body[:i].split(b";")[0], 16)
out += body[i + 2 : i + 2 + size]
body = body[i + 2 + size + 2 :]
if size == 0:
break
body = out
rows = []
for block in body.decode(errors="replace").split("\n\n"):
ev, data = None, None
for line in block.split("\n"):
line = line.rstrip("\r")
if line.startswith("event:"):
ev = line[6:].strip()
elif line.startswith("data:"):
data = line[5:].strip()
if ev in ("state", "state_detail_all") and data:
try:
obj = json.loads(data)
except ValueError:
rows.append({"event": ev, "invalid": data})
continue
# bare state updates that land inside the window carry no domain; only the listing rows are kept
if "domain" in obj:
rows.append({"event": ev, **obj})
return rows
def get_json(url: str) -> dict:
"""One retry: the ESP8266 async server occasionally leaves a request unanswered."""
for attempt in (1, 2):
try:
with urllib.request.urlopen(url, timeout=5) as resp:
return json.loads(resp.read())
except TimeoutError:
if attempt == 2:
raise
print(f"retrying {url}", flush=True)
return {}
rows = sse_listing(6)
ids = sorted({r["id"] for r in rows if "id" in r})
rest = []
for ident in ids:
domain, _, obj = ident.partition("/")
url = f"http://{HOST}/{domain}/{urllib.parse.quote(obj)}?detail=all"
try:
rest.append({"url": url.replace(HOST, "HOST"), **get_json(url)})
except Exception as e: # noqa: BLE001
rest.append({"url": url.replace(HOST, "HOST"), "error": str(e)})
time.sleep(0.3)
with pathlib.Path(OUT).open("w", encoding="utf-8") as f:
f.writelines(
json.dumps(r, sort_keys=True) + "\n"
for r in sorted(rows, key=lambda r: (r.get("id", ""), r["event"]))
)
f.writelines(json.dumps(r, sort_keys=True) + "\n" for r in rest)
print(f"{len(rows)} sse rows, {len(ids)} ids, {len(rest)} rest rows")
@@ -24,8 +24,10 @@ if [ "$RESTART" = restart ]; then
pid=$(cat "$WORK/mosquitto.pid" 2>/dev/null); [ -n "$pid" ] || { echo "no mosquitto.pid in $WORK, cannot restart the broker"; exit 1; }
kill "$pid" || { echo "broker PID $pid is not running, nothing to restart"; exit 1; }; sleep 8
nc -z -w 3 "$B" 1883 && { echo "the old broker still answers on 1883 after the kill"; exit 1; }
(cd "$WORK" && mosquitto -c mosquitto-ws.conf > mosquitto.out 2>&1 & echo $! > "$WORK/mosquitto.pid"); sleep 25
for port in 1883 9001 9002; do nc -z -w 3 "$B" "$port" || { echo "broker port $port not listening after the restart"; exit 1; }; done
# exec so the PID is the broker's own and no shell stays behind holding the caller's output pipe open
(cd "$WORK" && exec mosquitto -c mosquitto-ws.conf > mosquitto.out 2>&1 < /dev/null) &
echo $! > "$WORK/mosquitto.pid"; sleep 25
for port in $(awk '/^listener/ {print $2}' "$WORK/mosquitto-ws.conf"); do nc -z -w 3 "$B" "$port" || { echo "broker port $port not listening after the restart"; exit 1; }; done
tail -n +$((n1+1)) "$LOG" | grep -a -q "MQTT_EVENT_CONNECTED\|\[mqtt:[0-9]*\]: Connected" || { echo "the device did not reconnect after the broker restart"; exit 1; }
else
echo "=== $N: no broker restart (pass 'restart' as the 7th argument for a local broker)"
+24
View File
@@ -0,0 +1,24 @@
#!/bin/sh
# cli_tls_check.sh TREE [neg] YAML... : run `esphome clean-mqtt` from the checkout TREE for each config, which goes
# through the same TLS setup in esphome/mqtt.py as `esphome logs` over MQTT, without needing a board. clean-mqtt never
# exits on its own, so it runs under a 25 s timeout: status 124 after "Connected to MQTT broker!" means the CLI
# connected. With neg every config must instead fail with CERTIFICATE_VERIFY_FAILED and never connect, so a negative
# that fails for another reason (bad YAML, broker down) is reported as a failure too. A relative YAML path is taken
# from the working directory, where the cleanmqtt-NAME.log outputs also go. Exit 1 when any config missed its result.
TREE=$1; shift; PY=${PYTHON:-python3}; NEG=0
[ "$1" = neg ] && { NEG=1; shift; }
[ -d "$TREE/esphome" ] && [ -n "$1" ] || { echo "usage: cli_tls_check.sh TREE [neg] YAML..."; exit 2; }
bad=0
for y in "$@"; do
case $y in /*) ;; *) y=$PWD/$y;; esac
n=$(basename "$y" .yaml); log=$PWD/cleanmqtt-$n.log
(cd "$TREE" && PYTHONUNBUFFERED=1 timeout 25 $PY -m esphome clean-mqtt "$y" > "$log" 2>&1); rc=$?
if [ "$NEG" = 0 ] && [ "$rc" = 124 ] && grep -q "Connected to MQTT broker" "$log"; then
echo "$n: connected"
elif [ "$NEG" = 1 ] && grep -q "CERTIFICATE_VERIFY_FAILED" "$log" && ! grep -q "Connected to MQTT broker" "$log"; then
echo "$n: rejected (CERTIFICATE_VERIFY_FAILED)"
else
echo "$n: FAILED (status $rc): $(grep -a -m1 -i 'cannot connect\|error' "$log" | cut -c1-160)"; bad=$((bad+1))
fi
done
[ "$bad" = 0 ]
@@ -0,0 +1,53 @@
#!/bin/sh
# flash_and_drive.sh TREE YAML PORT KEY BROKER_HOST MODE [SUB_PORT] : flash YAML from the checkout TREE over the serial
# PORT, capture the serial log (cap-NAME.txt in the working directory), wait for the first MQTT connect or TLS error,
# then drive the device with cases.sh (KEY as for cases.sh, - for a plaintext API). MODE local runs cases.sh with a
# broker restart (the working directory must hold mosquitto-ws.conf and mosquitto.pid), public runs it without a
# restart, neg only watches for 100 s (a build that must never connect). SUB_PORT is the plain listener cases.sh
# subscribes on (default 1883). Ends with connect, disconnect, handshake error and crash counts, the config dump's
# TLS line, the probe heap lines and the broker listener each connection used. Exit 1 when the capture did not start,
# the device reached no MQTT event within 90 s (local and public), it crashed, or the mode's own check failed.
TREE=$1; YAML=$2; PORT=$3; KEY=$4; B=$5; MODE=$6; SP=${7:-1883}
case $YAML in /*) ;; *) YAML=$PWD/$YAML;; esac
HERE=$(cd "$(dirname "$0")" && pwd); PY=${PYTHON:-python3}; N=$(basename "$YAML" .yaml); CAP=$PWD/cap-$N.txt; ULOG=$PWD/upload-$N.log
[ -d "$TREE/esphome" ] && [ -e "$PORT" ] && [ -n "$KEY" ] && [ -n "$B" ] || { echo "usage: flash_and_drive.sh TREE YAML PORT KEY BROKER_HOST local|public|neg [SUB_PORT]"; exit 2; }
case $MODE in local|public|neg) ;; *) echo "MODE must be local, public or neg"; exit 2;; esac
pkill -f "[s]erial_capture.py $PORT "; sleep 1
echo "=== $N: flash ($(date +%T))"
(cd "$TREE" && PYTHONUNBUFFERED=1 timeout 300 $PY -m esphome upload "$YAML" --device "$PORT" > "$ULOG" 2>&1) || { echo "upload failed"; tail -5 "$ULOG"; exit 1; }
SECS=200; [ "$MODE" = neg ] && SECS=100
# a stale capture from an earlier run must not satisfy the wait below
rm -f "$CAP"
$PY "$HERE/../serial_capture.py" "$PORT" $SECS "$CAP" > "$PWD/cap-$N.stderr" 2>&1 &
cap_pid=$!
i=0; until grep -a -q "MQTT_EVENT_CONNECTED\|\[mqtt:[0-9]*\]: Connected\|mbedtls_ssl_handshake returned\|Failed to verify" "$CAP" 2>/dev/null || [ $i -ge 45 ]; do sleep 2; i=$((i+1)); done
kill -0 $cap_pid 2>/dev/null && [ -f "$CAP" ] || { echo "serial capture is not running on $PORT"; tail -3 "$PWD/cap-$N.stderr"; exit 1; }
DEV=$(grep -a -o 'IP Address: [0-9.]*' "$CAP" | head -1 | awk '{print $3}')
if [ $i -ge 45 ] || [ -z "$DEV" ]; then
echo "=== $N: no MQTT event or no IP within 90 s ($(date +%T))"
[ "$MODE" = neg ] || { pkill -f "[s]erial_capture.py $PORT "; exit 1; }
else
echo "=== $N: first MQTT event after $((i*2)) s, device $DEV ($(date +%T))"
fi
grep -a 'ESPHome version\|\]: Transport\|\]: TLS:' "$CAP" | sed 's/\x1b\[[0-9;]*m//g' | cut -c1-120
rc=0
case $MODE in
local) PYTHON=$PY sh "$HERE/cases.sh" "$N" "$KEY" "$B" "$SP" "$CAP" "$DEV" restart; rc=$?;;
public) PYTHON=$PY sh "$HERE/cases.sh" "$N" "$KEY" "$B" "$SP" "$CAP" "$DEV"; rc=$?;;
neg) sleep 70;;
esac
wait $cap_pid
strip() { sed 's/\x1b\[[0-9;]*m//g'; }
# count the backend's own events so the result does not depend on on_connect/on_disconnect log lines in the config
connects=$(grep -a -c 'MQTT_EVENT_CONNECTED' "$CAP"); errors=$(grep -a -c 'mbedtls_ssl_handshake returned\|Failed to verify certificate' "$CAP")
crashes=$(grep -a -c 'Guru\|abort()\|Backtrace' "$CAP")
echo "=== $N: connects $connects, disconnects $(grep -a -c 'MQTT_EVENT_DISCONNECTED' "$CAP"), handshake errors $errors, crashes $crashes"
grep -a 'mbedtls_ssl_handshake returned\|Failed to verify\|esp-tls' "$CAP" | strip | sed 's/^\[[^]]*\]//' | sort | uniq -c | sort -rn | head -4 | cut -c1-150
grep -a '\[probe:' "$CAP" | strip | sed 's/.*\[probe:[0-9]*\]: //' | sed -n '1p;$p'
[ -f "$PWD/mosquitto.log" ] && [ -n "$DEV" ] && echo "broker listeners used by $DEV: $(grep "New connection from $DEV" "$PWD/mosquitto.log" | sed 's/.*on port //' | sort | uniq -c | tr '\n' ';')"
[ "$crashes" = 0 ] || { echo "device crashed $crashes time(s)"; exit 1; }
if [ "$MODE" = neg ]; then
[ "$connects" = 0 ] && [ "$errors" -gt 0 ] || { echo "negative case: expected no connect and a handshake error"; exit 1; }
else
[ "$rc" = 0 ] || { echo "cases.sh failed with status $rc"; exit 1; }
fi
@@ -1,13 +1,21 @@
#!/bin/sh
# make_test_ca.sh BROKER_IP : a throwaway CA and a server certificate for the broker address (30 days), written into
# the working directory; run it in the scratch directory where a copy of mosquitto-ws.conf lives. The device
# config takes ca.crt as certificate_authority (skip_cert_cn_check: true, the name check does not match an address);
# other-ca.crt is a second CA for the negative case.
# make_test_ca.sh BROKER_IP : a throwaway CA, a server certificate for the broker address and a client certificate
# (30 days), written into the working directory; run it in the scratch directory where a copy of mosquitto-ws.conf
# lives. The device config takes ca.crt as certificate_authority (skip_cert_cn_check: true, the name check does not
# match an address) and client.crt/client.key as client_certificate/client_certificate_key for the listener that
# requires one; other-ca.crt is a second CA for the negative case. The CA carries basicConstraints and keyUsage
# because Python's default SSL context (esphome logs, esphome clean-mqtt) rejects a CA without them.
set -e
IP=$1
openssl req -x509 -newkey rsa:2048 -nodes -keyout ca.key -out ca.crt -days 30 -subj "/CN=hwtest-ca"
[ -n "$IP" ] || { echo "usage: make_test_ca.sh BROKER_IP"; exit 2; }
openssl req -x509 -newkey rsa:2048 -nodes -keyout ca.key -out ca.crt -days 30 -subj "/CN=hwtest-ca" \
-addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=hwtest-broker"
printf "subjectAltName=IP:%s\nextendedKeyUsage=serverAuth\n" "$IP" > san.ext
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 30 -extfile san.ext
openssl req -x509 -newkey rsa:2048 -nodes -keyout other-ca.key -out other-ca.crt -days 30 -subj "/CN=other-ca"
openssl verify -CAfile ca.crt server.crt
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj "/CN=hwtest-client"
printf "extendedKeyUsage=clientAuth\n" > client.ext
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 30 -extfile client.ext
openssl req -x509 -newkey rsa:2048 -nodes -keyout other-ca.key -out other-ca.crt -days 30 -subj "/CN=other-ca" \
-addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"
openssl verify -CAfile ca.crt server.crt client.crt
@@ -1,8 +1,20 @@
# Copy next to the certificates in the scratch directory and start it there with
# `mosquitto -c mosquitto-ws.conf & echo $! > mosquitto.pid` (cases.sh restarts that PID): plain MQTT, MQTT over WebSocket, and MQTT over WebSocket with TLS (server.crt and
# server.key from make_test_ca.sh in the same directory). log_type all gives the listener port per connection.
# `mosquitto -c mosquitto-ws.conf & echo $! > mosquitto.pid` (cases.sh restarts that PID): plain MQTT, MQTT over TLS,
# MQTT over TLS that requires a client certificate, MQTT over WebSocket, and MQTT over WebSocket with TLS
# (server.crt, server.key, ca.crt from make_test_ca.sh in the same directory). log_type all gives the listener port
# per connection.
listener 1883
protocol mqtt
listener 8883
protocol mqtt
certfile server.crt
keyfile server.key
listener 8884
protocol mqtt
certfile server.crt
keyfile server.key
cafile ca.crt
require_certificate true
listener 9001
protocol websockets
listener 9002
@@ -0,0 +1,40 @@
"""Compare the listener log (JSON lines from udp_listen.py) against the udp-write-dut.yaml payload sequence.
usage: check.py LISTEN_JSONL ECHO_HEX (ECHO_HEX is the datagram sent to the device for the echo case)
"""
import json
import pathlib
import sys
with pathlib.Path(sys.argv[1]).open(encoding="utf-8") as f:
log = [json.loads(line) for line in f if line.strip()]
echo_in = bytes.fromhex(sys.argv[2])
small = bytes([0xAA, 0x55, 0x01, 0x02])
expected = [
("small 1/2", small),
("small 2/2", small),
("simple", bytes([1, 2, 3])),
("text", b"hello udp"),
("empty", b""),
("stack128", bytes((0x10 + i) & 0xFF for i in range(128))),
("heap129", bytes((0x20 + i) & 0xFF for i in range(129))),
("heap600", bytes((0x30 + i) & 0xFF for i in range(600))),
("lambda300", bytes((i * 7) & 0xFF for i in range(300))),
("echo", echo_in[::-1]),
]
got = [bytes.fromhex(e["hex"]) for e in log]
ok = 0
for i, (name, want) in enumerate(expected):
have = got[i] if i < len(got) else None
res = (
"OK"
if have == want
else f"MISMATCH got {None if have is None else have[:16].hex() + '... len ' + str(len(have))}"
)
ok += res == "OK"
print(f"{name:10s} {len(want):4d} B {res}")
print(
f"{ok}/{len(expected)} payloads byte-exact, {len(got)} datagrams received, sources {sorted({e['src'] for e in log})}"
)
sys.exit(0 if ok == len(expected) and len(got) == len(expected) else 1)
@@ -0,0 +1,32 @@
"""Log every datagram on PORT for SECONDS as one JSON line: time, source, length, hex payload."""
import json
import pathlib
import socket
import sys
import time
port, secs, out = int(sys.argv[1]), float(sys.argv[2]), sys.argv[3]
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("", port))
s.settimeout(1.0)
end = time.monotonic() + secs
with pathlib.Path(out).open("w", encoding="utf-8") as f:
while time.monotonic() < end:
try:
data, (ip, sport) = s.recvfrom(65535)
except TimeoutError:
continue
f.write(
json.dumps(
{
"t": time.strftime("%H:%M:%S"),
"src": ip,
"len": len(data),
"hex": data.hex(),
}
)
+ "\n"
)
f.flush()
+22
View File
@@ -0,0 +1,22 @@
#!/bin/sh
# write_cases.sh DEVICE_IP KEY [PORT] : drive a device built from templates/udp-write-dut.yaml. Records every datagram
# the device sends to PORT (the udp component's port, default 18511) with udp_listen.py in the working directory,
# presses the eight payload buttons over the API two seconds apart (KEY as for api_button.py, - for a plaintext API),
# sends one 16 byte unicast datagram to the device for the echo case, then compares the recorded datagrams with
# check.py. The recorder runs until the driver stops it. Exit 1 when the recorder did not start or a payload is
# missing or differs; listen.jsonl stays in the working directory.
HERE=$(cd "$(dirname "$0")" && pwd); PY=${PYTHON:-python3}; DEV=$1; KEY=$2; PORT=${3:-18511}
[ -n "$DEV" ] && [ -n "$KEY" ] || { echo "usage: write_cases.sh DEVICE_IP KEY [PORT]"; exit 2; }
ECHO=0102030405060708090a0b0c0d0e0f10
rm -f "$PWD/listen.jsonl"
$PY "$HERE/udp_listen.py" "$PORT" 600 "$PWD/listen.jsonl" &
lst=$!
sleep 2
kill -0 $lst 2>/dev/null || { echo "udp_listen.py is not running on port $PORT"; exit 1; }
for b in Small Simple Text Empty Stack128 Heap129 Heap600 Lambda300; do
$PY "$HERE/../api_button.py" "$DEV" "$KEY" press "$b" > /dev/null || echo "press $b failed"; sleep 2
done
$PY -c "import socket; socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(bytes.fromhex('$ECHO'), ('$DEV', $PORT))"
sleep 5
kill $lst 2>/dev/null; wait $lst 2>/dev/null
$PY "$HERE/check.py" "$PWD/listen.jsonl" "$ECHO"
@@ -0,0 +1,148 @@
# Entity icon and device class readback (esphome#21111): the per-run file supplies name and broker_ip through substitutions and includes this file as a package. Every readback path is covered: API listing, MQTT discovery, web_server JSON and dump_config. See reference/recipes/web_server.md.
esp8266:
board: d1_mini
logger:
level: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
api:
encryption:
key: !secret api_key
reboot_timeout: 0s
ota:
- platform: esphome
web_server:
port: 80
mqtt:
broker: ${broker_ip}
reboot_timeout: 0s
interval:
- interval: 10s
then:
- lambda: |-
ESP_LOGI("probe", "free heap %u, max block %u", (unsigned) ESP.getFreeHeap(), (unsigned) ESP.getMaxFreeBlockSize());
esphome:
name: ${name}
sensor:
- platform: template
name: Temp
id: temp
device_class: temperature
unit_of_measurement: "°C"
icon: mdi:thermometer
accuracy_decimals: 1
lambda: return 21.5;
update_interval: 30s
- platform: template
name: Long Icon
id: long_icon
icon: mdi:this-icon-name-is-exactly-sixty-three-characters-long-abcde
device_class: humidity
unit_of_measurement: "%"
lambda: return 40.0;
update_interval: 30s
- platform: template
name: Plain
id: plain
lambda: return 1.0;
update_interval: 30s
- platform: template
name: Hidden
id: hidden
internal: true
icon: mdi:eye-off
device_class: power
lambda: return 2.0;
update_interval: 30s
binary_sensor:
- platform: template
name: Motion
id: motion
device_class: motion
icon: mdi:motion-sensor
lambda: return false;
switch:
- platform: template
name: Relay
id: relay
device_class: outlet
icon: mdi:power-plug
optimistic: true
button:
- platform: template
name: Reboot
id: reboot_btn
device_class: restart
icon: mdi:restart
on_press:
- logger.log: "Reboot pressed"
text_sensor:
- platform: template
name: Version
id: version
device_class: timestamp
icon: mdi:tag
lambda: return {"2026-10-21T00:00:00+00:00"};
update_interval: 30s
number:
- platform: template
name: Level
id: level
device_class: battery
icon: mdi:knob
unit_of_measurement: "%"
min_value: 0
max_value: 100
step: 1
optimistic: true
initial_value: 50
select:
- platform: template
name: Mode
id: mode
icon: mdi:format-list-bulleted
options: [a, b, c]
optimistic: true
initial_option: a
event:
- platform: template
name: Doorbell
id: doorbell
device_class: doorbell
icon: mdi:doorbell
event_types: [ring, knock]
cover:
- platform: template
name: Garage
id: garage
device_class: garage
icon: mdi:garage
optimistic: true
text:
- platform: template
name: Secret Note
id: note
mode: password
icon: mdi:form-textbox-password
optimistic: true
initial_value: "x"
@@ -0,0 +1,99 @@
# MQTT TLS trust-source test (#14318, needs that PR's tree for tls and verify_ssl): one build per trust source, with
# the name and the mqtt block edited per file (see reference/recipes/mqtt.md). Secrets: broker_ip (the local broker
# from make_test_ca.sh), mqtt_ca, mqtt_client_cert and mqtt_client_key as block scalars from the same run.
esp32:
board: esp32dev
framework:
type: esp-idf
logger:
level: VERBOSE
logs:
wifi: DEBUG
api: DEBUG
api.connection: DEBUG
scheduler: DEBUG
component: DEBUG
sensor: DEBUG
esp32: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
api:
encryption:
key: !secret api_key
reboot_timeout: 0s
ota:
- platform: esphome
interval:
- interval: 10s
then:
- lambda: |-
ESP_LOGI("probe", "mqtt connected %d, internal free %u, largest block %u", id(mq).is_connected(),
(unsigned) heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
(unsigned) heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL));
sensor:
- platform: template
name: Counter
update_interval: 2s
accuracy_decimals: 0
lambda: |-
static uint32_t n = 0;
return n++;
switch:
- platform: template
name: Relay
id: relay
optimistic: true
on_turn_on:
- logger.log: "Relay ON"
on_turn_off:
- logger.log: "Relay OFF"
button:
- platform: template
name: Publish big
on_press:
- mqtt.publish:
topic: ${name}/big
payload: !lambda |-
return std::string(3000, 'q');
substitutions:
name: mqtt-dut
esphome:
name: ${name}
mqtt:
id: mq
broker: !secret broker_ip # test.mosquitto.org for the bundle run
# No port: it must resolve to 1883 without TLS options and to 8883 with them. Spell it out only for the
# client-certificate listener (8884), wss (9002) and the public bundle broker (8886).
# The next two lines are the own-CA build. Remove both for the broker-only build (skip_cert_cn_check alone turns
# TLS on), replace both with verify_ssl: false for the unverified build (the flag is rejected next to it), or with
# tls: true for the bundle builds (public broker, and the local one as the negative).
skip_cert_cn_check: true # with the local CA: the certificate names an address
certificate_authority: !secret mqtt_ca
# client_certificate: !secret mqtt_client_cert # with the CA, port 8884
# client_certificate_key: !secret mqtt_client_key
# transport: wss # with the CA, port 9002
reboot_timeout: 0s
discovery: false
on_message:
- topic: ${name}/cmd
then:
- logger.log:
format: "cmd payload: %s"
args: ["x.c_str()"]
on_connect:
- logger.log: "MQTT on_connect"
on_disconnect:
- logger.log: "MQTT on_disconnect"
@@ -0,0 +1,93 @@
# udp.write payload shapes (#21263): every shape the action takes behind a template button, plus an on_receive that
# replies with the received bytes reversed through a lambda. Per run file: substitutions name and listener_ip (the test
# host that runs scripts/udp/udp_listen.py), then packages: common: !include this file. Drive it with
# scripts/udp/write_cases.sh DEVICE_IP KEY, which presses the buttons, sends the echo datagram and checks every payload.
esp8266:
board: d1_mini
logger:
level: VERBOSE
logs:
wifi: DEBUG
api: DEBUG
api.connection: DEBUG
scheduler: DEBUG
component: DEBUG
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
api:
encryption:
key: !secret api_key
reboot_timeout: 0s
ota:
- platform: esphome
interval:
- interval: 10s
then:
- lambda: |-
ESP_LOGI("probe", "free heap %u, max block %u", (unsigned) ESP.getFreeHeap(), (unsigned) ESP.getMaxFreeBlockSize());
esphome:
name: ${name}
udp:
id: u
addresses:
- ${listener_ip}
on_receive:
- lambda: ESP_LOGI("echo", "received %u bytes", (unsigned) data.size());
- udp.write: !lambda |-
std::vector<uint8_t> v(data.rbegin(), data.rend());
return v;
button:
- platform: template
name: Small
on_press:
- logger.log: "case small"
- udp.write: [0xAA, 0x55, 0x01, 0x02]
- udp.write: [0xAA, 0x55, 0x01, 0x02]
- platform: template
name: Simple
on_press:
- logger.log: "case simple"
- udp.write: [1, 2, 3]
- platform: template
name: Text
on_press:
- logger.log: "case text"
- udp.write: "hello udp"
- platform: template
name: Empty
on_press:
- logger.log: "case empty"
- udp.write: []
- platform: template
name: Stack128
on_press:
- logger.log: "case stack128"
- udp.write: [0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F]
- platform: template
name: Heap129
on_press:
- logger.log: "case heap129"
- udp.write: [0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0]
- platform: template
name: Heap600
on_press:
- logger.log: "case heap600"
- udp.write: [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87]
- platform: template
name: Lambda300
on_press:
- logger.log: "case lambda300"
- udp.write: !lambda |-
std::vector<uint8_t> v(300);
for (size_t i = 0; i < v.size(); i++) v[i] = (uint8_t) (i * 7);
return v;
+2
View File
@@ -2,4 +2,6 @@
omit =
esphome/components/*
esphome/analyze_memory/*
esphome/espidf/get_idf_tool_paths.py
esphome/espidf/get_idf_version.py
tests/integration/*
@@ -21,6 +21,7 @@ module.exports = {
'github-actions',
'by-code-owner',
'has-tests',
'api.proto',
'needs-tests',
'needs-docs',
'needs-developer-docs',
@@ -272,6 +272,18 @@ async function detectTests(changedFiles) {
return labels;
}
// Strategy: API protocol change detection
// aioesphomeapi carries copies of both files, so every change here needs a sync there
const API_PROTO_FILES = ['esphome/components/api/api.proto', 'esphome/components/api/api_options.proto'];
async function detectApiProto(changedFiles) {
const labels = new Set();
if (changedFiles.some(file => API_PROTO_FILES.includes(file))) {
labels.add('api.proto');
}
return labels;
}
// Strategy: PR Template Checkbox detection
async function detectPRTemplateCheckboxes(context) {
const labels = new Set();
@@ -460,6 +472,7 @@ module.exports = {
detectGitHubActionsChanges,
detectCodeOwner,
detectTests,
detectApiProto,
detectPRTemplateCheckboxes,
detectDeprecatedComponents,
detectMaintainerAccess,
+4
View File
@@ -10,6 +10,7 @@ const {
detectGitHubActionsChanges,
detectCodeOwner,
detectTests,
detectApiProto,
detectPRTemplateCheckboxes,
detectDeprecatedComponents,
detectMaintainerAccess,
@@ -114,6 +115,7 @@ module.exports = async ({ github, context }) => {
actionsLabels,
codeOwnerLabels,
testLabels,
apiProtoLabels,
checkboxLabels,
deprecatedResult,
maintainerAccess
@@ -128,6 +130,7 @@ module.exports = async ({ github, context }) => {
detectGitHubActionsChanges(changedFiles),
detectCodeOwner(github, context, changedFiles),
detectTests(changedFiles),
detectApiProto(changedFiles),
detectPRTemplateCheckboxes(context),
detectDeprecatedComponents(github, context, changedFiles),
detectMaintainerAccess(context)
@@ -156,6 +159,7 @@ module.exports = async ({ github, context }) => {
...actionsLabels,
...codeOwnerLabels,
...testLabels,
...apiProtoLabels,
...checkboxLabels,
...deprecatedLabels
]);
@@ -1,6 +1,7 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const {
detectApiProto,
detectMergeBranch,
detectNewPlatforms,
detectNewComponents,
@@ -375,6 +376,27 @@ describe('detectRequirements', () => {
});
});
// ---------------------------------------------------------------------------
// detectApiProto
// ---------------------------------------------------------------------------
describe('detectApiProto', () => {
it('labels a PR that changes api.proto', async () => {
const labels = await detectApiProto(['esphome/components/api/api.proto', 'esphome/components/api/api_pb2.cpp']);
assert.deepEqual(Array.from(labels), ['api.proto']);
});
it('labels a PR that changes only api_options.proto', async () => {
const labels = await detectApiProto(['esphome/components/api/api_options.proto']);
assert.deepEqual(Array.from(labels), ['api.proto']);
});
it('ignores the generated protocol files and other components', async () => {
const labels = await detectApiProto(['esphome/components/api/api_pb2.cpp', 'esphome/components/uart/api.proto']);
assert.equal(labels.size, 0);
});
});
// ---------------------------------------------------------------------------
// MANAGED_LABELS
// ---------------------------------------------------------------------------
@@ -387,6 +409,10 @@ describe('MANAGED_LABELS', () => {
it('includes needs-developer-docs so the workflow syncs it', () => {
assert.ok(MANAGED_LABELS.includes('needs-developer-docs'));
});
it('includes api.proto so the workflow removes it when the file drops out of the diff', () => {
assert.ok(MANAGED_LABELS.includes('api.proto'));
});
});
// ---------------------------------------------------------------------------
+3 -6
View File
@@ -205,9 +205,8 @@ file does, and it is the authority when they disagree. The most useful starting
for a table of structs copy the whole entry out and return the copy, never a pointer into flash.
On other platforms they are a plain `memcpy` and dereference, so no `#ifdef` is needed. Declare log tags with
`ESPHOME_LOG_TAG(TAG, "name")`, pass status text as `LOG_STR`, e.g.
`this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL))`. An action that only forwards a byte payload is
registered with `automation.ApplyBytes` (see Actions below), which keeps a constant payload in flash;
`TEMPLATABLE_BYTES` is for a `play()` that does more with the bytes.
`this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL))`, and give an action whose payload is a byte array
a `TEMPLATABLE_BYTES` field so a static code stays in flash.
* **Fixed sets of names** (status words, model names): a `PROGMEM_STRING_TABLE` (`esphome/core/progmem.h`),
logged with `get_log_str` and `LOG_STR_ARG`, copied out with `ESPHOME_strncpy_P` before `publish_state`.
A `dump_config` helper that picks a name returns `const LogString *` from `LOG_STR(...)`.
@@ -605,9 +604,7 @@ file does, and it is the authority when they disagree. The most useful starting
)
```
The `ApplyField`, `ApplyCall` and `register_apply_action` docstrings in `esphome/automation.py` cover
the rest; `cover.control` and `cover.template.publish` are in-tree examples. An action whose input is a
byte payload passes `automation.ApplyBytes(CONF_DATA, "send({})")` in the same call; a constant payload
stays in flash and a lambda's vector is forwarded as data and size. `TEMPLATABLE_VALUE` with
the rest; `cover.control` and `cover.template.publish` are in-tree examples. `TEMPLATABLE_VALUE` with
`cg.templatable` stays for actions whose `play()` has real logic beyond forwarding values.
* **Conditions:**
+1
View File
@@ -695,6 +695,7 @@ esphome/components/usb_uart/* @clydebarrow
esphome/components/valve/* @esphome/core
esphome/components/vbus/* @ssieb
esphome/components/veml3235/* @kbx81
esphome/components/veml6040/* @aalaei
esphome/components/veml7700/* @latonita
esphome/components/version/* @esphome/core
esphome/components/vevor_dtx/* @Bofr5555
+3
View File
@@ -11,6 +11,9 @@ coverage:
ignore:
- "esphome/components/**/*"
- "esphome/analyze_memory/**/*"
# Run as standalone scripts under the ESP-IDF Python, never imported by pytest
- "esphome/espidf/get_idf_tool_paths.py"
- "esphome/espidf/get_idf_version.py"
- "tests/integration/**/*"
comment:
+1 -1
View File
@@ -22,7 +22,7 @@ RUN \
-r /requirements.txt
# Install the ESPHome Device Builder dashboard.
RUN uv pip install --no-cache-dir esphome-device-builder==1.25.0
RUN uv pip install --no-cache-dir esphome-device-builder==1.26.0
RUN \
platformio settings set enable_telemetry No \
+14 -107
View File
@@ -59,15 +59,10 @@ async def templatable_bytes(
if cg.is_template(value):
fn = await cg.templatable(value, args, cg.std_vector.template(cg.uint8))
cg.add(set_template(fn))
elif len(value) > 0xFFFF:
raise EsphomeError(f"Byte payload is {len(value)} bytes; the maximum is 65535")
else:
cg.add(set_static(*_static_bytes(table_name, value)))
def _static_bytes(table_name: str, value: bytes | list[int]) -> tuple[MockObj, int]:
"""The shared PROGMEM table for a constant payload and its length."""
if (size := len(value)) > 0xFFFF:
raise EsphomeError(f"Byte payload is {size} bytes; the maximum is 65535")
return progmem_bytes(table_name, value), size
cg.add(set_static(progmem_bytes(table_name, value), len(value)))
def maybe_simple_id(*validators):
@@ -361,33 +356,6 @@ class ApplyField:
return ApplyCall(target, ((self.conf_key, self.type_, self.const_fn),))
@dataclass(frozen=True)
class ApplyBytes:
"""A byte payload key forwarded as ``target``, whose ``{}`` stands for ``data, len``.
A constant payload is a shared PROGMEM table passed as is; on ESP8266 it is first copied
out, to the stack up to ``stack`` bytes and to the heap beyond, unless ``progmem_target``
names a call that reads flash itself. A lambda's ``std::vector<uint8_t>`` is passed as
its data and size. The template may name the parent as ``{parent}``. An absent key
emits nothing.
"""
conf_key: str | tuple[str, ...]
target: str
stack: int = 64
progmem_target: str | None = None
def __post_init__(self) -> None:
for target in (self.target, self.progmem_target):
if target is None:
continue
fields = [
f for _, f, _, _ in string.Formatter().parse(target) if f is not None
]
if fields.count("") != 1 or any(f not in ("", "parent") for f in fields):
raise ValueError(f"apply bytes target {target!r} needs one {{}}")
def _config_lookup(config: ConfigType, key: str | tuple[str, ...]) -> Any:
if isinstance(key, str):
return config.get(key)
@@ -520,7 +488,7 @@ def _apply_values(config: ConfigType, members: list[tuple[Any, Any, Any]]) -> li
def register_apply_action(
name: str,
schema: cv.Schema,
*fields: ApplyField | ApplyCall | ApplyBytes,
*fields: ApplyField | ApplyCall,
call: str | None = None,
id_key: str = CONF_ID,
) -> None:
@@ -536,7 +504,7 @@ def register_apply_action(
def apply_action_builder(
name: str,
schema: cv.Schema,
*fields: ApplyField | ApplyCall | ApplyBytes,
*fields: ApplyField | ApplyCall,
call: str | None = None,
id_key: str = CONF_ID,
) -> Callable[..., Awaitable[MockObj]]:
@@ -549,20 +517,17 @@ def apply_action_builder(
and ``apply_call.perform()`` is appended.
"""
# An action stores the value, so a std::string constant stays in flash on ESP8266.
statements_spec = [
(
c.target,
_default_std_string(c.members, flash_string),
)
for c in (f if isinstance(f, ApplyCall) else f.call() for f in fields)
]
_check_key_in_schema(name, schema, id_key)
statements_spec: list[ApplyBytes | tuple[str, list[tuple[Any, Any, Any]]]] = []
for f in fields:
if isinstance(f, ApplyBytes):
_check_key_in_schema(name, schema, f.conf_key)
statements_spec.append(f)
continue
c = f if isinstance(f, ApplyCall) else f.call()
members = _default_std_string(c.members, flash_string)
for _, members in statements_spec:
for conf_key, _, _ in members:
_check_key_in_schema(name, schema, conf_key)
statements_spec.append((c.target, members))
# Named like the generated function, so it cannot clash with an SDK symbol
table_name = f"esphome__{name.replace('.', '_')}__bytes"
async def builder(
config: ConfigType,
@@ -574,15 +539,7 @@ def apply_action_builder(
lambda_args = _apply_lambda_args(args)
receiver = "apply_call." if call else f"{parent}->"
statements: list[str] = []
for spec in statements_spec:
if isinstance(spec, ApplyBytes):
statements.extend(
await _render_bytes(
spec, config, receiver, parent, lambda_args, table_name
)
)
continue
target, members = spec
for target, members in statements_spec:
values = _apply_values(config, members)
if not _apply_call_active(members, values):
continue
@@ -603,56 +560,6 @@ def apply_action_builder(
return builder
async def _render_bytes(
spec: ApplyBytes,
config: ConfigType,
receiver: str,
parent: str,
lambda_args: TemplateArgsType,
table_name: str,
) -> list[str]:
"""The statements for one ``ApplyBytes``: what ``TemplatableBytes::visit`` does, inlined."""
value = _config_lookup(config, spec.conf_key)
if value is None:
return []
# The temporary carries the generated-name prefix so a trigger argument cannot shadow it
def send(target: str, data: str) -> str:
return f"{receiver}{target.format(data, parent=parent)};"
if isinstance(value, Lambda):
inner = await cg.process_lambda(
value, lambda_args, return_type=cg.std_vector.template(cg.uint8)
)
return [
"{",
f" const std::vector<uint8_t> esphome__bytes = ({call_lambda(inner)});",
f" {send(spec.target, 'esphome__bytes.data(), esphome__bytes.size()')}",
"}",
]
table, size = _static_bytes(table_name, value)
# Qualified so a trigger argument cannot shadow a reused table; an empty payload is nullptr
args = f"::{table}, {size}" if size else f"{table}, {size}"
if CORE.is_esp8266 and spec.progmem_target is not None:
return [send(spec.progmem_target, args)]
if not CORE.is_esp8266:
return [send(spec.target, args)]
# A PROGMEM table must be read with aligned loads on ESP8266, so copy it out first;
# the length is known here, so the copy is an exact array, on the heap past ``stack``.
# An empty payload still gets a one byte array: the raw lwIP socket rejects a null buffer.
if size <= spec.stack:
buffer, data = f"uint8_t esphome__bytes[{max(size, 1)}];", "esphome__bytes"
else:
buffer, data = (
f"auto esphome__bytes = std::make_unique<uint8_t[]>({size});",
"esphome__bytes.get()",
)
statements = ["{", f" {buffer}"]
if size:
statements.append(f" esphome::progmem_memcpy({data}, {args});")
return [*statements, f" {send(spec.target, f'{data}, {size}')}", "}"]
def _apply_call_active(members: list[tuple[Any, Any, Any]], values: list[Any]) -> bool:
"""An ``ApplyCall`` is emitted unless it has keys and none of them is set."""
return not members or any(value is not None for value in values)
@@ -10,7 +10,7 @@ void AbsoluteHumidityComponent::setup() {
this->temperature_ = state;
this->enable_loop();
});
ESP_LOGD(TAG, " Added callback for temperature '%s'", this->temperature_sensor_->get_name().c_str());
ESP_LOGD(TAG, " Added callback for temperature '%s'", LOG_STR_ARG(this->temperature_sensor_->get_log_name()));
// Get initial value
if (this->temperature_sensor_->has_state()) {
this->temperature_ = this->temperature_sensor_->get_state();
@@ -20,7 +20,7 @@ void AbsoluteHumidityComponent::setup() {
this->humidity_ = state;
this->enable_loop();
});
ESP_LOGD(TAG, " Added callback for relative humidity '%s'", this->humidity_sensor_->get_name().c_str());
ESP_LOGD(TAG, " Added callback for relative humidity '%s'", LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
// Get initial value
if (this->humidity_sensor_->has_state()) {
this->humidity_ = this->humidity_sensor_->get_state();
@@ -49,7 +49,8 @@ void AbsoluteHumidityComponent::dump_config() {
"Sources\n"
" Temperature: '%s'\n"
" Relative Humidity: '%s'",
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
LOG_STR_ARG(this->temperature_sensor_->get_log_name()),
LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
}
void AbsoluteHumidityComponent::loop() {
+1 -1
View File
@@ -66,7 +66,7 @@ template class Aggregator<uint32_t>;
void ADCSensor::update() {
float value_v = this->sample();
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", this->get_name().c_str(), value_v);
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", LOG_STR_ARG(this->get_log_name()), value_v);
this->publish_state(value_v);
}
@@ -13,7 +13,7 @@ float ADS1115Sensor::sample() {
void ADS1115Sensor::update() {
float v = this->sample();
if (!std::isnan(v)) {
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", LOG_STR_ARG(this->get_log_name()), v);
this->publish_state(v);
}
}
@@ -21,7 +21,7 @@ float ADS1118Sensor::sample() {
void ADS1118Sensor::update() {
float v = this->sample();
if (!std::isnan(v)) {
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", LOG_STR_ARG(this->get_log_name()), v);
this->publish_state(v);
}
}
@@ -31,7 +31,7 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) {
this->last_update_ = millis();
if (state != this->current_state_) {
auto prev_state = this->current_state_;
ESP_LOGV(TAG, "'%s' >> %s (was %s)", this->get_name().c_str(),
ESP_LOGV(TAG, "'%s' >> %s (was %s)", LOG_STR_ARG(this->get_log_name()),
LOG_STR_ARG(alarm_control_panel_state_to_string(state)),
LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state)));
this->current_state_ = state;
+16 -13
View File
@@ -30,9 +30,9 @@ void Am43Component::loop() {
auto status =
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
ESP_LOGI(TAG, "[%s] Logging into AM43", LOG_STR_ARG(this->get_log_name()));
if (status) {
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", LOG_STR_ARG(this->get_log_name()), status);
} else {
this->logged_in_ = true;
}
@@ -50,7 +50,7 @@ CoverTraits Am43Component::get_traits() {
void Am43Component::control(const CoverCall &call) {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", LOG_STR_ARG(this->get_log_name()));
return;
}
if (call.get_stop()) {
@@ -59,7 +59,7 @@ void Am43Component::control(const CoverCall &call) {
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", LOG_STR_ARG(this->get_log_name()), status);
}
}
auto opt_pos = call.get_position();
@@ -73,7 +73,8 @@ void Am43Component::control(const CoverCall &call) {
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", LOG_STR_ARG(this->get_log_name()),
status);
}
}
}
@@ -89,9 +90,9 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
if (chr == nullptr) {
if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", LOG_STR_ARG(this->get_log_name()));
} else {
ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", this->get_name().c_str());
ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", LOG_STR_ARG(this->get_log_name()));
}
break;
}
@@ -100,7 +101,8 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
chr->handle);
if (status) {
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", LOG_STR_ARG(this->get_log_name()),
status);
}
break;
}
@@ -126,25 +128,26 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
if (this->decoder_->has_pin_response()) {
if (this->decoder_->pin_ok_) {
ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
ESP_LOGI(TAG, "[%s] AM43 pin accepted.", LOG_STR_ARG(this->get_log_name()));
auto *packet = this->encoder_->get_position_request();
auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
this->char_handle_, packet->length, packet->data,
ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
if (status) {
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", LOG_STR_ARG(this->get_log_name()),
status);
}
} else {
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", LOG_STR_ARG(this->get_log_name()));
}
}
if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_) {
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", LOG_STR_ARG(this->get_log_name()));
}
if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_) {
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", LOG_STR_ARG(this->get_log_name()));
}
break;
}
+5 -3
View File
@@ -67,8 +67,9 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
case ESP_GATTC_SEARCH_CMPL_EVT: {
auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
if (chr == nullptr) {
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", LOG_STR_ARG(this->get_log_name()));
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.",
LOG_STR_ARG(this->get_log_name()));
break;
}
this->char_handle_ = chr->handle;
@@ -76,7 +77,8 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
chr->handle);
if (status) {
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", LOG_STR_ARG(this->get_log_name()),
status);
}
break;
}
+70 -62
View File
@@ -227,11 +227,17 @@ message AreaInfo {
string name = 2 [(max_data_length) = 120, (force) = true];
}
enum DeviceRelation {
DEVICE_RELATION_VIA = 0;
DEVICE_RELATION_CHILD = 1;
}
message DeviceInfo {
uint32 device_id = 1;
// max_data_length matches core/config.FRIENDLY_NAME_MAX_LEN via DEVICE_SCHEMA
string name = 2 [(max_data_length) = 120, (force) = true];
uint32 area_id = 3;
DeviceRelation relation = 4;
}
enum SerialProxyPortType {
@@ -555,13 +561,13 @@ message ListEntitiesBinarySensorResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string device_class = 5 [(max_data_length) = 47];
string device_class = 5 [(max_data_length) = 47, (progmem) = true];
bool is_status_binary_sensor = 6;
bool disabled_by_default = 7;
string icon = 8 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 8 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
EntityCategory entity_category = 9;
uint32 device_id = 10 [(field_ifdef) = "USE_DEVICES"];
}
@@ -589,18 +595,19 @@ message ListEntitiesCoverResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
bool assumed_state = 5;
bool supports_position = 6;
bool supports_tilt = 7;
string device_class = 8 [(max_data_length) = 47];
string device_class = 8 [(max_data_length) = 47, (progmem) = true];
bool disabled_by_default = 9;
string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
EntityCategory entity_category = 11;
bool supports_stop = 12;
uint32 device_id = 13 [(field_ifdef) = "USE_DEVICES"];
bool supports_stop_tilt = 14;
}
// Deprecated in API version 1.1
@@ -662,6 +669,7 @@ message CoverCommandRequest {
float tilt = 7;
bool stop = 8;
uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"];
bool stop_tilt = 10;
}
// ==================== FAN ====================
@@ -673,7 +681,7 @@ message ListEntitiesFanResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
bool supports_oscillation = 5;
@@ -681,7 +689,7 @@ message ListEntitiesFanResponse {
bool supports_direction = 7;
int32 supported_speed_count = 8;
bool disabled_by_default = 9;
string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
EntityCategory entity_category = 11;
repeated string supported_preset_modes = 12 [(container_pointer_no_template) = "ConstVector<const char *, true>"];
uint32 device_id = 13 [(field_ifdef) = "USE_DEVICES"];
@@ -761,7 +769,7 @@ message ListEntitiesLightResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
repeated ColorMode supported_color_modes = 12 [(container_pointer_no_template) = "light::ColorModeMask"];
@@ -778,7 +786,7 @@ message ListEntitiesLightResponse {
float max_mireds = 10;
repeated string effects = 11 [(container_pointer_no_template) = "light::LightEffectNames"];
bool disabled_by_default = 13;
string icon = 14 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 14 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
EntityCategory entity_category = 15;
uint32 device_id = 16 [(field_ifdef) = "USE_DEVICES"];
}
@@ -866,14 +874,14 @@ message ListEntitiesSensorResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
string unit_of_measurement = 6 [(max_data_length) = 63];
int32 accuracy_decimals = 7;
bool force_update = 8;
string device_class = 9 [(max_data_length) = 47];
string device_class = 9 [(max_data_length) = 47, (progmem) = true];
SensorStateClass state_class = 10;
// Last reset type removed in 2021.9.0
// Deprecated in API version 1.5
@@ -907,14 +915,14 @@ message ListEntitiesSwitchResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool assumed_state = 6;
bool disabled_by_default = 7;
EntityCategory entity_category = 8;
string device_class = 9 [(max_data_length) = 47];
string device_class = 9 [(max_data_length) = 47, (progmem) = true];
uint32 device_id = 10 [(field_ifdef) = "USE_DEVICES"];
}
message SwitchStateResponse {
@@ -952,13 +960,13 @@ message ListEntitiesTextSensorResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8 [(max_data_length) = 47];
string device_class = 8 [(max_data_length) = 47, (progmem) = true];
uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"];
}
message TextSensorStateResponse {
@@ -1223,10 +1231,10 @@ message ListEntitiesCameraResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
bool disabled_by_default = 5;
string icon = 6 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 6 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
EntityCategory entity_category = 7;
uint32 device_id = 8 [(field_ifdef) = "USE_DEVICES"];
}
@@ -1315,7 +1323,7 @@ message ListEntitiesClimateResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
bool supports_current_temperature = 5; // Deprecated: use feature_flags
@@ -1335,7 +1343,7 @@ message ListEntitiesClimateResponse {
repeated ClimatePreset supported_presets = 16 [(container_pointer_no_template) = "climate::ClimatePresetMask"];
repeated string supported_custom_presets = 17 [(container_pointer_no_template) = "ConstVector<const char *, true>"];
bool disabled_by_default = 18;
string icon = 19 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 19 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
EntityCategory entity_category = 20;
float visual_current_temperature_step = 21;
bool supports_current_humidity = 22; // Deprecated: use feature_flags
@@ -1430,8 +1438,8 @@ message ListEntitiesWaterHeaterResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 5;
EntityCategory entity_category = 6;
uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"];
@@ -1510,10 +1518,10 @@ message ListEntitiesNumberResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
float min_value = 6;
float max_value = 7;
float step = 8;
@@ -1521,7 +1529,7 @@ message ListEntitiesNumberResponse {
EntityCategory entity_category = 10;
string unit_of_measurement = 11 [(max_data_length) = 63];
NumberMode mode = 12;
string device_class = 13 [(max_data_length) = 47];
string device_class = 13 [(max_data_length) = 47, (progmem) = true];
uint32 device_id = 14 [(field_ifdef) = "USE_DEVICES"];
}
message NumberStateResponse {
@@ -1559,10 +1567,10 @@ message ListEntitiesSelectResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
repeated string options = 6 [(container_pointer_no_template) = "std::span<const char *const>"];
bool disabled_by_default = 7;
EntityCategory entity_category = 8;
@@ -1603,10 +1611,10 @@ message ListEntitiesSirenResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
repeated string tones = 7 [(container_pointer_no_template) = "FixedVector<const char *>"];
bool supports_duration = 8;
@@ -1668,10 +1676,10 @@ message ListEntitiesLockResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
bool assumed_state = 8;
@@ -1717,13 +1725,13 @@ message ListEntitiesButtonResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8 [(max_data_length) = 47];
string device_class = 8 [(max_data_length) = 47, (progmem) = true];
uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"];
}
message ButtonCommandRequest {
@@ -1784,10 +1792,10 @@ message ListEntitiesMediaPlayerResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
@@ -2376,9 +2384,9 @@ message ListEntitiesAlarmControlPanelResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
uint32 supported_features = 8;
@@ -2423,9 +2431,9 @@ message ListEntitiesTextResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
@@ -2471,10 +2479,10 @@ message ListEntitiesDateResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
uint32 device_id = 8 [(field_ifdef) = "USE_DEVICES"];
@@ -2518,10 +2526,10 @@ message ListEntitiesTimeResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
uint32 device_id = 8 [(field_ifdef) = "USE_DEVICES"];
@@ -2565,13 +2573,13 @@ message ListEntitiesEventResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8 [(max_data_length) = 47];
string device_class = 8 [(max_data_length) = 47, (progmem) = true];
repeated string event_types = 9 [(container_pointer_no_template) = "ConstVector<const char *, true>"];
uint32 device_id = 10 [(field_ifdef) = "USE_DEVICES"];
@@ -2596,13 +2604,13 @@ message ListEntitiesValveResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8 [(max_data_length) = 47];
string device_class = 8 [(max_data_length) = 47, (progmem) = true];
bool assumed_state = 9;
bool supports_position = 10;
@@ -2651,10 +2659,10 @@ message ListEntitiesDateTimeResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
uint32 device_id = 8 [(field_ifdef) = "USE_DEVICES"];
@@ -2694,13 +2702,13 @@ message ListEntitiesUpdateResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8 [(max_data_length) = 47];
string device_class = 8 [(max_data_length) = 47, (progmem) = true];
uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"];
}
message UpdateStateResponse {
@@ -2794,8 +2802,8 @@ message ListEntitiesInfraredResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 5;
EntityCategory entity_category = 6;
uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"];
@@ -2863,8 +2871,8 @@ message ListEntitiesRadioFrequencyResponse {
string object_id = 1 [(max_data_length) = 120, (force) = true];
fixed32 key = 2 [(force) = true];
string name = 3 [(max_data_length) = 120, (force) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63, (progmem) = true];
bool disabled_by_default = 5;
EntityCategory entity_category = 6;
uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"];
+9 -6
View File
@@ -24,6 +24,7 @@
#endif
#include "esphome/components/network/util.h"
#include "esphome/core/application.h"
#include "esphome/core/device.h"
#include "esphome/core/entity_base.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
@@ -485,13 +486,12 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp
msg.key = entity->get_object_id_hash();
if (entity->has_own_name()) {
msg.name = entity->get_name();
msg.name = entity->get_name_progmem();
}
// Set common EntityBase properties
#ifdef USE_ENTITY_ICON
char icon_buf[MAX_ICON_LENGTH];
msg.icon = StringRef(entity->get_icon_to(icon_buf));
msg.icon = entity->get_icon_progmem();
#endif
msg.disabled_by_default = entity->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category());
@@ -502,12 +502,11 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp
}
uint16_t APIConnection::fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg,
StringRef &device_class_field,
ProgmemStringRef &device_class_field,
CalculateSizeFn size_fn,
MessageEncodeFn encode_fn, APIConnection *conn,
uint32_t remaining_size) {
char dc_buf[MAX_DEVICE_CLASS_LENGTH];
device_class_field = StringRef(entity->get_device_class_to(dc_buf));
device_class_field = entity->get_device_class_progmem();
return fill_and_encode_entity_info(entity, msg, size_fn, encode_fn, conn, remaining_size);
}
@@ -555,6 +554,7 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c
msg.supports_position = traits.get_supports_position();
msg.supports_tilt = traits.get_supports_tilt();
msg.supports_stop = traits.get_supports_stop();
msg.supports_stop_tilt = traits.get_supports_stop_tilt();
return fill_and_encode_entity_info_with_device_class(cover, msg, msg.device_class, conn, remaining_size);
}
void APIConnection::on_cover_command_request(const CoverCommandRequest &msg) {
@@ -565,6 +565,8 @@ void APIConnection::on_cover_command_request(const CoverCommandRequest &msg) {
call.set_tilt(msg.tilt);
if (msg.stop)
call.set_command_stop();
if (msg.stop_tilt)
call.set_command_stop_tilt();
call.perform();
}
#endif
@@ -2057,6 +2059,7 @@ bool APIConnection::send_device_info_response_() {
device_info.device_id = device->get_device_id();
device_info.name = StringRef(device->get_name());
device_info.area_id = device->get_area_id();
device_info.relation = static_cast<enums::DeviceRelation>(device->get_relation());
}
#endif
#ifdef USE_AREAS
+5 -5
View File
@@ -472,15 +472,15 @@ class APIConnection final : public APIServerConnectionBase {
// Non-template core — fills device_class, then delegates to fill_and_encode_entity_info
static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg,
StringRef &device_class_field, CalculateSizeFn size_fn,
MessageEncodeFn encode_fn, APIConnection *conn,
uint32_t remaining_size);
ProgmemStringRef &device_class_field,
CalculateSizeFn size_fn, MessageEncodeFn encode_fn,
APIConnection *conn, uint32_t remaining_size);
// Thin template wrapper
template<typename T>
static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, T &msg,
StringRef &device_class_field, APIConnection *conn,
uint32_t remaining_size) {
ProgmemStringRef &device_class_field,
APIConnection *conn, uint32_t remaining_size) {
return fill_and_encode_entity_info_with_device_class(entity, msg, device_class_field, &T::calc_size_msg,
&T::encode_msg, conn, remaining_size);
}
+69 -62
View File
@@ -85,6 +85,7 @@ uint8_t *DeviceInfo::encode_msg(const void *self, uint8_t *__restrict__ pos PROT
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.device_id);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, msg.name);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, msg.area_id);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast<uint32_t>(msg.relation));
return pos;
}
uint32_t DeviceInfo::calc_size_msg(const void *self) {
@@ -93,6 +94,7 @@ uint32_t DeviceInfo::calc_size_msg(const void *self) {
size += ProtoSize::calc_uint32(1, msg.device_id);
size += 2 + msg.name.size();
size += ProtoSize::calc_uint32(1, msg.area_id);
size += msg.relation ? 2 : 0;
return size;
}
#endif
@@ -403,12 +405,12 @@ uint8_t *ListEntitiesBinarySensorResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesBinarySensorResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.device_class);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.device_class);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.is_status_binary_sensor);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.icon);
#endif
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, static_cast<uint32_t>(msg.entity_category));
#ifdef USE_DEVICES
@@ -461,20 +463,21 @@ uint8_t *ListEntitiesCoverResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesCoverResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.assumed_state);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_position);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_tilt);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.icon);
#endif
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, msg.supports_stop);
#ifdef USE_DEVICES
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, msg.device_id);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 14, msg.supports_stop_tilt);
return pos;
}
uint32_t ListEntitiesCoverResponse::calc_size_msg(const void *self) {
@@ -496,6 +499,7 @@ uint32_t ListEntitiesCoverResponse::calc_size_msg(const void *self) {
#ifdef USE_DEVICES
size += ProtoSize::calc_uint32(1, msg.device_id);
#endif
size += ProtoSize::calc_bool(1, msg.supports_stop_tilt);
return size;
}
uint8_t *CoverStateResponse::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
@@ -552,6 +556,9 @@ void CoverCommandRequest::decode_field(void *self, uint32_t tag, const uint8_t *
msg.device_id = value.as_varint();
break;
#endif
case proto_tag(10, WIRE_TYPE_VARINT):
msg.stop_tilt = value.as_bool();
break;
}
}
#endif
@@ -560,14 +567,14 @@ uint8_t *ListEntitiesFanResponse::encode_msg(const void *self, uint8_t *__restri
const auto &msg = *static_cast<const ListEntitiesFanResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_oscillation);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_speed);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_direction);
pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.supported_speed_count);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.icon);
#endif
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast<uint32_t>(msg.entity_category));
for (const char *it : *msg.supported_preset_modes) {
@@ -680,7 +687,7 @@ uint8_t *ListEntitiesLightResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesLightResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
for (const auto &it : *msg.supported_color_modes) {
pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(it));
}
@@ -695,7 +702,7 @@ uint8_t *ListEntitiesLightResponse::encode_msg(const void *self, uint8_t *__rest
}
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 13, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 14, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 14, msg.icon);
#endif
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 15, static_cast<uint32_t>(msg.entity_category));
#ifdef USE_DEVICES
@@ -886,14 +893,14 @@ uint8_t *ListEntitiesSensorResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesSensorResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.unit_of_measurement);
pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.accuracy_decimals);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.force_update);
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.device_class);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast<uint32_t>(msg.state_class));
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast<uint32_t>(msg.entity_category));
@@ -954,14 +961,14 @@ uint8_t *ListEntitiesSwitchResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesSwitchResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.assumed_state);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.device_class);
#ifdef USE_DEVICES
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.device_id);
#endif
@@ -1030,13 +1037,13 @@ uint8_t *ListEntitiesTextSensorResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesTextSensorResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
#ifdef USE_DEVICES
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.device_id);
#endif
@@ -1476,10 +1483,10 @@ uint8_t *ListEntitiesCameraResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesCameraResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.icon);
#endif
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
#ifdef USE_DEVICES
@@ -1542,7 +1549,7 @@ uint8_t *ListEntitiesClimateResponse::encode_msg(const void *self, uint8_t *__re
const auto &msg = *static_cast<const ListEntitiesClimateResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_current_temperature);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_two_point_target_temperature);
for (const auto &it : *msg.supported_modes) {
@@ -1575,7 +1582,7 @@ uint8_t *ListEntitiesClimateResponse::encode_msg(const void *self, uint8_t *__re
}
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 18, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 19, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 19, msg.icon);
#endif
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 20, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.visual_current_temperature_step);
@@ -1779,9 +1786,9 @@ uint8_t *ListEntitiesWaterHeaterResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesWaterHeaterResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast<uint32_t>(msg.entity_category));
@@ -1906,9 +1913,9 @@ uint8_t *ListEntitiesNumberResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesNumberResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
if (uint32_t raw = float_to_raw(msg.min_value); raw != 0) [[likely]] {
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 53, raw);
@@ -1923,7 +1930,7 @@ uint8_t *ListEntitiesNumberResponse::encode_msg(const void *self, uint8_t *__res
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, msg.unit_of_measurement);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(msg.mode));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 13, msg.device_class);
#ifdef USE_DEVICES
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, msg.device_id);
#endif
@@ -1997,9 +2004,9 @@ uint8_t *ListEntitiesSelectResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesSelectResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
for (const char *it : *msg.options) {
pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 6, it, strlen(it));
@@ -2076,9 +2083,9 @@ uint8_t *ListEntitiesSirenResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesSirenResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
for (const char *it : *msg.tones) {
@@ -2178,9 +2185,9 @@ uint8_t *ListEntitiesLockResponse::encode_msg(const void *self, uint8_t *__restr
const auto &msg = *static_cast<const ListEntitiesLockResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
@@ -2261,13 +2268,13 @@ uint8_t *ListEntitiesButtonResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesButtonResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
#ifdef USE_DEVICES
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.device_id);
#endif
@@ -2330,9 +2337,9 @@ uint8_t *ListEntitiesMediaPlayerResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesMediaPlayerResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
@@ -3175,9 +3182,9 @@ uint8_t *ListEntitiesAlarmControlPanelResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesAlarmControlPanelResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
@@ -3255,9 +3262,9 @@ uint8_t *ListEntitiesTextResponse::encode_msg(const void *self, uint8_t *__restr
const auto &msg = *static_cast<const ListEntitiesTextResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
@@ -3334,9 +3341,9 @@ uint8_t *ListEntitiesDateResponse::encode_msg(const void *self, uint8_t *__restr
const auto &msg = *static_cast<const ListEntitiesDateResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
@@ -3415,9 +3422,9 @@ uint8_t *ListEntitiesTimeResponse::encode_msg(const void *self, uint8_t *__restr
const auto &msg = *static_cast<const ListEntitiesTimeResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
@@ -3496,13 +3503,13 @@ uint8_t *ListEntitiesEventResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesEventResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
for (const char *it : *msg.event_types) {
pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 9, it, strlen(it));
}
@@ -3558,13 +3565,13 @@ uint8_t *ListEntitiesValveResponse::encode_msg(const void *self, uint8_t *__rest
const auto &msg = *static_cast<const ListEntitiesValveResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.assumed_state);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.supports_position);
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 11, msg.supports_stop);
@@ -3646,9 +3653,9 @@ uint8_t *ListEntitiesDateTimeResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesDateTimeResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
@@ -3719,13 +3726,13 @@ uint8_t *ListEntitiesUpdateResponse::encode_msg(const void *self, uint8_t *__res
const auto &msg = *static_cast<const ListEntitiesUpdateResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(msg.entity_category));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 8, msg.device_class);
#ifdef USE_DEVICES
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, msg.device_id);
#endif
@@ -3873,9 +3880,9 @@ uint8_t *ListEntitiesInfraredResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesInfraredResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast<uint32_t>(msg.entity_category));
@@ -3989,9 +3996,9 @@ uint8_t *ListEntitiesRadioFrequencyResponse::encode_msg(const void *self,
const auto &msg = *static_cast<const ListEntitiesRadioFrequencyResponse *>(self);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
#ifdef USE_ENTITY_ICON
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
#endif
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.disabled_by_default);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast<uint32_t>(msg.entity_category));
+21 -14
View File
@@ -19,6 +19,10 @@ enum DisconnectReason : uint32_t {
DISCONNECT_REASON_UNSPECIFIED = 0,
DISCONNECT_REASON_PROVISIONING_CLOSED = 1,
};
enum DeviceRelation : uint32_t {
DEVICE_RELATION_VIA = 0,
DEVICE_RELATION_CHILD = 1,
};
enum SerialProxyPortType : uint32_t {
SERIAL_PROXY_PORT_TYPE_TTL = 0,
SERIAL_PROXY_PORT_TYPE_RS232 = 1,
@@ -399,10 +403,10 @@ class InfoResponseProtoMessage : public ProtoMessage {
public:
StringRef object_id{};
uint32_t key{0};
StringRef name{};
ProgmemStringRef name{};
bool disabled_by_default{false};
#ifdef USE_ENTITY_ICON
StringRef icon{nullptr, 0}; // null until set, encode only
ProgmemStringRef icon{};
#endif
enums::EntityCategory entity_category{};
#ifdef USE_DEVICES
@@ -567,6 +571,7 @@ class DeviceInfo final : public ProtoMessage {
uint32_t device_id{0};
StringRef name{};
uint32_t area_id{0};
enums::DeviceRelation relation{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -866,7 +871,7 @@ class ListEntitiesBinarySensorResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("list_entities_binary_sensor_response"); }
#endif
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
bool is_status_binary_sensor{false};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
@@ -906,15 +911,16 @@ class BinarySensorStateResponse final : public StateResponseProtoMessage {
class ListEntitiesCoverResponse final : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 13;
static constexpr uint8_t ESTIMATED_SIZE = 57;
static constexpr uint8_t ESTIMATED_SIZE = 59;
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("list_entities_cover_response"); }
#endif
bool assumed_state{false};
bool supports_position{false};
bool supports_tilt{false};
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
bool supports_stop{false};
bool supports_stop_tilt{false};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -952,7 +958,7 @@ class CoverStateResponse final : public StateResponseProtoMessage {
class CoverCommandRequest final : public CommandProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 30;
static constexpr uint8_t ESTIMATED_SIZE = 25;
static constexpr uint8_t ESTIMATED_SIZE = 27;
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("cover_command_request"); }
#endif
@@ -961,6 +967,7 @@ class CoverCommandRequest final : public CommandProtoMessage {
bool has_tilt{false};
float tilt{0.0f};
bool stop{false};
bool stop_tilt{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
@@ -1159,7 +1166,7 @@ class ListEntitiesSensorResponse final : public InfoResponseProtoMessage {
StringRef unit_of_measurement{nullptr, 0}; // null until set, encode only
int32_t accuracy_decimals{0};
bool force_update{false};
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
enums::SensorStateClass state_class{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
@@ -1204,7 +1211,7 @@ class ListEntitiesSwitchResponse final : public InfoResponseProtoMessage {
const LogString *message_name() const override { return LOG_STR("list_entities_switch_response"); }
#endif
bool assumed_state{false};
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -1265,7 +1272,7 @@ class ListEntitiesTextSensorResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("list_entities_text_sensor_response"); }
#endif
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -1959,7 +1966,7 @@ class ListEntitiesNumberResponse final : public InfoResponseProtoMessage {
float step{0.0f};
StringRef unit_of_measurement{nullptr, 0}; // null until set, encode only
enums::NumberMode mode{};
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -2215,7 +2222,7 @@ class ListEntitiesButtonResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("list_entities_button_response"); }
#endif
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -3460,7 +3467,7 @@ class ListEntitiesEventResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("list_entities_event_response"); }
#endif
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
const ConstVector<const char *, true> *event_types{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
@@ -3503,7 +3510,7 @@ class ListEntitiesValveResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("list_entities_valve_response"); }
#endif
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
bool assumed_state{false};
bool supports_position{false};
bool supports_stop{false};
@@ -3629,7 +3636,7 @@ class ListEntitiesUpdateResponse final : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("list_entities_update_response"); }
#endif
StringRef device_class{nullptr, 0}; // null until set, encode only
ProgmemStringRef device_class{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
+75 -62
View File
@@ -154,6 +154,16 @@ template<> const char *proto_enum_to_string<enums::DisconnectReason>(enums::Disc
return ESPHOME_PSTR("UNKNOWN");
}
}
template<> const char *proto_enum_to_string<enums::DeviceRelation>(enums::DeviceRelation value) {
switch (value) {
case enums::DEVICE_RELATION_VIA:
return ESPHOME_PSTR("DEVICE_RELATION_VIA");
case enums::DEVICE_RELATION_CHILD:
return ESPHOME_PSTR("DEVICE_RELATION_CHILD");
default:
return ESPHOME_PSTR("UNKNOWN");
}
}
template<> const char *proto_enum_to_string<enums::SerialProxyPortType>(enums::SerialProxyPortType value) {
switch (value) {
case enums::SERIAL_PROXY_PORT_TYPE_TTL:
@@ -1005,6 +1015,7 @@ const char *DeviceInfo::dump_to(DumpBuffer &out) const {
dump_field(out, ESPHOME_PSTR("device_id"), this->device_id);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("area_id"), this->area_id);
dump_field(out, ESPHOME_PSTR("relation"), static_cast<enums::DeviceRelation>(this->relation));
return out.c_str();
}
#endif
@@ -1191,12 +1202,12 @@ const char *ListEntitiesBinarySensorResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesBinarySensorResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_field(out, ESPHOME_PSTR("is_status_binary_sensor"), this->is_status_binary_sensor);
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
#ifdef USE_DEVICES
@@ -1220,20 +1231,21 @@ const char *ListEntitiesCoverResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCoverResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state);
dump_field(out, ESPHOME_PSTR("supports_position"), this->supports_position);
dump_field(out, ESPHOME_PSTR("supports_tilt"), this->supports_tilt);
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("supports_stop"), this->supports_stop);
#ifdef USE_DEVICES
dump_field(out, ESPHOME_PSTR("device_id"), this->device_id);
#endif
dump_field(out, ESPHOME_PSTR("supports_stop_tilt"), this->supports_stop_tilt);
return out.c_str();
}
const char *CoverStateResponse::dump_to(DumpBuffer &out) const {
@@ -1258,6 +1270,7 @@ const char *CoverCommandRequest::dump_to(DumpBuffer &out) const {
#ifdef USE_DEVICES
dump_field(out, ESPHOME_PSTR("device_id"), this->device_id);
#endif
dump_field(out, ESPHOME_PSTR("stop_tilt"), this->stop_tilt);
return out.c_str();
}
#endif
@@ -1266,14 +1279,14 @@ const char *ListEntitiesFanResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesFanResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("supports_oscillation"), this->supports_oscillation);
dump_field(out, ESPHOME_PSTR("supports_speed"), this->supports_speed);
dump_field(out, ESPHOME_PSTR("supports_direction"), this->supports_direction);
dump_field(out, ESPHOME_PSTR("supported_speed_count"), this->supported_speed_count);
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
for (const auto &it : *this->supported_preset_modes) {
@@ -1321,7 +1334,7 @@ const char *ListEntitiesLightResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLightResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
for (const auto &it : *this->supported_color_modes) {
dump_field(out, ESPHOME_PSTR("supported_color_modes"), static_cast<enums::ColorMode>(it), 4);
}
@@ -1332,7 +1345,7 @@ const char *ListEntitiesLightResponse::dump_to(DumpBuffer &out) const {
}
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
#ifdef USE_DEVICES
@@ -1400,14 +1413,14 @@ const char *ListEntitiesSensorResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSensorResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("unit_of_measurement"), this->unit_of_measurement);
dump_field(out, ESPHOME_PSTR("accuracy_decimals"), this->accuracy_decimals);
dump_field(out, ESPHOME_PSTR("force_update"), this->force_update);
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_field(out, ESPHOME_PSTR("state_class"), static_cast<enums::SensorStateClass>(this->state_class));
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -1432,14 +1445,14 @@ const char *ListEntitiesSwitchResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSwitchResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state);
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
#ifdef USE_DEVICES
dump_field(out, ESPHOME_PSTR("device_id"), this->device_id);
#endif
@@ -1470,13 +1483,13 @@ const char *ListEntitiesTextSensorResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextSensorResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
#ifdef USE_DEVICES
dump_field(out, ESPHOME_PSTR("device_id"), this->device_id);
#endif
@@ -1701,10 +1714,10 @@ const char *ListEntitiesCameraResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCameraResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
#ifdef USE_DEVICES
@@ -1734,7 +1747,7 @@ const char *ListEntitiesClimateResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesClimateResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
dump_field(out, ESPHOME_PSTR("supports_current_temperature"), this->supports_current_temperature);
dump_field(out, ESPHOME_PSTR("supports_two_point_target_temperature"), this->supports_two_point_target_temperature);
for (const auto &it : *this->supported_modes) {
@@ -1761,7 +1774,7 @@ const char *ListEntitiesClimateResponse::dump_to(DumpBuffer &out) const {
}
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("visual_current_temperature_step"), this->visual_current_temperature_step);
@@ -1832,9 +1845,9 @@ const char *ListEntitiesWaterHeaterResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesWaterHeaterResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -1886,9 +1899,9 @@ const char *ListEntitiesNumberResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesNumberResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("min_value"), this->min_value);
dump_field(out, ESPHOME_PSTR("max_value"), this->max_value);
@@ -1897,7 +1910,7 @@ const char *ListEntitiesNumberResponse::dump_to(DumpBuffer &out) const {
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("unit_of_measurement"), this->unit_of_measurement);
dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::NumberMode>(this->mode));
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
#ifdef USE_DEVICES
dump_field(out, ESPHOME_PSTR("device_id"), this->device_id);
#endif
@@ -1928,9 +1941,9 @@ const char *ListEntitiesSelectResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSelectResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
for (const auto &it : *this->options) {
dump_field(out, ESPHOME_PSTR("options"), it, 4);
@@ -1967,9 +1980,9 @@ const char *ListEntitiesSirenResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSirenResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
for (const auto &it : *this->tones) {
@@ -2014,9 +2027,9 @@ const char *ListEntitiesLockResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLockResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -2055,13 +2068,13 @@ const char *ListEntitiesButtonResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesButtonResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
#ifdef USE_DEVICES
dump_field(out, ESPHOME_PSTR("device_id"), this->device_id);
#endif
@@ -2090,9 +2103,9 @@ const char *ListEntitiesMediaPlayerResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesMediaPlayerResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -2480,9 +2493,9 @@ const char *ListEntitiesAlarmControlPanelResponse::dump_to(DumpBuffer &out) cons
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesAlarmControlPanelResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -2519,9 +2532,9 @@ const char *ListEntitiesTextResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -2559,9 +2572,9 @@ const char *ListEntitiesDateResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -2599,9 +2612,9 @@ const char *ListEntitiesTimeResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTimeResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -2639,13 +2652,13 @@ const char *ListEntitiesEventResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesEventResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
for (const auto &it : *this->event_types) {
dump_field(out, ESPHOME_PSTR("event_types"), it, 4);
}
@@ -2669,13 +2682,13 @@ const char *ListEntitiesValveResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesValveResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state);
dump_field(out, ESPHOME_PSTR("supports_position"), this->supports_position);
dump_field(out, ESPHOME_PSTR("supports_stop"), this->supports_stop);
@@ -2711,9 +2724,9 @@ const char *ListEntitiesDateTimeResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateTimeResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -2747,13 +2760,13 @@ const char *ListEntitiesUpdateResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesUpdateResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
dump_progmem_string_field(out, ESPHOME_PSTR("device_class"), this->device_class);
#ifdef USE_DEVICES
dump_field(out, ESPHOME_PSTR("device_id"), this->device_id);
#endif
@@ -2810,9 +2823,9 @@ const char *ListEntitiesInfraredResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesInfraredResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
@@ -2868,9 +2881,9 @@ const char *ListEntitiesRadioFrequencyResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesRadioFrequencyResponse"));
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
dump_field(out, ESPHOME_PSTR("key"), this->key);
dump_field(out, ESPHOME_PSTR("name"), this->name);
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
#ifdef USE_ENTITY_ICON
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
dump_progmem_string_field(out, ESPHOME_PSTR("icon"), this->icon);
#endif
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category));
+14
View File
@@ -409,6 +409,10 @@ class ProtoEncode {
/// Tag must be a single-byte varint (< 128). Always encodes (no zero check).
[[nodiscard]] static inline uint8_t *encode_short_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
uint8_t tag, const StringRef &ref) {
#ifdef USE_ESP8266
// memcpy_P reads RAM too, and sharing the progmem copy is smaller than an inline memcpy
return encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, tag, ProgmemStringRef(ref));
#else
#ifdef ESPHOME_DEBUG_API
assert(ref.size() < 128 && "encode_short_string_force: string exceeds max_data_length < 128");
#endif
@@ -417,6 +421,7 @@ class ProtoEncode {
pos[1] = static_cast<uint8_t>(ref.size());
std::memcpy(pos + 2, ref.c_str(), ref.size());
return pos + 2 + ref.size();
#endif
}
/// encode_short_string_force for a string that may be in flash (PROGMEM).
[[nodiscard]] static inline uint8_t *encode_short_progmem_string_force(
@@ -496,13 +501,22 @@ class ProtoEncode {
/// encode_progmem_bytes for a string field that may be in flash.
[[nodiscard]] static inline uint8_t *encode_progmem_string(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
uint32_t field_id, const ProgmemStringRef &ref) {
#ifdef USE_ESP8266
return encode_progmem_bytes(pos PROTO_ENCODE_DEBUG_ARG, field_id,
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
#else
// In RAM here, so share the plain string encoder
return encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, ref.ram_ref());
#endif
}
[[nodiscard]] static inline uint8_t *encode_progmem_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
uint32_t field_id, const ProgmemStringRef &ref) {
#ifdef USE_ESP8266
return encode_progmem_bytes_force(pos PROTO_ENCODE_DEBUG_ARG, field_id,
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
#else
return encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, ref.ram_ref());
#endif
}
[[nodiscard]] static inline uint8_t *encode_uint32_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
uint32_t field_id, uint32_t value) {
+2 -2
View File
@@ -30,10 +30,10 @@ void AQISensor::dump_config() {
ESP_LOGCONFIG(TAG, " Extended Range: %s",
this->extended_range_ ? LOG_STR_LITERAL("enabled") : LOG_STR_LITERAL("disabled"));
if (this->pm_2_5_sensor_ != nullptr) {
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", this->pm_2_5_sensor_->get_name().c_str());
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", LOG_STR_ARG(this->pm_2_5_sensor_->get_log_name()));
}
if (this->pm_10_0_sensor_ != nullptr) {
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", this->pm_10_0_sensor_->get_name().c_str());
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", LOG_STR_ARG(this->pm_10_0_sensor_->get_log_name()));
}
LOG_SENSOR(" ", "AQI", this);
}
@@ -23,7 +23,6 @@ AS5600Sensor = as5600_ns.class_("AS5600Sensor", sensor.Sensor, cg.PollingCompone
CONF_RAW_POSITION = "raw_position"
CONF_SLOW_FILTER = "slow_filter"
CONF_FAST_FILTER = "fast_filter"
CONF_PWM_FREQUENCY = "pwm_frequency"
CONF_BURN_COUNT = "burn_count"
CONF_START_POSITION = "start_position"
CONF_END_POSITION = "end_position"
+2 -2
View File
@@ -639,7 +639,7 @@ float ATM90E32Component::get_chip_temperature_() {
void ATM90E32Component::press_calibration_button(EntityBase *entity, void (ATM90E32Component::*action)(),
const LogString *hint, const LogString *hint2) {
ESP_LOGI(TAG, "%s", entity->get_name().c_str());
ESP_LOGI(TAG, "%s", LOG_STR_ARG(entity->get_log_name()));
if (hint != nullptr) {
ESP_LOGI(TAG, "%s", LOG_STR_ARG(hint));
}
@@ -1295,7 +1295,7 @@ void ATM90E32Component::check_phase_status() {
if (!status.empty()) {
status.pop_back(); // remove space
status.pop_back(); // remove semicolon
ESP_LOGW(TAG, "%s: %s", sensor->get_name().c_str(), status.c_str());
ESP_LOGW(TAG, "%s: %s", LOG_STR_ARG(sensor->get_log_name()), status.c_str());
sensor->publish_state(status);
} else {
sensor->publish_state("Okay");
@@ -211,7 +211,7 @@ void BedJetClimate::control(const ClimateCall &call) {
} else if (fan_mode == CLIMATE_FAN_HIGH) {
result = this->parent_->set_fan_speed(75);
} else {
ESP_LOGW(TAG, "[%s] Unsupported fan mode: %s", this->get_name().c_str(),
ESP_LOGW(TAG, "[%s] Unsupported fan mode: %s", LOG_STR_ARG(this->get_log_name()),
LOG_STR_ARG(climate_fan_mode_to_string(fan_mode)));
return;
}
@@ -223,7 +223,7 @@ void BedJetClimate::control(const ClimateCall &call) {
auto fan_mode = call.get_custom_fan_mode();
auto fan_index = bedjet_fan_speed_to_step(fan_mode.c_str());
if (fan_index <= 19) {
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", this->get_name().c_str(),
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", LOG_STR_ARG(this->get_log_name()),
(int) fan_mode.size(), fan_mode.c_str(), fan_index);
bool result = this->parent_->set_fan_index(fan_index);
if (result) {
@@ -236,7 +236,7 @@ void BedJetClimate::control(const ClimateCall &call) {
void BedJetClimate::on_bedjet_state(bool is_ready) {}
void BedJetClimate::on_status(const BedjetStatusPacket *data) {
ESP_LOGV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
ESP_LOGV(TAG, "[%s] Handling on_status with data=%p", LOG_STR_ARG(this->get_log_name()), (void *) data);
auto converted_temp = bedjet_temp_to_c(data->target_temp_step);
if (converted_temp > 0)
@@ -310,11 +310,11 @@ void BedJetClimate::on_status(const BedjetStatusPacket *data) {
break;
default:
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", this->get_name().c_str(), data->mode);
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", LOG_STR_ARG(this->get_log_name()), data->mode);
break;
}
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", this->get_name().c_str(),
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", LOG_STR_ARG(this->get_log_name()),
LOG_STR_ARG(climate_mode_to_string(this->mode)));
// FIXME: compare new state to previous state.
this->publish_state();
@@ -351,11 +351,11 @@ bool BedJetClimate::update_status_() {
}
void BedJetClimate::update() {
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
ESP_LOGD(TAG, "[%s] update()", LOG_STR_ARG(this->get_log_name()));
// TODO: if the hub component is already polling, do we also need to include polling?
// We're already going to get on_status() at the hub's polling interval.
auto result = this->update_status_();
ESP_LOGD(TAG, "[%s] update_status result=%s", this->get_name().c_str(), result ? "true" : "false");
ESP_LOGD(TAG, "[%s] update_status result=%s", LOG_STR_ARG(this->get_log_name()), result ? "true" : "false");
}
} // namespace esphome::bedjet
+3 -3
View File
@@ -53,7 +53,7 @@ void BedJetFan::control(const fan::FanCall &call) {
}
void BedJetFan::on_status(const BedjetStatusPacket *data) {
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", LOG_STR_ARG(this->get_log_name()), (void *) data);
bool did_change = false;
bool new_state = data->mode != MODE_STANDBY && data->mode != MODE_WAIT;
@@ -96,11 +96,11 @@ bool BedJetFan::update_status_() {
}
void BedJetFan::update() {
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
ESP_LOGD(TAG, "[%s] update()", LOG_STR_ARG(this->get_log_name()));
// TODO: if the hub component is already polling, do we also need to include polling?
// We're already going to get on_status() at the hub's polling interval.
auto result = this->update_status_();
ESP_LOGD(TAG, "[%s] update_status result=%s", this->get_name().c_str(), result ? "true" : "false");
ESP_LOGD(TAG, "[%s] update_status result=%s", LOG_STR_ARG(this->get_log_name()), result ? "true" : "false");
}
/** Resets states to defaults. */
+1 -1
View File
@@ -151,7 +151,7 @@ void BH1750Sensor::loop() {
break;
}
ESP_LOGV(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), lx);
ESP_LOGV(TAG, "'%s': Illuminance=%.1flx", LOG_STR_ARG(this->get_log_name()), lx);
this->status_clear_warning();
this->publish_state(lx);
this->state_ = IDLE;
@@ -36,7 +36,7 @@ bool BinarySensor::set_new_state(const optional<bool> &new_state) {
#if defined(USE_BINARY_SENSOR) && defined(USE_CONTROLLER_REGISTRY)
ControllerRegistry::notify_binary_sensor_update(this);
#endif
ESP_LOGV(TAG, "'%s' >> %s", this->get_name().c_str(), ONOFFMAYBE(new_state));
ESP_LOGV(TAG, "'%s' >> %s", LOG_STR_ARG(this->get_log_name()), ONOFFMAYBE(new_state));
return true;
}
return false;
@@ -47,7 +47,7 @@ void BinarySensorMap::process_group_() {
}
} else if (this->last_mask_ != 0ULL) {
// no buttons are pressed and the states have changed since last run, so publish NAN
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", LOG_STR_ARG(this->get_log_name()));
this->publish_state(NAN);
}
+1 -1
View File
@@ -192,7 +192,7 @@ float BL0940::update_temp_(sensor::Sensor *sensor, uint16_le_t temperature) cons
if (sensor != nullptr) {
if (sensor->has_state() && std::abs(converted_temp - sensor->get_state()) > max_temperature_diff_) {
ESP_LOGD(TAG, "Invalid temperature change. Sensor: '%s', Old temperature: %f, New temperature: %f",
sensor->get_name().c_str(), sensor->get_state(), converted_temp);
LOG_STR_ARG(sensor->get_log_name()), sensor->get_state(), converted_temp);
return 0.0f;
}
sensor->publish_state(converted_temp);
@@ -63,7 +63,7 @@ void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
void BLEClientRSSISensor::update() {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
this->should_update_ = true;
return;
}
@@ -37,13 +37,13 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
switch (event) {
case ESP_GATTC_OPEN_EVT: {
if (param->open.status == ESP_GATT_OK) {
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
ESP_LOGI(TAG, "[%s] Connected successfully!", LOG_STR_ARG(this->get_log_name()));
break;
}
break;
}
case ESP_GATTC_CLOSE_EVT: {
ESP_LOGW(TAG, "[%s] Disconnected!", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Disconnected!", LOG_STR_ARG(this->get_log_name()));
this->status_set_warning();
this->publish_state(NAN);
break;
@@ -102,10 +102,10 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
}
case ESP_GATTC_NOTIFY_EVT: {
if (param->notify.value_len == 0) {
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", LOG_STR_ARG(this->get_log_name()));
break;
}
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", LOG_STR_ARG(this->get_log_name()),
param->notify.handle, param->notify.value[0]);
if (param->notify.handle != this->handle)
break;
@@ -143,11 +143,11 @@ float BLESensor::parse_data_(uint8_t *value, uint16_t value_len) {
void BLESensor::update() {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
return;
}
if (this->handle == 0) {
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", LOG_STR_ARG(this->get_log_name()));
return;
}
@@ -156,7 +156,7 @@ void BLESensor::update() {
if (status) {
this->status_set_warning();
this->publish_state(NAN);
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", LOG_STR_ARG(this->get_log_name()), status);
}
}
@@ -38,7 +38,7 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
switch (event) {
case ESP_GATTC_OPEN_EVT: {
if (param->open.status == ESP_GATT_OK) {
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
ESP_LOGI(TAG, "[%s] Connected successfully!", LOG_STR_ARG(this->get_log_name()));
break;
}
break;
@@ -104,10 +104,10 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
if (param->notify.handle != this->handle)
break;
if (param->notify.value_len == 0) {
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", LOG_STR_ARG(this->get_log_name()));
break;
}
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", LOG_STR_ARG(this->get_log_name()),
param->notify.handle, param->notify.value[0]);
this->publish_state(reinterpret_cast<const char *>(param->notify.value), param->notify.value_len);
break;
@@ -124,11 +124,11 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
void BLETextSensor::update() {
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
return;
}
if (this->handle == 0) {
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", LOG_STR_ARG(this->get_log_name()));
return;
}
@@ -137,7 +137,7 @@ void BLETextSensor::update() {
if (status) {
this->status_set_warning();
this->publish_state("");
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", this->get_name().c_str(), status);
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", LOG_STR_ARG(this->get_log_name()), status);
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ void log_button(const char *tag, const char *prefix, const char *type, Button *o
}
void Button::press() {
ESP_LOGV(TAG, "'%s' Pressed.", this->get_name().c_str());
ESP_LOGV(TAG, "'%s' Pressed.", LOG_STR_ARG(this->get_log_name()));
this->press_action();
this->press_callback_.call();
}
@@ -2,6 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import esp32, uart, usb_cdc_acm
from esphome.components.bridge import DOMAIN as BRIDGE_DOMAIN
from esphome.components.const import CONF_DTR_PIN, CONF_RTS_PIN
from esphome.components.esp32 import VARIANT_ESP32P4, VARIANT_ESP32S2, VARIANT_ESP32S3
import esphome.config_validation as cv
from esphome.const import CONF_DEBUG, CONF_ID, CONF_UART_ID
@@ -11,8 +12,6 @@ from esphome.types import ConfigType
CODEOWNERS = ["@kbx81"]
DEPENDENCIES = ["tinyusb", "uart", "usb_cdc_acm"]
CONF_DTR_PIN = "dtr_pin"
CONF_RTS_PIN = "rts_pin"
CONF_USB_CDC_ACM_ID = "usb_cdc_acm_id"
cdc_acm_uart_ns = cg.esphome_ns.namespace("cdc_acm_uart")
+10 -7
View File
@@ -46,7 +46,7 @@ constexpr StringToUint8 CLIMATE_SWING_MODES_BY_STR[] = {
void ClimateCall::perform() {
this->parent_->control_callback_.call(*this);
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
this->validate_();
if (this->mode_.has_value()) {
const LogString *mode_s = climate_mode_to_string(*this->mode_);
@@ -183,7 +183,7 @@ ClimateCall &ClimateCall::set_mode(const char *mode, size_t len) {
return *this;
}
}
ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", this->parent_->get_name().c_str(), (int) len, mode);
ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len, mode);
return *this;
}
@@ -214,7 +214,8 @@ ClimateCall &ClimateCall::set_fan_mode(const char *custom_fan_mode, size_t len)
this->fan_mode_.reset();
return *this;
}
ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %.*s", this->parent_->get_name().c_str(), (int) len, custom_fan_mode);
ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
custom_fan_mode);
return *this;
}
@@ -252,7 +253,8 @@ ClimateCall &ClimateCall::set_preset(const char *custom_preset, size_t len) {
this->preset_.reset();
return *this;
}
ESP_LOGW(TAG, "'%s' - Unrecognized preset %.*s", this->parent_->get_name().c_str(), (int) len, custom_preset);
ESP_LOGW(TAG, "'%s' - Unrecognized preset %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
custom_preset);
return *this;
}
@@ -280,7 +282,8 @@ ClimateCall &ClimateCall::set_swing_mode(const char *swing_mode, size_t len) {
return *this;
}
}
ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", this->parent_->get_name().c_str(), (int) len, swing_mode);
ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
swing_mode);
return *this;
}
@@ -428,7 +431,7 @@ void Climate::save_state_(const ClimateTraits &traits) {
void Climate::publish_state() {
this->set_has_state(true);
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
ESP_LOGV(TAG, "'%s' >>", LOG_STR_ARG(this->get_log_name()));
auto traits = this->get_traits();
ESP_LOGV(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode)));
@@ -547,7 +550,7 @@ void ClimateDeviceRestoreState::apply(Climate *climate) {
if (traits.supports_mode(this->mode)) {
climate->mode = this->mode;
} else {
ESP_LOGW(TAG, "'%s' - Saved mode %s is no longer supported, keeping %s", climate->get_name().c_str(),
ESP_LOGW(TAG, "'%s' - Saved mode %s is no longer supported, keeping %s", LOG_STR_ARG(climate->get_log_name()),
LOG_STR_ARG(climate_mode_to_string(this->mode)), LOG_STR_ARG(climate_mode_to_string(climate->mode)));
}
if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
@@ -30,14 +30,14 @@ void CombinationOneParameterComponent::add_source(Sensor *sensor, float value) {
void CombinationNoParameterComponent::log_source_sensors() {
ESP_LOGCONFIG(TAG, " Source Sensors:");
for (const auto &sensor : this->sensors_) {
ESP_LOGCONFIG(TAG, " - %s", sensor->get_name().c_str());
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(sensor->get_log_name()));
}
}
void CombinationOneParameterComponent::log_source_sensors() {
ESP_LOGCONFIG(TAG, " Source Sensors:");
for (const auto &source : this->sensor_sources_) {
ESP_LOGCONFIG(TAG, " - %s", source.sensor->get_name().c_str());
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(source.sensor->get_log_name()));
}
}
+6
View File
@@ -33,6 +33,7 @@ CONF_DATA_BITS = "data_bits"
CONF_DESCRIPTION = "description"
CONF_DRAW_ROUNDING = "draw_rounding"
CONF_DRIVE_STRENGTH = "drive_strength"
CONF_DTR_PIN = "dtr_pin"
CONF_ENABLE_OTA_DOWNGRADE_PROTECTION = "enable_ota_downgrade_protection"
CONF_ENABLED = "enabled"
CONF_ERROR_CODE = "error_code"
@@ -40,6 +41,7 @@ CONF_GREEN_CHANNEL = "green_channel"
CONF_GYROSCOPE_ODR = "gyroscope_odr"
CONF_GYROSCOPE_RANGE = "gyroscope_range"
CONF_HOLD_STATE = "hold_state"
CONF_HORIZONTAL_DEFAULT = "horizontal_default"
CONF_HOST = "host"
CONF_HUMIDITY_SOURCE = "humidity_source"
CONF_IAQ = "iaq"
@@ -58,9 +60,11 @@ CONF_ON_RECEIVE = "on_receive"
CONF_ON_SCAN_END = "on_scan_end"
CONF_ON_STATE_CHANGE = "on_state_change"
CONF_ON_STOP = "on_stop"
CONF_OUT_PIN = "out_pin"
CONF_OUT_PIN_LEVEL = "out_pin_level"
CONF_PARITY = "parity"
CONF_PROVIDER = "provider"
CONF_PWM_FREQUENCY = "pwm_frequency"
CONF_QUERY_PARAMS = "query_params"
CONF_RECEIVER_FREQUENCY = "receiver_frequency"
CONF_RECONNECT_INTERVAL = "reconnect_interval"
@@ -70,6 +74,7 @@ CONF_REQUEST_HEADERS = "request_headers"
CONF_ROLE = "role"
CONF_ROWS = "rows"
CONF_RST_PIN = "rst_pin"
CONF_RTS_PIN = "rts_pin"
CONF_SCAN_PARAMETERS = "scan_parameters"
CONF_SERIAL_NUMBER = "serial_number"
CONF_SHA256 = "sha256"
@@ -81,6 +86,7 @@ CONF_TARGET_COUNT = "target_count"
CONF_USE_PSRAM = "use_psram"
CONF_VALUE_TYPE = "value_type"
CONF_VERIFY_SSL = "verify_ssl"
CONF_VERTICAL_DEFAULT = "vertical_default"
CONF_VOC_INDEX = "voc_index"
CONF_VOLUME_INCREMENT = "volume_increment"
CONF_VOLUME_INITIAL = "volume_initial"
@@ -31,12 +31,14 @@ cover::CoverTraits CopyCover::get_traits() {
traits.set_supports_position(base.get_supports_position());
traits.set_supports_tilt(base.get_supports_tilt());
traits.set_supports_toggle(base.get_supports_toggle());
traits.set_supports_stop_tilt(base.get_supports_stop_tilt());
return traits;
}
void CopyCover::control(const cover::CoverCall &call) {
auto call2 = source_->make_call();
call2.set_stop(call.get_stop());
call2.set_stop_tilt(call.get_stop_tilt());
auto tilt = call.get_tilt();
if (tilt.has_value())
call2.set_tilt(*tilt);
+4
View File
@@ -99,6 +99,7 @@ CONF_ON_CLOSED = "on_closed"
CONF_ON_OPENED = "on_opened"
CONF_ON_OPENING = "on_opening"
CONF_ON_CLOSING = "on_closing"
CONF_STOP_TILT = "stop_tilt"
TRIGGERS = {
CONF_ON_OPEN: CoverOpenedTrigger, # Deprecated, use on_opened
@@ -248,6 +249,7 @@ for _name, _command in (
("cover.open", "set_command_open()"),
("cover.close", "set_command_close()"),
("cover.stop", "set_command_stop()"),
("cover.stop_tilt", "set_command_stop_tilt()"),
("cover.toggle", "set_command_toggle()"),
):
automation.register_apply_action(
@@ -259,6 +261,7 @@ COVER_CONTROL_ACTION_SCHEMA = cv.Schema(
{
cv.Required(CONF_ID): cv.use_id(Cover),
cv.Optional(CONF_STOP): cv.templatable(cv.boolean),
cv.Optional(CONF_STOP_TILT): cv.templatable(cv.boolean),
cv.Exclusive(CONF_STATE, "pos"): cv.templatable(validate_cover_state),
cv.Exclusive(CONF_POSITION, "pos"): cv.templatable(cv.percentage),
cv.Optional(CONF_TILT): cv.templatable(cv.percentage),
@@ -272,6 +275,7 @@ automation.register_apply_action(
"cover.control",
COVER_CONTROL_ACTION_SCHEMA,
automation.ApplyField(CONF_STOP, "set_stop", cg.bool_),
automation.ApplyField(CONF_STOP_TILT, "set_stop_tilt", cg.bool_),
automation.ApplyField(CONF_STATE, "set_position", cg.float_),
automation.ApplyField(CONF_POSITION, "set_position", cg.float_),
automation.ApplyField(CONF_TILT, "set_tilt", cg.float_),
+24 -4
View File
@@ -39,7 +39,7 @@ CoverCall &CoverCall::set_command(const char *command) {
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TOGGLE")) == 0) {
this->set_command_toggle();
} else {
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command);
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", LOG_STR_ARG(this->parent_->get_log_name()), command);
}
return *this;
}
@@ -55,6 +55,10 @@ CoverCall &CoverCall::set_command_stop() {
this->stop_ = true;
return *this;
}
CoverCall &CoverCall::set_command_stop_tilt() {
this->stop_tilt_ = true;
return *this;
}
CoverCall &CoverCall::set_command_toggle() {
this->toggle_ = true;
return *this;
@@ -68,12 +72,15 @@ CoverCall &CoverCall::set_tilt(float tilt) {
return *this;
}
void CoverCall::perform() {
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
auto traits = this->parent_->get_traits();
this->validate_();
if (this->stop_) {
ESP_LOGV(TAG, " Command: STOP");
}
if (this->stop_tilt_) {
ESP_LOGV(TAG, " Command: STOP_TILT");
}
if (this->position_.has_value()) {
if (traits.get_supports_position()) {
ESP_LOGV(TAG, " Position: %.0f%%", *this->position_ * 100.0f);
@@ -94,7 +101,7 @@ const optional<float> &CoverCall::get_tilt() const { return this->tilt_; }
const optional<bool> &CoverCall::get_toggle() const { return this->toggle_; }
void CoverCall::validate_() {
auto traits = this->parent_->get_traits();
const char *name = this->parent_->get_name().c_str();
const char *name = LOG_STR_ARG(this->parent_->get_log_name());
if (this->position_.has_value()) {
auto pos = *this->position_;
@@ -122,6 +129,15 @@ void CoverCall::validate_() {
this->toggle_.reset();
}
}
if (this->stop_tilt_) {
if (!traits.get_supports_stop_tilt()) {
ESP_LOGW(TAG, "'%s': stop tilt unsupported", name);
this->stop_tilt_ = false;
} else if (this->tilt_.has_value()) {
ESP_LOGW(TAG, "'%s': cannot tilt when stopping tilt", name);
this->tilt_.reset();
}
}
if (this->stop_) {
if (this->position_.has_value() || this->tilt_.has_value() || this->toggle_.has_value()) {
ESP_LOGW(TAG, "'%s': cannot position/tilt/toggle when stopping", name);
@@ -135,11 +151,15 @@ CoverCall &CoverCall::set_stop(bool stop) {
this->stop_ = stop;
return *this;
}
CoverCall &CoverCall::set_stop_tilt(bool stop_tilt) {
this->stop_tilt_ = stop_tilt;
return *this;
}
void Cover::publish_state(bool save) {
this->position = clamp(this->position, 0.0f, 1.0f);
this->tilt = clamp(this->tilt, 0.0f, 1.0f);
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
ESP_LOGV(TAG, "'%s' >>", LOG_STR_ARG(this->get_log_name()));
auto traits = this->get_traits();
if (traits.get_supports_position()) {
ESP_LOGV(TAG, " Position: %.0f%%", this->position * 100.0f);
+6
View File
@@ -36,6 +36,8 @@ class CoverCall {
CoverCall &set_command_close();
/// Set the command to stop the cover.
CoverCall &set_command_stop();
/// Set the command to stop the cover tilt.
CoverCall &set_command_stop_tilt();
/// Set the command to toggle the cover.
CoverCall &set_command_toggle();
/// Set the call to a certain target position.
@@ -44,12 +46,15 @@ class CoverCall {
CoverCall &set_tilt(float tilt);
/// Set whether this cover call should stop the cover.
CoverCall &set_stop(bool stop);
/// Set whether this cover call should stop the cover tilt.
CoverCall &set_stop_tilt(bool stop_tilt);
/// Perform the cover call.
void perform();
const optional<float> &get_position() const;
bool get_stop() const { return this->stop_; }
bool get_stop_tilt() const { return this->stop_tilt_; }
const optional<float> &get_tilt() const;
const optional<bool> &get_toggle() const;
@@ -58,6 +63,7 @@ class CoverCall {
Cover *parent_;
bool stop_{false};
bool stop_tilt_{false};
optional<float> position_{};
optional<float> tilt_{};
optional<bool> toggle_{};
+24 -15
View File
@@ -1,28 +1,37 @@
#pragma once
#include <cstdint>
namespace esphome::cover {
class CoverTraits {
public:
CoverTraits() = default;
bool get_is_assumed_state() const { return this->is_assumed_state_; }
void set_is_assumed_state(bool is_assumed_state) { this->is_assumed_state_ = is_assumed_state; }
bool get_supports_position() const { return this->supports_position_; }
void set_supports_position(bool supports_position) { this->supports_position_ = supports_position; }
bool get_supports_tilt() const { return this->supports_tilt_; }
void set_supports_tilt(bool supports_tilt) { this->supports_tilt_ = supports_tilt; }
bool get_supports_toggle() const { return this->supports_toggle_; }
void set_supports_toggle(bool supports_toggle) { this->supports_toggle_ = supports_toggle; }
bool get_supports_stop() const { return this->supports_stop_; }
void set_supports_stop(bool supports_stop) { this->supports_stop_ = supports_stop; }
bool get_is_assumed_state() const { return this->flags_.is_assumed_state; }
void set_is_assumed_state(bool is_assumed_state) { this->flags_.is_assumed_state = is_assumed_state; }
bool get_supports_position() const { return this->flags_.supports_position; }
void set_supports_position(bool supports_position) { this->flags_.supports_position = supports_position; }
bool get_supports_tilt() const { return this->flags_.supports_tilt; }
void set_supports_tilt(bool supports_tilt) { this->flags_.supports_tilt = supports_tilt; }
bool get_supports_toggle() const { return this->flags_.supports_toggle; }
void set_supports_toggle(bool supports_toggle) { this->flags_.supports_toggle = supports_toggle; }
bool get_supports_stop() const { return this->flags_.supports_stop; }
void set_supports_stop(bool supports_stop) { this->flags_.supports_stop = supports_stop; }
bool get_supports_stop_tilt() const { return this->flags_.supports_stop_tilt; }
void set_supports_stop_tilt(bool supports_stop_tilt) { this->flags_.supports_stop_tilt = supports_stop_tilt; }
protected:
bool is_assumed_state_{false};
bool supports_position_{false};
bool supports_tilt_{false};
bool supports_toggle_{false};
bool supports_stop_{false};
// Bit-packed flags to save memory (1 byte instead of 6)
struct CoverTraitFlags {
uint8_t is_assumed_state : 1;
uint8_t supports_position : 1;
uint8_t supports_tilt : 1;
uint8_t supports_toggle : 1;
uint8_t supports_stop : 1;
uint8_t supports_stop_tilt : 1;
uint8_t reserved : 2;
} flags_{};
};
} // namespace esphome::cover
@@ -40,7 +40,8 @@ void CTClampSensor::update() {
if (rms_ac_squared > 0)
rms_ac = std::sqrt(rms_ac_squared);
ESP_LOGD(TAG, "'%s' - Raw AC Value: %.3fA after %" PRIu32 " different samples (%" PRIu32 " SPS)",
this->name_.c_str(), rms_ac, this->num_samples_, 1000 * this->num_samples_ / this->sample_duration_);
LOG_STR_ARG(this->get_log_name()), rms_ac, this->num_samples_,
1000 * this->num_samples_ / this->sample_duration_);
this->publish_state(rms_ac);
});
@@ -70,20 +70,20 @@ void CurrentBasedCover::loop() {
this->direction_idle_();
this->malfunction_trigger_.trigger();
ESP_LOGI(TAG, "'%s' - Malfunction detected during opening. Current flow detected in close circuit",
this->name_.c_str());
LOG_STR_ARG(this->get_log_name()));
} else if (this->is_opening_blocked_()) { // Blocked
ESP_LOGD(TAG, "'%s' - Obstacle detected during opening.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Obstacle detected during opening.", LOG_STR_ARG(this->get_log_name()));
this->direction_idle_();
if (this->obstacle_rollback_ != 0) {
this->set_timeout(ROLLBACK_TIMEOUT_ID, 300, [this]() {
ESP_LOGD(TAG, "'%s' - Rollback.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Rollback.", LOG_STR_ARG(this->get_log_name()));
this->target_position_ = clamp(this->position - this->obstacle_rollback_, 0.0F, 1.0F);
this->start_direction_(COVER_OPERATION_CLOSING);
});
}
} else if (this->is_initial_delay_finished_() && !this->is_opening_()) { // End reached
auto dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - Open position reached. Took %.1fs.", this->name_.c_str(), dur);
ESP_LOGD(TAG, "'%s' - Open position reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
this->direction_idle_(COVER_OPEN);
}
} else if (this->current_operation == COVER_OPERATION_CLOSING) {
@@ -91,25 +91,25 @@ void CurrentBasedCover::loop() {
this->direction_idle_();
this->malfunction_trigger_.trigger();
ESP_LOGI(TAG, "'%s' - Malfunction detected during closing. Current flow detected in open circuit",
this->name_.c_str());
LOG_STR_ARG(this->get_log_name()));
} else if (this->is_closing_blocked_()) { // Blocked
ESP_LOGD(TAG, "'%s' - Obstacle detected during closing.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Obstacle detected during closing.", LOG_STR_ARG(this->get_log_name()));
this->direction_idle_();
if (this->obstacle_rollback_ != 0) {
this->set_timeout(ROLLBACK_TIMEOUT_ID, 300, [this]() {
ESP_LOGD(TAG, "'%s' - Rollback.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Rollback.", LOG_STR_ARG(this->get_log_name()));
this->target_position_ = clamp(this->position + this->obstacle_rollback_, 0.0F, 1.0F);
this->start_direction_(COVER_OPERATION_OPENING);
});
}
} else if (this->is_initial_delay_finished_() && !this->is_closing_()) { // End reached
auto dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - Close position reached. Took %.1fs.", this->name_.c_str(), dur);
ESP_LOGD(TAG, "'%s' - Close position reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
this->direction_idle_(COVER_CLOSED);
}
}
if (now - this->start_dir_time_ > this->max_duration_) {
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
this->direction_idle_();
}
@@ -54,7 +54,7 @@ void DallasTemperatureSensor::update() {
}
float tempc = this->get_temp_c_();
ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", this->get_name().c_str(), tempc);
ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", LOG_STR_ARG(this->get_log_name()), tempc);
this->publish_state(tempc);
});
}
@@ -66,7 +66,7 @@ bool DallasTemperatureSensor::read_scratch_pad_() {
i = this->bus_->read8();
}
} else {
ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", this->get_name().c_str());
ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", LOG_STR_ARG(this->get_log_name()));
this->status_set_warning(LOG_STR("bus reset failed"));
}
return success;
+2 -2
View File
@@ -30,7 +30,7 @@ void DateEntity::publish_state() {
return;
}
this->set_has_state(true);
ESP_LOGV(TAG, "'%s' >> %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_);
ESP_LOGV(TAG, "'%s' >> %d-%d-%d", LOG_STR_ARG(this->get_log_name()), this->year_, this->month_, this->day_);
this->state_callback_.call();
#if defined(USE_DATETIME_DATE) && defined(USE_CONTROLLER_REGISTRY)
ControllerRegistry::notify_date_update(this);
@@ -81,7 +81,7 @@ void DateCall::validate_() {
void DateCall::perform() {
this->validate_();
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
if (this->year_.has_value()) {
ESP_LOGV(TAG, " Year: %d", *this->year_);
@@ -45,7 +45,7 @@ void DateTimeEntity::publish_state() {
return;
}
this->set_has_state(true);
ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, this->month_,
ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", LOG_STR_ARG(this->get_log_name()), this->year_, this->month_,
this->day_, this->hour_, this->minute_, this->second_);
this->state_callback_.call();
#if defined(USE_DATETIME_DATETIME) && defined(USE_CONTROLLER_REGISTRY)
@@ -125,7 +125,7 @@ void DateTimeCall::validate_() {
void DateTimeCall::perform() {
this->validate_();
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
if (this->year_.has_value()) {
ESP_LOGV(TAG, " Year: %d", *this->year_);
+2 -2
View File
@@ -26,7 +26,7 @@ void TimeEntity::publish_state() {
return;
}
this->set_has_state(true);
ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, this->second_);
ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", LOG_STR_ARG(this->get_log_name()), this->hour_, this->minute_, this->second_);
this->state_callback_.call();
#if defined(USE_DATETIME_TIME) && defined(USE_CONTROLLER_REGISTRY)
ControllerRegistry::notify_time_update(this);
@@ -50,7 +50,7 @@ void TimeCall::validate_() {
void TimeCall::perform() {
this->validate_();
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
if (this->hour_.has_value()) {
ESP_LOGV(TAG, " Hour: %d", *this->hour_);
}
+4 -3
View File
@@ -36,7 +36,8 @@ void DewPointComponent::dump_config() {
"Sources\n"
" Temperature: '%s'\n"
" Humidity: '%s'",
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
LOG_STR_ARG(this->temperature_sensor_->get_log_name()),
LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
}
float DewPointComponent::get_setup_priority() const { return setup_priority::DATA; }
@@ -75,8 +76,8 @@ void DewPointComponent::loop() {
// Publish the calculated dew point
this->publish_state(dew_point);
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", this->get_name().c_str(), dew_point, this->temperature_value_,
this->humidity_value_);
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", LOG_STR_ARG(this->get_log_name()), dew_point,
this->temperature_value_, this->humidity_value_);
}
} // namespace esphome::dew_point
@@ -36,7 +36,7 @@ void DutyCycleSensor::update() {
const float total_time = float(now - this->last_update_);
const float value = (on_time * 100.0f) / total_time;
ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", this->get_name().c_str(), value);
ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", LOG_STR_ARG(this->get_log_name()), value);
this->publish_state(value);
}
this->last_update_ = now;
+3 -3
View File
@@ -70,20 +70,20 @@ void EndstopCover::loop() {
if (this->current_operation == COVER_OPERATION_OPENING && this->is_open_()) {
float dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - Open endstop reached. Took %.1fs.", this->name_.c_str(), dur);
ESP_LOGD(TAG, "'%s' - Open endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
this->start_direction_(COVER_OPERATION_IDLE);
this->position = COVER_OPEN;
this->publish_state();
} else if (this->current_operation == COVER_OPERATION_CLOSING && this->is_closed_()) {
float dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - Close endstop reached. Took %.1fs.", this->name_.c_str(), dur);
ESP_LOGD(TAG, "'%s' - Close endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
this->start_direction_(COVER_OPERATION_IDLE);
this->position = COVER_CLOSED;
this->publish_state();
} else if (now - this->start_dir_time_ > this->max_duration_) {
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
this->start_direction_(COVER_OPERATION_IDLE);
this->publish_state();
}
@@ -132,9 +132,9 @@ void ESP32Camera::dump_config() {
" External Clock: Pin:%d Frequency:%u\n"
" I2C Pins: SDA:%d SCL:%d\n"
" Reset Pin: %d",
this->name_.c_str(), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2, conf.pin_d3,
conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href, conf.pin_pclk,
conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset);
LOG_STR_ARG(this->get_log_name()), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2,
conf.pin_d3, conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href,
conf.pin_pclk, conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset);
ESP_LOGCONFIG(TAG, " Resolution: %s", frame_size_to_str(this->config_.frame_size));
ESP_LOGCONFIG(TAG, " Pixel Format: %s", pixel_format_to_str(this->config_.pixel_format));
@@ -425,7 +425,7 @@ esp_err_t esp_now_send(const uint8_t *peer_addr, const uint8_t *data, size_t len
// task, and a shared build buffer here would let two callers corrupt each
// other's frame. Passing the body through also drops a full-frame copy per
// transmit, on the path this shim exists to keep quick.
uint8_t hdr[sizeof(esp_now_hosted_send_req_t)];
uint8_t hdr[sizeof(esp_now_hosted_send_req_t)] = {};
auto *s = reinterpret_cast<esp_now_hosted_send_req_t *>(hdr);
s->has_addr = peer_addr != nullptr ? 1 : 0;
if (peer_addr != nullptr) {
@@ -26,9 +26,14 @@ ESPHOME_LOG_TAG(TAG, "esp32_hosted.update");
// Older coprocessor firmware versions have a 1500-byte limit per RPC call
constexpr size_t CHUNK_SIZE = 1500;
// OTA begin blocks while the coprocessor erases its partition
// OTA begin blocks while the coprocessor erases its partition, end while it validates the image
constexpr uint32_t OTA_WDT_TIMEOUT_MS = 60000;
static esp_err_t ota_end_guarded() {
watchdog::WatchdogManager wdt(OTA_WDT_TIMEOUT_MS);
return esp_hosted_slave_ota_end(); // NOLINT
}
#ifdef USE_ESP32_HOSTED_HTTP_UPDATE
// Interval/timeout IDs (uint32_t to avoid string comparison)
constexpr uint32_t INITIAL_CHECK_INTERVAL_ID = 0;
@@ -380,7 +385,7 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() {
} else {
ESP_LOGE(TAG, "Error reading firmware data: %d", read_or_error);
}
esp_hosted_slave_ota_end(); // NOLINT
ota_end_guarded();
container->end();
this->status_set_error(LOG_STR("Download failed"));
return false;
@@ -390,7 +395,7 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() {
err = esp_hosted_slave_ota_write(buffer, read_or_error); // NOLINT
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(err));
esp_hosted_slave_ota_end(); // NOLINT
ota_end_guarded();
container->end();
this->status_set_error(LOG_STR("Failed to write OTA data"));
return false;
@@ -402,7 +407,7 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() {
hasher.calculate();
if (!hasher.equals_bytes(this->firmware_sha256_.data())) {
ESP_LOGE(TAG, "SHA256 mismatch");
esp_hosted_slave_ota_end(); // NOLINT
ota_end_guarded();
this->status_set_error(LOG_STR("SHA256 verification failed"));
return false;
}
@@ -451,7 +456,7 @@ bool Esp32HostedUpdate::write_embedded_firmware_to_coprocessor_() {
err = esp_hosted_slave_ota_write(chunk, chunk_size); // NOLINT
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(err));
esp_hosted_slave_ota_end(); // NOLINT
ota_end_guarded();
this->status_set_error(LOG_STR("Failed to write OTA data"));
return false;
}
@@ -494,7 +499,7 @@ void Esp32HostedUpdate::perform(bool force) {
}
// End OTA and activate new firmware
esp_err_t end_err = esp_hosted_slave_ota_end(); // NOLINT
esp_err_t end_err = ota_end_guarded();
if (end_err != ESP_OK) {
ESP_LOGE(TAG, "Failed to end OTA: %s", esp_err_to_name(end_err));
this->state_ = prev_state;
@@ -341,13 +341,13 @@ void ESP32TouchComponent::loop() {
child->publish_state(new_state);
#ifdef USE_ESP32_VARIANT_ESP32
ESP_LOGV(TAG, "Touch Pad '%s' state: %s (value: %" PRIu32 ", threshold: %" PRIu32 ")",
child->get_name().c_str(), ONOFF(new_state), value, child->get_threshold());
LOG_STR_ARG(child->get_log_name()), ONOFF(new_state), value, child->get_threshold());
#else
if (new_state) {
ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 ", benchmark: %" PRIu32 ", threshold: %" PRIu32 ")",
child->get_name().c_str(), value, benchmark, child->get_threshold());
LOG_STR_ARG(child->get_log_name()), value, benchmark, child->get_threshold());
} else {
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", child->get_name().c_str());
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", LOG_STR_ARG(child->get_log_name()));
}
#endif
}
@@ -470,7 +470,8 @@ void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) {
child->value_ = smooth_value;
#ifdef USE_ESP32_VARIANT_ESP32
ESP_LOGD(TAG, "Touch Pad '%s' (Ch%d): %" PRIu32, child->get_name().c_str(), child->channel_id_, smooth_value);
ESP_LOGD(TAG, "Touch Pad '%s' (Ch%d): %" PRIu32, LOG_STR_ARG(child->get_log_name()), child->channel_id_,
smooth_value);
#else
uint32_t benchmark = 0;
touch_channel_read_data(child->chan_handle_, TOUCH_CHAN_DATA_TYPE_BENCHMARK, &benchmark);
@@ -479,7 +480,7 @@ void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) {
ESP_LOGD(TAG,
"Touch Pad '%s' (Ch%d): value=%" PRIu32 ", benchmark=%" PRIu32 ", difference=%" PRId32
" (set threshold < %" PRId32 " to detect touch)",
child->get_name().c_str(), child->channel_id_, smooth_value, benchmark, difference, difference);
LOG_STR_ARG(child->get_log_name()), child->channel_id_, smooth_value, benchmark, difference, difference);
#endif
}
this->setup_mode_last_log_print_ = now;
@@ -491,7 +492,7 @@ void ESP32TouchComponent::publish_initial_state_if_needed_(ESP32TouchBinarySenso
if (now > INITIAL_STATE_DELAY_MS) {
child->publish_initial_state(false);
child->initial_state_published_ = true;
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", child->get_name().c_str());
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", LOG_STR_ARG(child->get_log_name()));
}
}
}
+4 -2
View File
@@ -48,7 +48,8 @@ static inline bool esp_rtc_user_mem_read(uint32_t index, uint32_t *dest) {
if (index >= ESP_RTC_USER_MEM_SIZE_WORDS) {
return false;
}
*dest = ESP_RTC_USER_MEM[index]; // NOLINT(performance-no-int-to-ptr,clang-analyzer-core.FixedAddressDereference)
// NOLINTNEXTLINE(performance-no-int-to-ptr,clang-analyzer-core.FixedAddressDereference,clang-analyzer-optin.core.FixedAddressDereference)
*dest = ESP_RTC_USER_MEM[index];
return true;
}
@@ -61,7 +62,8 @@ static inline bool esp_rtc_user_mem_write(uint32_t index, uint32_t value) {
}
auto *ptr = &ESP_RTC_USER_MEM[index]; // NOLINT(performance-no-int-to-ptr)
*ptr = value; // NOLINT(clang-analyzer-core.FixedAddressDereference)
// NOLINTNEXTLINE(clang-analyzer-core.FixedAddressDereference,clang-analyzer-optin.core.FixedAddressDereference)
*ptr = value;
return true;
}
+2 -2
View File
@@ -17,11 +17,11 @@ void Event::trigger(const char *event_type) {
}
}
if (found == nullptr) {
ESP_LOGE(TAG, "'%s': invalid event type for trigger(): %s", this->get_name().c_str(), event_type);
ESP_LOGE(TAG, "'%s': invalid event type for trigger(): %s", LOG_STR_ARG(this->get_log_name()), event_type);
return;
}
this->last_event_type_ = found;
ESP_LOGV(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->last_event_type_);
ESP_LOGV(TAG, "'%s' >> '%s'", LOG_STR_ARG(this->get_log_name()), this->last_event_type_);
this->event_callback_.call(StringRef(found));
#if defined(USE_EVENT) && defined(USE_CONTROLLER_REGISTRY)
ControllerRegistry::notify_event(this);
+7 -6
View File
@@ -42,14 +42,15 @@ FanCall &FanCall::set_preset_mode(const char *preset_mode, size_t len) {
this->preset_mode_ = validated_mode; // Store pointer from traits
} else {
// Preset mode not found in traits - log warning and don't set
ESP_LOGW(TAG, "%s: Preset mode '%.*s' not supported", this->parent_.get_name().c_str(), (int) len, preset_mode);
ESP_LOGW(TAG, "%s: Preset mode '%.*s' not supported", LOG_STR_ARG(this->parent_.get_log_name()), (int) len,
preset_mode);
this->preset_mode_ = nullptr;
}
return *this;
}
void FanCall::perform() {
ESP_LOGV(TAG, "'%s' - Setting:", this->parent_.get_name().c_str());
ESP_LOGV(TAG, "'%s' - Setting:", LOG_STR_ARG(this->parent_.get_log_name()));
this->validate_();
if (this->binary_state_.has_value()) {
ESP_LOGV(TAG, " State: %s", ONOFF(*this->binary_state_));
@@ -93,17 +94,17 @@ void FanCall::validate_() {
}
if (this->oscillating_.has_value() && !traits.supports_oscillation()) {
ESP_LOGW(TAG, "%s: Oscillation not supported", this->parent_.get_name().c_str());
ESP_LOGW(TAG, "%s: Oscillation not supported", LOG_STR_ARG(this->parent_.get_log_name()));
this->oscillating_.reset();
}
if (this->speed_.has_value() && !traits.supports_speed()) {
ESP_LOGW(TAG, "%s: Speed control not supported", this->parent_.get_name().c_str());
ESP_LOGW(TAG, "%s: Speed control not supported", LOG_STR_ARG(this->parent_.get_log_name()));
this->speed_.reset();
}
if (this->direction_.has_value() && !traits.supports_direction()) {
ESP_LOGW(TAG, "%s: Direction control not supported", this->parent_.get_name().c_str());
ESP_LOGW(TAG, "%s: Direction control not supported", LOG_STR_ARG(this->parent_.get_log_name()));
this->direction_.reset();
}
}
@@ -207,7 +208,7 @@ void Fan::publish_state() {
ESP_LOGV(TAG,
"'%s' >>\n"
" State: %s",
this->name_.c_str(), ONOFF(this->state));
LOG_STR_ARG(this->get_log_name()), ONOFF(this->state));
if (traits.supports_speed()) {
ESP_LOGV(TAG, " Speed: %d", this->speed);
}
+10 -10
View File
@@ -98,7 +98,7 @@ void FeedbackCover::set_open_sensor(binary_sensor::BinarySensor *open_feedback)
// setup callbacks to react to sensor changes
open_feedback->add_on_state_callback([this](bool state) {
ESP_LOGD(TAG, "'%s' - Open feedback '%s'.", this->name_.c_str(),
ESP_LOGD(TAG, "'%s' - Open feedback '%s'.", LOG_STR_ARG(this->get_log_name()),
state ? LOG_STR_LITERAL("STARTED") : LOG_STR_LITERAL("ENDED"));
this->recompute_position_();
if (!state && this->infer_endstop_ && this->current_trigger_operation_ == COVER_OPERATION_OPENING) {
@@ -112,7 +112,7 @@ void FeedbackCover::set_close_sensor(binary_sensor::BinarySensor *close_feedback
this->close_feedback_ = close_feedback;
close_feedback->add_on_state_callback([this](bool state) {
ESP_LOGD(TAG, "'%s' - Close feedback '%s'.", this->name_.c_str(),
ESP_LOGD(TAG, "'%s' - Close feedback '%s'.", LOG_STR_ARG(this->get_log_name()),
state ? LOG_STR_LITERAL("STARTED") : LOG_STR_LITERAL("ENDED"));
this->recompute_position_();
if (!state && this->infer_endstop_ && this->current_trigger_operation_ == COVER_OPERATION_CLOSING) {
@@ -151,7 +151,7 @@ void FeedbackCover::endstop_reached_(bool open_endstop) {
// from a position slightly past the endpoint
if (this->current_trigger_operation_ == (open_endstop ? COVER_OPERATION_OPENING : COVER_OPERATION_CLOSING)) {
float dur = (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", this->name_.c_str(),
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()),
open_endstop ? LOG_STR_LITERAL("Open") : LOG_STR_LITERAL("Close"), dur);
// if there is no external mechanism, stop the cover
@@ -198,7 +198,7 @@ void FeedbackCover::set_close_obstacle_sensor(binary_sensor::BinarySensor *close
close_obstacle->add_on_state_callback([this](bool state) {
if (state && (this->current_operation == COVER_OPERATION_CLOSING ||
this->current_trigger_operation_ == COVER_OPERATION_CLOSING)) {
ESP_LOGD(TAG, "'%s' - Close obstacle detected.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Close obstacle detected.", LOG_STR_ARG(this->get_log_name()));
this->start_direction_(COVER_OPERATION_IDLE);
if (this->obstacle_rollback_) {
@@ -215,7 +215,7 @@ void FeedbackCover::set_open_obstacle_sensor(binary_sensor::BinarySensor *open_o
open_obstacle->add_on_state_callback([this](bool state) {
if (state && (this->current_operation == COVER_OPERATION_OPENING ||
this->current_trigger_operation_ == COVER_OPERATION_OPENING)) {
ESP_LOGD(TAG, "'%s' - Open obstacle detected.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Open obstacle detected.", LOG_STR_ARG(this->get_log_name()));
this->start_direction_(COVER_OPERATION_IDLE);
if (this->obstacle_rollback_) {
@@ -251,7 +251,7 @@ void FeedbackCover::loop() {
this->start_overshoot_time_ = now;
} else if (now - this->start_overshoot_time_ > this->overshoot_duration_ ||
now - this->start_dir_time_ > this->max_duration_) {
ESP_LOGD(TAG, "'%s' - Overshoot duration reached. Stopping cover.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Overshoot duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
this->start_direction_(COVER_OPERATION_IDLE);
}
#endif
@@ -259,7 +259,7 @@ void FeedbackCover::loop() {
this->start_direction_(COVER_OPERATION_IDLE);
}
} else if (now - this->start_dir_time_ > this->max_duration_) {
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
this->start_direction_(COVER_OPERATION_IDLE);
}
}
@@ -390,7 +390,7 @@ void FeedbackCover::start_direction_(CoverOperation dir) {
// check if there is an obstacle to start the new operation -> abort without any change
// the case when an obstacle appears while moving is handled in the callback
if (obstacle != nullptr && obstacle->state) {
ESP_LOGD(TAG, "'%s' - %s obstacle detected. Action not started.", this->name_.c_str(),
ESP_LOGD(TAG, "'%s' - %s obstacle detected. Action not started.", LOG_STR_ARG(this->get_log_name()),
dir == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("Open") : LOG_STR_LITERAL("Close"));
return;
}
@@ -401,13 +401,13 @@ void FeedbackCover::start_direction_(CoverOperation dir) {
if (this->direction_change_waittime_.has_value() && dir != COVER_OPERATION_IDLE &&
this->current_operation != COVER_OPERATION_IDLE && dir != this->current_operation) {
const uint32_t waittime = *this->direction_change_waittime_;
ESP_LOGD(TAG, "'%s' - Reversing direction.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Reversing direction.", LOG_STR_ARG(this->get_log_name()));
this->start_direction_(COVER_OPERATION_IDLE);
this->set_timeout(DIRECTION_CHANGE_TIMEOUT_ID, waittime, [this, dir]() { this->start_direction_(dir); });
} else {
this->set_current_operation_(dir, true);
this->prev_command_trigger_ = trig;
ESP_LOGD(TAG, "'%s' - Firing '%s' trigger.", this->name_.c_str(),
ESP_LOGD(TAG, "'%s' - Firing '%s' trigger.", LOG_STR_ARG(this->get_log_name()),
dir == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("OPEN")
: dir == COVER_OPERATION_CLOSING ? LOG_STR_LITERAL("CLOSE")
: LOG_STR_LITERAL("STOP"));
@@ -28,7 +28,7 @@ void GPIOSwitch::dump_config() {
for (auto *lock : this->interlock_) {
if (lock == this)
continue;
ESP_LOGCONFIG(TAG, " %s", lock->get_name().c_str());
ESP_LOGCONFIG(TAG, " %s", LOG_STR_ARG(lock->get_log_name()));
}
}
#endif
+3 -3
View File
@@ -58,7 +58,7 @@ void HE60rCover::endstop_reached_(CoverOperation operation) {
this->current_operation = COVER_OPERATION_IDLE;
if (this->last_command_ == operation) {
float dur = (float) (now - this->start_dir_time_) / 1e3f;
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", this->name_.c_str(),
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()),
operation == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("Open") : LOG_STR_LITERAL("Close"), dur);
}
this->publish_state();
@@ -207,7 +207,7 @@ void HE60rCover::start_direction_(CoverOperation dir) {
this->last_command_ = dir;
if (this->current_operation == dir)
return;
ESP_LOGD(TAG, "'%s' - Direction '%s' requested.", this->name_.c_str(),
ESP_LOGD(TAG, "'%s' - Direction '%s' requested.", LOG_STR_ARG(this->get_log_name()),
dir == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("OPEN")
: dir == COVER_OPERATION_CLOSING ? LOG_STR_LITERAL("CLOSE")
: LOG_STR_LITERAL("STOP"));
@@ -223,7 +223,7 @@ void HE60rCover::start_direction_(CoverOperation dir) {
// just stop and reverse
this->toggles_needed_ = 2;
}
ESP_LOGD(TAG, "'%s' - Reversing direction.", this->name_.c_str());
ESP_LOGD(TAG, "'%s' - Reversing direction.", LOG_STR_ARG(this->get_log_name()));
}
this->start_dir_time_ = millis();
}
+1 -2
View File
@@ -1,5 +1,6 @@
import esphome.codegen as cg
from esphome.components import climate_ir
from esphome.components.const import CONF_HORIZONTAL_DEFAULT, CONF_VERTICAL_DEFAULT
import esphome.config_validation as cv
from esphome.const import (
CONF_MAX_TEMPERATURE,
@@ -76,13 +77,11 @@ PROTOCOLS = {
"r51m": Protocol.PROTOCOL_R51M,
}
CONF_HORIZONTAL_DEFAULT = "horizontal_default"
HorizontalDirections = heatpumpir_ns.enum("HorizontalDirections")
HORIZONTAL_DIRECTIONS = HorizontalDirections.options(
"auto", "middle", "left", "mleft", "mright", "right", prefix="HORIZONTAL_DIRECTION_"
)
CONF_VERTICAL_DEFAULT = "vertical_default"
VerticalDirections = heatpumpir_ns.enum("VerticalDirections")
VERTICAL_DIRECTIONS = VerticalDirections.options(
"auto", "up", "mup", "middle", "mdown", "down", prefix="VERTICAL_DIRECTION_"
@@ -27,7 +27,7 @@ void HomeassistantButton::press_action() {
#ifdef USE_API_WIZARD_LINKED_INPUTS
if (this->entity_id_[0] == '\0') {
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
return;
}
#endif
@@ -408,7 +408,7 @@ void HomeassistantLight::write_state(LightState *state) {
}
#ifdef USE_API_WIZARD_LINKED_INPUTS
if (this->entity_id_[0] == '\0') {
ESP_LOGW(TAG, "'%s': No entity ID set yet", state->get_name().c_str());
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(state->get_log_name()));
this->fall_back_();
return;
}
@@ -32,7 +32,7 @@ void HomeassistantNumber::min_retrieved_(StringRef min) {
ESP_LOGE(TAG, "'%s': Can't convert 'min' value '%s' to number!", this->entity_id_, min.c_str());
return;
}
ESP_LOGD(TAG, "'%s': Min retrieved: %s", get_name().c_str(), min.c_str());
ESP_LOGD(TAG, "'%s': Min retrieved: %s", LOG_STR_ARG(this->get_log_name()), min.c_str());
this->traits.set_min_value(min_value.value());
}
@@ -42,7 +42,7 @@ void HomeassistantNumber::max_retrieved_(StringRef max) {
ESP_LOGE(TAG, "'%s': Can't convert 'max' value '%s' to number!", this->entity_id_, max.c_str());
return;
}
ESP_LOGD(TAG, "'%s': Max retrieved: %s", get_name().c_str(), max.c_str());
ESP_LOGD(TAG, "'%s': Max retrieved: %s", LOG_STR_ARG(this->get_log_name()), max.c_str());
this->traits.set_max_value(max_value.value());
}
@@ -52,7 +52,7 @@ void HomeassistantNumber::step_retrieved_(StringRef step) {
ESP_LOGE(TAG, "'%s': Can't convert 'step' value '%s' to number!", this->entity_id_, step.c_str());
return;
}
ESP_LOGD(TAG, "'%s': Step Retrieved %s", get_name().c_str(), step.c_str());
ESP_LOGD(TAG, "'%s': Step Retrieved %s", LOG_STR_ARG(this->get_log_name()), step.c_str());
this->traits.set_step(step_value.value());
}
@@ -83,7 +83,7 @@ void HomeassistantNumber::control(float value) {
#ifdef USE_API_WIZARD_LINKED_INPUTS
if (this->entity_id_[0] == '\0') {
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
return;
}
#endif
@@ -123,7 +123,7 @@ void HomeassistantSelect::control(size_t index) {
#ifdef USE_API_WIZARD_LINKED_INPUTS
if (this->entity_id_[0] == '\0') {
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
return;
}
#endif
@@ -43,7 +43,7 @@ void HomeassistantSwitch::write_state(bool state) {
#ifdef USE_API_WIZARD_LINKED_INPUTS
if (this->entity_id_[0] == '\0') {
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
return;
}
#endif
@@ -82,7 +82,7 @@ void HomeassistantText::control(const std::string &value) {
#ifdef USE_API_WIZARD_LINKED_INPUTS
if (this->entity_id_[0] == '\0') {
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
return;
}
#endif
+1 -1
View File
@@ -25,7 +25,7 @@ void HX711Sensor::update() {
uint32_t result;
if (this->read_sensor_(&result)) {
int32_t value = static_cast<int32_t>(result);
ESP_LOGD(TAG, "'%s': Got value %" PRId32, this->name_.c_str(), value);
ESP_LOGD(TAG, "'%s': Got value %" PRId32, LOG_STR_ARG(this->get_log_name()), value);
this->publish_state(value);
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ void Infrared::dump_config() {
"Infrared '%s'\n"
" Supports Transmitter: %s\n"
" Supports Receiver: %s",
this->get_name().c_str(), YESNO(this->get_supports_transmitter()),
LOG_STR_ARG(this->get_log_name()), YESNO(this->get_supports_transmitter()),
YESNO(this->get_supports_receiver()));
}
+4 -3
View File
@@ -143,7 +143,7 @@ bool IrRfEntity::expect_api_reply_(api::APIConnection *conn) {
if (this->api_reply_ == ApiReply::API_REPLY_WAITING)
this->finish_api_reply_(false);
if (this->api_reply_ != ApiReply::API_REPLY_NONE && !this->send_api_reply_()) {
ESP_LOGW(TAG, "'%s': transmit %s", this->get_name().c_str(), LOG_STR_LITERAL("refused, reply still owed"));
ESP_LOGW(TAG, "'%s': transmit %s", LOG_STR_ARG(this->get_log_name()), LOG_STR_LITERAL("refused, reply still owed"));
this->refuse_api_call_(conn);
return false;
}
@@ -198,13 +198,14 @@ void IrRfEntity::loop() {
if (this->api_reply_ != ApiReply::API_REPLY_WAITING) {
if (this->send_api_reply_() || remaining > 0)
return;
ESP_LOGW(TAG, "'%s': transmit %s", this->get_name().c_str(), LOG_STR_LITERAL("reply dropped, client not reading"));
ESP_LOGW(TAG, "'%s': transmit %s", LOG_STR_ARG(this->get_log_name()),
LOG_STR_LITERAL("reply dropped, client not reading"));
this->clear_api_reply_();
return;
}
if (remaining > 0)
return;
ESP_LOGW(TAG, "'%s': transmit %s", this->get_name().c_str(), LOG_STR_LITERAL("never reported completion"));
ESP_LOGW(TAG, "'%s': transmit %s", LOG_STR_ARG(this->get_log_name()), LOG_STR_LITERAL("never reported completion"));
this->finish_api_reply_(false);
}
@@ -17,7 +17,7 @@ void IrRfProxy::dump_config() {
"IR Proxy '%s'\n"
" Supports Transmitter: %s\n"
" Supports Receiver: %s",
this->get_name().c_str(), YESNO(this->get_supports_transmitter()),
LOG_STR_ARG(this->get_log_name()), YESNO(this->get_supports_transmitter()),
YESNO(this->get_supports_receiver()));
if (this->is_rf()) {
@@ -44,7 +44,7 @@ void RfProxy::dump_config() {
"RF Proxy '%s'\n"
" Supports Transmitter: %s\n"
" Supports Receiver: %s",
this->get_name().c_str(), YESNO(this->get_supports_transmitter()),
LOG_STR_ARG(this->get_log_name()), YESNO(this->get_supports_transmitter()),
YESNO(this->get_supports_receiver()));
const auto &traits = this->traits_;
+5 -5
View File
@@ -4,6 +4,7 @@
#include <cstddef>
#include <cstring>
#include <string>
#include <utility>
#include <vector>
#include "esphome/core/defines.h"
@@ -50,15 +51,15 @@ template<size_t STACK_SIZE = 640> class SerializationBuffer {
~SerializationBuffer() { delete[] heap_buffer_; }
// Move constructor - works with same template instantiation
SerializationBuffer(SerializationBuffer &&other) noexcept : heap_buffer_(other.heap_buffer_), size_(other.size_) {
SerializationBuffer(SerializationBuffer &&other) noexcept
: heap_buffer_(std::exchange(other.heap_buffer_, nullptr)), size_(other.size_) {
if (other.buffer_ == other.stack_buffer_) {
// Stack buffer - must copy content
std::memcpy(stack_buffer_, other.stack_buffer_, size_ + 1);
buffer_ = stack_buffer_;
} else {
// Heap buffer - steal ownership
// Heap buffer - ownership was taken above
buffer_ = heap_buffer_;
other.heap_buffer_ = nullptr;
}
// Leave moved-from object in valid empty state
other.stack_buffer_[0] = '\0';
@@ -70,14 +71,13 @@ template<size_t STACK_SIZE = 640> class SerializationBuffer {
SerializationBuffer &operator=(SerializationBuffer &&other) noexcept {
if (this != &other) {
delete[] heap_buffer_;
heap_buffer_ = other.heap_buffer_;
heap_buffer_ = std::exchange(other.heap_buffer_, nullptr);
size_ = other.size_;
if (other.buffer_ == other.stack_buffer_) {
std::memcpy(stack_buffer_, other.stack_buffer_, size_ + 1);
buffer_ = stack_buffer_;
} else {
buffer_ = heap_buffer_;
other.heap_buffer_ = nullptr;
}
// Leave moved-from object in valid empty state
other.stack_buffer_[0] = '\0';
+4 -4
View File
@@ -15,7 +15,7 @@ void PolygonZone::setup() {
if (saved.is_valid()) {
this->polygon_ = saved;
} else {
ESP_LOGW(TAG, "'%s': saved polygon is invalid; zone disabled", this->get_name().c_str());
ESP_LOGW(TAG, "'%s': saved polygon is invalid; zone disabled", LOG_STR_ARG(this->get_log_name()));
}
}
// Presence stays unknown until the first radar frame
@@ -33,11 +33,11 @@ void PolygonZone::dump_config() {
void PolygonZone::control(const std::string &value) {
Polygon polygon;
if (!polygon.parse(value.c_str(), value.size())) {
ESP_LOGW(TAG, "'%s': invalid polygon '%s'; expected 'x,y;x,y;...' with %u to %u points", this->get_name().c_str(),
value.c_str(), MIN_POLYGON_POINTS, MAX_POLYGON_POINTS);
ESP_LOGW(TAG, "'%s': invalid polygon '%s'; expected 'x,y;x,y;...' with %u to %u points",
LOG_STR_ARG(this->get_log_name()), value.c_str(), MIN_POLYGON_POINTS, MAX_POLYGON_POINTS);
} else if (!this->pref_.save(&polygon)) {
// On ESP8266, the space for saved settings is small and can run out with several zones
ESP_LOGW(TAG, "'%s': could not save the polygon; keeping the previous one", this->get_name().c_str());
ESP_LOGW(TAG, "'%s': could not save the polygon; keeping the previous one", LOG_STR_ARG(this->get_log_name()));
} else {
this->polygon_ = polygon;
// A target seen inside the previous polygon must not keep the new one on
+2 -2
View File
@@ -1041,8 +1041,8 @@ void LD6002BComponent::publish_number_clamped_(number::Number *number, float val
// Outside the declared range the user cannot write the value back, so publish
// what they can reach and say what the module actually sent.
if (value < min_value || value > max_value) {
ESP_LOGW(TAG, "'%s': module reported %.1f, clamped to %.1f..%.1f", number->get_name().c_str(), value, min_value,
max_value);
ESP_LOGW(TAG, "'%s': module reported %.1f, clamped to %.1f..%.1f", LOG_STR_ARG(number->get_log_name()), value,
min_value, max_value);
value = std::clamp(value, min_value, max_value);
}
number->publish_state(value);

Some files were not shown because too many files have changed in this diff Show More