Compare commits

..

2119 Commits

Author SHA1 Message Date
J. Nick Koston
0824c21841 pool for scheduler 2025-07-28 08:08:53 -10:00
J. Nick Koston
226d465f6a Merge branch 'integration' into memory_api 2025-07-27 18:50:05 -10:00
J. Nick Koston
2123e778e5 Merge branch 'protosize_object' into integration 2025-07-27 18:49:51 -10:00
J. Nick Koston
14744fc381 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-27 18:49:43 -10:00
J. Nick Koston
ab643350f5 Merge remote-tracking branch 'upstream/dev' into protosize_object 2025-07-27 18:46:54 -10:00
J. Nick Koston
81cea0b2eb Merge branch 'integration' into memory_api 2025-07-27 11:36:35 -10:00
J. Nick Koston
44ec2b37af Merge branch 'unspec_string_copies' into integration 2025-07-27 11:36:28 -10:00
J. Nick Koston
0fa9704675 [core] Use nullptr defaults in status_set_error/warning to reduce flash usage 2025-07-27 11:25:42 -10:00
J. Nick Koston
0f5aff4d21 Merge branch 'integration' into memory_api 2025-07-27 11:08:21 -10:00
J. Nick Koston
d56ff40952 Merge branch 'retry_string_cleanup' into integration 2025-07-27 11:08:12 -10:00
J. Nick Koston
4fc6ef6d3e cover 2025-07-27 10:54:57 -10:00
J. Nick Koston
6c8df02d9c [core] Optimize scheduler retry mechanism to reduce flash usage 2025-07-27 10:45:35 -10:00
J. Nick Koston
e3b3259243 Merge branch 'integration' into memory_api 2025-07-26 22:15:15 -10:00
J. Nick Koston
0d23476a1d Merge branch 'light_opt_part2' into integration 2025-07-26 22:15:06 -10:00
J. Nick Koston
4f28aacf66 fix 2025-07-26 22:11:48 -10:00
J. Nick Koston
5769fbc3b6 fix 2025-07-26 22:10:17 -10:00
J. Nick Koston
9cf0535d39 Merge branch 'integration' into memory_api 2025-07-26 21:55:34 -10:00
J. Nick Koston
52b04611ba Merge branch 'light_opt_part2' into integration 2025-07-26 21:55:23 -10:00
J. Nick Koston
bcdfc744c6 missed existing helper 2025-07-26 21:48:53 -10:00
J. Nick Koston
e223a1008b missed existing helper 2025-07-26 21:46:54 -10:00
J. Nick Koston
b7d48284ac missed existing helper 2025-07-26 21:44:31 -10:00
J. Nick Koston
de3e9451dc missed existing helper 2025-07-26 21:43:53 -10:00
J. Nick Koston
eb25ff0de7 Merge branch 'integration' into memory_api 2025-07-26 21:38:04 -10:00
J. Nick Koston
fa4a52a0dc Merge branch 'light_opt_part2' into integration 2025-07-26 21:37:53 -10:00
J. Nick Koston
51de85b1c1 merge 2025-07-26 21:37:46 -10:00
J. Nick Koston
4f30fd9668 Merge branch 'integration' into memory_api 2025-07-26 21:36:16 -10:00
J. Nick Koston
c9995e5fac Merge branch 'light_opt_part2' into integration 2025-07-26 21:35:54 -10:00
J. Nick Koston
28dbf3bbcc revert 2025-07-26 21:32:34 -10:00
J. Nick Koston
29e61c8913 revert 2025-07-26 21:27:44 -10:00
J. Nick Koston
10434ac2a3 fixes 2025-07-26 21:24:24 -10:00
J. Nick Koston
92e9383164 light_opt_part2 2025-07-26 21:18:58 -10:00
J. Nick Koston
3a49215dd6 preen 2025-07-26 21:18:39 -10:00
J. Nick Koston
dc45bed048 preen 2025-07-26 21:15:53 -10:00
J. Nick Koston
8e6a053ead preen 2025-07-26 21:11:57 -10:00
J. Nick Koston
5cf89f8594 light2 2025-07-26 21:06:39 -10:00
J. Nick Koston
825f3eee70 light2 2025-07-26 21:04:39 -10:00
J. Nick Koston
eec31846e1 Revert "Revert "light2""
This reverts commit b99b0140ae.
2025-07-26 20:50:50 -10:00
J. Nick Koston
b99b0140ae Revert "light2"
This reverts commit af7e43bbc1.
2025-07-26 20:49:51 -10:00
J. Nick Koston
af7e43bbc1 light2 2025-07-26 20:45:21 -10:00
J. Nick Koston
52750f931b light2 2025-07-26 20:42:45 -10:00
J. Nick Koston
446e9bc529 Merge branch 'integration' into memory_api 2025-07-26 20:26:28 -10:00
J. Nick Koston
6c44392359 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-26 20:26:16 -10:00
J. Nick Koston
d9f3ecd1a3 Merge branch 'integration' into memory_api 2025-07-26 17:14:24 -10:00
J. Nick Koston
3ec6b9d1a4 Merge branch 'light_flash' into integration 2025-07-26 17:14:09 -10:00
J. Nick Koston
2d237d0f97 fixes 2025-07-26 17:13:59 -10:00
J. Nick Koston
f9d0fa1c6d Merge branch 'integration' into memory_api 2025-07-26 17:09:53 -10:00
J. Nick Koston
75525349c7 Merge branch 'light_flash' into integration 2025-07-26 17:09:44 -10:00
J. Nick Koston
79984a288e preen 2025-07-26 17:06:39 -10:00
J. Nick Koston
f333ab1fd7 cover 2025-07-26 17:01:02 -10:00
J. Nick Koston
5bdd850012 reduce light flash 2025-07-26 16:59:57 -10:00
J. Nick Koston
6e345c5f23 dry 2025-07-26 15:03:36 -10:00
J. Nick Koston
5ebce4a901 dry 2025-07-26 15:01:45 -10:00
J. Nick Koston
a82b5fa87a dry 2025-07-26 15:01:07 -10:00
J. Nick Koston
193a85eb1c dry 2025-07-26 14:57:50 -10:00
J. Nick Koston
0773fc320b dry 2025-07-26 14:57:42 -10:00
J. Nick Koston
32edc3f062 dry 2025-07-26 14:54:52 -10:00
J. Nick Koston
ae12097636 dry 2025-07-26 14:53:14 -10:00
J. Nick Koston
2e16b3ea31 dry 2025-07-26 14:52:15 -10:00
J. Nick Koston
d98a3fca96 dry 2025-07-26 14:49:43 -10:00
J. Nick Koston
e94f5bffa3 preen 2025-07-26 14:45:26 -10:00
J. Nick Koston
09a30689e9 preen 2025-07-26 14:19:35 -10:00
J. Nick Koston
33ec5e195f Make ProtoSize an object 2025-07-26 14:09:17 -10:00
J. Nick Koston
1032e5c220 Make ProtoSize an object 2025-07-26 14:08:43 -10:00
J. Nick Koston
d111b84ca4 Make ProtoSize an object 2025-07-26 14:03:47 -10:00
J. Nick Koston
de6686ee14 Merge branch 'integration' into memory_api 2025-07-26 13:11:37 -10:00
J. Nick Koston
fd5805c54a Merge branch 'noise_key_flash' into integration 2025-07-26 13:11:19 -10:00
J. Nick Koston
32d6acb3b2 [api] Reduce code duplication in send_noise_encryption_set_key_response 2025-07-26 11:52:23 -10:00
J. Nick Koston
cab11086ac Merge branch 'integration' into memory_api 2025-07-25 23:38:30 -10:00
J. Nick Koston
c40a9eabef Merge branch 'services_must_make_copy' into integration 2025-07-25 23:38:17 -10:00
J. Nick Koston
17e1d3650c missed ha 2025-07-25 23:37:40 -10:00
J. Nick Koston
56b00f9bb7 Merge branch 'integration' into memory_api 2025-07-25 23:31:53 -10:00
J. Nick Koston
cfb4ef120f Merge remote-tracking branch 'upstream/dev' into integration 2025-07-25 23:31:43 -10:00
J. Nick Koston
eb2bfd4b70 Merge branch 'empty_messages' into integration 2025-07-25 23:31:37 -10:00
J. Nick Koston
91b46757b4 Merge remote-tracking branch 'upstream/dev' into empty_messages 2025-07-25 23:30:39 -10:00
J. Nick Koston
2d501e7b42 Merge branch 'dev' into services_must_make_copy 2025-07-25 23:27:43 -10:00
J. Nick Koston
01101380ee Merge branch 'integration' into memory_api 2025-07-25 23:15:42 -10:00
J. Nick Koston
eedcd818a9 Merge branch 'services_must_make_copy' into integration 2025-07-25 23:15:31 -10:00
J. Nick Koston
ab02f6da3d custom api 2025-07-25 23:15:24 -10:00
J. Nick Koston
90908996b1 Merge branch 'integration' into memory_api 2025-07-25 23:13:32 -10:00
J. Nick Koston
58d043ea0d Merge branch 'services_must_make_copy' into integration 2025-07-25 23:13:09 -10:00
J. Nick Koston
a57daa2656 Merge branch 'integration' into memory_api 2025-07-25 23:12:04 -10:00
J. Nick Koston
6bb6e475e7 Merge branch 'optional_api' into integration 2025-07-25 23:11:54 -10:00
J. Nick Koston
01b24a7b69 fix merge conflict 2025-07-25 23:11:11 -10:00
J. Nick Koston
5feb891e97 fix 2025-07-25 23:08:22 -10:00
J. Nick Koston
c32767db81 Merge branch 'dev' into optional_api 2025-07-25 23:06:10 -10:00
J. Nick Koston
0155769ffe [api] Fix string lifetime issue in Home Assistant service calls with templated values 2025-07-25 23:01:24 -10:00
J. Nick Koston
30b6a683c2 Merge branch 'integration' into memory_api 2025-07-25 21:39:46 -10:00
J. Nick Koston
7976c5e06c Merge branch 'api_ha_services' into memory_api 2025-07-25 21:39:38 -10:00
J. Nick Koston
50f770c600 Merge branch 'api_ha_services' into integration 2025-07-25 21:39:28 -10:00
J. Nick Koston
1cf5822bf5 Merge remote-tracking branch 'upstream/dev' into api_ha_services 2025-07-25 21:39:09 -10:00
J. Nick Koston
369b5e6c86 Merge branch 'dev' into optional_api 2025-07-25 21:36:44 -10:00
J. Nick Koston
f6ebdd79fe Merge branch 'dev' into empty_messages 2025-07-25 19:29:06 -10:00
J. Nick Koston
9010ddf56b [api] Optimize protobuf empty message handling to reduce flash and runtime overhead 2025-07-25 19:28:20 -10:00
J. Nick Koston
89c47c0dae Merge branch 'integration' into memory_api 2025-07-25 18:34:24 -10:00
J. Nick Koston
cae688446f Merge remote-tracking branch 'upstream/dependabot/pip/aioesphomeapi-37.1.0' into integration 2025-07-25 18:34:16 -10:00
dependabot[bot]
9bf666d63f Bump aioesphomeapi from 37.0.4 to 37.1.0
Bumps [aioesphomeapi](https://github.com/esphome/aioesphomeapi) from 37.0.4 to 37.1.0.
- [Release notes](https://github.com/esphome/aioesphomeapi/releases)
- [Commits](https://github.com/esphome/aioesphomeapi/compare/v37.0.4...v37.1.0)

---
updated-dependencies:
- dependency-name: aioesphomeapi
  dependency-version: 37.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-26 04:33:21 +00:00
J. Nick Koston
63e5a0b38c Merge branch 'integration' into memory_api 2025-07-25 18:28:03 -10:00
J. Nick Koston
09a24e0d88 Merge branch 'i2c_logging_fix' into integration 2025-07-25 18:27:54 -10:00
J. Nick Koston
de69e78a78 [i2c] Fix logging level for bus scan results in dump_config 2025-07-25 18:26:10 -10:00
J. Nick Koston
00266e080b merge 2025-07-25 17:39:48 -10:00
J. Nick Koston
9d4cf2543f Merge branch 'ble_chars' into integration 2025-07-25 17:39:24 -10:00
J. Nick Koston
967993f70d fix descriptor lookup 2025-07-25 17:39:14 -10:00
J. Nick Koston
711b153a6a revert 2025-07-25 17:32:30 -10:00
J. Nick Koston
ec9b10954c Merge branch 'integration' into memory_api 2025-07-25 17:25:55 -10:00
J. Nick Koston
c272e7282a Merge branch 'ble_chars' into integration 2025-07-25 17:25:47 -10:00
J. Nick Koston
5884bdb9e8 preen 2025-07-25 17:25:30 -10:00
J. Nick Koston
f0a63313b1 Merge branch 'integration' into memory_api 2025-07-25 17:22:54 -10:00
J. Nick Koston
15806fb95d Merge branch 'ble_chars' into integration 2025-07-25 17:22:40 -10:00
J. Nick Koston
d40a5a1651 preen 2025-07-25 17:21:38 -10:00
J. Nick Koston
535e995c75 preen 2025-07-25 17:20:37 -10:00
J. Nick Koston
6c825def9e Merge branch 'integration' into memory_api 2025-07-25 17:15:23 -10:00
J. Nick Koston
cb51c2e930 Merge branch 'ble_chars' into integration 2025-07-25 17:15:14 -10:00
J. Nick Koston
a06c4e1d56 cleanup 2025-07-25 17:14:56 -10:00
J. Nick Koston
793b3de3e9 revert 2025-07-25 16:50:36 -10:00
J. Nick Koston
60d988ca92 Merge branch 'ble_chars' into memory_api 2025-07-25 16:44:40 -10:00
J. Nick Koston
abf94e61f1 Revert "Revert "cleanup""
This reverts commit 7320cd24f0.
2025-07-25 16:43:28 -10:00
J. Nick Koston
7320cd24f0 Revert "cleanup"
This reverts commit 40a3232267.
2025-07-25 16:42:05 -10:00
J. Nick Koston
40a3232267 cleanup 2025-07-25 16:40:09 -10:00
J. Nick Koston
1d22bcac82 cleanup 2025-07-25 16:38:32 -10:00
J. Nick Koston
9dbcb2ea2e Merge branch 'integration' into memory_api 2025-07-25 16:17:31 -10:00
J. Nick Koston
cab19aed3d Merge branch 'ble_chars' into integration 2025-07-25 16:17:22 -10:00
J. Nick Koston
b22ff37e3d cleanup 2025-07-25 16:09:44 -10:00
J. Nick Koston
3396dfe52a cleanup 2025-07-25 16:08:22 -10:00
J. Nick Koston
accbc8fb0b cleanup 2025-07-25 16:07:46 -10:00
J. Nick Koston
5d8f38cce4 cleanup 2025-07-25 15:58:49 -10:00
J. Nick Koston
85a4f05d67 cleanup 2025-07-25 15:57:23 -10:00
J. Nick Koston
8a03e4c2cb cleanup 2025-07-25 15:56:00 -10:00
J. Nick Koston
e28c32af15 Merge branch 'integration' into memory_api 2025-07-25 15:37:20 -10:00
J. Nick Koston
4da9abe3fa Merge branch 'api_ha_services' into integration 2025-07-25 15:37:06 -10:00
J. Nick Koston
95b8321284 [api] Add conditional compilation for Home Assistant service subscriptions 2025-07-25 15:26:15 -10:00
J. Nick Koston
ce96c3c105 Merge branch 'integration' into memory_api 2025-07-25 14:48:21 -10:00
J. Nick Koston
3538cf936c Merge branch 'optional_api' into integration 2025-07-25 14:48:12 -10:00
J. Nick Koston
fd8c77c340 remove unneeded assertion 2025-07-25 14:48:00 -10:00
J. Nick Koston
6b49813084 Merge branch 'integration' into memory_api 2025-07-25 14:36:23 -10:00
J. Nick Koston
80407cf755 Merge branch 'missing_password_ifdefs' into integration 2025-07-25 14:36:01 -10:00
J. Nick Koston
ed379852fb cleanup 2025-07-25 14:35:47 -10:00
J. Nick Koston
662b5a452e Merge branch 'integration' into memory_api 2025-07-25 13:34:00 -10:00
J. Nick Koston
64d92fc92c Merge branch 'missing_password_ifdefs' into integration 2025-07-25 13:33:47 -10:00
J. Nick Koston
48128d965e make clang-tidy happy 2025-07-25 13:33:36 -10:00
J. Nick Koston
254c70a420 Merge branch 'integration' into memory_api 2025-07-25 13:28:11 -10:00
J. Nick Koston
5f9bd75954 Merge branch 'missing_password_ifdefs' into integration 2025-07-25 13:27:58 -10:00
J. Nick Koston
9ac38ff8d0 [api] Add missing USE_API_PASSWORD guards to reduce flash usage 2025-07-25 13:25:46 -10:00
J. Nick Koston
436ba20b7f Merge branch 'integration' into memory_api 2025-07-25 12:11:11 -10:00
J. Nick Koston
b89b1dfc29 Merge remote-tracking branch 'upstream/integration' into integration 2025-07-25 12:10:58 -10:00
J. Nick Koston
e7ea184709 preen 2025-07-25 12:10:41 -10:00
J. Nick Koston
b68f2b0ae4 Merge remote-tracking branch 'origin/memory_api' into memory_api 2025-07-25 12:08:26 -10:00
J. Nick Koston
4053a88c3a Merge branch 'integration' into memory_api 2025-07-25 12:08:13 -10:00
J. Nick Koston
9df3ad3567 Merge remote-tracking branch 'origin/homeassistant_states' into integration 2025-07-25 12:06:39 -10:00
J. Nick Koston
52df0a9412 Merge branch 'homeassistant_states' into integration 2025-07-25 12:05:59 -10:00
J. Nick Koston
9c4fc5d354 fixes 2025-07-25 11:59:13 -10:00
J. Nick Koston
1ac444a558 Merge remote-tracking branch 'origin/dev' into homeassistant_states 2025-07-25 11:55:29 -10:00
J. Nick Koston
90587583b4 [api] Add conditional compilation for Home Assistant state subscriptions 2025-07-25 11:55:07 -10:00
J. Nick Koston
0420bb3862 [api] Add conditional compilation for Home Assistant state subscriptions 2025-07-25 11:47:52 -10:00
J. Nick Koston
17dca4d761 Merge branch 'integration' into memory_api 2025-07-25 11:29:22 -10:00
J. Nick Koston
794db17e0f Merge remote-tracking branch 'upstream/optional_api' into integration 2025-07-25 11:29:10 -10:00
J. Nick Koston
91ec0f959e review comment 2025-07-25 11:27:01 -10:00
J. Nick Koston
066e4940e1 Merge branch 'integration' into memory_api 2025-07-25 11:02:11 -10:00
J. Nick Koston
88adbe7197 Merge branch 'optional_api' into integration 2025-07-25 11:02:01 -10:00
J. Nick Koston
3765058813 cover 2025-07-25 10:58:15 -10:00
J. Nick Koston
6cd2a80224 [api] Remove unnecessary string copies from optional access 2025-07-25 10:50:32 -10:00
J. Nick Koston
bacb6a2c11 Merge branch 'integration' into memory_api 2025-07-25 08:42:45 -10:00
J. Nick Koston
f248309a7f Merge branch 'start_end_setup' into integration 2025-07-25 08:42:32 -10:00
J. Nick Koston
76a63e5d55 Merge branch 'dev' into integration 2025-07-25 08:42:21 -10:00
J. Nick Koston
65f7426ceb keep mcp2515 since it has error flags 2025-07-24 22:08:59 -10:00
J. Nick Koston
9cd657e8f5 Apply suggestions from code review 2025-07-24 22:05:39 -10:00
J. Nick Koston
431766d898 preen 2025-07-24 21:08:57 -10:00
J. Nick Koston
9d20b04512 preen 2025-07-24 21:07:43 -10:00
J. Nick Koston
6a9f1d9b2e preen 2025-07-24 21:05:38 -10:00
J. Nick Koston
c18724526a preen 2025-07-24 21:03:46 -10:00
J. Nick Koston
cce7eca2b7 preen 2025-07-24 21:03:32 -10:00
J. Nick Koston
0f9fa89ddc preen 2025-07-24 21:02:53 -10:00
J. Nick Koston
56d6c41a1d preen 2025-07-24 21:02:45 -10:00
J. Nick Koston
0f7cfe2c95 preen 2025-07-24 21:02:05 -10:00
J. Nick Koston
f33419a3aa preen 2025-07-24 21:01:47 -10:00
J. Nick Koston
3f33f04651 preen 2025-07-24 21:01:32 -10:00
J. Nick Koston
abcf62339d preen 2025-07-24 21:00:53 -10:00
J. Nick Koston
bd20d8b7b2 preen 2025-07-24 20:59:26 -10:00
J. Nick Koston
3843e4011f preen 2025-07-24 20:58:29 -10:00
J. Nick Koston
5b7ed4f419 preen 2025-07-24 20:57:51 -10:00
J. Nick Koston
a14809999a preen 2025-07-24 20:56:28 -10:00
J. Nick Koston
fd6204e804 preen 2025-07-24 20:54:00 -10:00
J. Nick Koston
a418e8df48 preen 2025-07-24 20:53:25 -10:00
J. Nick Koston
05d1c0300f preen 2025-07-24 20:49:36 -10:00
J. Nick Koston
d54724a475 preen 2025-07-24 20:48:51 -10:00
J. Nick Koston
0121dfc514 preen 2025-07-24 20:46:10 -10:00
J. Nick Koston
1a1382de43 running setup 2025-07-24 16:29:54 -10:00
J. Nick Koston
3d0cea4ce3 revert 2025-07-24 16:28:31 -10:00
J. Nick Koston
25cd16409b running setup 2025-07-24 16:27:59 -10:00
J. Nick Koston
d839141386 Merge branch 'integration' into memory_api 2025-07-23 22:41:37 -10:00
J. Nick Koston
86919102c8 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-23 22:41:22 -10:00
J. Nick Koston
43e2938724 Merge branch '20250724-ld2450-use-deduplicator' into integration 2025-07-23 22:41:09 -10:00
J. Nick Koston
82c65040e2 Merge branch 'integration' into memory_api 2025-07-23 21:23:01 -10:00
J. Nick Koston
d291c1b207 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-23 21:22:50 -10:00
J. Nick Koston
3a4f645a6c Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-23 21:22:29 -10:00
Keith Burzinski
b977231431 clang-tidy 2025-07-24 02:13:52 -05:00
J. Nick Koston
557da2e7a7 Merge branch 'integration' into memory_api 2025-07-23 20:54:51 -10:00
J. Nick Koston
1458845672 Merge branch 'threading_model' into integration 2025-07-23 20:54:43 -10:00
J. Nick Koston
e4c8a6a0af [core] Revert #9851 and rename ESPHOME_CORES to ESPHOME_THREAD 2025-07-23 20:45:54 -10:00
Keith Burzinski
6609dce695 [ld2450] Use Deduplicator for sensors 2025-07-24 01:30:31 -05:00
J. Nick Koston
a5b4629662 Merge branch 'integration' into memory_api 2025-07-23 19:06:33 -10:00
J. Nick Koston
a4f952b851 Merge branch 'lwip_slowness' into integration 2025-07-23 19:06:24 -10:00
J. Nick Koston
8146a0139f [esp32] Enable LWIP core locking on ESP-IDF to reduce socket operation overhead 2025-07-23 18:50:46 -10:00
J. Nick Koston
7ba2927d1d Merge branch 'integration' into memory_api 2025-07-23 18:05:17 -10:00
J. Nick Koston
2d66effbda Merge branch 'api_nest' into integration 2025-07-23 18:05:03 -10:00
J. Nick Koston
dcae628b25 [api] Use C++17 nested namespace syntax 2025-07-23 18:04:06 -10:00
J. Nick Koston
74c9580e4b Merge branch 'integration' into memory_api 2025-07-23 17:55:17 -10:00
J. Nick Koston
42862ec5b5 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-23 17:54:53 -10:00
J. Nick Koston
f9c844be89 Merge branch 'integration' into memory_api 2025-07-22 23:52:21 -10:00
J. Nick Koston
dee58804e8 Merge branch 'loop_fix' into integration 2025-07-22 23:52:08 -10:00
J. Nick Koston
77c8363946 [core] Restore COMPONENT_STATE_LOOP_DONE check in calculate_looping_components 2025-07-22 23:49:33 -10:00
J. Nick Koston
0b2270c1d0 Merge branch 'integration' into memory_api 2025-07-22 23:24:24 -10:00
J. Nick Koston
bfae905a2b Merge branch 'bluetooth_namespace_cpp17' into integration 2025-07-22 19:41:52 -10:00
J. Nick Koston
5b8ae6ed1a update script 2025-07-22 19:20:28 -10:00
J. Nick Koston
1b74c877e1 Merge branch 'integration' into memory_api 2025-07-22 19:17:27 -10:00
J. Nick Koston
edeee42fd9 Merge branch 'bluetooth_namespace_cpp17' into integration 2025-07-22 19:17:18 -10:00
J. Nick Koston
8ae2b31a2f [bluetooth_proxy] [esp32_ble_tracker] [esp32_ble] Use C++17 nested namespace syntax 2025-07-22 19:16:01 -10:00
J. Nick Koston
aefb53cb0e Merge branch 'integration' into memory_api 2025-07-22 17:58:44 -10:00
J. Nick Koston
0fea9aab99 Merge remote-tracking branch 'upstream/component_cleanups' into integration 2025-07-22 17:58:36 -10:00
J. Nick Koston
e5001734ce [core] Fix component state documentation and add state helper method 2025-07-22 17:57:34 -10:00
J. Nick Koston
39f79522db Merge branch 'integration' into memory_api 2025-07-22 15:57:37 -10:00
J. Nick Koston
9bceed2cfc Merge branch 'fix_missed_calculate_looping_components_' into integration 2025-07-22 15:57:15 -10:00
J. Nick Koston
c400d8e5a9 Merge branch 'dev' into fix_missed_calculate_looping_components_ 2025-07-22 15:51:47 -10:00
J. Nick Koston
e6961f8f24 wip 2025-07-22 15:46:49 -10:00
J. Nick Koston
0b9b33b81b [core] Initialize looping_components_ before setup blocking phase 2025-07-22 15:42:09 -10:00
J. Nick Koston
d71f2ad185 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-22 13:16:00 -10:00
J. Nick Koston
f92571e767 Merge branch 'integration' into memory_api 2025-07-22 13:07:29 -10:00
J. Nick Koston
efa3d32fce Merge branch '5_4_2' into memory_api 2025-07-22 13:07:27 -10:00
J. Nick Koston
ac19d5eba2 Merge branch '5_4_2' into integration 2025-07-22 13:07:08 -10:00
J. Nick Koston
ffcf2229f6 Merge branch 'integration' into memory_api 2025-07-22 09:21:38 -10:00
J. Nick Koston
157c4f4369 Merge branch 'pb_dump' into integration 2025-07-22 09:21:32 -10:00
J. Nick Koston
2a935d9238 preen 2025-07-22 09:21:20 -10:00
J. Nick Koston
d4556608c8 preen 2025-07-22 09:21:14 -10:00
J. Nick Koston
285ad9af1e Merge branch 'integration' into memory_api 2025-07-22 09:16:47 -10:00
J. Nick Koston
f15662d4b5 Merge branch 'protobuf_magic_numbers' into integration 2025-07-22 09:16:28 -10:00
J. Nick Koston
fffa6eb0db Merge branch 'api_cleanups_5' into integration 2025-07-22 09:16:10 -10:00
J. Nick Koston
6711742248 Merge branch 'pb_dump' into integration 2025-07-22 09:15:49 -10:00
J. Nick Koston
d624f2a9ce dump helper 2025-07-22 09:10:01 -10:00
J. Nick Koston
c590ffd289 cleans to dump 2025-07-22 09:03:01 -10:00
J. Nick Koston
8096eea6c3 cleans to dump 2025-07-22 09:01:11 -10:00
J. Nick Koston
873aebc572 cleans to dump 2025-07-22 09:00:53 -10:00
J. Nick Koston
5adc58f826 cleans to dump 2025-07-22 09:00:44 -10:00
J. Nick Koston
3d35b9679a cleans to dump 2025-07-22 08:58:52 -10:00
J. Nick Koston
fbd3c051ec cleans to dump 2025-07-22 08:58:19 -10:00
J. Nick Koston
26b77e0f06 [api] Simplify generated authentication check code 2025-07-22 08:01:42 -10:00
J. Nick Koston
f3030e35a8 Merge branch 'integration' into memory_api 2025-07-22 07:49:36 -10:00
J. Nick Koston
adc21eef70 Merge branch 'api_services_emplace_back' into integration 2025-07-22 07:49:23 -10:00
J. Nick Koston
93fdea954f [api] Use emplace_back for TemplatableKeyValuePair construction in HomeAssistant services 2025-07-22 07:46:21 -10:00
J. Nick Koston
bb81a40b7c Merge branch 'integration' into memory_api 2025-07-21 22:26:21 -10:00
J. Nick Koston
922692338f Merge branch 'zero_copy_str' into integration 2025-07-21 22:26:09 -10:00
J. Nick Koston
2088deeacb give bot hint 2025-07-21 22:10:26 -10:00
J. Nick Koston
0534d1bfcf preen 2025-07-21 21:46:37 -10:00
J. Nick Koston
b8e326eb01 preen 2025-07-21 21:34:46 -10:00
J. Nick Koston
58d7533128 docs 2025-07-21 21:26:06 -10:00
J. Nick Koston
444c77775f Merge remote-tracking branch 'origin/zero_copy_str' into zero_copy_str 2025-07-21 21:25:01 -10:00
J. Nick Koston
2310610aa0 missed some 2025-07-21 21:24:34 -10:00
J. Nick Koston
7dec484eae Merge branch 'dev' into zero_copy_str 2025-07-21 21:21:29 -10:00
J. Nick Koston
712d3dee98 missed one 2025-07-21 21:06:43 -10:00
J. Nick Koston
44d7147ea4 fixes 2025-07-21 20:02:22 -10:00
J. Nick Koston
ede8e542bc fixes 2025-07-21 20:00:50 -10:00
J. Nick Koston
e17fef3208 unused 2025-07-21 19:50:41 -10:00
J. Nick Koston
7f25d3e6d3 unused 2025-07-21 19:50:01 -10:00
J. Nick Koston
72fd984d4b preen 2025-07-21 19:39:23 -10:00
J. Nick Koston
97525cfe87 preen 2025-07-21 19:31:42 -10:00
J. Nick Koston
8f201cdb7e fixes 2025-07-21 18:31:13 -10:00
J. Nick Koston
d0511e118d fixes 2025-07-21 18:28:09 -10:00
J. Nick Koston
c120676d19 fixes 2025-07-21 18:26:59 -10:00
J. Nick Koston
bd52acff12 adjust 2025-07-21 18:14:36 -10:00
J. Nick Koston
22422fc3dd send 2025-07-21 18:03:00 -10:00
J. Nick Koston
70c9cf9d95 ref 2025-07-21 17:24:23 -10:00
J. Nick Koston
b0aafb1226 ref 2025-07-21 17:21:59 -10:00
J. Nick Koston
c4ac22286f zero_copy_str 2025-07-21 17:02:01 -10:00
J. Nick Koston
4a0716d7ba Merge branch 'integration' into memory_api 2025-07-21 13:46:41 -10:00
J. Nick Koston
4f17c352db Merge branch 'fixed_arrays' into integration 2025-07-21 13:46:25 -10:00
J. Nick Koston
37d24dd707 cleanup 2025-07-21 13:44:28 -10:00
J. Nick Koston
a508d9dd3a Merge branch 'integration' into memory_api 2025-07-21 13:25:22 -10:00
J. Nick Koston
48436ec7c8 Merge branch 'fixed_arrays' into integration 2025-07-21 13:25:13 -10:00
Jonathan Swoboda
daf241b3f6 Remove picolibc dir from clangtidy 2025-07-21 19:23:34 -04:00
J. Nick Koston
4c62f43dcd cleanup 2025-07-21 13:19:19 -10:00
J. Nick Koston
767ec53cfa cleanup 2025-07-21 13:18:10 -10:00
J. Nick Koston
7b9acd39e1 cleanup 2025-07-21 13:17:18 -10:00
J. Nick Koston
55272dd0fd cleanup 2025-07-21 13:13:45 -10:00
J. Nick Koston
bc6b1ffc14 cleanup 2025-07-21 13:12:30 -10:00
J. Nick Koston
b3abebfb37 cleanup 2025-07-21 13:08:51 -10:00
J. Nick Koston
f034069b5e cleanup 2025-07-21 13:04:23 -10:00
J. Nick Koston
9a391df0f0 cleanup 2025-07-21 13:03:21 -10:00
J. Nick Koston
6d6bf82501 cleanup 2025-07-21 13:02:46 -10:00
J. Nick Koston
5f14579af8 cleanup 2025-07-21 13:00:30 -10:00
J. Nick Koston
8ee06cdc8c cleanup 2025-07-21 12:56:57 -10:00
J. Nick Koston
37cbcd5110 preen 2025-07-21 12:55:05 -10:00
J. Nick Koston
91e1a4ff76 fixed arrays 2025-07-21 12:49:48 -10:00
J. Nick Koston
ed190a92b1 Merge branch 'integration' into memory_api 2025-07-21 11:54:02 -10:00
J. Nick Koston
b660c867fb Merge branch 'api_inserts' into integration 2025-07-21 11:53:51 -10:00
J. Nick Koston
4cdef8c001 const 2025-07-21 11:50:20 -10:00
J. Nick Koston
a1667b29f1 Merge branch 'integration' into memory_api 2025-07-21 11:40:58 -10:00
J. Nick Koston
74fe8bd022 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-21 11:40:41 -10:00
J. Nick Koston
b38faa1870 Merge branch 'integration' into memory_api 2025-07-21 11:29:30 -10:00
J. Nick Koston
524d69a238 Merge branch 'api_inserts' into integration 2025-07-21 11:29:10 -10:00
J. Nick Koston
4a39f14037 [api] Optimize noise handshake with memcpy for faster connection setup 2025-07-21 11:20:49 -10:00
J. Nick Koston
b66c6dd856 Merge branch 'integration' into memory_api 2025-07-21 10:54:17 -10:00
J. Nick Koston
504c67f59f Merge branch 'memcpy_speedup' into integration 2025-07-21 10:54:10 -10:00
J. Nick Koston
383791418b [api] Optimize string encoding with memcpy for 10x performance improvement 2025-07-21 10:50:36 -10:00
J. Nick Koston
0240a7c310 Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-21 09:57:58 -10:00
J. Nick Koston
0be1395647 [api] Replace magic numbers with MESSAGE_TYPE constants in protobuf switch cases 2025-07-21 08:44:30 -10:00
Jonathan Swoboda
daae3a93ab Update .clang-tidy.hash 2025-07-21 08:13:20 -04:00
Jonathan Swoboda
00eba20ea9 Merge remote-tracking branch 'upstream/dev' into 5_4_2 2025-07-21 07:59:19 -04:00
J. Nick Koston
31caacabf0 revert -- for followup 2025-07-20 21:46:14 -10:00
J. Nick Koston
8a7446a1ea Merge branch 'integration' into memory_api 2025-07-20 21:37:55 -10:00
J. Nick Koston
1395af2c1c Merge branch 'ble_services_opt' into integration 2025-07-20 21:37:41 -10:00
J. Nick Koston
ebf225d5f2 cleanup 2025-07-20 21:37:15 -10:00
J. Nick Koston
b6aca30c42 cleanup 2025-07-20 21:36:27 -10:00
J. Nick Koston
b5da9b0e7c Merge branch 'integration' into memory_api 2025-07-20 21:31:38 -10:00
J. Nick Koston
38d38d6e8c Merge branch 'ble_services_opt' into integration 2025-07-20 21:31:15 -10:00
J. Nick Koston
fffc324c6e [bluetooth_proxy] Optimize service discovery with in-place construction 2025-07-20 21:29:36 -10:00
J. Nick Koston
3d832e4d92 Merge branch 'zero_copy' into memory_api 2025-07-20 21:15:16 -10:00
J. Nick Koston
85ab9d3eec Merge branch 'zero_copy' into integration 2025-07-20 21:14:53 -10:00
J. Nick Koston
67b9c249d4 device_id 2025-07-20 21:12:03 -10:00
J. Nick Koston
c66726336c Merge branch 'zero_copy' into memory_api 2025-07-20 21:03:01 -10:00
J. Nick Koston
54158bf5f1 Merge branch 'zero_copy' into integration 2025-07-20 21:02:54 -10:00
J. Nick Koston
edc641cfa3 Merge remote-tracking branch 'origin/zero_copy' into zero_copy 2025-07-20 21:02:48 -10:00
J. Nick Koston
12994c3a29 preen 2025-07-20 21:02:33 -10:00
J. Nick Koston
a63ebf2c5e preen 2025-07-20 21:02:01 -10:00
J. Nick Koston
839a26c289 Merge branch 'dev' into zero_copy 2025-07-20 20:46:13 -10:00
J. Nick Koston
9e6481c492 Merge branch 'integration' into memory_api 2025-07-20 20:44:25 -10:00
J. Nick Koston
311888ac6d Merge branch 'zero_copy' into integration 2025-07-20 20:44:14 -10:00
J. Nick Koston
7e86aefa91 preen 2025-07-20 20:44:03 -10:00
J. Nick Koston
756fc89eab preen 2025-07-20 20:43:50 -10:00
J. Nick Koston
c8140e966a Merge branch 'integration' into memory_api 2025-07-20 20:39:31 -10:00
J. Nick Koston
eff866c222 Merge branch 'zero_copy' into integration 2025-07-20 20:39:24 -10:00
J. Nick Koston
ffaba916d7 cleanup 2025-07-20 20:39:13 -10:00
J. Nick Koston
1de659420e Merge branch 'zero_copy' into memory_api 2025-07-20 20:23:15 -10:00
J. Nick Koston
d9210eba69 Merge branch 'zero_copy' into integration 2025-07-20 20:18:35 -10:00
J. Nick Koston
4a8f6ce556 Merge remote-tracking branch 'upstream/dev' into zero_copy 2025-07-20 20:17:55 -10:00
J. Nick Koston
8c11241af0 cleanup 2025-07-20 20:08:57 -10:00
J. Nick Koston
b24ff7236e cleanup 2025-07-20 20:07:30 -10:00
J. Nick Koston
5e906b1dd9 cleanup 2025-07-20 20:06:50 -10:00
J. Nick Koston
ad52d80281 cleanup 2025-07-20 19:57:32 -10:00
J. Nick Koston
04953db51e cleanup 2025-07-20 19:56:42 -10:00
J. Nick Koston
8b74333e8b preen 2025-07-20 19:52:26 -10:00
J. Nick Koston
5fb97e8e3c preen 2025-07-20 19:50:55 -10:00
J. Nick Koston
8b09a5259e preen 2025-07-20 19:48:19 -10:00
J. Nick Koston
ae7aa4c0ef preen 2025-07-20 19:46:41 -10:00
J. Nick Koston
9cb86241b9 cleanup 2025-07-20 19:40:21 -10:00
J. Nick Koston
1dc736e27a preen 2025-07-20 19:28:07 -10:00
J. Nick Koston
7de63d0670 fixes 2025-07-20 19:18:25 -10:00
J. Nick Koston
54bbde6183 zero copy cleanup 2025-07-20 19:01:41 -10:00
J. Nick Koston
8b54e46652 Merge branch 'add_fixed_field' into integration 2025-07-20 18:06:30 -10:00
J. Nick Koston
14e2c85028 [api] Remove unused add_fixed_field template function 2025-07-20 18:05:21 -10:00
J. Nick Koston
9cd1c7a355 Merge branch 'integration' into memory_api 2025-07-20 16:48:23 -10:00
J. Nick Koston
e2a0879239 Merge branch 'uses_password_ifdef' into integration 2025-07-20 16:46:55 -10:00
J. Nick Koston
197b04d74f Merge remote-tracking branch 'upstream/dev' into integration 2025-07-20 16:45:58 -10:00
J. Nick Koston
852671945a [api] Sync uses_password field_ifdef optimization from aioesphomeapi 2025-07-20 16:26:17 -10:00
J. Nick Koston
8a296e013c Merge branch 'integration' into memory_api 2025-07-20 14:37:04 -10:00
J. Nick Koston
953c05d4da Merge branch 'api_frame_helper_split' into integration 2025-07-20 14:33:06 -10:00
J. Nick Koston
af061d6cd8 have to dupe macros 2025-07-20 14:32:54 -10:00
J. Nick Koston
836ea5c60a have to dupe macros 2025-07-20 14:32:19 -10:00
J. Nick Koston
58f79ef654 Merge branch 'api_frame_helper_split' into integration 2025-07-20 14:31:12 -10:00
J. Nick Koston
984d10aff1 have to dupe macros 2025-07-20 14:31:01 -10:00
J. Nick Koston
48ddb5c999 Merge branch 'api_frame_helper_split' into integration 2025-07-20 14:27:48 -10:00
J. Nick Koston
cc34cc7a4e order 2025-07-20 14:27:34 -10:00
J. Nick Koston
59e567e567 Merge branch 'api_frame_helper_split' into integration 2025-07-20 14:23:58 -10:00
J. Nick Koston
a45be553ed Merge remote-tracking branch 'origin/api_frame_helper_split' into api_frame_helper_split 2025-07-20 14:23:44 -10:00
J. Nick Koston
ff59e37d8d fixes 2025-07-20 14:23:34 -10:00
J. Nick Koston
d251d78002 Merge branch 'dev' into api_frame_helper_split 2025-07-20 14:18:56 -10:00
J. Nick Koston
55833380c1 Merge branch 'api_frame_helper_split' into integration 2025-07-20 14:17:59 -10:00
J. Nick Koston
16bd3f92c4 fixes 2025-07-20 14:17:45 -10:00
J. Nick Koston
e1e95c36c5 Merge branch 'api_frame_helper_split' into integration 2025-07-20 14:15:14 -10:00
J. Nick Koston
2e7826aa34 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-20 14:13:20 -10:00
J. Nick Koston
e1be941bda preen 2025-07-20 14:07:52 -10:00
J. Nick Koston
eea7b9843b preen 2025-07-20 14:04:08 -10:00
J. Nick Koston
a626053220 Merge branch 'integration' into memory_api 2025-07-20 13:20:02 -10:00
J. Nick Koston
a5f22e99a3 Merge branch 'frame_helper_dupe_name_storage' into integration 2025-07-20 13:19:50 -10:00
J. Nick Koston
fb44fddacf Merge remote-tracking branch 'upstream/dev' into integration 2025-07-20 13:19:34 -10:00
J. Nick Koston
72fcb29fd2 Merge remote-tracking branch 'upstream/dev' into frame_helper_dupe_name_storage 2025-07-20 13:00:45 -10:00
J. Nick Koston
29988d414c Merge branch 'integration' into memory_api 2025-07-20 12:28:11 -10:00
J. Nick Koston
82970b640f merge 2025-07-20 12:27:51 -10:00
J. Nick Koston
af724ffb15 Merge branch 'api_cleanups_2' into memory_api 2025-07-20 12:26:33 -10:00
J. Nick Koston
82dfd0a233 empty commit 2025-07-20 12:24:31 -10:00
J. Nick Koston
7688cc619b Merge branch 'integration' into memory_api 2025-07-20 12:23:25 -10:00
J. Nick Koston
232d3a8b89 Merge branch 'api_cleanups_2' into integration 2025-07-20 12:23:12 -10:00
J. Nick Koston
a976df4da8 Merge remote-tracking branch 'upstream/dev' into api_cleanups_2 2025-07-20 12:22:42 -10:00
J. Nick Koston
f9744dabc1 Merge remote-tracking branch 'upstream/dev' into api_cleanups_2 2025-07-20 12:21:49 -10:00
J. Nick Koston
79acf97c48 Merge branch 'integration' into memory_api 2025-07-20 12:18:30 -10:00
J. Nick Koston
8becc57835 Merge branch 'empty_hidden_side_effects' into integration 2025-07-20 12:18:14 -10:00
J. Nick Koston
f6b989bd9a cleanup 2025-07-20 12:15:16 -10:00
J. Nick Koston
109eae26a7 [core] Refactor scheduler to eliminate hidden side effects in empty_() method 2025-07-20 12:09:11 -10:00
J. Nick Koston
8496102eb6 Merge branch 'dev' into memory_api 2025-07-20 11:22:18 -10:00
J. Nick Koston
04d7213ede simplify 2025-07-20 09:42:17 -10:00
J. Nick Koston
2ebb17a05e Merge remote-tracking branch 'upstream/frame_helper_dupe_name_storage' into frame_helper_dupe_name_storage 2025-07-20 09:30:52 -10:00
J. Nick Koston
905263548d cleaner 2025-07-20 09:30:40 -10:00
J. Nick Koston
83c0589c06 Update esphome/components/api/api_frame_helper.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-20 09:22:17 -10:00
J. Nick Koston
acc8b57709 [api] Reduce memory usage by eliminating duplicate client info strings 2025-07-20 09:18:52 -10:00
J. Nick Koston
8621bca535 Merge branch 'integration' into memory_api 2025-07-19 22:04:57 -10:00
J. Nick Koston
fc4c383409 Merge branch 'area_device_info_ifdefs' into integration 2025-07-19 22:04:06 -10:00
J. Nick Koston
a5ed8db5bd [api] Fix missing ifdef guards for AreaInfo and DeviceInfo messages 2025-07-19 22:01:22 -10:00
J. Nick Koston
3060e2cbc3 Merge branch 'integration' into memory_api 2025-07-19 16:21:13 -10:00
J. Nick Koston
1cc507b211 Merge branch 'touch_setup_mode' into integration 2025-07-19 16:21:03 -10:00
J. Nick Koston
b88061843c Merge branch 'integration' into memory_api 2025-07-19 15:43:02 -10:00
J. Nick Koston
1d6fcafefc Merge branch 'api_cleanups_2' into integration 2025-07-19 15:42:49 -10:00
J. Nick Koston
bc57cdb71a preen 2025-07-19 15:40:53 -10:00
J. Nick Koston
b70007852d Merge branch 'integration' into memory_api 2025-07-19 15:29:42 -10:00
J. Nick Koston
9f6cd1f809 Merge branch 'api_cleanups_2' into integration 2025-07-19 15:29:32 -10:00
J. Nick Koston
3905085614 dry 2025-07-19 15:22:08 -10:00
J. Nick Koston
722df19758 dry 2025-07-19 15:18:43 -10:00
J. Nick Koston
0046e67727 wip 2025-07-19 15:06:42 -10:00
J. Nick Koston
7e3027d9bd wip 2025-07-19 15:05:26 -10:00
Jonathan Swoboda
d0307cec4f Fix logging message 2025-07-19 20:12:33 -04:00
J. Nick Koston
1bc7b805c0 Merge branch 'integration' into memory_api 2025-07-19 13:46:17 -10:00
J. Nick Koston
79e20ed894 Merge branch 'api_buffering_cleanup' into integration 2025-07-19 13:46:07 -10:00
J. Nick Koston
b125cd6979 save some more 2025-07-19 13:45:58 -10:00
J. Nick Koston
0582fee82c save some more 2025-07-19 13:43:47 -10:00
Jonathan Swoboda
cd4a10e4e1 Fix setup mode in v1 driver 2025-07-19 19:43:17 -04:00
J. Nick Koston
3400cdf4c0 Merge branch 'integration' into memory_api 2025-07-19 13:18:55 -10:00
J. Nick Koston
d72fe6ea4b Merge branch 'api_buffering_cleanup' into integration 2025-07-19 13:18:44 -10:00
J. Nick Koston
2ca306c1c1 [api] Optimize frame helper buffering to reduce flash usage by 176 bytes 2025-07-19 13:15:55 -10:00
J. Nick Koston
3ad551b27e Merge branch 'integration' into memory_api 2025-07-19 12:34:13 -10:00
J. Nick Koston
9682c6c3d7 Merge branch 'bugfix/make_schedule_rollover_atomic' into integration 2025-07-19 11:13:38 -10:00
J. Nick Koston
d67508a6eb move defines 2025-07-19 11:12:59 -10:00
J. Nick Koston
b25206b7bb move defines 2025-07-19 11:12:41 -10:00
J. Nick Koston
112c6e34a5 move defines 2025-07-19 11:11:32 -10:00
J. Nick Koston
2ed70c3c60 Merge branch 'bugfix/make_schedule_rollover_atomic' into integration 2025-07-19 10:53:31 -10:00
J. Nick Koston
9119ac1c32 fix stale comments 2025-07-19 10:50:40 -10:00
J. Nick Koston
152e3ee587 make more readable 2025-07-19 10:43:57 -10:00
J. Nick Koston
acbcc5f9b8 make more readable 2025-07-19 10:40:21 -10:00
J. Nick Koston
5ed589fc97 make more readable 2025-07-19 10:39:27 -10:00
J. Nick Koston
58696961bd make more readable 2025-07-19 10:38:28 -10:00
J. Nick Koston
a5f5af9596 make more readable 2025-07-19 10:36:49 -10:00
RubenKelevra
fde80bc530 core/scheduler: split millis_64_ into different platform functions 2025-07-19 21:44:35 +02:00
RubenKelevra
211739bba0 core/scheduler: Make millis_64_ rollover monotonic on SMP
The current implementation uses only memory_order_relaxed on all atomic
accesses. That protects each variable individually but not the semantic
link between the low word (last_millis_) and the high-word epoch counter
(millis_major_). On a multi-core target a reader could observe a freshly
stored low word before seeing the matching increment of the epoch,
causing a ~49-day negative jump.

Key fixes
- Release/acquire pairing
  - writer: compare_exchange_weak(..., memory_order_release, …)
  - reader: first load of last_millis_ now uses memory_order_acquire
  - ensures any core that sees the new low word also sees the updated
    high word
- Epoch-coherency retry loop
  - re-loads millis_major_ after the update and retries if it changed,
    guaranteeing monotonicity even when another core rolls over
    concurrently
- millis_major_ promoted to std::atomic<uint16_t> on SMP platforms
  - removes the formal data race at negligible cost
- new macros for better readability
  - ESPHOME_SINGLE_CORE – currently ESP8266/RP2040 only
  - ESPHOME_ATOMIC_SCHEDULER – all others except LibreTiny
- Logging and comments
  - loads atomics safely in debug output
  - updated inline docs to match the memory ordering

Behavior on single-core or non-atomic platforms is unchanged; multi-core
targets now get a provably monotonic 64-bit millisecond clock with
minimal overhead.
2025-07-19 19:09:10 +02:00
J. Nick Koston
23f0c596c2 Merge branch 'integration' into memory_api 2025-07-18 22:21:19 -10:00
J. Nick Koston
dec3c69190 Merge branch 'batch_eliminate_heap' into integration 2025-07-18 22:20:08 -10:00
J. Nick Koston
3204cf52e9 Update esphome/components/api/api_connection.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-18 22:17:12 -10:00
J. Nick Koston
e2d509d63d Merge branch 'integration' into memory_api 2025-07-18 22:11:40 -10:00
J. Nick Koston
00dd5d64de Merge branch 'batch_eliminate_heap' into integration 2025-07-18 22:11:20 -10:00
J. Nick Koston
09705ca526 guard 2025-07-18 22:11:13 -10:00
J. Nick Koston
8223db761d document 2025-07-18 22:05:55 -10:00
J. Nick Koston
9dddb749c5 Merge branch 'batch_eliminate_heap' into integration 2025-07-18 21:31:31 -10:00
J. Nick Koston
e2524c9764 [api] Eliminate heap allocation in process_batch_ using stack-allocated PacketInfo array 2025-07-18 21:14:25 -10:00
J. Nick Koston
03a2237f2e Merge remote-tracking branch 'upstream/dev' into integration 2025-07-18 20:19:21 -10:00
J. Nick Koston
ba62a368ff Merge branch 'ble_tracker_read_up_to_end' into integration 2025-07-18 16:32:32 -10:00
J. Nick Koston
ffbadc0929 [esp32_ble_tracker] Batch BLE advertisement processing to reduce overhead 2025-07-18 16:30:56 -10:00
J. Nick Koston
d19e2d9cce Merge branch 'bluetooth_proxy_fixes' into integration 2025-07-18 16:11:26 -10:00
J. Nick Koston
c7884253d2 cannot always need to update timestamp 2025-07-18 16:11:16 -10:00
J. Nick Koston
fd2e6b1d2d Merge branch 'bluetooth_proxy_fixes' into integration 2025-07-18 16:09:47 -10:00
J. Nick Koston
6b8da2f0ca preen 2025-07-18 16:09:37 -10:00
J. Nick Koston
45e9522221 Merge branch 'integration' into memory_api 2025-07-18 15:41:34 -10:00
J. Nick Koston
8084c19a6c Merge branch 'bluetooth_proxy_fixes' into integration 2025-07-18 14:51:40 -10:00
J. Nick Koston
2c63d5c7ce rpreen 2025-07-18 14:51:12 -10:00
J. Nick Koston
6a728c2d7d Merge branch 'bluetooth_proxy_fixes' into integration 2025-07-18 14:43:29 -10:00
J. Nick Koston
7afb2fe077 preen 2025-07-18 14:43:05 -10:00
J. Nick Koston
57c0a44b55 Merge branch 'bluetooth_proxy_fixes' into integration 2025-07-18 14:33:50 -10:00
J. Nick Koston
b2ec2615bb other way 2025-07-18 14:33:10 -10:00
J. Nick Koston
6a566c6305 other way 2025-07-18 14:31:27 -10:00
J. Nick Koston
da1e1ce9ce other way 2025-07-18 14:30:46 -10:00
J. Nick Koston
9902a4ee9c Revert "preen"
This reverts commit 5f13aa162d.
2025-07-18 14:28:45 -10:00
J. Nick Koston
2ce0753ec6 Revert "preen"
This reverts commit 27db5352ac.
2025-07-18 14:28:45 -10:00
J. Nick Koston
e4736e9aa7 Revert "preen"
This reverts commit 9f5584ac62.
2025-07-18 14:28:44 -10:00
J. Nick Koston
8acd7548c6 Revert "preen"
This reverts commit 1c4a50ad3a.
2025-07-18 14:28:43 -10:00
J. Nick Koston
1ca1ceb08d Revert "preen"
This reverts commit 4c9fa2f753.
2025-07-18 14:28:42 -10:00
J. Nick Koston
3087ccface Revert "preen"
This reverts commit a8dd0b474a.
2025-07-18 14:28:41 -10:00
J. Nick Koston
d9fe52a5fb Revert "preen"
This reverts commit 56fdc1d115.
2025-07-18 14:28:40 -10:00
J. Nick Koston
56fdc1d115 preen 2025-07-18 14:25:22 -10:00
J. Nick Koston
a8dd0b474a preen 2025-07-18 14:25:06 -10:00
J. Nick Koston
4c9fa2f753 preen 2025-07-18 14:24:49 -10:00
J. Nick Koston
1c4a50ad3a preen 2025-07-18 14:24:32 -10:00
J. Nick Koston
9f5584ac62 preen 2025-07-18 14:24:20 -10:00
J. Nick Koston
27db5352ac preen 2025-07-18 14:24:05 -10:00
J. Nick Koston
5f13aa162d preen 2025-07-18 14:23:38 -10:00
J. Nick Koston
9aa53fd140 preen 2025-07-18 14:22:43 -10:00
J. Nick Koston
b9afa119a0 preen 2025-07-18 14:22:29 -10:00
J. Nick Koston
1a62b75ec3 [bluetooth_proxy] Fix performance issue and service discovery on disconnect 2025-07-18 14:19:06 -10:00
J. Nick Koston
15693a9cf0 Merge branch 'integration' into memory_api 2025-07-18 13:04:17 -10:00
J. Nick Koston
a62a8c3d94 Merge branch 'missing_ifdef_member_vars' into integration 2025-07-18 12:57:59 -10:00
J. Nick Koston
8593da7426 missing ifdef 2025-07-18 12:57:32 -10:00
J. Nick Koston
0ce077db94 Merge branch 'missing_ifdef_member_vars' into integration 2025-07-18 12:53:28 -10:00
J. Nick Koston
512cc24dc7 [api] Fix missing ifdef guards for field_ifdef fields in protobuf base classes 2025-07-18 12:50:36 -10:00
J. Nick Koston
cd6d686fd6 Merge remote-tracking branch 'origin/dep_proto_fields' into memory_api 2025-07-18 12:31:11 -10:00
J. Nick Koston
eeb827e88f Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-18 12:30:32 -10:00
J. Nick Koston
a8324e84f0 Merge branch 'integration' into memory_api 2025-07-18 10:52:00 -10:00
J. Nick Koston
a23f33cbad Merge branch 'libretiny_gpio' into integration 2025-07-18 10:51:23 -10:00
J. Nick Koston
bab6fdcf4e nrf52 2025-07-18 10:50:40 -10:00
J. Nick Koston
a1e74802ea nrf52 2025-07-18 10:49:17 -10:00
J. Nick Koston
5be2339bb5 Merge branch 'dev' into dep_proto_fields 2025-07-18 10:30:42 -10:00
J. Nick Koston
9a0ab594ef Merge remote-tracking branch 'upstream/libretiny_gpio' into libretiny_gpio 2025-07-18 10:24:08 -10:00
J. Nick Koston
fbf615f73c list them all 2025-07-18 10:23:52 -10:00
J. Nick Koston
186e64931a Update esphome/components/gpio/binary_sensor/__init__.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-18 10:17:52 -10:00
J. Nick Koston
6e7e2b4471 [gpio] Disable interrupt mode by default for LibreTiny platforms 2025-07-18 10:15:56 -10:00
J. Nick Koston
6b83975df0 Merge branch 'integration' into memory_api 2025-07-18 10:05:43 -10:00
J. Nick Koston
f52fe63ad1 Merge remote-tracking branch 'origin/integration' into integration 2025-07-18 10:05:29 -10:00
J. Nick Koston
4723f767f4 Merge remote-tracking branch 'upstream/dep_proto_fields' into integration 2025-07-18 10:05:16 -10:00
J. Nick Koston
cc1abfcdb3 fixed unref enum tracking 2025-07-18 09:24:24 -10:00
J. Nick Koston
d6422b6d25 missed some more 2025-07-18 09:07:29 -10:00
J. Nick Koston
cde4fc0609 missed some more 2025-07-18 09:07:13 -10:00
J. Nick Koston
7f5eefed10 remove dead code 2025-07-18 09:01:18 -10:00
J. Nick Koston
1aab2f5a7f missed one 2025-07-18 08:57:30 -10:00
J. Nick Koston
7566d85941 preen 2025-07-18 08:47:27 -10:00
J. Nick Koston
db59f3ae88 preen 2025-07-18 08:42:18 -10:00
J. Nick Koston
dc7b39722d preen 2025-07-18 08:39:31 -10:00
J. Nick Koston
19ab40e5c2 preen 2025-07-18 08:38:22 -10:00
J. Nick Koston
8a2599b7c2 preen 2025-07-18 08:36:15 -10:00
J. Nick Koston
0a45014330 Remove deprecated protobuf fields to reduce flash usage 2025-07-18 08:13:33 -10:00
J. Nick Koston
10605e93cd Merge remote-tracking branch 'upstream/dev' into integration 2025-07-18 07:58:14 -10:00
J. Nick Koston
0f65731673 Merge branch 'async_tcp_mismatch_fix' into integration 2025-07-18 07:51:18 -10:00
J. Nick Koston
5f9331b112 Fix AsyncTCP version mismatch between platformio.ini and async_tcp component 2025-07-18 07:50:28 -10:00
J. Nick Koston
94f49ab9da Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-17 21:59:34 -10:00
J. Nick Koston
603d4cfcf9 Merge branch 'retiny_includes' into integration 2025-07-17 20:19:47 -10:00
J. Nick Koston
759fe53fd4 [libretiny] Remove unsupported lock-free queue and event pool implementations 2025-07-17 20:18:40 -10:00
J. Nick Koston
61a965019f Merge remote-tracking branch 'origin/integration' into integration 2025-07-17 14:43:45 -10:00
J. Nick Koston
a91d0e5c2f Merge branch 'scheduler_retiny' into integration 2025-07-17 14:43:35 -10:00
J. Nick Koston
e26c20910d [scheduler] Fix LibreTiny compilation error due to missing atomic operations 2025-07-17 14:42:35 -10:00
J. Nick Koston
6740561bd7 Fix scheduler with libretiny 2025-07-17 14:24:31 -10:00
J. Nick Koston
04820ede37 Merge branch 'bluetooth_proxy_heap' into integration 2025-07-17 14:08:00 -10:00
J. Nick Koston
732370effc remove unneeded cast 2025-07-17 13:34:00 -10:00
J. Nick Koston
03f52e741b Merge branch 'bluetooth_proxy_heap' into integration 2025-07-17 12:59:43 -10:00
J. Nick Koston
f5c6e03404 Merge remote-tracking branch 'upstream/dev' into bluetooth_proxy_heap 2025-07-17 12:58:40 -10:00
J. Nick Koston
ee7bda74c0 Revert "Revert "missed one""
This reverts commit d40fcb324c.
2025-07-17 12:24:57 -10:00
J. Nick Koston
d40fcb324c Revert "missed one"
This reverts commit 8ba14d1f54.
2025-07-17 12:24:36 -10:00
J. Nick Koston
126f7acad2 Merge branch 'bluetooth_proxy_heap' into integration 2025-07-17 12:23:39 -10:00
J. Nick Koston
f9357f5e6e Merge remote-tracking branch 'upstream/dev' into integration 2025-07-17 12:23:10 -10:00
J. Nick Koston
81281c181f Merge branch 'dev' into bluetooth_proxy_heap 2025-07-17 12:07:47 -10:00
J. Nick Koston
c17fdd91de commit overreserve fix 2025-07-17 10:23:00 -10:00
J. Nick Koston
1f0958e824 safer 2025-07-17 09:57:29 -10:00
J. Nick Koston
9291dc4e27 Merge remote-tracking branch 'upstream/dev' into bluetooth_proxy_heap 2025-07-17 09:53:25 -10:00
J. Nick Koston
72419eb540 fix 2025-07-17 07:21:32 -10:00
J. Nick Koston
dbbcbc0998 ble churn fix 2025-07-16 20:41:01 -10:00
J. Nick Koston
7c45afa338 ble churn fix 2025-07-16 20:40:46 -10:00
J. Nick Koston
984601f0b2 ble churn fix 2025-07-16 20:39:15 -10:00
J. Nick Koston
ee600ced31 Merge branch 'esphome_webserver_ota' into integration 2025-07-16 16:21:12 -10:00
J. Nick Koston
c3da5b7a3f tell the bot 2025-07-16 15:50:42 -10:00
J. Nick Koston
ce21b992e3 tidy happy 2025-07-16 15:49:30 -10:00
J. Nick Koston
88323bcca0 Allow disabling OTA for web_server while keeping it enabled for captive_portal 2025-07-16 15:42:48 -10:00
J. Nick Koston
121759c07d Merge branch 'lwip_locking_fix' into integration 2025-07-16 13:15:26 -10:00
J. Nick Koston
f1d2300153 simplify 2025-07-16 13:10:00 -10:00
J. Nick Koston
94fd2d8ca1 Merge branch 'dev' into lwip_locking_fix 2025-07-16 12:47:29 -10:00
J. Nick Koston
c51bae3640 Merge branch 'lwip_locking_fix' into integration 2025-07-16 11:10:51 -10:00
J. Nick Koston
a399e90ed6 fix missing init 2025-07-16 11:10:36 -10:00
J. Nick Koston
e164e6ce37 Merge branch 'lwip_locking_fix' into integration 2025-07-16 10:57:10 -10:00
J. Nick Koston
cb0ef0b54a Fix lwIP thread safety assertion failures on ESP32 2025-07-16 10:56:29 -10:00
J. Nick Koston
73a8c03562 Merge branch 'integration' into memory_api 2025-07-16 08:26:40 -10:00
J. Nick Koston
e1583ff2d3 Merge branch 'template_send_message' into integration 2025-07-16 08:26:29 -10:00
J. Nick Koston
969fc54409 Merge branch 'template_send_message' into memory_api 2025-07-16 08:26:19 -10:00
J. Nick Koston
8ba14d1f54 missed one 2025-07-16 08:18:51 -10:00
J. Nick Koston
6aeefdc085 Refactor API send_message from template to non-template implementation 2025-07-16 08:09:54 -10:00
J. Nick Koston
9d10c79491 Merge branch 'integration' into memory_api 2025-07-15 23:24:53 -10:00
J. Nick Koston
b50bd00207 Merge branch 'dev' into integration 2025-07-15 23:24:34 -10:00
J. Nick Koston
472a594c6d Merge branch 'integration' into memory_api 2025-07-15 22:25:01 -10:00
J. Nick Koston
3e6da2870a Merge branch 'vtable' into integration 2025-07-15 22:24:32 -10:00
J. Nick Koston
d999ef3047 Merge branch 'entity_dupe_code' into integration 2025-07-15 22:24:23 -10:00
J. Nick Koston
e5bd2bd31b not virtual 2025-07-15 22:17:42 -10:00
J. Nick Koston
fc30ca83ca Reduce API proto vtable overhead by splitting decode functionality 2025-07-15 22:07:27 -10:00
J. Nick Koston
5dc7dee6d6 empty commit 2025-07-15 21:30:58 -10:00
J. Nick Koston
5aa4ed8d87 Merge remote-tracking branch 'upstream/dev' into entity_dupe_code 2025-07-15 21:24:00 -10:00
J. Nick Koston
5c4ded83d0 Merge branch 'integration' into memory_api 2025-07-15 20:04:01 -10:00
J. Nick Koston
7744b2db79 Merge branch 'proto_field_ifdefs' into integration 2025-07-15 20:02:50 -10:00
J. Nick Koston
8fcbcebf84 Merge branch 'entity_dupe_code' into integration 2025-07-15 20:02:45 -10:00
J. Nick Koston
561ed32b2a fix a few more that are missing 2025-07-15 19:58:28 -10:00
J. Nick Koston
5adfb71fe1 fix a few more that are missing 2025-07-15 19:58:13 -10:00
J. Nick Koston
dfdec8ec0a fix a few more that are missing 2025-07-15 19:58:08 -10:00
J. Nick Koston
f6c12229e5 fix a few more that are missing 2025-07-15 19:57:43 -10:00
J. Nick Koston
c80481baab fix a few more that are missing 2025-07-15 19:57:34 -10:00
J. Nick Koston
86ceccbb1c fix a few more that are missing 2025-07-15 19:57:15 -10:00
J. Nick Koston
628caf63fc fix a few more that are missing 2025-07-15 19:57:10 -10:00
J. Nick Koston
1ce5a994d8 fix a few more that are missing 2025-07-15 19:56:40 -10:00
J. Nick Koston
2abccce297 Merge remote-tracking branch 'upstream/dev' into proto_field_ifdefs 2025-07-15 19:51:56 -10:00
J. Nick Koston
0448a66960 Merge remote-tracking branch 'upstream/dev' into entity_dupe_code 2025-07-15 19:49:33 -10:00
J. Nick Koston
1a36c3cec4 Merge branch 'integration' into memory_api 2025-07-15 17:18:42 -10:00
J. Nick Koston
b497f11af0 Merge branch 'proto_field_ifdefs' into integration 2025-07-15 17:17:19 -10:00
J. Nick Koston
07f16dc065 Merge branch 'drop_unique_id' into integration 2025-07-15 17:16:13 -10:00
pre-commit-ci-lite[bot]
d2deba6b69 [pre-commit.ci lite] apply automatic fixes 2025-07-16 01:56:19 +00:00
J. Nick Koston
545fa1f1bc Merge remote-tracking branch 'upstream/dev' into proto_field_ifdefs 2025-07-15 15:52:18 -10:00
pre-commit-ci-lite[bot]
a477249266 [pre-commit.ci lite] apply automatic fixes 2025-07-16 01:35:26 +00:00
J. Nick Koston
b974ccabac Merge branch 'dev' from upstream 2025-07-15 15:25:51 -10:00
J. Nick Koston
8f38be0914 Merge remote-tracking branch 'upstream/dev' into proto_field_ifdefs 2025-07-15 15:19:26 -10:00
J. Nick Koston
2b12307b49 Merge remote-tracking branch 'upstream/drop_unique_id' into drop_unique_id 2025-07-15 15:10:29 -10:00
J. Nick Koston
e340d61a85 Merge upstream/dev into drop_unique_id 2025-07-15 15:09:56 -10:00
Jesse Hills
0110a376b7 Merge branch 'dev' into drop_unique_id 2025-07-16 13:09:52 +12:00
J. Nick Koston
c739a33be0 Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-15 12:22:30 -10:00
J. Nick Koston
0f6dad9c62 Merge branch 'scheduler_opt' into integration 2025-07-15 11:15:19 -10:00
J. Nick Koston
58541aa739 simplify 2025-07-15 11:11:15 -10:00
J. Nick Koston
4c91dead3d Merge branch 'loop_time_update_disable' into integration 2025-07-15 11:07:42 -10:00
J. Nick Koston
78a0fecc08 Fix timing overflow when components disable themselves during loop 2025-07-15 11:03:56 -10:00
J. Nick Koston
ff7a3d9f55 Merge branch 'integration' into memory_api 2025-07-15 09:39:01 -10:00
J. Nick Koston
42e1b1a2c1 Merge branch 'api_logconfig' into integration 2025-07-15 09:38:35 -10:00
J. Nick Koston
0d360938c2 Optimize API component LOGCONFIG usage for flash memory savings 2025-07-15 09:37:15 -10:00
J. Nick Koston
36ca3546f5 Merge branch 'scheduler_opt' into integration 2025-07-15 09:24:51 -10:00
J. Nick Koston
5536bdf0c9 Optimize scheduler timing by reducing millis() calls 2025-07-15 09:21:32 -10:00
J. Nick Koston
1718591ac1 Merge branch 'integration' into memory_api 2025-07-14 21:26:50 -10:00
J. Nick Koston
5aaa99d0e4 Merge branch 'logger_check_outside_func' into integration 2025-07-14 21:23:49 -10:00
J. Nick Koston
60e9ad2240 Skip API log message calls for unsubscribed log levels 2025-07-14 21:22:45 -10:00
J. Nick Koston
5ec25d84be Merge branch 'integration' into memory_api 2025-07-14 21:00:55 -10:00
J. Nick Koston
74b0a29a52 Merge branch 'api_connection_batch_prio' into integration 2025-07-14 20:59:52 -10:00
J. Nick Koston
909356698c Optimize API connection batch priority message handling to reduce flash usage 2025-07-14 20:31:34 -10:00
J. Nick Koston
bd416e761e Merge branch 'integration' into memory_api 2025-07-14 17:29:12 -10:00
J. Nick Koston
f34fe95f1c wip 2025-07-14 17:28:30 -10:00
J. Nick Koston
388fde1ee8 Merge entity_dupe_code: Refactor API connection entity encoding to reduce code duplication 2025-07-14 17:25:02 -10:00
J. Nick Koston
b13842f44e Refactor API connection entity encoding to reduce code duplication 2025-07-14 17:17:49 -10:00
J. Nick Koston
2396bf412d Merge branch 'integration' into memory_api 2025-07-14 17:03:26 -10:00
J. Nick Koston
1229766436 Merge branch 'drop_unique_id' into integration 2025-07-14 17:03:10 -10:00
J. Nick Koston
3fa899776d Merge branch 'integration' into memory_api 2025-07-14 16:56:53 -10:00
J. Nick Koston
77a5430f00 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-14 16:56:37 -10:00
J. Nick Koston
f27ef9210a Merge branch 'integration' into memory_api 2025-07-14 16:56:19 -10:00
J. Nick Koston
8ac6075321 Merge remote-tracking branch 'origin/dev' into integration 2025-07-14 15:52:35 -10:00
J. Nick Koston
6e1e8ed321 Merge branch 'remove_parsed_adv_support_bluetooth_proxy' into integration 2025-07-14 15:52:20 -10:00
J. Nick Koston
0826ade69d Merge remote-tracking branch 'origin/dev' into integration 2025-07-14 14:33:50 -10:00
J. Nick Koston
cf9130f906 Merge remote-tracking branch 'kahrendt/json-bump-library' into integration 2025-07-14 14:33:42 -10:00
Kevin Ahrendt
d268c14f7e Apply suggestions from code review
Fixes unsigned integer wrong type

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-07-14 20:20:46 -04:00
J. Nick Koston
3cca7a6161 fix incorrect comment 2025-07-14 12:31:41 -10:00
J. Nick Koston
52d6801618 address bot comments 2025-07-14 12:29:40 -10:00
J. Nick Koston
a714e8da0b last ones 2025-07-14 11:52:11 -10:00
J. Nick Koston
1778776b73 use NOLINTBEGIN/NOLINTEND for the multi occ cases 2025-07-14 11:30:43 -10:00
J. Nick Koston
d6e05061f8 a few more 2025-07-14 11:19:49 -10:00
J. Nick Koston
13ceda899b add some more , rearrange 2025-07-14 11:00:25 -10:00
J. Nick Koston
40d436746c webserver needs as well 2025-07-14 10:28:10 -10:00
J. Nick Koston
5c59b4fcad Merge remote-tracking branch 'kahrendt/json-bump-library' into integration 2025-07-14 10:14:19 -10:00
J. Nick Koston
4de36ffeb4 Merge branch 'dev' into json-bump-library 2025-07-14 10:13:33 -10:00
J. Nick Koston
4b3393ce64 location fixes 2025-07-14 10:12:46 -10:00
J. Nick Koston
4c8bb878bf Merge branch 'json-bump-library' of https://github.com/kahrendt/esphome into json-bump-library 2025-07-14 09:57:16 -10:00
Kevin Ahrendt
8a3cb32531 a few formatting things 2025-07-14 15:57:01 -04:00
Kevin Ahrendt
d3ab7f320e a few missing nolint messages 2025-07-14 15:52:40 -04:00
J. Nick Koston
85351bb952 a few more 2025-07-14 09:50:29 -10:00
Kevin Ahrendt
b47f9158b2 fix a few wrong types 2025-07-14 15:47:22 -04:00
J. Nick Koston
ee5242ec8d no real good option but to disable them all manually 2025-07-14 09:33:33 -10:00
J. Nick Koston
238909c0de no real good option but to disable them all manually 2025-07-14 09:31:22 -10:00
J. Nick Koston
fe9316c95d Merge branch 'json-bump-library' of https://github.com/kahrendt/esphome into json-bump-library 2025-07-14 09:30:45 -10:00
J. Nick Koston
a7e74bb7de no real good option but to disable them all manually 2025-07-14 09:30:43 -10:00
Kevin Ahrendt
b9cb690986 use better types 2025-07-14 15:28:54 -04:00
J. Nick Koston
808066f564 no real good option but to disable them all manually 2025-07-14 09:24:38 -10:00
J. Nick Koston
2057af8396 Revert "try another way"
This reverts commit 96d39403f4.
2025-07-14 09:21:42 -10:00
J. Nick Koston
b95449615f Revert "more aggressive fix"
This reverts commit 4f10a0ccf7.
2025-07-14 09:21:36 -10:00
Kevin Ahrendt
5e8f1d82c3 specify data types 2025-07-14 14:58:16 -04:00
Kevin Ahrendt
6afda9d4dc don't set string define 2025-07-14 14:58:16 -04:00
J. Nick Koston
4f10a0ccf7 more aggressive fix 2025-07-14 08:53:32 -10:00
J. Nick Koston
96d39403f4 try another way 2025-07-14 08:45:33 -10:00
J. Nick Koston
aeb56cc3d0 Revert "do not analyze platformio files"
This reverts commit f76cba0af6.
2025-07-14 08:45:15 -10:00
J. Nick Koston
33389f9c7f Revert "do not analyze platformio files"
This reverts commit 55a7926670.
2025-07-14 08:45:06 -10:00
J. Nick Koston
55a7926670 do not analyze platformio files 2025-07-14 08:13:45 -10:00
J. Nick Koston
f76cba0af6 do not analyze platformio files 2025-07-14 08:10:23 -10:00
J. Nick Koston
1dc75f6ffa Merge branch 'bump_ESPAsyncWebServer_AsyncTCP' into integration 2025-07-14 07:18:15 -10:00
J. Nick Koston
acb0fdc288 one more dep 2025-07-14 07:16:41 -10:00
J. Nick Koston
de235b638a Fix LibreTiny compilation error by updating ESPAsyncWebServer to 3.7.10 2025-07-14 07:12:07 -10:00
Kevin Ahrendt
ab454e9928 explicitly define support for std::string 2025-07-14 11:54:02 -04:00
Kevin Ahrendt
0a8af3ec85 Revert "testing a different approach"
This reverts commit 51eecac2de.
2025-07-14 11:52:26 -04:00
Kevin Ahrendt
51eecac2de testing a different approach 2025-07-14 11:43:31 -04:00
Kevin Ahrendt
815744b0f6 fix merge issues and clean up old comments 2025-07-14 10:47:38 -04:00
Kevin Ahrendt
a1281febe9 bump to 7.4.2 2025-07-14 10:35:10 -04:00
Kevin Ahrendt
9ef982fa4d clang fix 2025-07-14 10:35:10 -04:00
Kevin Ahrendt
44f97e2de4 move allocator to be a protected variable 2025-07-14 10:35:10 -04:00
Kevin Ahrendt
8ad4d3b6f5 fix type of ota object 2025-07-14 10:33:32 -04:00
Kevin Ahrendt
d97f473e4a include proper header for allocator and mark the functions as override 2025-07-14 10:33:32 -04:00
Kevin Ahrendt
ef072eb655 update createNestedObject 2025-07-14 10:33:32 -04:00
Kevin Ahrendt
8040c7cd92 update createdNestedArray calls 2025-07-14 10:33:32 -04:00
Kevin Ahrendt
8648acab5d remove old capacity() call 2025-07-14 10:33:32 -04:00
Kevin Ahrendt
1155e9b88a use new syntax instead of containsKey 2025-07-14 10:33:32 -04:00
Kevin Ahrendt
c069a66625 bump ArduinoJSON library to 7.4.1 2025-07-14 10:33:32 -04:00
J. Nick Koston
2a10f58bdd Remove parsed advertisement support from bluetooth_proxy to save memory 2025-07-13 22:09:53 -10:00
J. Nick Koston
e713b0bd8c Remove parsed advertisement support from bluetooth_proxy to save memory 2025-07-13 22:01:44 -10:00
J. Nick Koston
6ed5ea87f1 Merge branch 'integration' into memory_api 2025-07-13 18:08:10 -10:00
J. Nick Koston
fd13ed78ab Merge branch 'proto_size_remove_cond' into integration 2025-07-13 18:07:57 -10:00
J. Nick Koston
221f380ca3 single func 2025-07-13 18:03:21 -10:00
J. Nick Koston
cf472d5281 Merge branch 'integration' into memory_api 2025-07-13 17:37:35 -10:00
J. Nick Koston
85fa884382 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-13 17:37:13 -10:00
J. Nick Koston
6cd443e9dc Merge remote-tracking branch 'upstream/dev' into integration 2025-07-13 14:51:19 -10:00
J. Nick Koston
26b12ee790 Merge branch 'format_hex_dupe_code' into memory_api 2025-07-13 14:15:11 -10:00
J. Nick Koston
b1c6ece50d Merge branch 'integration' into memory_api 2025-07-13 14:12:49 -10:00
J. Nick Koston
c8c1573fbb Merge branch 'component_logging' into integration 2025-07-13 14:12:35 -10:00
J. Nick Koston
e7fb069bb3 Merge branch 'ram_realloc_bug' into integration 2025-07-13 14:12:31 -10:00
J. Nick Koston
fe7e5feba7 Fix dormant bug in RAMAllocator::reallocate() manual_size calculation 2025-07-13 14:11:23 -10:00
J. Nick Koston
1abdc23a23 Follow logging best practices by removing redundant component prefix 2025-07-13 13:55:35 -10:00
J. Nick Koston
c59c5db03e Refactor format_hex_pretty functions to eliminate code duplication 2025-07-13 13:44:31 -10:00
J. Nick Koston
2076d615f0 Merge branch 'integration' into memory_api 2025-07-13 13:06:20 -10:00
J. Nick Koston
ec3660e8ae Merge remote-tracking branch 'upstream/dev' into integration 2025-07-13 13:05:16 -10:00
J. Nick Koston
f6251cf6e4 Merge branch 'proto_field_ifdefs' into integration 2025-07-13 12:43:54 -10:00
J. Nick Koston
77258b5e62 Merge remote-tracking branch 'upstream/proto_field_ifdefs' into proto_field_ifdefs 2025-07-13 12:12:11 -10:00
J. Nick Koston
dc7996922b missing ifdefs 2025-07-13 12:11:59 -10:00
J. Nick Koston
31a6ae00b5 Merge branch 'dev' into proto_field_ifdefs 2025-07-13 11:57:55 -10:00
J. Nick Koston
d2569c0f1e Reduce binary size with field-level conditional compilation for protobuf messages 2025-07-13 11:16:36 -10:00
J. Nick Koston
ae9a48ebbb Reduce binary size with field-level conditional compilation for protobuf messages 2025-07-13 11:13:17 -10:00
J. Nick Koston
1c00e0b9c1 Merge branch 'integration' into memory_api 2025-07-13 10:20:30 -10:00
J. Nick Koston
d8f786cfdf Merge branch 'wire_type_1' into integration 2025-07-13 10:20:21 -10:00
J. Nick Koston
75ef572a24 Remove dead code: 64-bit protobuf types never used in 7 years 2025-07-13 10:18:55 -10:00
J. Nick Koston
f0f30224d3 Merge branch 'webserver_cleanups' into integration 2025-07-13 09:10:24 -10:00
J. Nick Koston
ec6e61e688 Refactor WebServer request handling for improved maintainability 2025-07-13 09:08:51 -10:00
J. Nick Koston
3dd457c471 Merge branch 'api_errors' into integration 2025-07-13 08:08:52 -10:00
J. Nick Koston
3b8a34c8d0 Reduce API component flash usage by consolidating error logging 2025-07-13 07:57:27 -10:00
J. Nick Koston
864709b006 Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-12 16:51:07 -10:00
J. Nick Koston
fe76955f3e Merge remote-tracking branch 'upstream/dev' into integration 2025-07-12 16:50:25 -10:00
J. Nick Koston
db8767fb05 Merge remote-tracking branch 'upstream/dev' into drop_unique_id 2025-07-12 14:25:47 -10:00
J. Nick Koston
7dad9c2ab0 Merge branch 'reformat_api_jump_tables' into integration 2025-07-12 13:52:14 -10:00
J. Nick Koston
4c0c0954a4 Merge remote-tracking branch 'upstream/dev' into reformat_api_jump_tables 2025-07-12 13:51:50 -10:00
J. Nick Koston
f5a486a7da Merge branch 'source_server' into integration 2025-07-12 10:50:31 -10:00
J. Nick Koston
a0b4100ff0 Merge branch 'source_server' into memory_api 2025-07-12 10:38:15 -10:00
J. Nick Koston
425d57ba7d other direction 2025-07-12 10:23:21 -10:00
J. Nick Koston
1965a41725 Skip generating decode methods for SOURCE_SERVER protobuf messages 2025-07-12 10:18:53 -10:00
J. Nick Koston
27f352b7dc Merge remote-tracking branch 'upstream/dev' into integration 2025-07-12 10:08:17 -10:00
J. Nick Koston
e01fb0b677 merge 2025-07-12 07:24:12 -10:00
J. Nick Koston
671f0d62c7 Merge remote-tracking branch 'origin/runtime_stats' into integration 2025-07-12 07:21:51 -10:00
J. Nick Koston
f1b888b309 Merge branch 'dev' into runtime_stats 2025-07-12 07:21:44 -10:00
J. Nick Koston
9cbcd0497a Merge branch 'encode_perf' into integration 2025-07-12 07:14:06 -10:00
J. Nick Koston
0139de37ba fixup 2025-07-12 06:51:40 -10:00
J. Nick Koston
4e7fe88da3 Apply existing protobuf buffer optimization to nested message encoding 2025-07-12 06:45:37 -10:00
J. Nick Koston
b1a81b45ea Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-11 20:59:41 -10:00
J. Nick Koston
fb0a8b9f3e Merge branch 'disable_wifi_ethernet_pr' into memory_api 2025-07-11 19:17:57 -10:00
J. Nick Koston
87ad8eab62 Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-11 19:17:51 -10:00
J. Nick Koston
6af4961695 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-11 19:08:23 -10:00
J. Nick Koston
ae78f7798f Merge branch 'disable_wifi_ethernet_pr' into integration 2025-07-11 19:00:15 -10:00
J. Nick Koston
53295fde7e Disable WiFi when using Ethernet to save memory 2025-07-11 18:59:31 -10:00
J. Nick Koston
268816bf7f Merge branch 'reformat_api_jump_tables' into memory_api 2025-07-11 18:43:40 -10:00
J. Nick Koston
200bec8440 Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-11 18:43:23 -10:00
J. Nick Koston
df461c08a9 Merge branch 'reformat_api_jump_tables' into integration 2025-07-11 18:34:07 -10:00
J. Nick Koston
bbf9dcc15a Merge remote-tracking branch 'origin/integration' into integration 2025-07-11 18:33:57 -10:00
J. Nick Koston
a3e7105cb0 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-11 18:33:40 -10:00
J. Nick Koston
10e5400d1f Improve API protobuf decode method readability and reduce code size 2025-07-11 18:30:08 -10:00
J. Nick Koston
97eb949670 Merge remote-tracking branch 'origin/integration' into integration 2025-07-11 17:32:30 -10:00
J. Nick Koston
8f484a89f3 Merge branch 'enum_uint32' into integration 2025-07-11 17:32:15 -10:00
J. Nick Koston
1f35c35e2a oops, removed wrong one 2025-07-11 17:32:07 -10:00
J. Nick Koston
427560f814 address bot review comments 2025-07-11 17:24:55 -10:00
J. Nick Koston
991200551d Merge branch 'enum_uint32' into memory_api 2025-07-11 17:10:21 -10:00
J. Nick Koston
60de0c6e69 Merge branch 'guard_custom_services' into memory_api 2025-07-11 17:10:12 -10:00
J. Nick Koston
4a3000bcc5 Merge branch 'guard_custom_services' into integration 2025-07-11 17:06:28 -10:00
J. Nick Koston
25cac3e04e make clang-tidy happy 2025-07-11 17:06:08 -10:00
J. Nick Koston
fc386a2648 Merge branch 'integration' of https://github.com/esphome/esphome into integration 2025-07-11 16:52:42 -10:00
J. Nick Koston
3fd9a3507c Merge branch 'reduce_api_size' into integration 2025-07-11 16:52:27 -10:00
J. Nick Koston
d92005113a Merge branch 'guard_custom_services' into integration 2025-07-11 16:52:15 -10:00
J. Nick Koston
fb2d764c89 tidy 2025-07-11 16:48:20 -10:00
J. Nick Koston
0251bb48ec Merge branch 'guard_custom_services' into integration 2025-07-11 16:34:10 -10:00
J. Nick Koston
a035db1d11 Merge remote-tracking branch 'origin/enum_uint32' into integration 2025-07-11 16:34:05 -10:00
J. Nick Koston
88049f9801 Merge branch 'dev' into enum_uint32 2025-07-11 16:33:45 -10:00
J. Nick Koston
42a9125ea7 preen 2025-07-11 16:25:49 -10:00
J. Nick Koston
63972ff272 preen 2025-07-11 16:24:16 -10:00
J. Nick Koston
dc53473e7e less templates 2025-07-11 16:16:57 -10:00
J. Nick Koston
2c290e3bee less templates 2025-07-11 16:10:39 -10:00
J. Nick Koston
c37494ea55 less templates 2025-07-11 16:09:33 -10:00
J. Nick Koston
b3e8963a33 less templates 2025-07-11 16:06:50 -10:00
J. Nick Koston
e2c77c0c4f less templates 2025-07-11 16:05:55 -10:00
J. Nick Koston
139ce4c655 lint 2025-07-11 15:54:20 -10:00
J. Nick Koston
010dc35efc etst 2025-07-11 15:49:59 -10:00
J. Nick Koston
413969300b etst 2025-07-11 15:48:36 -10:00
J. Nick Koston
b67a88027d guard 2025-07-11 15:35:26 -10:00
J. Nick Koston
2384b54ee3 Guard custom services 2025-07-11 15:30:37 -10:00
J. Nick Koston
c3ae23dc90 Merge branch 'remove_false' into memory_api 2025-07-11 14:42:42 -10:00
J. Nick Koston
aa00091e2b Merge remote-tracking branch 'upstream/dev' into memory_api 2025-07-11 14:42:38 -10:00
J. Nick Koston
7e3a203f0b Merge branch 'remove_false' into integration 2025-07-11 14:42:18 -10:00
J. Nick Koston
054e39316c Merge remote-tracking branch 'upstream/dev' into integration 2025-07-11 14:42:09 -10:00
J. Nick Koston
7ce879521d Merge branch 'dev' into remove_false 2025-07-11 14:39:09 -10:00
J. Nick Koston
6f5f378857 address lint comment 2025-07-11 14:36:54 -10:00
J. Nick Koston
773950332b address lint comment 2025-07-11 14:36:38 -10:00
J. Nick Koston
35cd8616a2 Merge branch 'remove_false' into integration 2025-07-11 14:17:44 -10:00
J. Nick Koston
95786ce269 review feedback from bot 2025-07-11 14:16:17 -10:00
J. Nick Koston
c082ee616e address feedback 2025-07-11 14:12:03 -10:00
J. Nick Koston
869f96f832 Optimize API proto size calculations by removing redundant force parameter 2025-07-11 14:06:27 -10:00
J. Nick Koston
2dff08b6f9 opt 2025-07-11 12:15:11 -10:00
J. Nick Koston
e76c40a1e7 Merge remote-tracking branch 'upstream/dev' into memory 2025-07-11 12:05:55 -10:00
J. Nick Koston
504ca09451 revert 2025-07-11 11:59:39 -10:00
J. Nick Koston
90c4b71d3f revert 2025-07-11 11:59:14 -10:00
J. Nick Koston
7e1db7a75c Merge remote-tracking branch 'origin/integration' into integration 2025-07-11 11:54:39 -10:00
J. Nick Koston
2f298992cf Merge branch 'auto_auth' into integration 2025-07-11 11:54:23 -10:00
J. Nick Koston
c8c5c26896 Merge remote-tracking branch 'origin/integration' into integration 2025-07-11 11:54:03 -10:00
J. Nick Koston
d8545ef946 Merge branch 'reduce_api_size' into integration 2025-07-11 11:53:49 -10:00
J. Nick Koston
db68f9571b revert 2025-07-11 11:47:09 -10:00
J. Nick Koston
0350471fa9 revert 2025-07-11 11:46:03 -10:00
J. Nick Koston
3ed533d709 tweak 2025-07-11 11:37:17 -10:00
J. Nick Koston
e472a345c9 tweak 2025-07-11 11:05:28 -10:00
J. Nick Koston
42be5d892a cleanup 2025-07-11 10:58:05 -10:00
J. Nick Koston
9a0d5019e1 tweak 2025-07-11 10:27:59 -10:00
J. Nick Koston
fc8c1ac9dd make sure we did not break password auth 2025-07-11 10:19:33 -10:00
J. Nick Koston
536134e2b5 preen 2025-07-11 10:17:41 -10:00
J. Nick Koston
005d4354d5 test this 2025-07-11 10:14:59 -10:00
J. Nick Koston
7107b5cfef preen 2025-07-11 10:11:26 -10:00
J. Nick Koston
bb153d42dc review 2025-07-11 10:02:51 -10:00
J. Nick Koston
a3806e4de2 Optimize API performance and flash usage by eliminating runtime message size lookup 2025-07-11 10:01:11 -10:00
J. Nick Koston
4dbe19a56e Auto auth if no password is required
Next step in password deprecation
2025-07-11 09:22:40 -10:00
J. Nick Koston
0b74122d6f Auto auth if no password is required
Next step in password deprecation
2025-07-11 09:21:18 -10:00
J. Nick Koston
e148c22f25 Auto auth if no password is required
Next step in password deprecation
2025-07-11 09:20:42 -10:00
J. Nick Koston
33fb4d5d42 fixes 2025-07-09 16:27:40 -10:00
J. Nick Koston
7f7623cc8d Merge remote-tracking branch 'upstream/dev' into memory 2025-07-09 16:16:01 -10:00
J. Nick Koston
f2e914fb94 Merge remote-tracking branch 'upstream/dev' into memory 2025-07-09 15:20:45 -10:00
J. Nick Koston
1678eb0591 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-09 15:20:35 -10:00
J. Nick Koston
1a0943c960 add component symbols 2025-07-09 10:00:20 -10:00
J. Nick Koston
073590124d Merge remote-tracking branch 'upstream/dev' into memory 2025-07-09 09:37:48 -10:00
J. Nick Koston
dfa4328604 tidy up 2025-07-08 13:03:01 -06:00
J. Nick Koston
9dab840c58 tidy up 2025-07-08 11:42:17 -06:00
J. Nick Koston
29fff967f5 tweak 2025-07-08 11:38:14 -06:00
J. Nick Koston
2a35c95718 fixes 2025-07-08 11:31:25 -06:00
J. Nick Koston
4a70aa26e8 Merge branch 'runtime_stats' into integration 2025-07-08 11:25:09 -06:00
J. Nick Koston
748604d374 preen 2025-07-08 11:12:46 -06:00
J. Nick Koston
d32db20aa0 preen 2025-07-08 11:10:32 -06:00
J. Nick Koston
ae346bb94e remove dead code 2025-07-08 10:11:47 -06:00
J. Nick Koston
cb67010574 remove dead code 2025-07-08 10:11:24 -06:00
J. Nick Koston
defa452aa1 preen 2025-07-08 09:58:02 -06:00
J. Nick Koston
97a476b475 stats 2025-07-08 09:52:44 -06:00
J. Nick Koston
07a4f6f53c fixes 2025-07-08 09:40:12 -06:00
J. Nick Koston
7d2726ab21 fixes 2025-07-08 09:37:07 -06:00
J. Nick Koston
3862e3b4e7 fixes 2025-07-08 09:35:31 -06:00
J. Nick Koston
be84f12100 fixes 2025-07-08 09:34:56 -06:00
J. Nick Koston
0097a55eaa fixes 2025-07-08 09:34:16 -06:00
J. Nick Koston
d1609de25a cleanup 2025-07-08 09:28:09 -06:00
J. Nick Koston
02395c92a1 cleanup 2025-07-08 09:26:13 -06:00
J. Nick Koston
f2ac6b0af6 cleanup 2025-07-08 09:25:00 -06:00
J. Nick Koston
a3c8f667a7 cleanup 2025-07-08 09:16:42 -06:00
J. Nick Koston
d06bab01ac runtime_stats 2025-07-08 09:09:07 -06:00
J. Nick Koston
591786a787 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-08 09:08:03 -06:00
Jonathan Swoboda
6c593fde22 Merge remote-tracking branch 'upstream/dev' into 5_4_2 2025-07-08 07:47:31 -04:00
Jonathan Swoboda
5e862412d8 Fix ifdef 2025-07-07 22:35:11 -04:00
Jonathan Swoboda
c72489b502 Merge remote-tracking branch 'upstream/dev' into 5_4_2 2025-07-07 21:59:15 -04:00
Jonathan Swoboda
33f6599320 Remove USE_ESP_IDF_VERSION_CODE & fix ethernet 2025-07-07 21:28:51 -04:00
J. Nick Koston
5de7b874b0 sync 2025-07-07 17:23:01 -05:00
J. Nick Koston
a27f6c72b9 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-07 17:22:35 -05:00
J. Nick Koston
a80d3012bd Merge remote-tracking branch 'origin/integration' into integration 2025-07-07 16:34:03 -05:00
J. Nick Koston
1c0a646309 Merge upstream/dev into integration 2025-07-07 16:33:30 -05:00
J. Nick Koston
eabb781e5f Merge remote-tracking branch 'upstream/dev' into integration 2025-07-07 15:46:19 -05:00
J. Nick Koston
03c2cda17c Merge branch 'logger_strlen' into integration 2025-07-07 15:38:53 -05:00
J. Nick Koston
26b72ccb10 Merge remote-tracking branch 'origin/logger_strlen' into logger_strlen 2025-07-07 15:18:37 -05:00
J. Nick Koston
ab993c6d5a add diagram 2025-07-07 15:18:27 -05:00
J. Nick Koston
999090fa18 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-07 15:11:18 -05:00
J. Nick Koston
2eed309224 Merge branch 'dev' into logger_strlen 2025-07-07 15:09:16 -05:00
J. Nick Koston
12980847a8 Merge branch 'logger_strlen' into integration 2025-07-07 15:08:21 -05:00
J. Nick Koston
01a6b38b89 null term is already there 2025-07-07 15:08:11 -05:00
J. Nick Koston
73b786c22e fix calculation 2025-07-07 15:01:15 -05:00
J. Nick Koston
c1a6e82322 fix calculation 2025-07-07 14:58:45 -05:00
J. Nick Koston
ec848bc7b4 Merge branch 'bluetooth_proxy_guard_var' into integration 2025-07-07 14:39:39 -05:00
J. Nick Koston
e5df43b934 cleanup 2025-07-07 14:38:49 -05:00
J. Nick Koston
d13f87e891 Merge upstream/dev while preserving guard variable optimization 2025-07-07 14:37:28 -05:00
J. Nick Koston
132d56fe1a lint 2025-07-07 14:24:55 -05:00
J. Nick Koston
171e19381f Update esphome/components/text_sensor/text_sensor.cpp 2025-07-07 14:19:17 -05:00
J. Nick Koston
9cc7b060c9 Update esphome/components/sensor/sensor.h 2025-07-07 14:18:57 -05:00
J. Nick Koston
d178e2da6f reduce more 2025-07-07 14:05:14 -05:00
J. Nick Koston
1e8f961362 reduce more 2025-07-07 14:03:15 -05:00
J. Nick Koston
166f77610f reduce more 2025-07-07 14:02:15 -05:00
J. Nick Koston
97dc244d1e reduce more 2025-07-07 13:55:22 -05:00
J. Nick Koston
085ddebf7d Merge remote-tracking branch 'upstream/dev' into drop_unique_id 2025-07-07 13:51:53 -05:00
J. Nick Koston
bccc3d79d8 Merge branch 'api_voice' into integration 2025-07-07 13:39:47 -05:00
J. Nick Koston
4df3bfe85d review 2025-07-07 13:39:37 -05:00
J. Nick Koston
99345574e4 Merge branch 'api_voice' into integration 2025-07-07 13:09:45 -05:00
J. Nick Koston
80c66b0742 preen 2025-07-07 13:09:30 -05:00
J. Nick Koston
17d820570b Merge branch 'api_dispatch_dry' into integration 2025-07-07 12:24:09 -05:00
J. Nick Koston
c979d5c9b1 bad linter suggestion again 2025-07-07 12:23:57 -05:00
J. Nick Koston
62c7f14d9a Merge remote-tracking branch 'upstream/dev' into memory 2025-07-07 12:08:50 -05:00
J. Nick Koston
13ac6df1dd Merge branch 'api_voice' into integration 2025-07-07 12:06:12 -05:00
J. Nick Koston
98d091fbc3 Refactor voice assistant API methods to reduce code duplication 2025-07-07 12:05:31 -05:00
J. Nick Koston
22e67f9754 Merge branch 'prepare_commands_for_device_id' into integration 2025-07-07 11:48:43 -05:00
J. Nick Koston
515a97de76 clang-format 2025-07-07 11:48:35 -05:00
J. Nick Koston
68b5337ed3 Merge branch 'api_dispatch_dry' into integration 2025-07-07 11:44:49 -05:00
J. Nick Koston
8ee86c717b update is a special case as well 2025-07-07 11:44:31 -05:00
J. Nick Koston
10530cdef3 Merge branch 'api_dispatch_dry' into integration 2025-07-07 11:40:41 -05:00
J. Nick Koston
5de0f9efc9 Refactor API entity update dispatch to reduce code duplication 2025-07-07 11:37:06 -05:00
J. Nick Koston
6d1d7f137f Merge branch 'prepare_commands_for_device_id' into integration 2025-07-07 11:15:32 -05:00
J. Nick Koston
38e16efa11 Refactor entity lookup methods with macros in preparation for device_id support 2025-07-07 11:10:23 -05:00
J. Nick Koston
5e2f0f7f5e Merge branch 'socket_read_dupe_code' into integration 2025-07-07 10:33:51 -05:00
J. Nick Koston
83c7afc46f Refactor duplicate socket read error handling in API frame helper 2025-07-07 10:33:04 -05:00
J. Nick Koston
10753f0f99 Merge branch 'more_str_len_logger' into integration 2025-07-07 10:10:17 -05:00
J. Nick Koston
34a852d433 Optimize logger performance by eliminating redundant strlen calls 2025-07-07 10:09:51 -05:00
J. Nick Koston
3922fbdef7 Merge branch 'logger_strlen' into integration 2025-07-07 09:04:17 -05:00
J. Nick Koston
e5415abf20 tidy 2025-07-07 09:03:52 -05:00
J. Nick Koston
67e1a92cce Merge branch 'logger_strlen' into integration 2025-07-07 08:53:11 -05:00
J. Nick Koston
4c64511a15 apply suggestions from review 2025-07-07 08:52:52 -05:00
J. Nick Koston
75f3e0900e apply suggestions from review 2025-07-07 08:52:28 -05:00
J. Nick Koston
abd33c21bf Update esphome/components/syslog/esphome_syslog.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-07 08:50:40 -05:00
J. Nick Koston
d592ba2c5e Update esphome/components/web_server/web_server.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-07 08:50:33 -05:00
J. Nick Koston
321eba5184 Merge branch 'logger_strlen' into integration 2025-07-07 08:48:45 -05:00
J. Nick Koston
82b9ec53fd fix merge error 2025-07-07 08:48:35 -05:00
J. Nick Koston
b9262f967b Merge branch 'logger_strlen' into integration 2025-07-07 08:47:27 -05:00
J. Nick Koston
949fb9a890 Optimize logger callback API by including message length parameter 2025-07-07 08:46:21 -05:00
J. Nick Koston
99952a701f Merge remote-tracking branch 'upstream/jesserockz-2025-282' into integration 2025-07-07 07:34:48 -05:00
J. Nick Koston
88878adb6c Merge branch 'filter_compile_warning_vv' into integration 2025-07-07 07:33:53 -05:00
J. Nick Koston
17e3b49ebb Merge branch 'api_sprint' into integration 2025-07-07 07:33:49 -05:00
J. Nick Koston
a217747f5d Replace deprecated sprintf with snprintf in API protobuf code generation 2025-07-07 07:32:22 -05:00
J. Nick Koston
790c9cbb84 Fix format specifier warnings in QuantileFilter logging 2025-07-07 07:27:31 -05:00
J. Nick Koston
da5fb6e24f Merge branch '20250707-ld2450-clean-up' into integration 2025-07-07 07:18:12 -05:00
Jesse Hills
a77439b4b7 Ignore new helper files for namespace inclusion 2025-07-07 23:24:30 +12:00
Jesse Hills
1a049bdcbb More missing includes 2025-07-07 21:06:50 +12:00
Keith Burzinski
79686239d3 Rename button, sort vars 2025-07-07 03:33:21 -05:00
Keith Burzinski
c934e84e21 [ld2450] Clean-up for consistency, reduce CPU usage when idle 2025-07-07 03:23:04 -05:00
Jesse Hills
5e2f8cb018 Missing includes 2025-07-07 17:33:05 +12:00
J. Nick Koston
6bd0af6d85 Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 23:58:09 -05:00
J. Nick Koston
0f28a49822 tidy 2025-07-06 23:57:46 -05:00
Jesse Hills
66d96646b1 [core] Move platform helper implementations into their own file 2025-07-07 16:40:45 +12:00
J. Nick Koston
be4cf6505f Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 22:56:46 -05:00
J. Nick Koston
e8ea7825a9 Merge branch 'dev' into heap_scheduler_stress_component 2025-07-06 22:56:18 -05:00
J. Nick Koston
8c13eab731 no flakey 2025-07-06 22:54:46 -05:00
J. Nick Koston
bf4cbb0aee Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 22:14:38 -05:00
J. Nick Koston
aaec4b7bd3 validation consistent 2025-07-06 22:13:35 -05:00
J. Nick Koston
7bddcd4f64 Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 22:07:21 -05:00
J. Nick Koston
af205a5267 one more test 2025-07-06 22:01:19 -05:00
J. Nick Koston
c2599d7719 safer 2025-07-06 21:43:03 -05:00
J. Nick Koston
4ea6f23d9e Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 21:32:06 -05:00
J. Nick Koston
f23fd52a26 clarify what we know 2025-07-06 21:31:39 -05:00
J. Nick Koston
cfd43c81fb clarify what we know 2025-07-06 21:30:39 -05:00
J. Nick Koston
3dcba675b4 Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 21:23:51 -05:00
J. Nick Koston
bb51031ec6 preen 2025-07-06 21:23:30 -05:00
J. Nick Koston
ecb99cbcce fix flakey test 2025-07-06 21:19:38 -05:00
J. Nick Koston
0a514821c6 preen 2025-07-06 21:04:23 -05:00
J. Nick Koston
074fbb522c preen 2025-07-06 21:01:52 -05:00
J. Nick Koston
71d6ba242e preen 2025-07-06 21:01:25 -05:00
J. Nick Koston
37ffd64b48 Merge remote-tracking branch 'upstream/heap_scheduler_stress_component' into heap_scheduler_stress_component 2025-07-06 20:59:59 -05:00
J. Nick Koston
ec65652567 add missed remake 2025-07-06 20:59:43 -05:00
J. Nick Koston
731613421d fix flakey 2025-07-06 20:59:08 -05:00
J. Nick Koston
58dfad4ed0 Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 20:38:10 -05:00
J. Nick Koston
7eb029f4b9 cleanup 2025-07-06 20:38:00 -05:00
J. Nick Koston
8da8d938f0 Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 20:36:50 -05:00
J. Nick Koston
64ac0d2bde cover 2025-07-06 20:36:32 -05:00
J. Nick Koston
7d3cdd15ad cleanup 2025-07-06 20:31:28 -05:00
J. Nick Koston
53baf02087 cleanup 2025-07-06 20:30:40 -05:00
J. Nick Koston
a0d2392344 cleanup 2025-07-06 20:26:43 -05:00
J. Nick Koston
fb3c092eaa cleanup 2025-07-06 20:25:27 -05:00
J. Nick Koston
c169cf1e77 Merge remote-tracking branch 'origin/heap_scheduler_stress_component' into heap_scheduler_stress_component 2025-07-06 20:13:48 -05:00
J. Nick Koston
fa4d8e083a Merge remote-tracking branch 'origin/dev' into heap_scheduler_stress_component 2025-07-06 20:13:34 -05:00
J. Nick Koston
2cfeccfd71 cleanup locking 2025-07-06 20:13:21 -05:00
J. Nick Koston
f36ca93752 Merge branch 'dev' into heap_scheduler_stress_component 2025-07-06 20:05:23 -05:00
J. Nick Koston
dc8714c277 fix race 2025-07-06 19:59:11 -05:00
J. Nick Koston
90fcb5fbcd fix another race 2025-07-06 19:54:07 -05:00
J. Nick Koston
932d0a5d8b fix another race 2025-07-06 19:50:54 -05:00
J. Nick Koston
4cafa18fa4 fix another race 2025-07-06 19:46:23 -05:00
J. Nick Koston
b12d7db5a7 prevent future refactoring errors 2025-07-06 19:27:33 -05:00
J. Nick Koston
e84345594d Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 19:01:11 -05:00
J. Nick Koston
add7bec7f2 tweak 2025-07-06 18:54:00 -05:00
J. Nick Koston
db84d8e8dc tweak 2025-07-06 18:49:41 -05:00
J. Nick Koston
ad51e647af tweak 2025-07-06 18:48:50 -05:00
J. Nick Koston
c45901746b tweak 2025-07-06 18:46:48 -05:00
J. Nick Koston
033c469250 tweak 2025-07-06 18:44:19 -05:00
J. Nick Koston
0900fd3cea tweak 2025-07-06 18:42:47 -05:00
J. Nick Koston
ba8f3d3f63 tweak 2025-07-06 18:36:05 -05:00
J. Nick Koston
2759f3828e tweak 2025-07-06 18:34:56 -05:00
J. Nick Koston
f395767766 tweak 2025-07-06 18:27:49 -05:00
J. Nick Koston
2dc222aea6 tweak 2025-07-06 18:26:29 -05:00
J. Nick Koston
82d68c87e2 adjust 2025-07-06 18:24:00 -05:00
J. Nick Koston
f213657753 adjust 2025-07-06 18:18:47 -05:00
J. Nick Koston
e077e6cec7 adjust 2025-07-06 18:17:16 -05:00
J. Nick Koston
339a3270f6 adjust 2025-07-06 18:16:25 -05:00
J. Nick Koston
462b44ee23 adjust 2025-07-06 18:15:11 -05:00
J. Nick Koston
52d3dba89c adjust 2025-07-06 18:11:04 -05:00
J. Nick Koston
939d01dd99 preen 2025-07-06 18:08:50 -05:00
J. Nick Koston
4900f7c7ca preen 2025-07-06 18:07:34 -05:00
J. Nick Koston
48957aee8b preen 2025-07-06 18:03:53 -05:00
J. Nick Koston
e355ce04f7 preen 2025-07-06 18:01:21 -05:00
J. Nick Koston
758e5b89bb preen 2025-07-06 17:53:56 -05:00
J. Nick Koston
3ffdd1d451 preen 2025-07-06 17:42:57 -05:00
J. Nick Koston
4c1b8c8b96 preen 2025-07-06 17:33:50 -05:00
J. Nick Koston
3ca956cd6a fix merge error 2025-07-06 17:27:32 -05:00
J. Nick Koston
2e24a11a1d Merge remote-tracking branch 'upstream/dev' into heap_scheduler_stress_component 2025-07-06 17:21:36 -05:00
J. Nick Koston
10a03ad538 tidy 2025-07-06 15:37:09 -05:00
J. Nick Koston
69839ec4dc Merge branch 'filter_files' into integration 2025-07-06 14:22:31 -05:00
J. Nick Koston
28a66d4bf0 preen 2025-07-06 14:18:17 -05:00
J. Nick Koston
782d894801 preen 2025-07-06 14:18:05 -05:00
J. Nick Koston
06dd731c78 preen 2025-07-06 14:10:20 -05:00
J. Nick Koston
6af74302dc missed one 2025-07-06 14:06:03 -05:00
J. Nick Koston
03380a6ecd some tests 2025-07-06 13:51:51 -05:00
J. Nick Koston
8d8db11dd9 some tests 2025-07-06 13:51:17 -05:00
J. Nick Koston
28886a896b some tests 2025-07-06 13:48:11 -05:00
J. Nick Koston
05253991c2 fixes 2025-07-06 13:42:44 -05:00
J. Nick Koston
96f0fda477 fixes 2025-07-06 13:42:18 -05:00
J. Nick Koston
023fa4d220 fixes 2025-07-06 13:37:41 -05:00
J. Nick Koston
a1f63c0dfc fixes 2025-07-06 13:24:50 -05:00
J. Nick Koston
ef98f42e7e tweaks 2025-07-06 13:18:24 -05:00
J. Nick Koston
737e1284af tweaks 2025-07-06 13:18:10 -05:00
J. Nick Koston
8677918157 tweaks 2025-07-06 13:16:49 -05:00
J. Nick Koston
629c891dfc Filter unused files 2025-07-06 12:12:16 -05:00
J. Nick Koston
8e8ef83780 cleanup 2025-07-06 11:05:18 -05:00
J. Nick Koston
2a15f35e9d cleanup 2025-07-06 11:04:04 -05:00
J. Nick Koston
9bfa942cf2 merge 2025-07-06 10:58:15 -05:00
J. Nick Koston
b00adbddce fix race 2025-07-06 10:40:44 -05:00
J. Nick Koston
a71030c4de fix race 2025-07-06 10:40:19 -05:00
J. Nick Koston
6bb32c2e61 tweaks 2025-07-06 10:12:29 -05:00
J. Nick Koston
7bc2c685e0 tweaks 2025-07-06 10:12:14 -05:00
J. Nick Koston
9205338cc8 Merge branch 'heap_scheduler_stress_component' into integration 2025-07-06 10:08:35 -05:00
J. Nick Koston
04336f7ba3 Merge branch 'dev' into heap_scheduler_stress_component 2025-07-06 10:08:03 -05:00
J. Nick Koston
6f64312d08 remove debugging 2025-07-06 10:06:45 -05:00
J. Nick Koston
79dfb86830 remove debugging 2025-07-06 10:04:17 -05:00
J. Nick Koston
453dc29540 preen 2025-07-06 10:03:28 -05:00
J. Nick Koston
f4260d370c preen 2025-07-06 10:03:24 -05:00
J. Nick Koston
655f9489a8 preen 2025-07-06 10:02:58 -05:00
J. Nick Koston
4b3cc52afe preen 2025-07-06 10:02:47 -05:00
J. Nick Koston
fd3f15637a lint 2025-07-06 10:01:07 -05:00
J. Nick Koston
1311e1b8b0 lint 2025-07-06 10:00:55 -05:00
J. Nick Koston
64e84872da lint 2025-07-06 10:00:35 -05:00
J. Nick Koston
bc7379030e lint 2025-07-06 10:00:25 -05:00
J. Nick Koston
ecfb6dc8ed lint 2025-07-06 10:00:17 -05:00
J. Nick Koston
75d67af932 Add heap scheduler tests 2025-07-06 09:55:14 -05:00
J. Nick Koston
845dad6ee7 Merge branch 'idf_webserver_guard' into integration 2025-07-05 23:48:48 -05:00
J. Nick Koston
e2e86da64b make bot happy 2025-07-05 23:48:37 -05:00
J. Nick Koston
90ec63589f Merge branch 'core_ram' into integration 2025-07-05 23:40:51 -05:00
J. Nick Koston
ea308eaaa2 add comments to explain why its safe and the bot is wrong 2025-07-05 23:39:25 -05:00
J. Nick Koston
87f1fac2bf nolint 2025-07-05 23:28:39 -05:00
J. Nick Koston
c23651527f Merge branch 'bluetooth_proxy_guard_var' into integration 2025-07-05 23:02:44 -05:00
J. Nick Koston
2cc263a707 lint 2025-07-05 23:01:49 -05:00
J. Nick Koston
fb336718de Merge branch 'core_ram' into integration 2025-07-05 23:00:30 -05:00
J. Nick Koston
e2e35bf965 simplify 2025-07-05 22:58:27 -05:00
J. Nick Koston
bdd25c7268 Merge branch 'idf_webserver_guard' into integration 2025-07-05 22:26:54 -05:00
J. Nick Koston
82c788d6ce Eliminate web_server_idf guard variable to save 8 bytes RAM 2025-07-05 22:24:26 -05:00
J. Nick Koston
5167184cc7 merge 2025-07-05 22:18:20 -05:00
J. Nick Koston
a5d1b11204 Merge branch 'bluetooth_proxy_guard_var' into integration 2025-07-05 22:17:32 -05:00
J. Nick Koston
dc8f2fd37e Eliminate bluetooth_proxy guard variable to save 8 bytes RAM 2025-07-05 22:15:45 -05:00
J. Nick Koston
7c85886ce8 Merge branch 'api_guard_var' into integration 2025-07-05 21:59:47 -05:00
J. Nick Koston
12f172436d Eliminate API component guard variable to save 8 bytes RAM 2025-07-05 21:59:08 -05:00
J. Nick Koston
e69ac0478e Merge branch 'core_ram' into integration 2025-07-05 21:38:49 -05:00
J. Nick Koston
a45743c2b7 Reduce core RAM usage by 40 bytes with static initialization optimizations 2025-07-05 21:35:32 -05:00
J. Nick Koston
ebe1531927 Merge branch 'color_memory' into integration 2025-07-05 21:24:23 -05:00
J. Nick Koston
a88a059c6a Reduce RAM usage by optimizing Color constant storage 2025-07-05 21:21:43 -05:00
J. Nick Koston
d314cbb0d5 Merge branch 'icon_opt_pay_as_you_go' into integration 2025-07-05 17:44:05 -05:00
J. Nick Koston
4d75758eb2 tests 2025-07-05 17:39:02 -05:00
J. Nick Koston
0eecc29039 Merge branch 'icon_opt_pay_as_you_go' into integration 2025-07-05 17:38:13 -05:00
J. Nick Koston
294fb67410 Optimize entity icon memory usage with USE_ENTITY_ICON flag 2025-07-05 17:36:51 -05:00
J. Nick Koston
2f1f098b47 revert 2025-07-05 16:55:15 -05:00
J. Nick Koston
77be414261 Merge branch 'deep_sleep_loop' into integration 2025-07-05 16:12:06 -05:00
J. Nick Koston
c34fc3c4c7 simplify 2025-07-05 16:07:43 -05:00
J. Nick Koston
8aac2f525e simplify 2025-07-05 16:01:59 -05:00
J. Nick Koston
f85dcdca4e unreachable 2025-07-05 15:57:21 -05:00
J. Nick Koston
e7a1ef7aa1 Merge branch 'deep_sleep_loop' into integration 2025-07-05 15:54:13 -05:00
J. Nick Koston
7c2d2ef5a3 deep_sleep: Replace polling loop with event-driven state machine 2025-07-05 15:53:12 -05:00
J. Nick Koston
1449001747 Merge branch 'ld2450_cpu_drain_spam' into integration 2025-07-05 15:07:58 -05:00
J. Nick Koston
f245c74520 fix byte ordering 2025-07-05 15:01:02 -05:00
J. Nick Koston
da1658e4f9 Merge branch 'ld2450_cpu_drain_spam' into integration 2025-07-05 14:50:51 -05:00
J. Nick Koston
80f9352a79 Merge branch 'light_ram' into integration 2025-07-05 14:50:47 -05:00
J. Nick Koston
9ded501402 clang-tidy 2025-07-05 14:50:17 -05:00
J. Nick Koston
3d6a1811c5 comments 2025-07-05 14:28:26 -05:00
J. Nick Koston
a5ee047efb Fix LD2450 excessive CPU usage and redundant sensor updates 2025-07-05 14:25:56 -05:00
J. Nick Koston
fb0090dcdc Merge branch 'light_ram' into integration 2025-07-05 13:53:20 -05:00
J. Nick Koston
294bd4d042 tweaks 2025-07-05 13:44:42 -05:00
J. Nick Koston
e99b8d2daf tweaks 2025-07-05 13:41:09 -05:00
J. Nick Koston
6dbdeeb59b tidy 2025-07-05 13:18:45 -05:00
J. Nick Koston
82fd62e9dd comments 2025-07-05 13:00:48 -05:00
J. Nick Koston
70f935d323 fixed a few missed ones 2025-07-05 12:39:05 -05:00
J. Nick Koston
0f3e6cccd9 Reduce light component memory usage by 50+ bytes per instance 2025-07-05 12:33:54 -05:00
J. Nick Koston
6ff323c56d Merge branch 'busy_disconnect_loop' into integration 2025-07-05 11:12:06 -05:00
J. Nick Koston
096ec79ef9 Fix bluetooth proxy busy loop when disconnecting pending BLE connections 2025-07-05 11:11:36 -05:00
J. Nick Koston
bf5ba65558 Merge branch 'ble_align' into integration 2025-07-05 09:05:20 -05:00
J. Nick Koston
62088dfaed Split LockFreeQueue into base and notifying variants to reduce memory usage 2025-07-05 09:02:33 -05:00
J. Nick Koston
dfcc3206f7 Split LockFreeQueue into base and notifying variants to reduce memory usage 2025-07-05 08:59:19 -05:00
J. Nick Koston
e173b7f0c2 Split LockFreeQueue into base and notifying variants to reduce memory usage 2025-07-05 08:58:41 -05:00
J. Nick Koston
f98e28a8a2 Split LockFreeQueue into base and notifying variants to reduce memory usage 2025-07-05 08:57:04 -05:00
J. Nick Koston
f63557f2e7 notes to the future 2025-07-05 07:34:46 -05:00
J. Nick Koston
a353598961 Merge branch 'ble_batching' into integration 2025-07-05 07:24:07 -05:00
J. Nick Koston
bc33b44648 Optimize Bluetooth proxy batching and increase scan buffer capacity 2025-07-05 07:23:31 -05:00
J. Nick Koston
1579779967 Merge branch 'defer_const' into integration 2025-07-04 20:54:41 -05:00
J. Nick Koston
cc6ea4cd14 cover 2025-07-04 20:51:50 -05:00
J. Nick Koston
303a8ff87a Merge branch 'defer_const' into integration 2025-07-04 20:33:07 -05:00
J. Nick Koston
7d3a11a735 Add const char overload for Component::defer() 2025-07-04 20:30:04 -05:00
J. Nick Koston
94b6344820 Merge branch 'reduce_main_loop' into integration 2025-07-04 13:56:19 -05:00
J. Nick Koston
40307c079c Merge remote-tracking branch 'origin/reduce_main_loop' into reduce_main_loop 2025-07-04 13:54:41 -05:00
J. Nick Koston
debef6fde4 address review comments 2025-07-04 13:54:07 -05:00
J. Nick Koston
0cda83d29c Update scheduler.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-04 13:46:39 -05:00
J. Nick Koston
32729c7ca7 Merge branch 'reduce_main_loop' into integration 2025-07-04 12:59:23 -05:00
J. Nick Koston
b7fca5488a lol 2025-07-04 12:59:11 -05:00
J. Nick Koston
9c22772758 fix scope issue 2025-07-04 11:40:11 -05:00
J. Nick Koston
1e72f07fdf Merge branch 'reduce_main_loop' into integration 2025-07-04 11:29:12 -05:00
J. Nick Koston
a592e96709 preen 2025-07-04 11:29:01 -05:00
J. Nick Koston
3980339868 Merge branch 'reduce_main_loop' into integration 2025-07-04 11:26:45 -05:00
J. Nick Koston
afa66c17bd preen 2025-07-04 11:26:33 -05:00
J. Nick Koston
be2988b1d7 Merge branch 'reduce_main_loop' into integration 2025-07-04 11:24:46 -05:00
J. Nick Koston
cf647f0c36 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-04 11:24:40 -05:00
J. Nick Koston
385ed4ca0c Merge remote-tracking branch 'upstream/reduce_main_loop' into reduce_main_loop 2025-07-04 11:23:44 -05:00
J. Nick Koston
9188a8e326 preen 2025-07-04 11:23:33 -05:00
J. Nick Koston
0efb6d55c8 Merge branch 'dev' into reduce_main_loop 2025-07-04 11:20:27 -05:00
J. Nick Koston
f748047b7b Merge branch 'reduce_main_loop' into integration 2025-07-04 11:18:55 -05:00
J. Nick Koston
49bc767bf4 cleanup 2025-07-04 11:13:08 -05:00
J. Nick Koston
e12cc9a9a7 cleanup 2025-07-04 11:12:54 -05:00
J. Nick Koston
8e4470cdff Merge branch 'reduce_main_loop' into integration 2025-07-04 11:02:07 -05:00
J. Nick Koston
bdb7e19fd0 guard esp8266 2025-07-04 10:59:58 -05:00
J. Nick Koston
0fc3f0e162 guard esp8266 2025-07-04 10:57:39 -05:00
J. Nick Koston
6fac66e63b Merge branch 'reduce_main_loop' into integration 2025-07-04 10:46:38 -05:00
J. Nick Koston
71e06ea1b6 cleanup 2025-07-04 10:45:47 -05:00
J. Nick Koston
3df434fd55 improve test 2025-07-04 10:41:59 -05:00
J. Nick Koston
729b2b2873 remove debug 2025-07-04 10:35:29 -05:00
J. Nick Koston
bc2adb6b5a there was no locking on host! 2025-07-04 10:25:31 -05:00
J. Nick Koston
aaff086aeb there was no locking on host! 2025-07-04 10:24:04 -05:00
J. Nick Koston
e4c0f18ee3 fixes 2025-07-04 10:17:41 -05:00
J. Nick Koston
9c09a271f2 tweaks 2025-07-04 10:14:54 -05:00
J. Nick Koston
37578f3e22 fixes 2025-07-04 10:11:19 -05:00
J. Nick Koston
4649599592 fixes 2025-07-04 10:01:00 -05:00
J. Nick Koston
71f78e3a81 fixes 2025-07-04 10:00:25 -05:00
J. Nick Koston
f7ca26eef8 stress 2025-07-04 08:59:15 -05:00
J. Nick Koston
0665fcea9e stress test 2025-07-04 08:49:35 -05:00
J. Nick Koston
cd2b50c27f stress test 2025-07-04 08:49:12 -05:00
J. Nick Koston
ca70f17b3b make test race safe 2025-07-04 08:33:34 -05:00
J. Nick Koston
a5e08aaf74 make test race safe 2025-07-04 08:33:24 -05:00
J. Nick Koston
947db4605a Merge branch 'reduce_main_loop' into integration 2025-07-04 08:16:18 -05:00
J. Nick Koston
481a00a0b5 Merge remote-tracking branch 'upstream/dev' into integration 2025-07-04 08:16:16 -05:00
J. Nick Koston
465019e510 cover 2025-07-04 08:04:16 -05:00
J. Nick Koston
a4d5f39fb6 cover 2025-07-04 07:59:12 -05:00
J. Nick Koston
5dd76966c3 cover 2025-07-04 07:55:01 -05:00
J. Nick Koston
db86f87fc3 Make defer FIFO 2025-07-04 07:42:59 -05:00
J. Nick Koston
e21334b7fa Make defer FIFO 2025-07-04 07:42:37 -05:00
J. Nick Koston
ba4c268956 Make defer FIFO 2025-07-04 07:35:24 -05:00
J. Nick Koston
068594be5e Make defer FIFO 2025-07-04 07:29:37 -05:00
J. Nick Koston
0fd45fc86e fix 2025-07-03 20:15:45 -05:00
J. Nick Koston
257fb98113 Merge branch 'api_cleanup' into integration 2025-07-03 20:05:59 -05:00
J. Nick Koston
f8922b3cca Use std::span to eliminate heap allocation for single-packet API transmissions 2025-07-03 20:01:28 -05:00
J. Nick Koston
b0b08f317b Merge remote-tracking branch 'origin/dev' into integration 2025-07-03 17:47:02 -05:00
Jonathan Swoboda
a8e4ed009b Bump arduino version to 3.2.1 2025-07-03 16:49:22 -04:00
J. Nick Koston
2c4667fb46 Merge branch 'camera-platform' into integration 2025-07-03 15:14:49 -05:00
J. Nick Koston
9eadfa21d8 Merge branch 'webserver_busy_loop_dropped_connection' into integration 2025-07-03 14:45:38 -05:00
J. Nick Koston
953fd24458 Fix web_server busy loop with ungracefully disconnected clients 2025-07-03 14:43:11 -05:00
J. Nick Koston
1be171e084 Merge remote-tracking branch 'origin/webserver_string_lifetime' into integration 2025-07-03 14:06:25 -05:00
J. Nick Koston
5c83b99e0c do not need to rename as we changed design to not need it 2025-07-03 14:06:07 -05:00
J. Nick Koston
743e611735 Merge remote-tracking branch 'origin/webserver_string_lifetime' into integration 2025-07-03 13:59:22 -05:00
J. Nick Koston
35ff850894 make sure its bug for bug compat 2025-07-03 13:56:29 -05:00
Dieter Tschanz
b666295b53 Replace Windows-style with Unix-style directory separators in test 2025-07-03 20:53:00 +02:00
J. Nick Koston
96cf8d97ab Merge remote-tracking branch 'upstream/webserver_string_lifetime' into integration 2025-07-03 13:52:04 -05:00
J. Nick Koston
3c1a781a1c cleanups 2025-07-03 13:51:01 -05:00
J. Nick Koston
00bd1b0a02 cleanups 2025-07-03 13:49:22 -05:00
J. Nick Koston
b8482da421 fix defines 2025-07-03 13:38:23 -05:00
J. Nick Koston
756ece9ff3 Merge branch 'dev' into camera-platform 2025-07-03 13:37:54 -05:00
J. Nick Koston
4bb016fec3 Merge branch 'webserver_lock_churn' into integration 2025-07-03 13:35:15 -05:00
J. Nick Koston
32f0322dec Merge branch 'webserver_string_lifetime' into integration 2025-07-03 13:35:10 -05:00
J. Nick Koston
1a1c13b722 Fix web_server URL parsing lifetime issue 2025-07-03 13:27:02 -05:00
Dieter Tschanz
139453822b Add compile-time test to verify Camera interface implementation. 2025-07-03 20:26:10 +02:00
J. Nick Koston
7a33994666 Reduce web_server loop overhead on ESP32 by avoiding unnecessary semaphore operations 2025-07-03 12:50:59 -05:00
J. Nick Koston
f381d9011b Merge remote-tracking branch 'upstream/dev' into integration 2025-07-03 12:18:06 -05:00
J. Nick Koston
96352f047d Merge branch 'device_id_state' into integration 2025-07-03 12:17:48 -05:00
J. Nick Koston
5e7a1fea8c Add device_id to entity state messages for sub-device support 2025-07-03 10:21:12 -05:00
Jonathan Swoboda
baaafb7fcb Bump ESP-IDF to 5.4.2 2025-07-03 11:13:45 -04:00
J. Nick Koston
64eb70444d Merge branch 'dev' into camera-platform 2025-07-02 19:52:06 -05:00
J. Nick Koston
0f39b1c49a merge 2025-07-02 14:06:59 -05:00
J. Nick Koston
e2d6363c68 merge 2025-07-02 14:06:32 -05:00
J. Nick Koston
cdeef700c2 Merge branch 'password_api' into integration 2025-07-02 14:05:12 -05:00
J. Nick Koston
86fd702841 Save flash and RAM by conditionally compiling unused API password code 2025-07-02 13:56:41 -05:00
J. Nick Koston
b1553807f7 wip 2025-07-02 09:14:26 -05:00
J. Nick Koston
797d4929ab wip 2025-07-02 09:05:28 -05:00
J. Nick Koston
ba5bb9dfa7 wip 2025-07-02 09:02:06 -05:00
J. Nick Koston
dd49d832c4 wip 2025-07-02 08:56:13 -05:00
J. Nick Koston
5004f44f65 wip 2025-07-02 08:42:17 -05:00
J. Nick Koston
bc9c4a8b8e wip 2025-07-02 08:35:42 -05:00
J. Nick Koston
6f05ee7427 wip 2025-07-02 08:25:41 -05:00
J. Nick Koston
f3523a96c9 wip 2025-07-02 08:24:15 -05:00
J. Nick Koston
06957d9895 wip 2025-07-02 08:21:36 -05:00
J. Nick Koston
1f361b07d1 wip 2025-07-02 08:16:35 -05:00
J. Nick Koston
40d9c0a3db wip 2025-07-02 07:58:35 -05:00
J. Nick Koston
548cd39496 wip 2025-07-02 07:51:04 -05:00
J. Nick Koston
85049611c3 wip 2025-07-02 07:48:55 -05:00
J. Nick Koston
b8a75bc925 analyze_memory 2025-07-02 07:30:17 -05:00
J. Nick Koston
6c62d4a923 Merge branch 'fix_bytes_encoding' into integration 2025-07-01 22:44:43 -05:00
J. Nick Koston
6e42d009fb Fix bytes field encoding in protobuf code generator 2025-07-01 20:26:34 -05:00
J. Nick Koston
7d7769ea5d Merge branch 'component_memory' into integration 2025-07-01 14:11:58 -05:00
J. Nick Koston
3908677fe2 Merge branch 'ota_base_extract' into integration 2025-07-01 14:09:51 -05:00
J. Nick Koston
9799a2b636 test 2025-07-01 13:47:59 -05:00
Dieter Tschanz
55c8129423 Correction for failed component test. 2025-07-01 20:44:11 +02:00
J. Nick Koston
099474053e cleanuip 2025-07-01 13:38:47 -05:00
J. Nick Koston
efafabed97 fix rp2040 2025-07-01 13:23:24 -05:00
Dieter Tschanz
d209739f85 Introduce base Camera class to support alternative camera implementations
This commit introduces a new 'Camera' base class positioned between the
API layer and the existing 'ESP32Camera' implementation.
- No changes to functionality in 'ESP32Camera' or
'ESP32CameraWebServer'.
- This refactoring enables future camera implementations to integrate
with the existing API.
- The goal is to keep the commit as minimal and non-breaking as
possible.

This is the first step in a series of changes aimed at modernizing and
generalizing ESPHome's camera support.
2025-07-01 19:47:50 +02:00
J. Nick Koston
d463dd0f57 Merge branch 'bk7200_tagged_pointer_fix' into integration 2025-07-01 11:57:11 -05:00
J. Nick Koston
c33c14a46f tidy 2025-07-01 11:57:02 -05:00
J. Nick Koston
2d0c109dc1 Merge remote-tracking branch 'origin/dev' into ota_base_extract 2025-07-01 11:50:49 -05:00
J. Nick Koston
825d0bed88 fix esp8266 error handling 2025-07-01 11:29:38 -05:00
J. Nick Koston
cd1390916c md5 fixes 2025-07-01 11:09:08 -05:00
J. Nick Koston
149bdaf146 fixes 2025-07-01 10:50:17 -05:00
J. Nick Koston
ad628c9cba single ota path 2025-07-01 10:36:36 -05:00
J. Nick Koston
b88f87799e single ota path 2025-07-01 10:30:52 -05:00
J. Nick Koston
1ff7cf1125 single ota path 2025-07-01 10:28:48 -05:00
J. Nick Koston
31db6e51eb single ota path 2025-07-01 10:27:46 -05:00
J. Nick Koston
681d9236f9 single ota path 2025-07-01 10:26:55 -05:00
J. Nick Koston
8aa8af735d single ota path 2025-07-01 10:25:48 -05:00
J. Nick Koston
943d0f103d single ota path 2025-07-01 10:17:28 -05:00
J. Nick Koston
8b195d7f63 use ota backend 2025-07-01 10:11:41 -05:00
J. Nick Koston
649ad47e62 web_server_ support for ota backend idf 2025-07-01 10:05:23 -05:00
J. Nick Koston
93dc5765bb Merge upstream/dev into ota_base_extract 2025-07-01 09:57:09 -05:00
J. Nick Koston
b000b1b70c Fix regression: BK7231N devices not returning entities via API 2025-07-01 09:43:50 -05:00
J. Nick Koston
8707b6e01a lint 2025-07-01 07:31:45 -05:00
J. Nick Koston
34abd67f3e Merge branch 'component_memory' into integration 2025-06-30 21:21:07 -05:00
J. Nick Koston
45f1db9233 address review comments 2025-06-30 21:20:58 -05:00
J. Nick Koston
beb4d1511a Merge branch 'component_memory' into integration 2025-06-30 21:18:06 -05:00
J. Nick Koston
adeceee71f Reduce Component memory usage by 40% (8 bytes per component) 2025-06-30 21:15:20 -05:00
J. Nick Koston
7d4b11d112 Reduce Component memory usage by 40% (8 bytes per component) 2025-06-30 21:11:49 -05:00
J. Nick Koston
6733cd4ed1 Merge branch 'entity_name_must_be_unique' into integration 2025-06-30 18:31:40 -05:00
J. Nick Koston
07f361a404 empty name uses device name, use get_base_entity_object_id 2025-06-30 18:26:09 -05:00
J. Nick Koston
ae981ea7f2 Merge branch 'entity_name_must_be_unique' into integration 2025-06-30 17:48:49 -05:00
J. Nick Koston
b7d0f5e36b Fix entity hash collisions by enforcing unique names across devices per platform 2025-06-30 17:38:04 -05:00
J. Nick Koston
3cbce4df42 Merge branch 'esp32_touch_isr' into integration 2025-06-30 14:38:54 -05:00
J. Nick Koston
7e77e40bda cleanup 2025-06-30 14:37:30 -05:00
J. Nick Koston
305805256d dry 2025-06-30 14:34:07 -05:00
J. Nick Koston
e36c669dc0 dry 2025-06-30 14:32:13 -05:00
J. Nick Koston
71aff9bc60 dry 2025-06-30 14:30:07 -05:00
J. Nick Koston
36d11c969f dry 2025-06-30 14:29:57 -05:00
J. Nick Koston
f76ce5d3bb dry 2025-06-30 14:28:31 -05:00
J. Nick Koston
0df454481e safer 2025-06-30 14:15:26 -05:00
J. Nick Koston
83c1a30cfb Merge branch 'esp32_touch_isr' into integration 2025-06-30 13:46:54 -05:00
J. Nick Koston
6cbd1479c6 loop 2025-06-30 13:46:47 -05:00
J. Nick Koston
3e6e438920 Merge remote-tracking branch 'upstream/dev' into esp32_touch_isr 2025-06-30 13:43:18 -05:00
J. Nick Koston
560886eb90 clenaup 2025-06-30 13:32:59 -05:00
J. Nick Koston
340bb5cef6 clenaup 2025-06-30 13:31:55 -05:00
J. Nick Koston
44a7c1d4a5 cleanup 2025-06-30 13:14:55 -05:00
J. Nick Koston
519c49f175 Revert "fix"
This reverts commit c96ffefa42.
2025-06-30 13:11:27 -05:00
J. Nick Koston
c96ffefa42 fix 2025-06-30 13:02:26 -05:00
J. Nick Koston
490ca8ad5a relo 2025-06-30 12:53:41 -05:00
J. Nick Koston
e385f87d6c move more 2025-06-30 12:46:47 -05:00
J. Nick Koston
58de53123a move more 2025-06-30 12:41:55 -05:00
J. Nick Koston
4f365c1716 todo 2025-06-30 12:11:37 -05:00
J. Nick Koston
981177da23 todo 2025-06-30 12:09:07 -05:00
J. Nick Koston
088bea9ccd split 2025-06-30 10:50:26 -05:00
J. Nick Koston
36350f179e split 2025-06-30 10:49:59 -05:00
J. Nick Koston
902f08c1bc Extract OTA backend functionality into separate ota_base component 2025-06-30 10:38:31 -05:00
J. Nick Koston
47ad206ccd Extract OTA backend functionality into separate ota_base component 2025-06-30 10:35:19 -05:00
J. Nick Koston
9f51546023 Extract OTA backend functionality into separate ota_base component 2025-06-30 10:33:43 -05:00
J. Nick Koston
f6d679f056 Merge branch 'idf_webserver_ota' into integration 2025-06-30 10:04:39 -05:00
J. Nick Koston
93c45e88e7 revert ota backend changes 2025-06-30 10:04:23 -05:00
J. Nick Koston
da189da9ae Merge branch 'idf_webserver_ota' into integration 2025-06-30 09:56:30 -05:00
J. Nick Koston
c40a33cb48 revert ota backend changes 2025-06-30 09:56:20 -05:00
J. Nick Koston
9846beee7d revert ota backend changes 2025-06-30 09:55:02 -05:00
J. Nick Koston
81685f9132 Merge branch 'idf_webserver_ota' into integration 2025-06-30 09:50:56 -05:00
J. Nick Koston
14123d25c2 fixes 2025-06-30 09:50:46 -05:00
J. Nick Koston
928819ffbd fixes 2025-06-30 09:49:59 -05:00
J. Nick Koston
7f2f9636f5 make sure ota still works without ota loaded 2025-06-30 09:46:33 -05:00
J. Nick Koston
b49fe146ad make sure ota still works without ota loaded 2025-06-30 09:44:20 -05:00
J. Nick Koston
98bbd4136b Merge branch 'idf_webserver_ota' into integration 2025-06-30 09:24:05 -05:00
J. Nick Koston
d8d02f71ba cleanup 2025-06-30 09:23:57 -05:00
J. Nick Koston
26980df2b9 Merge branch 'idf_webserver_ota' into integration 2025-06-30 08:25:08 -05:00
J. Nick Koston
ffe39473d0 fixes 2025-06-30 08:18:34 -05:00
J. Nick Koston
6af8d152ee fixes 2025-06-30 08:18:18 -05:00
J. Nick Koston
de846a8f7a Merge branch 'idf_webserver_ota' into integration 2025-06-30 07:54:26 -05:00
J. Nick Koston
8e31316e3d Merge remote-tracking branch 'upstream/dev' into idf_webserver_ota 2025-06-30 07:51:22 -05:00
J. Nick Koston
fb6edb3243 fixes 2025-06-30 07:51:11 -05:00
J. Nick Koston
244bd9256f tidy 2025-06-30 06:55:08 -05:00
J. Nick Koston
1f61fd383c Merge branch 'dev' into esp32_touch_isr 2025-06-30 01:06:49 -05:00
J. Nick Koston
ce294ce0c1 Merge branch 'idf_webserver_ota' into integration 2025-06-30 01:01:29 -05:00
J. Nick Koston
dcbdc0ac51 Merge branch 'dev' into esp32_touch_isr 2025-06-30 00:59:07 -05:00
J. Nick Koston
daea06586d Merge branch 'update_libsodium' into integration 2025-06-30 00:54:49 -05:00
J. Nick Koston
9c8bf2587b Merge remote-tracking branch 'origin/update_libsodium' into update_libsodium 2025-06-30 00:50:31 -05:00
J. Nick Koston
9871cb04ea 0.1.10 2025-06-30 00:50:18 -05:00
J. Nick Koston
7dc093815f reduce 2025-06-29 23:40:09 -05:00
J. Nick Koston
087697106c remove debug 2025-06-29 23:32:59 -05:00
J. Nick Koston
9beebc7bfe Merge branch 'dev' into idf_webserver_ota 2025-06-29 23:22:34 -05:00
J. Nick Koston
4a948b7aae Merge branch 'dev' into update_libsodium 2025-06-29 23:20:30 -05:00
J. Nick Koston
0d3bc21e97 Merge branch 'dev' from upstream
Resolved conflicts in:
- esphome/components/api/list_entities.h
- esphome/components/api/subscribe_state.h

Both conflicts were about NOLINT comment style - chose upstream's inline comment format.
2025-06-29 23:18:41 -05:00
J. Nick Koston
7496894ae6 0.1.9 2025-06-29 23:16:20 -05:00
J. Nick Koston
918d7217a9 fix 2025-06-29 23:15:28 -05:00
J. Nick Koston
2103d583f9 bump to 0.1.8 2025-06-29 23:12:48 -05:00
J. Nick Koston
837c446926 Merge branch 'dev' from upstream 2025-06-29 23:10:20 -05:00
J. Nick Koston
480ea54ee0 Merge branch 'dev' into update_libsodium 2025-06-29 22:49:46 -05:00
J. Nick Koston
97e7c34cb6 Merge branch 'dev' into idf_webserver_ota 2025-06-29 22:41:30 -05:00
J. Nick Koston
fe65b149f5 tweak 2025-06-29 22:34:42 -05:00
J. Nick Koston
4106b97174 tweak 2025-06-29 22:31:47 -05:00
J. Nick Koston
8648954b94 tweak 2025-06-29 22:29:40 -05:00
J. Nick Koston
9f1fae0955 tweak 2025-06-29 22:27:36 -05:00
Jesse Hills
1d631c3c6d Update platformio.ini 2025-06-30 15:26:14 +12:00
J. Nick Koston
727161f1db tweak 2025-06-29 22:24:28 -05:00
Jesse Hills
bf5f628769 Update esphome/components/api/__init__.py 2025-06-30 15:23:40 +12:00
J. Nick Koston
8563a5785f tweak 2025-06-29 22:19:29 -05:00
J. Nick Koston
4082634e6d tweak 2025-06-29 22:14:15 -05:00
J. Nick Koston
a74adb5865 tweak 2025-06-29 22:13:56 -05:00
J. Nick Koston
2e4d7301f2 tweak 2025-06-29 22:12:36 -05:00
J. Nick Koston
94845222ad tweak 2025-06-29 22:12:20 -05:00
J. Nick Koston
7f6ac2deee tweak 2025-06-29 22:10:50 -05:00
J. Nick Koston
a054aa9c52 clean 2025-06-29 21:57:50 -05:00
J. Nick Koston
22cb59b88c clean 2025-06-29 21:55:13 -05:00
J. Nick Koston
6968772a31 preen 2025-06-29 21:48:35 -05:00
J. Nick Koston
004f4b51d1 preen 2025-06-29 21:41:57 -05:00
J. Nick Koston
8c8dd7b4bc preen 2025-06-29 21:40:20 -05:00
J. Nick Koston
9778289d33 revert 2025-06-29 21:36:25 -05:00
J. Nick Koston
a43caf08a6 cleanup 2025-06-29 21:31:54 -05:00
J. Nick Koston
01e550fac9 cleanup 2025-06-29 21:13:05 -05:00
J. Nick Koston
ad4dd6a060 cleanup 2025-06-29 21:07:39 -05:00
J. Nick Koston
849d99b0dc cleanup 2025-06-29 21:06:04 -05:00
J. Nick Koston
f5df5f71a3 cleanup 2025-06-29 21:04:45 -05:00
J. Nick Koston
429be0a5ae cleanup 2025-06-29 21:03:13 -05:00
J. Nick Koston
148e4ec555 cleanup 2025-06-29 20:59:51 -05:00
J. Nick Koston
bb22f4d6a3 cleanup 2025-06-29 20:54:36 -05:00
J. Nick Koston
f94703360b cleanup 2025-06-29 20:54:13 -05:00
J. Nick Koston
f26bec1a5a preen 2025-06-29 20:18:32 -05:00
J. Nick Koston
d065f4ae62 cleanup 2025-06-29 20:15:18 -05:00
J. Nick Koston
ed2c3e626b cleanup 2025-06-29 19:53:29 -05:00
J. Nick Koston
1927f92358 cleanup 2025-06-29 19:49:01 -05:00
J. Nick Koston
939144174c cleanup 2025-06-29 19:32:43 -05:00
J. Nick Koston
59bcbe7fef proper state machine 2025-06-29 19:31:01 -05:00
J. Nick Koston
8e00fedc67 rwatchdog 2025-06-29 19:24:40 -05:00
J. Nick Koston
0ac879ae0b remove 2025-06-29 19:22:13 -05:00
J. Nick Koston
22d1a18d22 Merge remote-tracking branch 'upstream/dev' into idf_webserver_ota 2025-06-29 19:19:32 -05:00
J. Nick Koston
ca203bff9b cleanup 2025-06-29 19:18:33 -05:00
J. Nick Koston
e01d16ce82 cleanup 2025-06-29 19:07:47 -05:00
J. Nick Koston
93b6b9835c cleanup 2025-06-29 19:04:54 -05:00
J. Nick Koston
d0ac5388d9 cleanup 2025-06-29 19:03:54 -05:00
J. Nick Koston
9097d646ca cleanup 2025-06-29 19:03:48 -05:00
J. Nick Koston
596a28e1fb cleanup 2025-06-29 19:00:07 -05:00
J. Nick Koston
5205ff5c43 cleanup 2025-06-29 18:59:09 -05:00
J. Nick Koston
c420bf5f4f cleanup 2025-06-29 18:55:46 -05:00
J. Nick Koston
18844e15dc cleanup 2025-06-29 18:54:48 -05:00
J. Nick Koston
af2f5b7348 cleanup 2025-06-29 18:54:14 -05:00
J. Nick Koston
bcbf0f0e26 cleanup 2025-06-29 18:53:43 -05:00
J. Nick Koston
4d460d4bc3 cleanup 2025-06-29 18:51:35 -05:00
J. Nick Koston
92f6f3ac0d cleanup 2025-06-29 18:48:30 -05:00
J. Nick Koston
bc63d246c8 cleanup 2025-06-29 18:46:15 -05:00
J. Nick Koston
b25f272d72 lint 2025-06-29 18:44:14 -05:00
J. Nick Koston
e3a3305adb delete 2025-06-29 18:44:02 -05:00
J. Nick Koston
c655c4e106 remove cruft 2025-06-29 18:39:17 -05:00
J. Nick Koston
7fe8cdaa34 remove cruft 2025-06-29 18:37:48 -05:00
J. Nick Koston
df97985048 Merge remote-tracking branch 'origin/integration' into integration 2025-06-29 18:33:46 -05:00
J. Nick Koston
3779675816 Merge branch 'binary_sensor_gpio_polling' into integration 2025-06-29 18:33:34 -05:00
J. Nick Koston
0005aad5b5 cleanup 2025-06-29 18:30:00 -05:00
J. Nick Koston
98c18517e2 Merge branch 'another_webserver_crash' into idf_webserver_ota 2025-06-29 18:23:25 -05:00
J. Nick Koston
e4dee935ce Fix thread-safe cleanup of event source connections in ESP-IDF web server 2025-06-29 18:21:24 -05:00
J. Nick Koston
f8cb44fb3c fixes 2025-06-29 17:54:11 -05:00
J. Nick Koston
101901fdb8 Merge remote-tracking branch 'upstream/loop_enable_disable_log_spam' into idf_webserver_ota 2025-06-29 17:41:04 -05:00
J. Nick Koston
b8579d2040 Reduce loop enable/disable log spam by using very verbose level 2025-06-29 17:39:48 -05:00
J. Nick Koston
3fca3df756 working 2025-06-29 17:22:33 -05:00
J. Nick Koston
2f5db85997 Merge remote-tracking branch 'upstream/last_Event_fix' into idf_webserver_ota 2025-06-29 16:54:00 -05:00
Jesse Hills
e0d4361875 Update esphome/components/gpio/binary_sensor/__init__.py 2025-06-30 09:53:54 +12:00
J. Nick Koston
30bafc43bd make bot happy 2025-06-29 16:52:55 -05:00
J. Nick Koston
3530437b48 Merge branch 'last_Event_fix' into idf_webserver_ota 2025-06-29 16:19:20 -05:00
J. Nick Koston
81db42942c Fix crash when event last_event_type is null in web_server 2025-06-29 16:16:53 -05:00
J. Nick Koston
6cb0d9e0b5 fixes 2025-06-29 16:11:33 -05:00
J. Nick Koston
19f7e36753 fixes 2025-06-29 16:10:58 -05:00
J. Nick Koston
a963f97520 fixes 2025-06-29 16:07:26 -05:00
J. Nick Koston
ad2d48e9b7 fixes 2025-06-29 16:03:05 -05:00
J. Nick Koston
5c0d67ca14 fixes 2025-06-29 15:50:12 -05:00
J. Nick Koston
3467329a7c cleanup 2025-06-29 15:43:41 -05:00
J. Nick Koston
d73fa370f3 cleanup 2025-06-29 15:35:59 -05:00
J. Nick Koston
78fd0a4870 cleanup 2025-06-29 15:23:32 -05:00
J. Nick Koston
3162bb475d cleanup 2025-06-29 15:08:27 -05:00
J. Nick Koston
c17503abd5 cleanup 2025-06-29 15:03:48 -05:00
J. Nick Koston
3433ee8171 cleanup 2025-06-29 14:59:41 -05:00
J. Nick Koston
344297b0a7 cleanup 2025-06-29 14:51:24 -05:00
J. Nick Koston
947456628e cleanup 2025-06-29 14:51:01 -05:00
J. Nick Koston
80dd6c111d cleanup 2025-06-29 14:44:47 -05:00
J. Nick Koston
b70188ba4b cleanup 2025-06-29 14:40:13 -05:00
J. Nick Koston
c6064aa2b4 Merge remote-tracking branch 'upstream/dev' into idf_webserver_ota 2025-06-29 14:35:44 -05:00
J. Nick Koston
6596f864be merg3 2025-06-29 14:35:38 -05:00
J. Nick Koston
f61a40efb8 fixes 2025-06-29 11:16:00 -05:00
J. Nick Koston
b049f0b480 fixes 2025-06-29 11:13:25 -05:00
J. Nick Koston
b2641d29c1 fixes 2025-06-29 11:12:40 -05:00
J. Nick Koston
7b8cfc768d fixes 2025-06-29 11:11:47 -05:00
J. Nick Koston
04860567f7 fixes 2025-06-29 11:10:29 -05:00
J. Nick Koston
b16edb5a99 fixes 2025-06-29 11:09:05 -05:00
J. Nick Koston
15a995b2e7 fixes 2025-06-29 11:07:48 -05:00
J. Nick Koston
f57e26c54e fixes 2025-06-29 11:07:25 -05:00
J. Nick Koston
2b7bc1cd9f fixes 2025-06-29 11:03:37 -05:00
J. Nick Koston
614a2f66a3 fixes 2025-06-29 10:57:00 -05:00
J. Nick Koston
9047b02c92 fixes 2025-06-29 10:53:29 -05:00
J. Nick Koston
e73d0477bb Merge branch 'api_conditional_memory' into integration 2025-06-29 10:42:24 -05:00
J. Nick Koston
2b1e623eb4 defines 2025-06-29 10:42:11 -05:00
J. Nick Koston
c366d555e9 Add OTA support to ESP-IDF webserver 2025-06-29 10:38:53 -05:00
J. Nick Koston
7efbd62730 Add OTA support to ESP-IDF webserver 2025-06-29 10:34:49 -05:00
J. Nick Koston
b77c1d0af8 Add OTA support to ESP-IDF webserver 2025-06-29 10:33:49 -05:00
J. Nick Koston
f8810ea6a8 Merge branch 'webserver_eliminate_heap_url_match' into integration 2025-06-29 10:26:55 -05:00
J. Nick Koston
40dd667211 fixes 2025-06-29 10:26:39 -05:00
J. Nick Koston
848b572864 Merge branch 'webserver_eliminate_heap_url_match' into integration 2025-06-29 10:17:49 -05:00
J. Nick Koston
7c858fbccd Optimize web_server UrlMatch to avoid heap allocations 2025-06-29 10:15:06 -05:00
J. Nick Koston
a1814ea37d Merge branch 'useless_default_data' into integration 2025-06-29 09:22:57 -05:00
J. Nick Koston
5892a1dbe2 tests 2025-06-29 08:40:26 -05:00
J. Nick Koston
29f524f432 tests 2025-06-29 08:37:53 -05:00
J. Nick Koston
4ec588ebd7 Merge remote-tracking branch 'origin/integration' into integration 2025-06-29 08:20:36 -05:00
J. Nick Koston
efdef61477 Merge branch 'api_reduce' into integration 2025-06-29 08:20:22 -05:00
J. Nick Koston
fe2b9f8c12 correct fix 2025-06-29 08:20:12 -05:00
J. Nick Koston
c6be55eb55 Merge branch 'api_conditional_memory' into integration 2025-06-29 08:14:25 -05:00
J. Nick Koston
4c69925b84 lint 2025-06-29 08:13:28 -05:00
J. Nick Koston
bc6407df0a Merge branch 'bitpack_api' into integration 2025-06-29 08:09:52 -05:00
J. Nick Koston
01982a8d0a reduce upper bound of batch delay as it did not make sense 2025-06-29 07:59:59 -05:00
J. Nick Koston
b995cd6257 Merge remote-tracking branch 'origin/integration' into integration 2025-06-29 07:47:28 -05:00
J. Nick Koston
b16d7b7a95 Merge branch 'api_conditional_memory' into integration 2025-06-29 07:47:17 -05:00
J. Nick Koston
42aea701d3 Reduce API component memory usage with conditional compilation 2025-06-29 07:45:48 -05:00
J. Nick Koston
5f56c85182 Merge remote-tracking branch 'origin/integration' into integration 2025-06-29 07:42:05 -05:00
J. Nick Koston
52b4eb8950 Merge branch 'api_reduce' into integration 2025-06-29 07:41:00 -05:00
J. Nick Koston
eeb2b42a0f fixes 2025-06-29 07:39:07 -05:00
J. Nick Koston
90772033d1 revert bad feedback 2025-06-29 06:10:55 -05:00
J. Nick Koston
dadeb4d2a9 Merge branch 'api_reduce' into integration 2025-06-28 23:24:40 -05:00
J. Nick Koston
60a5029c88 lint 2025-06-28 23:24:30 -05:00
J. Nick Koston
d7ba16b48b Merge branch 'api_reduce' into integration 2025-06-28 23:06:51 -05:00
J. Nick Koston
fca9befa63 cleanup 2025-06-28 23:06:40 -05:00
J. Nick Koston
187cbde0db cleanup 2025-06-28 23:06:34 -05:00
J. Nick Koston
f5ae5cade8 cleanup 2025-06-28 23:06:09 -05:00
J. Nick Koston
3e66c28aff Merge branch 'api_reduce' into integration 2025-06-28 23:05:15 -05:00
J. Nick Koston
89703a1aef cleanup 2025-06-28 23:05:02 -05:00
J. Nick Koston
cba31617e9 Merge branch 'api_reduce' into integration 2025-06-28 23:02:05 -05:00
J. Nick Koston
a3eeb46961 reduce 2025-06-28 23:01:48 -05:00
J. Nick Koston
128bd76f20 reduce 2025-06-28 22:45:00 -05:00
J. Nick Koston
c0355fd2c6 Merge branch 'webserver_helper_reduce_flash' into integration 2025-06-28 22:09:03 -05:00
J. Nick Koston
a5fd440e25 cleanup 2025-06-28 22:08:47 -05:00
J. Nick Koston
592ef8be2a Merge remote-tracking branch 'origin/integration' into integration 2025-06-28 22:04:41 -05:00
J. Nick Koston
3bcc1c7297 Merge branch 'add_message_object' into integration 2025-06-28 22:04:27 -05:00
J. Nick Koston
3b44c3acd1 Reduce flash usage by making add_message_object non-template 2025-06-28 22:03:04 -05:00
J. Nick Koston
ec4911643a Merge remote-tracking branch 'upstream/integration' into integration 2025-06-28 21:40:44 -05:00
J. Nick Koston
f4fedbab44 Merge branch 'webserver_helper_reduce_flash' into integration 2025-06-28 21:40:26 -05:00
J. Nick Koston
553d441ecc Reduce web_server code duplication by extracting detail parameter parsing 2025-06-28 21:38:40 -05:00
J. Nick Koston
1946116438 Merge branch 'api_read_message' into integration 2025-06-28 21:22:25 -05:00
J. Nick Koston
ab28515fba fix 2025-06-28 21:17:59 -05:00
J. Nick Koston
4dc11fb95e Merge branch 'api_read_message' into integration 2025-06-28 21:11:16 -05:00
J. Nick Koston
e27094e0f3 Remove unused return value from read_message and fix ifdef placement in generated API code 2025-06-28 21:09:33 -05:00
J. Nick Koston
88302201eb Merge remote-tracking branch 'origin/integration' into integration 2025-06-28 20:56:24 -05:00
J. Nick Koston
8afb172e83 Merge branch 'api_reduce' into integration 2025-06-28 20:56:00 -05:00
J. Nick Koston
562d024623 Remove single-use send_*_info wrappers in API connection 2025-06-28 20:49:09 -05:00
J. Nick Koston
50b094547c Remove single-use send_*_info wrappers in API connection 2025-06-28 20:47:57 -05:00
J. Nick Koston
a6c1e50985 Remove single-use send_*_info wrappers in API connection 2025-06-28 20:46:17 -05:00
J. Nick Koston
96772bdfc6 Merge remote-tracking branch 'origin/integration' into integration 2025-06-28 20:13:13 -05:00
J. Nick Koston
ed154d373c Merge remote-tracking branch 'origin/dev' into integration 2025-06-28 20:12:59 -05:00
J. Nick Koston
a5e862ce36 Remove redundant get_setup_priority() overrides returning default value 2025-06-28 17:21:20 -05:00
J. Nick Koston
ae55964bd9 Merge remote-tracking branch 'origin/bitpack_api' into integration 2025-06-28 16:47:43 -05:00
J. Nick Koston
c162309f41 Pack APIConnection members to reduce memory footprint 2025-06-28 16:46:17 -05:00
J. Nick Koston
62c667f1a0 Merge remote-tracking branch 'origin/dev' into integration 2025-06-28 16:11:15 -05:00
J. Nick Koston
3d08eae8e4 Merge branch 'scheduler_copy' into integration 2025-06-28 15:52:09 -05:00
J. Nick Koston
2af5a0a6dd Merge remote-tracking branch 'origin/scheduler_copy' into scheduler_copy 2025-06-28 15:52:03 -05:00
J. Nick Koston
6d24b04235 cover 2025-06-28 15:51:50 -05:00
J. Nick Koston
3ee8103353 Merge branch 'scheduler_copy' into integration 2025-06-28 15:49:33 -05:00
J. Nick Koston
1296165fce Merge branch 'dev' into scheduler_copy 2025-06-28 15:48:11 -05:00
J. Nick Koston
7100c22dc4 address copilot comments 2025-06-28 15:47:24 -05:00
J. Nick Koston
5718c0f5b8 Update test_scheduler_string_test.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-28 11:25:42 -05:00
J. Nick Koston
25ebddfa1c Update test_scheduler_string_test.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-28 11:25:36 -05:00
J. Nick Koston
2c0558fe23 Update test_scheduler_string_test.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-28 11:25:30 -05:00
J. Nick Koston
7192108fc1 Merge branch 'scheduler_copy' into integration 2025-06-28 10:32:21 -05:00
J. Nick Koston
847696c342 safer 2025-06-28 10:32:10 -05:00
J. Nick Koston
912ae1fc87 Merge remote-tracking branch 'origin/integration' into integration 2025-06-28 10:28:35 -05:00
J. Nick Koston
a86f75d31d Merge branch 'scheduler_copy' into integration 2025-06-28 10:28:22 -05:00
J. Nick Koston
fe1e25b5c7 Merge remote-tracking branch 'upstream/integration' into integration 2025-06-28 10:22:18 -05:00
J. Nick Koston
9b241b596a Merge branch 'scheduler_copy' into integration 2025-06-28 10:22:07 -05:00
J. Nick Koston
53b9c8d5bb cleanup 2025-06-28 10:15:05 -05:00
J. Nick Koston
2946bc9d72 cover 2025-06-28 10:10:43 -05:00
J. Nick Koston
67a20e212d safe 2025-06-28 09:59:50 -05:00
J. Nick Koston
a9ace366eb dry 2025-06-28 09:50:27 -05:00
J. Nick Koston
df3469efba dry 2025-06-28 09:48:58 -05:00
J. Nick Koston
0a3bbb8554 dry 2025-06-28 09:48:26 -05:00
J. Nick Koston
a15b9f5d3b dry 2025-06-28 09:45:59 -05:00
J. Nick Koston
e6334b0716 dry 2025-06-28 09:41:12 -05:00
J. Nick Koston
7a835baa5a Merge remote-tracking branch 'upstream/dev' into scheduler_copy 2025-06-28 09:36:32 -05:00
J. Nick Koston
c9c21a5728 Merge remote-tracking branch 'upstream/dev' into integration 2025-06-28 09:36:07 -05:00
J. Nick Koston
956959fc32 safety 2025-06-28 09:23:16 -05:00
J. Nick Koston
6f67f74638 Merge remote-tracking branch 'upstream/dev' into integration 2025-06-28 08:43:19 -05:00
J. Nick Koston
b3dd4543b7 Merge branch 'update_libsodium' into integration 2025-06-27 17:10:52 -05:00
J. Nick Koston
4f17a28ac5 Merge branch 'extract_helpers' into integration 2025-06-27 17:10:17 -05:00
J. Nick Koston
90736f367a release 2025-06-27 16:36:32 -05:00
J. Nick Koston
9af88bd482 DNM: Update libsodium
needs https://github.com/esphome/noise-c/pull/4
2025-06-27 14:07:27 -05:00
J. Nick Koston
13b89f4934 Merge branch 'libretiny_logconfig' into integration 2025-06-27 13:59:01 -05:00
J. Nick Koston
d00a00d142 Reduce libretiny logconfig messages
align with https://developers.esphome.io/architecture/logging
2025-06-27 13:58:33 -05:00
J. Nick Koston
e662c39e16 Merge branch 'extract_helpers' into integration 2025-06-27 13:18:50 -05:00
J. Nick Koston
95ef131285 address bot comments 2025-06-27 13:18:39 -05:00
J. Nick Koston
7476f170f6 Merge remote-tracking branch 'upstream/extract_helpers' into extract_helpers 2025-06-27 13:16:17 -05:00
J. Nick Koston
3b6bd55d1e address bot comments 2025-06-27 13:16:06 -05:00
J. Nick Koston
10dbc9e884 Merge remote-tracking branch 'origin/extract_helpers' into integration 2025-06-27 13:03:20 -05:00
J. Nick Koston
860f619dfe Merge branch 'dev' into extract_helpers 2025-06-27 20:02:57 +02:00
J. Nick Koston
17ddc9ee0c Merge branch 'extract_helpers' into integration 2025-06-27 12:56:28 -05:00
J. Nick Koston
949689c318 address bot review 2025-06-27 12:55:58 -05:00
J. Nick Koston
86a2aac011 Merge branch 'extract_helpers' into integration 2025-06-27 12:50:37 -05:00
J. Nick Koston
d0a402f201 Extract lock-free queue and event pool to core helpers 2025-06-27 12:49:44 -05:00
J. Nick Koston
05772d5365 Merge remote-tracking branch 'origin/integration' into integration 2025-06-27 10:19:35 -05:00
J. Nick Koston
c2a68f5147 Merge branch 'duplicate_webserver_code' into integration 2025-06-27 10:19:21 -05:00
J. Nick Koston
697ca1c7be simplify 2025-06-27 10:17:33 -05:00
J. Nick Koston
409346952f clang-format 2025-06-27 10:15:04 -05:00
J. Nick Koston
f4b3539d77 clang-format 2025-06-27 10:05:30 -05:00
J. Nick Koston
c12166c1a1 missed one 2025-06-27 10:04:29 -05:00
J. Nick Koston
8d20f003cb Merge branch 'duplicate_webserver_code' into integration 2025-06-27 09:45:00 -05:00
J. Nick Koston
88f857a2f0 defines 2025-06-27 09:44:50 -05:00
J. Nick Koston
fb7faadd99 reduce memory 2025-06-27 09:41:20 -05:00
J. Nick Koston
5c8d6752fb Merge branch 'dev' into duplicate_webserver_code 2025-06-27 16:01:32 +02:00
J. Nick Koston
dda81fbc2c Merge branch 'dev' into binary_sensor_gpio_polling 2025-06-27 15:58:14 +02:00
J. Nick Koston
c40dff5d63 cleanup 2025-06-27 06:30:51 -05:00
J. Nick Koston
6f07b54772 cleanup 2025-06-27 06:30:42 -05:00
J. Nick Koston
ce0f1dfcb6 Merge remote-tracking branch 'upstream/dev' into integration 2025-06-27 06:30:15 -05:00
J. Nick Koston
9a3a5d48eb Merge branch 'dynamic_logging' into integration 2025-06-26 20:47:40 -05:00
J. Nick Koston
4a759eda02 Disable dynamic log level control for ESP32 ESP-IDF builds 2025-06-26 20:47:02 -05:00
J. Nick Koston
26badf201d fixes 2025-06-27 01:17:26 +02:00
J. Nick Koston
384f27cd6d Merge branch 'wifi_memory' into integration 2025-06-27 01:13:11 +02:00
J. Nick Koston
ac1c5f9f58 Reduce WiFi component memory usage 2025-06-27 01:12:19 +02:00
J. Nick Koston
8ad058fdf4 Merge branch 'ethernet_padding' into integration 2025-06-27 01:00:27 +02:00
J. Nick Koston
9024c3c67a Reduce ethernet component memory usage by 8 bytes through struct optimization 2025-06-27 00:59:50 +02:00
J. Nick Koston
fc81a47499 Merge branch 'esp32_gpio_padding_waste' into integration 2025-06-27 00:43:41 +02:00
J. Nick Koston
a331452076 Reduce ESP32 GPIO memory usage by optimizing struct padding 2025-06-27 00:42:30 +02:00
J. Nick Koston
b1c6e8168e Merge remote-tracking branch 'origin/ota_memory_str' into integration 2025-06-27 00:34:36 +02:00
J. Nick Koston
b41cc0226e Optimize OTA password storage from std::string to const char 2025-06-27 00:24:45 +02:00
J. Nick Koston
450429ddd5 Merge branch 'safe_mode_padding' into integration 2025-06-27 00:22:40 +02:00
J. Nick Koston
f7b24f4b4b Optimize SafeModeComponent memory layout to reduce padding 2025-06-27 00:20:44 +02:00
J. Nick Koston
294c985380 Merge branch 'duplicate_webserver_code' into integration 2025-06-27 00:09:07 +02:00
J. Nick Koston
720964b901 Refactor web_server to extract duplicate sorting info code into helper method 2025-06-27 00:05:56 +02:00
J. Nick Koston
8895c8a987 bitpack api flags 2025-06-26 12:46:57 +02:00
J. Nick Koston
740dcd72a2 Merge branch 'duplicate_client_peername' into integration 2025-06-26 12:00:03 +02:00
J. Nick Koston
ffd442624f Optimize API connection memory usage by removing client_peername_ 2025-06-26 11:59:03 +02:00
J. Nick Koston
088fd85694 Merge branch 'batch_ping_fallback' into integration 2025-06-26 10:14:21 +02:00
J. Nick Koston
d5b68d69d3 tweak 2025-06-26 10:14:05 +02:00
J. Nick Koston
bb0f7bb393 Merge branch 'batch_ping_fallback' into integration 2025-06-26 10:10:12 +02:00
J. Nick Koston
d86a108f18 Merge remote-tracking branch 'upstream/dev' into batch_ping_fallback 2025-06-26 10:09:24 +02:00
J. Nick Koston
7828ed2d9e Merge branch 'batch_ping_fallback' into integration 2025-06-26 10:05:06 +02:00
J. Nick Koston
ebf14f50fb Merge branch 'dev' of https://github.com/esphome/esphome into batch_ping_fallback 2025-06-26 10:02:32 +02:00
J. Nick Koston
1546ff615b Merge branch 'app_padding' into integration 2025-06-26 02:47:46 +02:00
J. Nick Koston
46cf1fb597 comment 2025-06-26 02:47:33 +02:00
J. Nick Koston
8bf8655054 Merge branch 'app_padding' into integration 2025-06-26 02:45:13 +02:00
J. Nick Koston
a6d84948e2 Optimize Application class memory layout and reduce loop_interval size 2025-06-26 02:44:44 +02:00
J. Nick Koston
fac20a1f97 Merge branch 'batch_ping_fallback' into integration 2025-06-26 02:15:41 +02:00
J. Nick Koston
c65586b5e1 cleanup 2025-06-26 02:15:32 +02:00
J. Nick Koston
b27b018b06 Merge remote-tracking branch 'origin/integration' into integration 2025-06-26 02:13:42 +02:00
J. Nick Koston
403da1e632 Merge branch 'batch_ping_fallback' into integration 2025-06-26 02:12:53 +02:00
J. Nick Koston
2371ec1f9e Replace ping retry timer with batch queue fallback 2025-06-26 02:11:17 +02:00
J. Nick Koston
5e3ec2d34b lint 2025-06-26 00:24:53 +02:00
J. Nick Koston
78d84644c9 lint 2025-06-26 00:24:12 +02:00
J. Nick Koston
0cd0f8015a Merge branch 'message_creator_ram' into integration 2025-06-26 00:09:31 +02:00
J. Nick Koston
4b5424f695 nolint 2025-06-26 00:08:15 +02:00
J. Nick Koston
a1d59040f7 Merge remote-tracking branch 'origin/message_creator_ram' into integration 2025-06-25 23:54:37 +02:00
J. Nick Koston
0306398072 Merge remote-tracking branch 'origin/component_iterator' into integration 2025-06-25 23:54:33 +02:00
J. Nick Koston
a7e0bf9013 tweak 2025-06-25 23:53:22 +02:00
J. Nick Koston
ddb988cd83 Merge remote-tracking branch 'upstream/dev' into component_iterator 2025-06-25 23:39:45 +02:00
J. Nick Koston
04b54353f1 Merge remote-tracking branch 'upstream/dev' into scheduler_copy 2025-06-25 23:36:41 +02:00
J. Nick Koston
f058107c05 tweak 2025-06-25 23:33:54 +02:00
J. Nick Koston
6b5b0815d7 tidy issues 2025-06-25 23:26:57 +02:00
J. Nick Koston
8388497038 tidy issues 2025-06-25 23:18:50 +02:00
J. Nick Koston
825b1113b6 tweak 2025-06-25 23:17:41 +02:00
J. Nick Koston
9074ef792f Reduce component_iterator memory usage 2025-06-25 19:35:40 +02:00
J. Nick Koston
0946f28511 avoid string copy in scheduler for const strings 2025-06-25 19:08:18 +02:00
J. Nick Koston
23765cd4f5 Merge branch 'message_creator_ram' into integration 2025-06-25 18:28:56 +02:00
J. Nick Koston
e20c6468d0 fix missed one 2025-06-25 18:27:43 +02:00
J. Nick Koston
b90516de1d Merge branch 'template_value' into integration 2025-06-25 17:30:36 +02:00
J. Nick Koston
ec5cc0f00f Merge branch 'integration' of https://github.com/esphome/esphome into integration 2025-06-25 17:30:27 +02:00
J. Nick Koston
5dda5a976e Merge branch 'message_creator_ram' into integration 2025-06-25 17:22:41 +02:00
J. Nick Koston
915da9ae13 make the bot happy 2025-06-25 17:22:23 +02:00
J. Nick Koston
8652464f4e Merge branch 'dev' into message_creator_ram 2025-06-25 17:16:31 +02:00
J. Nick Koston
ce6ce1c1f8 Merge branch 'message_creator_ram' into integration 2025-06-25 17:10:41 +02:00
J. Nick Koston
39efe67e55 Optimize API connection memory with tagged pointers 2025-06-25 17:08:57 +02:00
J. Nick Koston
748ffa00f3 Optimize TemplatableValue memory 2025-06-25 14:49:01 +02:00
J. Nick Koston
e8d9df2b0e Merge branch 'sensor_memory' into integration 2025-06-25 14:32:47 +02:00
J. Nick Koston
17396d67de revert 2025-06-25 14:32:38 +02:00
J. Nick Koston
edd6a86714 Merge branch 'sensor_memory' into integration 2025-06-25 14:26:03 +02:00
J. Nick Koston
85b4012c56 Merge branch 'dev' into sensor_memory 2025-06-25 14:24:09 +02:00
J. Nick Koston
7d98433502 Update tests/integration/test_host_mode_sensor.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-25 14:23:59 +02:00
J. Nick Koston
23774ae03b Reduce memory required for sensor entities 2025-06-25 14:17:05 +02:00
J. Nick Koston
0dedbcdd71 Merge branch 'multi_device' into integration 2025-06-25 13:44:20 +02:00
J. Nick Koston
4bdd08887e use a common that does not have dupes on dev 2025-06-25 00:50:18 +02:00
J. Nick Koston
1fd8ebf386 update tests now that duplicate names are validated 2025-06-25 00:35:38 +02:00
J. Nick Koston
d2fc3e749c update tests now that duplicate names are validated 2025-06-25 00:34:50 +02:00
J. Nick Koston
71fbcbceaf update tests now that duplicate names are validated 2025-06-25 00:34:27 +02:00
J. Nick Koston
27347b2088 update tests now that duplicate names are validated 2025-06-25 00:34:04 +02:00
J. Nick Koston
599993d1a5 update tests now that duplicate names are validated 2025-06-25 00:22:51 +02:00
J. Nick Koston
bf359cb8e3 update tests now that duplicate names are validated 2025-06-25 00:20:51 +02:00
J. Nick Koston
509a704410 update tests now that duplicate names are validated 2025-06-25 00:19:32 +02:00
J. Nick Koston
1f48e2b01f update tests now that duplicate names are validated 2025-06-25 00:18:40 +02:00
J. Nick Koston
8b25b1eee6 update tests now that duplicate names are validated 2025-06-25 00:18:28 +02:00
J. Nick Koston
3bbf30ff5f Merge branch 'multi_device' into integration 2025-06-25 00:04:33 +02:00
J. Nick Koston
83613726d1 fix 2025-06-25 00:04:07 +02:00
J. Nick Koston
254b6a17f3 Merge remote-tracking branch 'dala318/multi_device' into integration 2025-06-24 23:54:40 +02:00
J. Nick Koston
796e12bd70 Merge branch 'dev' into multi_device 2025-06-24 23:54:24 +02:00
J. Nick Koston
ddbe17d3f6 fixes 2025-06-24 23:40:16 +02:00
J. Nick Koston
591ec36f4a fixes 2025-06-24 23:37:58 +02:00
J. Nick Koston
41eceb72ef preen 2025-06-24 23:28:06 +02:00
J. Nick Koston
0a5f094025 cleanup 2025-06-24 23:25:46 +02:00
J. Nick Koston
ca0f3ba262 cleanup 2025-06-24 23:23:59 +02:00
J. Nick Koston
30f4e782db cleanup 2025-06-24 23:23:35 +02:00
J. Nick Koston
192158ef1a cleanup 2025-06-24 23:22:18 +02:00
J. Nick Koston
602456db40 cleanup 2025-06-24 23:13:45 +02:00
J. Nick Koston
536e45668f migrate 2025-06-24 23:09:08 +02:00
J. Nick Koston
10bf05ab0d migrate 2025-06-24 22:59:46 +02:00
J. Nick Koston
5ad1af69e4 migrate 2025-06-24 22:57:10 +02:00
J. Nick Koston
48f2911434 raise 2025-06-24 22:18:29 +02:00
J. Nick Koston
dbb0d6349a Merge branch 'multi_device' into integration 2025-06-24 18:08:14 +02:00
J. Nick Koston
ac3598f12a cleanup 2025-06-24 18:07:58 +02:00
J. Nick Koston
66201be5ca preen 2025-06-24 18:00:10 +02:00
J. Nick Koston
ac0b0b652e cleanup 2025-06-24 17:55:58 +02:00
J. Nick Koston
d89ee2df42 Update esphome/core/application.h 2025-06-24 17:52:13 +02:00
J. Nick Koston
418e248e5e cleanup 2025-06-24 17:51:05 +02:00
J. Nick Koston
8c2b141049 cleanup 2025-06-24 17:41:40 +02:00
J. Nick Koston
2f8e07302b Update esphome/core/entity_base.cpp 2025-06-24 17:10:06 +02:00
J. Nick Koston
c3776240b6 fixes 2025-06-24 17:03:23 +02:00
J. Nick Koston
e370872ec1 fix conflicts 2025-06-24 16:13:34 +02:00
Jesse Hills
d4e978369a Store reference to device on EntityBase
This is so we can get the name of the device to use as part of the object id and to internally set the name for logging.
2025-06-24 19:56:30 +12:00
Jesse Hills
8d5d7f5237 Merge branch 'dev' into multi_device 2025-06-24 16:02:03 +12:00
J. Nick Koston
5cd498fbe9 Merge branch 'multi_device' into integration 2025-06-23 22:56:28 +02:00
J. Nick Koston
250f515f08 Merge branch 'api_opt' into integration 2025-06-23 12:20:40 +02:00
J. Nick Koston
0ec0a9e313 missing ifdef 2025-06-23 12:19:21 +02:00
J. Nick Koston
184f42ef03 Merge branch 'api_opt' into integration 2025-06-23 12:10:26 +02:00
J. Nick Koston
499517418d clang-tidy 2025-06-23 12:10:15 +02:00
J. Nick Koston
606b9c1a6d Merge branch 'api_opt' into integration 2025-06-23 12:00:34 +02:00
J. Nick Koston
971e954a54 follow logging guidelines 2025-06-23 11:59:07 +02:00
J. Nick Koston
e3aaf3219d speed up test 2025-06-23 11:58:16 +02:00
J. Nick Koston
0eea1c0e40 preen 2025-06-23 11:56:09 +02:00
J. Nick Koston
0773819778 cleanup 2025-06-23 11:45:58 +02:00
J. Nick Koston
170869b7db preen 2025-06-23 11:39:25 +02:00
J. Nick Koston
5dc54782e5 preen 2025-06-23 11:38:30 +02:00
J. Nick Koston
97b26fbefe preen 2025-06-23 11:38:10 +02:00
J. Nick Koston
686cc58d6c preen 2025-06-23 11:37:59 +02:00
J. Nick Koston
76a59759b2 preen 2025-06-23 11:37:27 +02:00
J. Nick Koston
93245a24b5 preen 2025-06-23 11:36:54 +02:00
J. Nick Koston
6a22ea1c7d preen 2025-06-23 11:35:41 +02:00
J. Nick Koston
56a02409c8 preen 2025-06-23 11:34:11 +02:00
J. Nick Koston
edeafd5a53 preen 2025-06-23 11:31:38 +02:00
J. Nick Koston
f67490b69b preen 2025-06-23 11:29:04 +02:00
J. Nick Koston
b76e34fb7b preen 2025-06-23 11:25:52 +02:00
J. Nick Koston
ddbda5032b preen 2025-06-23 11:25:24 +02:00
J. Nick Koston
5898d34b0a preen 2025-06-23 11:22:45 +02:00
J. Nick Koston
b0c02341ff preen 2025-06-23 11:22:08 +02:00
J. Nick Koston
19cbc8c33b preen 2025-06-23 11:21:37 +02:00
J. Nick Koston
02e61ef5d3 preen 2025-06-23 11:20:06 +02:00
J. Nick Koston
8d5d18064d preen 2025-06-23 11:19:56 +02:00
J. Nick Koston
c5ef7ebd27 preen 2025-06-23 11:19:07 +02:00
J. Nick Koston
047a3e0e8c preen 2025-06-23 11:18:47 +02:00
J. Nick Koston
13b23f840b preen 2025-06-23 11:17:17 +02:00
J. Nick Koston
147f6012b2 preen 2025-06-23 11:16:34 +02:00
J. Nick Koston
2c315595f0 preen 2025-06-23 11:12:04 +02:00
J. Nick Koston
20405c84ac preen 2025-06-23 11:10:07 +02:00
J. Nick Koston
0bc59b97de more api loop reductions 2025-06-23 11:06:51 +02:00
J. Nick Koston
a3a3bdc7eb more api loop reductions 2025-06-23 11:02:27 +02:00
J. Nick Koston
e767f30886 more api loop reductions 2025-06-23 10:59:49 +02:00
J. Nick Koston
e8c250a03c more api loop reductions 2025-06-23 10:59:00 +02:00
J. Nick Koston
d6725fc1ca more api loop reductions 2025-06-23 10:54:50 +02:00
J. Nick Koston
8ec998ff30 more api loop reductions 2025-06-23 10:52:34 +02:00
J. Nick Koston
23cc0c7f39 Merge remote-tracking branch 'upstream/dev' into api_reboot 2025-06-23 10:48:26 +02:00
J. Nick Koston
19b8bd6aa8 Merge remote-tracking branch 'upstream/logger_disable_loop' into integration 2025-06-23 09:03:16 +02:00
J. Nick Koston
ed57e7c6b0 Update esphome/components/logger/logger.cpp 2025-06-23 09:02:22 +02:00
J. Nick Koston
9f489c9f27 Update esphome/components/logger/logger.h 2025-06-23 09:01:21 +02:00
J. Nick Koston
f036989361 Update esphome/components/logger/logger.h 2025-06-23 09:01:01 +02:00
J. Nick Koston
6afa8141c0 Update esphome/components/logger/logger.cpp 2025-06-23 09:00:46 +02:00
J. Nick Koston
587964c6f1 Merge branch 'dev' into logger_disable_loop 2025-06-23 09:00:22 +02:00
Jesse Hills
7aea82a273 Move define 2025-06-23 14:15:10 +12:00
J. Nick Koston
20f946ccaf Merge branch 'dev' into multi_device 2025-06-23 00:32:09 +02:00
Jesse Hills
e5e972231c Update testing 2025-06-23 10:26:31 +12:00
J. Nick Koston
bfa80157f2 Merge branch 'scheduler_memory_opt' into integration 2025-06-23 00:07:43 +02:00
J. Nick Koston
99b1b079d0 Reduce RAM usage for scheduled tasks 2025-06-23 00:03:01 +02:00
J. Nick Koston
5697d549a8 Use scheduler for api reboot 2025-06-22 23:44:08 +02:00
Jesse Hills
754d2874e7 `this->` 2025-06-23 09:21:29 +12:00
Jesse Hills
06de58ff8b Dont need to warning about simple string area
A single device in a single area can have a simple string as the area
2025-06-23 09:20:53 +12:00
J. Nick Koston
a0b3527710 Merge branch 'logger_memory' into integration 2025-06-22 22:59:51 +02:00
J. Nick Koston
df24f48fa1 Merge branch 'pre_preserve_looping_components' into integration 2025-06-22 22:57:38 +02:00
J. Nick Koston
13d53590b2 Pre-reserve looping components vector to reduce memory allocations 2025-06-22 22:56:31 +02:00
J. Nick Koston
5857f7b9a7 Merge remote-tracking branch 'dala318/multi_device' into multi_device 2025-06-22 21:55:46 +02:00
J. Nick Koston
a5ea0cd41f remove unreachable code 2025-06-22 21:55:23 +02:00
J. Nick Koston
d677934417 Merge branch 'dev' into multi_device 2025-06-22 21:45:28 +02:00
J. Nick Koston
ba87a0b63c cleanups 2025-06-22 21:32:20 +02:00
J. Nick Koston
b725bb3dd1 lint 2025-06-22 21:28:16 +02:00
J. Nick Koston
c34ba3deb5 lint 2025-06-22 21:25:55 +02:00
J. Nick Koston
68b13340fb lint 2025-06-22 21:24:17 +02:00
J. Nick Koston
8831999ea6 lint 2025-06-22 21:23:41 +02:00
J. Nick Koston
c1853f8b84 document design decisions 2025-06-22 21:21:29 +02:00
J. Nick Koston
2b9b7e2853 validation should happen sooner 2025-06-22 21:18:04 +02:00
J. Nick Koston
d3b18debf9 validate sooner 2025-06-22 21:06:33 +02:00
J. Nick Koston
b01eb28d42 validate sooner 2025-06-22 21:05:15 +02:00
J. Nick Koston
02019dd16c validate sooner 2025-06-22 21:04:42 +02:00
J. Nick Koston
7be12f5ff6 validate sooner 2025-06-22 20:59:54 +02:00
J. Nick Koston
a90d59b6ba validate sooner 2025-06-22 20:59:07 +02:00
J. Nick Koston
e7fa156254 Merge remote-tracking branch 'upstream/dev' into integration 2025-06-22 20:15:02 +02:00
J. Nick Koston
a8ab6b1c43 Merge branch 'dev' into logger_disable_loop 2025-06-22 20:12:17 +02:00
J. Nick Koston
25ed7c890b cleanups 2025-06-22 20:03:02 +02:00
J. Nick Koston
85e3b63f05 adjust 2025-06-22 19:49:12 +02:00
J. Nick Koston
a37bac1956 add files 2025-06-22 19:47:19 +02:00
J. Nick Koston
818a978dfc units 2025-06-22 19:40:53 +02:00
J. Nick Koston
180aeb7d8e simplify 2025-06-22 13:50:29 +02:00
J. Nick Koston
0764fa7292 simplify 2025-06-22 13:48:27 +02:00
J. Nick Koston
17bf533ed7 simplify 2025-06-22 13:44:05 +02:00
J. Nick Koston
d7eae1c1a0 simplify 2025-06-22 13:43:52 +02:00
J. Nick Koston
7f2d979255 preen 2025-06-22 13:39:12 +02:00
J. Nick Koston
46b419ea8b preen 2025-06-22 13:38:14 +02:00
J. Nick Koston
b30b527ff9 one more place to check 2025-06-22 13:37:30 +02:00
J. Nick Koston
41b1bfc504 legacy test 2025-06-22 13:37:01 +02:00
J. Nick Koston
f4f14a7507 fixes 2025-06-22 13:29:49 +02:00
J. Nick Koston
61c29213a7 fixes 2025-06-22 13:29:41 +02:00
J. Nick Koston
e6d7639209 Merge branch 'dev' into multi_device 2025-06-22 13:03:16 +02:00
J. Nick Koston
3c07a186b2 Merge remote-tracking branch 'dala318/multi_device' into multi_device 2025-06-22 13:02:48 +02:00
J. Nick Koston
8a725250a9 Merge branch 'dev' into multi_device 2025-06-22 12:32:44 +02:00
J. Nick Koston
502b8a6073 fixes 2025-06-22 12:32:25 +02:00
J. Nick Koston
6212c6f80f Merge branch 'dev' into logger_disable_loop 2025-06-22 12:10:11 +02:00
J. Nick Koston
b03e3b8d4a fixes 2025-06-22 10:07:05 +02:00
J. Nick Koston
a98e34d190 handle collisions 2025-06-22 10:02:59 +02:00
J. Nick Koston
bf8d8b6e63 handle collisions 2025-06-22 10:01:53 +02:00
J. Nick Koston
57599f7a98 handle collisions 2025-06-22 10:00:31 +02:00
J. Nick Koston
ffccce7ffc handle collisions 2025-06-22 09:58:12 +02:00
J. Nick Koston
bbd5d050a9 Merge branch 'dev' into logger_disable_loop 2025-06-21 18:36:59 +02:00
J. Nick Koston
71a96fdcbf Merge branch 'dev' into logger_disable_loop 2025-06-21 18:11:19 +02:00
J. Nick Koston
221e3c6c9c preen 2025-06-21 18:09:16 +02:00
J. Nick Koston
fb1679d572 preen 2025-06-21 18:07:45 +02:00
J. Nick Koston
c19065f112 preen 2025-06-21 18:02:32 +02:00
J. Nick Koston
f2b04a077e preen 2025-06-21 18:01:12 +02:00
J. Nick Koston
8e7841c880 preen 2025-06-21 18:00:17 +02:00
J. Nick Koston
1873490b24 preen 2025-06-21 17:57:36 +02:00
J. Nick Koston
4d231953f4 preen 2025-06-21 17:57:10 +02:00
J. Nick Koston
aa4c399657 reverse space in vectors 2025-06-21 17:36:25 +02:00
J. Nick Koston
1f99d18982 reverse space in vectors 2025-06-21 17:34:08 +02:00
J. Nick Koston
be37178ef8 make areas and devices consistant 2025-06-21 17:32:11 +02:00
J. Nick Koston
fad86c655e make areas and devices consistant 2025-06-21 17:30:17 +02:00
J. Nick Koston
4a7958586e make areas and devices consistant 2025-06-21 17:19:16 +02:00
J. Nick Koston
f44ecd0891 make areas and devices consistant 2025-06-21 17:18:23 +02:00
J. Nick Koston
3d0392d668 make areas and devices consistant 2025-06-21 17:17:29 +02:00
J. Nick Koston
d300d2605b make areas and devices consistant 2025-06-21 17:13:04 +02:00
J. Nick Koston
66cce6a2f2 make areas and devices consistant 2025-06-21 17:12:25 +02:00
J. Nick Koston
65e3c6bfbb make areas and devices consistant 2025-06-21 17:12:00 +02:00
J. Nick Koston
2a39060912 Merge remote-tracking branch 'upstream/dev' into multi_device 2025-06-21 17:06:11 +02:00
J. Nick Koston
8714e80978 make areas and devices consistant 2025-06-21 17:05:46 +02:00
J. Nick Koston
98de53f60b migrate to using same area info for top level and sub devices 2025-06-21 16:47:03 +02:00
J. Nick Koston
41e11e9a0e migrate to using same area info for top level and sub devices 2025-06-21 16:43:48 +02:00
J. Nick Koston
e7a4eac8bd migrate to using same area info for top level and sub devices 2025-06-21 16:42:05 +02:00
J. Nick Koston
1589a131db migrate to using same area info for top level and sub devices 2025-06-21 16:39:07 +02:00
J. Nick Koston
7d84f0e650 migrate to using same area info for top level and sub devices 2025-06-21 16:37:21 +02:00
J. Nick Koston
86fb0e317f fixes 2025-06-21 15:22:35 +02:00
J. Nick Koston
32088d5ef7 revert 2025-06-21 13:35:32 +02:00
J. Nick Koston
63de88dd57 fixes 2025-06-21 13:33:29 +02:00
J. Nick Koston
153a6440dc cleanups to address review comments 2025-06-21 13:20:59 +02:00
J. Nick Koston
8937ed2269 cleanups to address review comments 2025-06-21 13:18:25 +02:00
J. Nick Koston
02e922b56f cleanups to address review comments 2025-06-21 13:16:42 +02:00
J. Nick Koston
bf9e901ab9 cleanups to address review comments 2025-06-21 13:13:44 +02:00
J. Nick Koston
1234ef8de2 Merge remote-tracking branch 'upstream/dev' into multi_device 2025-06-21 12:13:54 +02:00
J. Nick Koston
41697a7b1b Merge remote-tracking branch 'upstream/logger_disable_loop' into integration 2025-06-21 11:19:12 +02:00
J. Nick Koston
912e265bc0 Merge branch 'dev' into logger_disable_loop 2025-06-21 11:18:59 +02:00
J. Nick Koston
96ee6fb064 Merge branch 'logger_disable_loop' into integration 2025-06-21 11:17:13 +02:00
J. Nick Koston
788dba8ef3 define 2025-06-21 11:16:14 +02:00
J. Nick Koston
fdde9c4681 Reduce Logger memory usage by optimizing variable sizes 2025-06-21 00:27:05 +02:00
J. Nick Koston
f195e73d38 Merge branch 'logger_disable_loop' into integration 2025-06-20 22:54:40 +02:00
J. Nick Koston
b0d9ffc6a1 Reduce logger CPU usage by disabling loop when buffer is empty 2025-06-20 22:53:12 +02:00
J. Nick Koston
e17619841d fix last component being charged for stats 2025-06-20 22:03:53 +02:00
J. Nick Koston
eb6a7cf3b9 fix last component being charged for stats 2025-06-20 22:02:19 +02:00
J. Nick Koston
9901e2d72e Merge branch 'dev' into integration 2025-06-20 21:36:36 +02:00
J. Nick Koston
1be4e23b68 Merge branch 'dev' into binary_sensor_gpio_polling 2025-06-19 11:07:42 +02:00
J. Nick Koston
e78094cc0a Merge branch 'dev' into esp32_touch_isr 2025-06-19 10:49:17 +02:00
J. Nick Koston
bcf961c0b0 Merge branch 'dev' into integration 2025-06-19 04:05:25 +02:00
J. Nick Koston
f84a4c9753 Merge remote-tracking branch 'origin/disable_ethernet_loop' into integration 2025-06-19 03:42:53 +02:00
J. Nick Koston
df56ca0236 remove redundant enable_loop, it must already be enabled to get here 2025-06-19 03:41:25 +02:00
J. Nick Koston
de0cd0ec67 Merge branch 'dev' into disable_ethernet_loop 2025-06-19 03:39:15 +02:00
J. Nick Koston
67c30245c4 make copilot happy 2025-06-19 02:01:55 +02:00
J. Nick Koston
1f72757591 tidy 2025-06-19 01:35:45 +02:00
J. Nick Koston
35c2fdf6af dry 2025-06-19 01:31:11 +02:00
J. Nick Koston
d1ecd841be avoid auto 2025-06-19 01:28:17 +02:00
J. Nick Koston
828a49697c Merge branch 'gap_events' into integration 2025-06-19 01:18:36 +02:00
J. Nick Koston
0551495501 try another way 2025-06-19 01:18:26 +02:00
J. Nick Koston
2bbffe4a68 try another way 2025-06-19 01:18:11 +02:00
J. Nick Koston
281ad90e39 fixes 2025-06-19 01:16:46 +02:00
J. Nick Koston
ed50976a07 fixes 2025-06-19 01:16:22 +02:00
J. Nick Koston
a3400037d9 fixes 2025-06-19 01:14:15 +02:00
J. Nick Koston
f0d82f75bc fixes 2025-06-19 01:14:05 +02:00
J. Nick Koston
349cb80e90 Merge remote-tracking branch 'origin/integration' into integration 2025-06-19 01:12:20 +02:00
J. Nick Koston
c263ee39af Merge branch 'gap_events' into integration 2025-06-19 01:12:07 +02:00
J. Nick Koston
e99bc52756 Fix missing BLE GAP events causing RSSI sensor and beacon failures 2025-06-19 01:09:13 +02:00
J. Nick Koston
7944b2b8e9 Merge branch 'ota_perf' into integration 2025-06-19 00:40:07 +02:00
J. Nick Koston
ca6ae746c1 be explict 2025-06-19 00:39:19 +02:00
J. Nick Koston
deabac18b2 Merge branch 'disable_ethernet_loop' into integration 2025-06-18 21:39:35 +02:00
J. Nick Koston
5cf8681c61 Merge branch 'ota_perf' into integration 2025-06-18 21:35:14 +02:00
J. Nick Koston
ca7ede8f96 more cleanups 2025-06-18 21:35:04 +02:00
J. Nick Koston
4969682d52 Merge branch 'ota_perf' into integration 2025-06-18 21:27:51 +02:00
J. Nick Koston
8002fe0dd5 remove safety check 2025-06-18 21:27:30 +02:00
J. Nick Koston
7dfdf965b7 remove safety check 2025-06-18 21:26:32 +02:00
J. Nick Koston
b408795dd6 Merge branch 'api_reads' into integration 2025-06-18 19:24:32 +02:00
J. Nick Koston
a5a099336b one more 2025-06-18 19:22:23 +02:00
J. Nick Koston
4ae56fc004 Merge branch 'api_reads' into integration 2025-06-18 18:40:35 +02:00
J. Nick Koston
3f71c09b7b Fix slow noise handshake by reading multiple messages per loop 2025-06-18 18:36:55 +02:00
J. Nick Koston
bd50a7f1ab cleanup 2025-06-18 14:33:58 +02:00
J. Nick Koston
51e4c45e5c Merge branch 'loop_done_enable_isr' into disable_ethernet_loop 2025-06-18 14:27:18 +02:00
J. Nick Koston
e3fae49add Merge branch 'binary_sensor_gpio_polling' into integration 2025-06-18 14:24:42 +02:00
J. Nick Koston
610215ab60 updates 2025-06-18 14:24:31 +02:00
J. Nick Koston
74acbda435 Merge branch 'loop_done_enable_isr' into binary_sensor_gpio_polling 2025-06-18 14:19:03 +02:00
J. Nick Koston
25c4af777c Merge branch 'loop_done_enable_isr' into integration 2025-06-18 14:18:35 +02:00
J. Nick Koston
ec186e6324 rename 2025-06-18 14:17:45 +02:00
J. Nick Koston
150b7a98f3 Merge branch 'dev' into ota_perf 2025-06-18 13:57:20 +02:00
J. Nick Koston
8ae7c1cff0 Merge branch 'ota_perf' into integration 2025-06-18 13:46:36 +02:00
J. Nick Koston
7f1d0eef98 Optimize OTA loop to avoid unnecessary stack allocations 2025-06-18 13:44:07 +02:00
J. Nick Koston
1179ab33f2 tweaks 2025-06-18 12:52:18 +02:00
J. Nick Koston
a09faa1c10 Merge branch 'dev' into disable_ethernet_loop 2025-06-18 12:36:22 +02:00
J. Nick Koston
c0319d9b2f Merge branch 'binary_sensor_gpio_polling' into integration 2025-06-18 12:28:59 +02:00
J. Nick Koston
4870cd2921 use enable_loop_soon_from_isr 2025-06-18 12:28:49 +02:00
J. Nick Koston
d4280ec68b Merge branch 'loop_done_enable_isr' into binary_sensor_gpio_polling 2025-06-18 12:23:55 +02:00
J. Nick Koston
52cdc11927 Merge remote-tracking branch 'origin/proxy_memory' into integration 2025-06-18 12:21:31 +02:00
J. Nick Koston
8345b8c9ce Update esphome/components/esp32_ble_client/ble_client_base.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-18 12:21:10 +02:00
J. Nick Koston
c56f0677c3 Merge remote-tracking branch 'upstream/proxy_memory' into integration 2025-06-18 12:16:23 +02:00
J. Nick Koston
00e9e1421e Merge branch 'dev' into proxy_memory 2025-06-18 12:16:12 +02:00
J. Nick Koston
93c72c6e6c Merge branch 'loop_done_enable_isr' into integration 2025-06-18 12:15:24 +02:00
J. Nick Koston
9cea930dbd Merge remote-tracking branch 'upstream/dev' into integration 2025-06-18 12:15:18 +02:00
J. Nick Koston
7b9bd70729 Add enable_loop_soon_from_isr 2025-06-18 12:09:12 +02:00
J. Nick Koston
5115c7a100 Merge branch 'bump_ruff_precommit' into integration 2025-06-18 00:15:23 +02:00
J. Nick Koston
5634494e64 Bump ruff in pre-commit to 0.12.0
matches https://github.com/esphome/esphome/pull/9120
2025-06-18 00:11:40 +02:00
J. Nick Koston
aa8bd4abf1 Bump ruff in pre-commit to 0.12.0
matches https://github.com/esphome/esphome/pull/9120
2025-06-18 00:10:30 +02:00
J. Nick Koston
17fd69dd7f Bump ruff in pre-commit to 0.12.0
matches https://github.com/esphome/esphome/pull/9120
2025-06-18 00:09:18 +02:00
J. Nick Koston
1d9dae374b Merge branch 'loop_done' into integration 2025-06-17 23:45:20 +02:00
J. Nick Koston
cb2241ad91 make sure components that disable in setup are disabled at start 2025-06-17 23:45:16 +02:00
J. Nick Koston
d8a7e9abc8 make sure components that disable in setup are disabled at start 2025-06-17 23:44:32 +02:00
J. Nick Koston
969abc3f29 make sure components that disable in setup are disabled at start 2025-06-17 23:40:46 +02:00
J. Nick Koston
766fdc8a1f make sure components that disable in setup are disabled at start 2025-06-17 23:40:31 +02:00
J. Nick Koston
4c37c20d76 cleaner fix 2025-06-17 22:30:35 +02:00
J. Nick Koston
7d314398e1 cleaner fix 2025-06-17 22:30:31 +02:00
J. Nick Koston
b69191e3a8 cleaner fix 2025-06-17 22:29:21 +02:00
J. Nick Koston
b27c6b3596 cleaner fix 2025-06-17 22:27:24 +02:00
J. Nick Koston
5453835963 make ble client disable/enable smarter 2025-06-17 18:13:09 +02:00
J. Nick Koston
4d55ba057c make ble client disable/enable smarter 2025-06-17 18:09:53 +02:00
J. Nick Koston
325c01242c tweak 2025-06-17 16:16:20 +02:00
J. Nick Koston
45b32bca89 tweak 2025-06-17 16:08:28 +02:00
J. Nick Koston
7620049214 tweak 2025-06-17 16:05:48 +02:00
J. Nick Koston
3553495a60 Merge remote-tracking branch 'origin/integration' into integration 2025-06-17 15:55:51 +02:00
J. Nick Koston
3ce6db61d5 Merge branch 'binary_sensor_gpio_polling' into integration 2025-06-17 15:55:28 +02:00
J. Nick Koston
798ff32c40 cleanup 2025-06-17 15:55:10 +02:00
J. Nick Koston
430cee8bda Merge branch 'integration' of https://github.com/esphome/esphome into integration 2025-06-17 15:05:27 +02:00
J. Nick Koston
1fe3fb25a6 Merge branch 'binary_sensor_gpio_polling' into integration 2025-06-17 14:38:08 +02:00
J. Nick Koston
685ed87581 preen 2025-06-17 14:38:00 +02:00
J. Nick Koston
ea3ea1eee7 tweak 2025-06-17 14:17:35 +02:00
J. Nick Koston
c9edcb909b Merge branch 'binary_sensor_gpio_polling' into integration 2025-06-17 13:42:02 +02:00
J. Nick Koston
35bfc9f069 tweak 2025-06-17 13:41:57 +02:00
J. Nick Koston
c4aec194b9 Merge branch 'binary_sensor_gpio_polling' into integration 2025-06-17 13:31:44 +02:00
J. Nick Koston
e8547b16f6 Avoid polling for GPIO binary sensors when possible 2025-06-17 13:20:41 +02:00
J. Nick Koston
2bbe08cee0 Avoid polling for GPIO binary sensors when possible 2025-06-17 13:18:45 +02:00
J. Nick Koston
0a0c369b88 Avoid polling for GPIO binary sensors when possible 2025-06-17 13:17:35 +02:00
J. Nick Koston
5d2f454a94 Avoid polling for GPIO binary sensors when possible 2025-06-17 13:13:58 +02:00
J. Nick Koston
04bcc5c879 Avoid polling for GPIO binary sensors when possible 2025-06-17 13:02:00 +02:00
J. Nick Koston
d4db16665f Avoid polling for GPIO binary sensors when possible 2025-06-17 12:41:17 +02:00
J. Nick Koston
20b7a494f6 Merge remote-tracking branch 'origin/proxy_memory' into integration 2025-06-17 12:05:43 +02:00
J. Nick Koston
fbdce3ad89 Optimize bluetooth_proxy memory usage on ESP32 2025-06-17 12:04:49 +02:00
J. Nick Koston
4fc8807f02 Merge branch 'light_memory' into integration 2025-06-17 11:49:58 +02:00
J. Nick Koston
83075bfb5c Optimize LightState memory layout 2025-06-17 11:49:15 +02:00
J. Nick Koston
4074ec0425 Merge branch 'switch_memory' into integration 2025-06-17 11:27:45 +02:00
J. Nick Koston
8e1694dd0f Reduce Switch component memory usage by 8 bytes per instance 2025-06-17 11:27:11 +02:00
J. Nick Koston
911df18855 Merge branch 'api_memory' into integration 2025-06-17 11:10:17 +02:00
J. Nick Koston
6b049e93f8 Optimize API component memory usage by reordering class members to reduce padding 2025-06-17 11:09:22 +02:00
J. Nick Koston
a335dcc379 Merge remote-tracking branch 'upstream/dev' into integration 2025-06-17 10:40:41 +02:00
J. Nick Koston
c6478c8a79 Merge branch 'reduce_duplicate_gen_code_api' into integration 2025-06-17 10:40:23 +02:00
J. Nick Koston
cc9d40cb60 tweaks 2025-06-17 10:40:12 +02:00
J. Nick Koston
0a6b7f9a1b Update script/api_protobuf/api_protobuf.py 2025-06-17 10:39:49 +02:00
J. Nick Koston
daa1fb9a7a Merge remote-tracking branch 'swoboda1337/bump_libretiny' into integration 2025-06-17 04:33:57 +02:00
Jonathan Swoboda
b7d543290b Bump LibreTiny 2025-06-16 21:40:06 -04:00
J. Nick Koston
ea852b60ac Merge branch 'esp32_ble_tracker_reduce_memory' into integration 2025-06-16 22:07:13 +02:00
J. Nick Koston
ed341988ea Use smaller atomic types for ESP32 BLE Tracker ring buffer indices 2025-06-16 22:06:04 +02:00
J. Nick Koston
057b6c8e30 Merge branch 'api_reduce_millis' into integration 2025-06-16 19:34:07 +02:00
J. Nick Koston
44444fe071 Optimize API server performance by using cached loop time 2025-06-16 19:33:29 +02:00
J. Nick Koston
797330d6ab Disable Ethernet loop polling when connected and stable 2025-06-16 17:28:04 +02:00
J. Nick Koston
a630d5b5f5 Merge branch 'ble_pool' into integration 2025-06-16 15:45:50 +02:00
J. Nick Koston
eb3dc82b5d naming 2025-06-16 15:45:38 +02:00
J. Nick Koston
34ed18d562 Merge branch 'ble_pool' into integration 2025-06-16 15:43:59 +02:00
J. Nick Koston
1ce02ee313 naming 2025-06-16 15:43:43 +02:00
J. Nick Koston
2a26a0188c ble pool 2025-06-16 15:29:37 +02:00
J. Nick Koston
50cb05d1b1 ble pool 2025-06-16 15:28:03 +02:00
J. Nick Koston
6e739ac453 ble pool 2025-06-16 15:23:04 +02:00
J. Nick Koston
7aa2fd9f0e ble pool 2025-06-16 15:19:10 +02:00
J. Nick Koston
8e254e1b03 ble pool 2025-06-16 15:18:19 +02:00
J. Nick Koston
1ad9d717ff ble pool 2025-06-16 15:17:57 +02:00
J. Nick Koston
104658e43a ble pool 2025-06-16 15:16:15 +02:00
J. Nick Koston
e7e4b995bf ble pool 2025-06-16 15:15:26 +02:00
J. Nick Koston
b35b54f2c2 ble pool 2025-06-16 15:11:42 +02:00
J. Nick Koston
f80aeb1d1d cleanup 2025-06-16 15:10:27 +02:00
J. Nick Koston
6a756ab3b6 cleanup 2025-06-16 15:09:49 +02:00
J. Nick Koston
58a697bed1 cleanup 2025-06-16 15:07:23 +02:00
J. Nick Koston
280960ac18 cleanup 2025-06-16 15:06:02 +02:00
J. Nick Koston
0640ff13aa ble pool 2025-06-16 15:04:40 +02:00
J. Nick Koston
545505691f ble pool 2025-06-16 15:02:10 +02:00
J. Nick Koston
11fcf81321 ble pool 2025-06-16 15:00:58 +02:00
J. Nick Koston
c565b37dc8 ble pool 2025-06-16 15:00:07 +02:00
J. Nick Koston
3d18495270 ble pool 2025-06-16 14:55:15 +02:00
J. Nick Koston
419e4e63e9 ble pool 2025-06-16 14:53:50 +02:00
J. Nick Koston
724aa2bf65 ble pool 2025-06-16 14:52:38 +02:00
J. Nick Koston
573fa8aeb3 ble pool 2025-06-16 14:52:28 +02:00
J. Nick Koston
8a672e34c5 ble pool 2025-06-16 14:47:05 +02:00
J. Nick Koston
bc49211dab ble pool 2025-06-16 14:43:29 +02:00
J. Nick Koston
4ef9c3667e Merge branch 'reduce_duplicate_gen_code_api' into integration 2025-06-16 06:06:19 -05:00
J. Nick Koston
6babe516ac move to proto.h to have less generated code 2025-06-16 06:05:19 -05:00
J. Nick Koston
e0b258ef7e Merge branch 'empty_methods' into integration 2025-06-15 22:30:02 -05:00
J. Nick Koston
ff0c3a89b1 Remove empty generated protobuf methods 2025-06-15 22:25:21 -05:00
J. Nick Koston
2511b81048 Merge branch 'reduce_duplicate_gen_code_api' into integration 2025-06-15 22:09:15 -05:00
J. Nick Koston
6ffcd94edc early return was worse for simple functions 2025-06-15 22:00:40 -05:00
J. Nick Koston
2fcf73c812 Reduce code duplication in auto-generated API protocol code 2025-06-15 21:53:33 -05:00
J. Nick Koston
dee0608af9 adjust 2025-06-15 20:47:53 -05:00
J. Nick Koston
d11860a383 Merge remote-tracking branch 'origin/loop_done' into integration 2025-06-15 20:44:24 -05:00
J. Nick Koston
1c05115bf5 Merge branch 'dev' into loop_done 2025-06-15 20:44:09 -05:00
J. Nick Koston
d7e7382d0b tests, address review comments 2025-06-15 20:43:30 -05:00
J. Nick Koston
872388f6e3 tests, address review comments 2025-06-15 20:43:01 -05:00
J. Nick Koston
1215ef920b Merge branch 'loop_done' into integration 2025-06-15 20:36:08 -05:00
J. Nick Koston
d19d5a23ea speed up test a bit 2025-06-15 20:36:00 -05:00
J. Nick Koston
f49a779f1d speed up test a bit 2025-06-15 20:35:52 -05:00
J. Nick Koston
d8bf5b80e1 Merge branch 'loop_done' into integration 2025-06-15 20:34:22 -05:00
J. Nick Koston
69483b9353 speed up test a bit 2025-06-15 20:34:13 -05:00
J. Nick Koston
14e8548989 speed up test a bit 2025-06-15 20:33:52 -05:00
J. Nick Koston
4abd93b661 tests, address review comments 2025-06-15 20:32:36 -05:00
J. Nick Koston
5d925af76f tests, address review comments 2025-06-15 20:31:25 -05:00
J. Nick Koston
b999c6064a tests, address review comments 2025-06-15 20:30:54 -05:00
J. Nick Koston
94e3576978 tests, address review comments 2025-06-15 20:30:43 -05:00
J. Nick Koston
7a22406a2d Merge remote-tracking branch 'origin/integration' into integration 2025-06-15 20:29:36 -05:00
J. Nick Koston
e60684494f Merge branch 'loop_done' into integration 2025-06-15 20:29:25 -05:00
J. Nick Koston
9db28ed779 cover 2025-06-15 20:29:12 -05:00
J. Nick Koston
6fd8c5cee7 tests, address review comments 2025-06-15 20:22:49 -05:00
J. Nick Koston
787ec43266 tests, address review comments 2025-06-15 20:22:29 -05:00
J. Nick Koston
a4efc63bf2 test 2025-06-15 19:57:20 -05:00
J. Nick Koston
80a8f1437e tests 2025-06-15 19:38:13 -05:00
J. Nick Koston
fcca94169d Merge remote-tracking branch 'origin/integration' into integration 2025-06-15 19:12:32 -05:00
J. Nick Koston
d1924088e3 Merge remote-tracking branch 'origin/loop_done' into integration 2025-06-15 19:11:57 -05:00
J. Nick Koston
fd31afe09c tidy 2025-06-15 18:58:42 -05:00
J. Nick Koston
7a763712c5 tidy 2025-06-15 18:58:32 -05:00
J. Nick Koston
7216be5da7 Merge branch 'loop_done' into integration 2025-06-15 18:44:36 -05:00
J. Nick Koston
711b0a291b comments 2025-06-15 18:44:28 -05:00
J. Nick Koston
dfc96496c8 comments 2025-06-15 18:44:15 -05:00
J. Nick Koston
2a1c5ef333 Merge branch 'loop_done' into integration 2025-06-15 18:42:49 -05:00
J. Nick Koston
9755209499 comments 2025-06-15 18:42:40 -05:00
J. Nick Koston
0b26e537d4 Merge branch 'loop_done' into integration 2025-06-15 18:40:46 -05:00
J. Nick Koston
98c6233ec3 Merge branch 'dev' into loop_done 2025-06-15 18:40:33 -05:00
J. Nick Koston
f711706b1a Fix ESP32 Improv component to re-enable loop when service starts again 2025-06-15 18:40:08 -05:00
J. Nick Koston
cee7789ab6 tweak 2025-06-15 18:37:05 -05:00
J. Nick Koston
8a06c4380d partition 2025-06-15 18:32:36 -05:00
J. Nick Koston
72ecf7a288 Merge remote-tracking branch 'upstream/dev' into integration 2025-06-15 16:48:20 -05:00
J. Nick Koston
ef98c7502d Merge remote-tracking branch 'origin/dev' into integration 2025-06-15 13:42:11 -05:00
J. Nick Koston
03d0e74b65 Merge remote-tracking branch 'upstream/less_templates' into integration 2025-06-15 10:48:53 -05:00
J. Nick Koston
5b8fdc0364 Merge branch 'dev' into less_templates 2025-06-15 10:42:41 -05:00
J. Nick Koston
593b4bd137 Update script/api_protobuf/api_protobuf.py 2025-06-15 10:42:28 -05:00
J. Nick Koston
267e12d058 lint 2025-06-15 10:09:54 -05:00
J. Nick Koston
4a5e39b651 Add common base classes for entity protobuf messages to reduce duplicate code 2025-06-15 09:40:45 -05:00
J. Nick Koston
ea24fa5b78 Merge branch 'loop_done' into integration 2025-06-15 01:52:27 -05:00
J. Nick Koston
bb2bb128f7 remove trailing . 2025-06-15 01:52:17 -05:00
J. Nick Koston
94e8a856d7 Merge branch 'loop_done' into integration 2025-06-15 01:47:22 -05:00
J. Nick Koston
4c19fbf98e lint 2025-06-15 01:47:10 -05:00
J. Nick Koston
60f8938bfa Merge branch 'loop_done' into integration 2025-06-15 01:34:12 -05:00
J. Nick Koston
55679662b5 ordering 2025-06-15 01:34:03 -05:00
J. Nick Koston
53df959e49 Merge branch 'loop_done' into integration 2025-06-15 01:26:56 -05:00
J. Nick Koston
8e6ef9966f Merge remote-tracking branch 'upstream/loop_done' into loop_done 2025-06-15 01:26:45 -05:00
J. Nick Koston
1d52fceafa rename, cleanup 2025-06-15 01:26:25 -05:00
J. Nick Koston
99186ed864 rename, cleanup 2025-06-15 01:25:59 -05:00
J. Nick Koston
383931d484 Merge branch 'ble_events_ring_buffer' into integration 2025-06-15 00:31:34 -05:00
J. Nick Koston
0b49a54cb3 comments 2025-06-15 00:31:25 -05:00
J. Nick Koston
705c0f1891 Merge branch 'ble_events_ring_buffer' into integration 2025-06-15 00:27:13 -05:00
J. Nick Koston
544c3ffc95 comments 2025-06-15 00:26:06 -05:00
J. Nick Koston
33f252a45d Implement a lock free ring buffer for BLEEvents to avoid drops 2025-06-15 00:22:24 -05:00
J. Nick Koston
f55d82a015 Merge branch 'ble_queue_lock_free' into integration 2025-06-15 00:16:02 -05:00
J. Nick Koston
8cf33fdef0 preen 2025-06-15 00:15:48 -05:00
J. Nick Koston
f858d98811 Merge branch 'ble_queue_lock_free' into integration 2025-06-15 00:12:47 -05:00
J. Nick Koston
2a6165d440 simplify 2025-06-15 00:12:34 -05:00
J. Nick Koston
4586528c40 merge 2025-06-15 00:01:15 -05:00
J. Nick Koston
23a07baa19 Merge branch 'ble_queue_lock_free' into integration 2025-06-14 23:58:53 -05:00
J. Nick Koston
f9040ca932 cleanup 2025-06-14 23:54:42 -05:00
J. Nick Koston
4cea7f0237 Update esphome/components/esp32_ble/ble.cpp 2025-06-14 23:49:38 -05:00
J. Nick Koston
b1847d5e98 Make ble events queue lock free 2025-06-14 23:48:26 -05:00
J. Nick Koston
9ce4d2e952 Merge remote-tracking branch 'upstream/dev' into integration 2025-06-14 23:21:51 -05:00
J. Nick Koston
247078e06d Merge remote-tracking branch 'origin/loop_done' into integration 2025-06-14 23:20:20 -05:00
J. Nick Koston
a0cd72de28 revert 2025-06-14 23:19:43 -05:00
J. Nick Koston
e467f569f0 Merge branch 'loop_done' into integration 2025-06-14 23:15:49 -05:00
J. Nick Koston
e31c7b7dfc one more 2025-06-14 23:15:06 -05:00
J. Nick Koston
dc2e0c832b Merge branch 'loop_done' into integration 2025-06-14 22:37:11 -05:00
J. Nick Koston
7ddf51bb51 fix 2025-06-14 22:36:29 -05:00
J. Nick Koston
8fb3856665 small fix 2025-06-14 22:17:27 -05:00
J. Nick Koston
183dd74f3e one more 2025-06-14 22:17:27 -05:00
J. Nick Koston
4f29039b41 mark_loop_done 2025-06-14 22:17:24 -05:00
J. Nick Koston
102fcbec20 small fix 2025-06-14 22:09:19 -05:00
J. Nick Koston
d00e5212c7 one more 2025-06-14 22:04:33 -05:00
J. Nick Koston
0e6bfb62cd mark_loop_done 2025-06-14 21:58:18 -05:00
J. Nick Koston
f576e8f635 remove cap 2025-06-14 21:40:16 -05:00
J. Nick Koston
e6dc10a440 address review comments 2025-06-14 21:34:21 -05:00
J. Nick Koston
aa930fb6b6 Merge branch 'ble_queue_lock_free' into integration 2025-06-14 20:09:56 -05:00
J. Nick Koston
f327ed87e9 Make ble events queue lock free 2025-06-14 20:08:43 -05:00
J. Nick Koston
2de9be0589 Merge branch 'loop_runtime_stats' into integration 2025-06-14 19:43:45 -05:00
J. Nick Koston
345cde8645 Merge branch 'ble_events_ring_buffer' into integration 2025-06-14 19:25:57 -05:00
J. Nick Koston
cf152af9ae Implement a lock free ring buffer for BLEEvents to avoid drops 2025-06-14 19:24:57 -05:00
J. Nick Koston
d6333dcfd9 Revert "Reorder Application to reduce padding"
This reverts commit 82c39580df.
2025-06-14 18:18:45 -05:00
J. Nick Koston
0121f799f0 Merge branch 'reorder_app_reduce_padding' into integration 2025-06-14 18:16:39 -05:00
J. Nick Koston
82c39580df Reorder Application to reduce padding 2025-06-14 18:15:40 -05:00
J. Nick Koston
53a578a46f Merge branch 'area_str' into integration 2025-06-14 18:01:44 -05:00
J. Nick Koston
62612ef80b Optimize Application area_ from std::string to const char* 2025-06-14 18:00:32 -05:00
J. Nick Koston
61ac874c4c Merge branch 'parse_on_off_uint8t' into integration 2025-06-14 17:46:25 -05:00
J. Nick Koston
976b200ff6 Make ParseOnOffState enum uint8_t 2025-06-14 17:44:22 -05:00
J. Nick Koston
852343b6d8 Merge remote-tracking branch 'upstream/has_state_' into integration 2025-06-14 17:32:40 -05:00
J. Nick Koston
c56af9d52b Merge branch 'component_state_oversized' into integration 2025-06-14 17:03:31 -05:00
J. Nick Koston
05f18e2828 Optimize Component and Application state storage from uint32_t to uint8_t 2025-06-14 17:01:57 -05:00
J. Nick Koston
72804caab2 Merge branch 'warn_if_blocking_over_' into integration 2025-06-14 16:43:26 -05:00
J. Nick Koston
80cbe5c7c9 Reduce Component blocking threshold memory usage by 2 bytes per component 2025-06-14 16:42:08 -05:00
J. Nick Koston
21892d1236 Merge branch 'error_message_memory' into integration 2025-06-14 16:29:43 -05:00
J. Nick Koston
13824624f8 Reduce Component memory usage by 20 bytes per component 2025-06-14 16:27:45 -05:00
J. Nick Koston
0fd72ecbab Merge remote-tracking branch 'upstream/batch_exceeds_max_packet_size' into integration 2025-06-14 15:46:22 -05:00
J. Nick Koston
f848cb1546 Merge remote-tracking branch 'upstream/footer_not_reserved' into integration 2025-06-14 15:46:13 -05:00
J. Nick Koston
633854081a Merge remote-tracking branch 'upstream/guard_wrong_total_size' into integration 2025-06-14 15:45:35 -05:00
J. Nick Koston
4fed9a581b Merge remote-tracking branch 'upstream/missing_force' into integration 2025-06-14 15:45:28 -05:00
J. Nick Koston
e9c1202aaa Merge remote-tracking branch 'upstream/ble_events' into integration 2025-06-14 15:45:18 -05:00
J. Nick Koston
0a7ae279d0 preen 2025-06-14 11:40:50 -05:00
J. Nick Koston
0de2696543 Optimize memory usage by lazy-allocating raw callbacks in sensors 2025-06-14 11:37:11 -05:00
J. Nick Koston
a7dc239b71 cleanup 2025-06-14 10:49:23 -05:00
J. Nick Koston
fe0e6990f5 cover 2025-06-14 10:14:41 -05:00
J. Nick Koston
5ba65e92d9 cover 2025-06-14 10:12:12 -05:00
J. Nick Koston
a1452b52c9 Reduce entity memory usage by eliminating field shadowing and bit-packing 2025-06-14 10:00:49 -05:00
J. Nick Koston
dd2aa23a5f cover 2025-06-13 19:28:59 -05:00
J. Nick Koston
0e0359ba7d Fix protobuf encoding size mismatch by passing force parameter in encode_string 2025-06-13 19:20:08 -05:00
J. Nick Koston
93b1b7aded assert 2025-06-13 18:32:21 -05:00
J. Nick Koston
9472dc6a53 Fix API message encoding to return actual size instead of calculated size 2025-06-13 18:24:51 -05:00
J. Nick Koston
67b681854e Fix API message encoding to return actual size instead of calculated size 2025-06-13 18:20:01 -05:00
J. Nick Koston
7b5990833e Merge branch 'dev' into batch_exceeds_max_packet_size 2025-06-13 17:01:10 -05:00
J. Nick Koston
b6d5d04589 More coverage 2025-06-13 16:59:36 -05:00
J. Nick Koston
fdfbb3e944 Fix footer space not being reserved for batched messages
This only affects noise protocol, and its not a correctness issue, its only
fixing an inefficent reserve
2025-06-13 15:54:31 -05:00
J. Nick Koston
faa7a3e37f tweak 2025-06-13 15:14:14 -05:00
J. Nick Koston
23748b82bb Ensure api can send batches where the first message exceeds MAX_PACKET_SIZE 2025-06-13 14:58:09 -05:00
J. Nick Koston
bccb6f578a Ensure we can send batches where the first message exceeds MAX_PACKET_SIZE 2025-06-13 14:55:17 -05:00
J. Nick Koston
de8a5d6e9e Merge branch 'dev' into ble_events 2025-06-13 10:46:45 -05:00
J. Nick Koston
a8eb3f7961 lint 2025-06-13 10:46:09 -05:00
J. Nick Koston
2dc85f5a42 Merge remote-tracking branch 'upstream/esp32_touch_isr' into esp32_touch_isr 2025-06-13 10:11:49 -05:00
J. Nick Koston
82518b351d lint 2025-06-13 10:11:38 -05:00
J. Nick Koston
68f34a1683 Merge branch 'dev' into esp32_touch_isr 2025-06-12 20:19:29 -05:00
J. Nick Koston
bc6b72a422 tweaks 2025-06-12 20:16:12 -05:00
J. Nick Koston
599e28e1cb fixes 2025-06-12 20:02:39 -05:00
J. Nick Koston
ee6b2ba6c6 fixes 2025-06-12 19:56:12 -05:00
J. Nick Koston
0877b3e2af suppress unused events 2025-06-12 19:18:22 -05:00
J. Nick Koston
d1edb1e32a fix 2025-06-12 18:34:00 -05:00
J. Nick Koston
d1e6b8dd10 comment 2025-06-12 18:33:27 -05:00
J. Nick Koston
b32fc3bfdd lint 2025-06-12 18:30:53 -05:00
J. Nick Koston
1e24417db0 help with setup 2025-06-12 18:09:39 -05:00
J. Nick Koston
fb9387ecc5 help with setup 2025-06-12 17:55:21 -05:00
J. Nick Koston
6c5f4cdb70 help with setup 2025-06-12 17:49:01 -05:00
J. Nick Koston
aabacb7454 help with setup 2025-06-12 17:47:25 -05:00
J. Nick Koston
b5da84479e help with setup 2025-06-12 17:43:08 -05:00
J. Nick Koston
88d9361050 help with setup 2025-06-12 17:34:24 -05:00
J. Nick Koston
1d90388ffc help with setup 2025-06-12 17:27:09 -05:00
J. Nick Koston
b3c43ce31f help with setup 2025-06-12 17:23:10 -05:00
J. Nick Koston
6d9d22d422 help with setup 2025-06-12 17:17:16 -05:00
J. Nick Koston
86be1f56d0 preen 2025-06-12 17:14:00 -05:00
J. Nick Koston
a0c81ffd7a preen 2025-06-12 17:08:47 -05:00
J. Nick Koston
ec1dc42e58 Revert "preen"
This reverts commit 866eaed73d.
2025-06-12 17:05:06 -05:00
J. Nick Koston
866eaed73d preen 2025-06-12 16:58:24 -05:00
J. Nick Koston
a18374e1ad cleanup 2025-06-12 16:33:15 -05:00
J. Nick Koston
f7afcb3b24 cleanup 2025-06-12 16:30:41 -05:00
J. Nick Koston
3adcae783c cleanup 2025-06-12 16:19:27 -05:00
J. Nick Koston
73b40dd2e7 cleanup 2025-06-12 16:19:15 -05:00
J. Nick Koston
1e12614f9a cleanup 2025-06-12 16:14:37 -05:00
J. Nick Koston
aeaa7c699a Merge branch 'dev' into esp32_touch_isr 2025-06-12 15:57:26 -05:00
J. Nick Koston
f1c56b7254 cleanup 2025-06-12 15:56:32 -05:00
J. Nick Koston
e72e0d0646 cleanup 2025-06-12 15:56:19 -05:00
J. Nick Koston
5719d334aa cleanup 2025-06-12 15:56:04 -05:00
J. Nick Koston
bcb6b85333 cleanup 2025-06-12 15:54:15 -05:00
J. Nick Koston
5d765413ef cleanup 2025-06-12 15:53:42 -05:00
J. Nick Koston
efb2e5e7a8 cleanup 2025-06-12 15:52:38 -05:00
J. Nick Koston
5d5e346199 cleanup 2025-06-12 15:50:21 -05:00
J. Nick Koston
08a74890da cleanup 2025-06-12 15:48:29 -05:00
J. Nick Koston
0545b9c7f2 cleanup 2025-06-12 15:48:00 -05:00
J. Nick Koston
bbf7d32676 cleanup 2025-06-12 15:47:31 -05:00
J. Nick Koston
e83f4ae974 cleanup 2025-06-12 15:46:56 -05:00
J. Nick Koston
9b0d01e03f cleanup 2025-06-12 15:45:47 -05:00
J. Nick Koston
eae0d90a1e adjust 2025-06-12 15:41:41 -05:00
J. Nick Koston
90c09a7650 split 2025-06-12 13:29:12 -05:00
J. Nick Koston
aecf080211 touch ups 2025-06-12 13:16:48 -05:00
J. Nick Koston
8517420356 touch ups 2025-06-12 13:14:29 -05:00
J. Nick Koston
376be1f009 touch ups 2025-06-12 13:12:40 -05:00
J. Nick Koston
0021e76649 working 2025-06-12 13:07:25 -05:00
J. Nick Koston
d440c4bc43 derbug 2025-06-12 13:00:55 -05:00
J. Nick Koston
50840b2105 derbug 2025-06-12 13:00:39 -05:00
J. Nick Koston
7502c6b6c0 debug 2025-06-12 12:44:28 -05:00
J. Nick Koston
919c32f0cc tweak 2025-06-12 12:20:47 -05:00
J. Nick Koston
a28c951272 more debug 2025-06-12 12:13:46 -05:00
J. Nick Koston
13d7c5a9a9 more debug 2025-06-12 12:12:55 -05:00
J. Nick Koston
5f1383344d tweak 2025-06-12 12:10:50 -05:00
J. Nick Koston
48f43d3eb1 tweak 2025-06-12 11:58:21 -05:00
J. Nick Koston
4ac2141307 adjust 2025-06-12 11:52:29 -05:00
J. Nick Koston
719d8cac97 split it 2025-06-12 11:45:50 -05:00
J. Nick Koston
99cbe53a8e split it 2025-06-12 11:43:47 -05:00
J. Nick Koston
a36af1bfac s3 fixes 2025-06-12 10:59:40 -05:00
J. Nick Koston
8b6aa319bf s3 fixes 2025-06-12 10:57:46 -05:00
J. Nick Koston
a16d321e1a downgrade logging 2025-06-12 10:38:47 -05:00
J. Nick Koston
74e70278e2 fixes 2025-06-12 10:34:59 -05:00
J. Nick Koston
1332e24a2c fixes 2025-06-12 10:31:13 -05:00
J. Nick Koston
5ab78ec461 fixes 2025-06-12 10:30:58 -05:00
J. Nick Koston
ce701d3c31 fixes 2025-06-12 10:29:11 -05:00
J. Nick Koston
5fca1be44d fixes 2025-06-12 10:27:22 -05:00
J. Nick Koston
0bd4c333bd cleanup 2025-06-12 10:21:41 -05:00
J. Nick Koston
c6ed880732 fixes 2025-06-12 10:19:25 -05:00
J. Nick Koston
da0f3c6cce fixes 2025-06-12 10:12:56 -05:00
J. Nick Koston
e5d12d346a fixes 2025-06-12 10:08:29 -05:00
J. Nick Koston
478e2e726b fixes 2025-06-12 10:01:35 -05:00
J. Nick Koston
dbdac3707b fixes 2025-06-12 10:00:49 -05:00
J. Nick Koston
bd89a88e34 fixes 2025-06-12 09:23:38 -05:00
J. Nick Koston
d322d83745 fixes 2025-06-12 09:21:03 -05:00
J. Nick Koston
463a581ab9 DEBUG! 2025-06-12 00:56:42 -05:00
J. Nick Koston
eae4bd222a track pads 2025-06-11 23:29:00 -05:00
J. Nick Koston
a7bb7fc14d fix 2025-06-11 22:55:15 -05:00
J. Nick Koston
c047aa47eb use ll for all 2025-06-11 22:46:40 -05:00
J. Nick Koston
61bca56316 try touch_ll_read_raw_data 2025-06-11 22:43:41 -05:00
J. Nick Koston
9a37323eb8 Use interrupt based approach for esp32_touch 2025-06-11 22:32:25 -05:00
J. Nick Koston
99a54369bf Merge remote-tracking branch 'upstream/dev' into loop_runtime_stats 2025-06-11 22:01:22 -05:00
J. Nick Koston
f7533dfc5c review 2025-06-11 16:25:31 -05:00
J. Nick Koston
ee7d95272d lets be sure 2025-06-11 13:32:55 -05:00
J. Nick Koston
2b9b1d12e6 lets be sure 2025-06-11 13:32:47 -05:00
J. Nick Koston
2cbb5c7d8e fix error 2025-06-11 13:16:44 -05:00
J. Nick Koston
9686c7babe Merge branch 'dev' into ble_events 2025-06-11 13:09:32 -05:00
J. Nick Koston
66bd4c96c4 safety 2025-06-11 13:05:30 -05:00
J. Nick Koston
dc47faa4b6 safety 2025-06-11 13:05:01 -05:00
J. Nick Koston
55ee0b116d lint 2025-06-11 13:03:50 -05:00
J. Nick Koston
c6957c08bc lint 2025-06-11 13:02:08 -05:00
J. Nick Koston
8fe6a323d8 remove workaround 2025-06-11 13:00:55 -05:00
J. Nick Koston
8e51590c32 remove workaround 2025-06-11 12:59:57 -05:00
J. Nick Koston
ae066d5627 cleanup 2025-06-11 11:55:28 -05:00
J. Nick Koston
6760279916 cleanup compacted code 2025-06-11 11:51:43 -05:00
J. Nick Koston
3c208050b0 comments 2025-06-11 11:47:34 -05:00
J. Nick Koston
bbc7c9fb37 dry 2025-06-11 11:46:17 -05:00
J. Nick Koston
e1c3862586 preen 2025-06-11 11:36:50 -05:00
J. Nick Koston
c24b7cb7bd v->d 2025-06-11 11:34:30 -05:00
J. Nick Koston
c91e16549d lint 2025-06-11 11:27:13 -05:00
J. Nick Koston
6e70aca458 wip 2025-06-11 11:23:13 -05:00
J. Nick Koston
d9ffd0ac8e wip 2025-06-11 11:22:01 -05:00
J. Nick Koston
4641f73d19 comments 2025-06-11 11:19:36 -05:00
J. Nick Koston
9f0051c21f cleanup 2025-06-11 11:17:10 -05:00
J. Nick Koston
0331cb09e8 reduce 2025-06-11 11:17:01 -05:00
J. Nick Koston
2f8946f86c cleanup 2025-06-11 11:14:10 -05:00
J. Nick Koston
88a3df4008 cleanup 2025-06-11 11:13:34 -05:00
J. Nick Koston
0adf514bd6 preen 2025-06-11 11:09:19 -05:00
J. Nick Koston
a1b5a2abcb tweak 2025-06-11 10:58:56 -05:00
J. Nick Koston
068c62c6fe adjust 2025-06-11 10:43:48 -05:00
J. Nick Koston
0e9f14f969 wip 2025-06-11 10:20:18 -05:00
J. Nick Koston
78315fd388 preen 2025-06-11 10:08:30 -05:00
J. Nick Koston
0ab69002df preen 2025-06-11 10:05:15 -05:00
J. Nick Koston
1eec1239ec wip 2025-06-11 09:56:02 -05:00
J. Nick Koston
60cc4c4ed0 Merge branch 'dev' into drop_unique_id 2025-06-11 08:26:41 -05:00
J. Nick Koston
34c100e997 Remove legacy unique_id field from entities
These are no longer used in Home Assistant. This will be a breaking
change for MQTT for the sensors that defined custom unique ids.
2025-06-07 22:17:07 -05:00
Daniel Vikstrom
57f4067fbf Move fnv1a_32bit_hash to helpers 2025-06-02 14:42:39 +02:00
Daniel Vikstrom
f4a9221232 Change hash method 2025-06-02 08:31:06 +02:00
J. Nick Koston
3d4a75148d Merge branch 'dev' into multi_device 2025-05-31 10:27:31 -05:00
J. Nick Koston
c2c5bd844d Merge branch 'dev' into multi_device 2025-05-29 13:43:21 -05:00
J. Nick Koston
98a2f23024 Merge remote-tracking branch 'upstream/dev' into loop_runtime_stats 2025-05-29 11:04:14 -05:00
J. Nick Koston
c955897d1b Merge remote-tracking branch 'upstream/dev' into loop_runtime_stats 2025-05-27 11:39:45 -05:00
Daniel Vikstrom
9624efa21e Fix proto generation and clang 2025-05-22 14:18:46 +02:00
DanielV
831638210d Merge branch 'dev' into multi_device 2025-05-22 08:41:54 +02:00
J. Nick Koston
cfdb0925ce Merge branch 'dev' into loop_runtime_stats 2025-05-13 23:42:19 -05:00
J. Nick Koston
83db3eddd9 revert ota 2025-05-13 01:07:43 -05:00
J. Nick Koston
cc2c5a544e revert ota 2025-05-13 01:07:38 -05:00
J. Nick Koston
8fba8c2800 revert ota 2025-05-13 01:05:37 -05:00
J. Nick Koston
51d1da8460 revert ota 2025-05-13 01:04:09 -05:00
J. Nick Koston
2f1257056d revert 2025-05-13 01:02:00 -05:00
J. Nick Koston
2f8f6967bf fix ota 2025-05-13 00:55:19 -05:00
J. Nick Koston
246527e618 runtime stats 2025-05-13 00:54:05 -05:00
J. Nick Koston
3857cc9c83 runtime stats 2025-05-13 00:51:14 -05:00
Daniel Vikström
a59a8c563e Attempt fixing circular import by lazy import 2025-05-06 12:30:04 +02:00
Daniel Vikström
856829bcbb More namespace and import fixes 2025-05-06 12:05:45 +02:00
Daniel Vikström
dd2b931f61 Fix namespace error 2025-05-06 11:46:23 +02:00
Daniel Vikström
39beccbbb0 remove from CODEOWNERS 2025-05-06 10:50:09 +02:00
Daniel Vikström
ff626b428f Attempt moving it to esphome config section 2025-05-06 10:48:26 +02:00
Daniel Vikström
3915e1f012 Revert "Improve stability for unrelated test"
This reverts commit 3922950951.
2025-05-06 03:36:03 +02:00
Daniel Vikström
7b460b6224 Restore ci-api-proto.yml 2025-05-06 03:34:33 +02:00
Daniel Vikström
8fb8e79730 Fix clang 2025-05-06 03:20:22 +02:00
Daniel Vikström
79bbc475f4 Fix generated files and revert entity config to device_id 2025-05-06 03:05:00 +02:00
Daniel Vikström
cef023283b Fix generated files 2025-05-06 02:55:44 +02:00
Daniel Vikström
d4fda79ada Attempt to replace device_id:str with device_uid:uint32 2025-05-06 02:07:59 +02:00
DanielV
ff0bdcf4cd Merge branch 'dev' into multi_device 2025-05-06 00:48:23 +02:00
DanielV
bfbc313144 Merge branch 'dev' into multi_device 2025-04-22 14:28:51 +02:00
Daniel Vikström
31f2376f15 Rename ref in codegen 2025-04-22 14:03:07 +02:00
DanielV
f76ecb6604 Merge pull request #10 from dala318/multi_device_2
Sub Devices (all entities)
2025-04-22 08:49:28 +02:00
Daniel Vikström
298cc58433 Activate the rest of entities 2025-04-19 23:18:26 +02:00
Daniel Vikström
825c0593e1 Fix generated code after merge 2025-04-19 19:07:50 +02:00
DanielV
87ed1dc3e3 Merge branch 'dev' into multi_device 2025-04-19 18:58:09 +02:00
DanielV
67e9db021c Merge branch 'dev' into multi_device 2025-04-14 22:21:50 +02:00
Daniel Vikström
3922950951 Improve stability for unrelated test 2025-04-14 21:37:27 +02:00
DanielV
9c4aa0ba53 Merge branch 'dev' into multi_device 2025-04-11 13:19:52 +02:00
Daniel Vikström
f5f1651b31 Fix clang 2025-04-10 09:35:08 +02:00
Daniel Vikström
32f4e4ca13 Cleaning up 2025-04-09 19:20:28 +02:00
Daniel Vikström
962e0c4c33 Make it a Class but only use the id in entities 2025-04-09 19:09:31 +02:00
Daniel Vikström
2c01bc5795 Fix clang-tidy 2025-04-09 15:22:40 +02:00
Daniel Vikström
0651f7cb3c Work on sub-device creation 2025-04-09 01:39:24 +02:00
Daniel Vikström
01ac59ce2a Store proto with all additions but commented out 2025-04-09 01:18:42 +02:00
Daniel Vikström
c1fd597757 Add CODEOWNER 2025-04-09 01:12:14 +02:00
Daniel Vikström
e79e244eee Fix generated proto-files 2025-04-09 01:09:45 +02:00
Daniel Vikström
68ecc08111 Register device_id to entity and separate struct for all device info 2025-04-09 00:11:05 +02:00
Daniel Vikström
3b5fbc359f Formating updates 2025-04-08 22:21:11 +02:00
Daniel Vikström
583e5ea47f Add code-owner tag 2025-04-08 22:21:08 +02:00
Daniel Vikström
7b647c3fae Add a single test 2025-04-08 22:21:07 +02:00
Daniel Vikström
a8b76c617c Some basic chain working 2025-04-08 22:07:09 +02:00
Daniel Vikström
1bd8985dff Add a device component 2025-04-08 22:00:09 +02:00
Daniel Vikström
25b5a6c4ae Add device_id to entity_base 2025-04-08 22:00:06 +02:00
814 changed files with 9392 additions and 29540 deletions

View File

@@ -9,7 +9,7 @@ This document provides essential context for AI models interacting with this pro
## 2. Core Technologies & Stack
* **Languages:** Python (>=3.11), C++ (gnu++20)
* **Languages:** Python (>=3.10), C++ (gnu++20)
* **Frameworks & Runtimes:** PlatformIO, Arduino, ESP-IDF.
* **Build Systems:** PlatformIO is the primary build system. CMake is used as an alternative.
* **Configuration:** YAML.
@@ -38,7 +38,7 @@ This document provides essential context for AI models interacting with this pro
5. **Dashboard** (`esphome/dashboard/`): A web-based interface for device configuration, management, and OTA updates.
* **Platform Support:**
1. **ESP32** (`components/esp32/`): Espressif ESP32 family. Supports multiple variants (Original, C2, C3, C5, C6, H2, P4, S2, S3) with ESP-IDF framework. Arduino framework supports only a subset of the variants (Original, C3, S2, S3).
1. **ESP32** (`components/esp32/`): Espressif ESP32 family. Supports multiple variants (S2, S3, C3, etc.) and both IDF and Arduino frameworks.
2. **ESP8266** (`components/esp8266/`): Espressif ESP8266. Arduino framework only, with memory constraints.
3. **RP2040** (`components/rp2040/`): Raspberry Pi Pico/RP2040. Arduino framework with PIO (Programmable I/O) support.
4. **LibreTiny** (`components/libretiny/`): Realtek and Beken chips. Supports multiple chip families and auto-generated components.
@@ -60,7 +60,7 @@ This document provides essential context for AI models interacting with this pro
├── __init__.py # Component configuration schema and code generation
├── [component].h # C++ header file (if needed)
├── [component].cpp # C++ implementation (if needed)
└── [platform]/ # Platform-specific implementations
└── [platform]/ # Platform-specific implementations
├── __init__.py # Platform-specific configuration
├── [platform].h # Platform C++ header
└── [platform].cpp # Platform C++ implementation
@@ -150,8 +150,7 @@ This document provides essential context for AI models interacting with this pro
* **Configuration Validation:**
* **Common Validators:** `cv.int_`, `cv.float_`, `cv.string`, `cv.boolean`, `cv.int_range(min=0, max=100)`, `cv.positive_int`, `cv.percentage`.
* **Complex Validation:** `cv.All(cv.string, cv.Length(min=1, max=50))`, `cv.Any(cv.int_, cv.string)`.
* **Platform-Specific:** `cv.only_on(["esp32", "esp8266"])`, `esp32.only_on_variant(...)`, `cv.only_on_esp32`, `cv.only_on_esp8266`, `cv.only_on_rp2040`.
* **Framework-Specific:** `cv.only_with_framework(...)`, `cv.only_with_arduino`, `cv.only_with_esp_idf`.
* **Platform-Specific:** `cv.only_on(["esp32", "esp8266"])`, `cv.only_with_arduino`.
* **Schema Extensions:**
```python
CONFIG_SCHEMA = cv.Schema({ ... })
@@ -169,8 +168,6 @@ This document provides essential context for AI models interacting with this pro
* `platformio.ini`: Configures the PlatformIO build environments for different microcontrollers.
* `.pre-commit-config.yaml`: Configures the pre-commit hooks for linting and formatting.
* **CI/CD Pipeline:** Defined in `.github/workflows`.
* **Static Analysis & Development:**
* `esphome/core/defines.h`: A comprehensive header file containing all `#define` directives that can be added by components using `cg.add_define()` in Python. This file is used exclusively for development, static analysis tools, and CI testing - it is not used during runtime compilation. When developing components that add new defines, they must be added to this file to ensure proper IDE support and static analysis coverage. The file includes feature flags, build configurations, and platform-specific defines that help static analyzers understand the complete codebase without needing to compile for specific platforms.
## 6. Development & Testing Workflow

View File

@@ -1 +1 @@
4368db58e8f884aff245996b1e8b644cc0796c0bb2fa706d5740d40b823d3ac9
32b0db73b3ae01ba18c9cbb1dabbd8156bc14dded500471919bd0a3dc33916e0

View File

@@ -17,12 +17,12 @@ runs:
steps:
- name: Set up Python ${{ inputs.python-version }}
id: python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: ${{ inputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache/restore@v4.2.4
uses: actions/cache/restore@v4.2.3
with:
path: venv
# yamllint disable-line rule:line-length

View File

@@ -22,7 +22,7 @@ jobs:
if: github.event.action != 'labeled' || github.event.sender.type != 'Bot'
steps:
- name: Checkout
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Generate a token
id: generate-token
@@ -32,7 +32,7 @@ jobs:
private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
- name: Auto Label PR
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
@@ -63,11 +63,7 @@ jobs:
'needs-docs',
'needs-codeowners',
'too-big',
'labeller-recheck',
'bugfix',
'new-feature',
'breaking-change',
'code-quality'
'labeller-recheck'
];
const DOCS_PR_PATTERNS = [
@@ -105,9 +101,7 @@ jobs:
// Calculate data from PR files
const changedFiles = prFiles.map(file => file.filename);
const totalAdditions = prFiles.reduce((sum, file) => sum + (file.additions || 0), 0);
const totalDeletions = prFiles.reduce((sum, file) => sum + (file.deletions || 0), 0);
const totalChanges = totalAdditions + totalDeletions;
const totalChanges = prFiles.reduce((sum, file) => sum + (file.additions || 0) + (file.deletions || 0), 0);
console.log('Current labels:', currentLabels.join(', '));
console.log('Changed files:', changedFiles.length);
@@ -233,21 +227,16 @@ jobs:
// Strategy: PR size detection
async function detectPRSize() {
const labels = new Set();
const testChanges = prFiles
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.additions || 0) + (file.deletions || 0), 0);
const nonTestChanges = totalChanges - testChanges;
if (totalChanges <= SMALL_PR_THRESHOLD) {
labels.add('small-pr');
return labels;
}
const testAdditions = prFiles
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.additions || 0), 0);
const testDeletions = prFiles
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.deletions || 0), 0);
const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions);
// Don't add too-big if mega-pr label is already present
if (nonTestChanges > TOO_BIG_THRESHOLD && !isMegaPR) {
labels.add('too-big');
@@ -352,42 +341,17 @@ jobs:
return labels;
}
// Strategy: PR Template Checkbox detection
async function detectPRTemplateCheckboxes() {
const labels = new Set();
const prBody = context.payload.pull_request.body || '';
console.log('Checking PR template checkboxes...');
// Check for checked checkboxes in the "Types of changes" section
const checkboxPatterns = [
{ pattern: /- \[x\] Bugfix \(non-breaking change which fixes an issue\)/i, label: 'bugfix' },
{ pattern: /- \[x\] New feature \(non-breaking change which adds functionality\)/i, label: 'new-feature' },
{ pattern: /- \[x\] Breaking change \(fix or feature that would cause existing functionality to not work as expected\)/i, label: 'breaking-change' },
{ pattern: /- \[x\] Code quality improvements to existing code or addition of tests/i, label: 'code-quality' }
];
for (const { pattern, label } of checkboxPatterns) {
if (pattern.test(prBody)) {
console.log(`Found checked checkbox for: ${label}`);
labels.add(label);
}
}
return labels;
}
// Strategy: Requirements detection
async function detectRequirements(allLabels) {
const labels = new Set();
// Check for missing tests
if ((allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) && !allLabels.has('has-tests')) {
if ((allLabels.has('new-component') || allLabels.has('new-platform')) && !allLabels.has('has-tests')) {
labels.add('needs-tests');
}
// Check for missing docs
if (allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) {
if (allLabels.has('new-component') || allLabels.has('new-platform')) {
const prBody = context.payload.pull_request.body || '';
const hasDocsLink = DOCS_PR_PATTERNS.some(pattern => pattern.test(prBody));
@@ -419,13 +383,10 @@ jobs:
// Too big message
if (finalLabels.includes('too-big')) {
const testAdditions = prFiles
const testChanges = prFiles
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.additions || 0), 0);
const testDeletions = prFiles
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.deletions || 0), 0);
const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions);
.reduce((sum, file) => sum + (file.additions || 0) + (file.deletions || 0), 0);
const nonTestChanges = totalChanges - testChanges;
const tooManyLabels = finalLabels.length > MAX_LABELS;
const tooManyChanges = nonTestChanges > TOO_BIG_THRESHOLD;
@@ -574,8 +535,7 @@ jobs:
dashboardLabels,
actionsLabels,
codeOwnerLabels,
testLabels,
checkboxLabels
testLabels
] = await Promise.all([
detectMergeBranch(),
detectComponentPlatforms(apiData),
@@ -586,8 +546,7 @@ jobs:
detectDashboardChanges(),
detectGitHubActionsChanges(),
detectCodeOwner(),
detectTests(),
detectPRTemplateCheckboxes()
detectTests()
]);
// Combine all labels
@@ -601,8 +560,7 @@ jobs:
...dashboardLabels,
...actionsLabels,
...codeOwnerLabels,
...testLabels,
...checkboxLabels
...testLabels
]);
// Detect requirements based on all other labels

View File

@@ -21,9 +21,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Set up Python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: "3.11"
@@ -47,7 +47,7 @@ jobs:
fi
- if: failure()
name: Review PR
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
script: |
await github.rest.pulls.createReview({
@@ -70,7 +70,7 @@ jobs:
esphome/components/api/api_pb2_service.*
- if: success()
name: Dismiss review
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
script: |
let reviews = await github.rest.pulls.listReviews({

View File

@@ -20,10 +20,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Set up Python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: "3.11"
@@ -41,7 +41,7 @@ jobs:
- if: failure()
name: Request changes
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
script: |
await github.rest.pulls.createReview({
@@ -54,7 +54,7 @@ jobs:
- if: success()
name: Dismiss review
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
script: |
let reviews = await github.rest.pulls.listReviews({

View File

@@ -43,9 +43,9 @@ jobs:
- "docker"
# - "lint"
steps:
- uses: actions/checkout@v5.0.0
- uses: actions/checkout@v4.2.2
- name: Set up Python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: "3.11"
- name: Set up Docker Buildx

View File

@@ -36,18 +36,18 @@ jobs:
cache-key: ${{ steps.cache-key.outputs.key }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Generate cache-key
id: cache-key
run: echo key="${{ hashFiles('requirements.txt', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.2.4
uses: actions/cache@v4.2.3
with:
path: venv
# yamllint disable-line rule:line-length
@@ -70,7 +70,7 @@ jobs:
if: needs.determine-jobs.outputs.python-linters == 'true'
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -91,7 +91,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -136,7 +136,7 @@ jobs:
- common
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Restore Python
id: restore-python
uses: ./.github/actions/restore-python
@@ -156,12 +156,12 @@ jobs:
. venv/bin/activate
pytest -vv --cov-report=xml --tb=native -n auto tests --ignore=tests/integration/
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5.5.1
uses: codecov/codecov-action@v5.4.3
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Save Python virtual environment cache
if: github.ref == 'refs/heads/dev'
uses: actions/cache/save@v4.2.4
uses: actions/cache/save@v4.2.3
with:
path: venv
key: ${{ runner.os }}-${{ steps.restore-python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }}
@@ -179,7 +179,7 @@ jobs:
component-test-count: ${{ steps.determine.outputs.component-test-count }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
with:
# Fetch enough history to find the merge base
fetch-depth: 2
@@ -214,15 +214,15 @@ jobs:
if: needs.determine-jobs.outputs.integration-tests == 'true'
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Set up Python 3.13
id: python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: "3.13"
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.2.4
uses: actions/cache@v4.2.3
with:
path: venv
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }}
@@ -281,13 +281,13 @@ jobs:
pio_cache_key: tidyesp32-idf
- id: clang-tidy
name: Run script/clang-tidy for ZEPHYR
options: --environment nrf52-tidy --grep USE_ZEPHYR --grep USE_NRF52
options: --environment nrf52-tidy --grep USE_ZEPHYR
pio_cache_key: tidy-zephyr
ignore_errors: false
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
with:
# Need history for HEAD~1 to work for checking changed files
fetch-depth: 2
@@ -300,14 +300,14 @@ jobs:
- name: Cache platformio
if: github.ref == 'refs/heads/dev'
uses: actions/cache@v4.2.4
uses: actions/cache@v4.2.3
with:
path: ~/.platformio
key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }}
- name: Cache platformio
if: github.ref != 'refs/heads/dev'
uses: actions/cache/restore@v4.2.4
uses: actions/cache/restore@v4.2.3
with:
path: ~/.platformio
key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }}
@@ -374,7 +374,7 @@ jobs:
sudo apt-get install libsdl2-dev
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -400,7 +400,7 @@ jobs:
matrix: ${{ steps.split.outputs.components }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Split components into 20 groups
id: split
run: |
@@ -430,7 +430,7 @@ jobs:
sudo apt-get install libsdl2-dev
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Restore Python
uses: ./.github/actions/restore-python
with:
@@ -459,7 +459,7 @@ jobs:
if: github.event_name == 'pull_request' && github.base_ref != 'beta' && github.base_ref != 'release'
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Restore Python
uses: ./.github/actions/restore-python
with:

View File

@@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Request reviews from component codeowners
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
script: |
const owner = context.repo.owner;

View File

@@ -54,7 +54,7 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Add external component comment
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Notify codeowners for component issues
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
script: |
const owner = context.repo.owner;

24
.github/workflows/needs-docs.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Needs Docs
on:
pull_request:
types: [labeled, unlabeled]
jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- name: Check for needs-docs label
uses: actions/github-script@v7.0.1
with:
script: |
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const needsDocs = labels.find(label => label.name === 'needs-docs');
if (needsDocs) {
core.setFailed('Pull request needs docs');
}

View File

@@ -20,7 +20,7 @@ jobs:
branch_build: ${{ steps.tag.outputs.branch_build }}
deploy_env: ${{ steps.tag.outputs.deploy_env }}
steps:
- uses: actions/checkout@v5.0.0
- uses: actions/checkout@v4.2.2
- name: Get tag
id: tag
# yamllint disable rule:line-length
@@ -60,9 +60,9 @@ jobs:
contents: read
id-token: write
steps:
- uses: actions/checkout@v5.0.0
- uses: actions/checkout@v4.2.2
- name: Set up Python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: "3.x"
- name: Build
@@ -70,7 +70,7 @@ jobs:
pip3 install build
python3 -m build
- name: Publish
uses: pypa/gh-action-pypi-publish@v1.13.0
uses: pypa/gh-action-pypi-publish@v1.12.4
with:
skip-existing: true
@@ -92,9 +92,9 @@ jobs:
os: "ubuntu-24.04-arm"
steps:
- uses: actions/checkout@v5.0.0
- uses: actions/checkout@v4.2.2
- name: Set up Python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: "3.11"
@@ -102,12 +102,12 @@ jobs:
uses: docker/setup-buildx-action@v3.11.1
- name: Log in to docker hub
uses: docker/login-action@v3.5.0
uses: docker/login-action@v3.4.0
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
uses: docker/login-action@v3.5.0
uses: docker/login-action@v3.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -168,10 +168,10 @@ jobs:
- ghcr
- dockerhub
steps:
- uses: actions/checkout@v5.0.0
- uses: actions/checkout@v4.2.2
- name: Download digests
uses: actions/download-artifact@v5.0.0
uses: actions/download-artifact@v4.3.0
with:
pattern: digests-*
path: /tmp/digests
@@ -182,13 +182,13 @@ jobs:
- name: Log in to docker hub
if: matrix.registry == 'dockerhub'
uses: docker/login-action@v3.5.0
uses: docker/login-action@v3.4.0
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
if: matrix.registry == 'ghcr'
uses: docker/login-action@v3.5.0
uses: docker/login-action@v3.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -220,7 +220,7 @@ jobs:
- deploy-manifest
steps:
- name: Trigger Workflow
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
github-token: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }}
script: |
@@ -246,7 +246,7 @@ jobs:
environment: ${{ needs.init.outputs.deploy_env }}
steps:
- name: Trigger Workflow
uses: actions/github-script@v8.0.0
uses: actions/github-script@v7.0.1
with:
github-token: ${{ secrets.DEPLOY_ESPHOME_SCHEMA_REPO_TOKEN }}
script: |

View File

@@ -17,7 +17,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10.0.0
- uses: actions/stale@v9.1.0
with:
days-before-pr-stale: 90
days-before-pr-close: 7
@@ -37,7 +37,7 @@ jobs:
close-issues:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10.0.0
- uses: actions/stale@v9.1.0
with:
days-before-pr-stale: -1
days-before-pr-close: -1

View File

@@ -1,30 +0,0 @@
name: Status check labels
on:
pull_request:
types: [labeled, unlabeled]
jobs:
check:
name: Check ${{ matrix.label }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
label:
- needs-docs
- merge-after-release
steps:
- name: Check for ${{ matrix.label }} label
uses: actions/github-script@v8.0.0
with:
script: |
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const hasLabel = labels.find(label => label.name === '${{ matrix.label }}');
if (hasLabel) {
core.setFailed('Pull request cannot be merged, it is labeled as ${{ matrix.label }}');
}

View File

@@ -13,16 +13,16 @@ jobs:
if: github.repository == 'esphome/esphome'
steps:
- name: Checkout
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
- name: Checkout Home Assistant
uses: actions/checkout@v5.0.0
uses: actions/checkout@v4.2.2
with:
repository: home-assistant/core
path: lib/home-assistant
- name: Setup Python
uses: actions/setup-python@v6.0.0
uses: actions/setup-python@v5.6.0
with:
python-version: 3.13

View File

@@ -11,7 +11,7 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.13.0
rev: v0.12.5
hooks:
# Run the linter.
- id: ruff

View File

@@ -40,11 +40,11 @@ esphome/components/analog_threshold/* @ianchi
esphome/components/animation/* @syndlex
esphome/components/anova/* @buxtronix
esphome/components/apds9306/* @aodrenah
esphome/components/api/* @esphome/core
esphome/components/api/* @OttoWinter
esphome/components/as5600/* @ammmze
esphome/components/as5600/sensor/* @ammmze
esphome/components/as7341/* @mrgnr
esphome/components/async_tcp/* @esphome/core
esphome/components/async_tcp/* @OttoWinter
esphome/components/at581x/* @X-Ryl669
esphome/components/atc_mithermometer/* @ahpohl
esphome/components/atm90e26/* @danieltwagner
@@ -66,10 +66,10 @@ esphome/components/binary_sensor/* @esphome/core
esphome/components/bk72xx/* @kuba2k2
esphome/components/bl0906/* @athom-tech @jesserockz @tarontop
esphome/components/bl0939/* @ziceva
esphome/components/bl0940/* @dan-s-github @tobias-
esphome/components/bl0940/* @tobias-
esphome/components/bl0942/* @dbuezas @dwmw2
esphome/components/ble_client/* @buxtronix @clydebarrow
esphome/components/bluetooth_proxy/* @bdraco @jesserockz
esphome/components/bluetooth_proxy/* @jesserockz
esphome/components/bme280_base/* @esphome/core
esphome/components/bme280_spi/* @apbodrov
esphome/components/bme680_bsec/* @trvrnrth
@@ -88,11 +88,10 @@ esphome/components/bp1658cj/* @Cossid
esphome/components/bp5758d/* @Cossid
esphome/components/button/* @esphome/core
esphome/components/bytebuffer/* @clydebarrow
esphome/components/camera/* @bdraco @DT-art1
esphome/components/camera_encoder/* @DT-art1
esphome/components/camera/* @DT-art1 @bdraco
esphome/components/canbus/* @danielschramm @mvturnho
esphome/components/cap1188/* @mreditor97
esphome/components/captive_portal/* @esphome/core
esphome/components/captive_portal/* @OttoWinter
esphome/components/ccs811/* @habbie
esphome/components/cd74hc4067/* @asoehlke
esphome/components/ch422g/* @clydebarrow @jesterret
@@ -119,7 +118,7 @@ esphome/components/dallas_temp/* @ssieb
esphome/components/daly_bms/* @s1lvi0
esphome/components/dashboard_import/* @esphome/core
esphome/components/datetime/* @jesserockz @rfdarter
esphome/components/debug/* @esphome/core
esphome/components/debug/* @OttoWinter
esphome/components/delonghi/* @grob6000
esphome/components/dfplayer/* @glmnet
esphome/components/dfrobot_sen0395/* @niklasweber
@@ -145,10 +144,9 @@ esphome/components/es8156/* @kbx81
esphome/components/es8311/* @kahrendt @kroimon
esphome/components/es8388/* @P4uLT
esphome/components/esp32/* @esphome/core
esphome/components/esp32_ble/* @bdraco @jesserockz @Rapsssito
esphome/components/esp32_ble_client/* @bdraco @jesserockz
esphome/components/esp32_ble_server/* @clydebarrow @jesserockz @Rapsssito
esphome/components/esp32_ble_tracker/* @bdraco
esphome/components/esp32_ble/* @Rapsssito @jesserockz
esphome/components/esp32_ble_client/* @jesserockz
esphome/components/esp32_ble_server/* @Rapsssito @clydebarrow @jesserockz
esphome/components/esp32_camera_web_server/* @ayufan
esphome/components/esp32_can/* @Sympatron
esphome/components/esp32_hosted/* @swoboda1337
@@ -157,7 +155,6 @@ esphome/components/esp32_rmt/* @jesserockz
esphome/components/esp32_rmt_led_strip/* @jesserockz
esphome/components/esp8266/* @esphome/core
esphome/components/esp_ldo/* @clydebarrow
esphome/components/espnow/* @jesserockz
esphome/components/ethernet_info/* @gtjadsonsantos
esphome/components/event/* @nohat
esphome/components/event_emitter/* @Rapsssito
@@ -167,7 +164,7 @@ esphome/components/ezo_pmp/* @carlos-sarmiento
esphome/components/factory_reset/* @anatoly-savchenkov
esphome/components/fastled_base/* @OttoWinter
esphome/components/feedback/* @ianchi
esphome/components/fingerprint_grow/* @alexborro @loongyh @OnFreund
esphome/components/fingerprint_grow/* @OnFreund @alexborro @loongyh
esphome/components/font/* @clydebarrow @esphome/core
esphome/components/fs3000/* @kahrendt
esphome/components/ft5x06/* @clydebarrow
@@ -203,7 +200,7 @@ esphome/components/heatpumpir/* @rob-deutsch
esphome/components/hitachi_ac424/* @sourabhjaiswal
esphome/components/hm3301/* @freekode
esphome/components/hmac_md5/* @dwmw2
esphome/components/homeassistant/* @esphome/core @OttoWinter
esphome/components/homeassistant/* @OttoWinter @esphome/core
esphome/components/homeassistant/number/* @landonr
esphome/components/homeassistant/switch/* @Links2004
esphome/components/honeywell_hih_i2c/* @Benichou34
@@ -228,18 +225,18 @@ esphome/components/iaqcore/* @yozik04
esphome/components/ili9xxx/* @clydebarrow @nielsnl68
esphome/components/improv_base/* @esphome/core
esphome/components/improv_serial/* @esphome/core
esphome/components/ina226/* @latonita @Sergio303
esphome/components/ina226/* @Sergio303 @latonita
esphome/components/ina260/* @mreditor97
esphome/components/ina2xx_base/* @latonita
esphome/components/ina2xx_i2c/* @latonita
esphome/components/ina2xx_spi/* @latonita
esphome/components/inkbird_ibsth1_mini/* @fkirill
esphome/components/inkplate/* @jesserockz @JosipKuci
esphome/components/inkplate6/* @jesserockz
esphome/components/integration/* @OttoWinter
esphome/components/internal_temperature/* @Mat931
esphome/components/interval/* @esphome/core
esphome/components/jsn_sr04t/* @Mafus1
esphome/components/json/* @esphome/core
esphome/components/json/* @OttoWinter
esphome/components/kamstrup_kmp/* @cfeenstra1024
esphome/components/key_collector/* @ssieb
esphome/components/key_provider/* @ssieb
@@ -247,7 +244,6 @@ esphome/components/kuntze/* @ssieb
esphome/components/lc709203f/* @ilikecake
esphome/components/lcd_menu/* @numo68
esphome/components/ld2410/* @regevbr @sebcaps
esphome/components/ld2412/* @Rihan9
esphome/components/ld2420/* @descipher
esphome/components/ld2450/* @hareeshmu
esphome/components/ld24xx/* @kbx81
@@ -277,8 +273,8 @@ esphome/components/max7219digit/* @rspaargaren
esphome/components/max9611/* @mckaymatthew
esphome/components/mcp23008/* @jesserockz
esphome/components/mcp23017/* @jesserockz
esphome/components/mcp23s08/* @jesserockz @SenexCrenshaw
esphome/components/mcp23s17/* @jesserockz @SenexCrenshaw
esphome/components/mcp23s08/* @SenexCrenshaw @jesserockz
esphome/components/mcp23s17/* @SenexCrenshaw @jesserockz
esphome/components/mcp23x08_base/* @jesserockz
esphome/components/mcp23x17_base/* @jesserockz
esphome/components/mcp23xxx_base/* @jesserockz
@@ -299,7 +295,6 @@ esphome/components/mics_4514/* @jesserockz
esphome/components/midea/* @dudanov
esphome/components/midea_ir/* @dudanov
esphome/components/mipi_dsi/* @clydebarrow
esphome/components/mipi_rgb/* @clydebarrow
esphome/components/mipi_spi/* @clydebarrow
esphome/components/mitsubishi/* @RubyBailey
esphome/components/mixer/speaker/* @kahrendt
@@ -343,7 +338,7 @@ esphome/components/ota/* @esphome/core
esphome/components/output/* @esphome/core
esphome/components/packet_transport/* @clydebarrow
esphome/components/pca6416a/* @Mat931
esphome/components/pca9554/* @bdraco @clydebarrow @hwstar
esphome/components/pca9554/* @clydebarrow @hwstar
esphome/components/pcf85063/* @brogon
esphome/components/pcf8563/* @KoenBreeman
esphome/components/pi4ioe5v6408/* @jesserockz
@@ -354,9 +349,9 @@ esphome/components/pm2005/* @andrewjswan
esphome/components/pmsa003i/* @sjtrny
esphome/components/pmsx003/* @ximex
esphome/components/pmwcs3/* @SeByDocKy
esphome/components/pn532/* @jesserockz @OttoWinter
esphome/components/pn532_i2c/* @jesserockz @OttoWinter
esphome/components/pn532_spi/* @jesserockz @OttoWinter
esphome/components/pn532/* @OttoWinter @jesserockz
esphome/components/pn532_i2c/* @OttoWinter @jesserockz
esphome/components/pn532_spi/* @OttoWinter @jesserockz
esphome/components/pn7150/* @jesserockz @kbx81
esphome/components/pn7150_i2c/* @jesserockz @kbx81
esphome/components/pn7160/* @jesserockz @kbx81
@@ -365,7 +360,7 @@ esphome/components/pn7160_spi/* @jesserockz @kbx81
esphome/components/power_supply/* @esphome/core
esphome/components/preferences/* @esphome/core
esphome/components/psram/* @esphome/core
esphome/components/pulse_meter/* @cstaahl @stevebaxter @TrentHouliston
esphome/components/pulse_meter/* @TrentHouliston @cstaahl @stevebaxter
esphome/components/pvvx_mithermometer/* @pasiz
esphome/components/pylontech/* @functionpointer
esphome/components/qmp6988/* @andrewpc
@@ -406,7 +401,7 @@ esphome/components/sensirion_common/* @martgras
esphome/components/sensor/* @esphome/core
esphome/components/sfa30/* @ghsensdev
esphome/components/sgp40/* @SenexCrenshaw
esphome/components/sgp4x/* @martgras @SenexCrenshaw
esphome/components/sgp4x/* @SenexCrenshaw @martgras
esphome/components/shelly_dimmer/* @edge90 @rnauber
esphome/components/sht3xd/* @mrtoy-me
esphome/components/sht4x/* @sjtrny
@@ -471,13 +466,13 @@ esphome/components/template/event/* @nohat
esphome/components/template/fan/* @ssieb
esphome/components/text/* @mauritskorse
esphome/components/thermostat/* @kbx81
esphome/components/time/* @esphome/core
esphome/components/time/* @OttoWinter
esphome/components/tlc5947/* @rnauber
esphome/components/tlc5971/* @IJIJI
esphome/components/tm1621/* @Philippe12
esphome/components/tm1637/* @glmnet
esphome/components/tm1638/* @skykingjwc
esphome/components/tm1651/* @mrtoy-me
esphome/components/tm1651/* @freekode
esphome/components/tmp102/* @timsavage
esphome/components/tmp1075/* @sybrenstuvel
esphome/components/tmp117/* @Azimath
@@ -515,7 +510,7 @@ esphome/components/wake_on_lan/* @clydebarrow @willwill2will54
esphome/components/watchdog/* @oarcher
esphome/components/waveshare_epaper/* @clydebarrow
esphome/components/web_server/ota/* @esphome/core
esphome/components/web_server_base/* @esphome/core
esphome/components/web_server_base/* @OttoWinter
esphome/components/web_server_idf/* @dentra
esphome/components/weikai/* @DrCoolZic
esphome/components/weikai_i2c/* @DrCoolZic

View File

@@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 2025.10.0-dev
PROJECT_NUMBER = 2025.8.0-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@@ -90,7 +90,7 @@ def main():
def run_command(*cmd, ignore_error: bool = False):
print(f"$ {shlex.join(list(cmd))}")
if not args.dry_run:
rc = subprocess.call(list(cmd), close_fds=False)
rc = subprocess.call(list(cmd))
if rc != 0 and not ignore_error:
print("Command failed")
sys.exit(1)

View File

@@ -9,17 +9,14 @@ import os
import re
import sys
import time
from typing import Protocol
import argcomplete
from esphome import const, writer, yaml_util
import esphome.codegen as cg
from esphome.components.mqtt import CONF_DISCOVER_IP
from esphome.config import iter_component_configs, read_config, strip_default_ids
from esphome.const import (
ALLOWED_NAME_CHARS,
CONF_API,
CONF_BAUD_RATE,
CONF_BROKER,
CONF_DEASSERT_RTS_DTR,
@@ -45,10 +42,8 @@ from esphome.const import (
SECRETS_FILES,
)
from esphome.core import CORE, EsphomeError, coroutine
from esphome.enum import StrEnum
from esphome.helpers import get_bool_env, indent, is_ip_address
from esphome.log import AnsiFore, color, setup_log
from esphome.types import ConfigType
from esphome.util import (
get_serial_ports,
list_yaml_files,
@@ -60,23 +55,6 @@ from esphome.util import (
_LOGGER = logging.getLogger(__name__)
class ArgsProtocol(Protocol):
device: list[str] | None
reset: bool
username: str | None
password: str | None
client_id: str | None
topic: str | None
file: str | None
no_logs: bool
only_generate: bool
show_secrets: bool
dashboard: bool
configuration: str
name: str
upload_speed: str | None
def choose_prompt(options, purpose: str = None):
if not options:
raise EsphomeError(
@@ -109,176 +87,51 @@ def choose_prompt(options, purpose: str = None):
return options[opt - 1][1]
class Purpose(StrEnum):
UPLOADING = "uploading"
LOGGING = "logging"
def choose_upload_log_host(
default: list[str] | str | None,
check_default: str | None,
purpose: Purpose,
) -> list[str]:
# Convert to list for uniform handling
defaults = [default] if isinstance(default, str) else default or []
# If devices specified, resolve them
if defaults:
resolved: list[str] = []
for device in defaults:
if device == "SERIAL":
serial_ports = get_serial_ports()
if not serial_ports:
_LOGGER.warning("No serial ports found, skipping SERIAL device")
continue
options = [
(f"{port.path} ({port.description})", port.path)
for port in serial_ports
]
resolved.append(choose_prompt(options, purpose=purpose))
elif device == "OTA":
# ensure IP adresses are used first
if is_ip_address(CORE.address) and (
(purpose == Purpose.LOGGING and has_api())
or (purpose == Purpose.UPLOADING and has_ota())
):
resolved.append(CORE.address)
if purpose == Purpose.LOGGING:
if has_api() and has_mqtt_ip_lookup():
resolved.append("MQTTIP")
if has_mqtt_logging():
resolved.append("MQTT")
if has_api() and has_non_ip_address():
resolved.append(CORE.address)
elif purpose == Purpose.UPLOADING:
if has_ota() and has_mqtt_ip_lookup():
resolved.append("MQTTIP")
if has_ota() and has_non_ip_address():
resolved.append(CORE.address)
else:
resolved.append(device)
if not resolved:
_LOGGER.error("All specified devices: %s could not be resolved.", defaults)
return resolved
# No devices specified, show interactive chooser
default, check_default, show_ota, show_mqtt, show_api, purpose: str = None
):
options = [
(f"{port.path} ({port.description})", port.path) for port in get_serial_ports()
]
if purpose == Purpose.LOGGING:
if has_mqtt_logging():
mqtt_config = CORE.config[CONF_MQTT]
options.append((f"MQTT ({mqtt_config[CONF_BROKER]})", "MQTT"))
if has_api():
if has_resolvable_address():
options.append((f"Over The Air ({CORE.address})", CORE.address))
if has_mqtt_ip_lookup():
options.append(("Over The Air (MQTT IP lookup)", "MQTTIP"))
elif purpose == Purpose.UPLOADING and has_ota():
if has_resolvable_address():
options.append((f"Over The Air ({CORE.address})", CORE.address))
if has_mqtt_ip_lookup():
options.append(("Over The Air (MQTT IP lookup)", "MQTTIP"))
if default == "SERIAL":
return choose_prompt(options, purpose=purpose)
if (show_ota and "ota" in CORE.config) or (show_api and "api" in CORE.config):
options.append((f"Over The Air ({CORE.address})", CORE.address))
if default == "OTA":
return CORE.address
if (
show_mqtt
and (mqtt_config := CORE.config.get(CONF_MQTT))
and mqtt_logging_enabled(mqtt_config)
):
options.append((f"MQTT ({mqtt_config[CONF_BROKER]})", "MQTT"))
if default == "OTA":
return "MQTT"
if default is not None:
return default
if check_default is not None and check_default in [opt[1] for opt in options]:
return [check_default]
return [choose_prompt(options, purpose=purpose)]
return check_default
return choose_prompt(options, purpose=purpose)
def has_mqtt_logging() -> bool:
"""Check if MQTT logging is available."""
if CONF_MQTT not in CORE.config:
return False
mqtt_config = CORE.config[CONF_MQTT]
# enabled by default
if CONF_LOG_TOPIC not in mqtt_config:
return True
def mqtt_logging_enabled(mqtt_config):
log_topic = mqtt_config[CONF_LOG_TOPIC]
if log_topic is None:
return False
if CONF_TOPIC not in log_topic:
return False
return log_topic[CONF_LEVEL] != "NONE"
return log_topic.get(CONF_LEVEL, None) != "NONE"
def has_mqtt() -> bool:
"""Check if MQTT is available."""
return CONF_MQTT in CORE.config
def has_api() -> bool:
"""Check if API is available."""
return CONF_API in CORE.config
def has_ota() -> bool:
"""Check if OTA is available."""
return CONF_OTA in CORE.config
def has_mqtt_ip_lookup() -> bool:
"""Check if MQTT is available and IP lookup is supported."""
if CONF_MQTT not in CORE.config:
return False
# Default Enabled
if CONF_DISCOVER_IP not in CORE.config[CONF_MQTT]:
return True
return CORE.config[CONF_MQTT][CONF_DISCOVER_IP]
def has_mdns() -> bool:
"""Check if MDNS is available."""
return CONF_MDNS not in CORE.config or not CORE.config[CONF_MDNS][CONF_DISABLED]
def has_non_ip_address() -> bool:
"""Check if CORE.address is set and is not an IP address."""
return CORE.address is not None and not is_ip_address(CORE.address)
def has_ip_address() -> bool:
"""Check if CORE.address is a valid IP address."""
return CORE.address is not None and is_ip_address(CORE.address)
def has_resolvable_address() -> bool:
"""Check if CORE.address is resolvable (via mDNS or is an IP address)."""
return has_mdns() or has_ip_address()
def mqtt_get_ip(config: ConfigType, username: str, password: str, client_id: str):
from esphome import mqtt
return mqtt.get_esphome_device_ip(config, username, password, client_id)
_PORT_TO_PORT_TYPE = {
"MQTT": "MQTT",
"MQTTIP": "MQTTIP",
}
def get_port_type(port: str) -> str:
def get_port_type(port):
if port.startswith("/") or port.startswith("COM"):
return "SERIAL"
return _PORT_TO_PORT_TYPE.get(port, "NETWORK")
if port == "MQTT":
return "MQTT"
return "NETWORK"
def run_miniterm(config: ConfigType, port: str, args) -> int:
def run_miniterm(config, port, args):
from aioesphomeapi import LogParser
import serial
@@ -320,9 +173,7 @@ def run_miniterm(config: ConfigType, port: str, args) -> int:
.replace(b"\n", b"")
.decode("utf8", "backslashreplace")
)
time_ = datetime.now()
nanoseconds = time_.microsecond // 1000
time_str = f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}.{nanoseconds:03}]"
time_str = datetime.now().time().strftime("[%H:%M:%S]")
safe_print(parser.parse_line(line, time_str))
backtrace_state = platformio_api.process_stacktrace(
@@ -357,7 +208,7 @@ def wrap_to_code(name, comp):
return wrapped
def write_cpp(config: ConfigType) -> int:
def write_cpp(config):
if not get_bool_env(ENV_NOGITIGNORE):
writer.write_gitignore()
@@ -365,7 +216,7 @@ def write_cpp(config: ConfigType) -> int:
return write_cpp_file()
def generate_cpp_contents(config: ConfigType) -> None:
def generate_cpp_contents(config):
_LOGGER.info("Generating C++ source...")
for name, component, conf in iter_component_configs(CORE.config):
@@ -376,7 +227,7 @@ def generate_cpp_contents(config: ConfigType) -> None:
CORE.flush_tasks()
def write_cpp_file() -> int:
def write_cpp_file():
code_s = indent(CORE.cpp_main_section)
writer.write_cpp(code_s)
@@ -387,7 +238,7 @@ def write_cpp_file() -> int:
return 0
def compile_program(args: ArgsProtocol, config: ConfigType) -> int:
def compile_program(args, config):
from esphome import platformio_api
_LOGGER.info("Compiling app...")
@@ -398,9 +249,7 @@ def compile_program(args: ArgsProtocol, config: ConfigType) -> int:
return 0 if idedata is not None else 1
def upload_using_esptool(
config: ConfigType, port: str, file: str, speed: int
) -> str | int:
def upload_using_esptool(config, port, file, speed):
from esphome import platformio_api
first_baudrate = speed or config[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS].get(
@@ -428,20 +277,20 @@ def upload_using_esptool(
def run_esptool(baud_rate):
cmd = [
"esptool",
"esptool.py",
"--before",
"default-reset",
"default_reset",
"--after",
"hard-reset",
"hard_reset",
"--baud",
str(baud_rate),
"--port",
port,
"--chip",
mcu,
"write-flash",
"write_flash",
"-z",
"--flash-size",
"--flash_size",
"detect",
]
for img in flash_images:
@@ -465,7 +314,7 @@ def upload_using_esptool(
return run_esptool(115200)
def upload_using_platformio(config: ConfigType, port: str):
def upload_using_platformio(config, port):
from esphome import platformio_api
upload_args = ["-t", "upload", "-t", "nobuild"]
@@ -474,7 +323,7 @@ def upload_using_platformio(config: ConfigType, port: str):
return platformio_api.run_platformio_cli_run(config, CORE.verbose, *upload_args)
def check_permissions(port: str):
def check_permissions(port):
if os.name == "posix" and get_port_type(port) == "SERIAL":
# Check if we can open selected serial port
if not os.access(port, os.F_OK):
@@ -492,29 +341,27 @@ def check_permissions(port: str):
)
def upload_program(
config: ConfigType, args: ArgsProtocol, devices: list[str]
) -> tuple[int, str | None]:
host = devices[0]
def upload_program(config, args, host):
try:
module = importlib.import_module("esphome.components." + CORE.target_platform)
if getattr(module, "upload_program")(config, args, host):
return 0, host
return 0
except AttributeError:
pass
if get_port_type(host) == "SERIAL":
check_permissions(host)
exit_code = 1
if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
file = getattr(args, "file", None)
exit_code = upload_using_esptool(config, host, file, args.upload_speed)
elif CORE.target_platform == PLATFORM_RP2040 or CORE.is_libretiny:
exit_code = upload_using_platformio(config, host)
# else: Unknown target platform, exit_code remains 1
return upload_using_esptool(config, host, file, args.upload_speed)
return exit_code, host if exit_code == 0 else None
if CORE.target_platform in (PLATFORM_RP2040):
return upload_using_platformio(config, args.device)
if CORE.is_libretiny:
return upload_using_platformio(config, host)
return 1 # Unknown target platform
ota_conf = {}
for ota_item in config.get(CONF_OTA, []):
@@ -531,53 +378,45 @@ def upload_program(
remote_port = int(ota_conf[CONF_PORT])
password = ota_conf.get(CONF_PASSWORD, "")
binary = args.file if getattr(args, "file", None) is not None else CORE.firmware_bin
# MQTT address resolution
if get_port_type(host) in ("MQTT", "MQTTIP"):
devices = mqtt_get_ip(config, args.username, args.password, args.client_id)
if (
CONF_MQTT in config # pylint: disable=too-many-boolean-expressions
and (not args.device or args.device in ("MQTT", "OTA"))
and (
((config[CONF_MDNS][CONF_DISABLED]) and not is_ip_address(CORE.address))
or get_port_type(host) == "MQTT"
)
):
from esphome import mqtt
return espota2.run_ota(devices, remote_port, password, binary)
host = mqtt.get_esphome_device_ip(
config, args.username, args.password, args.client_id
)
if getattr(args, "file", None) is not None:
return espota2.run_ota(host, remote_port, password, args.file)
return espota2.run_ota(host, remote_port, password, CORE.firmware_bin)
def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int | None:
try:
module = importlib.import_module("esphome.components." + CORE.target_platform)
if getattr(module, "show_logs")(config, args, devices):
return 0
except AttributeError:
pass
def show_logs(config, args, port):
if "logger" not in config:
raise EsphomeError("Logger is not configured!")
port = devices[0]
if get_port_type(port) == "SERIAL":
check_permissions(port)
return run_miniterm(config, port, args)
if get_port_type(port) == "NETWORK" and "api" in config:
if config[CONF_MDNS][CONF_DISABLED] and CONF_MQTT in config:
from esphome import mqtt
port_type = get_port_type(port)
# Check if we should use API for logging
if has_api():
addresses_to_use: list[str] | None = None
if port_type == "NETWORK" and (has_mdns() or is_ip_address(port)):
addresses_to_use = devices
elif port_type in ("NETWORK", "MQTT", "MQTTIP") and has_mqtt_ip_lookup():
# Only use MQTT IP lookup if the first condition didn't match
# (for MQTT/MQTTIP types, or for NETWORK when mdns/ip check fails)
addresses_to_use = mqtt_get_ip(
port = mqtt.get_esphome_device_ip(
config, args.username, args.password, args.client_id
)
)[0]
if addresses_to_use is not None:
from esphome.components.api.client import run_logs
from esphome.components.api.client import run_logs
return run_logs(config, addresses_to_use)
if port_type in ("NETWORK", "MQTT") and has_mqtt_logging():
return run_logs(config, port)
if get_port_type(port) == "MQTT" and "mqtt" in config:
from esphome import mqtt
return mqtt.show_logs(
@@ -587,7 +426,7 @@ def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int
raise EsphomeError("No remote or local logging method configured (api/mqtt/logger)")
def clean_mqtt(config: ConfigType, args: ArgsProtocol) -> int | None:
def clean_mqtt(config, args):
from esphome import mqtt
return mqtt.clear_topic(
@@ -595,13 +434,13 @@ def clean_mqtt(config: ConfigType, args: ArgsProtocol) -> int | None:
)
def command_wizard(args: ArgsProtocol) -> int | None:
def command_wizard(args):
from esphome import wizard
return wizard.wizard(args.configuration)
def command_config(args: ArgsProtocol, config: ConfigType) -> int | None:
def command_config(args, config):
if not CORE.verbose:
config = strip_default_ids(config)
output = yaml_util.dump(config, args.show_secrets)
@@ -616,7 +455,7 @@ def command_config(args: ArgsProtocol, config: ConfigType) -> int | None:
return 0
def command_vscode(args: ArgsProtocol) -> int | None:
def command_vscode(args):
from esphome import vscode
logging.disable(logging.INFO)
@@ -624,7 +463,14 @@ def command_vscode(args: ArgsProtocol) -> int | None:
vscode.read_config(args)
def command_compile(args: ArgsProtocol, config: ConfigType) -> int | None:
def command_compile(args, config):
# Set memory analysis options in config
if args.analyze_memory:
config.setdefault(CONF_ESPHOME, {})["analyze_memory"] = True
if args.memory_report:
config.setdefault(CONF_ESPHOME, {})["memory_report_file"] = args.memory_report
exit_code = write_cpp(config)
if exit_code != 0:
return exit_code
@@ -638,23 +484,23 @@ def command_compile(args: ArgsProtocol, config: ConfigType) -> int | None:
return 0
def command_upload(args: ArgsProtocol, config: ConfigType) -> int | None:
# Get devices, resolving special identifiers like OTA
devices = choose_upload_log_host(
def command_upload(args, config):
port = choose_upload_log_host(
default=args.device,
check_default=None,
purpose=Purpose.UPLOADING,
show_ota=True,
show_mqtt=False,
show_api=False,
purpose="uploading",
)
exit_code, _ = upload_program(config, args, devices)
if exit_code == 0:
_LOGGER.info("Successfully uploaded program.")
else:
_LOGGER.warning("Failed to upload to %s", devices)
return exit_code
exit_code = upload_program(config, args, port)
if exit_code != 0:
return exit_code
_LOGGER.info("Successfully uploaded program.")
return 0
def command_discover(args: ArgsProtocol, config: ConfigType) -> int | None:
def command_discover(args, config):
if "mqtt" in config:
from esphome import mqtt
@@ -663,17 +509,19 @@ def command_discover(args: ArgsProtocol, config: ConfigType) -> int | None:
raise EsphomeError("No discover method configured (mqtt)")
def command_logs(args: ArgsProtocol, config: ConfigType) -> int | None:
# Get devices, resolving special identifiers like OTA
devices = choose_upload_log_host(
def command_logs(args, config):
port = choose_upload_log_host(
default=args.device,
check_default=None,
purpose=Purpose.LOGGING,
show_ota=False,
show_mqtt=True,
show_api=True,
purpose="logging",
)
return show_logs(config, args, devices)
return show_logs(config, args, port)
def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
def command_run(args, config):
exit_code = write_cpp(config)
if exit_code != 0:
return exit_code
@@ -690,48 +538,47 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
program_path = idedata.raw["prog_path"]
return run_external_process(program_path)
# Get devices, resolving special identifiers like OTA
devices = choose_upload_log_host(
port = choose_upload_log_host(
default=args.device,
check_default=None,
purpose=Purpose.UPLOADING,
show_ota=True,
show_mqtt=False,
show_api=True,
purpose="uploading",
)
exit_code, successful_device = upload_program(config, args, devices)
if exit_code == 0:
_LOGGER.info("Successfully uploaded program.")
else:
_LOGGER.warning("Failed to upload to %s", devices)
exit_code = upload_program(config, args, port)
if exit_code != 0:
return exit_code
_LOGGER.info("Successfully uploaded program.")
if args.no_logs:
return 0
# For logs, prefer the device we successfully uploaded to
devices = choose_upload_log_host(
default=successful_device,
check_default=successful_device,
purpose=Purpose.LOGGING,
port = choose_upload_log_host(
default=args.device,
check_default=port,
show_ota=False,
show_mqtt=True,
show_api=True,
purpose="logging",
)
return show_logs(config, args, devices)
return show_logs(config, args, port)
def command_clean_mqtt(args: ArgsProtocol, config: ConfigType) -> int | None:
def command_clean_mqtt(args, config):
return clean_mqtt(config, args)
def command_mqtt_fingerprint(args: ArgsProtocol, config: ConfigType) -> int | None:
def command_mqtt_fingerprint(args, config):
from esphome import mqtt
return mqtt.get_fingerprint(config)
def command_version(args: ArgsProtocol) -> int | None:
def command_version(args):
safe_print(f"Version: {const.__version__}")
return 0
def command_clean(args: ArgsProtocol, config: ConfigType) -> int | None:
def command_clean(args, config):
try:
writer.clean_build()
except OSError as err:
@@ -741,13 +588,13 @@ def command_clean(args: ArgsProtocol, config: ConfigType) -> int | None:
return 0
def command_dashboard(args: ArgsProtocol) -> int | None:
def command_dashboard(args):
from esphome.dashboard import dashboard
return dashboard.start_dashboard(args)
def command_update_all(args: ArgsProtocol) -> int | None:
def command_update_all(args):
import click
success = {}
@@ -794,7 +641,7 @@ def command_update_all(args: ArgsProtocol) -> int | None:
return failed
def command_idedata(args: ArgsProtocol, config: ConfigType) -> int:
def command_idedata(args, config):
import json
from esphome import platformio_api
@@ -810,7 +657,7 @@ def command_idedata(args: ArgsProtocol, config: ConfigType) -> int:
return 0
def command_rename(args: ArgsProtocol, config: ConfigType) -> int | None:
def command_rename(args, config):
for c in args.name:
if c not in ALLOWED_NAME_CHARS:
print(
@@ -927,12 +774,6 @@ POST_CONFIG_ACTIONS = {
"discover": command_discover,
}
SIMPLE_CONFIG_ACTIONS = [
"clean",
"clean-mqtt",
"config",
]
def parse_args(argv):
options_parser = argparse.ArgumentParser(add_help=False)
@@ -1009,6 +850,17 @@ def parse_args(argv):
help="Only generate source code, do not compile.",
action="store_true",
)
parser_compile.add_argument(
"--analyze-memory",
help="Analyze and display memory usage by component after compilation.",
action="store_true",
)
parser_compile.add_argument(
"--memory-report",
help="Save memory analysis report to a file (supports .json or .txt).",
type=str,
metavar="FILE",
)
parser_upload = subparsers.add_parser(
"upload",
@@ -1020,8 +872,7 @@ def parse_args(argv):
)
parser_upload.add_argument(
"--device",
action="append",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0. Can be specified multiple times for fallback addresses.",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
)
parser_upload.add_argument(
"--upload_speed",
@@ -1043,8 +894,7 @@ def parse_args(argv):
)
parser_logs.add_argument(
"--device",
action="append",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0. Can be specified multiple times for fallback addresses.",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
)
parser_logs.add_argument(
"--reset",
@@ -1073,8 +923,7 @@ def parse_args(argv):
)
parser_run.add_argument(
"--device",
action="append",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0. Can be specified multiple times for fallback addresses.",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
)
parser_run.add_argument(
"--upload_speed",
@@ -1201,13 +1050,6 @@ def parse_args(argv):
arguments = argv[1:]
argcomplete.autocomplete(parser)
if len(arguments) > 0 and arguments[0] in SIMPLE_CONFIG_ACTIONS:
args, unknown_args = parser.parse_known_args(arguments)
if unknown_args:
_LOGGER.warning("Ignored unrecognized arguments: %s", unknown_args)
return args
return parser.parse_args(arguments)

1620
esphome/analyze_memory.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -391,7 +391,8 @@ async def build_action(full_config, template_arg, args):
)
action_id = full_config[CONF_TYPE_ID]
builder = registry_entry.coroutine_fun
return await builder(config, action_id, template_arg, args)
ret = await builder(config, action_id, template_arg, args)
return ret
async def build_action_list(config, templ, arg_type):
@@ -408,7 +409,8 @@ async def build_condition(full_config, template_arg, args):
)
action_id = full_config[CONF_TYPE_ID]
builder = registry_entry.coroutine_fun
return await builder(config, action_id, template_arg, args)
ret = await builder(config, action_id, template_arg, args)
return ret
async def build_condition_list(config, templ, args):

View File

@@ -61,10 +61,11 @@ void AbsoluteHumidityComponent::loop() {
ESP_LOGW(TAG, "No valid state from temperature sensor!");
}
if (no_humidity) {
ESP_LOGW(TAG, "No valid state from humidity sensor!");
ESP_LOGW(TAG, "No valid state from temperature sensor!");
}
ESP_LOGW(TAG, "Unable to calculate absolute humidity.");
this->publish_state(NAN);
this->status_set_warning(LOG_STR("Unable to calculate absolute humidity."));
this->status_set_warning();
return;
}
@@ -86,8 +87,9 @@ void AbsoluteHumidityComponent::loop() {
es = es_wobus(temperature_c);
break;
default:
ESP_LOGE(TAG, "Invalid saturation vapor pressure equation selection!");
this->publish_state(NAN);
this->status_set_error("Invalid saturation vapor pressure equation selection!");
this->status_set_error();
return;
}
ESP_LOGD(TAG, "Saturation vapor pressure %f kPa", es);

View File

@@ -5,7 +5,7 @@ from esphome.const import (
CONF_EQUATION,
CONF_HUMIDITY,
CONF_TEMPERATURE,
DEVICE_CLASS_ABSOLUTE_HUMIDITY,
ICON_WATER,
STATE_CLASS_MEASUREMENT,
UNIT_GRAMS_PER_CUBIC_METER,
)
@@ -27,8 +27,8 @@ EQUATION = {
CONFIG_SCHEMA = (
sensor.sensor_schema(
unit_of_measurement=UNIT_GRAMS_PER_CUBIC_METER,
icon=ICON_WATER,
accuracy_decimals=2,
device_class=DEVICE_CLASS_ABSOLUTE_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT,
)
.extend(

View File

@@ -1,6 +1,6 @@
from esphome import pins
import esphome.codegen as cg
from esphome.components.esp32 import VARIANT_ESP32P4, get_esp32_variant
from esphome.components.esp32 import get_esp32_variant
from esphome.components.esp32.const import (
VARIANT_ESP32,
VARIANT_ESP32C2,
@@ -11,8 +11,15 @@ from esphome.components.esp32.const import (
VARIANT_ESP32S2,
VARIANT_ESP32S3,
)
from esphome.config_helpers import filter_source_files_from_platform
import esphome.config_validation as cv
from esphome.const import CONF_ANALOG, CONF_INPUT, CONF_NUMBER, PLATFORM_ESP8266
from esphome.const import (
CONF_ANALOG,
CONF_INPUT,
CONF_NUMBER,
PLATFORM_ESP8266,
PlatformFramework,
)
from esphome.core import CORE
CODEOWNERS = ["@esphome/core"]
@@ -133,16 +140,6 @@ ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = {
9: adc_channel_t.ADC_CHANNEL_8,
10: adc_channel_t.ADC_CHANNEL_9,
},
VARIANT_ESP32P4: {
16: adc_channel_t.ADC_CHANNEL_0,
17: adc_channel_t.ADC_CHANNEL_1,
18: adc_channel_t.ADC_CHANNEL_2,
19: adc_channel_t.ADC_CHANNEL_3,
20: adc_channel_t.ADC_CHANNEL_4,
21: adc_channel_t.ADC_CHANNEL_5,
22: adc_channel_t.ADC_CHANNEL_6,
23: adc_channel_t.ADC_CHANNEL_7,
},
}
# pin to adc2 channel mapping
@@ -201,14 +198,6 @@ ESP32_VARIANT_ADC2_PIN_TO_CHANNEL = {
19: adc_channel_t.ADC_CHANNEL_8,
20: adc_channel_t.ADC_CHANNEL_9,
},
VARIANT_ESP32P4: {
49: adc_channel_t.ADC_CHANNEL_0,
50: adc_channel_t.ADC_CHANNEL_1,
51: adc_channel_t.ADC_CHANNEL_2,
52: adc_channel_t.ADC_CHANNEL_3,
53: adc_channel_t.ADC_CHANNEL_4,
54: adc_channel_t.ADC_CHANNEL_5,
},
}
@@ -260,9 +249,21 @@ def validate_adc_pin(value):
{CONF_ANALOG: True, CONF_INPUT: True}, internal=True
)(value)
if CORE.is_nrf52:
return pins.gpio_pin_schema(
{CONF_ANALOG: True, CONF_INPUT: True}, internal=True
)(value)
raise NotImplementedError
FILTER_SOURCE_FILES = filter_source_files_from_platform(
{
"adc_sensor_esp32.cpp": {
PlatformFramework.ESP32_ARDUINO,
PlatformFramework.ESP32_IDF,
},
"adc_sensor_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
"adc_sensor_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO},
"adc_sensor_libretiny.cpp": {
PlatformFramework.BK72XX_ARDUINO,
PlatformFramework.RTL87XX_ARDUINO,
PlatformFramework.LN882X_ARDUINO,
},
}
)

View File

@@ -13,10 +13,6 @@
#include "hal/adc_types.h" // This defines ADC_CHANNEL_MAX
#endif // USE_ESP32
#ifdef USE_ZEPHYR
#include <zephyr/drivers/adc.h>
#endif
namespace esphome {
namespace adc {
@@ -42,15 +38,15 @@ enum class SamplingMode : uint8_t {
const LogString *sampling_mode_to_str(SamplingMode mode);
template<typename T> class Aggregator {
class Aggregator {
public:
Aggregator(SamplingMode mode);
void add_sample(T value);
T aggregate();
void add_sample(uint32_t value);
uint32_t aggregate();
protected:
T aggr_{0};
uint8_t samples_{0};
uint32_t aggr_{0};
uint32_t samples_{0};
SamplingMode mode_{SamplingMode::AVG};
};
@@ -73,11 +69,6 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
/// @return A float representing the setup priority.
float get_setup_priority() const override;
#ifdef USE_ZEPHYR
/// Set the ADC channel to be used by the ADC sensor.
/// @param channel Pointer to an adc_dt_spec structure representing the ADC channel.
void set_adc_channel(const adc_dt_spec *channel) { this->channel_ = channel; }
#endif
/// Set the GPIO pin to be used by the ADC sensor.
/// @param pin Pointer to an InternalGPIOPin representing the ADC input pin.
void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; }
@@ -145,8 +136,8 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
adc_oneshot_unit_handle_t adc_handle_{nullptr};
adc_cali_handle_t calibration_handle_{nullptr};
adc_atten_t attenuation_{ADC_ATTEN_DB_0};
adc_channel_t channel_{};
adc_unit_t adc_unit_{};
adc_channel_t channel_;
adc_unit_t adc_unit_;
struct SetupFlags {
uint8_t init_complete : 1;
uint8_t config_complete : 1;
@@ -160,10 +151,6 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
#ifdef USE_RP2040
bool is_temperature_{false};
#endif // USE_RP2040
#ifdef USE_ZEPHYR
const struct adc_dt_spec *channel_ = nullptr;
#endif
};
} // namespace adc

View File

@@ -18,15 +18,15 @@ const LogString *sampling_mode_to_str(SamplingMode mode) {
return LOG_STR("unknown");
}
template<typename T> Aggregator<T>::Aggregator(SamplingMode mode) {
Aggregator::Aggregator(SamplingMode mode) {
this->mode_ = mode;
// set to max uint if mode is "min"
if (mode == SamplingMode::MIN) {
this->aggr_ = std::numeric_limits<T>::max();
this->aggr_ = UINT32_MAX;
}
}
template<typename T> void Aggregator<T>::add_sample(T value) {
void Aggregator::add_sample(uint32_t value) {
this->samples_ += 1;
switch (this->mode_) {
@@ -47,7 +47,7 @@ template<typename T> void Aggregator<T>::add_sample(T value) {
}
}
template<typename T> T Aggregator<T>::aggregate() {
uint32_t Aggregator::aggregate() {
if (this->mode_ == SamplingMode::AVG) {
if (this->samples_ == 0) {
return this->aggr_;
@@ -59,12 +59,6 @@ template<typename T> T Aggregator<T>::aggregate() {
return this->aggr_;
}
#ifdef USE_ZEPHYR
template class Aggregator<int32_t>;
#else
template class Aggregator<uint32_t>;
#endif
void ADCSensor::update() {
float value_v = this->sample();
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", this->get_name().c_str(), value_v);

View File

@@ -72,9 +72,10 @@ void ADCSensor::setup() {
// Initialize ADC calibration
if (this->calibration_handle_ == nullptr) {
adc_cali_handle_t handle = nullptr;
esp_err_t err;
#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2
// RISC-V variants and S3 use curve fitting calibration
adc_cali_curve_fitting_config_t cali_config = {}; // Zero initialize first
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
@@ -152,7 +153,7 @@ float ADCSensor::sample() {
}
float ADCSensor::sample_fixed_attenuation_() {
auto aggr = Aggregator<uint32_t>(this->sampling_mode_);
auto aggr = Aggregator(this->sampling_mode_);
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
int raw;
@@ -186,7 +187,7 @@ float ADCSensor::sample_fixed_attenuation_() {
ESP_LOGW(TAG, "ADC calibration conversion failed with error %d, disabling calibration", err);
if (this->calibration_handle_ != nullptr) {
#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2
adc_cali_delete_scheme_curve_fitting(this->calibration_handle_);
#else // Other ESP32 variants use line fitting calibration
adc_cali_delete_scheme_line_fitting(this->calibration_handle_);
@@ -219,7 +220,7 @@ float ADCSensor::sample_autorange_() {
if (this->calibration_handle_ != nullptr) {
// Delete old calibration handle
#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2
adc_cali_delete_scheme_curve_fitting(this->calibration_handle_);
#else
adc_cali_delete_scheme_line_fitting(this->calibration_handle_);
@@ -231,7 +232,7 @@ float ADCSensor::sample_autorange_() {
adc_cali_handle_t handle = nullptr;
#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2
adc_cali_curve_fitting_config_t cali_config = {};
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
cali_config.chan = this->channel_;
@@ -241,8 +242,6 @@ float ADCSensor::sample_autorange_() {
cali_config.bitwidth = ADC_BITWIDTH_DEFAULT;
err = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
ESP_LOGVV(TAG, "Autorange atten=%d: Calibration handle creation %s (err=%d)", atten,
(err == ESP_OK) ? "SUCCESS" : "FAILED", err);
#else
adc_cali_line_fitting_config_t cali_config = {
.unit_id = this->adc_unit_,
@@ -253,20 +252,16 @@ float ADCSensor::sample_autorange_() {
#endif
};
err = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
ESP_LOGVV(TAG, "Autorange atten=%d: Calibration handle creation %s (err=%d)", atten,
(err == ESP_OK) ? "SUCCESS" : "FAILED", err);
#endif
int raw;
err = adc_oneshot_read(this->adc_handle_, this->channel_, &raw);
ESP_LOGVV(TAG, "Autorange atten=%d: Raw ADC read %s, value=%d (err=%d)", atten,
(err == ESP_OK) ? "SUCCESS" : "FAILED", raw, err);
if (err != ESP_OK) {
ESP_LOGW(TAG, "ADC read failed in autorange with error %d", err);
if (handle != nullptr) {
#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2
adc_cali_delete_scheme_curve_fitting(handle);
#else
adc_cali_delete_scheme_line_fitting(handle);
@@ -281,21 +276,18 @@ float ADCSensor::sample_autorange_() {
err = adc_cali_raw_to_voltage(handle, raw, &voltage_mv);
if (err == ESP_OK) {
voltage = voltage_mv / 1000.0f;
ESP_LOGVV(TAG, "Autorange atten=%d: CALIBRATED - raw=%d -> %dmV -> %.6fV", atten, raw, voltage_mv, voltage);
} else {
voltage = raw * 3.3f / 4095.0f;
ESP_LOGVV(TAG, "Autorange atten=%d: UNCALIBRATED FALLBACK - raw=%d -> %.6fV (3.3V ref)", atten, raw, voltage);
}
// Clean up calibration handle
#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4
USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32H2
adc_cali_delete_scheme_curve_fitting(handle);
#else
adc_cali_delete_scheme_line_fitting(handle);
#endif
} else {
voltage = raw * 3.3f / 4095.0f;
ESP_LOGVV(TAG, "Autorange atten=%d: NO CALIBRATION - raw=%d -> %.6fV (3.3V ref)", atten, raw, voltage);
}
return {raw, voltage};
@@ -333,32 +325,18 @@ float ADCSensor::sample_autorange_() {
}
const int adc_half = 2048;
const uint32_t c12 = std::min(raw12, adc_half);
const int32_t c6_signed = adc_half - std::abs(raw6 - adc_half);
const uint32_t c6 = (c6_signed > 0) ? c6_signed : 0; // Clamp to prevent underflow
const int32_t c2_signed = adc_half - std::abs(raw2 - adc_half);
const uint32_t c2 = (c2_signed > 0) ? c2_signed : 0; // Clamp to prevent underflow
const uint32_t c0 = std::min(4095 - raw0, adc_half);
const uint32_t csum = c12 + c6 + c2 + c0;
ESP_LOGVV(TAG, "Autorange summary:");
ESP_LOGVV(TAG, " Raw readings: 12db=%d, 6db=%d, 2.5db=%d, 0db=%d", raw12, raw6, raw2, raw0);
ESP_LOGVV(TAG, " Voltages: 12db=%.6f, 6db=%.6f, 2.5db=%.6f, 0db=%.6f", mv12, mv6, mv2, mv0);
ESP_LOGVV(TAG, " Coefficients: c12=%u, c6=%u, c2=%u, c0=%u, sum=%u", c12, c6, c2, c0, csum);
uint32_t c12 = std::min(raw12, adc_half);
uint32_t c6 = adc_half - std::abs(raw6 - adc_half);
uint32_t c2 = adc_half - std::abs(raw2 - adc_half);
uint32_t c0 = std::min(4095 - raw0, adc_half);
uint32_t csum = c12 + c6 + c2 + c0;
if (csum == 0) {
ESP_LOGE(TAG, "Invalid weight sum in autorange calculation");
return NAN;
}
const float final_result = (mv12 * c12 + mv6 * c6 + mv2 * c2 + mv0 * c0) / csum;
ESP_LOGV(TAG, "Autorange final: (%.6f*%u + %.6f*%u + %.6f*%u + %.6f*%u)/%u = %.6fV", mv12, c12, mv6, c6, mv2, c2, mv0,
c0, csum, final_result);
return final_result;
return (mv12 * c12 + mv6 * c6 + mv2 * c2 + mv0 * c0) / csum;
}
} // namespace adc

View File

@@ -37,7 +37,7 @@ void ADCSensor::dump_config() {
}
float ADCSensor::sample() {
auto aggr = Aggregator<uint32_t>(this->sampling_mode_);
auto aggr = Aggregator(this->sampling_mode_);
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
uint32_t raw = 0;

View File

@@ -30,7 +30,7 @@ void ADCSensor::dump_config() {
float ADCSensor::sample() {
uint32_t raw = 0;
auto aggr = Aggregator<uint32_t>(this->sampling_mode_);
auto aggr = Aggregator(this->sampling_mode_);
if (this->output_raw_) {
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {

View File

@@ -41,7 +41,7 @@ void ADCSensor::dump_config() {
float ADCSensor::sample() {
uint32_t raw = 0;
auto aggr = Aggregator<uint32_t>(this->sampling_mode_);
auto aggr = Aggregator(this->sampling_mode_);
if (this->is_temperature_) {
adc_set_temp_sensor_enabled(true);

View File

@@ -1,207 +0,0 @@
#include "adc_sensor.h"
#ifdef USE_ZEPHYR
#include "esphome/core/log.h"
#include "hal/nrf_saadc.h"
namespace esphome {
namespace adc {
static const char *const TAG = "adc.zephyr";
void ADCSensor::setup() {
if (!adc_is_ready_dt(this->channel_)) {
ESP_LOGE(TAG, "ADC controller device %s not ready", this->channel_->dev->name);
return;
}
auto err = adc_channel_setup_dt(this->channel_);
if (err < 0) {
ESP_LOGE(TAG, "Could not setup channel %s (%d)", this->channel_->dev->name, err);
return;
}
}
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
static const LogString *gain_to_str(enum adc_gain gain) {
switch (gain) {
case ADC_GAIN_1_6:
return LOG_STR("1/6");
case ADC_GAIN_1_5:
return LOG_STR("1/5");
case ADC_GAIN_1_4:
return LOG_STR("1/4");
case ADC_GAIN_1_3:
return LOG_STR("1/3");
case ADC_GAIN_2_5:
return LOG_STR("2/5");
case ADC_GAIN_1_2:
return LOG_STR("1/2");
case ADC_GAIN_2_3:
return LOG_STR("2/3");
case ADC_GAIN_4_5:
return LOG_STR("4/5");
case ADC_GAIN_1:
return LOG_STR("1");
case ADC_GAIN_2:
return LOG_STR("2");
case ADC_GAIN_3:
return LOG_STR("3");
case ADC_GAIN_4:
return LOG_STR("4");
case ADC_GAIN_6:
return LOG_STR("6");
case ADC_GAIN_8:
return LOG_STR("8");
case ADC_GAIN_12:
return LOG_STR("12");
case ADC_GAIN_16:
return LOG_STR("16");
case ADC_GAIN_24:
return LOG_STR("24");
case ADC_GAIN_32:
return LOG_STR("32");
case ADC_GAIN_64:
return LOG_STR("64");
case ADC_GAIN_128:
return LOG_STR("128");
}
return LOG_STR("undefined gain");
}
static const LogString *reference_to_str(enum adc_reference reference) {
switch (reference) {
case ADC_REF_VDD_1:
return LOG_STR("VDD");
case ADC_REF_VDD_1_2:
return LOG_STR("VDD/2");
case ADC_REF_VDD_1_3:
return LOG_STR("VDD/3");
case ADC_REF_VDD_1_4:
return LOG_STR("VDD/4");
case ADC_REF_INTERNAL:
return LOG_STR("INTERNAL");
case ADC_REF_EXTERNAL0:
return LOG_STR("External, input 0");
case ADC_REF_EXTERNAL1:
return LOG_STR("External, input 1");
}
return LOG_STR("undefined reference");
}
static const LogString *input_to_str(uint8_t input) {
switch (input) {
case NRF_SAADC_INPUT_AIN0:
return LOG_STR("AIN0");
case NRF_SAADC_INPUT_AIN1:
return LOG_STR("AIN1");
case NRF_SAADC_INPUT_AIN2:
return LOG_STR("AIN2");
case NRF_SAADC_INPUT_AIN3:
return LOG_STR("AIN3");
case NRF_SAADC_INPUT_AIN4:
return LOG_STR("AIN4");
case NRF_SAADC_INPUT_AIN5:
return LOG_STR("AIN5");
case NRF_SAADC_INPUT_AIN6:
return LOG_STR("AIN6");
case NRF_SAADC_INPUT_AIN7:
return LOG_STR("AIN7");
case NRF_SAADC_INPUT_VDD:
return LOG_STR("VDD");
case NRF_SAADC_INPUT_VDDHDIV5:
return LOG_STR("VDDHDIV5");
}
return LOG_STR("undefined input");
}
#endif // ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
void ADCSensor::dump_config() {
LOG_SENSOR("", "ADC Sensor", this);
LOG_PIN(" Pin: ", this->pin_);
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
ESP_LOGV(TAG,
" Name: %s\n"
" Channel: %d\n"
" vref_mv: %d\n"
" Resolution %d\n"
" Oversampling %d",
this->channel_->dev->name, this->channel_->channel_id, this->channel_->vref_mv, this->channel_->resolution,
this->channel_->oversampling);
ESP_LOGV(TAG,
" Gain: %s\n"
" reference: %s\n"
" acquisition_time: %d\n"
" differential %s",
LOG_STR_ARG(gain_to_str(this->channel_->channel_cfg.gain)),
LOG_STR_ARG(reference_to_str(this->channel_->channel_cfg.reference)),
this->channel_->channel_cfg.acquisition_time, YESNO(this->channel_->channel_cfg.differential));
if (this->channel_->channel_cfg.differential) {
ESP_LOGV(TAG,
" Positive: %s\n"
" Negative: %s",
LOG_STR_ARG(input_to_str(this->channel_->channel_cfg.input_positive)),
LOG_STR_ARG(input_to_str(this->channel_->channel_cfg.input_negative)));
} else {
ESP_LOGV(TAG, " Positive: %s", LOG_STR_ARG(input_to_str(this->channel_->channel_cfg.input_positive)));
}
#endif
LOG_UPDATE_INTERVAL(this);
}
float ADCSensor::sample() {
auto aggr = Aggregator<int32_t>(this->sampling_mode_);
int err;
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
int16_t buf = 0;
struct adc_sequence sequence = {
.buffer = &buf,
/* buffer size in bytes, not number of samples */
.buffer_size = sizeof(buf),
};
int32_t val_raw;
err = adc_sequence_init_dt(this->channel_, &sequence);
if (err < 0) {
ESP_LOGE(TAG, "Could sequence init %s (%d)", this->channel_->dev->name, err);
return 0.0;
}
err = adc_read(this->channel_->dev, &sequence);
if (err < 0) {
ESP_LOGE(TAG, "Could not read %s (%d)", this->channel_->dev->name, err);
return 0.0;
}
val_raw = (int32_t) buf;
if (!this->channel_->channel_cfg.differential) {
// https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/0ed4d9ffc674ae407be7cacf5696a02f5e789861/cores/nRF5/wiring_analog_nRF52.c#L222
if (val_raw < 0) {
val_raw = 0;
}
}
aggr.add_sample(val_raw);
}
int32_t val_mv = aggr.aggregate();
if (this->output_raw_) {
return val_mv;
}
err = adc_raw_to_millivolts_dt(this->channel_, &val_mv);
/* conversion to mV may not be supported, skip if not */
if (err < 0) {
ESP_LOGE(TAG, "Value in mV not available %s (%d)", this->channel_->dev->name, err);
return 0.0;
}
return val_mv / 1000.0f;
}
} // namespace adc
} // namespace esphome
#endif

View File

@@ -3,13 +3,6 @@ import logging
import esphome.codegen as cg
from esphome.components import sensor, voltage_sampler
from esphome.components.esp32 import get_esp32_variant
from esphome.components.nrf52.const import AIN_TO_GPIO, EXTRA_ADC
from esphome.components.zephyr import (
zephyr_add_overlay,
zephyr_add_prj_conf,
zephyr_add_user,
)
from esphome.config_helpers import filter_source_files_from_platform
import esphome.config_validation as cv
from esphome.const import (
CONF_ATTENUATION,
@@ -18,10 +11,8 @@ from esphome.const import (
CONF_PIN,
CONF_RAW,
DEVICE_CLASS_VOLTAGE,
PLATFORM_NRF52,
STATE_CLASS_MEASUREMENT,
UNIT_VOLT,
PlatformFramework,
)
from esphome.core import CORE
@@ -69,10 +60,6 @@ ADCSensor = adc_ns.class_(
"ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler
)
CONF_NRF_SAADC = "nrf_saadc"
adc_dt_spec = cg.global_ns.class_("adc_dt_spec")
CONFIG_SCHEMA = cv.All(
sensor.sensor_schema(
ADCSensor,
@@ -88,7 +75,6 @@ CONFIG_SCHEMA = cv.All(
cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All(
cv.only_on_esp32, _attenuation
),
cv.OnlyWith(CONF_NRF_SAADC, PLATFORM_NRF52): cv.declare_id(adc_dt_spec),
cv.Optional(CONF_SAMPLES, default=1): cv.int_range(min=1, max=255),
cv.Optional(CONF_SAMPLING_MODE, default="avg"): _sampling_mode,
}
@@ -97,8 +83,6 @@ CONFIG_SCHEMA = cv.All(
validate_config,
)
CONF_ADC_CHANNEL_ID = "adc_channel_id"
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
@@ -109,7 +93,7 @@ async def to_code(config):
cg.add_define("USE_ADC_SENSOR_VCC")
elif config[CONF_PIN] == "TEMPERATURE":
cg.add(var.set_is_temperature())
elif not CORE.is_nrf52 or config[CONF_PIN][CONF_NUMBER] not in EXTRA_ADC:
else:
pin = await cg.gpio_pin_expression(config[CONF_PIN])
cg.add(var.set_pin(pin))
@@ -138,59 +122,3 @@ async def to_code(config):
):
chan = ESP32_VARIANT_ADC2_PIN_TO_CHANNEL[variant][pin_num]
cg.add(var.set_channel(adc_unit_t.ADC_UNIT_2, chan))
elif CORE.is_nrf52:
CORE.data.setdefault(CONF_ADC_CHANNEL_ID, 0)
channel_id = CORE.data[CONF_ADC_CHANNEL_ID]
CORE.data[CONF_ADC_CHANNEL_ID] = channel_id + 1
zephyr_add_prj_conf("ADC", True)
nrf_saadc = config[CONF_NRF_SAADC]
rhs = cg.RawExpression(
f"ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), {channel_id})"
)
adc = cg.new_Pvariable(nrf_saadc, rhs)
cg.add(var.set_adc_channel(adc))
gain = "ADC_GAIN_1_6"
pin_number = config[CONF_PIN][CONF_NUMBER]
if pin_number == "VDDHDIV5":
gain = "ADC_GAIN_1_2"
if isinstance(pin_number, int):
GPIO_TO_AIN = {v: k for k, v in AIN_TO_GPIO.items()}
pin_number = GPIO_TO_AIN[pin_number]
zephyr_add_user("io-channels", f"<&adc {channel_id}>")
zephyr_add_overlay(
f"""
&adc {{
#address-cells = <1>;
#size-cells = <0>;
channel@{channel_id} {{
reg = <{channel_id}>;
zephyr,gain = "{gain}";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_{pin_number}>;
zephyr,resolution = <14>;
zephyr,oversampling = <8>;
}};
}};
"""
)
FILTER_SOURCE_FILES = filter_source_files_from_platform(
{
"adc_sensor_esp32.cpp": {
PlatformFramework.ESP32_ARDUINO,
PlatformFramework.ESP32_IDF,
},
"adc_sensor_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
"adc_sensor_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO},
"adc_sensor_libretiny.cpp": {
PlatformFramework.BK72XX_ARDUINO,
PlatformFramework.RTL87XX_ARDUINO,
PlatformFramework.LN882X_ARDUINO,
},
"adc_sensor_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR},
}
)

View File

@@ -36,7 +36,6 @@ from esphome.const import (
UNIT_WATT,
UNIT_WATT_HOURS,
)
from esphome.types import ConfigType
DEPENDENCIES = ["i2c"]
@@ -52,20 +51,6 @@ CONF_POWER_GAIN = "power_gain"
CONF_NEUTRAL = "neutral"
# Tuple of power channel phases
POWER_PHASES = (CONF_PHASE_A, CONF_PHASE_B, CONF_PHASE_C)
# Tuple of sensor types that can be configured for power channels
POWER_SENSOR_TYPES = (
CONF_CURRENT,
CONF_VOLTAGE,
CONF_ACTIVE_POWER,
CONF_APPARENT_POWER,
CONF_POWER_FACTOR,
CONF_FORWARD_ACTIVE_ENERGY,
CONF_REVERSE_ACTIVE_ENERGY,
)
NEUTRAL_CHANNEL_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(NeutralChannel),
@@ -165,64 +150,7 @@ POWER_CHANNEL_SCHEMA = cv.Schema(
}
)
def prefix_sensor_name(
sensor_conf: ConfigType,
channel_name: str,
channel_config: ConfigType,
sensor_type: str,
) -> None:
"""Helper to prefix sensor name with channel name.
Args:
sensor_conf: The sensor configuration (dict or string)
channel_name: The channel name to prefix with
channel_config: The channel configuration to update
sensor_type: The sensor type key in the channel config
"""
if isinstance(sensor_conf, dict) and CONF_NAME in sensor_conf:
sensor_name = sensor_conf[CONF_NAME]
if sensor_name and not sensor_name.startswith(channel_name):
sensor_conf[CONF_NAME] = f"{channel_name} {sensor_name}"
elif isinstance(sensor_conf, str):
# Simple value case - convert to dict with prefixed name
channel_config[sensor_type] = {CONF_NAME: f"{channel_name} {sensor_conf}"}
def process_channel_sensors(
config: ConfigType, channel_key: str, sensor_types: tuple
) -> None:
"""Process sensors for a channel and prefix their names.
Args:
config: The main configuration
channel_key: The channel key (e.g., CONF_PHASE_A, CONF_NEUTRAL)
sensor_types: Tuple of sensor types to process for this channel
"""
if not (channel_config := config.get(channel_key)) or not (
channel_name := channel_config.get(CONF_NAME)
):
return
for sensor_type in sensor_types:
if sensor_conf := channel_config.get(sensor_type):
prefix_sensor_name(sensor_conf, channel_name, channel_config, sensor_type)
def preprocess_channels(config: ConfigType) -> ConfigType:
"""Preprocess channel configurations to add channel name prefix to sensor names."""
# Process power channels
for channel in POWER_PHASES:
process_channel_sensors(config, channel, POWER_SENSOR_TYPES)
# Process neutral channel
process_channel_sensors(config, CONF_NEUTRAL, (CONF_CURRENT,))
return config
CONFIG_SCHEMA = cv.All(
preprocess_channels,
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(ADE7880),
@@ -239,7 +167,7 @@ CONFIG_SCHEMA = cv.All(
}
)
.extend(cv.polling_component_schema("60s"))
.extend(i2c.i2c_device_schema(0x38)),
.extend(i2c.i2c_device_schema(0x38))
)
@@ -260,7 +188,15 @@ async def neutral_channel(config):
async def power_channel(config):
var = cg.new_Pvariable(config[CONF_ID])
for sensor_type in POWER_SENSOR_TYPES:
for sensor_type in [
CONF_CURRENT,
CONF_VOLTAGE,
CONF_ACTIVE_POWER,
CONF_APPARENT_POWER,
CONF_POWER_FACTOR,
CONF_FORWARD_ACTIVE_ENERGY,
CONF_REVERSE_ACTIVE_ENERGY,
]:
if conf := config.get(sensor_type):
sens = await sensor.new_sensor(conf)
cg.add(getattr(var, f"set_{sensor_type}")(sens))
@@ -280,6 +216,44 @@ async def power_channel(config):
return var
def final_validate(config):
for channel in [CONF_PHASE_A, CONF_PHASE_B, CONF_PHASE_C]:
if channel := config.get(channel):
channel_name = channel.get(CONF_NAME)
for sensor_type in [
CONF_CURRENT,
CONF_VOLTAGE,
CONF_ACTIVE_POWER,
CONF_APPARENT_POWER,
CONF_POWER_FACTOR,
CONF_FORWARD_ACTIVE_ENERGY,
CONF_REVERSE_ACTIVE_ENERGY,
]:
if conf := channel.get(sensor_type):
sensor_name = conf.get(CONF_NAME)
if (
sensor_name
and channel_name
and not sensor_name.startswith(channel_name)
):
conf[CONF_NAME] = f"{channel_name} {sensor_name}"
if channel := config.get(CONF_NEUTRAL):
channel_name = channel.get(CONF_NAME)
if conf := channel.get(CONF_CURRENT):
sensor_name = conf.get(CONF_NAME)
if (
sensor_name
and channel_name
and not sensor_name.startswith(channel_name)
):
conf[CONF_NAME] = f"{channel_name} {sensor_name}"
FINAL_VALIDATE_SCHEMA = final_validate
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)

View File

@@ -89,7 +89,7 @@ void AGS10Component::dump_config() {
bool AGS10Component::new_i2c_address(uint8_t newaddress) {
uint8_t rev_newaddress = ~newaddress;
std::array<uint8_t, 5> data{newaddress, rev_newaddress, newaddress, rev_newaddress, 0};
data[4] = crc8(data.data(), 4, 0xFF, 0x31, true);
data[4] = calc_crc8_(data, 4);
if (!this->write_bytes(REG_ADDRESS, data)) {
this->error_code_ = COMMUNICATION_FAILED;
this->status_set_warning();
@@ -109,7 +109,7 @@ bool AGS10Component::set_zero_point_with_current_resistance() { return this->set
bool AGS10Component::set_zero_point_with(uint16_t value) {
std::array<uint8_t, 5> data{0x00, 0x0C, (uint8_t) ((value >> 8) & 0xFF), (uint8_t) (value & 0xFF), 0};
data[4] = crc8(data.data(), 4, 0xFF, 0x31, true);
data[4] = calc_crc8_(data, 4);
if (!this->write_bytes(REG_CALIBRATION, data)) {
this->error_code_ = COMMUNICATION_FAILED;
this->status_set_warning();
@@ -184,7 +184,7 @@ template<size_t N> optional<std::array<uint8_t, N>> AGS10Component::read_and_che
auto res = *data;
auto crc_byte = res[len];
if (crc_byte != crc8(res.data(), len, 0xFF, 0x31, true)) {
if (crc_byte != calc_crc8_(res, len)) {
this->error_code_ = CRC_CHECK_FAILED;
ESP_LOGE(TAG, "Reading AGS10 version failed: crc error!");
return optional<std::array<uint8_t, N>>();
@@ -192,5 +192,20 @@ template<size_t N> optional<std::array<uint8_t, N>> AGS10Component::read_and_che
return data;
}
template<size_t N> uint8_t AGS10Component::calc_crc8_(std::array<uint8_t, N> dat, uint8_t num) {
uint8_t i, byte1, crc = 0xFF;
for (byte1 = 0; byte1 < num; byte1++) {
crc ^= (dat[byte1]);
for (i = 0; i < 8; i++) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x31;
} else {
crc = (crc << 1);
}
}
}
return crc;
}
} // namespace ags10
} // namespace esphome

View File

@@ -1,9 +1,9 @@
#pragma once
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/i2c/i2c.h"
namespace esphome {
namespace ags10 {
@@ -99,6 +99,16 @@ class AGS10Component : public PollingComponent, public i2c::I2CDevice {
* Read, checks and returns data from the sensor.
*/
template<size_t N> optional<std::array<uint8_t, N>> read_and_check_(uint8_t a_register);
/**
* Calculates CRC8 value.
*
* CRC8 calculation, initial value: 0xFF, polynomial: 0x31 (x8+ x5+ x4+1)
*
* @param[in] dat the data buffer
* @param num number of bytes in the buffer
*/
template<size_t N> uint8_t calc_crc8_(std::array<uint8_t, N> dat, uint8_t num);
};
template<typename... Ts> class AGS10NewI2cAddressAction : public Action<Ts...>, public Parented<AGS10Component> {

View File

@@ -96,7 +96,7 @@ void AHT10Component::read_data_() {
ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_));
}
if (this->read(data, 6) != i2c::ERROR_OK) {
this->status_set_warning(LOG_STR("Read failed, will retry"));
this->status_set_warning("Read failed, will retry");
this->restart_read_();
return;
}
@@ -113,7 +113,7 @@ void AHT10Component::read_data_() {
} else {
ESP_LOGD(TAG, "Invalid humidity, retrying");
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
}
this->restart_read_();
return;
@@ -144,7 +144,7 @@ void AHT10Component::update() {
return;
this->start_time_ = millis();
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
return;
}
this->restart_read_();

View File

@@ -18,6 +18,6 @@ CONFIG_SCHEMA = cv.Schema(
).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
async def to_code(config):
def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await esp32_ble_tracker.register_ble_device(var, config)
yield esp32_ble_tracker.register_ble_device(var, config)

View File

@@ -13,7 +13,7 @@ from esphome.const import (
CONF_TRIGGER_ID,
CONF_WEB_SERVER,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core import CORE, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
from esphome.cpp_generator import MockObjClass
@@ -301,7 +301,8 @@ async def alarm_action_disarm_to_code(config, action_id, template_arg, args):
)
async def alarm_action_pending_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
var = cg.new_Pvariable(action_id, template_arg, paren)
return var
@automation.register_action(
@@ -309,7 +310,8 @@ async def alarm_action_pending_to_code(config, action_id, template_arg, args):
)
async def alarm_action_trigger_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
var = cg.new_Pvariable(action_id, template_arg, paren)
return var
@automation.register_action(
@@ -317,7 +319,8 @@ async def alarm_action_trigger_to_code(config, action_id, template_arg, args):
)
async def alarm_action_chime_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
var = cg.new_Pvariable(action_id, template_arg, paren)
return var
@automation.register_action(
@@ -330,7 +333,8 @@ async def alarm_action_chime_to_code(config, action_id, template_arg, args):
)
async def alarm_action_ready_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
var = cg.new_Pvariable(action_id, template_arg, paren)
return var
@automation.register_condition(
@@ -345,6 +349,7 @@ async def alarm_control_panel_is_armed_to_code(
return cg.new_Pvariable(condition_id, template_arg, paren)
@coroutine_with_priority(CoroPriority.CORE)
@coroutine_with_priority(100.0)
async def to_code(config):
cg.add_global(alarm_control_panel_ns.using)
cg.add_define("USE_ALARM_CONTROL_PANEL")

View File

@@ -29,6 +29,22 @@ namespace am2315c {
static const char *const TAG = "am2315c";
uint8_t AM2315C::crc8_(uint8_t *data, uint8_t len) {
uint8_t crc = 0xFF;
while (len--) {
crc ^= *data++;
for (uint8_t i = 0; i < 8; i++) {
if (crc & 0x80) {
crc <<= 1;
crc ^= 0x31;
} else {
crc <<= 1;
}
}
}
return crc;
}
bool AM2315C::reset_register_(uint8_t reg) {
// code based on demo code sent by www.aosong.com
// no further documentation.
@@ -70,7 +86,7 @@ bool AM2315C::convert_(uint8_t *data, float &humidity, float &temperature) {
humidity = raw * 9.5367431640625e-5;
raw = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5];
temperature = raw * 1.9073486328125e-4 - 50;
return crc8(data, 6, 0xFF, 0x31, true) == data[6];
return this->crc8_(data, 6) == data[6];
}
void AM2315C::setup() {

View File

@@ -21,9 +21,9 @@
// SOFTWARE.
#pragma once
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/i2c/i2c.h"
namespace esphome {
namespace am2315c {
@@ -39,6 +39,7 @@ class AM2315C : public PollingComponent, public i2c::I2CDevice {
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
protected:
uint8_t crc8_(uint8_t *data, uint8_t len);
bool convert_(uint8_t *data, float &humidity, float &temperature);
bool reset_register_(uint8_t reg);

View File

@@ -34,20 +34,17 @@ SetFrameAction = animation_ns.class_(
"AnimationSetFrameAction", automation.Action, cg.Parented.template(Animation_)
)
CONFIG_SCHEMA = cv.All(
espImage.IMAGE_SCHEMA.extend(
{
cv.Required(CONF_ID): cv.declare_id(Animation_),
cv.Optional(CONF_LOOP): cv.All(
{
cv.Optional(CONF_START_FRAME, default=0): cv.positive_int,
cv.Optional(CONF_END_FRAME): cv.positive_int,
cv.Optional(CONF_REPEAT): cv.positive_int,
}
),
},
),
espImage.validate_settings,
CONFIG_SCHEMA = espImage.IMAGE_SCHEMA.extend(
{
cv.Required(CONF_ID): cv.declare_id(Animation_),
cv.Optional(CONF_LOOP): cv.All(
{
cv.Optional(CONF_START_FRAME, default=0): cv.positive_int,
cv.Optional(CONF_END_FRAME): cv.positive_int,
cv.Optional(CONF_REPEAT): cv.positive_int,
}
),
},
)

View File

@@ -24,12 +24,12 @@ from esphome.const import (
CONF_TRIGGER_ID,
CONF_VARIABLES,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core import CORE, coroutine_with_priority
DOMAIN = "api"
DEPENDENCIES = ["network"]
AUTO_LOAD = ["socket"]
CODEOWNERS = ["@esphome/core"]
CODEOWNERS = ["@OttoWinter"]
api_ns = cg.esphome_ns.namespace("api")
APIServer = api_ns.class_("APIServer", cg.Component, cg.Controller)
@@ -122,6 +122,8 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_CUSTOM_SERVICES, default=False): cv.boolean,
cv.Optional(CONF_HOMEASSISTANT_SERVICES, default=False): cv.boolean,
cv.Optional(CONF_HOMEASSISTANT_STATES, default=False): cv.boolean,
cv.Optional(CONF_HOMEASSISTANT_SERVICES, default=False): cv.boolean,
cv.Optional(CONF_HOMEASSISTANT_STATES, default=False): cv.boolean,
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation(
single=True
),
@@ -134,7 +136,7 @@ CONFIG_SCHEMA = cv.All(
)
@coroutine_with_priority(CoroPriority.WEB)
@coroutine_with_priority(40.0)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
@@ -321,7 +323,6 @@ HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA = cv.maybe_simple_value(
HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA,
)
async def homeassistant_tag_scanned_to_code(config, action_id, template_arg, args):
cg.add_define("USE_API_HOMEASSISTANT_SERVICES")
serv = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, serv, True)
cg.add(var.set_service("esphome.tag_scanned"))

View File

@@ -27,6 +27,9 @@ service APIConnection {
rpc subscribe_logs (SubscribeLogsRequest) returns (void) {}
rpc subscribe_homeassistant_services (SubscribeHomeassistantServicesRequest) returns (void) {}
rpc subscribe_home_assistant_states (SubscribeHomeAssistantStatesRequest) returns (void) {}
rpc get_time (GetTimeRequest) returns (GetTimeResponse) {
option (needs_authentication) = false;
}
rpc execute_service (ExecuteServiceRequest) returns (void) {}
rpc noise_encryption_set_key (NoiseEncryptionSetKeyRequest) returns (NoiseEncryptionSetKeyResponse) {}
@@ -133,7 +136,6 @@ message ConnectRequest {
option (id) = 3;
option (source) = SOURCE_CLIENT;
option (no_delay) = true;
option (ifdef) = "USE_API_PASSWORD";
// The password to log in with
string password = 1;
@@ -145,7 +147,6 @@ message ConnectResponse {
option (id) = 4;
option (source) = SOURCE_SERVER;
option (no_delay) = true;
option (ifdef) = "USE_API_PASSWORD";
bool invalid_password = 1;
}
@@ -249,8 +250,8 @@ message DeviceInfoResponse {
// Supports receiving and saving api encryption key
bool api_encryption_supported = 19 [(field_ifdef) = "USE_API_NOISE"];
repeated DeviceInfo devices = 20 [(field_ifdef) = "USE_DEVICES", (fixed_array_size_define) = "ESPHOME_DEVICE_COUNT"];
repeated AreaInfo areas = 21 [(field_ifdef) = "USE_AREAS", (fixed_array_size_define) = "ESPHOME_AREA_COUNT"];
repeated DeviceInfo devices = 20 [(field_ifdef) = "USE_DEVICES"];
repeated AreaInfo areas = 21 [(field_ifdef) = "USE_AREAS"];
// Top-level area info to phase out suggested_area
AreaInfo area = 22 [(field_ifdef) = "USE_AREAS"];
@@ -418,7 +419,7 @@ message ListEntitiesFanResponse {
bool disabled_by_default = 9;
string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON"];
EntityCategory entity_category = 11;
repeated string supported_preset_modes = 12 [(container_pointer) = "std::set"];
repeated string supported_preset_modes = 12;
uint32 device_id = 13 [(field_ifdef) = "USE_DEVICES"];
}
// Deprecated in API version 1.6 - only used in deprecated fields
@@ -499,7 +500,7 @@ message ListEntitiesLightResponse {
string name = 3;
reserved 4; // Deprecated: was string unique_id
repeated ColorMode supported_color_modes = 12 [(container_pointer) = "std::set<light::ColorMode>"];
repeated ColorMode supported_color_modes = 12;
// next four supports_* are for legacy clients, newer clients should use color modes
// Deprecated in API version 1.6
bool legacy_supports_brightness = 5 [deprecated=true];
@@ -808,16 +809,15 @@ message HomeAssistantStateResponse {
// ==================== IMPORT TIME ====================
message GetTimeRequest {
option (id) = 36;
option (source) = SOURCE_SERVER;
option (source) = SOURCE_BOTH;
}
message GetTimeResponse {
option (id) = 37;
option (source) = SOURCE_CLIENT;
option (source) = SOURCE_BOTH;
option (no_delay) = true;
fixed32 epoch_seconds = 1;
string timezone = 2;
}
// ==================== USER-DEFINES SERVICES ====================
@@ -966,7 +966,7 @@ message ListEntitiesClimateResponse {
bool supports_current_temperature = 5;
bool supports_two_point_target_temperature = 6;
repeated ClimateMode supported_modes = 7 [(container_pointer) = "std::set<climate::ClimateMode>"];
repeated ClimateMode supported_modes = 7;
float visual_min_temperature = 8;
float visual_max_temperature = 9;
float visual_target_temperature_step = 10;
@@ -975,11 +975,11 @@ message ListEntitiesClimateResponse {
// Deprecated in API version 1.5
bool legacy_supports_away = 11 [deprecated=true];
bool supports_action = 12;
repeated ClimateFanMode supported_fan_modes = 13 [(container_pointer) = "std::set<climate::ClimateFanMode>"];
repeated ClimateSwingMode supported_swing_modes = 14 [(container_pointer) = "std::set<climate::ClimateSwingMode>"];
repeated string supported_custom_fan_modes = 15 [(container_pointer) = "std::set"];
repeated ClimatePreset supported_presets = 16 [(container_pointer) = "std::set<climate::ClimatePreset>"];
repeated string supported_custom_presets = 17 [(container_pointer) = "std::set"];
repeated ClimateFanMode supported_fan_modes = 13;
repeated ClimateSwingMode supported_swing_modes = 14;
repeated string supported_custom_fan_modes = 15;
repeated ClimatePreset supported_presets = 16;
repeated string supported_custom_presets = 17;
bool disabled_by_default = 18;
string icon = 19 [(field_ifdef) = "USE_ENTITY_ICON"];
EntityCategory entity_category = 20;
@@ -1119,7 +1119,7 @@ message ListEntitiesSelectResponse {
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"];
repeated string options = 6 [(container_pointer) = "std::vector"];
repeated string options = 6;
bool disabled_by_default = 7;
EntityCategory entity_category = 8;
uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"];
@@ -1297,9 +1297,6 @@ enum MediaPlayerState {
MEDIA_PLAYER_STATE_IDLE = 1;
MEDIA_PLAYER_STATE_PLAYING = 2;
MEDIA_PLAYER_STATE_PAUSED = 3;
MEDIA_PLAYER_STATE_ANNOUNCING = 4;
MEDIA_PLAYER_STATE_OFF = 5;
MEDIA_PLAYER_STATE_ON = 6;
}
enum MediaPlayerCommand {
MEDIA_PLAYER_COMMAND_PLAY = 0;
@@ -1307,15 +1304,6 @@ enum MediaPlayerCommand {
MEDIA_PLAYER_COMMAND_STOP = 2;
MEDIA_PLAYER_COMMAND_MUTE = 3;
MEDIA_PLAYER_COMMAND_UNMUTE = 4;
MEDIA_PLAYER_COMMAND_TOGGLE = 5;
MEDIA_PLAYER_COMMAND_VOLUME_UP = 6;
MEDIA_PLAYER_COMMAND_VOLUME_DOWN = 7;
MEDIA_PLAYER_COMMAND_ENQUEUE = 8;
MEDIA_PLAYER_COMMAND_REPEAT_ONE = 9;
MEDIA_PLAYER_COMMAND_REPEAT_OFF = 10;
MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST = 11;
MEDIA_PLAYER_COMMAND_TURN_ON = 12;
MEDIA_PLAYER_COMMAND_TURN_OFF = 13;
}
enum MediaPlayerFormatPurpose {
MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT = 0;
@@ -1350,8 +1338,6 @@ message ListEntitiesMediaPlayerResponse {
repeated MediaPlayerSupportedFormat supported_formats = 9;
uint32 device_id = 10 [(field_ifdef) = "USE_DEVICES"];
uint32 feature_flags = 11;
}
message MediaPlayerStateResponse {
option (id) = 64;
@@ -1438,11 +1424,11 @@ message BluetoothLERawAdvertisementsResponse {
option (ifdef) = "USE_BLUETOOTH_PROXY";
option (no_delay) = true;
repeated BluetoothLERawAdvertisement advertisements = 1 [(fixed_array_with_length_define) = "BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE"];
repeated BluetoothLERawAdvertisement advertisements = 1;
}
enum BluetoothDeviceRequestType {
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT = 0 [deprecated = true]; // V1 removed, use V3 variants
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT = 0;
BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1;
BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2;
BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3;
@@ -1482,39 +1468,21 @@ message BluetoothGATTGetServicesRequest {
}
message BluetoothGATTDescriptor {
repeated uint64 uuid = 1 [(fixed_array_size) = 2, (fixed_array_skip_zero) = true];
repeated uint64 uuid = 1 [(fixed_array_size) = 2];
uint32 handle = 2;
// New field for efficient UUID (v1.12+)
// Only one of uuid or short_uuid will be set.
// short_uuid is used for both 16-bit and 32-bit UUIDs with v1.12+ clients.
// 128-bit UUIDs always use the uuid field for backwards compatibility.
uint32 short_uuid = 3; // 16-bit or 32-bit UUID
}
message BluetoothGATTCharacteristic {
repeated uint64 uuid = 1 [(fixed_array_size) = 2, (fixed_array_skip_zero) = true];
repeated uint64 uuid = 1 [(fixed_array_size) = 2];
uint32 handle = 2;
uint32 properties = 3;
repeated BluetoothGATTDescriptor descriptors = 4;
// New field for efficient UUID (v1.12+)
// Only one of uuid or short_uuid will be set.
// short_uuid is used for both 16-bit and 32-bit UUIDs with v1.12+ clients.
// 128-bit UUIDs always use the uuid field for backwards compatibility.
uint32 short_uuid = 5; // 16-bit or 32-bit UUID
}
message BluetoothGATTService {
repeated uint64 uuid = 1 [(fixed_array_size) = 2, (fixed_array_skip_zero) = true];
repeated uint64 uuid = 1 [(fixed_array_size) = 2];
uint32 handle = 2;
repeated BluetoothGATTCharacteristic characteristics = 3;
// New field for efficient UUID (v1.12+)
// Only one of uuid or short_uuid will be set.
// short_uuid is used for both 16-bit and 32-bit UUIDs with v1.12+ clients.
// 128-bit UUIDs always use the uuid field for backwards compatibility.
uint32 short_uuid = 4; // 16-bit or 32-bit UUID
}
message BluetoothGATTGetServicesResponse {
@@ -1523,7 +1491,7 @@ message BluetoothGATTGetServicesResponse {
option (ifdef) = "USE_BLUETOOTH_PROXY";
uint64 address = 1;
repeated BluetoothGATTService services = 2;
repeated BluetoothGATTService services = 2 [(fixed_array_size) = 1];
}
message BluetoothGATTGetServicesDoneResponse {
@@ -1621,10 +1589,7 @@ message BluetoothConnectionsFreeResponse {
uint32 free = 1;
uint32 limit = 2;
repeated uint64 allocated = 3 [
(fixed_array_size_define) = "BLUETOOTH_PROXY_MAX_CONNECTIONS",
(fixed_array_skip_zero) = true
];
repeated uint64 allocated = 3;
}
message BluetoothGATTErrorResponse {
@@ -1712,7 +1677,6 @@ message BluetoothScannerStateResponse {
BluetoothScannerState state = 1;
BluetoothScannerMode mode = 2;
BluetoothScannerMode configured_mode = 3;
}
message BluetoothScannerSetModeRequest {
@@ -1870,7 +1834,7 @@ message VoiceAssistantConfigurationResponse {
option (ifdef) = "USE_VOICE_ASSISTANT";
repeated VoiceAssistantWakeWord available_wake_words = 1;
repeated string active_wake_words = 2 [(container_pointer) = "std::vector"];
repeated string active_wake_words = 2;
uint32 max_active_wake_words = 3;
}

View File

@@ -42,8 +42,6 @@ static constexpr uint8_t MAX_PING_RETRIES = 60;
static constexpr uint16_t PING_RETRY_INTERVAL = 1000;
static constexpr uint32_t KEEPALIVE_DISCONNECT_TIMEOUT = (KEEPALIVE_TIMEOUT_MS * 5) / 2;
static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION);
static const char *const TAG = "api.connection";
#ifdef USE_CAMERA
static const int CAMERA_STOP_STREAM = 5000;
@@ -114,7 +112,8 @@ void APIConnection::start() {
APIError err = this->helper_->init();
if (err != APIError::OK) {
on_fatal_error();
this->log_warning_(LOG_STR("Helper init failed"), err);
ESP_LOGW(TAG, "%s: Helper init failed %s errno=%d", this->get_client_combined_info().c_str(), api_error_to_str(err),
errno);
return;
}
this->client_info_.peername = helper_->getpeername();
@@ -145,7 +144,8 @@ void APIConnection::loop() {
APIError err = this->helper_->loop();
if (err != APIError::OK) {
on_fatal_error();
this->log_socket_operation_failed_(err);
ESP_LOGW(TAG, "%s: Socket operation failed %s errno=%d", this->get_client_combined_info().c_str(),
api_error_to_str(err), errno);
return;
}
@@ -161,7 +161,8 @@ void APIConnection::loop() {
break;
} else if (err != APIError::OK) {
on_fatal_error();
this->log_warning_(LOG_STR("Reading failed"), err);
ESP_LOGW(TAG, "%s: Reading failed %s errno=%d", this->get_client_combined_info().c_str(), api_error_to_str(err),
errno);
return;
} else {
this->last_traffic_ = now;
@@ -291,26 +292,16 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess
return 0; // Doesn't fit
}
// Allocate buffer space - pass payload size, allocation functions add header/footer space
ProtoWriteBuffer buffer = is_single ? conn->allocate_single_message_buffer(calculated_size)
: conn->allocate_batch_message_buffer(calculated_size);
// Get buffer size after allocation (which includes header padding)
std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref();
if (is_single || conn->flags_.batch_first_message) {
// Single message or first batch message
conn->prepare_first_message_buffer(shared_buf, header_padding, total_calculated_size);
if (conn->flags_.batch_first_message) {
conn->flags_.batch_first_message = false;
}
} else {
// Batch message second or later
// Add padding for previous message footer + this message header
size_t current_size = shared_buf.size();
shared_buf.reserve(current_size + total_calculated_size);
shared_buf.resize(current_size + footer_size + header_padding);
}
size_t size_before_encode = shared_buf.size();
// Encode directly into buffer
size_t size_before_encode = shared_buf.size();
msg.encode({&shared_buf});
msg.encode(buffer);
// Calculate actual encoded size (not including header that was already added)
size_t actual_payload_size = shared_buf.size() - size_before_encode;
@@ -422,7 +413,8 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con
msg.supports_speed = traits.supports_speed();
msg.supports_direction = traits.supports_direction();
msg.supported_speed_count = traits.supported_speed_count();
msg.supported_preset_modes = &traits.supported_preset_modes_for_api_();
for (auto const &preset : traits.supported_preset_modes())
msg.supported_preset_modes.push_back(preset);
return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
}
void APIConnection::fan_command(const FanCommandRequest &msg) {
@@ -467,7 +459,9 @@ uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *
resp.cold_white = values.get_cold_white();
resp.warm_white = values.get_warm_white();
if (light->supports_effects()) {
resp.set_effect(light->get_effect_name_ref());
// get_effect_name() returns temporary std::string - must store it
std::string effect_name = light->get_effect_name();
resp.set_effect(StringRef(effect_name));
}
return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
}
@@ -476,7 +470,8 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c
auto *light = static_cast<light::LightState *>(entity);
ListEntitiesLightResponse msg;
auto traits = light->get_traits();
msg.supported_color_modes = &traits.get_supported_color_modes_for_api_();
for (auto mode : traits.get_supported_color_modes())
msg.supported_color_modes.push_back(static_cast<enums::ColorMode>(mode));
if (traits.supports_color_capability(light::ColorCapability::COLOR_TEMPERATURE) ||
traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE)) {
msg.min_mireds = traits.get_min_mireds();
@@ -662,7 +657,8 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection
msg.supports_current_humidity = traits.get_supports_current_humidity();
msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
msg.supports_target_humidity = traits.get_supports_target_humidity();
msg.supported_modes = &traits.get_supported_modes_for_api_();
for (auto mode : traits.get_supported_modes())
msg.supported_modes.push_back(static_cast<enums::ClimateMode>(mode));
msg.visual_min_temperature = traits.get_visual_min_temperature();
msg.visual_max_temperature = traits.get_visual_max_temperature();
msg.visual_target_temperature_step = traits.get_visual_target_temperature_step();
@@ -670,11 +666,16 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection
msg.visual_min_humidity = traits.get_visual_min_humidity();
msg.visual_max_humidity = traits.get_visual_max_humidity();
msg.supports_action = traits.get_supports_action();
msg.supported_fan_modes = &traits.get_supported_fan_modes_for_api_();
msg.supported_custom_fan_modes = &traits.get_supported_custom_fan_modes_for_api_();
msg.supported_presets = &traits.get_supported_presets_for_api_();
msg.supported_custom_presets = &traits.get_supported_custom_presets_for_api_();
msg.supported_swing_modes = &traits.get_supported_swing_modes_for_api_();
for (auto fan_mode : traits.get_supported_fan_modes())
msg.supported_fan_modes.push_back(static_cast<enums::ClimateFanMode>(fan_mode));
for (auto const &custom_fan_mode : traits.get_supported_custom_fan_modes())
msg.supported_custom_fan_modes.push_back(custom_fan_mode);
for (auto preset : traits.get_supported_presets())
msg.supported_presets.push_back(static_cast<enums::ClimatePreset>(preset));
for (auto const &custom_preset : traits.get_supported_custom_presets())
msg.supported_custom_presets.push_back(custom_preset);
for (auto swing_mode : traits.get_supported_swing_modes())
msg.supported_swing_modes.push_back(static_cast<enums::ClimateSwingMode>(swing_mode));
return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size,
is_single);
}
@@ -880,7 +881,8 @@ uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *
bool is_single) {
auto *select = static_cast<select::Select *>(entity);
ListEntitiesSelectResponse msg;
msg.options = &select->traits.get_options();
for (const auto &option : select->traits.get_options())
msg.options.push_back(option);
return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size,
is_single);
}
@@ -1006,7 +1008,6 @@ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnec
ListEntitiesMediaPlayerResponse msg;
auto traits = media_player->get_traits();
msg.supports_pause = traits.get_supports_pause();
msg.feature_flags = traits.get_feature_flags();
for (auto &supported_format : traits.get_supported_formats()) {
msg.supported_formats.emplace_back();
auto &media_format = msg.supported_formats.back();
@@ -1072,17 +1073,17 @@ void APIConnection::camera_image(const CameraImageRequest &msg) {
#ifdef USE_HOMEASSISTANT_TIME
void APIConnection::on_get_time_response(const GetTimeResponse &value) {
if (homeassistant::global_homeassistant_time != nullptr) {
if (homeassistant::global_homeassistant_time != nullptr)
homeassistant::global_homeassistant_time->set_epoch_time(value.epoch_seconds);
#ifdef USE_TIME_TIMEZONE
if (!value.timezone.empty() && value.timezone != homeassistant::global_homeassistant_time->get_timezone()) {
homeassistant::global_homeassistant_time->set_timezone(value.timezone);
}
#endif
}
}
#endif
bool APIConnection::send_get_time_response(const GetTimeRequest &msg) {
GetTimeResponse resp;
resp.epoch_seconds = ::time(nullptr);
return this->send_message(resp, GetTimeResponse::MESSAGE_TYPE);
}
#ifdef USE_BLUETOOTH_PROXY
void APIConnection::subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->subscribe_api_connection(this, msg.flags);
@@ -1115,8 +1116,10 @@ void APIConnection::bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg)
bool APIConnection::send_subscribe_bluetooth_connections_free_response(
const SubscribeBluetoothConnectionsFreeRequest &msg) {
bluetooth_proxy::global_bluetooth_proxy->send_connections_free(this);
return true;
BluetoothConnectionsFreeResponse resp;
resp.free = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_connections_free();
resp.limit = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_connections_limit();
return this->send_message(resp, BluetoothConnectionsFreeResponse::MESSAGE_TYPE);
}
void APIConnection::bluetooth_scanner_set_mode(const BluetoothScannerSetModeRequest &msg) {
@@ -1193,7 +1196,9 @@ bool APIConnection::send_voice_assistant_get_configuration_response(const VoiceA
resp_wake_word.trained_languages.push_back(lang);
}
}
resp.active_wake_words = &config.active_wake_words;
for (auto &wake_word_id : config.active_wake_words) {
resp.active_wake_words.push_back(wake_word_id);
}
resp.max_active_wake_words = config.max_active_wake_words;
return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE);
}
@@ -1371,9 +1376,10 @@ bool APIConnection::send_hello_response(const HelloRequest &msg) {
HelloResponse resp;
resp.api_version_major = 1;
resp.api_version_minor = 12;
// Send only the version string - the client only logs this for debugging and doesn't use it otherwise
resp.set_server_info(ESPHOME_VERSION_REF);
resp.api_version_minor = 10;
// Temporary string for concatenation - will be valid during send_message call
std::string server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
resp.set_server_info(StringRef(server_info));
resp.set_name(StringRef(App.get_name()));
#ifdef USE_API_PASSWORD
@@ -1386,17 +1392,20 @@ bool APIConnection::send_hello_response(const HelloRequest &msg) {
return this->send_message(resp, HelloResponse::MESSAGE_TYPE);
}
#ifdef USE_API_PASSWORD
bool APIConnection::send_connect_response(const ConnectRequest &msg) {
bool correct = true;
#ifdef USE_API_PASSWORD
correct = this->parent_->check_password(msg.password);
#endif
ConnectResponse resp;
// bool invalid_password = 1;
resp.invalid_password = !this->parent_->check_password(msg.password);
if (!resp.invalid_password) {
resp.invalid_password = !correct;
if (correct) {
this->complete_authentication_();
}
return this->send_message(resp, ConnectResponse::MESSAGE_TYPE);
}
#endif // USE_API_PASSWORD
bool APIConnection::send_ping_response(const PingRequest &msg) {
PingResponse resp;
@@ -1417,9 +1426,13 @@ bool APIConnection::send_device_info_response(const DeviceInfoRequest &msg) {
std::string mac_address = get_mac_address_pretty();
resp.set_mac_address(StringRef(mac_address));
// Compile-time StringRef constants
static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION);
resp.set_esphome_version(ESPHOME_VERSION_REF);
resp.set_compilation_time(App.get_compilation_time_ref());
// get_compilation_time() returns temporary std::string - must store it
std::string compilation_time = App.get_compilation_time();
resp.set_compilation_time(StringRef(compilation_time));
// Compile-time StringRef constants for manufacturers
#if defined(USE_ESP8266) || defined(USE_ESP32)
@@ -1464,22 +1477,18 @@ bool APIConnection::send_device_info_response(const DeviceInfoRequest &msg) {
resp.api_encryption_supported = true;
#endif
#ifdef USE_DEVICES
size_t device_index = 0;
for (auto const &device : App.get_devices()) {
if (device_index >= ESPHOME_DEVICE_COUNT)
break;
auto &device_info = resp.devices[device_index++];
resp.devices.emplace_back();
auto &device_info = resp.devices.back();
device_info.device_id = device->get_device_id();
device_info.set_name(StringRef(device->get_name()));
device_info.area_id = device->get_area_id();
}
#endif
#ifdef USE_AREAS
size_t area_index = 0;
for (auto const &area : App.get_areas()) {
if (area_index >= ESPHOME_AREA_COUNT)
break;
auto &area_info = resp.areas[area_index++];
resp.areas.emplace_back();
auto &area_info = resp.areas.back();
area_info.area_id = area->get_area_id();
area_info.set_name(StringRef(area->get_name()));
}
@@ -1541,7 +1550,8 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
APIError err = this->helper_->loop();
if (err != APIError::OK) {
on_fatal_error();
this->log_socket_operation_failed_(err);
ESP_LOGW(TAG, "%s: Socket operation failed %s errno=%d", this->get_client_combined_info().c_str(),
api_error_to_str(err), errno);
return false;
}
if (this->helper_->can_write_without_blocking())
@@ -1561,7 +1571,8 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) {
return false;
if (err != APIError::OK) {
on_fatal_error();
this->log_warning_(LOG_STR("Packet write failed"), err);
ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->get_client_combined_info().c_str(),
api_error_to_str(err), errno);
return false;
}
// Do not set last_traffic_ on send
@@ -1622,6 +1633,14 @@ bool APIConnection::schedule_batch_() {
return true;
}
ProtoWriteBuffer APIConnection::allocate_single_message_buffer(uint16_t size) { return this->create_buffer(size); }
ProtoWriteBuffer APIConnection::allocate_batch_message_buffer(uint16_t size) {
ProtoWriteBuffer result = this->prepare_message_buffer(size, this->flags_.batch_first_message);
this->flags_.batch_first_message = false;
return result;
}
void APIConnection::process_batch_() {
// Ensure PacketInfo remains trivially destructible for our placement new approach
static_assert(std::is_trivially_destructible<PacketInfo>::value,
@@ -1638,8 +1657,6 @@ void APIConnection::process_batch_() {
return;
}
// Get shared buffer reference once to avoid multiple calls
auto &shared_buf = this->parent_->get_shared_buffer_ref();
size_t num_items = this->deferred_batch_.size();
// Fast path for single message - allocate exact size needed
@@ -1650,7 +1667,8 @@ void APIConnection::process_batch_() {
uint16_t payload_size =
item.creator(item.entity, this, std::numeric_limits<uint16_t>::max(), true, item.message_type);
if (payload_size > 0 && this->send_buffer(ProtoWriteBuffer{&shared_buf}, item.message_type)) {
if (payload_size > 0 &&
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, item.message_type)) {
#ifdef HAS_PROTO_MESSAGE_DUMP
// Log messages after send attempt for VV debugging
// It's safe to use the buffer for logging at this point regardless of send result
@@ -1677,18 +1695,20 @@ void APIConnection::process_batch_() {
const uint8_t footer_size = this->helper_->frame_footer_size();
// Initialize buffer and tracking variables
shared_buf.clear();
this->parent_->get_shared_buffer_ref().clear();
// Pre-calculate exact buffer size needed based on message types
uint32_t total_estimated_size = num_items * (header_padding + footer_size);
uint32_t total_estimated_size = 0;
for (size_t i = 0; i < this->deferred_batch_.size(); i++) {
const auto &item = this->deferred_batch_[i];
total_estimated_size += item.estimated_size;
}
// Calculate total overhead for all messages
uint32_t total_overhead = (header_padding + footer_size) * num_items;
// Reserve based on estimated size (much more accurate than 24-byte worst-case)
shared_buf.reserve(total_estimated_size);
this->parent_->get_shared_buffer_ref().reserve(total_estimated_size + total_overhead);
this->flags_.batch_first_message = true;
size_t items_processed = 0;
@@ -1729,8 +1749,8 @@ void APIConnection::process_batch_() {
}
remaining_size -= payload_size;
// Calculate where the next message's header padding will start
// Current buffer size + footer space for this message
current_offset = shared_buf.size() + footer_size;
// Current buffer size + footer space (that prepare_message_buffer will add for this message)
current_offset = this->parent_->get_shared_buffer_ref().size() + footer_size;
}
if (items_processed == 0) {
@@ -1740,15 +1760,17 @@ void APIConnection::process_batch_() {
// Add footer space for the last message (for Noise protocol MAC)
if (footer_size > 0) {
auto &shared_buf = this->parent_->get_shared_buffer_ref();
shared_buf.resize(shared_buf.size() + footer_size);
}
// Send all collected packets
APIError err = this->helper_->write_protobuf_packets(ProtoWriteBuffer{&shared_buf},
APIError err = this->helper_->write_protobuf_packets(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()},
std::span<const PacketInfo>(packet_info, packet_count));
if (err != APIError::OK && err != APIError::WOULD_BLOCK) {
on_fatal_error();
this->log_warning_(LOG_STR("Batch write failed"), err);
ESP_LOGW(TAG, "%s: Batch write failed %s errno=%d", this->get_client_combined_info().c_str(), api_error_to_str(err),
errno);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
@@ -1826,14 +1848,5 @@ void APIConnection::process_state_subscriptions_() {
}
#endif // USE_API_HOMEASSISTANT_STATES
void APIConnection::log_warning_(const LogString *message, APIError err) {
ESP_LOGW(TAG, "%s: %s %s errno=%d", this->get_client_combined_info().c_str(), LOG_STR_ARG(message),
LOG_STR_ARG(api_error_to_logstr(err)), errno);
}
void APIConnection::log_socket_operation_failed_(APIError err) {
this->log_warning_(LOG_STR("Socket operation failed"), err);
}
} // namespace esphome::api
#endif

View File

@@ -44,7 +44,7 @@ static constexpr size_t MAX_PACKETS_PER_BATCH = 64; // ESP32 has 8KB+ stack, HO
static constexpr size_t MAX_PACKETS_PER_BATCH = 32; // ESP8266/RP2040/etc have smaller stacks
#endif
class APIConnection final : public APIServerConnection {
class APIConnection : public APIServerConnection {
public:
friend class APIServer;
friend class ListEntitiesIterator;
@@ -197,9 +197,7 @@ class APIConnection final : public APIServerConnection {
void on_get_time_response(const GetTimeResponse &value) override;
#endif
bool send_hello_response(const HelloRequest &msg) override;
#ifdef USE_API_PASSWORD
bool send_connect_response(const ConnectRequest &msg) override;
#endif
bool send_disconnect_response(const DisconnectRequest &msg) override;
bool send_ping_response(const PingRequest &msg) override;
bool send_device_info_response(const DeviceInfoRequest &msg) override;
@@ -221,6 +219,7 @@ class APIConnection final : public APIServerConnection {
#ifdef USE_API_HOMEASSISTANT_STATES
void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) override;
#endif
bool send_get_time_response(const GetTimeRequest &msg) override;
#ifdef USE_API_SERVICES
void execute_service(const ExecuteServiceRequest &msg) override;
#endif
@@ -236,13 +235,6 @@ class APIConnection final : public APIServerConnection {
this->is_authenticated();
}
uint8_t get_log_subscription_level() const { return this->flags_.log_subscription; }
// Get client API version for feature detection
bool client_supports_api_version(uint16_t major, uint16_t minor) const {
return this->client_api_version_major_ > major ||
(this->client_api_version_major_ == major && this->client_api_version_minor_ >= minor);
}
void on_fatal_error() override;
#ifdef USE_API_PASSWORD
void on_unauthenticated_access() override;
@@ -253,21 +245,44 @@ class APIConnection final : public APIServerConnection {
// Get header padding size - used for both reserve and insert
uint8_t header_padding = this->helper_->frame_header_padding();
// Get shared buffer from parent server
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
this->prepare_first_message_buffer(shared_buf, header_padding,
reserve_size + header_padding + this->helper_->frame_footer_size());
return {&shared_buf};
}
void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) {
shared_buf.clear();
// Reserve space for header padding + message + footer
// - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext)
// - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext)
shared_buf.reserve(total_size);
shared_buf.reserve(reserve_size + header_padding + this->helper_->frame_footer_size());
// Resize to add header padding so message encoding starts at the correct position
shared_buf.resize(header_padding);
return {&shared_buf};
}
// Prepare buffer for next message in batch
ProtoWriteBuffer prepare_message_buffer(uint16_t message_size, bool is_first_message) {
// Get reference to shared buffer (it maintains state between batch messages)
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
if (is_first_message) {
shared_buf.clear();
}
size_t current_size = shared_buf.size();
// Calculate padding to add:
// - First message: just header padding
// - Subsequent messages: footer for previous message + header padding for this message
size_t padding_to_add = is_first_message
? this->helper_->frame_header_padding()
: this->helper_->frame_header_padding() + this->helper_->frame_footer_size();
// Reserve space for padding + message
shared_buf.reserve(current_size + padding_to_add + message_size);
// Resize to add the padding bytes
shared_buf.resize(current_size + padding_to_add);
return {&shared_buf};
}
bool try_to_clear_buffer(bool log_out_of_space);
@@ -275,13 +290,17 @@ class APIConnection final : public APIServerConnection {
std::string get_client_combined_info() const { return this->client_info_.get_combined_info(); }
// Buffer allocator methods for batch processing
ProtoWriteBuffer allocate_single_message_buffer(uint16_t size);
ProtoWriteBuffer allocate_batch_message_buffer(uint16_t size);
protected:
// Helper function to handle authentication completion
void complete_authentication_();
#ifdef USE_API_HOMEASSISTANT_STATES
void process_state_subscriptions_();
#endif
#endif // USE_API_HOMEASSISTANT_STATES
// Non-template helper to encode any ProtoMessage
static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn,
@@ -302,17 +321,9 @@ class APIConnection final : public APIServerConnection {
APIConnection *conn, uint32_t remaining_size, bool is_single) {
// Set common fields that are shared by all entity types
msg.key = entity->get_object_id_hash();
// Try to use static reference first to avoid allocation
StringRef static_ref = entity->get_object_id_ref_for_api_();
// Store dynamic string outside the if-else to maintain lifetime
std::string object_id;
if (!static_ref.empty()) {
msg.set_object_id(static_ref);
} else {
// Dynamic case - need to allocate
object_id = entity->get_object_id();
msg.set_object_id(StringRef(object_id));
}
// IMPORTANT: get_object_id() may return a temporary std::string
std::string object_id = entity->get_object_id();
msg.set_object_id(StringRef(object_id));
if (entity->has_own_name()) {
msg.set_name(entity->get_name());
@@ -685,16 +696,10 @@ class APIConnection final : public APIServerConnection {
bool send_message_smart_(EntityBase *entity, MessageCreatorPtr creator, uint8_t message_type,
uint8_t estimated_size) {
// Try to send immediately if:
// 1. It's an UpdateStateResponse (always send immediately to handle cases where
// the main loop is blocked, e.g., during OTA updates)
// 2. OR: We should try to send immediately (should_try_send_immediately = true)
// AND Batch delay is 0 (user has opted in to immediate sending)
// 3. AND: Buffer has space available
if ((
#ifdef USE_UPDATE
message_type == UpdateStateResponse::MESSAGE_TYPE ||
#endif
(this->flags_.should_try_send_immediately && this->get_batch_delay_ms_() == 0)) &&
// 1. We should try to send immediately (should_try_send_immediately = true)
// 2. Batch delay is 0 (user has opted in to immediate sending)
// 3. Buffer has space available
if (this->flags_.should_try_send_immediately && this->get_batch_delay_ms_() == 0 &&
this->helper_->can_write_without_blocking()) {
// Now actually encode and send
if (creator(entity, this, MAX_BATCH_PACKET_SIZE, true) &&
@@ -731,11 +736,6 @@ class APIConnection final : public APIServerConnection {
this->deferred_batch_.add_item_front(entity, MessageCreator(function_ptr), message_type, estimated_size);
return this->schedule_batch_();
}
// Helper function to log API errors with errno
void log_warning_(const LogString *message, APIError err);
// Specific helper for duplicated error message
void log_socket_operation_failed_(APIError err);
};
} // namespace esphome::api

View File

@@ -23,59 +23,59 @@ static const char *const TAG = "api.frame_helper";
#define LOG_PACKET_SENDING(data, len) ((void) 0)
#endif
const LogString *api_error_to_logstr(APIError err) {
const char *api_error_to_str(APIError err) {
// not using switch to ensure compiler doesn't try to build a big table out of it
if (err == APIError::OK) {
return LOG_STR("OK");
return "OK";
} else if (err == APIError::WOULD_BLOCK) {
return LOG_STR("WOULD_BLOCK");
return "WOULD_BLOCK";
} else if (err == APIError::BAD_INDICATOR) {
return LOG_STR("BAD_INDICATOR");
return "BAD_INDICATOR";
} else if (err == APIError::BAD_DATA_PACKET) {
return LOG_STR("BAD_DATA_PACKET");
return "BAD_DATA_PACKET";
} else if (err == APIError::TCP_NODELAY_FAILED) {
return LOG_STR("TCP_NODELAY_FAILED");
return "TCP_NODELAY_FAILED";
} else if (err == APIError::TCP_NONBLOCKING_FAILED) {
return LOG_STR("TCP_NONBLOCKING_FAILED");
return "TCP_NONBLOCKING_FAILED";
} else if (err == APIError::CLOSE_FAILED) {
return LOG_STR("CLOSE_FAILED");
return "CLOSE_FAILED";
} else if (err == APIError::SHUTDOWN_FAILED) {
return LOG_STR("SHUTDOWN_FAILED");
return "SHUTDOWN_FAILED";
} else if (err == APIError::BAD_STATE) {
return LOG_STR("BAD_STATE");
return "BAD_STATE";
} else if (err == APIError::BAD_ARG) {
return LOG_STR("BAD_ARG");
return "BAD_ARG";
} else if (err == APIError::SOCKET_READ_FAILED) {
return LOG_STR("SOCKET_READ_FAILED");
return "SOCKET_READ_FAILED";
} else if (err == APIError::SOCKET_WRITE_FAILED) {
return LOG_STR("SOCKET_WRITE_FAILED");
return "SOCKET_WRITE_FAILED";
} else if (err == APIError::OUT_OF_MEMORY) {
return LOG_STR("OUT_OF_MEMORY");
return "OUT_OF_MEMORY";
} else if (err == APIError::CONNECTION_CLOSED) {
return LOG_STR("CONNECTION_CLOSED");
return "CONNECTION_CLOSED";
}
#ifdef USE_API_NOISE
else if (err == APIError::BAD_HANDSHAKE_PACKET_LEN) {
return LOG_STR("BAD_HANDSHAKE_PACKET_LEN");
return "BAD_HANDSHAKE_PACKET_LEN";
} else if (err == APIError::HANDSHAKESTATE_READ_FAILED) {
return LOG_STR("HANDSHAKESTATE_READ_FAILED");
return "HANDSHAKESTATE_READ_FAILED";
} else if (err == APIError::HANDSHAKESTATE_WRITE_FAILED) {
return LOG_STR("HANDSHAKESTATE_WRITE_FAILED");
return "HANDSHAKESTATE_WRITE_FAILED";
} else if (err == APIError::HANDSHAKESTATE_BAD_STATE) {
return LOG_STR("HANDSHAKESTATE_BAD_STATE");
return "HANDSHAKESTATE_BAD_STATE";
} else if (err == APIError::CIPHERSTATE_DECRYPT_FAILED) {
return LOG_STR("CIPHERSTATE_DECRYPT_FAILED");
return "CIPHERSTATE_DECRYPT_FAILED";
} else if (err == APIError::CIPHERSTATE_ENCRYPT_FAILED) {
return LOG_STR("CIPHERSTATE_ENCRYPT_FAILED");
return "CIPHERSTATE_ENCRYPT_FAILED";
} else if (err == APIError::HANDSHAKESTATE_SETUP_FAILED) {
return LOG_STR("HANDSHAKESTATE_SETUP_FAILED");
return "HANDSHAKESTATE_SETUP_FAILED";
} else if (err == APIError::HANDSHAKESTATE_SPLIT_FAILED) {
return LOG_STR("HANDSHAKESTATE_SPLIT_FAILED");
return "HANDSHAKESTATE_SPLIT_FAILED";
} else if (err == APIError::BAD_HANDSHAKE_ERROR_BYTE) {
return LOG_STR("BAD_HANDSHAKE_ERROR_BYTE");
return "BAD_HANDSHAKE_ERROR_BYTE";
}
#endif
return LOG_STR("UNKNOWN");
return "UNKNOWN";
}
// Default implementation for loop - handles sending buffered data
@@ -156,9 +156,7 @@ APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt, uint16_
}
// Try to send directly if no buffered data
// Optimize for single iovec case (common for plaintext API)
ssize_t sent =
(iovcnt == 1) ? this->socket_->write(iov[0].iov_base, iov[0].iov_len) : this->socket_->writev(iov, iovcnt);
ssize_t sent = this->socket_->writev(iov, iovcnt);
if (sent == -1) {
APIError err = this->handle_socket_write_error_();

View File

@@ -66,7 +66,7 @@ enum class APIError : uint16_t {
#endif
};
const LogString *api_error_to_logstr(APIError err);
const char *api_error_to_str(APIError err);
class APIFrameHelper {
public:
@@ -104,9 +104,9 @@ class APIFrameHelper {
// The buffer contains all messages with appropriate padding before each
virtual APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) = 0;
// Get the frame header padding required by this protocol
uint8_t frame_header_padding() const { return frame_header_padding_; }
virtual uint8_t frame_header_padding() = 0;
// Get the frame footer size required by this protocol
uint8_t frame_footer_size() const { return frame_footer_size_; }
virtual uint8_t frame_footer_size() = 0;
// Check if socket has data ready to read
bool is_socket_ready() const { return socket_ != nullptr && socket_->ready(); }

View File

@@ -10,18 +10,10 @@
#include <cstring>
#include <cinttypes>
#ifdef USE_ESP8266
#include <pgmspace.h>
#endif
namespace esphome::api {
static const char *const TAG = "api.noise";
#ifdef USE_ESP8266
static const char PROLOGUE_INIT[] PROGMEM = "NoiseAPIInit";
#else
static const char *const PROLOGUE_INIT = "NoiseAPIInit";
#endif
static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, this->client_info_->get_combined_info().c_str(), ##__VA_ARGS__)
@@ -35,42 +27,42 @@ static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
#endif
/// Convert a noise error code to a readable error
const LogString *noise_err_to_logstr(int err) {
std::string noise_err_to_str(int err) {
if (err == NOISE_ERROR_NO_MEMORY)
return LOG_STR("NO_MEMORY");
return "NO_MEMORY";
if (err == NOISE_ERROR_UNKNOWN_ID)
return LOG_STR("UNKNOWN_ID");
return "UNKNOWN_ID";
if (err == NOISE_ERROR_UNKNOWN_NAME)
return LOG_STR("UNKNOWN_NAME");
return "UNKNOWN_NAME";
if (err == NOISE_ERROR_MAC_FAILURE)
return LOG_STR("MAC_FAILURE");
return "MAC_FAILURE";
if (err == NOISE_ERROR_NOT_APPLICABLE)
return LOG_STR("NOT_APPLICABLE");
return "NOT_APPLICABLE";
if (err == NOISE_ERROR_SYSTEM)
return LOG_STR("SYSTEM");
return "SYSTEM";
if (err == NOISE_ERROR_REMOTE_KEY_REQUIRED)
return LOG_STR("REMOTE_KEY_REQUIRED");
return "REMOTE_KEY_REQUIRED";
if (err == NOISE_ERROR_LOCAL_KEY_REQUIRED)
return LOG_STR("LOCAL_KEY_REQUIRED");
return "LOCAL_KEY_REQUIRED";
if (err == NOISE_ERROR_PSK_REQUIRED)
return LOG_STR("PSK_REQUIRED");
return "PSK_REQUIRED";
if (err == NOISE_ERROR_INVALID_LENGTH)
return LOG_STR("INVALID_LENGTH");
return "INVALID_LENGTH";
if (err == NOISE_ERROR_INVALID_PARAM)
return LOG_STR("INVALID_PARAM");
return "INVALID_PARAM";
if (err == NOISE_ERROR_INVALID_STATE)
return LOG_STR("INVALID_STATE");
return "INVALID_STATE";
if (err == NOISE_ERROR_INVALID_NONCE)
return LOG_STR("INVALID_NONCE");
return "INVALID_NONCE";
if (err == NOISE_ERROR_INVALID_PRIVATE_KEY)
return LOG_STR("INVALID_PRIVATE_KEY");
return "INVALID_PRIVATE_KEY";
if (err == NOISE_ERROR_INVALID_PUBLIC_KEY)
return LOG_STR("INVALID_PUBLIC_KEY");
return "INVALID_PUBLIC_KEY";
if (err == NOISE_ERROR_INVALID_FORMAT)
return LOG_STR("INVALID_FORMAT");
return "INVALID_FORMAT";
if (err == NOISE_ERROR_INVALID_SIGNATURE)
return LOG_STR("INVALID_SIGNATURE");
return LOG_STR("UNKNOWN");
return "INVALID_SIGNATURE";
return to_string(err);
}
/// Initialize the frame helper, returns OK if successful.
@@ -83,11 +75,7 @@ APIError APINoiseFrameHelper::init() {
// init prologue
size_t old_size = prologue_.size();
prologue_.resize(old_size + PROLOGUE_INIT_LEN);
#ifdef USE_ESP8266
memcpy_P(prologue_.data() + old_size, PROLOGUE_INIT, PROLOGUE_INIT_LEN);
#else
std::memcpy(prologue_.data() + old_size, PROLOGUE_INIT, PROLOGUE_INIT_LEN);
#endif
state_ = State::CLIENT_HELLO;
return APIError::OK;
@@ -95,18 +83,18 @@ APIError APINoiseFrameHelper::init() {
// Helper for handling handshake frame errors
APIError APINoiseFrameHelper::handle_handshake_frame_error_(APIError aerr) {
if (aerr == APIError::BAD_INDICATOR) {
send_explicit_handshake_reject_(LOG_STR("Bad indicator byte"));
send_explicit_handshake_reject_("Bad indicator byte");
} else if (aerr == APIError::BAD_HANDSHAKE_PACKET_LEN) {
send_explicit_handshake_reject_(LOG_STR("Bad handshake packet len"));
send_explicit_handshake_reject_("Bad handshake packet len");
}
return aerr;
}
// Helper for handling noise library errors
APIError APINoiseFrameHelper::handle_noise_error_(int err, const LogString *func_name, APIError api_err) {
APIError APINoiseFrameHelper::handle_noise_error_(int err, const char *func_name, APIError api_err) {
if (err != 0) {
state_ = State::FAILED;
HELPER_LOG("%s failed: %s", LOG_STR_ARG(func_name), LOG_STR_ARG(noise_err_to_logstr(err)));
HELPER_LOG("%s failed: %s", func_name, noise_err_to_str(err).c_str());
return api_err;
}
return APIError::OK;
@@ -291,11 +279,11 @@ APIError APINoiseFrameHelper::state_action_() {
}
if (frame.empty()) {
send_explicit_handshake_reject_(LOG_STR("Empty handshake message"));
send_explicit_handshake_reject_("Empty handshake message");
return APIError::BAD_HANDSHAKE_ERROR_BYTE;
} else if (frame[0] != 0x00) {
HELPER_LOG("Bad handshake error byte: %u", frame[0]);
send_explicit_handshake_reject_(LOG_STR("Bad handshake error byte"));
send_explicit_handshake_reject_("Bad handshake error byte");
return APIError::BAD_HANDSHAKE_ERROR_BYTE;
}
@@ -305,10 +293,8 @@ APIError APINoiseFrameHelper::state_action_() {
err = noise_handshakestate_read_message(handshake_, &mbuf, nullptr);
if (err != 0) {
// Special handling for MAC failure
send_explicit_handshake_reject_(err == NOISE_ERROR_MAC_FAILURE ? LOG_STR("Handshake MAC failure")
: LOG_STR("Handshake error"));
return handle_noise_error_(err, LOG_STR("noise_handshakestate_read_message"),
APIError::HANDSHAKESTATE_READ_FAILED);
send_explicit_handshake_reject_(err == NOISE_ERROR_MAC_FAILURE ? "Handshake MAC failure" : "Handshake error");
return handle_noise_error_(err, "noise_handshakestate_read_message", APIError::HANDSHAKESTATE_READ_FAILED);
}
aerr = check_handshake_finished_();
@@ -321,8 +307,8 @@ APIError APINoiseFrameHelper::state_action_() {
noise_buffer_set_output(mbuf, buffer + 1, sizeof(buffer) - 1);
err = noise_handshakestate_write_message(handshake_, &mbuf, nullptr);
APIError aerr_write = handle_noise_error_(err, LOG_STR("noise_handshakestate_write_message"),
APIError::HANDSHAKESTATE_WRITE_FAILED);
APIError aerr_write =
handle_noise_error_(err, "noise_handshakestate_write_message", APIError::HANDSHAKESTATE_WRITE_FAILED);
if (aerr_write != APIError::OK)
return aerr_write;
buffer[0] = 0x00; // success
@@ -345,31 +331,15 @@ APIError APINoiseFrameHelper::state_action_() {
}
return APIError::OK;
}
void APINoiseFrameHelper::send_explicit_handshake_reject_(const LogString *reason) {
#ifdef USE_STORE_LOG_STR_IN_FLASH
// On ESP8266 with flash strings, we need to use PROGMEM-aware functions
size_t reason_len = strlen_P(reinterpret_cast<PGM_P>(reason));
void APINoiseFrameHelper::send_explicit_handshake_reject_(const std::string &reason) {
std::vector<uint8_t> data;
data.resize(reason_len + 1);
data[0] = 0x01; // failure
// Copy error message from PROGMEM
if (reason_len > 0) {
memcpy_P(data.data() + 1, reinterpret_cast<PGM_P>(reason), reason_len);
}
#else
// Normal memory access
const char *reason_str = LOG_STR_ARG(reason);
size_t reason_len = strlen(reason_str);
std::vector<uint8_t> data;
data.resize(reason_len + 1);
data.resize(reason.length() + 1);
data[0] = 0x01; // failure
// Copy error message in bulk
if (reason_len > 0) {
std::memcpy(data.data() + 1, reason_str, reason_len);
if (!reason.empty()) {
std::memcpy(data.data() + 1, reason.c_str(), reason.length());
}
#endif
// temporarily remove failed state
auto orig_state = state_;
@@ -398,8 +368,7 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) {
noise_buffer_init(mbuf);
noise_buffer_set_inout(mbuf, frame.data(), frame.size(), frame.size());
err = noise_cipherstate_decrypt(recv_cipher_, &mbuf);
APIError decrypt_err =
handle_noise_error_(err, LOG_STR("noise_cipherstate_decrypt"), APIError::CIPHERSTATE_DECRYPT_FAILED);
APIError decrypt_err = handle_noise_error_(err, "noise_cipherstate_decrypt", APIError::CIPHERSTATE_DECRYPT_FAILED);
if (decrypt_err != APIError::OK)
return decrypt_err;
@@ -481,8 +450,7 @@ APIError APINoiseFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, st
4 + packet.payload_size + frame_footer_size_);
int err = noise_cipherstate_encrypt(send_cipher_, &mbuf);
APIError aerr =
handle_noise_error_(err, LOG_STR("noise_cipherstate_encrypt"), APIError::CIPHERSTATE_ENCRYPT_FAILED);
APIError aerr = handle_noise_error_(err, "noise_cipherstate_encrypt", APIError::CIPHERSTATE_ENCRYPT_FAILED);
if (aerr != APIError::OK)
return aerr;
@@ -536,27 +504,25 @@ APIError APINoiseFrameHelper::init_handshake_() {
nid_.modifier_ids[0] = NOISE_MODIFIER_PSK0;
err = noise_handshakestate_new_by_id(&handshake_, &nid_, NOISE_ROLE_RESPONDER);
APIError aerr =
handle_noise_error_(err, LOG_STR("noise_handshakestate_new_by_id"), APIError::HANDSHAKESTATE_SETUP_FAILED);
APIError aerr = handle_noise_error_(err, "noise_handshakestate_new_by_id", APIError::HANDSHAKESTATE_SETUP_FAILED);
if (aerr != APIError::OK)
return aerr;
const auto &psk = ctx_->get_psk();
err = noise_handshakestate_set_pre_shared_key(handshake_, psk.data(), psk.size());
aerr = handle_noise_error_(err, LOG_STR("noise_handshakestate_set_pre_shared_key"),
APIError::HANDSHAKESTATE_SETUP_FAILED);
aerr = handle_noise_error_(err, "noise_handshakestate_set_pre_shared_key", APIError::HANDSHAKESTATE_SETUP_FAILED);
if (aerr != APIError::OK)
return aerr;
err = noise_handshakestate_set_prologue(handshake_, prologue_.data(), prologue_.size());
aerr = handle_noise_error_(err, LOG_STR("noise_handshakestate_set_prologue"), APIError::HANDSHAKESTATE_SETUP_FAILED);
aerr = handle_noise_error_(err, "noise_handshakestate_set_prologue", APIError::HANDSHAKESTATE_SETUP_FAILED);
if (aerr != APIError::OK)
return aerr;
// set_prologue copies it into handshakestate, so we can get rid of it now
prologue_ = {};
err = noise_handshakestate_start(handshake_);
aerr = handle_noise_error_(err, LOG_STR("noise_handshakestate_start"), APIError::HANDSHAKESTATE_SETUP_FAILED);
aerr = handle_noise_error_(err, "noise_handshakestate_start", APIError::HANDSHAKESTATE_SETUP_FAILED);
if (aerr != APIError::OK)
return aerr;
return APIError::OK;
@@ -574,8 +540,7 @@ APIError APINoiseFrameHelper::check_handshake_finished_() {
return APIError::HANDSHAKESTATE_BAD_STATE;
}
int err = noise_handshakestate_split(handshake_, &send_cipher_, &recv_cipher_);
APIError aerr =
handle_noise_error_(err, LOG_STR("noise_handshakestate_split"), APIError::HANDSHAKESTATE_SPLIT_FAILED);
APIError aerr = handle_noise_error_(err, "noise_handshakestate_split", APIError::HANDSHAKESTATE_SPLIT_FAILED);
if (aerr != APIError::OK)
return aerr;

View File

@@ -7,7 +7,7 @@
namespace esphome::api {
class APINoiseFrameHelper final : public APIFrameHelper {
class APINoiseFrameHelper : public APIFrameHelper {
public:
APINoiseFrameHelper(std::unique_ptr<socket::Socket> socket, std::shared_ptr<APINoiseContext> ctx,
const ClientInfo *client_info)
@@ -25,6 +25,10 @@ class APINoiseFrameHelper final : public APIFrameHelper {
APIError read_packet(ReadPacketBuffer *buffer) override;
APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override;
APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) override;
// Get the frame header padding required by this protocol
uint8_t frame_header_padding() override { return frame_header_padding_; }
// Get the frame footer size required by this protocol
uint8_t frame_footer_size() override { return frame_footer_size_; }
protected:
APIError state_action_();
@@ -32,9 +36,9 @@ class APINoiseFrameHelper final : public APIFrameHelper {
APIError write_frame_(const uint8_t *data, uint16_t len);
APIError init_handshake_();
APIError check_handshake_finished_();
void send_explicit_handshake_reject_(const LogString *reason);
void send_explicit_handshake_reject_(const std::string &reason);
APIError handle_handshake_frame_error_(APIError aerr);
APIError handle_noise_error_(int err, const LogString *func_name, APIError api_err);
APIError handle_noise_error_(int err, const char *func_name, APIError api_err);
// Pointers first (4 bytes each)
NoiseHandshakeState *handshake_{nullptr};

View File

@@ -10,10 +10,6 @@
#include <cstring>
#include <cinttypes>
#ifdef USE_ESP8266
#include <pgmspace.h>
#endif
namespace esphome::api {
static const char *const TAG = "api.plaintext";
@@ -201,20 +197,11 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
// We must send at least 3 bytes to be read, so we add
// a message after the indicator byte to ensures its long
// enough and can aid in debugging.
static constexpr uint8_t INDICATOR_MSG_SIZE = 19;
#ifdef USE_ESP8266
static const char MSG_PROGMEM[] PROGMEM = "\x00"
"Bad indicator byte";
char msg[INDICATOR_MSG_SIZE];
memcpy_P(msg, MSG_PROGMEM, INDICATOR_MSG_SIZE);
const char msg[] = "\x00"
"Bad indicator byte";
iov[0].iov_base = (void *) msg;
#else
static const char MSG[] = "\x00"
"Bad indicator byte";
iov[0].iov_base = (void *) MSG;
#endif
iov[0].iov_len = INDICATOR_MSG_SIZE;
this->write_raw_(iov, 1, INDICATOR_MSG_SIZE);
iov[0].iov_len = 19;
this->write_raw_(iov, 1, 19);
}
return aerr;
}

View File

@@ -5,7 +5,7 @@
namespace esphome::api {
class APIPlaintextFrameHelper final : public APIFrameHelper {
class APIPlaintextFrameHelper : public APIFrameHelper {
public:
APIPlaintextFrameHelper(std::unique_ptr<socket::Socket> socket, const ClientInfo *client_info)
: APIFrameHelper(std::move(socket), client_info) {
@@ -22,6 +22,9 @@ class APIPlaintextFrameHelper final : public APIFrameHelper {
APIError read_packet(ReadPacketBuffer *buffer) override;
APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override;
APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) override;
uint8_t frame_header_padding() override { return frame_header_padding_; }
// Get the frame footer size required by this protocol
uint8_t frame_footer_size() override { return frame_footer_size_; }
protected:
APIError try_read_frame_(std::vector<uint8_t> *frame);

View File

@@ -28,33 +28,4 @@ extend google.protobuf.FieldOptions {
optional string field_ifdef = 1042;
optional uint32 fixed_array_size = 50007;
optional bool no_zero_copy = 50008 [default=false];
optional bool fixed_array_skip_zero = 50009 [default=false];
optional string fixed_array_size_define = 50010;
optional string fixed_array_with_length_define = 50011;
// container_pointer: Zero-copy optimization for repeated fields.
//
// When container_pointer is set on a repeated field, the generated message will
// store a pointer to an existing container instead of copying the data into the
// message's own repeated field. This eliminates heap allocations and improves performance.
//
// Requirements for safe usage:
// 1. The source container must remain valid until the message is encoded
// 2. Messages must be encoded immediately (which ESPHome does by default)
// 3. The container type must match the field type exactly
//
// Supported container types:
// - "std::vector<T>" for most repeated fields
// - "std::set<T>" for unique/sorted data
// - Full type specification required for enums (e.g., "std::set<climate::ClimateMode>")
//
// Example usage in .proto file:
// repeated string supported_modes = 12 [(container_pointer) = "std::set"];
// repeated ColorMode color_modes = 13 [(container_pointer) = "std::set<light::ColorMode>"];
//
// The corresponding C++ code must provide const reference access to a container
// that matches the specified type and remains valid during message encoding.
// This is typically done through methods returning const T& or special accessor
// methods like get_options() or supported_modes_for_api_().
optional string container_pointer = 50001;
}

View File

@@ -42,7 +42,6 @@ void HelloResponse::calculate_size(ProtoSize &size) const {
size.add_length(1, this->server_info_ref_.size());
size.add_length(1, this->name_ref_.size());
}
#ifdef USE_API_PASSWORD
bool ConnectRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 1:
@@ -55,7 +54,6 @@ bool ConnectRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value
}
void ConnectResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->invalid_password); }
void ConnectResponse::calculate_size(ProtoSize &size) const { size.add_bool(1, this->invalid_password); }
#endif
#ifdef USE_AREAS
void AreaInfo::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(1, this->area_id);
@@ -117,12 +115,12 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(19, this->api_encryption_supported);
#endif
#ifdef USE_DEVICES
for (const auto &it : this->devices) {
for (auto &it : this->devices) {
buffer.encode_message(20, it, true);
}
#endif
#ifdef USE_AREAS
for (const auto &it : this->areas) {
for (auto &it : this->areas) {
buffer.encode_message(21, it, true);
}
#endif
@@ -169,14 +167,10 @@ void DeviceInfoResponse::calculate_size(ProtoSize &size) const {
size.add_bool(2, this->api_encryption_supported);
#endif
#ifdef USE_DEVICES
for (const auto &it : this->devices) {
size.add_message_object_force(2, it);
}
size.add_repeated_message(2, this->devices);
#endif
#ifdef USE_AREAS
for (const auto &it : this->areas) {
size.add_message_object_force(2, it);
}
size.add_repeated_message(2, this->areas);
#endif
#ifdef USE_AREAS
size.add_message_object(2, this->area);
@@ -337,7 +331,7 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(10, this->icon_ref_);
#endif
buffer.encode_uint32(11, static_cast<uint32_t>(this->entity_category));
for (const auto &it : *this->supported_preset_modes) {
for (auto &it : this->supported_preset_modes) {
buffer.encode_string(12, it, true);
}
#ifdef USE_DEVICES
@@ -357,8 +351,8 @@ void ListEntitiesFanResponse::calculate_size(ProtoSize &size) const {
size.add_length(1, this->icon_ref_.size());
#endif
size.add_uint32(1, static_cast<uint32_t>(this->entity_category));
if (!this->supported_preset_modes->empty()) {
for (const auto &it : *this->supported_preset_modes) {
if (!this->supported_preset_modes.empty()) {
for (const auto &it : this->supported_preset_modes) {
size.add_length_force(1, it.size());
}
}
@@ -453,7 +447,7 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(1, this->object_id_ref_);
buffer.encode_fixed32(2, this->key);
buffer.encode_string(3, this->name_ref_);
for (const auto &it : *this->supported_color_modes) {
for (auto &it : this->supported_color_modes) {
buffer.encode_uint32(12, static_cast<uint32_t>(it), true);
}
buffer.encode_float(9, this->min_mireds);
@@ -474,8 +468,8 @@ void ListEntitiesLightResponse::calculate_size(ProtoSize &size) const {
size.add_length(1, this->object_id_ref_.size());
size.add_fixed32(1, this->key);
size.add_length(1, this->name_ref_.size());
if (!this->supported_color_modes->empty()) {
for (const auto &it : *this->supported_color_modes) {
if (!this->supported_color_modes.empty()) {
for (const auto &it : this->supported_color_modes) {
size.add_uint32_force(1, static_cast<uint32_t>(it));
}
}
@@ -903,16 +897,6 @@ bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDel
return true;
}
#endif
bool GetTimeResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 2:
this->timezone = value.as_string();
break;
default:
return false;
}
return true;
}
bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
switch (field_id) {
case 1:
@@ -923,6 +907,8 @@ bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
}
return true;
}
void GetTimeResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_fixed32(1, this->epoch_seconds); }
void GetTimeResponse::calculate_size(ProtoSize &size) const { size.add_fixed32(1, this->epoch_seconds); }
#ifdef USE_API_SERVICES
void ListEntitiesServicesArgument::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(1, this->name_ref_);
@@ -1078,26 +1064,26 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(3, this->name_ref_);
buffer.encode_bool(5, this->supports_current_temperature);
buffer.encode_bool(6, this->supports_two_point_target_temperature);
for (const auto &it : *this->supported_modes) {
for (auto &it : this->supported_modes) {
buffer.encode_uint32(7, static_cast<uint32_t>(it), true);
}
buffer.encode_float(8, this->visual_min_temperature);
buffer.encode_float(9, this->visual_max_temperature);
buffer.encode_float(10, this->visual_target_temperature_step);
buffer.encode_bool(12, this->supports_action);
for (const auto &it : *this->supported_fan_modes) {
for (auto &it : this->supported_fan_modes) {
buffer.encode_uint32(13, static_cast<uint32_t>(it), true);
}
for (const auto &it : *this->supported_swing_modes) {
for (auto &it : this->supported_swing_modes) {
buffer.encode_uint32(14, static_cast<uint32_t>(it), true);
}
for (const auto &it : *this->supported_custom_fan_modes) {
for (auto &it : this->supported_custom_fan_modes) {
buffer.encode_string(15, it, true);
}
for (const auto &it : *this->supported_presets) {
for (auto &it : this->supported_presets) {
buffer.encode_uint32(16, static_cast<uint32_t>(it), true);
}
for (const auto &it : *this->supported_custom_presets) {
for (auto &it : this->supported_custom_presets) {
buffer.encode_string(17, it, true);
}
buffer.encode_bool(18, this->disabled_by_default);
@@ -1120,8 +1106,8 @@ void ListEntitiesClimateResponse::calculate_size(ProtoSize &size) const {
size.add_length(1, this->name_ref_.size());
size.add_bool(1, this->supports_current_temperature);
size.add_bool(1, this->supports_two_point_target_temperature);
if (!this->supported_modes->empty()) {
for (const auto &it : *this->supported_modes) {
if (!this->supported_modes.empty()) {
for (const auto &it : this->supported_modes) {
size.add_uint32_force(1, static_cast<uint32_t>(it));
}
}
@@ -1129,28 +1115,28 @@ void ListEntitiesClimateResponse::calculate_size(ProtoSize &size) const {
size.add_float(1, this->visual_max_temperature);
size.add_float(1, this->visual_target_temperature_step);
size.add_bool(1, this->supports_action);
if (!this->supported_fan_modes->empty()) {
for (const auto &it : *this->supported_fan_modes) {
if (!this->supported_fan_modes.empty()) {
for (const auto &it : this->supported_fan_modes) {
size.add_uint32_force(1, static_cast<uint32_t>(it));
}
}
if (!this->supported_swing_modes->empty()) {
for (const auto &it : *this->supported_swing_modes) {
if (!this->supported_swing_modes.empty()) {
for (const auto &it : this->supported_swing_modes) {
size.add_uint32_force(1, static_cast<uint32_t>(it));
}
}
if (!this->supported_custom_fan_modes->empty()) {
for (const auto &it : *this->supported_custom_fan_modes) {
if (!this->supported_custom_fan_modes.empty()) {
for (const auto &it : this->supported_custom_fan_modes) {
size.add_length_force(1, it.size());
}
}
if (!this->supported_presets->empty()) {
for (const auto &it : *this->supported_presets) {
if (!this->supported_presets.empty()) {
for (const auto &it : this->supported_presets) {
size.add_uint32_force(2, static_cast<uint32_t>(it));
}
}
if (!this->supported_custom_presets->empty()) {
for (const auto &it : *this->supported_custom_presets) {
if (!this->supported_custom_presets.empty()) {
for (const auto &it : this->supported_custom_presets) {
size.add_length_force(2, it.size());
}
}
@@ -1385,7 +1371,7 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const {
#ifdef USE_ENTITY_ICON
buffer.encode_string(5, this->icon_ref_);
#endif
for (const auto &it : *this->options) {
for (auto &it : this->options) {
buffer.encode_string(6, it, true);
}
buffer.encode_bool(7, this->disabled_by_default);
@@ -1401,8 +1387,8 @@ void ListEntitiesSelectResponse::calculate_size(ProtoSize &size) const {
#ifdef USE_ENTITY_ICON
size.add_length(1, this->icon_ref_.size());
#endif
if (!this->options->empty()) {
for (const auto &it : *this->options) {
if (!this->options.empty()) {
for (const auto &it : this->options) {
size.add_length_force(1, it.size());
}
}
@@ -1739,7 +1725,6 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const {
#ifdef USE_DEVICES
buffer.encode_uint32(10, this->device_id);
#endif
buffer.encode_uint32(11, this->feature_flags);
}
void ListEntitiesMediaPlayerResponse::calculate_size(ProtoSize &size) const {
size.add_length(1, this->object_id_ref_.size());
@@ -1755,7 +1740,6 @@ void ListEntitiesMediaPlayerResponse::calculate_size(ProtoSize &size) const {
#ifdef USE_DEVICES
size.add_uint32(1, this->device_id);
#endif
size.add_uint32(1, this->feature_flags);
}
void MediaPlayerStateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_fixed32(1, this->key);
@@ -1853,14 +1837,12 @@ void BluetoothLERawAdvertisement::calculate_size(ProtoSize &size) const {
size.add_length(1, this->data_len);
}
void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer buffer) const {
for (uint16_t i = 0; i < this->advertisements_len; i++) {
buffer.encode_message(1, this->advertisements[i], true);
for (auto &it : this->advertisements) {
buffer.encode_message(1, it, true);
}
}
void BluetoothLERawAdvertisementsResponse::calculate_size(ProtoSize &size) const {
for (uint16_t i = 0; i < this->advertisements_len; i++) {
size.add_message_object_force(1, this->advertisements[i]);
}
size.add_repeated_message(1, this->advertisements);
}
bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
@@ -1904,72 +1886,52 @@ bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, ProtoVarI
return true;
}
void BluetoothGATTDescriptor::encode(ProtoWriteBuffer buffer) const {
if (this->uuid[0] != 0 || this->uuid[1] != 0) {
buffer.encode_uint64(1, this->uuid[0], true);
buffer.encode_uint64(1, this->uuid[1], true);
}
buffer.encode_uint64(1, this->uuid[0], true);
buffer.encode_uint64(1, this->uuid[1], true);
buffer.encode_uint32(2, this->handle);
buffer.encode_uint32(3, this->short_uuid);
}
void BluetoothGATTDescriptor::calculate_size(ProtoSize &size) const {
if (this->uuid[0] != 0 || this->uuid[1] != 0) {
size.add_uint64_force(1, this->uuid[0]);
size.add_uint64_force(1, this->uuid[1]);
}
size.add_uint64_force(1, this->uuid[0]);
size.add_uint64_force(1, this->uuid[1]);
size.add_uint32(1, this->handle);
size.add_uint32(1, this->short_uuid);
}
void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer buffer) const {
if (this->uuid[0] != 0 || this->uuid[1] != 0) {
buffer.encode_uint64(1, this->uuid[0], true);
buffer.encode_uint64(1, this->uuid[1], true);
}
buffer.encode_uint64(1, this->uuid[0], true);
buffer.encode_uint64(1, this->uuid[1], true);
buffer.encode_uint32(2, this->handle);
buffer.encode_uint32(3, this->properties);
for (auto &it : this->descriptors) {
buffer.encode_message(4, it, true);
}
buffer.encode_uint32(5, this->short_uuid);
}
void BluetoothGATTCharacteristic::calculate_size(ProtoSize &size) const {
if (this->uuid[0] != 0 || this->uuid[1] != 0) {
size.add_uint64_force(1, this->uuid[0]);
size.add_uint64_force(1, this->uuid[1]);
}
size.add_uint64_force(1, this->uuid[0]);
size.add_uint64_force(1, this->uuid[1]);
size.add_uint32(1, this->handle);
size.add_uint32(1, this->properties);
size.add_repeated_message(1, this->descriptors);
size.add_uint32(1, this->short_uuid);
}
void BluetoothGATTService::encode(ProtoWriteBuffer buffer) const {
if (this->uuid[0] != 0 || this->uuid[1] != 0) {
buffer.encode_uint64(1, this->uuid[0], true);
buffer.encode_uint64(1, this->uuid[1], true);
}
buffer.encode_uint64(1, this->uuid[0], true);
buffer.encode_uint64(1, this->uuid[1], true);
buffer.encode_uint32(2, this->handle);
for (auto &it : this->characteristics) {
buffer.encode_message(3, it, true);
}
buffer.encode_uint32(4, this->short_uuid);
}
void BluetoothGATTService::calculate_size(ProtoSize &size) const {
if (this->uuid[0] != 0 || this->uuid[1] != 0) {
size.add_uint64_force(1, this->uuid[0]);
size.add_uint64_force(1, this->uuid[1]);
}
size.add_uint64_force(1, this->uuid[0]);
size.add_uint64_force(1, this->uuid[1]);
size.add_uint32(1, this->handle);
size.add_repeated_message(1, this->characteristics);
size.add_uint32(1, this->short_uuid);
}
void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint64(1, this->address);
for (auto &it : this->services) {
buffer.encode_message(2, it, true);
}
buffer.encode_message(2, this->services[0], true);
}
void BluetoothGATTGetServicesResponse::calculate_size(ProtoSize &size) const {
size.add_uint64(1, this->address);
size.add_repeated_message(1, this->services);
size.add_message_object_force(1, this->services[0]);
}
void BluetoothGATTGetServicesDoneResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint64(1, this->address);
@@ -2089,17 +2051,15 @@ void BluetoothGATTNotifyDataResponse::calculate_size(ProtoSize &size) const {
void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(1, this->free);
buffer.encode_uint32(2, this->limit);
for (const auto &it : this->allocated) {
if (it != 0) {
buffer.encode_uint64(3, it, true);
}
for (auto &it : this->allocated) {
buffer.encode_uint64(3, it, true);
}
}
void BluetoothConnectionsFreeResponse::calculate_size(ProtoSize &size) const {
size.add_uint32(1, this->free);
size.add_uint32(1, this->limit);
for (const auto &it : this->allocated) {
if (it != 0) {
if (!this->allocated.empty()) {
for (const auto &it : this->allocated) {
size.add_uint64_force(1, it);
}
}
@@ -2163,12 +2123,10 @@ void BluetoothDeviceClearCacheResponse::calculate_size(ProtoSize &size) const {
void BluetoothScannerStateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(1, static_cast<uint32_t>(this->state));
buffer.encode_uint32(2, static_cast<uint32_t>(this->mode));
buffer.encode_uint32(3, static_cast<uint32_t>(this->configured_mode));
}
void BluetoothScannerStateResponse::calculate_size(ProtoSize &size) const {
size.add_uint32(1, static_cast<uint32_t>(this->state));
size.add_uint32(1, static_cast<uint32_t>(this->mode));
size.add_uint32(1, static_cast<uint32_t>(this->configured_mode));
}
bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
@@ -2374,15 +2332,15 @@ void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer buffer) const
for (auto &it : this->available_wake_words) {
buffer.encode_message(1, it, true);
}
for (const auto &it : *this->active_wake_words) {
for (auto &it : this->active_wake_words) {
buffer.encode_string(2, it, true);
}
buffer.encode_uint32(3, this->max_active_wake_words);
}
void VoiceAssistantConfigurationResponse::calculate_size(ProtoSize &size) const {
size.add_repeated_message(1, this->available_wake_words);
if (!this->active_wake_words->empty()) {
for (const auto &it : *this->active_wake_words) {
if (!this->active_wake_words.empty()) {
for (const auto &it : this->active_wake_words) {
size.add_length_force(1, it.size());
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -383,12 +383,6 @@ template<> const char *proto_enum_to_string<enums::MediaPlayerState>(enums::Medi
return "MEDIA_PLAYER_STATE_PLAYING";
case enums::MEDIA_PLAYER_STATE_PAUSED:
return "MEDIA_PLAYER_STATE_PAUSED";
case enums::MEDIA_PLAYER_STATE_ANNOUNCING:
return "MEDIA_PLAYER_STATE_ANNOUNCING";
case enums::MEDIA_PLAYER_STATE_OFF:
return "MEDIA_PLAYER_STATE_OFF";
case enums::MEDIA_PLAYER_STATE_ON:
return "MEDIA_PLAYER_STATE_ON";
default:
return "UNKNOWN";
}
@@ -405,24 +399,6 @@ template<> const char *proto_enum_to_string<enums::MediaPlayerCommand>(enums::Me
return "MEDIA_PLAYER_COMMAND_MUTE";
case enums::MEDIA_PLAYER_COMMAND_UNMUTE:
return "MEDIA_PLAYER_COMMAND_UNMUTE";
case enums::MEDIA_PLAYER_COMMAND_TOGGLE:
return "MEDIA_PLAYER_COMMAND_TOGGLE";
case enums::MEDIA_PLAYER_COMMAND_VOLUME_UP:
return "MEDIA_PLAYER_COMMAND_VOLUME_UP";
case enums::MEDIA_PLAYER_COMMAND_VOLUME_DOWN:
return "MEDIA_PLAYER_COMMAND_VOLUME_DOWN";
case enums::MEDIA_PLAYER_COMMAND_ENQUEUE:
return "MEDIA_PLAYER_COMMAND_ENQUEUE";
case enums::MEDIA_PLAYER_COMMAND_REPEAT_ONE:
return "MEDIA_PLAYER_COMMAND_REPEAT_ONE";
case enums::MEDIA_PLAYER_COMMAND_REPEAT_OFF:
return "MEDIA_PLAYER_COMMAND_REPEAT_OFF";
case enums::MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST:
return "MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST";
case enums::MEDIA_PLAYER_COMMAND_TURN_ON:
return "MEDIA_PLAYER_COMMAND_TURN_ON";
case enums::MEDIA_PLAYER_COMMAND_TURN_OFF:
return "MEDIA_PLAYER_COMMAND_TURN_OFF";
default:
return "UNKNOWN";
}
@@ -669,10 +645,8 @@ void HelloResponse::dump_to(std::string &out) const {
dump_field(out, "server_info", this->server_info_ref_);
dump_field(out, "name", this->name_ref_);
}
#ifdef USE_API_PASSWORD
void ConnectRequest::dump_to(std::string &out) const { dump_field(out, "password", this->password); }
void ConnectResponse::dump_to(std::string &out) const { dump_field(out, "invalid_password", this->invalid_password); }
#endif
void DisconnectRequest::dump_to(std::string &out) const { out.append("DisconnectRequest {}"); }
void DisconnectResponse::dump_to(std::string &out) const { out.append("DisconnectResponse {}"); }
void PingRequest::dump_to(std::string &out) const { out.append("PingRequest {}"); }
@@ -840,7 +814,7 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const {
dump_field(out, "icon", this->icon_ref_);
#endif
dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category));
for (const auto &it : *this->supported_preset_modes) {
for (const auto &it : this->supported_preset_modes) {
dump_field(out, "supported_preset_modes", it, 4);
}
#ifdef USE_DEVICES
@@ -883,7 +857,7 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const {
dump_field(out, "object_id", this->object_id_ref_);
dump_field(out, "key", this->key);
dump_field(out, "name", this->name_ref_);
for (const auto &it : *this->supported_color_modes) {
for (const auto &it : this->supported_color_modes) {
dump_field(out, "supported_color_modes", static_cast<enums::ColorMode>(it), 4);
}
dump_field(out, "min_mireds", this->min_mireds);
@@ -1112,11 +1086,7 @@ void HomeAssistantStateResponse::dump_to(std::string &out) const {
}
#endif
void GetTimeRequest::dump_to(std::string &out) const { out.append("GetTimeRequest {}"); }
void GetTimeResponse::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "GetTimeResponse");
dump_field(out, "epoch_seconds", this->epoch_seconds);
dump_field(out, "timezone", this->timezone);
}
void GetTimeResponse::dump_to(std::string &out) const { dump_field(out, "epoch_seconds", this->epoch_seconds); }
#ifdef USE_API_SERVICES
void ListEntitiesServicesArgument::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "ListEntitiesServicesArgument");
@@ -1141,7 +1111,7 @@ void ExecuteServiceArgument::dump_to(std::string &out) const {
dump_field(out, "string_", this->string_);
dump_field(out, "int_", this->int_);
for (const auto it : this->bool_array) {
dump_field(out, "bool_array", static_cast<bool>(it), 4);
dump_field(out, "bool_array", it, 4);
}
for (const auto &it : this->int_array) {
dump_field(out, "int_array", it, 4);
@@ -1203,26 +1173,26 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
dump_field(out, "name", this->name_ref_);
dump_field(out, "supports_current_temperature", this->supports_current_temperature);
dump_field(out, "supports_two_point_target_temperature", this->supports_two_point_target_temperature);
for (const auto &it : *this->supported_modes) {
for (const auto &it : this->supported_modes) {
dump_field(out, "supported_modes", static_cast<enums::ClimateMode>(it), 4);
}
dump_field(out, "visual_min_temperature", this->visual_min_temperature);
dump_field(out, "visual_max_temperature", this->visual_max_temperature);
dump_field(out, "visual_target_temperature_step", this->visual_target_temperature_step);
dump_field(out, "supports_action", this->supports_action);
for (const auto &it : *this->supported_fan_modes) {
for (const auto &it : this->supported_fan_modes) {
dump_field(out, "supported_fan_modes", static_cast<enums::ClimateFanMode>(it), 4);
}
for (const auto &it : *this->supported_swing_modes) {
for (const auto &it : this->supported_swing_modes) {
dump_field(out, "supported_swing_modes", static_cast<enums::ClimateSwingMode>(it), 4);
}
for (const auto &it : *this->supported_custom_fan_modes) {
for (const auto &it : this->supported_custom_fan_modes) {
dump_field(out, "supported_custom_fan_modes", it, 4);
}
for (const auto &it : *this->supported_presets) {
for (const auto &it : this->supported_presets) {
dump_field(out, "supported_presets", static_cast<enums::ClimatePreset>(it), 4);
}
for (const auto &it : *this->supported_custom_presets) {
for (const auto &it : this->supported_custom_presets) {
dump_field(out, "supported_custom_presets", it, 4);
}
dump_field(out, "disabled_by_default", this->disabled_by_default);
@@ -1335,7 +1305,7 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const {
#ifdef USE_ENTITY_ICON
dump_field(out, "icon", this->icon_ref_);
#endif
for (const auto &it : *this->options) {
for (const auto &it : this->options) {
dump_field(out, "options", it, 4);
}
dump_field(out, "disabled_by_default", this->disabled_by_default);
@@ -1496,7 +1466,6 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const {
#ifdef USE_DEVICES
dump_field(out, "device_id", this->device_id);
#endif
dump_field(out, "feature_flags", this->feature_flags);
}
void MediaPlayerStateResponse::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "MediaPlayerStateResponse");
@@ -1540,9 +1509,9 @@ void BluetoothLERawAdvertisement::dump_to(std::string &out) const {
}
void BluetoothLERawAdvertisementsResponse::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "BluetoothLERawAdvertisementsResponse");
for (uint16_t i = 0; i < this->advertisements_len; i++) {
for (const auto &it : this->advertisements) {
out.append(" advertisements: ");
this->advertisements[i].dump_to(out);
it.dump_to(out);
out.append("\n");
}
}
@@ -1567,7 +1536,6 @@ void BluetoothGATTDescriptor::dump_to(std::string &out) const {
dump_field(out, "uuid", it, 4);
}
dump_field(out, "handle", this->handle);
dump_field(out, "short_uuid", this->short_uuid);
}
void BluetoothGATTCharacteristic::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "BluetoothGATTCharacteristic");
@@ -1581,7 +1549,6 @@ void BluetoothGATTCharacteristic::dump_to(std::string &out) const {
it.dump_to(out);
out.append("\n");
}
dump_field(out, "short_uuid", this->short_uuid);
}
void BluetoothGATTService::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "BluetoothGATTService");
@@ -1594,7 +1561,6 @@ void BluetoothGATTService::dump_to(std::string &out) const {
it.dump_to(out);
out.append("\n");
}
dump_field(out, "short_uuid", this->short_uuid);
}
void BluetoothGATTGetServicesResponse::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "BluetoothGATTGetServicesResponse");
@@ -1710,7 +1676,6 @@ void BluetoothScannerStateResponse::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "BluetoothScannerStateResponse");
dump_field(out, "state", static_cast<enums::BluetoothScannerState>(this->state));
dump_field(out, "mode", static_cast<enums::BluetoothScannerMode>(this->mode));
dump_field(out, "configured_mode", static_cast<enums::BluetoothScannerMode>(this->configured_mode));
}
void BluetoothScannerSetModeRequest::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "BluetoothScannerSetModeRequest");
@@ -1804,7 +1769,7 @@ void VoiceAssistantConfigurationResponse::dump_to(std::string &out) const {
it.dump_to(out);
out.append("\n");
}
for (const auto &it : *this->active_wake_words) {
for (const auto &it : this->active_wake_words) {
dump_field(out, "active_wake_words", it, 4);
}
dump_field(out, "max_active_wake_words", this->max_active_wake_words);

View File

@@ -1,34 +0,0 @@
#pragma once
#include "esphome/core/defines.h"
// This file provides includes needed by the generated protobuf code
// when using pointer optimizations for component-specific types
#ifdef USE_CLIMATE
#include "esphome/components/climate/climate_mode.h"
#include "esphome/components/climate/climate_traits.h"
#endif
#ifdef USE_LIGHT
#include "esphome/components/light/light_traits.h"
#endif
#ifdef USE_FAN
#include "esphome/components/fan/fan_traits.h"
#endif
#ifdef USE_SELECT
#include "esphome/components/select/select_traits.h"
#endif
// Standard library includes that might be needed
#include <set>
#include <vector>
#include <string>
namespace esphome::api {
// This file only provides includes, no actual code
} // namespace esphome::api

View File

@@ -24,7 +24,6 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
this->on_hello_request(msg);
break;
}
#ifdef USE_API_PASSWORD
case ConnectRequest::MESSAGE_TYPE: {
ConnectRequest msg;
msg.decode(msg_data, msg_size);
@@ -34,7 +33,6 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
this->on_connect_request(msg);
break;
}
#endif
case DisconnectRequest::MESSAGE_TYPE: {
DisconnectRequest msg;
// Empty message: no decode needed
@@ -162,6 +160,15 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
break;
}
#endif
case GetTimeRequest::MESSAGE_TYPE: {
GetTimeRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_get_time_request: %s", msg.dump().c_str());
#endif
this->on_get_time_request(msg);
break;
}
case GetTimeResponse::MESSAGE_TYPE: {
GetTimeResponse msg;
msg.decode(msg_data, msg_size);
@@ -599,13 +606,11 @@ void APIServerConnection::on_hello_request(const HelloRequest &msg) {
this->on_fatal_error();
}
}
#ifdef USE_API_PASSWORD
void APIServerConnection::on_connect_request(const ConnectRequest &msg) {
if (!this->send_connect_response(msg)) {
this->on_fatal_error();
}
}
#endif
void APIServerConnection::on_disconnect_request(const DisconnectRequest &msg) {
if (!this->send_disconnect_response(msg)) {
this->on_fatal_error();
@@ -651,6 +656,11 @@ void APIServerConnection::on_subscribe_home_assistant_states_request(const Subsc
}
}
#endif
void APIServerConnection::on_get_time_request(const GetTimeRequest &msg) {
if (this->check_connection_setup_() && !this->send_get_time_response(msg)) {
this->on_fatal_error();
}
}
#ifdef USE_API_SERVICES
void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest &msg) {
if (this->check_authenticated_()) {

View File

@@ -26,9 +26,7 @@ class APIServerConnectionBase : public ProtoService {
virtual void on_hello_request(const HelloRequest &value){};
#ifdef USE_API_PASSWORD
virtual void on_connect_request(const ConnectRequest &value){};
#endif
virtual void on_disconnect_request(const DisconnectRequest &value){};
virtual void on_disconnect_response(const DisconnectResponse &value){};
@@ -73,7 +71,7 @@ class APIServerConnectionBase : public ProtoService {
#ifdef USE_API_HOMEASSISTANT_STATES
virtual void on_home_assistant_state_response(const HomeAssistantStateResponse &value){};
#endif
virtual void on_get_time_request(const GetTimeRequest &value){};
virtual void on_get_time_response(const GetTimeResponse &value){};
#ifdef USE_API_SERVICES
@@ -215,9 +213,7 @@ class APIServerConnectionBase : public ProtoService {
class APIServerConnection : public APIServerConnectionBase {
public:
virtual bool send_hello_response(const HelloRequest &msg) = 0;
#ifdef USE_API_PASSWORD
virtual bool send_connect_response(const ConnectRequest &msg) = 0;
#endif
virtual bool send_disconnect_response(const DisconnectRequest &msg) = 0;
virtual bool send_ping_response(const PingRequest &msg) = 0;
virtual bool send_device_info_response(const DeviceInfoRequest &msg) = 0;
@@ -230,6 +226,7 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_API_HOMEASSISTANT_STATES
virtual void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) = 0;
#endif
virtual bool send_get_time_response(const GetTimeRequest &msg) = 0;
#ifdef USE_API_SERVICES
virtual void execute_service(const ExecuteServiceRequest &msg) = 0;
#endif
@@ -338,9 +335,7 @@ class APIServerConnection : public APIServerConnectionBase {
#endif
protected:
void on_hello_request(const HelloRequest &msg) override;
#ifdef USE_API_PASSWORD
void on_connect_request(const ConnectRequest &msg) override;
#endif
void on_disconnect_request(const DisconnectRequest &msg) override;
void on_ping_request(const PingRequest &msg) override;
void on_device_info_request(const DeviceInfoRequest &msg) override;
@@ -353,6 +348,7 @@ class APIServerConnection : public APIServerConnectionBase {
#ifdef USE_API_HOMEASSISTANT_STATES
void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) override;
#endif
void on_get_time_request(const GetTimeRequest &msg) override;
#ifdef USE_API_SERVICES
void on_execute_service_request(const ExecuteServiceRequest &msg) override;
#endif

View File

@@ -30,7 +30,7 @@ if TYPE_CHECKING:
_LOGGER = logging.getLogger(__name__)
async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None:
async def async_run_logs(config: dict[str, Any], address: str) -> None:
"""Run the logs command in the event loop."""
conf = config["api"]
name = config["esphome"]["name"]
@@ -39,21 +39,13 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None:
noise_psk: str | None = None
if (encryption := conf.get(CONF_ENCRYPTION)) and (key := encryption.get(CONF_KEY)):
noise_psk = key
if len(addresses) == 1:
_LOGGER.info("Starting log output from %s using esphome API", addresses[0])
else:
_LOGGER.info(
"Starting log output from %s using esphome API", " or ".join(addresses)
)
_LOGGER.info("Starting log output from %s using esphome API", address)
cli = APIClient(
addresses[0], # Primary address for compatibility
address,
port,
password,
client_info=f"ESPHome Logs {__version__}",
noise_psk=noise_psk,
addresses=addresses, # Pass all addresses for automatic retry
)
dashboard = CORE.dashboard
@@ -62,11 +54,9 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None:
time_ = datetime.now()
message: bytes = msg.message
text = message.decode("utf8", "backslashreplace")
nanoseconds = time_.microsecond // 1000
timestamp = (
f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}.{nanoseconds:03}]"
)
for parsed_msg in parse_log_message(text, timestamp):
for parsed_msg in parse_log_message(
text, f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}]"
):
print(parsed_msg.replace("\033", "\\033") if dashboard else parsed_msg)
stop = await async_run(cli, on_log, name=name)
@@ -76,7 +66,7 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None:
await stop()
def run_logs(config: dict[str, Any], addresses: list[str]) -> None:
def run_logs(config: dict[str, Any], address: str) -> None:
"""Run the logs command."""
with contextlib.suppress(KeyboardInterrupt):
asyncio.run(async_run_logs(config, addresses))
asyncio.run(async_run_logs(config, address))

View File

@@ -56,14 +56,6 @@ class CustomAPIDevice {
auto *service = new CustomAPIDeviceService<T, Ts...>(name, arg_names, (T *) this, callback); // NOLINT
global_api_server->register_user_service(service);
}
#else
template<typename T, typename... Ts>
void register_service(void (T::*callback)(Ts...), const std::string &name,
const std::array<std::string, sizeof...(Ts)> &arg_names) {
static_assert(
sizeof(T) == 0,
"register_service() requires 'custom_services: true' in the 'api:' section of your YAML configuration");
}
#endif
/** Register a custom native API service that will show up in Home Assistant.
@@ -89,12 +81,6 @@ class CustomAPIDevice {
auto *service = new CustomAPIDeviceService<T>(name, {}, (T *) this, callback); // NOLINT
global_api_server->register_user_service(service);
}
#else
template<typename T> void register_service(void (T::*callback)(), const std::string &name) {
static_assert(
sizeof(T) == 0,
"register_service() requires 'custom_services: true' in the 'api:' section of your YAML configuration");
}
#endif
#ifdef USE_API_HOMEASSISTANT_STATES
@@ -149,22 +135,6 @@ class CustomAPIDevice {
auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1);
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), f);
}
#else
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
const std::string &attribute = "") {
static_assert(sizeof(T) == 0,
"subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
"of your YAML configuration");
}
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
const std::string &attribute = "") {
static_assert(sizeof(T) == 0,
"subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
"of your YAML configuration");
}
#endif
#ifdef USE_API_HOMEASSISTANT_SERVICES
@@ -252,28 +222,6 @@ class CustomAPIDevice {
}
global_api_server->send_homeassistant_service_call(resp);
}
#else
template<typename T = void> void call_homeassistant_service(const std::string &service_name) {
static_assert(sizeof(T) == 0, "call_homeassistant_service() requires 'homeassistant_services: true' in the 'api:' "
"section of your YAML configuration");
}
template<typename T = void>
void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
static_assert(sizeof(T) == 0, "call_homeassistant_service() requires 'homeassistant_services: true' in the 'api:' "
"section of your YAML configuration");
}
template<typename T = void> void fire_homeassistant_event(const std::string &event_name) {
static_assert(sizeof(T) == 0, "fire_homeassistant_event() requires 'homeassistant_services: true' in the 'api:' "
"section of your YAML configuration");
}
template<typename T = void>
void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
static_assert(sizeof(T) == 0, "fire_homeassistant_event() requires 'homeassistant_services: true' in the 'api:' "
"section of your YAML configuration");
}
#endif
};

View File

@@ -8,70 +8,74 @@ namespace esphome::api {
static const char *const TAG = "api.proto";
void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) {
const uint8_t *ptr = buffer;
const uint8_t *end = buffer + length;
while (ptr < end) {
uint32_t i = 0;
bool error = false;
while (i < length) {
uint32_t consumed;
// Parse field header
auto res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
auto res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
if (!res.has_value()) {
ESP_LOGV(TAG, "Invalid field start at offset %ld", (long) (ptr - buffer));
return;
ESP_LOGV(TAG, "Invalid field start at %" PRIu32, i);
break;
}
uint32_t tag = res->as_uint32();
uint32_t field_type = tag & 0b111;
uint32_t field_id = tag >> 3;
ptr += consumed;
uint32_t field_type = (res->as_uint32()) & 0b111;
uint32_t field_id = (res->as_uint32()) >> 3;
i += consumed;
switch (field_type) {
case 0: { // VarInt
res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
if (!res.has_value()) {
ESP_LOGV(TAG, "Invalid VarInt at offset %ld", (long) (ptr - buffer));
return;
ESP_LOGV(TAG, "Invalid VarInt at %" PRIu32, i);
error = true;
break;
}
if (!this->decode_varint(field_id, *res)) {
ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu32 "!", field_id, res->as_uint32());
}
ptr += consumed;
i += consumed;
break;
}
case 2: { // Length-delimited
res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
if (!res.has_value()) {
ESP_LOGV(TAG, "Invalid Length Delimited at offset %ld", (long) (ptr - buffer));
return;
ESP_LOGV(TAG, "Invalid Length Delimited at %" PRIu32, i);
error = true;
break;
}
uint32_t field_length = res->as_uint32();
ptr += consumed;
if (ptr + field_length > end) {
ESP_LOGV(TAG, "Out-of-bounds Length Delimited at offset %ld", (long) (ptr - buffer));
return;
i += consumed;
if (field_length > length - i) {
ESP_LOGV(TAG, "Out-of-bounds Length Delimited at %" PRIu32, i);
error = true;
break;
}
if (!this->decode_length(field_id, ProtoLengthDelimited(ptr, field_length))) {
if (!this->decode_length(field_id, ProtoLengthDelimited(&buffer[i], field_length))) {
ESP_LOGV(TAG, "Cannot decode Length Delimited field %" PRIu32 "!", field_id);
}
ptr += field_length;
i += field_length;
break;
}
case 5: { // 32-bit
if (ptr + 4 > end) {
ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at offset %ld", (long) (ptr - buffer));
return;
if (length - i < 4) {
ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at %" PRIu32, i);
error = true;
break;
}
uint32_t val = encode_uint32(ptr[3], ptr[2], ptr[1], ptr[0]);
uint32_t val = encode_uint32(buffer[i + 3], buffer[i + 2], buffer[i + 1], buffer[i]);
if (!this->decode_32bit(field_id, Proto32Bit(val))) {
ESP_LOGV(TAG, "Cannot decode 32-bit field %" PRIu32 " with value %" PRIu32 "!", field_id, val);
}
ptr += 4;
i += 4;
break;
}
default:
ESP_LOGV(TAG, "Invalid field type %u at offset %ld", field_type, (long) (ptr - buffer));
return;
ESP_LOGV(TAG, "Invalid field type at %" PRIu32, i);
error = true;
break;
}
if (error) {
break;
}
}
}

View File

@@ -15,23 +15,6 @@
namespace esphome::api {
// Helper functions for ZigZag encoding/decoding
inline constexpr uint32_t encode_zigzag32(int32_t value) {
return (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31));
}
inline constexpr uint64_t encode_zigzag64(int64_t value) {
return (static_cast<uint64_t>(value) << 1) ^ (static_cast<uint64_t>(value >> 63));
}
inline constexpr int32_t decode_zigzag32(uint32_t value) {
return (value & 1) ? static_cast<int32_t>(~(value >> 1)) : static_cast<int32_t>(value >> 1);
}
inline constexpr int64_t decode_zigzag64(uint64_t value) {
return (value & 1) ? static_cast<int64_t>(~(value >> 1)) : static_cast<int64_t>(value >> 1);
}
/*
* StringRef Ownership Model for API Protocol Messages
* ===================================================
@@ -104,25 +87,33 @@ class ProtoVarInt {
return {}; // Incomplete or invalid varint
}
constexpr uint16_t as_uint16() const { return this->value_; }
constexpr uint32_t as_uint32() const { return this->value_; }
constexpr uint64_t as_uint64() const { return this->value_; }
constexpr bool as_bool() const { return this->value_; }
constexpr int32_t as_int32() const {
uint16_t as_uint16() const { return this->value_; }
uint32_t as_uint32() const { return this->value_; }
uint64_t as_uint64() const { return this->value_; }
bool as_bool() const { return this->value_; }
int32_t as_int32() const {
// Not ZigZag encoded
return static_cast<int32_t>(this->as_int64());
}
constexpr int64_t as_int64() const {
int64_t as_int64() const {
// Not ZigZag encoded
return static_cast<int64_t>(this->value_);
}
constexpr int32_t as_sint32() const {
int32_t as_sint32() const {
// with ZigZag encoding
return decode_zigzag32(static_cast<uint32_t>(this->value_));
if (this->value_ & 1) {
return static_cast<int32_t>(~(this->value_ >> 1));
} else {
return static_cast<int32_t>(this->value_ >> 1);
}
}
constexpr int64_t as_sint64() const {
int64_t as_sint64() const {
// with ZigZag encoding
return decode_zigzag64(this->value_);
if (this->value_ & 1) {
return static_cast<int64_t>(~(this->value_ >> 1));
} else {
return static_cast<int64_t>(this->value_ >> 1);
}
}
/**
* Encode the varint value to a pre-allocated buffer without bounds checking.
@@ -318,10 +309,22 @@ class ProtoWriteBuffer {
this->encode_uint64(field_id, static_cast<uint64_t>(value), force);
}
void encode_sint32(uint32_t field_id, int32_t value, bool force = false) {
this->encode_uint32(field_id, encode_zigzag32(value), force);
uint32_t uvalue;
if (value < 0) {
uvalue = ~(value << 1);
} else {
uvalue = value << 1;
}
this->encode_uint32(field_id, uvalue, force);
}
void encode_sint64(uint32_t field_id, int64_t value, bool force = false) {
this->encode_uint64(field_id, encode_zigzag64(value), force);
uint64_t uvalue;
if (value < 0) {
uvalue = ~(value << 1);
} else {
uvalue = value << 1;
}
this->encode_uint64(field_id, uvalue, force);
}
void encode_message(uint32_t field_id, const ProtoMessage &value, bool force = false);
std::vector<uint8_t> *get_buffer() const { return buffer_; }
@@ -392,7 +395,7 @@ class ProtoSize {
* @param value The uint32_t value to calculate size for
* @return The number of bytes needed to encode the value
*/
static constexpr uint32_t varint(uint32_t value) {
static inline uint32_t varint(uint32_t value) {
// Optimized varint size calculation using leading zeros
// Each 7 bits requires one byte in the varint encoding
if (value < 128)
@@ -416,7 +419,7 @@ class ProtoSize {
* @param value The uint64_t value to calculate size for
* @return The number of bytes needed to encode the value
*/
static constexpr uint32_t varint(uint64_t value) {
static inline uint32_t varint(uint64_t value) {
// Handle common case of values fitting in uint32_t (vast majority of use cases)
if (value <= UINT32_MAX) {
return varint(static_cast<uint32_t>(value));
@@ -447,7 +450,7 @@ class ProtoSize {
* @param value The int32_t value to calculate size for
* @return The number of bytes needed to encode the value
*/
static constexpr uint32_t varint(int32_t value) {
static inline uint32_t varint(int32_t value) {
// Negative values are sign-extended to 64 bits in protocol buffers,
// which always results in a 10-byte varint for negative int32
if (value < 0) {
@@ -463,7 +466,7 @@ class ProtoSize {
* @param value The int64_t value to calculate size for
* @return The number of bytes needed to encode the value
*/
static constexpr uint32_t varint(int64_t value) {
static inline uint32_t varint(int64_t value) {
// For int64_t, we convert to uint64_t and calculate the size
// This works because the bit pattern determines the encoding size,
// and we've handled negative int32 values as a special case above
@@ -477,7 +480,7 @@ class ProtoSize {
* @param type The wire type value (from the WireType enum in the protobuf spec)
* @return The number of bytes needed to encode the field ID and wire type
*/
static constexpr uint32_t field(uint32_t field_id, uint32_t type) {
static inline uint32_t field(uint32_t field_id, uint32_t type) {
uint32_t tag = (field_id << 3) | (type & 0b111);
return varint(tag);
}
@@ -604,8 +607,9 @@ class ProtoSize {
*/
inline void add_sint32_force(uint32_t field_id_size, int32_t value) {
// Always calculate size when force is true
// ZigZag encoding for sint32
total_size_ += field_id_size + varint(encode_zigzag32(value));
// ZigZag encoding for sint32: (n << 1) ^ (n >> 31)
uint32_t zigzag = (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31));
total_size_ += field_id_size + varint(zigzag);
}
/**

View File

@@ -7,7 +7,6 @@ from esphome.const import (
CONF_DIRECTION,
CONF_HYSTERESIS,
CONF_ID,
CONF_POWER_MODE,
CONF_RANGE,
)
@@ -58,6 +57,7 @@ FAST_FILTER = {
CONF_RAW_ANGLE = "raw_angle"
CONF_RAW_POSITION = "raw_position"
CONF_WATCHDOG = "watchdog"
CONF_POWER_MODE = "power_mode"
CONF_SLOW_FILTER = "slow_filter"
CONF_FAST_FILTER = "fast_filter"
CONF_START_POSITION = "start_position"

View File

@@ -24,6 +24,7 @@ AS5600Sensor = as5600_ns.class_("AS5600Sensor", sensor.Sensor, cg.PollingCompone
CONF_RAW_ANGLE = "raw_angle"
CONF_RAW_POSITION = "raw_position"
CONF_WATCHDOG = "watchdog"
CONF_POWER_MODE = "power_mode"
CONF_SLOW_FILTER = "slow_filter"
CONF_FAST_FILTER = "fast_filter"
CONF_PWM_FREQUENCY = "pwm_frequency"

View File

@@ -8,9 +8,9 @@ from esphome.const import (
PLATFORM_LN882X,
PLATFORM_RTL87XX,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core import CORE, coroutine_with_priority
CODEOWNERS = ["@esphome/core"]
CODEOWNERS = ["@OttoWinter"]
CONFIG_SCHEMA = cv.All(
cv.Schema({}),
@@ -27,7 +27,7 @@ CONFIG_SCHEMA = cv.All(
)
@coroutine_with_priority(CoroPriority.NETWORK_TRANSPORT)
@coroutine_with_priority(200.0)
async def to_code(config):
if CORE.is_esp32 or CORE.is_libretiny:
# https://github.com/ESP32Async/AsyncTCP

View File

@@ -16,7 +16,6 @@ from esphome.const import (
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_POWER,
DEVICE_CLASS_POWER_FACTOR,
DEVICE_CLASS_REACTIVE_POWER,
DEVICE_CLASS_VOLTAGE,
ICON_CURRENT_AC,
ICON_LIGHTBULB,
@@ -79,7 +78,6 @@ CONFIG_SCHEMA = (
unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
icon=ICON_LIGHTBULB,
accuracy_decimals=2,
device_class=DEVICE_CLASS_REACTIVE_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema(

View File

@@ -110,8 +110,6 @@ void ATM90E32Component::update() {
void ATM90E32Component::setup() {
this->spi_setup();
this->cs_summary_ = this->cs_->dump_summary();
const char *cs = this->cs_summary_.c_str();
uint16_t mmode0 = 0x87; // 3P4W 50Hz
uint16_t high_thresh = 0;
@@ -132,9 +130,9 @@ void ATM90E32Component::setup() {
mmode0 |= 0 << 1; // sets 1st bit to 0, phase b is not counted into the all-phase sum energy/power (P/Q/S)
}
this->write16_(ATM90E32_REGISTER_SOFTRESET, 0x789A, false); // Perform soft reset
delay(6); // Wait for the minimum 5ms + 1ms
this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x55AA); // enable register config access
this->write16_(ATM90E32_REGISTER_SOFTRESET, 0x789A); // Perform soft reset
delay(6); // Wait for the minimum 5ms + 1ms
this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x55AA); // enable register config access
if (!this->validate_spi_read_(0x55AA, "setup()")) {
ESP_LOGW(TAG, "Could not initialize ATM90E32 IC, check SPI settings");
this->mark_failed();
@@ -158,17 +156,16 @@ void ATM90E32Component::setup() {
if (this->enable_offset_calibration_) {
// Initialize flash storage for offset calibrations
uint32_t o_hash = fnv1_hash(std::string("_offset_calibration_") + this->cs_summary_);
uint32_t o_hash = fnv1_hash(std::string("_offset_calibration_") + this->cs_->dump_summary());
this->offset_pref_ = global_preferences->make_preference<OffsetCalibration[3]>(o_hash, true);
this->restore_offset_calibrations_();
// Initialize flash storage for power offset calibrations
uint32_t po_hash = fnv1_hash(std::string("_power_offset_calibration_") + this->cs_summary_);
uint32_t po_hash = fnv1_hash(std::string("_power_offset_calibration_") + this->cs_->dump_summary());
this->power_offset_pref_ = global_preferences->make_preference<PowerOffsetCalibration[3]>(po_hash, true);
this->restore_power_offset_calibrations_();
} else {
ESP_LOGI(TAG, "[CALIBRATION][%s] Power & Voltage/Current offset calibration is disabled. Using config file values.",
cs);
ESP_LOGI(TAG, "[CALIBRATION] Power & Voltage/Current offset calibration is disabled. Using config file values.");
for (uint8_t phase = 0; phase < 3; ++phase) {
this->write16_(this->voltage_offset_registers[phase],
static_cast<uint16_t>(this->offset_phase_[phase].voltage_offset_));
@@ -183,18 +180,21 @@ void ATM90E32Component::setup() {
if (this->enable_gain_calibration_) {
// Initialize flash storage for gain calibration
uint32_t g_hash = fnv1_hash(std::string("_gain_calibration_") + this->cs_summary_);
uint32_t g_hash = fnv1_hash(std::string("_gain_calibration_") + this->cs_->dump_summary());
this->gain_calibration_pref_ = global_preferences->make_preference<GainCalibration[3]>(g_hash, true);
this->restore_gain_calibrations_();
if (!this->using_saved_calibrations_) {
if (this->using_saved_calibrations_) {
ESP_LOGI(TAG, "[CALIBRATION] Successfully restored gain calibration from memory.");
} else {
for (uint8_t phase = 0; phase < 3; ++phase) {
this->write16_(voltage_gain_registers[phase], this->phase_[phase].voltage_gain_);
this->write16_(current_gain_registers[phase], this->phase_[phase].ct_gain_);
}
}
} else {
ESP_LOGI(TAG, "[CALIBRATION][%s] Gain calibration is disabled. Using config file values.", cs);
ESP_LOGI(TAG, "[CALIBRATION] Gain calibration is disabled. Using config file values.");
for (uint8_t phase = 0; phase < 3; ++phase) {
this->write16_(voltage_gain_registers[phase], this->phase_[phase].voltage_gain_);
this->write16_(current_gain_registers[phase], this->phase_[phase].ct_gain_);
@@ -213,122 +213,6 @@ void ATM90E32Component::setup() {
this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x0000); // end configuration
}
void ATM90E32Component::log_calibration_status_() {
const char *cs = this->cs_summary_.c_str();
bool offset_mismatch = false;
bool power_mismatch = false;
bool gain_mismatch = false;
for (uint8_t phase = 0; phase < 3; ++phase) {
offset_mismatch |= this->offset_calibration_mismatch_[phase];
power_mismatch |= this->power_offset_calibration_mismatch_[phase];
gain_mismatch |= this->gain_calibration_mismatch_[phase];
}
if (offset_mismatch) {
ESP_LOGW(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGW(TAG,
"[CALIBRATION][%s] ===================== Offset mismatch: using flash values =====================", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] | | config | flash | config | flash |", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
cs);
for (uint8_t phase = 0; phase < 3; ++phase) {
ESP_LOGW(TAG, "[CALIBRATION][%s] | %c | %6d | %6d | %6d | %6d |", cs, 'A' + phase,
this->config_offset_phase_[phase].voltage_offset_, this->offset_phase_[phase].voltage_offset_,
this->config_offset_phase_[phase].current_offset_, this->offset_phase_[phase].current_offset_);
}
ESP_LOGW(TAG,
"[CALIBRATION][%s] ===============================================================================", cs);
}
if (power_mismatch) {
ESP_LOGW(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGW(TAG,
"[CALIBRATION][%s] ================= Power offset mismatch: using flash values =================", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] | Phase | offset_active_power|offset_reactive_power|", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] | | config | flash | config | flash |", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
cs);
for (uint8_t phase = 0; phase < 3; ++phase) {
ESP_LOGW(TAG, "[CALIBRATION][%s] | %c | %6d | %6d | %6d | %6d |", cs, 'A' + phase,
this->config_power_offset_phase_[phase].active_power_offset,
this->power_offset_phase_[phase].active_power_offset,
this->config_power_offset_phase_[phase].reactive_power_offset,
this->power_offset_phase_[phase].reactive_power_offset);
}
ESP_LOGW(TAG,
"[CALIBRATION][%s] ===============================================================================", cs);
}
if (gain_mismatch) {
ESP_LOGW(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGW(TAG,
"[CALIBRATION][%s] ====================== Gain mismatch: using flash values =====================", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] | Phase | voltage_gain | current_gain |", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] | | config | flash | config | flash |", cs);
ESP_LOGW(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------------------",
cs);
for (uint8_t phase = 0; phase < 3; ++phase) {
ESP_LOGW(TAG, "[CALIBRATION][%s] | %c | %6u | %6u | %6u | %6u |", cs, 'A' + phase,
this->config_gain_phase_[phase].voltage_gain, this->gain_phase_[phase].voltage_gain,
this->config_gain_phase_[phase].current_gain, this->gain_phase_[phase].current_gain);
}
ESP_LOGW(TAG,
"[CALIBRATION][%s] ===============================================================================", cs);
}
if (!this->enable_offset_calibration_) {
ESP_LOGI(TAG, "[CALIBRATION][%s] Power & Voltage/Current offset calibration is disabled. Using config file values.",
cs);
} else if (this->restored_offset_calibration_ && !offset_mismatch) {
ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ============== Restored offset calibration from memory ==============", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; phase++) {
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase,
this->offset_phase_[phase].voltage_offset_, this->offset_phase_[phase].current_offset_);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] ==============================================================\\n", cs);
}
if (this->restored_power_offset_calibration_ && !power_mismatch) {
ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ============ Restored power offset calibration from memory ============", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_active_power | offset_reactive_power |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; phase++) {
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase,
this->power_offset_phase_[phase].active_power_offset,
this->power_offset_phase_[phase].reactive_power_offset);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
}
if (!this->enable_gain_calibration_) {
ESP_LOGI(TAG, "[CALIBRATION][%s] Gain calibration is disabled. Using config file values.", cs);
} else if (this->restored_gain_calibration_ && !gain_mismatch) {
ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ============ Restoring saved gain calibrations to registers ============", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | voltage_gain | current_gain |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; phase++) {
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6u | %6u |", cs, 'A' + phase,
this->gain_phase_[phase].voltage_gain, this->gain_phase_[phase].current_gain);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\\n", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] Gain calibration loaded and verified successfully.\n", cs);
}
this->calibration_message_printed_ = true;
}
void ATM90E32Component::dump_config() {
ESP_LOGCONFIG("", "ATM90E32:");
LOG_PIN(" CS Pin: ", this->cs_);
@@ -371,10 +255,6 @@ void ATM90E32Component::dump_config() {
LOG_SENSOR(" ", "Peak Current C", this->phase_[PHASEC].peak_current_sensor_);
LOG_SENSOR(" ", "Frequency", this->freq_sensor_);
LOG_SENSOR(" ", "Chip Temp", this->chip_temperature_sensor_);
if (this->restored_offset_calibration_ || this->restored_power_offset_calibration_ ||
this->restored_gain_calibration_ || !this->enable_offset_calibration_ || !this->enable_gain_calibration_) {
this->log_calibration_status_();
}
}
float ATM90E32Component::get_setup_priority() const { return setup_priority::IO; }
@@ -383,17 +263,19 @@ float ATM90E32Component::get_setup_priority() const { return setup_priority::IO;
// Peakdetect period: 05H. Bit 15:8 are PeakDet_period in ms. 7:0 are Sag_period
// Default is 143FH (20ms, 63ms)
uint16_t ATM90E32Component::read16_(uint16_t a_register) {
this->enable();
delay_microseconds_safe(1); // min delay between CS low and first SCK is 200ns - 1us is plenty
uint8_t addrh = (1 << 7) | ((a_register >> 8) & 0x03);
uint8_t addrl = (a_register & 0xFF);
uint8_t data[4] = {addrh, addrl, 0x00, 0x00};
this->transfer_array(data, 4);
uint16_t output = encode_uint16(data[2], data[3]);
ESP_LOGVV(TAG, "read16_ 0x%04" PRIX16 " output 0x%04" PRIX16, a_register, output);
delay_microseconds_safe(1); // allow the last clock to propagate before releasing CS
uint8_t data[2];
uint16_t output;
this->enable();
delay_microseconds_safe(1); // min delay between CS low and first SCK is 200ns - 1ms is plenty
this->write_byte(addrh);
this->write_byte(addrl);
this->read_array(data, 2);
this->disable();
delay_microseconds_safe(1); // meet minimum CS high time before next transaction
output = (uint16_t(data[0] & 0xFF) << 8) | (data[1] & 0xFF);
ESP_LOGVV(TAG, "read16_ 0x%04" PRIX16 " output 0x%04" PRIX16, a_register, output);
return output;
}
@@ -410,19 +292,13 @@ int ATM90E32Component::read32_(uint16_t addr_h, uint16_t addr_l) {
return val;
}
void ATM90E32Component::write16_(uint16_t a_register, uint16_t val, bool validate) {
void ATM90E32Component::write16_(uint16_t a_register, uint16_t val) {
ESP_LOGVV(TAG, "write16_ 0x%04" PRIX16 " val 0x%04" PRIX16, a_register, val);
uint8_t addrh = ((a_register >> 8) & 0x03);
uint8_t addrl = (a_register & 0xFF);
uint8_t data[4] = {addrh, addrl, uint8_t((val >> 8) & 0xFF), uint8_t(val & 0xFF)};
this->enable();
delay_microseconds_safe(1); // ensure CS setup time
this->write_array(data, 4);
delay_microseconds_safe(1); // allow clock to settle before raising CS
this->write_byte16(a_register);
this->write_byte16(val);
this->disable();
delay_microseconds_safe(1); // ensure minimum CS high time
if (validate)
this->validate_spi_read_(val, "write16()");
this->validate_spi_read_(val, "write16()");
}
float ATM90E32Component::get_local_phase_voltage_(uint8_t phase) { return this->phase_[phase].voltage_; }
@@ -565,10 +441,8 @@ float ATM90E32Component::get_chip_temperature_() {
}
void ATM90E32Component::run_gain_calibrations() {
const char *cs = this->cs_summary_.c_str();
if (!this->enable_gain_calibration_) {
ESP_LOGW(TAG, "[CALIBRATION][%s] Gain calibration is disabled! Enable it first with enable_gain_calibration: true",
cs);
ESP_LOGW(TAG, "[CALIBRATION] Gain calibration is disabled! Enable it first with enable_gain_calibration: true");
return;
}
@@ -580,14 +454,12 @@ void ATM90E32Component::run_gain_calibrations() {
float ref_currents[3] = {this->get_reference_current(0), this->get_reference_current(1),
this->get_reference_current(2)};
ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ========================= Gain Calibration =========================", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
ESP_LOGI(
TAG,
"[CALIBRATION][%s] | Phase | V_meas (V) | I_meas (A) | V_ref | I_ref | V_gain (old→new) | I_gain (old→new) |",
cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION] ");
ESP_LOGI(TAG, "[CALIBRATION] ========================= Gain Calibration =========================");
ESP_LOGI(TAG, "[CALIBRATION] ---------------------------------------------------------------------");
ESP_LOGI(TAG,
"[CALIBRATION] | Phase | V_meas (V) | I_meas (A) | V_ref | I_ref | V_gain (old→new) | I_gain (old→new) |");
ESP_LOGI(TAG, "[CALIBRATION] ---------------------------------------------------------------------");
for (uint8_t phase = 0; phase < 3; phase++) {
float measured_voltage = this->get_phase_voltage_avg_(phase);
@@ -604,22 +476,22 @@ void ATM90E32Component::run_gain_calibrations() {
// Voltage calibration
if (ref_voltage <= 0.0f) {
ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping voltage calibration: reference voltage is 0.", cs,
ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Skipping voltage calibration: reference voltage is 0.",
phase_labels[phase]);
} else if (measured_voltage == 0.0f) {
ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping voltage calibration: measured voltage is 0.", cs,
ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Skipping voltage calibration: measured voltage is 0.",
phase_labels[phase]);
} else {
uint32_t new_voltage_gain = static_cast<uint16_t>((ref_voltage / measured_voltage) * current_voltage_gain);
if (new_voltage_gain == 0) {
ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Voltage gain would be 0. Check reference and measured voltage.", cs,
ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Voltage gain would be 0. Check reference and measured voltage.",
phase_labels[phase]);
} else {
if (new_voltage_gain >= 65535) {
ESP_LOGW(TAG,
"[CALIBRATION][%s] Phase %s - Voltage gain exceeds 65535. You may need a higher output voltage "
"transformer.",
cs, phase_labels[phase]);
ESP_LOGW(
TAG,
"[CALIBRATION] Phase %s - Voltage gain exceeds 65535. You may need a higher output voltage transformer.",
phase_labels[phase]);
new_voltage_gain = 65535;
}
this->gain_phase_[phase].voltage_gain = static_cast<uint16_t>(new_voltage_gain);
@@ -629,20 +501,20 @@ void ATM90E32Component::run_gain_calibrations() {
// Current calibration
if (ref_current == 0.0f) {
ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping current calibration: reference current is 0.", cs,
ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Skipping current calibration: reference current is 0.",
phase_labels[phase]);
} else if (measured_current == 0.0f) {
ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping current calibration: measured current is 0.", cs,
ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Skipping current calibration: measured current is 0.",
phase_labels[phase]);
} else {
uint32_t new_current_gain = static_cast<uint16_t>((ref_current / measured_current) * current_current_gain);
if (new_current_gain == 0) {
ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Current gain would be 0. Check reference and measured current.", cs,
ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Current gain would be 0. Check reference and measured current.",
phase_labels[phase]);
} else {
if (new_current_gain >= 65535) {
ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Current gain exceeds 65535. You may need to turn up pga gain.",
cs, phase_labels[phase]);
ESP_LOGW(TAG, "[CALIBRATION] Phase %s - Current gain exceeds 65535. You may need to turn up pga gain.",
phase_labels[phase]);
new_current_gain = 65535;
}
this->gain_phase_[phase].current_gain = static_cast<uint16_t>(new_current_gain);
@@ -651,13 +523,13 @@ void ATM90E32Component::run_gain_calibrations() {
}
// Final row output
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %9.2f | %9.4f | %5.2f | %6.4f | %5u → %-5u | %5u → %-5u |", cs,
ESP_LOGI(TAG, "[CALIBRATION] | %c | %9.2f | %9.4f | %5.2f | %6.4f | %5u → %-5u | %5u → %-5u |",
'A' + phase, measured_voltage, measured_current, ref_voltage, ref_current, current_voltage_gain,
did_voltage ? this->gain_phase_[phase].voltage_gain : current_voltage_gain, current_current_gain,
did_current ? this->gain_phase_[phase].current_gain : current_current_gain);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
ESP_LOGI(TAG, "[CALIBRATION] =====================================================================\n");
this->save_gain_calibration_to_memory_();
this->write_gains_to_registers_();
@@ -665,108 +537,54 @@ void ATM90E32Component::run_gain_calibrations() {
}
void ATM90E32Component::save_gain_calibration_to_memory_() {
const char *cs = this->cs_summary_.c_str();
bool success = this->gain_calibration_pref_.save(&this->gain_phase_);
global_preferences->sync();
if (success) {
this->using_saved_calibrations_ = true;
ESP_LOGI(TAG, "[CALIBRATION][%s] Gain calibration saved to memory.", cs);
ESP_LOGI(TAG, "[CALIBRATION] Gain calibration saved to memory.");
} else {
this->using_saved_calibrations_ = false;
ESP_LOGE(TAG, "[CALIBRATION][%s] Failed to save gain calibration to memory!", cs);
}
}
void ATM90E32Component::save_offset_calibration_to_memory_() {
const char *cs = this->cs_summary_.c_str();
bool success = this->offset_pref_.save(&this->offset_phase_);
global_preferences->sync();
if (success) {
this->using_saved_calibrations_ = true;
this->restored_offset_calibration_ = true;
for (bool &phase : this->offset_calibration_mismatch_)
phase = false;
ESP_LOGI(TAG, "[CALIBRATION][%s] Offset calibration saved to memory.", cs);
} else {
this->using_saved_calibrations_ = false;
ESP_LOGE(TAG, "[CALIBRATION][%s] Failed to save offset calibration to memory!", cs);
}
}
void ATM90E32Component::save_power_offset_calibration_to_memory_() {
const char *cs = this->cs_summary_.c_str();
bool success = this->power_offset_pref_.save(&this->power_offset_phase_);
global_preferences->sync();
if (success) {
this->using_saved_calibrations_ = true;
this->restored_power_offset_calibration_ = true;
for (bool &phase : this->power_offset_calibration_mismatch_)
phase = false;
ESP_LOGI(TAG, "[CALIBRATION][%s] Power offset calibration saved to memory.", cs);
} else {
this->using_saved_calibrations_ = false;
ESP_LOGE(TAG, "[CALIBRATION][%s] Failed to save power offset calibration to memory!", cs);
ESP_LOGE(TAG, "[CALIBRATION] Failed to save gain calibration to memory!");
}
}
void ATM90E32Component::run_offset_calibrations() {
const char *cs = this->cs_summary_.c_str();
if (!this->enable_offset_calibration_) {
ESP_LOGW(TAG,
"[CALIBRATION][%s] Offset calibration is disabled! Enable it first with enable_offset_calibration: true",
cs);
ESP_LOGW(TAG, "[CALIBRATION] Offset calibration is disabled! Enable it first with enable_offset_calibration: true");
return;
}
ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ======================== Offset Calibration ========================", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ------------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; phase++) {
int16_t voltage_offset = calibrate_offset(phase, true);
int16_t current_offset = calibrate_offset(phase, false);
this->write_offsets_to_registers_(phase, voltage_offset, current_offset);
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase, voltage_offset,
ESP_LOGI(TAG, "[CALIBRATION] Phase %c - offset_voltage: %d, offset_current: %d", 'A' + phase, voltage_offset,
current_offset);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] ==================================================================\n", cs);
this->save_offset_calibration_to_memory_();
this->offset_pref_.save(&this->offset_phase_); // Save to flash
}
void ATM90E32Component::run_power_offset_calibrations() {
const char *cs = this->cs_summary_.c_str();
if (!this->enable_offset_calibration_) {
ESP_LOGW(
TAG,
"[CALIBRATION][%s] Offset power calibration is disabled! Enable it first with enable_offset_calibration: true",
cs);
"[CALIBRATION] Offset power calibration is disabled! Enable it first with enable_offset_calibration: true");
return;
}
ESP_LOGI(TAG, "[CALIBRATION][%s] ", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ===================== Power Offset Calibration =====================", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_active_power | offset_reactive_power |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; ++phase) {
int16_t active_offset = calibrate_power_offset(phase, false);
int16_t reactive_offset = calibrate_power_offset(phase, true);
this->write_power_offsets_to_registers_(phase, active_offset, reactive_offset);
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase, active_offset,
reactive_offset);
ESP_LOGI(TAG, "[CALIBRATION] Phase %c - offset_active_power: %d, offset_reactive_power: %d", 'A' + phase,
active_offset, reactive_offset);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
this->save_power_offset_calibration_to_memory_();
this->power_offset_pref_.save(&this->power_offset_phase_); // Save to flash
}
void ATM90E32Component::write_gains_to_registers_() {
@@ -813,276 +631,102 @@ void ATM90E32Component::write_power_offsets_to_registers_(uint8_t phase, int16_t
}
void ATM90E32Component::restore_gain_calibrations_() {
const char *cs = this->cs_summary_.c_str();
for (uint8_t i = 0; i < 3; ++i) {
this->config_gain_phase_[i].voltage_gain = this->phase_[i].voltage_gain_;
this->config_gain_phase_[i].current_gain = this->phase_[i].ct_gain_;
this->gain_phase_[i] = this->config_gain_phase_[i];
}
if (this->gain_calibration_pref_.load(&this->gain_phase_)) {
bool all_zero = true;
bool same_as_config = true;
for (uint8_t phase = 0; phase < 3; ++phase) {
const auto &cfg = this->config_gain_phase_[phase];
const auto &saved = this->gain_phase_[phase];
if (saved.voltage_gain != 0 || saved.current_gain != 0)
all_zero = false;
if (saved.voltage_gain != cfg.voltage_gain || saved.current_gain != cfg.current_gain)
same_as_config = false;
ESP_LOGI(TAG, "[CALIBRATION] Restoring saved gain calibrations to registers:");
for (uint8_t phase = 0; phase < 3; phase++) {
uint16_t v_gain = this->gain_phase_[phase].voltage_gain;
uint16_t i_gain = this->gain_phase_[phase].current_gain;
ESP_LOGI(TAG, "[CALIBRATION] Phase %c - Voltage Gain: %u, Current Gain: %u", 'A' + phase, v_gain, i_gain);
}
if (!all_zero && !same_as_config) {
for (uint8_t phase = 0; phase < 3; ++phase) {
bool mismatch = false;
if (this->has_config_voltage_gain_[phase] &&
this->gain_phase_[phase].voltage_gain != this->config_gain_phase_[phase].voltage_gain)
mismatch = true;
if (this->has_config_current_gain_[phase] &&
this->gain_phase_[phase].current_gain != this->config_gain_phase_[phase].current_gain)
mismatch = true;
if (mismatch)
this->gain_calibration_mismatch_[phase] = true;
}
this->write_gains_to_registers_();
if (this->verify_gain_writes_()) {
this->using_saved_calibrations_ = true;
this->restored_gain_calibration_ = true;
return;
}
this->write_gains_to_registers_();
if (this->verify_gain_writes_()) {
this->using_saved_calibrations_ = true;
ESP_LOGI(TAG, "[CALIBRATION] Gain calibration loaded and verified successfully.");
} else {
this->using_saved_calibrations_ = false;
ESP_LOGE(TAG, "[CALIBRATION][%s] Gain verification failed! Calibration may not be applied correctly.", cs);
ESP_LOGE(TAG, "[CALIBRATION] Gain verification failed! Calibration may not be applied correctly.");
}
} else {
this->using_saved_calibrations_ = false;
ESP_LOGW(TAG, "[CALIBRATION] No stored gain calibrations found. Using config file values.");
}
this->using_saved_calibrations_ = false;
for (uint8_t i = 0; i < 3; ++i)
this->gain_phase_[i] = this->config_gain_phase_[i];
this->write_gains_to_registers_();
ESP_LOGW(TAG, "[CALIBRATION][%s] No stored gain calibrations found. Using config file values.", cs);
}
void ATM90E32Component::restore_offset_calibrations_() {
const char *cs = this->cs_summary_.c_str();
for (uint8_t i = 0; i < 3; ++i)
this->config_offset_phase_[i] = this->offset_phase_[i];
if (this->offset_pref_.load(&this->offset_phase_)) {
ESP_LOGI(TAG, "[CALIBRATION] Successfully restored offset calibration from memory.");
bool have_data = this->offset_pref_.load(&this->offset_phase_);
bool all_zero = true;
if (have_data) {
for (auto &phase : this->offset_phase_) {
if (phase.voltage_offset_ != 0 || phase.current_offset_ != 0) {
all_zero = false;
break;
}
}
}
if (have_data && !all_zero) {
this->restored_offset_calibration_ = true;
for (uint8_t phase = 0; phase < 3; phase++) {
auto &offset = this->offset_phase_[phase];
bool mismatch = false;
if (this->has_config_voltage_offset_[phase] &&
offset.voltage_offset_ != this->config_offset_phase_[phase].voltage_offset_)
mismatch = true;
if (this->has_config_current_offset_[phase] &&
offset.current_offset_ != this->config_offset_phase_[phase].current_offset_)
mismatch = true;
if (mismatch)
this->offset_calibration_mismatch_[phase] = true;
write_offsets_to_registers_(phase, offset.voltage_offset_, offset.current_offset_);
ESP_LOGI(TAG, "[CALIBRATION] Phase %c - offset_voltage:: %d, offset_current: %d", 'A' + phase,
offset.voltage_offset_, offset.current_offset_);
}
} else {
for (uint8_t phase = 0; phase < 3; phase++)
this->offset_phase_[phase] = this->config_offset_phase_[phase];
ESP_LOGW(TAG, "[CALIBRATION][%s] No stored offset calibrations found. Using default values.", cs);
}
for (uint8_t phase = 0; phase < 3; phase++) {
write_offsets_to_registers_(phase, this->offset_phase_[phase].voltage_offset_,
this->offset_phase_[phase].current_offset_);
ESP_LOGW(TAG, "[CALIBRATION] No stored offset calibrations found. Using default values.");
}
}
void ATM90E32Component::restore_power_offset_calibrations_() {
const char *cs = this->cs_summary_.c_str();
for (uint8_t i = 0; i < 3; ++i)
this->config_power_offset_phase_[i] = this->power_offset_phase_[i];
if (this->power_offset_pref_.load(&this->power_offset_phase_)) {
ESP_LOGI(TAG, "[CALIBRATION] Successfully restored power offset calibration from memory.");
bool have_data = this->power_offset_pref_.load(&this->power_offset_phase_);
bool all_zero = true;
if (have_data) {
for (auto &phase : this->power_offset_phase_) {
if (phase.active_power_offset != 0 || phase.reactive_power_offset != 0) {
all_zero = false;
break;
}
}
}
if (have_data && !all_zero) {
this->restored_power_offset_calibration_ = true;
for (uint8_t phase = 0; phase < 3; ++phase) {
auto &offset = this->power_offset_phase_[phase];
bool mismatch = false;
if (this->has_config_active_power_offset_[phase] &&
offset.active_power_offset != this->config_power_offset_phase_[phase].active_power_offset)
mismatch = true;
if (this->has_config_reactive_power_offset_[phase] &&
offset.reactive_power_offset != this->config_power_offset_phase_[phase].reactive_power_offset)
mismatch = true;
if (mismatch)
this->power_offset_calibration_mismatch_[phase] = true;
write_power_offsets_to_registers_(phase, offset.active_power_offset, offset.reactive_power_offset);
ESP_LOGI(TAG, "[CALIBRATION] Phase %c - offset_active_power: %d, offset_reactive_power: %d", 'A' + phase,
offset.active_power_offset, offset.reactive_power_offset);
}
} else {
for (uint8_t phase = 0; phase < 3; ++phase)
this->power_offset_phase_[phase] = this->config_power_offset_phase_[phase];
ESP_LOGW(TAG, "[CALIBRATION][%s] No stored power offsets found. Using default values.", cs);
}
for (uint8_t phase = 0; phase < 3; ++phase) {
write_power_offsets_to_registers_(phase, this->power_offset_phase_[phase].active_power_offset,
this->power_offset_phase_[phase].reactive_power_offset);
ESP_LOGW(TAG, "[CALIBRATION] No stored power offsets found. Using default values.");
}
}
void ATM90E32Component::clear_gain_calibrations() {
const char *cs = this->cs_summary_.c_str();
if (!this->using_saved_calibrations_) {
ESP_LOGI(TAG, "[CALIBRATION][%s] No stored gain calibrations to clear. Current values:", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | voltage_gain | current_gain |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs);
for (int phase = 0; phase < 3; phase++) {
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6u | %6u |", cs, 'A' + phase,
this->gain_phase_[phase].voltage_gain, this->gain_phase_[phase].current_gain);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] ==========================================================\n", cs);
return;
}
ESP_LOGI(TAG, "[CALIBRATION][%s] Clearing stored gain calibrations and restoring config-defined values", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | voltage_gain | current_gain |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION] Clearing stored gain calibrations and restoring config-defined values");
for (int phase = 0; phase < 3; phase++) {
uint16_t voltage_gain = this->phase_[phase].voltage_gain_;
uint16_t current_gain = this->phase_[phase].ct_gain_;
this->config_gain_phase_[phase].voltage_gain = voltage_gain;
this->config_gain_phase_[phase].current_gain = current_gain;
this->gain_phase_[phase].voltage_gain = voltage_gain;
this->gain_phase_[phase].current_gain = current_gain;
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6u | %6u |", cs, 'A' + phase, voltage_gain, current_gain);
gain_phase_[phase].voltage_gain = this->phase_[phase].voltage_gain_;
gain_phase_[phase].current_gain = this->phase_[phase].ct_gain_;
}
ESP_LOGI(TAG, "[CALIBRATION][%s] ==========================================================\n", cs);
GainCalibration zero_gains[3]{{0, 0}, {0, 0}, {0, 0}};
bool success = this->gain_calibration_pref_.save(&zero_gains);
global_preferences->sync();
bool success = this->gain_calibration_pref_.save(&this->gain_phase_);
this->using_saved_calibrations_ = false;
this->restored_gain_calibration_ = false;
for (bool &phase : this->gain_calibration_mismatch_)
phase = false;
if (!success) {
ESP_LOGE(TAG, "[CALIBRATION][%s] Failed to clear gain calibrations!", cs);
if (success) {
ESP_LOGI(TAG, "[CALIBRATION] Gain calibrations cleared. Config values restored:");
for (int phase = 0; phase < 3; phase++) {
ESP_LOGI(TAG, "[CALIBRATION] Phase %c - Voltage Gain: %u, Current Gain: %u", 'A' + phase,
gain_phase_[phase].voltage_gain, gain_phase_[phase].current_gain);
}
} else {
ESP_LOGE(TAG, "[CALIBRATION] Failed to clear gain calibrations!");
}
this->write_gains_to_registers_(); // Apply them to the chip immediately
}
void ATM90E32Component::clear_offset_calibrations() {
const char *cs = this->cs_summary_.c_str();
if (!this->restored_offset_calibration_) {
ESP_LOGI(TAG, "[CALIBRATION][%s] No stored offset calibrations to clear. Current values:", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; phase++) {
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase,
this->offset_phase_[phase].voltage_offset_, this->offset_phase_[phase].current_offset_);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] ==============================================================\n", cs);
return;
}
ESP_LOGI(TAG, "[CALIBRATION][%s] Clearing stored offset calibrations and restoring config-defined values", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_voltage | offset_current |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; phase++) {
int16_t voltage_offset =
this->has_config_voltage_offset_[phase] ? this->config_offset_phase_[phase].voltage_offset_ : 0;
int16_t current_offset =
this->has_config_current_offset_[phase] ? this->config_offset_phase_[phase].current_offset_ : 0;
this->write_offsets_to_registers_(phase, voltage_offset, current_offset);
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase, voltage_offset,
current_offset);
this->write_offsets_to_registers_(phase, 0, 0);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] ==============================================================\n", cs);
OffsetCalibration zero_offsets[3]{{0, 0}, {0, 0}, {0, 0}};
this->offset_pref_.save(&zero_offsets); // Clear stored values in flash
global_preferences->sync();
this->offset_pref_.save(&this->offset_phase_); // Save cleared values to flash memory
this->restored_offset_calibration_ = false;
for (bool &phase : this->offset_calibration_mismatch_)
phase = false;
ESP_LOGI(TAG, "[CALIBRATION][%s] Offsets cleared.", cs);
ESP_LOGI(TAG, "[CALIBRATION] Offsets cleared.");
}
void ATM90E32Component::clear_power_offset_calibrations() {
const char *cs = this->cs_summary_.c_str();
if (!this->restored_power_offset_calibration_) {
ESP_LOGI(TAG, "[CALIBRATION][%s] No stored power offsets to clear. Current values:", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_active_power | offset_reactive_power |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; phase++) {
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase,
this->power_offset_phase_[phase].active_power_offset,
this->power_offset_phase_[phase].reactive_power_offset);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
return;
}
ESP_LOGI(TAG, "[CALIBRATION][%s] Clearing stored power offsets and restoring config-defined values", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] | Phase | offset_active_power | offset_reactive_power |", cs);
ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs);
for (uint8_t phase = 0; phase < 3; phase++) {
int16_t active_offset =
this->has_config_active_power_offset_[phase] ? this->config_power_offset_phase_[phase].active_power_offset : 0;
int16_t reactive_offset = this->has_config_reactive_power_offset_[phase]
? this->config_power_offset_phase_[phase].reactive_power_offset
: 0;
this->write_power_offsets_to_registers_(phase, active_offset, reactive_offset);
ESP_LOGI(TAG, "[CALIBRATION][%s] | %c | %6d | %6d |", cs, 'A' + phase, active_offset,
reactive_offset);
this->write_power_offsets_to_registers_(phase, 0, 0);
}
ESP_LOGI(TAG, "[CALIBRATION][%s] =====================================================================\n", cs);
PowerOffsetCalibration zero_power_offsets[3]{{0, 0}, {0, 0}, {0, 0}};
this->power_offset_pref_.save(&zero_power_offsets);
global_preferences->sync();
this->power_offset_pref_.save(&this->power_offset_phase_);
this->restored_power_offset_calibration_ = false;
for (bool &phase : this->power_offset_calibration_mismatch_)
phase = false;
ESP_LOGI(TAG, "[CALIBRATION][%s] Power offsets cleared.", cs);
ESP_LOGI(TAG, "[CALIBRATION] Power offsets cleared.");
}
int16_t ATM90E32Component::calibrate_offset(uint8_t phase, bool voltage) {
@@ -1103,21 +747,20 @@ int16_t ATM90E32Component::calibrate_offset(uint8_t phase, bool voltage) {
int16_t ATM90E32Component::calibrate_power_offset(uint8_t phase, bool reactive) {
const uint8_t num_reads = 5;
int64_t total_value = 0;
uint64_t total_value = 0;
for (uint8_t i = 0; i < num_reads; ++i) {
int32_t reading = reactive ? this->read32_(ATM90E32_REGISTER_QMEAN + phase, ATM90E32_REGISTER_QMEANLSB + phase)
: this->read32_(ATM90E32_REGISTER_PMEAN + phase, ATM90E32_REGISTER_PMEANLSB + phase);
uint32_t reading = reactive ? this->read32_(ATM90E32_REGISTER_QMEAN + phase, ATM90E32_REGISTER_QMEANLSB + phase)
: this->read32_(ATM90E32_REGISTER_PMEAN + phase, ATM90E32_REGISTER_PMEANLSB + phase);
total_value += reading;
}
int32_t average_value = total_value / num_reads;
int32_t power_offset = -average_value;
const uint32_t average_value = total_value / num_reads;
const uint32_t power_offset = ~average_value + 1;
return static_cast<int16_t>(power_offset); // Takes the lower 16 bits
}
bool ATM90E32Component::verify_gain_writes_() {
const char *cs = this->cs_summary_.c_str();
bool success = true;
for (uint8_t phase = 0; phase < 3; phase++) {
uint16_t read_voltage = this->read16_(voltage_gain_registers[phase]);
@@ -1125,7 +768,7 @@ bool ATM90E32Component::verify_gain_writes_() {
if (read_voltage != this->gain_phase_[phase].voltage_gain ||
read_current != this->gain_phase_[phase].current_gain) {
ESP_LOGE(TAG, "[CALIBRATION][%s] Mismatch detected for Phase %s!", cs, phase_labels[phase]);
ESP_LOGE(TAG, "[CALIBRATION] Mismatch detected for Phase %s!", phase_labels[phase]);
success = false;
}
}
@@ -1148,16 +791,16 @@ void ATM90E32Component::check_phase_status() {
status += "Phase Loss; ";
auto *sensor = this->phase_status_text_sensor_[phase];
if (sensor == nullptr)
continue;
const char *phase_name = sensor ? sensor->get_name().c_str() : "Unknown Phase";
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());
sensor->publish_state(status);
ESP_LOGW(TAG, "%s: %s", phase_name, status.c_str());
if (sensor != nullptr)
sensor->publish_state(status);
} else {
sensor->publish_state("Okay");
if (sensor != nullptr)
sensor->publish_state("Okay");
}
}
}
@@ -1174,12 +817,9 @@ void ATM90E32Component::check_freq_status() {
} else {
freq_status = "Normal";
}
ESP_LOGW(TAG, "Frequency status: %s", freq_status.c_str());
if (this->freq_status_text_sensor_ != nullptr) {
if (freq_status == "Normal") {
ESP_LOGD(TAG, "Frequency status: %s", freq_status.c_str());
} else {
ESP_LOGW(TAG, "Frequency status: %s", freq_status.c_str());
}
this->freq_status_text_sensor_->publish_state(freq_status);
}
}

View File

@@ -61,29 +61,15 @@ class ATM90E32Component : public PollingComponent,
this->phase_[phase].harmonic_active_power_sensor_ = obj;
}
void set_peak_current_sensor(int phase, sensor::Sensor *obj) { this->phase_[phase].peak_current_sensor_ = obj; }
void set_volt_gain(int phase, uint16_t gain) {
this->phase_[phase].voltage_gain_ = gain;
this->has_config_voltage_gain_[phase] = true;
}
void set_ct_gain(int phase, uint16_t gain) {
this->phase_[phase].ct_gain_ = gain;
this->has_config_current_gain_[phase] = true;
}
void set_voltage_offset(uint8_t phase, int16_t offset) {
this->offset_phase_[phase].voltage_offset_ = offset;
this->has_config_voltage_offset_[phase] = true;
}
void set_current_offset(uint8_t phase, int16_t offset) {
this->offset_phase_[phase].current_offset_ = offset;
this->has_config_current_offset_[phase] = true;
}
void set_volt_gain(int phase, uint16_t gain) { this->phase_[phase].voltage_gain_ = gain; }
void set_ct_gain(int phase, uint16_t gain) { this->phase_[phase].ct_gain_ = gain; }
void set_voltage_offset(uint8_t phase, int16_t offset) { this->offset_phase_[phase].voltage_offset_ = offset; }
void set_current_offset(uint8_t phase, int16_t offset) { this->offset_phase_[phase].current_offset_ = offset; }
void set_active_power_offset(uint8_t phase, int16_t offset) {
this->power_offset_phase_[phase].active_power_offset = offset;
this->has_config_active_power_offset_[phase] = true;
}
void set_reactive_power_offset(uint8_t phase, int16_t offset) {
this->power_offset_phase_[phase].reactive_power_offset = offset;
this->has_config_reactive_power_offset_[phase] = true;
}
void set_freq_sensor(sensor::Sensor *freq_sensor) { freq_sensor_ = freq_sensor; }
void set_peak_current_signed(bool flag) { peak_current_signed_ = flag; }
@@ -141,7 +127,7 @@ class ATM90E32Component : public PollingComponent,
#endif
uint16_t read16_(uint16_t a_register);
int read32_(uint16_t addr_h, uint16_t addr_l);
void write16_(uint16_t a_register, uint16_t val, bool validate = true);
void write16_(uint16_t a_register, uint16_t val);
float get_local_phase_voltage_(uint8_t phase);
float get_local_phase_current_(uint8_t phase);
float get_local_phase_active_power_(uint8_t phase);
@@ -173,15 +159,12 @@ class ATM90E32Component : public PollingComponent,
void restore_offset_calibrations_();
void restore_power_offset_calibrations_();
void restore_gain_calibrations_();
void save_offset_calibration_to_memory_();
void save_gain_calibration_to_memory_();
void save_power_offset_calibration_to_memory_();
void write_offsets_to_registers_(uint8_t phase, int16_t voltage_offset, int16_t current_offset);
void write_power_offsets_to_registers_(uint8_t phase, int16_t p_offset, int16_t q_offset);
void write_gains_to_registers_();
bool verify_gain_writes_();
bool validate_spi_read_(uint16_t expected, const char *context = nullptr);
void log_calibration_status_();
struct ATM90E32Phase {
uint16_t voltage_gain_{0};
@@ -221,33 +204,19 @@ class ATM90E32Component : public PollingComponent,
int16_t current_offset_{0};
} offset_phase_[3];
OffsetCalibration config_offset_phase_[3];
struct PowerOffsetCalibration {
int16_t active_power_offset{0};
int16_t reactive_power_offset{0};
} power_offset_phase_[3];
PowerOffsetCalibration config_power_offset_phase_[3];
struct GainCalibration {
uint16_t voltage_gain{1};
uint16_t current_gain{1};
} gain_phase_[3];
GainCalibration config_gain_phase_[3];
bool has_config_voltage_offset_[3]{false, false, false};
bool has_config_current_offset_[3]{false, false, false};
bool has_config_active_power_offset_[3]{false, false, false};
bool has_config_reactive_power_offset_[3]{false, false, false};
bool has_config_voltage_gain_[3]{false, false, false};
bool has_config_current_gain_[3]{false, false, false};
ESPPreferenceObject offset_pref_;
ESPPreferenceObject power_offset_pref_;
ESPPreferenceObject gain_calibration_pref_;
std::string cs_summary_;
sensor::Sensor *freq_sensor_{nullptr};
#ifdef USE_TEXT_SENSOR
@@ -262,13 +231,6 @@ class ATM90E32Component : public PollingComponent,
bool peak_current_signed_{false};
bool enable_offset_calibration_{false};
bool enable_gain_calibration_{false};
bool restored_offset_calibration_{false};
bool restored_power_offset_calibration_{false};
bool restored_gain_calibration_{false};
bool calibration_message_printed_{false};
bool offset_calibration_mismatch_[3]{false, false, false};
bool power_offset_calibration_mismatch_[3]{false, false, false};
bool gain_calibration_mismatch_[3]{false, false, false};
};
} // namespace atm90e32

View File

@@ -17,12 +17,10 @@ from esphome.const import (
CONF_REACTIVE_POWER,
CONF_REVERSE_ACTIVE_ENERGY,
CONF_VOLTAGE,
DEVICE_CLASS_APPARENT_POWER,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_POWER,
DEVICE_CLASS_POWER_FACTOR,
DEVICE_CLASS_REACTIVE_POWER,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_VOLTAGE,
ENTITY_CATEGORY_DIAGNOSTIC,
@@ -102,13 +100,13 @@ ATM90E32_PHASE_SCHEMA = cv.Schema(
unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE,
icon=ICON_LIGHTBULB,
accuracy_decimals=2,
device_class=DEVICE_CLASS_REACTIVE_POWER,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_APPARENT_POWER): sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT_AMPS,
accuracy_decimals=2,
device_class=DEVICE_CLASS_APPARENT_POWER,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema(

View File

@@ -2,7 +2,7 @@ from esphome import automation
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_MIC_GAIN
from esphome.core import CoroPriority, coroutine_with_priority
from esphome.core import coroutine_with_priority
CODEOWNERS = ["@kbx81"]
IS_PLATFORM_COMPONENT = True
@@ -35,7 +35,7 @@ async def audio_adc_set_mic_gain_to_code(config, action_id, template_arg, args):
return var
@coroutine_with_priority(CoroPriority.CORE)
@coroutine_with_priority(100.0)
async def to_code(config):
cg.add_define("USE_AUDIO_ADC")
cg.add_global(audio_adc_ns.using)

View File

@@ -3,7 +3,7 @@ from esphome.automation import maybe_simple_id
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_VOLUME
from esphome.core import CoroPriority, coroutine_with_priority
from esphome.core import coroutine_with_priority
CODEOWNERS = ["@kbx81"]
IS_PLATFORM_COMPONENT = True
@@ -51,7 +51,7 @@ async def audio_dac_set_volume_to_code(config, action_id, template_arg, args):
return var
@coroutine_with_priority(CoroPriority.CORE)
@coroutine_with_priority(100.0)
async def to_code(config):
cg.add_define("USE_AUDIO_DAC")
cg.add_global(audio_dac_ns.using)

View File

@@ -12,7 +12,7 @@ constexpr static const uint8_t AXS_READ_TOUCHPAD[11] = {0xb5, 0xab, 0xa5, 0x5a,
#define ERROR_CHECK(err) \
if ((err) != i2c::ERROR_OK) { \
this->status_set_warning(LOG_STR("Failed to communicate")); \
this->status_set_warning("Failed to communicate"); \
return; \
}
@@ -41,7 +41,7 @@ void AXS15231Touchscreen::update_touches() {
i2c::ErrorCode err;
uint8_t data[8]{};
err = this->write(AXS_READ_TOUCHPAD, sizeof(AXS_READ_TOUCHPAD));
err = this->write(AXS_READ_TOUCHPAD, sizeof(AXS_READ_TOUCHPAD), false);
ERROR_CHECK(err);
err = this->read(data, sizeof(data));
ERROR_CHECK(err);

View File

@@ -493,7 +493,7 @@ void BedJetHub::dump_config() {
" ble_client.app_id: %d\n"
" ble_client.conn_id: %d",
this->get_name().c_str(), this->parent()->app_id, this->parent()->get_conn_id());
LOG_UPDATE_INTERVAL(this);
LOG_UPDATE_INTERVAL(this)
ESP_LOGCONFIG(TAG, " Child components (%d):", this->children_.size());
for (auto *child : this->children_) {
ESP_LOGCONFIG(TAG, " - %s", child->describe().c_str());

View File

@@ -59,7 +59,7 @@ from esphome.const import (
DEVICE_CLASS_VIBRATION,
DEVICE_CLASS_WINDOW,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
from esphome.core import CORE, coroutine_with_priority
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
from esphome.cpp_generator import MockObjClass
from esphome.util import Registry
@@ -516,7 +516,6 @@ def binary_sensor_schema(
icon: str = cv.UNDEFINED,
entity_category: str = cv.UNDEFINED,
device_class: str = cv.UNDEFINED,
filters: list = cv.UNDEFINED,
) -> cv.Schema:
schema = {}
@@ -528,7 +527,6 @@ def binary_sensor_schema(
(CONF_ICON, icon, cv.icon),
(CONF_ENTITY_CATEGORY, entity_category, cv.entity_category),
(CONF_DEVICE_CLASS, device_class, validate_device_class),
(CONF_FILTERS, filters, validate_filters),
]:
if default is not cv.UNDEFINED:
schema[cv.Optional(key, default=default)] = validator
@@ -652,8 +650,9 @@ async def binary_sensor_is_off_to_code(config, condition_id, template_arg, args)
return cg.new_Pvariable(condition_id, template_arg, paren, False)
@coroutine_with_priority(CoroPriority.CORE)
@coroutine_with_priority(100.0)
async def to_code(config):
cg.add_define("USE_BINARY_SENSOR")
cg.add_global(binary_sensor_ns.using)

View File

@@ -7,19 +7,6 @@ namespace binary_sensor {
static const char *const TAG = "binary_sensor";
// Function implementation of LOG_BINARY_SENSOR macro to reduce code size
void log_binary_sensor(const char *tag, const char *prefix, const char *type, BinarySensor *obj) {
if (obj == nullptr) {
return;
}
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str());
if (!obj->get_device_class_ref().empty()) {
ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class_ref().c_str());
}
}
void BinarySensor::publish_state(bool new_state) {
if (this->filter_list_ == nullptr) {
this->send_state_internal(new_state);

View File

@@ -10,10 +10,13 @@ namespace esphome {
namespace binary_sensor {
class BinarySensor;
void log_binary_sensor(const char *tag, const char *prefix, const char *type, BinarySensor *obj);
#define LOG_BINARY_SENSOR(prefix, type, obj) log_binary_sensor(TAG, prefix, LOG_STR_LITERAL(type), obj)
#define LOG_BINARY_SENSOR(prefix, type, obj) \
if ((obj) != nullptr) { \
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
if (!(obj)->get_device_class().empty()) { \
ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \
} \
}
#define SUB_BINARY_SENSOR(name) \
protected: \

View File

@@ -1,6 +1 @@
import esphome.codegen as cg
CODEOWNERS = ["@tobias-", "@dan-s-github"]
CONF_BL0940_ID = "bl0940_id"
bl0940_ns = cg.esphome_ns.namespace("bl0940")
CODEOWNERS = ["@tobias-"]

View File

@@ -7,26 +7,28 @@ namespace bl0940 {
static const char *const TAG = "bl0940";
static const uint8_t BL0940_READ_COMMAND = 0x50; // 0x58 according to documentation
static const uint8_t BL0940_FULL_PACKET = 0xAA;
static const uint8_t BL0940_PACKET_HEADER = 0x55; // 0x58 according to en doc but 0x55 in cn doc
static const uint8_t BL0940_PACKET_HEADER = 0x55; // 0x58 according to documentation
static const uint8_t BL0940_WRITE_COMMAND = 0xA0; // 0xA8 according to documentation
static const uint8_t BL0940_REG_I_FAST_RMS_CTRL = 0x10;
static const uint8_t BL0940_REG_MODE = 0x18;
static const uint8_t BL0940_REG_SOFT_RESET = 0x19;
static const uint8_t BL0940_REG_USR_WRPROT = 0x1A;
static const uint8_t BL0940_REG_TPS_CTRL = 0x1B;
static const uint8_t BL0940_INIT[5][5] = {
const uint8_t BL0940_INIT[5][6] = {
// Reset to default
{BL0940_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38},
{BL0940_WRITE_COMMAND, BL0940_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38},
// Enable User Operation Write
{BL0940_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0},
{BL0940_WRITE_COMMAND, BL0940_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0},
// 0x0100 = CF_UNABLE energy pulse, AC_FREQ_SEL 50Hz, RMS_UPDATE_SEL 800mS
{BL0940_REG_MODE, 0x00, 0x10, 0x00, 0x37},
{BL0940_WRITE_COMMAND, BL0940_REG_MODE, 0x00, 0x10, 0x00, 0x37},
// 0x47FF = Over-current and leakage alarm on, Automatic temperature measurement, Interval 100mS
{BL0940_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE},
{BL0940_WRITE_COMMAND, BL0940_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE},
// 0x181C = Half cycle, Fast RMS threshold 6172
{BL0940_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B}};
{BL0940_WRITE_COMMAND, BL0940_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B}};
void BL0940::loop() {
DataPacket buffer;
@@ -34,8 +36,8 @@ void BL0940::loop() {
return;
}
if (read_array((uint8_t *) &buffer, sizeof(buffer))) {
if (this->validate_checksum_(&buffer)) {
this->received_package_(&buffer);
if (validate_checksum(&buffer)) {
received_package_(&buffer);
}
} else {
ESP_LOGW(TAG, "Junk on wire. Throwing away partial message");
@@ -44,151 +46,35 @@ void BL0940::loop() {
}
}
bool BL0940::validate_checksum_(DataPacket *data) {
uint8_t checksum = this->read_command_;
bool BL0940::validate_checksum(const DataPacket *data) {
uint8_t checksum = BL0940_READ_COMMAND;
// Whole package but checksum
uint8_t *raw = (uint8_t *) data;
for (uint32_t i = 0; i < sizeof(*data) - 1; i++) {
checksum += raw[i];
for (uint32_t i = 0; i < sizeof(data->raw) - 1; i++) {
checksum += data->raw[i];
}
checksum ^= 0xFF;
if (checksum != data->checksum) {
ESP_LOGW(TAG, "Invalid checksum! 0x%02X != 0x%02X", checksum, data->checksum);
ESP_LOGW(TAG, "BL0940 invalid checksum! 0x%02X != 0x%02X", checksum, data->checksum);
}
return checksum == data->checksum;
}
void BL0940::update() {
this->flush();
this->write_byte(this->read_command_);
this->write_byte(BL0940_READ_COMMAND);
this->write_byte(BL0940_FULL_PACKET);
}
void BL0940::setup() {
#ifdef USE_NUMBER
// add calibration callbacks
if (this->voltage_calibration_number_ != nullptr) {
this->voltage_calibration_number_->add_on_state_callback(
[this](float state) { this->voltage_calibration_callback_(state); });
if (this->voltage_calibration_number_->has_state()) {
this->voltage_calibration_callback_(this->voltage_calibration_number_->state);
}
}
if (this->current_calibration_number_ != nullptr) {
this->current_calibration_number_->add_on_state_callback(
[this](float state) { this->current_calibration_callback_(state); });
if (this->current_calibration_number_->has_state()) {
this->current_calibration_callback_(this->current_calibration_number_->state);
}
}
if (this->power_calibration_number_ != nullptr) {
this->power_calibration_number_->add_on_state_callback(
[this](float state) { this->power_calibration_callback_(state); });
if (this->power_calibration_number_->has_state()) {
this->power_calibration_callback_(this->power_calibration_number_->state);
}
}
if (this->energy_calibration_number_ != nullptr) {
this->energy_calibration_number_->add_on_state_callback(
[this](float state) { this->energy_calibration_callback_(state); });
if (this->energy_calibration_number_->has_state()) {
this->energy_calibration_callback_(this->energy_calibration_number_->state);
}
}
#endif
// calculate calibrated reference values
this->voltage_reference_cal_ = this->voltage_reference_ / this->voltage_cal_;
this->current_reference_cal_ = this->current_reference_ / this->current_cal_;
this->power_reference_cal_ = this->power_reference_ / this->power_cal_;
this->energy_reference_cal_ = this->energy_reference_ / this->energy_cal_;
for (auto *i : BL0940_INIT) {
this->write_byte(this->write_command_), this->write_array(i, 5);
this->write_array(i, 6);
delay(1);
}
this->flush();
}
float BL0940::calculate_power_reference_() {
// calculate power reference based on voltage and current reference
return this->voltage_reference_cal_ * this->current_reference_cal_ * 4046 / 324004 / 79931;
}
float BL0940::calculate_energy_reference_() {
// formula: 3600000 * 4046 * RL * R1 * 1000 / (1638.4 * 256) / Vref² / (R1 + R2)
// or: power_reference_ * 3600000 / (1638.4 * 256)
return this->power_reference_cal_ * 3600000 / (1638.4 * 256);
}
float BL0940::calculate_calibration_value_(float state) { return (100 + state) / 100; }
void BL0940::reset_calibration() {
#ifdef USE_NUMBER
if (this->current_calibration_number_ != nullptr && this->current_cal_ != 1) {
this->current_calibration_number_->make_call().set_value(0).perform();
}
if (this->voltage_calibration_number_ != nullptr && this->voltage_cal_ != 1) {
this->voltage_calibration_number_->make_call().set_value(0).perform();
}
if (this->power_calibration_number_ != nullptr && this->power_cal_ != 1) {
this->power_calibration_number_->make_call().set_value(0).perform();
}
if (this->energy_calibration_number_ != nullptr && this->energy_cal_ != 1) {
this->energy_calibration_number_->make_call().set_value(0).perform();
}
#endif
ESP_LOGD(TAG, "external calibration values restored to initial state");
}
void BL0940::current_calibration_callback_(float state) {
this->current_cal_ = this->calculate_calibration_value_(state);
ESP_LOGV(TAG, "update current calibration state: %f", this->current_cal_);
this->recalibrate_();
}
void BL0940::voltage_calibration_callback_(float state) {
this->voltage_cal_ = this->calculate_calibration_value_(state);
ESP_LOGV(TAG, "update voltage calibration state: %f", this->voltage_cal_);
this->recalibrate_();
}
void BL0940::power_calibration_callback_(float state) {
this->power_cal_ = this->calculate_calibration_value_(state);
ESP_LOGV(TAG, "update power calibration state: %f", this->power_cal_);
this->recalibrate_();
}
void BL0940::energy_calibration_callback_(float state) {
this->energy_cal_ = this->calculate_calibration_value_(state);
ESP_LOGV(TAG, "update energy calibration state: %f", this->energy_cal_);
this->recalibrate_();
}
void BL0940::recalibrate_() {
ESP_LOGV(TAG, "Recalibrating reference values");
this->voltage_reference_cal_ = this->voltage_reference_ / this->voltage_cal_;
this->current_reference_cal_ = this->current_reference_ / this->current_cal_;
if (this->voltage_cal_ != 1 || this->current_cal_ != 1) {
this->power_reference_ = this->calculate_power_reference_();
}
this->power_reference_cal_ = this->power_reference_ / this->power_cal_;
if (this->voltage_cal_ != 1 || this->current_cal_ != 1 || this->power_cal_ != 1) {
this->energy_reference_ = this->calculate_energy_reference_();
}
this->energy_reference_cal_ = this->energy_reference_ / this->energy_cal_;
ESP_LOGD(TAG,
"Recalibrated reference values:\n"
"Voltage: %f\n, Current: %f\n, Power: %f\n, Energy: %f\n",
this->voltage_reference_cal_, this->current_reference_cal_, this->power_reference_cal_,
this->energy_reference_cal_);
}
float BL0940::update_temp_(sensor::Sensor *sensor, uint16_le_t temperature) const {
auto tb = (float) temperature;
float BL0940::update_temp_(sensor::Sensor *sensor, ube16_t temperature) const {
auto tb = (float) (temperature.h << 8 | temperature.l);
float converted_temp = ((float) 170 / 448) * (tb / 2 - 32) - 45;
if (sensor != nullptr) {
if (sensor->has_state() && std::abs(converted_temp - sensor->get_state()) > max_temperature_diff_) {
@@ -201,40 +87,33 @@ float BL0940::update_temp_(sensor::Sensor *sensor, uint16_le_t temperature) cons
return converted_temp;
}
void BL0940::received_package_(DataPacket *data) {
void BL0940::received_package_(const DataPacket *data) const {
// Bad header
if (data->frame_header != BL0940_PACKET_HEADER) {
ESP_LOGI(TAG, "Invalid data. Header mismatch: %d", data->frame_header);
return;
}
// cf_cnt is only 24 bits, so track overflows
uint32_t cf_cnt = (uint24_t) data->cf_cnt;
cf_cnt |= this->prev_cf_cnt_ & 0xff000000;
if (cf_cnt < this->prev_cf_cnt_) {
cf_cnt += 0x1000000;
}
this->prev_cf_cnt_ = cf_cnt;
float v_rms = (float) to_uint32_t(data->v_rms) / voltage_reference_;
float i_rms = (float) to_uint32_t(data->i_rms) / current_reference_;
float watt = (float) to_int32_t(data->watt) / power_reference_;
uint32_t cf_cnt = to_uint32_t(data->cf_cnt);
float total_energy_consumption = (float) cf_cnt / energy_reference_;
float v_rms = (uint24_t) data->v_rms / this->voltage_reference_cal_;
float i_rms = (uint24_t) data->i_rms / this->current_reference_cal_;
float watt = (int24_t) data->watt / this->power_reference_cal_;
float total_energy_consumption = cf_cnt / this->energy_reference_cal_;
float tps1 = update_temp_(internal_temperature_sensor_, data->tps1);
float tps2 = update_temp_(external_temperature_sensor_, data->tps2);
float tps1 = update_temp_(this->internal_temperature_sensor_, data->tps1);
float tps2 = update_temp_(this->external_temperature_sensor_, data->tps2);
if (this->voltage_sensor_ != nullptr) {
this->voltage_sensor_->publish_state(v_rms);
if (voltage_sensor_ != nullptr) {
voltage_sensor_->publish_state(v_rms);
}
if (this->current_sensor_ != nullptr) {
this->current_sensor_->publish_state(i_rms);
if (current_sensor_ != nullptr) {
current_sensor_->publish_state(i_rms);
}
if (this->power_sensor_ != nullptr) {
this->power_sensor_->publish_state(watt);
if (power_sensor_ != nullptr) {
power_sensor_->publish_state(watt);
}
if (this->energy_sensor_ != nullptr) {
this->energy_sensor_->publish_state(total_energy_consumption);
if (energy_sensor_ != nullptr) {
energy_sensor_->publish_state(total_energy_consumption);
}
ESP_LOGV(TAG, "BL0940: U %fV, I %fA, P %fW, Cnt %" PRId32 ", ∫P %fkWh, T1 %f°C, T2 %f°C", v_rms, i_rms, watt, cf_cnt,
@@ -242,27 +121,7 @@ void BL0940::received_package_(DataPacket *data) {
}
void BL0940::dump_config() { // NOLINT(readability-function-cognitive-complexity)
ESP_LOGCONFIG(TAG,
"BL0940:\n"
" LEGACY MODE: %s\n"
" READ CMD: 0x%02X\n"
" WRITE CMD: 0x%02X\n"
" ------------------\n"
" Current reference: %f\n"
" Energy reference: %f\n"
" Power reference: %f\n"
" Voltage reference: %f\n",
TRUEFALSE(this->legacy_mode_enabled_), this->read_command_, this->write_command_,
this->current_reference_, this->energy_reference_, this->power_reference_, this->voltage_reference_);
#ifdef USE_NUMBER
ESP_LOGCONFIG(TAG,
"BL0940:\n"
" Current calibration: %f\n"
" Energy calibration: %f\n"
" Power calibration: %f\n"
" Voltage calibration: %f\n",
this->current_cal_, this->energy_cal_, this->power_cal_, this->voltage_cal_);
#endif
ESP_LOGCONFIG(TAG, "BL0940:");
LOG_SENSOR("", "Voltage", this->voltage_sensor_);
LOG_SENSOR("", "Current", this->current_sensor_);
LOG_SENSOR("", "Power", this->power_sensor_);
@@ -271,5 +130,9 @@ void BL0940::dump_config() { // NOLINT(readability-function-cognitive-complexit
LOG_SENSOR("", "External temperature", this->external_temperature_sensor_);
}
uint32_t BL0940::to_uint32_t(ube24_t input) { return input.h << 16 | input.m << 8 | input.l; }
int32_t BL0940::to_int32_t(sbe24_t input) { return input.h << 16 | input.m << 8 | input.l; }
} // namespace bl0940
} // namespace esphome

View File

@@ -1,48 +1,66 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/datatypes.h"
#include "esphome/core/defines.h"
#ifdef USE_BUTTON
#include "esphome/components/button/button.h"
#endif
#ifdef USE_NUMBER
#include "esphome/components/number/number.h"
#endif
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/uart/uart.h"
#include "esphome/components/sensor/sensor.h"
namespace esphome {
namespace bl0940 {
static const float BL0940_PREF = 1430;
static const float BL0940_UREF = 33000;
static const float BL0940_IREF = 275000; // 2750 from tasmota. Seems to generate values 100 times too high
// Measured to 297J per click according to power consumption of 5 minutes
// Converted to kWh (3.6MJ per kwH). Used to be 256 * 1638.4
static const float BL0940_EREF = 3.6e6 / 297;
struct ube24_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
uint8_t l;
uint8_t m;
uint8_t h;
} __attribute__((packed));
struct ube16_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
uint8_t l;
uint8_t h;
} __attribute__((packed));
struct sbe24_t { // NOLINT(readability-identifier-naming,altera-struct-pack-align)
uint8_t l;
uint8_t m;
int8_t h;
} __attribute__((packed));
// Caveat: All these values are big endian (low - middle - high)
struct DataPacket {
uint8_t frame_header; // Packet header (0x58 in EN docs, 0x55 in CN docs and Tasmota tests)
uint24_le_t i_fast_rms; // Fast RMS current
uint24_le_t i_rms; // RMS current
uint24_t RESERVED0; // Reserved
uint24_le_t v_rms; // RMS voltage
uint24_t RESERVED1; // Reserved
int24_le_t watt; // Active power (can be negative for bidirectional measurement)
uint24_t RESERVED2; // Reserved
uint24_le_t cf_cnt; // Energy pulse count
uint24_t RESERVED3; // Reserved
uint16_le_t tps1; // Internal temperature sensor 1
uint8_t RESERVED4; // Reserved (should be 0x00)
uint16_le_t tps2; // Internal temperature sensor 2
uint8_t RESERVED5; // Reserved (should be 0x00)
uint8_t checksum; // Packet checksum
union DataPacket { // NOLINT(altera-struct-pack-align)
uint8_t raw[35];
struct {
uint8_t frame_header; // value of 0x58 according to docs. 0x55 according to Tasmota real world tests. Reality wins.
ube24_t i_fast_rms; // 0x00
ube24_t i_rms; // 0x04
ube24_t RESERVED0; // reserved
ube24_t v_rms; // 0x06
ube24_t RESERVED1; // reserved
sbe24_t watt; // 0x08
ube24_t RESERVED2; // reserved
ube24_t cf_cnt; // 0x0A
ube24_t RESERVED3; // reserved
ube16_t tps1; // 0x0c
uint8_t RESERVED4; // value of 0x00
ube16_t tps2; // 0x0c
uint8_t RESERVED5; // value of 0x00
uint8_t checksum; // checksum
};
} __attribute__((packed));
class BL0940 : public PollingComponent, public uart::UARTDevice {
public:
// Sensor setters
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; }
void set_energy_sensor(sensor::Sensor *energy_sensor) { energy_sensor_ = energy_sensor; }
// Temperature sensor setters
void set_internal_temperature_sensor(sensor::Sensor *internal_temperature_sensor) {
internal_temperature_sensor_ = internal_temperature_sensor;
}
@@ -50,105 +68,42 @@ class BL0940 : public PollingComponent, public uart::UARTDevice {
external_temperature_sensor_ = external_temperature_sensor;
}
// Configuration setters
void set_legacy_mode(bool enable) { this->legacy_mode_enabled_ = enable; }
void set_read_command(uint8_t read_command) { this->read_command_ = read_command; }
void set_write_command(uint8_t write_command) { this->write_command_ = write_command; }
// Reference value setters (used for calibration and conversion)
void set_current_reference(float current_ref) { this->current_reference_ = current_ref; }
void set_energy_reference(float energy_ref) { this->energy_reference_ = energy_ref; }
void set_power_reference(float power_ref) { this->power_reference_ = power_ref; }
void set_voltage_reference(float voltage_ref) { this->voltage_reference_ = voltage_ref; }
#ifdef USE_NUMBER
// Calibration number setters (for Home Assistant number entities)
void set_current_calibration_number(number::Number *num) { this->current_calibration_number_ = num; }
void set_voltage_calibration_number(number::Number *num) { this->voltage_calibration_number_ = num; }
void set_power_calibration_number(number::Number *num) { this->power_calibration_number_ = num; }
void set_energy_calibration_number(number::Number *num) { this->energy_calibration_number_ = num; }
#endif
#ifdef USE_BUTTON
// Resets all calibration values to defaults (can be triggered by a button)
void reset_calibration();
#endif
// Core component methods
void loop() override;
void update() override;
void setup() override;
void dump_config() override;
protected:
// --- Sensor pointers ---
sensor::Sensor *voltage_sensor_{nullptr}; // Voltage sensor
sensor::Sensor *current_sensor_{nullptr}; // Current sensor
sensor::Sensor *power_sensor_{nullptr}; // Power sensor (can be negative for bidirectional)
sensor::Sensor *energy_sensor_{nullptr}; // Energy sensor
sensor::Sensor *internal_temperature_sensor_{nullptr}; // Internal temperature sensor
sensor::Sensor *external_temperature_sensor_{nullptr}; // External temperature sensor
sensor::Sensor *voltage_sensor_{nullptr};
sensor::Sensor *current_sensor_{nullptr};
// NB This may be negative as the circuits is seemingly able to measure
// power in both directions
sensor::Sensor *power_sensor_{nullptr};
sensor::Sensor *energy_sensor_{nullptr};
sensor::Sensor *internal_temperature_sensor_{nullptr};
sensor::Sensor *external_temperature_sensor_{nullptr};
#ifdef USE_NUMBER
// --- Calibration number entities (for dynamic calibration via HA UI) ---
number::Number *voltage_calibration_number_{nullptr};
number::Number *current_calibration_number_{nullptr};
number::Number *power_calibration_number_{nullptr};
number::Number *energy_calibration_number_{nullptr};
#endif
// Max difference between two measurements of the temperature. Used to avoid noise.
float max_temperature_diff_{0};
// Divide by this to turn into Watt
float power_reference_ = BL0940_PREF;
// Divide by this to turn into Volt
float voltage_reference_ = BL0940_UREF;
// Divide by this to turn into Ampere
float current_reference_ = BL0940_IREF;
// Divide by this to turn into kWh
float energy_reference_ = BL0940_EREF;
// --- Internal state ---
uint32_t prev_cf_cnt_ = 0; // Previous energy pulse count (for energy calculation)
float max_temperature_diff_{0}; // Max allowed temperature difference between two measurements (noise filter)
float update_temp_(sensor::Sensor *sensor, ube16_t packed_temperature) const;
// --- Reference values for conversion ---
float power_reference_; // Divider for raw power to get Watts
float power_reference_cal_; // Calibrated power reference
float voltage_reference_; // Divider for raw voltage to get Volts
float voltage_reference_cal_; // Calibrated voltage reference
float current_reference_; // Divider for raw current to get Amperes
float current_reference_cal_; // Calibrated current reference
float energy_reference_; // Divider for raw energy to get kWh
float energy_reference_cal_; // Calibrated energy reference
static uint32_t to_uint32_t(ube24_t input);
// --- Home Assistant calibration values (multipliers, default 1) ---
float current_cal_{1};
float voltage_cal_{1};
float power_cal_{1};
float energy_cal_{1};
static int32_t to_int32_t(sbe24_t input);
// --- Protocol commands ---
uint8_t read_command_;
uint8_t write_command_;
static bool validate_checksum(const DataPacket *data);
// --- Mode flags ---
bool legacy_mode_enabled_ = true;
// --- Methods ---
// Converts packed temperature value to float and updates the sensor
float update_temp_(sensor::Sensor *sensor, uint16_le_t packed_temperature) const;
// Validates the checksum of a received data packet
bool validate_checksum_(DataPacket *data);
// Handles a received data packet
void received_package_(DataPacket *data);
// Calculates reference values for calibration and conversion
float calculate_energy_reference_();
float calculate_power_reference_();
float calculate_calibration_value_(float state);
// Calibration update callbacks (used with number entities)
void current_calibration_callback_(float state);
void voltage_calibration_callback_(float state);
void power_calibration_callback_(float state);
void energy_calibration_callback_(float state);
void reset_calibration_callback_();
// Recalculates all reference values after calibration changes
void recalibrate_();
void received_package_(const DataPacket *data) const;
};
} // namespace bl0940
} // namespace esphome

View File

@@ -1,27 +0,0 @@
import esphome.codegen as cg
from esphome.components import button
import esphome.config_validation as cv
from esphome.const import ENTITY_CATEGORY_CONFIG, ICON_RESTART
from .. import CONF_BL0940_ID, bl0940_ns
from ..sensor import BL0940
CalibrationResetButton = bl0940_ns.class_(
"CalibrationResetButton", button.Button, cg.Component
)
CONFIG_SCHEMA = cv.All(
button.button_schema(
CalibrationResetButton,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_RESTART,
)
.extend({cv.GenerateID(CONF_BL0940_ID): cv.use_id(BL0940)})
.extend(cv.COMPONENT_SCHEMA)
)
async def to_code(config):
var = await button.new_button(config)
await cg.register_component(var, config)
await cg.register_parented(var, config[CONF_BL0940_ID])

View File

@@ -1,20 +0,0 @@
#include "calibration_reset_button.h"
#include "../bl0940.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include "esphome/core/application.h"
namespace esphome {
namespace bl0940 {
static const char *const TAG = "bl0940.button.calibration_reset";
void CalibrationResetButton::dump_config() { LOG_BUTTON("", "Calibration Reset Button", this); }
void CalibrationResetButton::press_action() {
ESP_LOGI(TAG, "Resetting calibration defaults...");
this->parent_->reset_calibration();
}
} // namespace bl0940
} // namespace esphome

View File

@@ -1,19 +0,0 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/button/button.h"
namespace esphome {
namespace bl0940 {
class BL0940; // Forward declaration of BL0940 class
class CalibrationResetButton : public button::Button, public Component, public Parented<BL0940> {
public:
void dump_config() override;
void press_action() override;
};
} // namespace bl0940
} // namespace esphome

View File

@@ -1,94 +0,0 @@
import esphome.codegen as cg
from esphome.components import number
import esphome.config_validation as cv
from esphome.const import (
CONF_MAX_VALUE,
CONF_MIN_VALUE,
CONF_MODE,
CONF_RESTORE_VALUE,
CONF_STEP,
ENTITY_CATEGORY_CONFIG,
UNIT_PERCENT,
)
from .. import CONF_BL0940_ID, bl0940_ns
from ..sensor import BL0940
# Define calibration types
CONF_CURRENT_CALIBRATION = "current_calibration"
CONF_VOLTAGE_CALIBRATION = "voltage_calibration"
CONF_POWER_CALIBRATION = "power_calibration"
CONF_ENERGY_CALIBRATION = "energy_calibration"
BL0940Number = bl0940_ns.class_("BL0940Number")
CalibrationNumber = bl0940_ns.class_(
"CalibrationNumber", number.Number, cg.PollingComponent
)
def validate_min_max(config):
if config[CONF_MAX_VALUE] <= config[CONF_MIN_VALUE]:
raise cv.Invalid("max_value must be greater than min_value")
return config
CALIBRATION_SCHEMA = cv.All(
number.number_schema(
CalibrationNumber,
entity_category=ENTITY_CATEGORY_CONFIG,
unit_of_measurement=UNIT_PERCENT,
)
.extend(
{
cv.Optional(CONF_MODE, default="BOX"): cv.enum(number.NUMBER_MODES),
cv.Optional(CONF_MAX_VALUE, default=10): cv.All(
cv.float_, cv.Range(max=50)
),
cv.Optional(CONF_MIN_VALUE, default=-10): cv.All(
cv.float_, cv.Range(min=-50)
),
cv.Optional(CONF_STEP, default=0.1): cv.positive_float,
cv.Optional(CONF_RESTORE_VALUE): cv.boolean,
}
)
.extend(cv.COMPONENT_SCHEMA),
validate_min_max,
)
# Configuration schema for BL0940 numbers
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(BL0940Number),
cv.GenerateID(CONF_BL0940_ID): cv.use_id(BL0940),
cv.Optional(CONF_CURRENT_CALIBRATION): CALIBRATION_SCHEMA,
cv.Optional(CONF_VOLTAGE_CALIBRATION): CALIBRATION_SCHEMA,
cv.Optional(CONF_POWER_CALIBRATION): CALIBRATION_SCHEMA,
cv.Optional(CONF_ENERGY_CALIBRATION): CALIBRATION_SCHEMA,
}
)
async def to_code(config):
# Get the BL0940 component instance
bl0940 = await cg.get_variable(config[CONF_BL0940_ID])
# Process all calibration types
for cal_type, setter_method in [
(CONF_CURRENT_CALIBRATION, "set_current_calibration_number"),
(CONF_VOLTAGE_CALIBRATION, "set_voltage_calibration_number"),
(CONF_POWER_CALIBRATION, "set_power_calibration_number"),
(CONF_ENERGY_CALIBRATION, "set_energy_calibration_number"),
]:
if conf := config.get(cal_type):
var = await number.new_number(
conf,
min_value=conf.get(CONF_MIN_VALUE),
max_value=conf.get(CONF_MAX_VALUE),
step=conf.get(CONF_STEP),
)
await cg.register_component(var, conf)
if restore_value := config.get(CONF_RESTORE_VALUE):
cg.add(var.set_restore_value(restore_value))
cg.add(getattr(bl0940, setter_method)(var))

View File

@@ -1,29 +0,0 @@
#include "calibration_number.h"
#include "esphome/core/log.h"
namespace esphome {
namespace bl0940 {
static const char *const TAG = "bl0940.number";
void CalibrationNumber::setup() {
float value = 0.0f;
if (this->restore_value_) {
this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
if (!this->pref_.load(&value)) {
value = 0.0f;
}
}
this->publish_state(value);
}
void CalibrationNumber::control(float value) {
this->publish_state(value);
if (this->restore_value_)
this->pref_.save(&value);
}
void CalibrationNumber::dump_config() { LOG_NUMBER("", "Calibration Number", this); }
} // namespace bl0940
} // namespace esphome

View File

@@ -1,26 +0,0 @@
#pragma once
#include "esphome/components/number/number.h"
#include "esphome/core/component.h"
#include "esphome/core/preferences.h"
namespace esphome {
namespace bl0940 {
class CalibrationNumber : public number::Number, public Component {
public:
void setup() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
protected:
void control(float value) override;
bool restore_value_{true};
ESPPreferenceObject pref_;
};
} // namespace bl0940
} // namespace esphome

View File

@@ -8,7 +8,6 @@ from esphome.const import (
CONF_ID,
CONF_INTERNAL_TEMPERATURE,
CONF_POWER,
CONF_REFERENCE_VOLTAGE,
CONF_VOLTAGE,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_ENERGY,
@@ -24,133 +23,12 @@ from esphome.const import (
UNIT_WATT,
)
from . import bl0940_ns
DEPENDENCIES = ["uart"]
bl0940_ns = cg.esphome_ns.namespace("bl0940")
BL0940 = bl0940_ns.class_("BL0940", cg.PollingComponent, uart.UARTDevice)
CONF_LEGACY_MODE = "legacy_mode"
CONF_READ_COMMAND = "read_command"
CONF_WRITE_COMMAND = "write_command"
CONF_RESISTOR_SHUNT = "resistor_shunt"
CONF_RESISTOR_ONE = "resistor_one"
CONF_RESISTOR_TWO = "resistor_two"
CONF_CURRENT_REFERENCE = "current_reference"
CONF_ENERGY_REFERENCE = "energy_reference"
CONF_POWER_REFERENCE = "power_reference"
CONF_VOLTAGE_REFERENCE = "voltage_reference"
DEFAULT_BL0940_READ_COMMAND = 0x58
DEFAULT_BL0940_WRITE_COMMAND = 0xA1
# Values according to BL0940 application note:
# https://www.belling.com.cn/media/file_object/bel_product/BL0940/guide/BL0940_APPNote_TSSOP14_V1.04_EN.pdf
DEFAULT_BL0940_VREF = 1.218 # Vref = 1.218
DEFAULT_BL0940_RL = 1 # RL = 1 mΩ
DEFAULT_BL0940_R1 = 0.51 # R1 = 0.51 kΩ
DEFAULT_BL0940_R2 = 1950 # R2 = 5 x 390 kΩ -> 1950 kΩ
# ----------------------------------------------------
# values from initial implementation
DEFAULT_BL0940_LEGACY_READ_COMMAND = 0x50
DEFAULT_BL0940_LEGACY_WRITE_COMMAND = 0xA0
DEFAULT_BL0940_LEGACY_UREF = 33000
DEFAULT_BL0940_LEGACY_IREF = 275000
DEFAULT_BL0940_LEGACY_PREF = 1430
# Measured to 297J per click according to power consumption of 5 minutes
# Converted to kWh (3.6MJ per kwH). Used to be 256 * 1638.4
DEFAULT_BL0940_LEGACY_EREF = 3.6e6 / 297
# ----------------------------------------------------
# methods to calculate voltage and current reference values
def calculate_voltage_reference(vref, r_one, r_two):
# formula: 79931 / Vref * (R1 * 1000) / (R1 + R2)
return 79931 / vref * (r_one * 1000) / (r_one + r_two)
def calculate_current_reference(vref, r_shunt):
# formula: 324004 * RL / Vref
return 324004 * r_shunt / vref
def calculate_power_reference(voltage_reference, current_reference):
# calculate power reference based on voltage and current reference
return voltage_reference * current_reference * 4046 / 324004 / 79931
def calculate_energy_reference(power_reference):
# formula: power_reference * 3600000 / (1638.4 * 256)
return power_reference * 3600000 / (1638.4 * 256)
def validate_legacy_mode(config):
# Only allow schematic calibration options if legacy_mode is False
if config.get(CONF_LEGACY_MODE, True):
forbidden = [
CONF_REFERENCE_VOLTAGE,
CONF_RESISTOR_SHUNT,
CONF_RESISTOR_ONE,
CONF_RESISTOR_TWO,
]
for key in forbidden:
if key in config:
raise cv.Invalid(
f"Option '{key}' is only allowed when legacy_mode: false"
)
return config
def set_command_defaults(config):
# Set defaults for read_command and write_command based on legacy_mode
legacy = config.get(CONF_LEGACY_MODE, True)
if legacy:
config.setdefault(CONF_READ_COMMAND, DEFAULT_BL0940_LEGACY_READ_COMMAND)
config.setdefault(CONF_WRITE_COMMAND, DEFAULT_BL0940_LEGACY_WRITE_COMMAND)
else:
config.setdefault(CONF_READ_COMMAND, DEFAULT_BL0940_READ_COMMAND)
config.setdefault(CONF_WRITE_COMMAND, DEFAULT_BL0940_WRITE_COMMAND)
return config
def set_reference_values(config):
# Set default reference values based on legacy_mode
if config.get(CONF_LEGACY_MODE, True):
config.setdefault(CONF_VOLTAGE_REFERENCE, DEFAULT_BL0940_LEGACY_UREF)
config.setdefault(CONF_CURRENT_REFERENCE, DEFAULT_BL0940_LEGACY_IREF)
config.setdefault(CONF_POWER_REFERENCE, DEFAULT_BL0940_LEGACY_PREF)
config.setdefault(CONF_ENERGY_REFERENCE, DEFAULT_BL0940_LEGACY_PREF)
else:
vref = config.get(CONF_VOLTAGE_REFERENCE, DEFAULT_BL0940_VREF)
r_one = config.get(CONF_RESISTOR_ONE, DEFAULT_BL0940_R1)
r_two = config.get(CONF_RESISTOR_TWO, DEFAULT_BL0940_R2)
r_shunt = config.get(CONF_RESISTOR_SHUNT, DEFAULT_BL0940_RL)
config.setdefault(
CONF_VOLTAGE_REFERENCE, calculate_voltage_reference(vref, r_one, r_two)
)
config.setdefault(
CONF_CURRENT_REFERENCE, calculate_current_reference(vref, r_shunt)
)
config.setdefault(
CONF_POWER_REFERENCE,
calculate_power_reference(
config.get(CONF_VOLTAGE_REFERENCE), config.get(CONF_CURRENT_REFERENCE)
),
)
config.setdefault(
CONF_ENERGY_REFERENCE,
calculate_energy_reference(config.get(CONF_POWER_REFERENCE)),
)
return config
CONFIG_SCHEMA = (
cv.Schema(
{
@@ -191,24 +69,10 @@ CONFIG_SCHEMA = (
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
),
cv.Optional(CONF_LEGACY_MODE, default=True): cv.boolean,
cv.Optional(CONF_READ_COMMAND): cv.hex_uint8_t,
cv.Optional(CONF_WRITE_COMMAND): cv.hex_uint8_t,
cv.Optional(CONF_REFERENCE_VOLTAGE): cv.float_,
cv.Optional(CONF_RESISTOR_SHUNT): cv.float_,
cv.Optional(CONF_RESISTOR_ONE): cv.float_,
cv.Optional(CONF_RESISTOR_TWO): cv.float_,
cv.Optional(CONF_CURRENT_REFERENCE): cv.float_,
cv.Optional(CONF_ENERGY_REFERENCE): cv.float_,
cv.Optional(CONF_POWER_REFERENCE): cv.float_,
cv.Optional(CONF_VOLTAGE_REFERENCE): cv.float_,
}
)
.extend(cv.polling_component_schema("60s"))
.extend(uart.UART_DEVICE_SCHEMA)
.add_extra(validate_legacy_mode)
.add_extra(set_command_defaults)
.add_extra(set_reference_values)
)
@@ -235,16 +99,3 @@ async def to_code(config):
if external_temperature_config := config.get(CONF_EXTERNAL_TEMPERATURE):
sens = await sensor.new_sensor(external_temperature_config)
cg.add(var.set_external_temperature_sensor(sens))
# enable legacy mode
cg.add(var.set_legacy_mode(config.get(CONF_LEGACY_MODE)))
# Set bl0940 commands after validator has determined which defaults to use if not set
cg.add(var.set_read_command(config.get(CONF_READ_COMMAND)))
cg.add(var.set_write_command(config.get(CONF_WRITE_COMMAND)))
# Set reference values after validator has set the values either from defaults or calculated
cg.add(var.set_current_reference(config.get(CONF_CURRENT_REFERENCE)))
cg.add(var.set_voltage_reference(config.get(CONF_VOLTAGE_REFERENCE)))
cg.add(var.set_power_reference(config.get(CONF_POWER_REFERENCE)))
cg.add(var.set_energy_reference(config.get(CONF_ENERGY_REFERENCE)))

View File

@@ -149,7 +149,7 @@ void BL0942::setup() {
this->write_reg_(BL0942_REG_USR_WRPROT, 0);
if (this->read_reg_(BL0942_REG_MODE) != mode)
this->status_set_warning(LOG_STR("BL0942 setup failed!"));
this->status_set_warning("BL0942 setup failed!");
this->flush();
}

View File

@@ -175,7 +175,8 @@ BLE_REMOVE_BOND_ACTION_SCHEMA = cv.Schema(
)
async def ble_disconnect_to_code(config, action_id, template_arg, args):
parent = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, parent)
var = cg.new_Pvariable(action_id, template_arg, parent)
return var
@automation.register_action(
@@ -183,7 +184,8 @@ async def ble_disconnect_to_code(config, action_id, template_arg, args):
)
async def ble_connect_to_code(config, action_id, template_arg, args):
parent = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, parent)
var = cg.new_Pvariable(action_id, template_arg, parent)
return var
@automation.register_action(
@@ -280,13 +282,14 @@ async def passkey_reply_to_code(config, action_id, template_arg, args):
)
async def remove_bond_to_code(config, action_id, template_arg, args):
parent = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, parent)
var = cg.new_Pvariable(action_id, template_arg, parent)
return var
async def to_code(config):
# Register the loggers this component needs
esp32_ble.register_bt_logger(BTLoggers.GATT, BTLoggers.SMP)
cg.add_define("USE_ESP32_BLE_UUID")
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)

View File

@@ -27,7 +27,7 @@ CONFIG_SCHEMA = cv.All(
)
async def to_code(config):
def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
if len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid16_format):
cg.add(
@@ -63,6 +63,6 @@ async def to_code(config):
)
cg.add(var.set_char_uuid128(uuid128))
cg.add(var.set_require_response(config[CONF_REQUIRE_RESPONSE]))
await output.register_output(var, config)
await ble_client.register_ble_node(var, config)
await cg.register_component(var, config)
yield output.register_output(var, config)
yield ble_client.register_ble_node(var, config)
yield cg.register_component(var, config)

View File

@@ -1,19 +1,13 @@
import logging
import esphome.codegen as cg
from esphome.components import esp32_ble, esp32_ble_client, esp32_ble_tracker
from esphome.components.esp32 import add_idf_sdkconfig_option
from esphome.components.esp32_ble import BTLoggers
import esphome.config_validation as cv
from esphome.const import CONF_ACTIVE, CONF_ID
from esphome.core import CORE
from esphome.log import AnsiFore, color
AUTO_LOAD = ["esp32_ble_client", "esp32_ble_tracker"]
DEPENDENCIES = ["api", "esp32"]
CODEOWNERS = ["@jesserockz", "@bdraco"]
_LOGGER = logging.getLogger(__name__)
CODEOWNERS = ["@jesserockz"]
CONF_CONNECTION_SLOTS = "connection_slots"
CONF_CACHE_SERVICES = "cache_services"
@@ -47,27 +41,6 @@ def validate_connections(config):
esp32_ble_tracker.consume_connection_slots(connection_slots, "bluetooth_proxy")(
config
)
# Warn about connection slot waste when using Arduino framework
if CORE.using_arduino and connection_slots:
_LOGGER.warning(
"Bluetooth Proxy with active connections on Arduino framework has suboptimal performance.\n"
"If BLE connections fail, they can waste connection slots for 10 seconds because\n"
"Arduino doesn't allow configuring the BLE connection timeout (fixed at 30s).\n"
"ESP-IDF framework allows setting it to 20s to match client timeouts.\n"
"\n"
"To switch to ESP-IDF, add this to your YAML:\n"
" esp32:\n"
" framework:\n"
" type: esp-idf\n"
"\n"
"For detailed migration instructions, see:\n"
"%s",
color(
AnsiFore.BLUE, "https://esphome.io/guides/esp32_arduino_to_idf.html"
),
)
return {
**config,
CONF_CONNECTIONS: [CONNECTION_SCHEMA({}) for _ in range(connection_slots)],
@@ -80,7 +53,7 @@ CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.GenerateID(): cv.declare_id(BluetoothProxy),
cv.Optional(CONF_ACTIVE, default=True): cv.boolean,
cv.Optional(CONF_ACTIVE, default=False): cv.boolean,
cv.SplitDefault(CONF_CACHE_SERVICES, esp32_idf=True): cv.All(
cv.only_with_esp_idf, cv.boolean
),
@@ -114,16 +87,6 @@ async def to_code(config):
cg.add(var.set_active(config[CONF_ACTIVE]))
await esp32_ble_tracker.register_raw_ble_device(var, config)
# Define max connections for protobuf fixed array
connection_count = len(config.get(CONF_CONNECTIONS, []))
cg.add_define("BLUETOOTH_PROXY_MAX_CONNECTIONS", connection_count)
# Define batch size for BLE advertisements
# Each advertisement is up to 80 bytes when packaged (including protocol overhead)
# 16 advertisements × 80 bytes (worst case) = 1280 bytes out of ~1320 bytes usable payload
# This achieves ~97% WiFi MTU utilization while staying under the limit
cg.add_define("BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE", 16)
for connection_conf in config.get(CONF_CONNECTIONS, []):
connection_var = cg.new_Pvariable(connection_conf[CONF_ID])
await cg.register_component(connection_var, connection_conf)

View File

@@ -12,79 +12,16 @@ namespace esphome::bluetooth_proxy {
static const char *const TAG = "bluetooth_proxy.connection";
// This function is allocation-free and directly packs UUIDs into the output array
// using precalculated constants for the Bluetooth base UUID
static void fill_128bit_uuid_array(std::array<uint64_t, 2> &out, esp_bt_uuid_t uuid_source) {
// Bluetooth base UUID: 00000000-0000-1000-8000-00805F9B34FB
// out[0] = bytes 8-15 (big-endian)
// - For 128-bit UUIDs: use bytes 8-15 as-is
// - For 16/32-bit UUIDs: insert into bytes 12-15, use 0x00001000 for bytes 8-11
out[0] = uuid_source.len == ESP_UUID_LEN_128
? (((uint64_t) uuid_source.uuid.uuid128[15] << 56) | ((uint64_t) uuid_source.uuid.uuid128[14] << 48) |
((uint64_t) uuid_source.uuid.uuid128[13] << 40) | ((uint64_t) uuid_source.uuid.uuid128[12] << 32) |
((uint64_t) uuid_source.uuid.uuid128[11] << 24) | ((uint64_t) uuid_source.uuid.uuid128[10] << 16) |
((uint64_t) uuid_source.uuid.uuid128[9] << 8) | ((uint64_t) uuid_source.uuid.uuid128[8]))
: (((uint64_t) (uuid_source.len == ESP_UUID_LEN_16 ? uuid_source.uuid.uuid16 : uuid_source.uuid.uuid32)
<< 32) |
0x00001000ULL); // Base UUID bytes 8-11
// out[1] = bytes 0-7 (big-endian)
// - For 128-bit UUIDs: use bytes 0-7 as-is
// - For 16/32-bit UUIDs: use precalculated base UUID constant
out[1] = uuid_source.len == ESP_UUID_LEN_128
? ((uint64_t) uuid_source.uuid.uuid128[7] << 56) | ((uint64_t) uuid_source.uuid.uuid128[6] << 48) |
((uint64_t) uuid_source.uuid.uuid128[5] << 40) | ((uint64_t) uuid_source.uuid.uuid128[4] << 32) |
((uint64_t) uuid_source.uuid.uuid128[3] << 24) | ((uint64_t) uuid_source.uuid.uuid128[2] << 16) |
((uint64_t) uuid_source.uuid.uuid128[1] << 8) | ((uint64_t) uuid_source.uuid.uuid128[0])
: 0x800000805F9B34FBULL; // Base UUID bytes 0-7: 80-00-00-80-5F-9B-34-FB
}
// Helper to fill UUID in the appropriate format based on client support and UUID type
static void fill_gatt_uuid(std::array<uint64_t, 2> &uuid_128, uint32_t &short_uuid, const esp_bt_uuid_t &uuid,
bool use_efficient_uuids) {
if (!use_efficient_uuids || uuid.len == ESP_UUID_LEN_128) {
// Use 128-bit format for old clients or when UUID is already 128-bit
fill_128bit_uuid_array(uuid_128, uuid);
} else if (uuid.len == ESP_UUID_LEN_16) {
short_uuid = uuid.uuid.uuid16;
} else if (uuid.len == ESP_UUID_LEN_32) {
short_uuid = uuid.uuid.uuid32;
}
}
// Constants for size estimation
static constexpr uint8_t SERVICE_OVERHEAD_LEGACY = 25; // UUID(20) + handle(4) + overhead(1)
static constexpr uint8_t SERVICE_OVERHEAD_EFFICIENT = 10; // UUID(6) + handle(4)
static constexpr uint8_t CHAR_SIZE_128BIT = 35; // UUID(20) + handle(4) + props(4) + overhead(7)
static constexpr uint8_t DESC_SIZE_128BIT = 25; // UUID(20) + handle(4) + overhead(1)
static constexpr uint8_t DESC_SIZE_16BIT = 10; // UUID(6) + handle(4)
static constexpr uint8_t DESC_PER_CHAR = 1; // Assume 1 descriptor per characteristic
// Helper to estimate service size before fetching all data
/**
* Estimate the size of a Bluetooth service based on the number of characteristics and UUID format.
*
* @param char_count The number of characteristics in the service.
* @param use_efficient_uuids Whether to use efficient UUIDs (16-bit or 32-bit) for newer APIVersions.
* @return The estimated size of the service in bytes.
*
* This function calculates the size of a Bluetooth service by considering:
* - A service overhead, which depends on whether efficient UUIDs are used.
* - The size of each characteristic, assuming 128-bit UUIDs for safety.
* - The size of descriptors, assuming one 128-bit descriptor per characteristic.
*/
static size_t estimate_service_size(uint16_t char_count, bool use_efficient_uuids) {
size_t service_overhead = use_efficient_uuids ? SERVICE_OVERHEAD_EFFICIENT : SERVICE_OVERHEAD_LEGACY;
// Always assume 128-bit UUIDs for characteristics to be safe
size_t char_size = CHAR_SIZE_128BIT;
// Assume one 128-bit descriptor per characteristic
size_t desc_size = DESC_SIZE_128BIT * DESC_PER_CHAR;
return service_overhead + (char_size + desc_size) * char_count;
}
bool BluetoothConnection::supports_efficient_uuids_() const {
auto *api_conn = this->proxy_->get_api_connection();
return api_conn && api_conn->client_supports_api_version(1, 12);
esp_bt_uuid_t uuid = espbt::ESPBTUUID::from_uuid(uuid_source).as_128bit().get_uuid();
out[0] = ((uint64_t) uuid.uuid.uuid128[15] << 56) | ((uint64_t) uuid.uuid.uuid128[14] << 48) |
((uint64_t) uuid.uuid.uuid128[13] << 40) | ((uint64_t) uuid.uuid.uuid128[12] << 32) |
((uint64_t) uuid.uuid.uuid128[11] << 24) | ((uint64_t) uuid.uuid.uuid128[10] << 16) |
((uint64_t) uuid.uuid.uuid128[9] << 8) | ((uint64_t) uuid.uuid.uuid128[8]);
out[1] = ((uint64_t) uuid.uuid.uuid128[7] << 56) | ((uint64_t) uuid.uuid.uuid128[6] << 48) |
((uint64_t) uuid.uuid.uuid128[5] << 40) | ((uint64_t) uuid.uuid.uuid128[4] << 32) |
((uint64_t) uuid.uuid.uuid128[3] << 24) | ((uint64_t) uuid.uuid.uuid128[2] << 16) |
((uint64_t) uuid.uuid.uuid128[1] << 8) | ((uint64_t) uuid.uuid.uuid128[0]);
}
void BluetoothConnection::dump_config() {
@@ -92,53 +29,16 @@ void BluetoothConnection::dump_config() {
BLEClientBase::dump_config();
}
void BluetoothConnection::update_allocated_slot_(uint64_t find_value, uint64_t set_value) {
auto &allocated = this->proxy_->connections_free_response_.allocated;
for (auto &slot : allocated) {
if (slot == find_value) {
slot = set_value;
return;
}
}
}
void BluetoothConnection::set_address(uint64_t address) {
// If we're clearing an address (disconnecting), update the pre-allocated message
if (address == 0 && this->address_ != 0) {
this->proxy_->connections_free_response_.free++;
this->update_allocated_slot_(this->address_, 0);
}
// If we're setting a new address (connecting), update the pre-allocated message
else if (address != 0 && this->address_ == 0) {
this->proxy_->connections_free_response_.free--;
this->update_allocated_slot_(0, address);
}
// Call parent implementation to actually set the address
BLEClientBase::set_address(address);
}
void BluetoothConnection::loop() {
BLEClientBase::loop();
// Early return if no active connection
if (this->address_ == 0) {
// Early return if no active connection or not in service discovery phase
if (this->address_ == 0 || this->send_service_ < 0 || this->send_service_ > this->service_count_) {
return;
}
// Handle service discovery if in valid range
if (this->send_service_ >= 0 && this->send_service_ <= this->service_count_) {
this->send_service_for_discovery_();
}
// Check if we should disable the loop
// - For V3_WITH_CACHE: Services are never sent, disable after INIT state
// - For V3_WITHOUT_CACHE: Disable only after service discovery is complete
// (send_service_ == DONE_SENDING_SERVICES, which is only set after services are sent)
if (this->state_ != espbt::ClientState::INIT && (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE ||
this->send_service_ == DONE_SENDING_SERVICES)) {
this->disable_loop();
}
// Handle service discovery
this->send_service_for_discovery_();
}
void BluetoothConnection::reset_connection_(esp_err_t reason) {
@@ -152,222 +52,140 @@ void BluetoothConnection::reset_connection_(esp_err_t reason) {
// to detect incomplete service discovery rather than relying on us to
// tell them about a partial list.
this->set_address(0);
this->send_service_ = INIT_SENDING_SERVICES;
this->send_service_ = DONE_SENDING_SERVICES;
this->proxy_->send_connections_free();
}
void BluetoothConnection::send_service_for_discovery_() {
if (this->send_service_ >= this->service_count_) {
if (this->send_service_ == this->service_count_) {
this->send_service_ = DONE_SENDING_SERVICES;
this->proxy_->send_gatt_services_done(this->address_);
this->release_services();
if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE ||
this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
this->release_services();
}
return;
}
// Early return if no API connection
auto *api_conn = this->proxy_->get_api_connection();
if (api_conn == nullptr) {
this->send_service_ = DONE_SENDING_SERVICES;
return;
}
// Check if client supports efficient UUIDs
bool use_efficient_uuids = this->supports_efficient_uuids_();
// Send next service
esp_gattc_service_elem_t service_result;
uint16_t service_count = 1;
esp_gatt_status_t service_status = esp_ble_gattc_get_service(this->gattc_if_, this->conn_id_, nullptr,
&service_result, &service_count, this->send_service_);
this->send_service_++;
if (service_status != ESP_GATT_OK || service_count == 0) {
ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d",
this->connection_index_, this->address_str().c_str(), service_status != ESP_GATT_OK ? "error" : "missing",
service_status, service_count, this->send_service_ - 1);
return;
}
// Prepare response
api::BluetoothGATTGetServicesResponse resp;
resp.address = this->address_;
auto &service_resp = resp.services[0];
fill_128bit_uuid_array(service_resp.uuid, service_result.uuid);
service_resp.handle = service_result.start_handle;
// Dynamic batching based on actual size
// Conservative MTU limit for API messages (accounts for WPA3 overhead)
static constexpr size_t MAX_PACKET_SIZE = 1360;
// Get the number of characteristics directly with one call
uint16_t total_char_count = 0;
esp_gatt_status_t char_count_status =
esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_CHARACTERISTIC,
service_result.start_handle, service_result.end_handle, 0, &total_char_count);
// Keep running total of actual message size
size_t current_size = 0;
api::ProtoSize size;
resp.calculate_size(size);
current_size = size.get_size();
while (this->send_service_ < this->service_count_) {
esp_gattc_service_elem_t service_result;
uint16_t service_count = 1;
esp_gatt_status_t service_status = esp_ble_gattc_get_service(this->gattc_if_, this->conn_id_, nullptr,
&service_result, &service_count, this->send_service_);
if (service_status != ESP_GATT_OK || service_count == 0) {
ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_service %s, status=%d, service_count=%d, offset=%d",
this->connection_index_, this->address_str().c_str(),
service_status != ESP_GATT_OK ? "error" : "missing", service_status, service_count, this->send_service_);
this->send_service_ = DONE_SENDING_SERVICES;
return;
}
// Get the number of characteristics BEFORE adding to response
uint16_t total_char_count = 0;
esp_gatt_status_t char_count_status =
esp_ble_gattc_get_attr_count(this->gattc_if_, this->conn_id_, ESP_GATT_DB_CHARACTERISTIC,
service_result.start_handle, service_result.end_handle, 0, &total_char_count);
if (char_count_status != ESP_GATT_OK) {
this->log_connection_error_("esp_ble_gattc_get_attr_count", char_count_status);
this->send_service_ = DONE_SENDING_SERVICES;
return;
}
// If this service likely won't fit, send current batch (unless it's the first)
size_t estimated_size = estimate_service_size(total_char_count, use_efficient_uuids);
if (!resp.services.empty() && (current_size + estimated_size > MAX_PACKET_SIZE)) {
// This service likely won't fit, send current batch
break;
}
// Now add the service since we know it will likely fit
resp.services.emplace_back();
auto &service_resp = resp.services.back();
fill_gatt_uuid(service_resp.uuid, service_resp.short_uuid, service_result.uuid, use_efficient_uuids);
service_resp.handle = service_result.start_handle;
if (total_char_count > 0) {
// Reserve space and process characteristics
service_resp.characteristics.reserve(total_char_count);
uint16_t char_offset = 0;
esp_gattc_char_elem_t char_result;
while (true) { // characteristics
uint16_t char_count = 1;
esp_gatt_status_t char_status =
esp_ble_gattc_get_all_char(this->gattc_if_, this->conn_id_, service_result.start_handle,
service_result.end_handle, &char_result, &char_count, char_offset);
if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
break;
}
if (char_status != ESP_GATT_OK) {
this->log_connection_error_("esp_ble_gattc_get_all_char", char_status);
this->send_service_ = DONE_SENDING_SERVICES;
return;
}
if (char_count == 0) {
break;
}
service_resp.characteristics.emplace_back();
auto &characteristic_resp = service_resp.characteristics.back();
fill_gatt_uuid(characteristic_resp.uuid, characteristic_resp.short_uuid, char_result.uuid, use_efficient_uuids);
characteristic_resp.handle = char_result.char_handle;
characteristic_resp.properties = char_result.properties;
char_offset++;
// Get the number of descriptors directly with one call
uint16_t total_desc_count = 0;
esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
this->gattc_if_, this->conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
if (desc_count_status != ESP_GATT_OK) {
this->log_connection_error_("esp_ble_gattc_get_attr_count", desc_count_status);
this->send_service_ = DONE_SENDING_SERVICES;
return;
}
if (total_desc_count == 0) {
// No descriptors, continue to next characteristic
continue;
}
// Reserve space and process descriptors
characteristic_resp.descriptors.reserve(total_desc_count);
uint16_t desc_offset = 0;
esp_gattc_descr_elem_t desc_result;
while (true) { // descriptors
uint16_t desc_count = 1;
esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
this->gattc_if_, this->conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
break;
}
if (desc_status != ESP_GATT_OK) {
this->log_connection_error_("esp_ble_gattc_get_all_descr", desc_status);
this->send_service_ = DONE_SENDING_SERVICES;
return;
}
if (desc_count == 0) {
break; // No more descriptors
}
characteristic_resp.descriptors.emplace_back();
auto &descriptor_resp = characteristic_resp.descriptors.back();
fill_gatt_uuid(descriptor_resp.uuid, descriptor_resp.short_uuid, desc_result.uuid, use_efficient_uuids);
descriptor_resp.handle = desc_result.handle;
desc_offset++;
}
}
} // end if (total_char_count > 0)
// Calculate the actual size of just this service
api::ProtoSize service_sizer;
service_resp.calculate_size(service_sizer);
size_t service_size = service_sizer.get_size() + 1; // +1 for field tag
// Check if adding this service would exceed the limit
if (current_size + service_size > MAX_PACKET_SIZE) {
// We would go over - pop the last service if we have more than one
if (resp.services.size() > 1) {
resp.services.pop_back();
ESP_LOGD(TAG, "[%d] [%s] Service %d would exceed limit (current: %d + service: %d > %d), sending current batch",
this->connection_index_, this->address_str().c_str(), this->send_service_, current_size, service_size,
MAX_PACKET_SIZE);
// Don't increment send_service_ - we'll retry this service in next batch
} else {
// This single service is too large, but we have to send it anyway
ESP_LOGV(TAG, "[%d] [%s] Service %d is too large (%d bytes) but sending anyway", this->connection_index_,
this->address_str().c_str(), this->send_service_, service_size);
// Increment so we don't get stuck
this->send_service_++;
}
// Send what we have
break;
}
// Now we know we're keeping this service, add its size
current_size += service_size;
// Successfully added this service, increment counter
this->send_service_++;
if (char_count_status != ESP_GATT_OK) {
ESP_LOGW(TAG, "[%d] [%s] Error getting characteristic count, status=%d", this->connection_index_,
this->address_str().c_str(), char_count_status);
return;
}
// Send the message with dynamically batched services
if (total_char_count == 0) {
// No characteristics, just send the service response
api_conn->send_message(resp, api::BluetoothGATTGetServicesResponse::MESSAGE_TYPE);
return;
}
// Reserve space and process characteristics
service_resp.characteristics.reserve(total_char_count);
uint16_t char_offset = 0;
esp_gattc_char_elem_t char_result;
while (true) { // characteristics
uint16_t char_count = 1;
esp_gatt_status_t char_status =
esp_ble_gattc_get_all_char(this->gattc_if_, this->conn_id_, service_result.start_handle,
service_result.end_handle, &char_result, &char_count, char_offset);
if (char_status == ESP_GATT_INVALID_OFFSET || char_status == ESP_GATT_NOT_FOUND) {
break;
}
if (char_status != ESP_GATT_OK) {
ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_all_char error, status=%d", this->connection_index_,
this->address_str().c_str(), char_status);
return;
}
if (char_count == 0) {
break;
}
service_resp.characteristics.emplace_back();
auto &characteristic_resp = service_resp.characteristics.back();
fill_128bit_uuid_array(characteristic_resp.uuid, char_result.uuid);
characteristic_resp.handle = char_result.char_handle;
characteristic_resp.properties = char_result.properties;
char_offset++;
// Get the number of descriptors directly with one call
uint16_t total_desc_count = 0;
esp_gatt_status_t desc_count_status = esp_ble_gattc_get_attr_count(
this->gattc_if_, this->conn_id_, ESP_GATT_DB_DESCRIPTOR, 0, 0, char_result.char_handle, &total_desc_count);
if (desc_count_status != ESP_GATT_OK) {
ESP_LOGW(TAG, "[%d] [%s] Error getting descriptor count for char handle %d, status=%d", this->connection_index_,
this->address_str().c_str(), char_result.char_handle, desc_count_status);
return;
}
if (total_desc_count == 0) {
// No descriptors, continue to next characteristic
continue;
}
// Reserve space and process descriptors
characteristic_resp.descriptors.reserve(total_desc_count);
uint16_t desc_offset = 0;
esp_gattc_descr_elem_t desc_result;
while (true) { // descriptors
uint16_t desc_count = 1;
esp_gatt_status_t desc_status = esp_ble_gattc_get_all_descr(
this->gattc_if_, this->conn_id_, char_result.char_handle, &desc_result, &desc_count, desc_offset);
if (desc_status == ESP_GATT_INVALID_OFFSET || desc_status == ESP_GATT_NOT_FOUND) {
break;
}
if (desc_status != ESP_GATT_OK) {
ESP_LOGE(TAG, "[%d] [%s] esp_ble_gattc_get_all_descr error, status=%d", this->connection_index_,
this->address_str().c_str(), desc_status);
return;
}
if (desc_count == 0) {
break; // No more descriptors
}
characteristic_resp.descriptors.emplace_back();
auto &descriptor_resp = characteristic_resp.descriptors.back();
fill_128bit_uuid_array(descriptor_resp.uuid, desc_result.uuid);
descriptor_resp.handle = desc_result.handle;
desc_offset++;
}
}
// Send the message (we already checked api_conn is not null at the beginning)
api_conn->send_message(resp, api::BluetoothGATTGetServicesResponse::MESSAGE_TYPE);
}
void BluetoothConnection::log_connection_error_(const char *operation, esp_gatt_status_t status) {
ESP_LOGE(TAG, "[%d] [%s] %s error, status=%d", this->connection_index_, this->address_str().c_str(), operation,
status);
}
void BluetoothConnection::log_connection_warning_(const char *operation, esp_err_t err) {
ESP_LOGW(TAG, "[%d] [%s] %s failed, err=%d", this->connection_index_, this->address_str().c_str(), operation, err);
}
void BluetoothConnection::log_gatt_not_connected_(const char *action, const char *type) {
ESP_LOGW(TAG, "[%d] [%s] Cannot %s GATT %s, not connected.", this->connection_index_, this->address_str().c_str(),
action, type);
}
void BluetoothConnection::log_gatt_operation_error_(const char *operation, uint16_t handle, esp_gatt_status_t status) {
ESP_LOGW(TAG, "[%d] [%s] Error %s for handle 0x%2X, status=%d", this->connection_index_, this->address_str().c_str(),
operation, handle, status);
}
esp_err_t BluetoothConnection::check_and_log_error_(const char *operation, esp_err_t err) {
if (err != ESP_OK) {
this->log_connection_warning_(operation, err);
return err;
}
return ESP_OK;
}
bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) {
if (!BLEClientBase::gattc_event_handler(event, gattc_if, param))
@@ -375,19 +193,10 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
switch (event) {
case ESP_GATTC_DISCONNECT_EVT: {
// Don't reset connection yet - wait for CLOSE_EVT to ensure controller has freed resources
// This prevents race condition where we mark slot as free before controller cleanup is complete
ESP_LOGD(TAG, "[%d] [%s] Disconnect, reason=0x%02x", this->connection_index_, this->address_str_.c_str(),
param->disconnect.reason);
// Send disconnection notification but don't free the slot yet
this->proxy_->send_device_connection(this->address_, false, 0, param->disconnect.reason);
this->reset_connection_(param->disconnect.reason);
break;
}
case ESP_GATTC_CLOSE_EVT: {
ESP_LOGD(TAG, "[%d] [%s] Close, reason=0x%02x, freeing slot", this->connection_index_, this->address_str_.c_str(),
param->close.reason);
// Now the GATT connection is fully closed and controller resources are freed
// Safe to mark the connection slot as available
this->reset_connection_(param->close.reason);
break;
}
@@ -417,7 +226,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
case ESP_GATTC_READ_DESCR_EVT:
case ESP_GATTC_READ_CHAR_EVT: {
if (param->read.status != ESP_GATT_OK) {
this->log_gatt_operation_error_("reading char/descriptor", param->read.handle, param->read.status);
ESP_LOGW(TAG, "[%d] [%s] Error reading char/descriptor at handle 0x%2X, status=%d", this->connection_index_,
this->address_str_.c_str(), param->read.handle, param->read.status);
this->proxy_->send_gatt_error(this->address_, param->read.handle, param->read.status);
break;
}
@@ -431,7 +241,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
case ESP_GATTC_WRITE_CHAR_EVT:
case ESP_GATTC_WRITE_DESCR_EVT: {
if (param->write.status != ESP_GATT_OK) {
this->log_gatt_operation_error_("writing char/descriptor", param->write.handle, param->write.status);
ESP_LOGW(TAG, "[%d] [%s] Error writing char/descriptor at handle 0x%2X, status=%d", this->connection_index_,
this->address_str_.c_str(), param->write.handle, param->write.status);
this->proxy_->send_gatt_error(this->address_, param->write.handle, param->write.status);
break;
}
@@ -443,8 +254,9 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
}
case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
if (param->unreg_for_notify.status != ESP_GATT_OK) {
this->log_gatt_operation_error_("unregistering notifications", param->unreg_for_notify.handle,
param->unreg_for_notify.status);
ESP_LOGW(TAG, "[%d] [%s] Error unregistering notifications for handle 0x%2X, status=%d",
this->connection_index_, this->address_str_.c_str(), param->unreg_for_notify.handle,
param->unreg_for_notify.status);
this->proxy_->send_gatt_error(this->address_, param->unreg_for_notify.handle, param->unreg_for_notify.status);
break;
}
@@ -456,8 +268,8 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
}
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
if (param->reg_for_notify.status != ESP_GATT_OK) {
this->log_gatt_operation_error_("registering notifications", param->reg_for_notify.handle,
param->reg_for_notify.status);
ESP_LOGW(TAG, "[%d] [%s] Error registering notifications for handle 0x%2X, status=%d", this->connection_index_,
this->address_str_.c_str(), param->reg_for_notify.handle, param->reg_for_notify.status);
this->proxy_->send_gatt_error(this->address_, param->reg_for_notify.handle, param->reg_for_notify.status);
break;
}
@@ -503,7 +315,8 @@ void BluetoothConnection::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
if (!this->connected()) {
this->log_gatt_not_connected_("read", "characteristic");
ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT characteristic, not connected.", this->connection_index_,
this->address_str_.c_str());
return ESP_GATT_NOT_CONNECTED;
}
@@ -511,12 +324,18 @@ esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
handle);
esp_err_t err = esp_ble_gattc_read_char(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
return this->check_and_log_error_("esp_ble_gattc_read_char", err);
if (err != ERR_OK) {
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char error, err=%d", this->connection_index_,
this->address_str_.c_str(), err);
return err;
}
return ESP_OK;
}
esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::string &data, bool response) {
if (!this->connected()) {
this->log_gatt_not_connected_("write", "characteristic");
ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT characteristic, not connected.", this->connection_index_,
this->address_str_.c_str());
return ESP_GATT_NOT_CONNECTED;
}
ESP_LOGV(TAG, "[%d] [%s] Writing GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
@@ -525,24 +344,36 @@ esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::
esp_err_t err =
esp_ble_gattc_write_char(this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
return this->check_and_log_error_("esp_ble_gattc_write_char", err);
if (err != ERR_OK) {
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char error, err=%d", this->connection_index_,
this->address_str_.c_str(), err);
return err;
}
return ESP_OK;
}
esp_err_t BluetoothConnection::read_descriptor(uint16_t handle) {
if (!this->connected()) {
this->log_gatt_not_connected_("read", "descriptor");
ESP_LOGW(TAG, "[%d] [%s] Cannot read GATT descriptor, not connected.", this->connection_index_,
this->address_str_.c_str());
return ESP_GATT_NOT_CONNECTED;
}
ESP_LOGV(TAG, "[%d] [%s] Reading GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
handle);
esp_err_t err = esp_ble_gattc_read_char_descr(this->gattc_if_, this->conn_id_, handle, ESP_GATT_AUTH_REQ_NONE);
return this->check_and_log_error_("esp_ble_gattc_read_char_descr", err);
if (err != ERR_OK) {
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_read_char_descr error, err=%d", this->connection_index_,
this->address_str_.c_str(), err);
return err;
}
return ESP_OK;
}
esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::string &data, bool response) {
if (!this->connected()) {
this->log_gatt_not_connected_("write", "descriptor");
ESP_LOGW(TAG, "[%d] [%s] Cannot write GATT descriptor, not connected.", this->connection_index_,
this->address_str_.c_str());
return ESP_GATT_NOT_CONNECTED;
}
ESP_LOGV(TAG, "[%d] [%s] Writing GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
@@ -551,12 +382,18 @@ esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::stri
esp_err_t err = esp_ble_gattc_write_char_descr(
this->gattc_if_, this->conn_id_, handle, data.size(), (uint8_t *) data.data(),
response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
return this->check_and_log_error_("esp_ble_gattc_write_char_descr", err);
if (err != ERR_OK) {
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_write_char_descr error, err=%d", this->connection_index_,
this->address_str_.c_str(), err);
return err;
}
return ESP_OK;
}
esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enable) {
if (!this->connected()) {
this->log_gatt_not_connected_("notify", "characteristic");
ESP_LOGW(TAG, "[%d] [%s] Cannot notify GATT characteristic, not connected.", this->connection_index_,
this->address_str_.c_str());
return ESP_GATT_NOT_CONNECTED;
}
@@ -564,13 +401,22 @@ esp_err_t BluetoothConnection::notify_characteristic(uint16_t handle, bool enabl
ESP_LOGV(TAG, "[%d] [%s] Registering for GATT characteristic notifications handle %d", this->connection_index_,
this->address_str_.c_str(), handle);
esp_err_t err = esp_ble_gattc_register_for_notify(this->gattc_if_, this->remote_bda_, handle);
return this->check_and_log_error_("esp_ble_gattc_register_for_notify", err);
if (err != ESP_OK) {
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_register_for_notify failed, err=%d", this->connection_index_,
this->address_str_.c_str(), err);
return err;
}
} else {
ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications handle %d", this->connection_index_,
this->address_str_.c_str(), handle);
esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, handle);
if (err != ESP_OK) {
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_unregister_for_notify failed, err=%d", this->connection_index_,
this->address_str_.c_str(), err);
return err;
}
}
ESP_LOGV(TAG, "[%d] [%s] Unregistering for GATT characteristic notifications handle %d", this->connection_index_,
this->address_str_.c_str(), handle);
esp_err_t err = esp_ble_gattc_unregister_for_notify(this->gattc_if_, this->remote_bda_, handle);
return this->check_and_log_error_("esp_ble_gattc_unregister_for_notify", err);
return ESP_OK;
}
esp32_ble_tracker::AdvertisementParserType BluetoothConnection::get_advertisement_parser_type() {

View File

@@ -8,7 +8,7 @@ namespace esphome::bluetooth_proxy {
class BluetoothProxy;
class BluetoothConnection final : public esp32_ble_client::BLEClientBase {
class BluetoothConnection : public esp32_ble_client::BLEClientBase {
public:
void dump_config() override;
void loop() override;
@@ -24,27 +24,18 @@ class BluetoothConnection final : public esp32_ble_client::BLEClientBase {
esp_err_t notify_characteristic(uint16_t handle, bool enable);
void set_address(uint64_t address) override;
protected:
friend class BluetoothProxy;
bool supports_efficient_uuids_() const;
void send_service_for_discovery_();
void reset_connection_(esp_err_t reason);
void update_allocated_slot_(uint64_t find_value, uint64_t set_value);
void log_connection_error_(const char *operation, esp_gatt_status_t status);
void log_connection_warning_(const char *operation, esp_err_t err);
void log_gatt_not_connected_(const char *action, const char *type);
void log_gatt_operation_error_(const char *operation, uint16_t handle, esp_gatt_status_t status);
esp_err_t check_and_log_error_(const char *operation, esp_err_t err);
// Memory optimized layout for 32-bit systems
// Group 1: Pointers (4 bytes each, naturally aligned)
BluetoothProxy *proxy_;
// Group 2: 2-byte types
int16_t send_service_{-3}; // -3 = INIT_SENDING_SERVICES, -2 = DONE_SENDING_SERVICES, >=0 = service index
int16_t send_service_{-2}; // Needs to handle negative values and service count
// Group 3: 1-byte types
bool seen_mtu_or_services_{false};

View File

@@ -11,8 +11,12 @@ namespace esphome::bluetooth_proxy {
static const char *const TAG = "bluetooth_proxy";
// BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE is defined during code generation
// It sets the batch size for BLE advertisements to maximize WiFi efficiency
// Batch size for BLE advertisements to maximize WiFi efficiency
// Each advertisement is up to 80 bytes when packaged (including protocol overhead)
// Most advertisements are 20-30 bytes, allowing even more to fit per packet
// 16 advertisements × 80 bytes (worst case) = 1280 bytes out of ~1320 bytes usable payload
// This achieves ~97% WiFi MTU utilization while staying under the limit
static constexpr size_t FLUSH_BATCH_SIZE = 16;
// Verify BLE advertisement data array size matches the BLE specification (31 bytes adv + 31 bytes scan response)
static_assert(sizeof(((api::BluetoothLERawAdvertisement *) nullptr)->data) == 62,
@@ -21,11 +25,15 @@ static_assert(sizeof(((api::BluetoothLERawAdvertisement *) nullptr)->data) == 62
BluetoothProxy::BluetoothProxy() { global_bluetooth_proxy = this; }
void BluetoothProxy::setup() {
this->connections_free_response_.limit = BLUETOOTH_PROXY_MAX_CONNECTIONS;
this->connections_free_response_.free = BLUETOOTH_PROXY_MAX_CONNECTIONS;
// Pre-allocate response object
this->response_ = std::make_unique<api::BluetoothLERawAdvertisementsResponse>();
// Capture the configured scan mode from YAML before any API changes
this->configured_scan_active_ = this->parent_->get_scan_active();
// Reserve capacity but start with size 0
// Reserve 50% since we'll grow naturally and flush at FLUSH_BATCH_SIZE
this->response_->advertisements.reserve(FLUSH_BATCH_SIZE / 2);
// Don't pre-allocate pool - let it grow only if needed in busy environments
// Many devices in quiet areas will never need the overflow pool
this->parent_->add_scanner_state_callback([this](esp32_ble_tracker::ScannerState state) {
if (this->api_connection_ != nullptr) {
@@ -39,32 +47,9 @@ void BluetoothProxy::send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerSta
resp.state = static_cast<api::enums::BluetoothScannerState>(state);
resp.mode = this->parent_->get_scan_active() ? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE
: api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE;
resp.configured_mode = this->configured_scan_active_
? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE
: api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE;
this->api_connection_->send_message(resp, api::BluetoothScannerStateResponse::MESSAGE_TYPE);
}
void BluetoothProxy::log_connection_request_ignored_(BluetoothConnection *connection, espbt::ClientState state) {
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, state: %s", connection->get_connection_index(),
connection->address_str().c_str(), espbt::client_state_to_string(state));
}
void BluetoothProxy::log_connection_info_(BluetoothConnection *connection, const char *message) {
ESP_LOGI(TAG, "[%d] [%s] Connecting %s", connection->get_connection_index(), connection->address_str().c_str(),
message);
}
void BluetoothProxy::log_not_connected_gatt_(const char *action, const char *type) {
ESP_LOGW(TAG, "Cannot %s GATT %s, not connected", action, type);
}
void BluetoothProxy::handle_gatt_not_connected_(uint64_t address, uint16_t handle, const char *action,
const char *type) {
this->log_not_connected_gatt_(action, type);
this->send_gatt_error(address, handle, ESP_GATT_NOT_CONNECTED);
}
#ifdef USE_ESP32_BLE_DEVICE
bool BluetoothProxy::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
// This method should never be called since bluetooth_proxy always uses raw advertisements
@@ -77,27 +62,39 @@ bool BluetoothProxy::parse_devices(const esp32_ble::BLEScanResult *scan_results,
if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr)
return false;
auto &advertisements = this->response_.advertisements;
auto &advertisements = this->response_->advertisements;
for (size_t i = 0; i < count; i++) {
auto &result = scan_results[i];
uint8_t length = result.adv_data_len + result.scan_rsp_len;
// Check if we need to expand the vector
if (this->advertisement_count_ >= advertisements.size()) {
if (this->advertisement_pool_.empty()) {
// No room in pool, need to allocate
advertisements.emplace_back();
} else {
// Pull from pool
advertisements.push_back(std::move(this->advertisement_pool_.back()));
this->advertisement_pool_.pop_back();
}
}
// Fill in the data directly at current position
auto &adv = advertisements[this->response_.advertisements_len];
auto &adv = advertisements[this->advertisement_count_];
adv.address = esp32_ble::ble_addr_to_uint64(result.bda);
adv.rssi = result.rssi;
adv.address_type = result.ble_addr_type;
adv.data_len = length;
std::memcpy(adv.data, result.ble_adv, length);
this->response_.advertisements_len++;
this->advertisement_count_++;
ESP_LOGV(TAG, "Queuing raw packet from %02X:%02X:%02X:%02X:%02X:%02X, length %d. RSSI: %d dB", result.bda[0],
result.bda[1], result.bda[2], result.bda[3], result.bda[4], result.bda[5], length, result.rssi);
// Flush if we have reached BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE
if (this->response_.advertisements_len >= BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE) {
// Flush if we have reached FLUSH_BATCH_SIZE
if (this->advertisement_count_ >= FLUSH_BATCH_SIZE) {
this->flush_pending_advertisements();
}
}
@@ -106,31 +103,54 @@ bool BluetoothProxy::parse_devices(const esp32_ble::BLEScanResult *scan_results,
}
void BluetoothProxy::flush_pending_advertisements() {
if (this->response_.advertisements_len == 0 || !api::global_api_server->is_connected() ||
this->api_connection_ == nullptr)
if (this->advertisement_count_ == 0 || !api::global_api_server->is_connected() || this->api_connection_ == nullptr)
return;
auto &advertisements = this->response_->advertisements;
// Return any items beyond advertisement_count_ to the pool
if (advertisements.size() > this->advertisement_count_) {
// Move unused items back to pool
this->advertisement_pool_.insert(this->advertisement_pool_.end(),
std::make_move_iterator(advertisements.begin() + this->advertisement_count_),
std::make_move_iterator(advertisements.end()));
// Resize to actual count
advertisements.resize(this->advertisement_count_);
}
// Send the message
this->api_connection_->send_message(this->response_, api::BluetoothLERawAdvertisementsResponse::MESSAGE_TYPE);
this->api_connection_->send_message(*this->response_, api::BluetoothLERawAdvertisementsResponse::MESSAGE_TYPE);
ESP_LOGV(TAG, "Sent batch of %u BLE advertisements", this->response_.advertisements_len);
// Reset the length for the next batch
this->response_.advertisements_len = 0;
// Reset count - existing items will be overwritten in next batch
this->advertisement_count_ = 0;
}
void BluetoothProxy::dump_config() {
ESP_LOGCONFIG(TAG, "Bluetooth Proxy:");
ESP_LOGCONFIG(TAG,
"Bluetooth Proxy:\n"
" Active: %s\n"
" Connections: %d",
YESNO(this->active_), this->connection_count_);
YESNO(this->active_), this->connections_.size());
}
int BluetoothProxy::get_bluetooth_connections_free() {
int free = 0;
for (auto *connection : this->connections_) {
if (connection->address_ == 0) {
free++;
ESP_LOGV(TAG, "[%d] Free connection", connection->get_connection_index());
} else {
ESP_LOGV(TAG, "[%d] Used connection by [%s]", connection->get_connection_index(),
connection->address_str().c_str());
}
}
return free;
}
void BluetoothProxy::loop() {
if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr) {
for (uint8_t i = 0; i < this->connection_count_; i++) {
auto *connection = this->connections_[i];
for (auto *connection : this->connections_) {
if (connection->get_address() != 0 && !connection->disconnect_pending()) {
connection->disconnect();
}
@@ -153,8 +173,7 @@ esp32_ble_tracker::AdvertisementParserType BluetoothProxy::get_advertisement_par
}
BluetoothConnection *BluetoothProxy::get_connection_(uint64_t address, bool reserve) {
for (uint8_t i = 0; i < this->connection_count_; i++) {
auto *connection = this->connections_[i];
for (auto *connection : this->connections_) {
if (connection->get_address() == address)
return connection;
}
@@ -162,10 +181,9 @@ BluetoothConnection *BluetoothProxy::get_connection_(uint64_t address, bool rese
if (!reserve)
return nullptr;
for (uint8_t i = 0; i < this->connection_count_; i++) {
auto *connection = this->connections_[i];
for (auto *connection : this->connections_) {
if (connection->get_address() == 0) {
connection->send_service_ = INIT_SENDING_SERVICES;
connection->send_service_ = DONE_SENDING_SERVICES;
connection->set_address(address);
// All connections must start at INIT
// We only set the state if we allocate the connection
@@ -182,25 +200,33 @@ BluetoothConnection *BluetoothProxy::get_connection_(uint64_t address, bool rese
void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest &msg) {
switch (msg.request_type) {
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE:
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE: {
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE:
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT: {
auto *connection = this->get_connection_(msg.address, true);
if (connection == nullptr) {
ESP_LOGW(TAG, "No free connections available");
this->send_device_connection(msg.address, false);
return;
}
if (!msg.has_address_type) {
ESP_LOGE(TAG, "[%d] [%s] Missing address type in connect request", connection->get_connection_index(),
connection->address_str().c_str());
this->send_device_connection(msg.address, false);
return;
}
if (connection->state() == espbt::ClientState::CONNECTED ||
connection->state() == espbt::ClientState::ESTABLISHED) {
this->log_connection_request_ignored_(connection, connection->state());
ESP_LOGW(TAG, "[%d] [%s] Connection already established", connection->get_connection_index(),
connection->address_str().c_str());
this->send_device_connection(msg.address, true);
this->send_connections_free();
return;
} else if (connection->state() == espbt::ClientState::SEARCHING) {
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, already searching for device",
connection->get_connection_index(), connection->address_str().c_str());
return;
} else if (connection->state() == espbt::ClientState::DISCOVERED) {
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, device already discovered",
connection->get_connection_index(), connection->address_str().c_str());
return;
} else if (connection->state() == espbt::ClientState::READY_TO_CONNECT) {
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, waiting in line to connect",
connection->get_connection_index(), connection->address_str().c_str());
return;
} else if (connection->state() == espbt::ClientState::CONNECTING) {
if (connection->disconnect_pending()) {
ESP_LOGW(TAG, "[%d] [%s] Connection request while pending disconnect, cancelling pending disconnect",
@@ -208,22 +234,37 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest
connection->cancel_pending_disconnect();
return;
}
this->log_connection_request_ignored_(connection, connection->state());
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, already connecting", connection->get_connection_index(),
connection->address_str().c_str());
return;
} else if (connection->state() == espbt::ClientState::DISCONNECTING) {
ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, device is disconnecting",
connection->get_connection_index(), connection->address_str().c_str());
return;
} else if (connection->state() != espbt::ClientState::INIT) {
this->log_connection_request_ignored_(connection, connection->state());
ESP_LOGW(TAG, "[%d] [%s] Connection already in progress", connection->get_connection_index(),
connection->address_str().c_str());
return;
}
if (msg.request_type == api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE) {
connection->set_connection_type(espbt::ConnectionType::V3_WITH_CACHE);
this->log_connection_info_(connection, "v3 with cache");
} else { // BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE
ESP_LOGI(TAG, "[%d] [%s] Connecting v3 with cache", connection->get_connection_index(),
connection->address_str().c_str());
} else if (msg.request_type == api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE) {
connection->set_connection_type(espbt::ConnectionType::V3_WITHOUT_CACHE);
this->log_connection_info_(connection, "v3 without cache");
ESP_LOGI(TAG, "[%d] [%s] Connecting v3 without cache", connection->get_connection_index(),
connection->address_str().c_str());
} else {
connection->set_connection_type(espbt::ConnectionType::V1);
ESP_LOGI(TAG, "[%d] [%s] Connecting v1", connection->get_connection_index(), connection->address_str().c_str());
}
if (msg.has_address_type) {
uint64_to_bd_addr(msg.address, connection->remote_bda_);
connection->set_remote_addr_type(static_cast<esp_ble_addr_type_t>(msg.address_type));
connection->set_state(espbt::ClientState::DISCOVERED);
} else {
connection->set_state(espbt::ClientState::SEARCHING);
}
uint64_to_bd_addr(msg.address, connection->remote_bda_);
connection->set_remote_addr_type(static_cast<esp_ble_addr_type_t>(msg.address_type));
connection->set_state(espbt::ClientState::DISCOVERED);
this->send_connections_free();
break;
}
@@ -277,18 +318,14 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest
break;
}
case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT: {
ESP_LOGE(TAG, "V1 connections removed");
this->send_device_connection(msg.address, false);
break;
}
}
}
void BluetoothProxy::bluetooth_gatt_read(const api::BluetoothGATTReadRequest &msg) {
auto *connection = this->get_connection_(msg.address, false);
if (connection == nullptr) {
this->handle_gatt_not_connected_(msg.address, msg.handle, "read", "characteristic");
ESP_LOGW(TAG, "Cannot read GATT characteristic, not connected");
this->send_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
return;
}
@@ -301,7 +338,8 @@ void BluetoothProxy::bluetooth_gatt_read(const api::BluetoothGATTReadRequest &ms
void BluetoothProxy::bluetooth_gatt_write(const api::BluetoothGATTWriteRequest &msg) {
auto *connection = this->get_connection_(msg.address, false);
if (connection == nullptr) {
this->handle_gatt_not_connected_(msg.address, msg.handle, "write", "characteristic");
ESP_LOGW(TAG, "Cannot write GATT characteristic, not connected");
this->send_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
return;
}
@@ -314,7 +352,8 @@ void BluetoothProxy::bluetooth_gatt_write(const api::BluetoothGATTWriteRequest &
void BluetoothProxy::bluetooth_gatt_read_descriptor(const api::BluetoothGATTReadDescriptorRequest &msg) {
auto *connection = this->get_connection_(msg.address, false);
if (connection == nullptr) {
this->handle_gatt_not_connected_(msg.address, msg.handle, "read", "descriptor");
ESP_LOGW(TAG, "Cannot read GATT descriptor, not connected");
this->send_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
return;
}
@@ -327,7 +366,8 @@ void BluetoothProxy::bluetooth_gatt_read_descriptor(const api::BluetoothGATTRead
void BluetoothProxy::bluetooth_gatt_write_descriptor(const api::BluetoothGATTWriteDescriptorRequest &msg) {
auto *connection = this->get_connection_(msg.address, false);
if (connection == nullptr) {
this->handle_gatt_not_connected_(msg.address, msg.handle, "write", "descriptor");
ESP_LOGW(TAG, "Cannot write GATT descriptor, not connected");
this->send_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
return;
}
@@ -340,7 +380,8 @@ void BluetoothProxy::bluetooth_gatt_write_descriptor(const api::BluetoothGATTWri
void BluetoothProxy::bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg) {
auto *connection = this->get_connection_(msg.address, false);
if (connection == nullptr || !connection->connected()) {
this->handle_gatt_not_connected_(msg.address, 0, "get", "services");
ESP_LOGW(TAG, "Cannot get GATT services, not connected");
this->send_gatt_error(msg.address, 0, ESP_GATT_NOT_CONNECTED);
return;
}
if (!connection->service_count_) {
@@ -348,14 +389,16 @@ void BluetoothProxy::bluetooth_gatt_send_services(const api::BluetoothGATTGetSer
this->send_gatt_services_done(msg.address);
return;
}
if (connection->send_service_ == INIT_SENDING_SERVICES) // Start sending services if not started yet
if (connection->send_service_ ==
DONE_SENDING_SERVICES) // Only start sending services if we're not already sending them
connection->send_service_ = 0;
}
void BluetoothProxy::bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg) {
auto *connection = this->get_connection_(msg.address, false);
if (connection == nullptr) {
this->handle_gatt_not_connected_(msg.address, msg.handle, "notify", "characteristic");
ESP_LOGW(TAG, "Cannot notify GATT characteristic, not connected");
this->send_gatt_error(msg.address, msg.handle, ESP_GATT_NOT_CONNECTED);
return;
}
@@ -396,13 +439,17 @@ void BluetoothProxy::send_device_connection(uint64_t address, bool connected, ui
this->api_connection_->send_message(call, api::BluetoothDeviceConnectionResponse::MESSAGE_TYPE);
}
void BluetoothProxy::send_connections_free() {
if (this->api_connection_ != nullptr) {
this->send_connections_free(this->api_connection_);
if (this->api_connection_ == nullptr)
return;
api::BluetoothConnectionsFreeResponse call;
call.free = this->get_bluetooth_connections_free();
call.limit = this->get_bluetooth_connections_limit();
for (auto *connection : this->connections_) {
if (connection->address_ != 0) {
call.allocated.push_back(connection->address_);
}
}
}
void BluetoothProxy::send_connections_free(api::APIConnection *api_connection) {
api_connection->send_message(this->connections_free_response_, api::BluetoothConnectionsFreeResponse::MESSAGE_TYPE);
this->api_connection_->send_message(call, api::BluetoothConnectionsFreeResponse::MESSAGE_TYPE);
}
void BluetoothProxy::send_gatt_services_done(uint64_t address) {

View File

@@ -2,7 +2,6 @@
#ifdef USE_ESP32
#include <array>
#include <map>
#include <vector>
@@ -23,7 +22,6 @@ namespace esphome::bluetooth_proxy {
static const esp_err_t ESP_GATT_NOT_CONNECTED = -1;
static const int DONE_SENDING_SERVICES = -2;
static const int INIT_SENDING_SERVICES = -3;
using namespace esp32_ble_client;
@@ -50,8 +48,7 @@ enum BluetoothProxySubscriptionFlag : uint32_t {
SUBSCRIPTION_RAW_ADVERTISEMENTS = 1 << 0,
};
class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, public Component {
friend class BluetoothConnection; // Allow connection to update connections_free_response_
class BluetoothProxy : public esp32_ble_tracker::ESPBTDeviceListener, public Component {
public:
BluetoothProxy();
#ifdef USE_ESP32_BLE_DEVICE
@@ -65,10 +62,8 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, publ
esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override;
void register_connection(BluetoothConnection *connection) {
if (this->connection_count_ < BLUETOOTH_PROXY_MAX_CONNECTIONS) {
this->connections_[this->connection_count_++] = connection;
connection->proxy_ = this;
}
this->connections_.push_back(connection);
connection->proxy_ = this;
}
void bluetooth_device_request(const api::BluetoothDeviceRequest &msg);
@@ -79,13 +74,15 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, publ
void bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg);
void bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg);
int get_bluetooth_connections_free();
int get_bluetooth_connections_limit() { return this->connections_.size(); }
void subscribe_api_connection(api::APIConnection *api_connection, uint32_t flags);
void unsubscribe_api_connection(api::APIConnection *api_connection);
api::APIConnection *get_api_connection() { return this->api_connection_; }
void send_device_connection(uint64_t address, bool connected, uint16_t mtu = 0, esp_err_t error = ESP_OK);
void send_connections_free();
void send_connections_free(api::APIConnection *api_connection);
void send_gatt_services_done(uint64_t address);
void send_gatt_error(uint64_t address, uint16_t handle, esp_err_t error);
void send_device_pairing(uint64_t address, bool paired, esp_err_t error = ESP_OK);
@@ -130,41 +127,32 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, publ
std::string get_bluetooth_mac_address_pretty() {
const uint8_t *mac = esp_bt_dev_get_address();
char buf[18];
format_mac_addr_upper(mac, buf);
return std::string(buf);
return str_snprintf("%02X:%02X:%02X:%02X:%02X:%02X", 17, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
protected:
void send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerState state);
BluetoothConnection *get_connection_(uint64_t address, bool reserve);
void log_connection_request_ignored_(BluetoothConnection *connection, espbt::ClientState state);
void log_connection_info_(BluetoothConnection *connection, const char *message);
void log_not_connected_gatt_(const char *action, const char *type);
void handle_gatt_not_connected_(uint64_t address, uint16_t handle, const char *action, const char *type);
// Memory optimized layout for 32-bit systems
// Group 1: Pointers (4 bytes each, naturally aligned)
api::APIConnection *api_connection_{nullptr};
// Group 2: Fixed-size array of connection pointers
std::array<BluetoothConnection *, BLUETOOTH_PROXY_MAX_CONNECTIONS> connections_{};
// Group 2: Container types (typically 12 bytes on 32-bit)
std::vector<BluetoothConnection *> connections_{};
// BLE advertisement batching
api::BluetoothLERawAdvertisementsResponse response_;
std::vector<api::BluetoothLERawAdvertisement> advertisement_pool_;
std::unique_ptr<api::BluetoothLERawAdvertisementsResponse> response_;
// Group 3: 4-byte types
uint32_t last_advertisement_flush_time_{0};
// Pre-allocated response message - always ready to send
api::BluetoothConnectionsFreeResponse connections_free_response_;
// Group 4: 1-byte types grouped together
bool active_;
uint8_t connection_count_{0};
bool configured_scan_active_{false}; // Configured scan mode from YAML
// 3 bytes used, 1 byte padding
uint8_t advertisement_count_{0};
// 2 bytes used, 2 bytes padding
};
extern BluetoothProxy *global_bluetooth_proxy; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)

View File

@@ -7,8 +7,6 @@
#include <esphome/components/sensor/sensor.h>
#include <esphome/core/component.h>
#define BME280_ERROR_WRONG_CHIP_ID "Wrong chip ID"
namespace esphome {
namespace bme280_base {
@@ -100,18 +98,18 @@ void BME280Component::setup() {
if (!this->read_byte(BME280_REGISTER_CHIPID, &chip_id)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
this->mark_failed();
return;
}
if (chip_id != 0x60) {
this->error_code_ = WRONG_CHIP_ID;
this->mark_failed(BME280_ERROR_WRONG_CHIP_ID);
this->mark_failed();
return;
}
// Send a soft reset.
if (!this->write_byte(BME280_REGISTER_RESET, BME280_SOFT_RESET)) {
this->mark_failed("Reset failed");
this->mark_failed();
return;
}
// Wait until the NVM data has finished loading.
@@ -120,12 +118,14 @@ void BME280Component::setup() {
do { // NOLINT
delay(2);
if (!this->read_byte(BME280_REGISTER_STATUS, &status)) {
this->mark_failed("Error reading status register");
ESP_LOGW(TAG, "Error reading status register.");
this->mark_failed();
return;
}
} while ((status & BME280_STATUS_IM_UPDATE) && (--retry));
if (status & BME280_STATUS_IM_UPDATE) {
this->mark_failed("Timeout loading NVM");
ESP_LOGW(TAG, "Timeout loading NVM.");
this->mark_failed();
return;
}
@@ -153,26 +153,26 @@ void BME280Component::setup() {
uint8_t humid_control_val = 0;
if (!this->read_byte(BME280_REGISTER_CONTROLHUMID, &humid_control_val)) {
this->mark_failed("Read humidity control");
this->mark_failed();
return;
}
humid_control_val &= ~0b00000111;
humid_control_val |= this->humidity_oversampling_ & 0b111;
if (!this->write_byte(BME280_REGISTER_CONTROLHUMID, humid_control_val)) {
this->mark_failed("Write humidity control");
this->mark_failed();
return;
}
uint8_t config_register = 0;
if (!this->read_byte(BME280_REGISTER_CONFIG, &config_register)) {
this->mark_failed("Read config");
this->mark_failed();
return;
}
config_register &= ~0b11111100;
config_register |= 0b101 << 5; // 1000 ms standby time
config_register |= (this->iir_filter_ & 0b111) << 2;
if (!this->write_byte(BME280_REGISTER_CONFIG, config_register)) {
this->mark_failed("Write config");
this->mark_failed();
return;
}
}
@@ -183,7 +183,7 @@ void BME280Component::dump_config() {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case WRONG_CHIP_ID:
ESP_LOGE(TAG, BME280_ERROR_WRONG_CHIP_ID);
ESP_LOGE(TAG, "BME280 has wrong chip ID! Is it a BME280?");
break;
case NONE:
default:
@@ -223,21 +223,21 @@ void BME280Component::update() {
this->set_timeout("data", uint32_t(ceilf(meas_time)), [this]() {
uint8_t data[8];
if (!this->read_bytes(BME280_REGISTER_MEASUREMENTS, data, 8)) {
ESP_LOGW(TAG, "Error reading registers");
ESP_LOGW(TAG, "Error reading registers.");
this->status_set_warning();
return;
}
int32_t t_fine = 0;
float const temperature = this->read_temperature_(data, &t_fine);
if (std::isnan(temperature)) {
ESP_LOGW(TAG, "Invalid temperature");
ESP_LOGW(TAG, "Invalid temperature, cannot read pressure & humidity values.");
this->status_set_warning();
return;
}
float const pressure = this->read_pressure_(data, t_fine);
float const humidity = this->read_humidity_(data, t_fine);
ESP_LOGV(TAG, "Temperature=%.1f°C Pressure=%.1fhPa Humidity=%.1f%%", temperature, pressure, humidity);
ESP_LOGV(TAG, "Got temperature=%.1f°C pressure=%.1fhPa humidity=%.1f%%", temperature, pressure, humidity);
if (this->temperature_sensor_ != nullptr)
this->temperature_sensor_->publish_state(temperature);
if (this->pressure_sensor_ != nullptr)

View File

@@ -28,7 +28,7 @@ const float BME680_GAS_LOOKUP_TABLE_1[16] PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.0,
const float BME680_GAS_LOOKUP_TABLE_2[16] PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8,
-0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
[[maybe_unused]] static const char *oversampling_to_str(BME680Oversampling oversampling) {
static const char *oversampling_to_str(BME680Oversampling oversampling) {
switch (oversampling) {
case BME680_OVERSAMPLING_NONE:
return "None";
@@ -47,7 +47,7 @@ const float BME680_GAS_LOOKUP_TABLE_2[16] PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.1, 0
}
}
[[maybe_unused]] static const char *iir_filter_to_str(BME680IIRFilter filter) {
static const char *iir_filter_to_str(BME680IIRFilter filter) {
switch (filter) {
case BME680_IIR_FILTER_OFF:
return "OFF";

View File

@@ -203,7 +203,7 @@ void BMI160Component::dump_config() {
i2c::ErrorCode BMI160Component::read_le_int16_(uint8_t reg, int16_t *value, uint8_t len) {
uint8_t raw_data[len * 2];
// read using read_register because we have little-endian data, and read_bytes_16 will swap it
i2c::ErrorCode err = this->read_register(reg, raw_data, len * 2);
i2c::ErrorCode err = this->read_register(reg, raw_data, len * 2, true);
if (err != i2c::ERROR_OK) {
return err;
}

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