1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-14 22:05:54 +00:00

Compare commits

..

940 Commits

Author SHA1 Message Date
J. Nick Koston
217e5a4833 cleanups 2025-11-11 14:05:55 -06:00
J. Nick Koston
fd3689dd64 cleanup 2025-11-11 14:00:25 -06:00
J. Nick Koston
c166e063f9 cleanups 2025-11-11 13:55:29 -06:00
J. Nick Koston
8b6400f24c Fix scan failing after restart 2025-11-11 13:12:10 -06:00
J. Nick Koston
bbff660499 Merge branch 'integration' into memory_api 2025-11-11 12:19:33 -06:00
J. Nick Koston
366e95f8d8 Merge branch 'integration' into memory_api 2025-11-11 11:25:11 -06:00
J. Nick Koston
dbbc4f741d Merge branch 'integration' into memory_api 2025-11-11 11:23:02 -06:00
J. Nick Koston
300bd420f8 Merge branch 'integration' into memory_api 2025-11-11 11:19:12 -06:00
J. Nick Koston
e42b29659b Merge branch 'integration' into memory_api 2025-11-11 09:44:58 -06:00
J. Nick Koston
d2e1fbd76b Merge branch 'integration' into memory_api 2025-11-11 09:17:19 -06:00
J. Nick Koston
649e27bf62 Merge branch 'integration' into memory_api 2025-11-11 08:53:53 -06:00
J. Nick Koston
4565b126e2 Merge branch 'integration' into memory_api 2025-11-11 08:32:27 -06:00
J. Nick Koston
f28566545f Merge branch 'integration' into memory_api 2025-11-10 22:25:51 -06:00
J. Nick Koston
b8e4efc1cd manual_ip test 2025-11-10 22:23:02 -06:00
J. Nick Koston
cf66c4cd3e Merge branch 'integration' into memory_api 2025-11-10 22:14:11 -06:00
J. Nick Koston
bb51c6b6d5 Merge branch 'integration' into memory_api 2025-11-10 21:59:32 -06:00
J. Nick Koston
682b6711f3 Merge branch 'integration' into memory_api 2025-11-10 20:44:42 -06:00
J. Nick Koston
caf6045485 Merge branch 'integration' into memory_api 2025-11-10 20:24:34 -06:00
J. Nick Koston
e4c3ae4b16 Merge branch 'integration' into memory_api 2025-11-10 19:20:45 -06:00
J. Nick Koston
80e4eefc4c Merge branch 'integration' into memory_api 2025-11-10 19:18:05 -06:00
J. Nick Koston
5dc914268c Merge branch 'integration' into memory_api 2025-11-10 19:13:29 -06:00
J. Nick Koston
e263b3194e Merge branch 'integration' into memory_api 2025-11-10 18:30:28 -06:00
J. Nick Koston
16075e37f5 Merge branch 'integration' into memory_api 2025-11-10 00:00:19 -06:00
J. Nick Koston
057aede0cd Merge branch 'integration' into memory_api 2025-11-09 23:59:53 -06:00
J. Nick Koston
ff329a1476 Merge branch 'integration' into memory_api 2025-11-08 23:47:37 -06:00
J. Nick Koston
8cc89ea7ab Merge branch 'integration' into memory_api 2025-11-08 23:43:35 -06:00
J. Nick Koston
0709c21b8c Merge branch 'integration' into memory_api 2025-11-08 22:57:40 -06:00
J. Nick Koston
d9503344e3 Merge branch 'intt egration' into memory_api 2025-11-08 21:45:29 -06:00
J. Nick Koston
0ab8ce2bdc Merge branch 'integration' into memory_api 2025-11-08 21:19:58 -06:00
J. Nick Koston
c8d9232bd3 Merge branch 'integration' into memory_api 2025-11-08 19:20:19 -06:00
J. Nick Koston
1329d1af88 Merge branch 'integration' into memory_api 2025-11-07 17:17:11 -06:00
J. Nick Koston
0bf2dff056 Merge branch 'integration' into memory_api 2025-11-07 14:35:11 -06:00
J. Nick Koston
9b3f9ee70d Merge branch 'integration' into memory_api 2025-11-07 14:09:19 -06:00
J. Nick Koston
cf8b88b335 Merge branch 'integration' into memory_api 2025-11-06 18:10:12 -06:00
J. Nick Koston
398b5337c2 Merge branch 'integration' into memory_api 2025-11-06 09:58:45 -06:00
J. Nick Koston
d80822573a Merge branch 'integration' into memory_api 2025-11-05 23:47:31 -06:00
J. Nick Koston
1e58c400ea Revert "free"
This reverts commit fbc3413ed9.
2025-11-05 23:47:28 -06:00
J. Nick Koston
fbc3413ed9 free 2025-11-05 23:00:40 -06:00
J. Nick Koston
754eaab3be Merge branch 'integration' into memory_api 2025-11-05 22:51:10 -06:00
J. Nick Koston
f0e52227f2 Merge branch 'integration' into memory_api 2025-11-05 21:28:25 -06:00
J. Nick Koston
ef19d7bb24 Merge branch 'integration' into memory_api 2025-11-05 21:22:24 -06:00
J. Nick Koston
afe4ef17b7 Merge branch 'integration' into memory_api 2025-11-05 19:18:03 -06:00
J. Nick Koston
784dc358f0 Merge branch 'integration' into memory_api 2025-11-05 19:02:28 -06:00
J. Nick Koston
b3fdef3ac4 Merge branch 'integration' into memory_api 2025-11-05 18:59:08 -06:00
J. Nick Koston
4810c36141 [api] Store YAML service names in flash instead of heap
Reduces memory usage for YAML-defined API services by storing service
names and argument names as pointers to string literals in flash instead
of heap-allocated std::string objects.

Implementation:
- Created UserServiceBase<Ts...> for YAML services (const char* storage)
- Created UserServiceDynamic<Ts...> for custom_api_device (std::string storage)
- Updated CustomAPIDeviceService to inherit from UserServiceDynamic
- UserServiceTrigger uses UserServiceBase (YAML-only)

Memory savings per YAML service:
- 0 args: 32 bytes (57% reduction)
- 2 args: 48 bytes (60% reduction)
- 5 args: 96 bytes (63% reduction)

Custom API device services maintain same memory footprint (no regression).

Typical ESPHome device (2-5 services): 100-240 bytes saved
High-service device (10+ services): 400-800 bytes saved

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 18:49:58 -06:00
J. Nick Koston
351262aea9 Merge branch 'integration' into memory_api 2025-11-05 18:06:09 -06:00
J. Nick Koston
6d390d5b88 Merge branch 'integration' into memory_api 2025-11-05 12:36:32 -06:00
J. Nick Koston
0d2cdc5ce5 Merge branch 'integration' into memory_api 2025-11-05 12:25:24 -06:00
J. Nick Koston
d25ff00af4 Merge branch 'integration' into memory_api 2025-11-05 12:22:24 -06:00
J. Nick Koston
6e4b99db73 Merge branch 'integration' into memory_api 2025-11-05 12:15:30 -06:00
J. Nick Koston
ab128fe84a Merge branch 'integration' into memory_api 2025-11-05 11:45:35 -06:00
J. Nick Koston
ee229bd8f2 Merge branch 'integration' into memory_api 2025-11-05 11:27:55 -06:00
J. Nick Koston
a78767c714 Merge branch 'integration' into memory_api 2025-11-05 11:01:59 -06:00
J. Nick Koston
e648c0315e Merge branch 'integration' into memory_api 2025-11-05 09:18:11 -06:00
J. Nick Koston
3a947a205a Merge branch 'integration' into memory_api 2025-11-05 09:03:23 -06:00
J. Nick Koston
d7ea53a44f Merge branch 'integration' into memory_api 2025-11-04 22:33:13 -06:00
J. Nick Koston
6ba0d6b54b Merge branch 'integration' into memory_api 2025-11-04 22:21:45 -06:00
J. Nick Koston
bbe9169975 Merge branch 'integration' into memory_api 2025-11-04 22:13:30 -06:00
J. Nick Koston
f262c671a8 Merge branch 'integration' into memory_api 2025-11-04 22:02:34 -06:00
J. Nick Koston
28eb79b17b Merge branch 'integration' into memory_api 2025-11-04 21:46:10 -06:00
J. Nick Koston
c588d52bec Merge branch 'integration' into memory_api 2025-11-04 21:13:56 -06:00
J. Nick Koston
829455ac43 Merge branch 'integration' into memory_api 2025-11-04 21:12:37 -06:00
J. Nick Koston
cd3558623b Merge branch 'integration' into memory_api 2025-11-04 08:34:32 -06:00
J. Nick Koston
4ae36c0b59 Merge branch 'integration' into memory_api 2025-11-03 22:30:16 -06:00
J. Nick Koston
beca5901ec Merge branch 'integration' into memory_api 2025-11-03 22:27:11 -06:00
J. Nick Koston
2ee409d799 Merge branch 'integration' into memory_api 2025-11-03 21:33:39 -06:00
J. Nick Koston
60d309b97a Merge branch 'integration' into memory_api 2025-11-03 21:03:49 -06:00
J. Nick Koston
772c3b250e Merge branch 'integration' into memory_api 2025-11-03 16:36:17 -06:00
J. Nick Koston
b294dbd547 Merge branch 'integration' into memory_api 2025-11-03 15:01:06 -06:00
J. Nick Koston
2dc798f490 Merge branch 'integration' into memory_api 2025-11-02 23:20:42 -06:00
J. Nick Koston
a136501c63 Merge branch 'integration' into memory_api 2025-11-02 22:44:43 -06:00
J. Nick Koston
244716a05b Merge branch 'integration' into memory_api 2025-11-02 22:08:11 -06:00
J. Nick Koston
6aa4485baf Merge branch 'integration' into memory_api 2025-11-02 20:22:59 -06:00
J. Nick Koston
a436937b7d Merge branch 'integration' into memory_api 2025-11-02 20:22:20 -06:00
J. Nick Koston
5e70dd76bf Merge branch 'integration' into memory_api 2025-11-02 19:45:11 -06:00
J. Nick Koston
b4bebe0d44 Merge branch 'integration' into memory_api 2025-11-02 18:53:51 -06:00
J. Nick Koston
da53a13086 remove cruft 2025-11-02 18:17:39 -06:00
J. Nick Koston
7d0a04bac7 Merge branch 'integration' into memory_api 2025-11-02 17:59:04 -06:00
J. Nick Koston
1704e8dd69 Merge branch 'integration' into memory_api 2025-11-01 21:57:55 -05:00
J. Nick Koston
82964576f0 Merge branch 'integration' into memory_api 2025-11-01 16:58:54 -05:00
J. Nick Koston
e370dd0a14 Merge branch 'integration' into memory_api 2025-11-01 15:27:06 -05:00
J. Nick Koston
90fada3de9 Merge branch 'integration' into memory_api 2025-11-01 13:23:08 -05:00
J. Nick Koston
a6b64db51a Merge branch 'integration' into memory_api 2025-11-01 13:05:01 -05:00
J. Nick Koston
e567cb9658 tests 2025-11-01 12:47:54 -05:00
J. Nick Koston
7714f71d5c Merge branch 'integration' into memory_api 2025-11-01 12:42:49 -05:00
J. Nick Koston
3c5e702c84 Merge branch 'integration' into memory_api 2025-11-01 12:12:06 -05:00
J. Nick Koston
806f033800 Merge branch 'integration' into memory_api 2025-11-01 00:21:00 -05:00
J. Nick Koston
0dabd8d392 Merge branch 'integration' into memory_api 2025-10-31 23:28:44 -05:00
J. Nick Koston
2816aa6574 Merge branch 'integration' into memory_api 2025-10-31 22:56:48 -05:00
J. Nick Koston
1e470b3018 Merge branch 'integration' into memory_api 2025-10-31 22:27:49 -05:00
J. Nick Koston
07d00d5061 Merge branch 'integration' into memory_api 2025-10-31 22:22:46 -05:00
J. Nick Koston
95c4bb62d0 Merge branch 'integration' into memory_api 2025-10-31 15:21:21 -05:00
J. Nick Koston
1704752aef Merge branch 'integration' into memory_api 2025-10-31 14:39:18 -05:00
J. Nick Koston
62569c9770 Merge branch 'integration' into memory_api 2025-10-30 21:22:21 -05:00
J. Nick Koston
9753bd8b8a Merge branch 'integration' into memory_api 2025-10-30 18:06:24 -05:00
J. Nick Koston
c544b8258f Merge branch 'integration' into memory_api 2025-10-30 15:40:27 -05:00
J. Nick Koston
f7d3a8eab4 Merge branch 'integration' into memory_api 2025-10-30 15:38:59 -05:00
J. Nick Koston
b28dc7218d Merge branch 'integration' into memory_api 2025-10-30 15:33:37 -05:00
J. Nick Koston
c191405b6d preen 2025-10-30 15:33:07 -05:00
J. Nick Koston
74a9445eff Merge branch 'integration' into memory_api 2025-10-30 15:27:58 -05:00
J. Nick Koston
94207cb956 Merge branch 'integration' into memory_api 2025-10-30 15:24:18 -05:00
J. Nick Koston
04db4b821d Merge branch 'integration' into memory_api 2025-10-30 15:21:18 -05:00
J. Nick Koston
028d16d64e Merge branch 'integration' into memory_api 2025-10-30 14:31:21 -05:00
J. Nick Koston
90a6771f4b Merge branch 'integration' into memory_api 2025-10-30 14:28:26 -05:00
J. Nick Koston
be12da5690 Merge branch 'integration' into memory_api 2025-10-30 14:26:55 -05:00
J. Nick Koston
fad0e55dcc Merge branch 'integration' into memory_api 2025-10-30 14:20:58 -05:00
J. Nick Koston
400e64906b Merge branch 'integration' into memory_api 2025-10-30 14:19:18 -05:00
J. Nick Koston
4913351540 Merge branch 'integration' into memory_api 2025-10-30 14:17:17 -05:00
J. Nick Koston
9c9d6e61bb break it out, logic was too hard to follow 2025-10-30 14:16:43 -05:00
J. Nick Koston
a2e83d9018 Merge branch 'integration' into memory_api 2025-10-30 14:08:10 -05:00
J. Nick Koston
16b9eecbcd Merge branch 'integration' into memory_api 2025-10-30 13:40:47 -05:00
J. Nick Koston
7acc39abc8 Merge branch 'integration' into memory_api 2025-10-30 13:35:47 -05:00
J. Nick Koston
edc21fe41e Merge branch 'integration' into memory_api 2025-10-30 13:34:01 -05:00
J. Nick Koston
dcc7dbb9e1 Merge branch 'integration' into memory_api 2025-10-30 13:28:52 -05:00
J. Nick Koston
27cef4d250 Merge branch 'integration' into memory_api 2025-10-30 13:26:48 -05:00
J. Nick Koston
16f298896d Merge branch 'integration' into memory_api 2025-10-30 13:20:50 -05:00
J. Nick Koston
6f8842c170 Merge branch 'integration' into memory_api 2025-10-30 11:03:06 -05:00
J. Nick Koston
a9b66ff943 Merge branch 'integration' into memory_api 2025-10-29 22:01:37 -05:00
J. Nick Koston
932e19d9a1 Merge branch 'integration' into memory_api 2025-10-29 18:13:22 -05:00
J. Nick Koston
41abb8f9a5 Merge branch 'integration' into memory_api 2025-10-29 18:12:25 -05:00
J. Nick Koston
6e259c2dbb update cover 2025-10-29 18:08:04 -05:00
J. Nick Koston
80ed3a6f66 Merge branch 'integration' into memory_api 2025-10-29 18:05:32 -05:00
J. Nick Koston
36e859be37 Merge branch 'integration' into memory_api 2025-10-29 17:58:04 -05:00
J. Nick Koston
30e6d7a3c8 remove enable_loops, not needed since setup runs after setters, since setters are called in main setup() before component setup() 2025-10-29 16:53:13 -05:00
J. Nick Koston
97f53765b5 Merge branch 'integration' into memory_api 2025-10-29 16:49:55 -05:00
J. Nick Koston
931f52cb7b Merge branch 'integration' into memory_api 2025-10-29 16:24:12 -05:00
J. Nick Koston
b1dffcc921 Merge branch 'integration' into memory_api 2025-10-29 15:06:46 -05:00
J. Nick Koston
d8da806bab tidy 2025-10-29 15:06:08 -05:00
J. Nick Koston
d900b84e55 Merge branch 'integration' into memory_api 2025-10-29 14:59:47 -05:00
J. Nick Koston
6e1dace240 Merge branch 'integration' into memory_api 2025-10-29 00:03:57 -05:00
J. Nick Koston
5e6baba76c Merge branch 'integration' into memory_api 2025-10-28 23:43:01 -05:00
J. Nick Koston
a63b04fc0d Merge branch 'integration' into memory_api 2025-10-28 23:29:03 -05:00
J. Nick Koston
c7904e845e Merge branch 'integration' into memory_api 2025-10-28 21:16:45 -05:00
J. Nick Koston
df56346fb6 Merge branch 'integration' into memory_api 2025-10-28 14:19:22 -05:00
J. Nick Koston
c34872f923 Merge branch 'integration' into memory_api 2025-10-28 10:59:06 -05:00
J. Nick Koston
4a51486979 Merge branch 'integration' into memory_api 2025-10-27 22:06:38 -05:00
J. Nick Koston
b4be5e7996 Merge branch 'integration' into memory_api 2025-10-27 19:37:39 -05:00
J. Nick Koston
0ada17356c Merge branch 'integration' into memory_api 2025-10-27 19:15:28 -05:00
J. Nick Koston
71ccbd8212 Merge branch 'integration' into memory_api 2025-10-27 14:41:55 -05:00
J. Nick Koston
c5ef520b99 Merge branch 'integration' into memory_api 2025-10-27 12:05:52 -05:00
J. Nick Koston
1d885ca6aa Merge branch 'integration' into memory_api 2025-10-27 11:59:01 -05:00
J. Nick Koston
1b25144bd7 Merge branch 'integration' into memory_api 2025-10-27 11:24:19 -05:00
J. Nick Koston
0a47f7dfb5 Merge branch 'integration' into memory_api 2025-10-27 11:23:34 -05:00
J. Nick Koston
3389b92255 Merge branch 'template_lambdas_m' into memory_api 2025-10-26 19:43:32 -05:00
J. Nick Koston
05929c6248 Merge branch 'integration' into memory_api 2025-10-26 12:28:40 -07:00
J. Nick Koston
5ba7981c27 Merge branch 'integration' into memory_api 2025-10-26 12:24:41 -07:00
J. Nick Koston
c9178b8026 Merge branch 'integration' into memory_api 2025-10-26 12:19:54 -07:00
J. Nick Koston
f8661300f5 Merge branch 'integration' into memory_api 2025-10-26 09:41:42 -07:00
J. Nick Koston
beace82816 over engineered 2025-10-26 09:32:43 -07:00
J. Nick Koston
802b866d25 Merge branch 'integration' into memory_api 2025-10-26 01:31:20 -07:00
J. Nick Koston
c168766832 Merge branch 'integration' into memory_api 2025-10-26 01:05:16 -07:00
J. Nick Koston
cb0052f974 Merge branch 'integration' into memory_api 2025-10-25 19:12:40 -07:00
J. Nick Koston
d8d6560acb Merge branch 'integration' into memory_api 2025-10-25 16:50:05 -07:00
J. Nick Koston
892aa61e79 Merge branch 'integration' into memory_api 2025-10-25 16:48:51 -07:00
J. Nick Koston
a00c9a6861 Merge branch 'integration' into memory_api 2025-10-25 15:05:27 -07:00
J. Nick Koston
4f24448709 Merge branch 'integration' into memory_api 2025-10-25 15:03:11 -07:00
J. Nick Koston
052f6e6f0f Merge branch 'integration' into memory_api 2025-10-25 14:59:11 -07:00
J. Nick Koston
d653aa3203 fix off by one 2025-10-25 14:53:38 -07:00
J. Nick Koston
177bdabd38 Merge branch 'integration' into memory_api 2025-10-25 14:44:50 -07:00
J. Nick Koston
4c08a7b86a fix race. 2025-10-25 14:44:25 -07:00
J. Nick Koston
77053c4ffa Merge branch 'integration' into memory_api 2025-10-25 14:39:45 -07:00
J. Nick Koston
e2a71b2ea1 Merge branch 'integration' into memory_api 2025-10-25 14:21:17 -07:00
J. Nick Koston
1531b3c0d2 Merge branch 'integration' into memory_api 2025-10-25 14:12:28 -07:00
J. Nick Koston
6ad33a5a52 Merge branch 'integration' into memory_api 2025-10-25 13:46:41 -07:00
J. Nick Koston
82d76dc7a1 Merge branch 'integration' into memory_api 2025-10-25 11:37:48 -07:00
J. Nick Koston
1b529c2f74 Merge branch 'strftime_overkill' into memory_api 2025-10-25 11:24:09 -07:00
J. Nick Koston
4375d8ae61 Merge branch 'integration' into memory_api 2025-10-25 11:04:19 -07:00
J. Nick Koston
8ea1351285 Merge branch 'integration' into memory_api 2025-10-25 10:51:57 -07:00
J. Nick Koston
2fa5ed6029 Merge branch 'integration' into memory_api 2025-10-25 10:42:38 -07:00
J. Nick Koston
386c989b45 Merge branch 'integration' into memory_api 2025-10-25 10:31:45 -07:00
J. Nick Koston
075efbb216 Merge branch 'integration' into memory_api 2025-10-25 00:28:23 -07:00
J. Nick Koston
b62f620b57 Merge branch 'integration' into memory_api 2025-10-25 00:25:55 -07:00
J. Nick Koston
78585ca3f9 Merge branch 'integration' into memory_api 2025-10-24 17:32:52 -07:00
J. Nick Koston
7dd1071026 cleanup 2025-10-24 17:30:04 -07:00
J. Nick Koston
9a44f8c14d Merge branch 'integration' into memory_api 2025-10-24 14:39:17 -07:00
J. Nick Koston
2b75eca91f Merge branch 'integration' into memory_api 2025-10-24 14:31:46 -07:00
J. Nick Koston
3b750adf29 Merge branch 'integration' into memory_api 2025-10-24 13:41:24 -07:00
J. Nick Koston
2e1c8a114a touch ups 2025-10-24 09:33:38 -07:00
J. Nick Koston
2df6a8aa9e Merge branch 'integration' into memory_api 2025-10-24 07:29:26 -07:00
J. Nick Koston
a061af8d73 Merge branch 'integration' into memory_api 2025-10-23 22:32:17 -07:00
J. Nick Koston
dadf037037 Merge branch 'integration' into memory_api 2025-10-23 11:29:47 -07:00
J. Nick Koston
ba3fd5fdb5 Merge branch 'integration' into memory_api 2025-10-22 19:50:57 -10:00
J. Nick Koston
6a009d0945 Merge branch 'integration' into memory_api 2025-10-22 19:21:09 -10:00
J. Nick Koston
f66a526d2e [http_request] Pass collect_headers by const reference instead of by value 2025-10-22 19:00:58 -10:00
J. Nick Koston
af428fd7c5 Merge remote-tracking branch 'origin/memory_api' into memory_api 2025-10-22 16:26:03 -10:00
J. Nick Koston
d434f0c641 Merge branch 'integration' into memory_api 2025-10-22 16:25:47 -10:00
J. Nick Koston
87c630cf45 Merge branch 'memory_api' of https://github.com/esphome/esphome into memory_api 2025-10-22 16:14:53 -10:00
J. Nick Koston
fe7ebbc33e Merge branch 'integration' into memory_api 2025-10-22 16:14:46 -10:00
J. Nick Koston
7a033edbc2 Merge branch 'integration' into memory_api 2025-10-22 15:17:38 -10:00
J. Nick Koston
48643cd2de Merge branch 'integration' into memory_api 2025-10-22 15:09:10 -10:00
J. Nick Koston
ae41ae80ca Fix light_call.cpp to use first_value_from_mask instead of first_mode_from_mask
The generic FiniteSetMask uses first_value_from_mask, not first_mode_from_mask.
This aligns with the enum_mask_helper implementation.
2025-10-22 14:33:48 -10:00
J. Nick Koston
d8cb5d4aa4 Fix light_traits.h to use correct FiniteSetMask API
- Use count() instead of contains() (std::set compatible API)
- Use has_capability() free function instead of method
- Matches enum_mask_helper implementation
2025-10-22 14:33:02 -10:00
J. Nick Koston
416ce17c92 Merge branch 'climate_overhead' into memory_api 2025-10-22 14:31:45 -10:00
J. Nick Koston
4d86bbda79 Merge branch 'integration' into memory_api 2025-10-22 14:23:17 -10:00
J. Nick Koston
cdbf9682b1 Merge branch 'integration' into memory_api 2025-10-22 14:12:29 -10:00
J. Nick Koston
42a7385f98 Merge branch 'integration' into memory_api 2025-10-22 12:32:37 -10:00
J. Nick Koston
e822aa1e3d Merge branch 'integration' into memory_api 2025-10-22 12:14:08 -10:00
J. Nick Koston
771501ccbb Merge branch 'integration' into memory_api 2025-10-22 10:13:54 -10:00
J. Nick Koston
4c6cd05b7b Merge branch 'integration' into memory_api 2025-10-22 10:08:53 -10:00
J. Nick Koston
349dc7227e Merge branch 'integration' into memory_api 2025-10-22 09:59:39 -10:00
J. Nick Koston
0d2eb794c7 Merge branch 'integration' into memory_api 2025-10-21 23:57:40 -10:00
J. Nick Koston
46afd21738 Merge branch 'integration' into memory_api 2025-10-21 15:58:37 -10:00
J. Nick Koston
f562454f8e Merge branch 'integration' into memory_api 2025-10-21 14:17:00 -10:00
J. Nick Koston
033325d354 Merge branch 'integration' into memory_api 2025-10-21 13:45:01 -10:00
J. Nick Koston
0bde964441 Merge branch 'integration' into memory_api 2025-10-21 13:12:20 -10:00
J. Nick Koston
fead1a8c22 Merge branch 'integration' into memory_api 2025-10-21 11:16:06 -10:00
J. Nick Koston
c47d9345ea Merge branch 'integration' into memory_api 2025-10-20 23:38:37 -10:00
J. Nick Koston
811cd4582e Merge branch 'integration' into memory_api 2025-10-20 22:49:57 -10:00
J. Nick Koston
c2c55ac648 Merge branch 'integration' into memory_api 2025-10-20 22:23:39 -10:00
J. Nick Koston
375adbb86f [binary_sensor] Optimize AutorepeatFilter with FixedVector 2025-10-20 22:09:22 -10:00
J. Nick Koston
5b13814a9e Merge branch 'integration' into memory_api 2025-10-20 21:58:42 -10:00
J. Nick Koston
110f23caff fix 2025-10-20 21:34:14 -10:00
J. Nick Koston
faff196f1b Merge branch 'integration' into memory_api 2025-10-20 21:25:34 -10:00
J. Nick Koston
888db4c784 Merge branch 'integration' into memory_api 2025-10-20 20:59:26 -10:00
J. Nick Koston
45460c3165 Merge branch 'integration' into memory_api 2025-10-20 20:25:25 -10:00
J. Nick Koston
b9efaabdf0 more cleanup 2025-10-20 20:15:12 -10:00
J. Nick Koston
5b4e50d279 more cleanup 2025-10-20 20:13:20 -10:00
J. Nick Koston
8c115ab07b more cleanup 2025-10-20 20:12:51 -10:00
J. Nick Koston
ed94822174 Merge branch 'integration' into memory_api 2025-10-20 19:21:50 -10:00
J. Nick Koston
f7bcf87213 more filter cleanups 2025-10-20 19:13:20 -10:00
J. Nick Koston
1808d43fce Merge branch 'integration' into memory_api 2025-10-20 18:47:01 -10:00
J. Nick Koston
ec7c3add9b Merge branch 'integration' into memory_api 2025-10-20 17:07:00 -10:00
J. Nick Koston
fe0b2daec1 Merge branch 'integration' into memory_api 2025-10-20 15:34:39 -10:00
J. Nick Koston
a91fe2c4c3 Merge branch 'integration' into memory_api 2025-10-20 13:39:58 -10:00
J. Nick Koston
e7ba19b3ea Merge branch 'integration' into memory_api 2025-10-19 12:53:45 -10:00
J. Nick Koston
82f7b7f0d5 debug 2025-10-19 09:41:04 -10:00
J. Nick Koston
db5c78acb9 preen 2025-10-19 09:36:55 -10:00
J. Nick Koston
0b45e1d608 Merge branch 'integration' into memory_api 2025-10-19 09:36:02 -10:00
J. Nick Koston
453a668cfb Merge branch 'integration' into memory_api 2025-10-19 08:46:39 -10:00
J. Nick Koston
ae0c3875fc Merge branch 'integration' into memory_api 2025-10-19 08:02:39 -10:00
J. Nick Koston
c3b652b977 Merge branch 'integration' into memory_api 2025-10-18 22:43:58 -10:00
J. Nick Koston
504c2b9dfd Merge branch 'ci_impact_analysis' into memory_api 2025-10-18 22:43:09 -10:00
J. Nick Koston
314fe77b8d Merge branch 'min_filter_ring_buffer' into memory_api 2025-10-18 22:42:55 -10:00
J. Nick Koston
8686d05d05 Merge branch 'unbound_queued_script_fix' into memory_api 2025-10-18 22:42:50 -10:00
J. Nick Koston
be3dacfe64 Merge branch 'mqtt_reduce_json_assign' into memory_api 2025-10-18 22:42:45 -10:00
J. Nick Koston
3f7e22e271 Merge branch 'integration' into memory_api 2025-10-18 22:24:32 -10:00
J. Nick Koston
a28b85c3fa Merge branch 'dev' of https://github.com/esphome/esphome into memory_api 2025-10-18 22:23:32 -10:00
J. Nick Koston
1010006b5e Merge branch 'dev' into mqtt_reduce_json_assign 2025-10-18 22:16:33 -10:00
J. Nick Koston
9fc3ad1fa5 bot 2025-10-18 22:16:09 -10:00
J. Nick Koston
fc2c55b642 Merge branch 'integration' into memory_api 2025-10-18 21:26:22 -10:00
J. Nick Koston
cfcc6e22e0 Merge branch 'integration' into memory_api 2025-10-18 21:01:21 -10:00
J. Nick Koston
e52eeb528d Merge branch 'integration' into memory_api 2025-10-18 20:45:19 -10:00
J. Nick Koston
c8b2cf1ceb Merge branch 'integration' into memory_api 2025-10-18 20:21:22 -10:00
J. Nick Koston
a236f1c6d1 Merge branch 'integration' into memory_api 2025-10-18 20:05:56 -10:00
J. Nick Koston
d695c99dbe Merge branch 'integration' into memory_api 2025-10-18 19:50:34 -10:00
J. Nick Koston
eb45427d07 Merge branch 'integration' into memory_api 2025-10-18 14:58:13 -10:00
J. Nick Koston
76ad649bf9 review comments 2025-10-18 14:41:59 -10:00
J. Nick Koston
35f8dc528d Merge branch 'integration' into memory_api 2025-10-18 14:26:11 -10:00
J. Nick Koston
e7bc2b0a44 Merge branch 'light_bitmask' into memory_api 2025-10-18 12:35:33 -10:00
J. Nick Koston
f3c1733662 Merge branch 'integration' into memory_api 2025-10-18 12:07:32 -10:00
J. Nick Koston
efc98e9a2c Merge branch 'integration' into memory_api 2025-10-18 11:10:35 -10:00
J. Nick Koston
a0008d6f44 fix 2025-10-18 10:41:37 -10:00
J. Nick Koston
bb03d73106 Merge branch 'integration' into memory_api 2025-10-18 10:36:13 -10:00
J. Nick Koston
5ad22620c9 [mqtt] Reduce flash usage by optimizing ArduinoJson assignments 2025-10-17 23:35:52 -10:00
J. Nick Koston
e200f82d7a fixes 2025-10-17 21:48:03 -10:00
J. Nick Koston
d18a0888e9 Merge branch 'integration' into memory_api 2025-10-17 21:44:48 -10:00
J. Nick Koston
4dd1f51246 Merge branch 'integration' into memory_api 2025-10-17 21:41:47 -10:00
J. Nick Koston
7f38987c60 Merge branch 'integration' into memory_api 2025-10-17 19:24:31 -10:00
J. Nick Koston
54163bb520 Merge branch 'integration' into memory_api 2025-10-17 12:39:47 -10:00
J. Nick Koston
879ba5e090 Merge branch 'integration' into memory_api 2025-10-17 11:48:09 -10:00
J. Nick Koston
c26125c732 Merge branch 'integration' into memory_api 2025-10-17 11:20:53 -10:00
J. Nick Koston
63f9e1fde8 missing guard 2025-10-17 10:54:39 -10:00
J. Nick Koston
16a8645833 Merge branch 'integration' into memory_api 2025-10-17 10:41:20 -10:00
J. Nick Koston
2eeb9d097f Merge branch 'integration' into memory_api 2025-10-17 09:40:31 -10:00
J. Nick Koston
2ad80d2208 tweak 2025-10-17 09:29:58 -10:00
J. Nick Koston
7220d25a4d Merge branch 'integration' into memory_api 2025-10-17 09:07:34 -10:00
J. Nick Koston
5918db6012 Merge branch 'integration' into memory_api 2025-10-17 09:01:59 -10:00
J. Nick Koston
6e3cc21c34 Merge branch 'integration' into memory_api 2025-10-16 21:18:51 -10:00
J. Nick Koston
62e5b5cd2b Merge branch 'integration' into memory_api 2025-10-16 16:31:27 -10:00
J. Nick Koston
75b6fd4b43 Merge branch 'integration' into memory_api 2025-10-16 14:13:58 -10:00
J. Nick Koston
237504f4e8 Merge branch 'integration' into memory_api 2025-10-16 13:24:18 -10:00
J. Nick Koston
e48371a36d Merge branch 'integration' into memory_api 2025-10-16 11:18:40 -10:00
J. Nick Koston
b0cc53fe7d Merge branch 'integration' into memory_api 2025-10-16 10:29:58 -10:00
J. Nick Koston
819e155939 Merge branch 'integration' into memory_api 2025-10-16 10:19:27 -10:00
J. Nick Koston
a1b366b699 Merge branch 'integration' into memory_api 2025-10-16 09:58:42 -10:00
J. Nick Koston
da551a9257 Merge branch 'integration' into memory_api 2025-10-16 09:53:43 -10:00
J. Nick Koston
7c6351b5d7 Merge branch 'integration' into memory_api 2025-10-15 23:51:56 -10:00
J. Nick Koston
453d56fd13 Merge branch 'integration' into memory_api 2025-10-15 22:13:38 -10:00
J. Nick Koston
a49aed2dcb Merge branch 'integration' into memory_api 2025-10-15 16:19:52 -10:00
J. Nick Koston
b7fbc728f8 Merge branch 'integration' into memory_api 2025-10-15 16:08:38 -10:00
J. Nick Koston
8156c8ccf5 Merge branch 'integration' into memory_api 2025-10-15 15:51:19 -10:00
J. Nick Koston
98c1c2d9af Merge branch 'integration' into memory_api 2025-10-15 15:40:17 -10:00
J. Nick Koston
ec31f0b13b Merge branch 'memory_api' of https://github.com/esphome/esphome into memory_api 2025-10-15 15:21:05 -10:00
J. Nick Koston
d443d3037b Merge branch 'integration' into memory_api 2025-10-15 15:20:48 -10:00
J. Nick Koston
7a0ea74ec6 Merge branch 'integration' into memory_api 2025-10-15 09:45:21 -10:00
J. Nick Koston
2001ae1d41 Merge remote-tracking branch 'origin/integration' into memory_api 2025-10-15 09:45:15 -10:00
J. Nick Koston
9b00ab5fe4 Merge branch 'integration' into memory_api 2025-10-14 16:24:24 -10:00
J. Nick Koston
0a738b23f1 Merge branch 'integration' into memory_api 2025-10-14 16:06:16 -10:00
J. Nick Koston
e2327b46e6 Merge branch 'integration' into memory_api 2025-10-14 12:30:06 -10:00
J. Nick Koston
7598900cc2 Merge branch 'integration' into memory_api 2025-10-14 09:39:00 -10:00
J. Nick Koston
138c0fdf91 Merge branch 'integration' into memory_api 2025-10-14 09:17:14 -10:00
J. Nick Koston
41d5122a57 Merge branch 'integration' into memory_api 2025-10-13 22:51:25 -10:00
J. Nick Koston
5c3379120f Merge branch 'integration' into memory_api 2025-10-13 22:31:55 -10:00
J. Nick Koston
3dff1d02d2 Merge branch 'integration' into memory_api 2025-10-13 21:59:26 -10:00
J. Nick Koston
7572951bc5 Merge branch 'integration' into memory_api 2025-10-13 21:58:53 -10:00
J. Nick Koston
a8b6a56467 Merge branch 'integration' into memory_api 2025-10-13 21:46:14 -10:00
J. Nick Koston
66d859bfae Merge branch 'integration' into memory_api 2025-10-13 21:42:24 -10:00
J. Nick Koston
2316f3a5e3 Merge branch 'integration' into memory_api 2025-10-13 21:14:52 -10:00
J. Nick Koston
1479f48636 Merge branch 'fixed_vector_HomeassistantServiceMap' into memory_api 2025-10-13 19:31:38 -10:00
J. Nick Koston
adc0e986a2 Merge branch 'integration' into memory_api 2025-10-13 19:28:36 -10:00
J. Nick Koston
1c6dd52e9f Merge branch 'integration' into memory_api 2025-10-13 19:15:55 -10:00
J. Nick Koston
b7af2d7f4c Merge branch 'integration' into memory_api 2025-10-13 19:07:08 -10:00
J. Nick Koston
96dd348f9a Merge branch 'integration' into memory_api 2025-10-13 18:32:24 -10:00
J. Nick Koston
98132cb950 Merge branch 'integration' into memory_api 2025-10-13 17:50:00 -10:00
J. Nick Koston
a674727fa6 Merge branch 'integration' into memory_api 2025-10-13 16:51:04 -10:00
J. Nick Koston
9945c4b350 Merge branch 'integration' into memory_api 2025-10-13 15:41:57 -10:00
J. Nick Koston
044b3c07ef Merge branch 'integration' into memory_api 2025-10-13 15:30:38 -10:00
J. Nick Koston
910aff6589 Merge branch 'integration' into memory_api 2025-10-13 14:51:27 -10:00
J. Nick Koston
d82bcea106 Merge branch 'integration' into memory_api 2025-10-13 14:39:08 -10:00
J. Nick Koston
99a5a6f3a6 Merge branch 'integration' into memory_api 2025-10-13 14:20:29 -10:00
J. Nick Koston
7231b0cb5c Merge branch 'integration' into memory_api 2025-10-13 11:41:49 -10:00
J. Nick Koston
e28599b403 Merge branch 'integration' into memory_api 2025-10-12 20:22:31 -10:00
J. Nick Koston
987d616846 Merge branch 'integration' into memory_api 2025-10-12 20:20:49 -10:00
J. Nick Koston
ba408a10bb Merge branch 'integration' into memory_api 2025-10-12 20:15:20 -10:00
J. Nick Koston
767b5a11ef Merge branch 'integration' into memory_api 2025-10-12 12:55:42 -10:00
J. Nick Koston
a2254a6d55 Merge branch 'integration' into memory_api 2025-10-12 11:29:04 -10:00
J. Nick Koston
2c6828eb84 Merge branch 'integration' into memory_api 2025-10-12 11:16:36 -10:00
J. Nick Koston
a635db726d Merge branch 'integration' into memory_api 2025-10-12 10:32:11 -10:00
J. Nick Koston
dc53831b27 Merge branch 'integration' into memory_api 2025-10-11 22:03:51 -10:00
J. Nick Koston
6a0bcdf4f6 Merge branch 'integration' into memory_api 2025-10-11 21:26:37 -10:00
J. Nick Koston
cebc8a3867 Merge branch 'integration' into memory_api 2025-10-11 21:23:51 -10:00
J. Nick Koston
91dbdffea5 [mipi_rgb] Fix pin conflicts introduced by shared SPI bus in #11134 2025-10-11 19:56:05 -10:00
J. Nick Koston
2fc5afc79e Merge branch 'integration' into memory_api 2025-10-11 17:36:14 -10:00
J. Nick Koston
34d891761a Merge branch 'integration' into memory_api 2025-10-11 17:00:46 -10:00
J. Nick Koston
d6239398ed Merge branch 'loop_fix_vec' into memory_api 2025-10-11 17:00:25 -10:00
J. Nick Koston
d2a31b95c4 preen 2025-10-11 16:08:47 -10:00
J. Nick Koston
0d3489df3f Merge branch 'integration' into memory_api 2025-10-11 15:34:42 -10:00
J. Nick Koston
069893abb9 Merge branch 'integration' into memory_api 2025-10-11 13:46:07 -10:00
J. Nick Koston
b7b2b296a0 Merge branch 'integration' into memory_api 2025-10-11 12:39:33 -10:00
J. Nick Koston
c241258dfe Merge branch 'integration' into memory_api 2025-10-11 11:26:19 -10:00
J. Nick Koston
19c541f1e6 Merge branch 'integration' into memory_api 2025-10-11 11:11:46 -10:00
J. Nick Koston
245ccb02fa Merge branch 'integration' into memory_api 2025-10-11 10:52:51 -10:00
J. Nick Koston
69888af408 Merge branch 'integration' into memory_api 2025-10-11 09:32:00 -10:00
J. Nick Koston
a012557911 Merge branch 'integration' into memory_api 2025-10-11 09:31:08 -10:00
J. Nick Koston
d63af64282 Merge branch 'integration' into memory_api 2025-10-11 06:27:06 -10:00
J. Nick Koston
c524e6c2b3 Merge branch 'integration' into memory_api 2025-10-10 21:00:54 -10:00
J. Nick Koston
2184c1fde6 Merge branch 'integration' into memory_api 2025-10-10 20:04:45 -10:00
J. Nick Koston
ec44856537 Merge branch 'integration' into memory_api 2025-10-10 19:44:02 -10:00
J. Nick Koston
ee3af3904f Merge remote-tracking branch 'origin/memory_api' into memory_api 2025-10-10 17:39:56 -10:00
J. Nick Koston
02de8f9f80 merge 2025-10-10 17:39:37 -10:00
J. Nick Koston
9722c8eb60 Merge remote-tracking branch 'origin/integration' into memory_api 2025-10-10 17:39:14 -10:00
J. Nick Koston
29fb40a89f Merge branch 'integration' into memory_api 2025-10-10 17:39:01 -10:00
J. Nick Koston
e972767a11 Merge branch 'integration' into memory_api 2025-10-09 22:48:13 -10:00
J. Nick Koston
06a0ab6839 Merge branch 'integration' into memory_api 2025-10-09 16:04:24 -10:00
J. Nick Koston
968d1e2647 Merge branch 'integration' into memory_api 2025-10-09 10:41:47 -10:00
J. Nick Koston
5a4f1dd2da Merge branch 'esp32_remove_esp32_ard_apis' into integration 2025-10-09 10:41:40 -10:00
J. Nick Koston
5b146e1f12 fix 2025-10-09 10:39:41 -10:00
J. Nick Koston
de8a4ff6b0 Merge branch 'integration' into memory_api 2025-10-09 10:33:08 -10:00
J. Nick Koston
c756e132a7 Merge branch 'integration' into memory_api 2025-10-08 09:28:07 -10:00
J. Nick Koston
98e68c32ee Merge branch 'integration' into memory_api 2025-10-08 05:50:03 -10:00
J. Nick Koston
2ea32635c9 Merge branch 'integration' into memory_api 2025-10-08 05:12:32 -10:00
J. Nick Koston
48799517eb Merge branch 'integration' into memory_api 2025-10-07 22:55:15 -10:00
J. Nick Koston
a0d9098f41 Merge branch 'integration' into memory_api 2025-10-07 22:34:07 -10:00
J. Nick Koston
fc0afa1793 Merge branch 'integration' into memory_api 2025-10-07 22:22:31 -10:00
J. Nick Koston
21d4e090bf Merge branch 'integration' into memory_api 2025-10-07 21:52:06 -10:00
J. Nick Koston
181f360176 Merge branch 'integration' into memory_api 2025-10-07 16:21:40 -10:00
J. Nick Koston
58796141e9 Merge branch 'integration' into memory_api 2025-10-07 16:12:17 -10:00
J. Nick Koston
76c8da03fe Merge branch 'integration' into memory_api 2025-10-07 14:10:20 -10:00
J. Nick Koston
3b06b3386f Merge branch 'integration' into memory_api 2025-10-07 17:47:36 -05:00
J. Nick Koston
6107802d69 Merge remote-tracking branch 'upstream/dev' into memory_api 2025-10-07 17:17:47 -05:00
J. Nick Koston
f59d2d5aca Merge branch 'integration' into memory_api 2025-10-07 17:16:24 -05:00
J. Nick Koston
15968cd8be Merge branch 'integration' into memory_api 2025-10-07 15:42:36 -05:00
J. Nick Koston
65b8148f2e simplify 2025-10-07 15:24:48 -05:00
J. Nick Koston
93d493004c simplify 2025-10-07 15:24:42 -05:00
J. Nick Koston
94eab93110 Merge branch 'integration' into memory_api 2025-10-07 14:59:21 -05:00
J. Nick Koston
b89c230e6a Merge branch 'integration' into memory_api 2025-10-07 11:14:50 -05:00
J. Nick Koston
4088dbfdb6 Merge branch 'integration' into memory_api 2025-10-07 09:50:11 -05:00
J. Nick Koston
b2699f5e37 Merge branch 'integration' into memory_api 2025-10-06 17:42:49 -05:00
J. Nick Koston
517f59afe4 [api] Optimize frame helpers to eliminate double-move overhead 2025-10-06 17:27:05 -05:00
J. Nick Koston
1cf5290f28 Merge branch 'integration' into memory_api 2025-10-06 17:20:32 -05:00
J. Nick Koston
cb8765a1dd Merge branch 'integration' into memory_api 2025-10-06 14:17:42 -05:00
J. Nick Koston
553b65b998 Merge branch 'integration' into memory_api 2025-10-06 12:41:56 -05:00
J. Nick Koston
5daccc92c6 Merge branch 'integration' into memory_api 2025-10-06 12:34:44 -05:00
J. Nick Koston
4b09d3a11b Merge branch 'integration' into memory_api 2025-10-06 12:00:27 -05:00
J. Nick Koston
fae8b5f16a Merge branch 'integration' into memory_api 2025-10-06 11:57:44 -05:00
J. Nick Koston
3ab91e1f8b Merge branch 'integration' into memory_api 2025-10-05 22:51:51 -05:00
J. Nick Koston
0a45aad842 Merge branch 'integration' into memory_api 2025-10-05 17:23:15 -05:00
J. Nick Koston
0e04b5ce61 Merge branch 'integration' into memory_api 2025-10-05 17:22:14 -05:00
J. Nick Koston
c9a70eb270 Merge branch 'wifi_logging_opt' into memory_api 2025-10-05 17:11:28 -05:00
J. Nick Koston
71a254a126 Merge branch 'integration' into memory_api 2025-10-05 17:10:30 -05:00
J. Nick Koston
6841d40d07 Merge branch 'integration' into memory_api 2025-10-05 14:43:26 -05:00
J. Nick Koston
4687e58b03 help bot 2025-10-04 22:02:32 -05:00
J. Nick Koston
b31f381444 wip 2025-10-04 21:19:26 -05:00
J. Nick Koston
f2a84052db Merge branch 'integration' into memory_api 2025-10-04 20:31:35 -05:00
J. Nick Koston
481c87aac3 Merge branch 'integration' into memory_api 2025-10-04 20:18:05 -05:00
J. Nick Koston
244ed9f95f Merge branch 'integration' into memory_api 2025-10-04 13:58:45 -05:00
J. Nick Koston
0178bd166d Merge branch 'integration' into memory_api 2025-10-04 13:48:39 -05:00
J. Nick Koston
1ec74583a6 Merge branch 'integration' into memory_api 2025-10-04 13:08:16 -05:00
J. Nick Koston
395aef5a13 Merge branch 'integration' into memory_api 2025-10-04 12:46:45 -05:00
J. Nick Koston
8f4decdce4 Merge branch 'integration' into memory_api 2025-10-04 12:40:48 -05:00
J. Nick Koston
76afcc7647 Merge branch 'integration' into memory_api 2025-10-04 11:25:30 -05:00
J. Nick Koston
c640792482 Merge branch 'integration' into memory_api 2025-10-04 00:26:26 -05:00
J. Nick Koston
5600e52207 Merge branch 'integration' into memory_api 2025-10-03 20:35:52 -05:00
J. Nick Koston
e27df825f8 Merge branch 'integration' into memory_api 2025-10-03 19:40:40 -05:00
J. Nick Koston
e20ad92bf7 Merge branch 'integration' into memory_api 2025-10-03 18:38:55 -05:00
J. Nick Koston
ef3ab92979 Merge branch 'integration' into memory_api 2025-10-03 18:34:25 -05:00
J. Nick Koston
944514eea4 Merge branch 'integration' into memory_api 2025-10-03 18:21:34 -05:00
J. Nick Koston
34e0620765 Merge branch 'integration' into memory_api 2025-10-03 18:11:25 -05:00
J. Nick Koston
d660207c12 Merge branch 'integration' into memory_api 2025-10-03 18:07:17 -05:00
J. Nick Koston
249080d118 Merge branch 'integration' into memory_api 2025-10-03 18:04:25 -05:00
J. Nick Koston
5e9c9e8e79 Merge branch 'integration' into memory_api 2025-10-03 17:08:07 -05:00
J. Nick Koston
7887e136d6 Merge branch 'integration' into memory_api 2025-10-03 16:56:45 -05:00
J. Nick Koston
a3f4863fdc Merge branch 'integration' into memory_api 2025-10-03 16:41:25 -05:00
J. Nick Koston
9e6dc91051 Merge branch 'integration' into memory_api 2025-10-03 16:06:56 -05:00
J. Nick Koston
d909910d6d Merge branch 'integration' into memory_api 2025-10-03 15:32:28 -05:00
J. Nick Koston
c78dc048d8 Merge branch 'integration' into memory_api 2025-10-03 14:58:25 -05:00
J. Nick Koston
7b65279021 Merge branch 'integration' into memory_api 2025-10-03 14:32:17 -05:00
J. Nick Koston
916984b616 Merge branch 'integration' into memory_api 2025-10-03 14:23:48 -05:00
J. Nick Koston
095542035e Merge branch 'integration' into memory_api 2025-10-03 14:21:34 -05:00
J. Nick Koston
29551832b3 Merge branch 'integration' into memory_api 2025-10-03 00:46:01 +02:00
J. Nick Koston
f7cbb5d647 Merge branch 'integration' into memory_api 2025-10-02 23:06:43 +02:00
J. Nick Koston
cd1b47667b preen 2025-10-02 23:02:46 +02:00
J. Nick Koston
86f2d2e5c2 Merge remote-tracking branch 'upstream/memory_api' into memory_api 2025-10-02 22:14:58 +02:00
J. Nick Koston
650f2f915a Merge branch 'webserver_string_construction_reduce' into memory_api 2025-10-02 22:14:12 +02:00
J. Nick Koston
9865320c88 Merge branch 'integration' into memory_api 2025-10-02 20:08:01 +02:00
J. Nick Koston
be4af0a977 Merge branch 'integration' into memory_api 2025-10-02 16:45:45 +02:00
J. Nick Koston
28e8750ad6 Merge branch 'integration' into memory_api 2025-10-02 14:20:41 +02:00
J. Nick Koston
bd6169ce34 Merge branch 'integration' into memory_api 2025-10-02 10:08:55 +02:00
J. Nick Koston
e845bb3404 Merge branch 'integration' into memory_api 2025-10-02 00:22:06 +02:00
J. Nick Koston
2cdc04fa27 Merge branch 'integration' into memory_api 2025-10-02 00:04:56 +02:00
J. Nick Koston
28bc3c20ad Merge branch 'integration' into memory_api 2025-10-01 23:35:54 +02:00
J. Nick Koston
fabeae554f Merge branch 'integration' into memory_api 2025-10-01 23:10:25 +02:00
J. Nick Koston
4208bad94d Merge branch 'integration' into memory_api 2025-10-01 22:49:37 +02:00
J. Nick Koston
b89d969d09 Merge branch 'integration' into memory_api 2025-10-01 21:36:07 +02:00
J. Nick Koston
829f9fb9bc style 2025-10-01 21:08:31 +02:00
J. Nick Koston
5afe2ea48e Merge branch 'integration' into memory_api 2025-10-01 20:47:48 +02:00
J. Nick Koston
b7ab9773a3 Merge branch 'integration' into memory_api 2025-10-01 18:20:48 +02:00
J. Nick Koston
0cabe6d28e Merge branch 'integration' into memory_api 2025-10-01 17:06:11 +02:00
J. Nick Koston
767753bdda Merge branch 'integration' into memory_api 2025-10-01 16:08:09 +02:00
J. Nick Koston
8c9c2ea3ec Merge branch 'integration' into memory_api 2025-10-01 15:57:57 +02:00
J. Nick Koston
8ef4fc4fe9 Merge branch 'integration' into memory_api 2025-10-01 15:20:45 +02:00
J. Nick Koston
fc2f44fa77 Merge branch 'integration' into memory_api 2025-10-01 13:36:04 +02:00
J. Nick Koston
ef0079609e Merge branch 'integration' into memory_api 2025-10-01 13:09:34 +02:00
J. Nick Koston
f0408fb121 Merge branch 'integration' into memory_api 2025-10-01 04:58:22 +02:00
J. Nick Koston
21b22ccd34 Merge branch 'integration' into memory_api 2025-10-01 02:43:56 +02:00
J. Nick Koston
c9088fcaf2 Merge branch 'integration' into memory_api 2025-09-30 18:29:15 +02:00
J. Nick Koston
212933ec29 Merge branch 'web_server_more_tables' into memory_api 2025-09-30 14:11:57 +02:00
J. Nick Koston
fa89617a56 Merge branch 'integration' into memory_api 2025-09-30 13:59:59 +02:00
J. Nick Koston
950310e49a [web_server] Optimize handler methods with lookup tables to reduce flash usage 2025-09-30 11:08:48 +02:00
J. Nick Koston
823d97d216 Merge branch 'integration' into memory_api 2025-09-30 10:31:17 +02:00
J. Nick Koston
29b6a1a6aa add comments to explain to copilot why std::vector convert is needed 2025-09-29 20:15:31 -05:00
J. Nick Koston
d381a220f7 Merge branch 'integration' into memory_api 2025-09-29 20:00:45 -05:00
J. Nick Koston
daa18bdbaf Merge branch 'integration' into memory_api 2025-09-29 19:14:40 -05:00
J. Nick Koston
0eef3caa37 Merge branch 'integration' into memory_api 2025-09-29 18:51:24 -05:00
J. Nick Koston
ee50ea31b4 Merge branch 'integration' into memory_api 2025-09-29 16:41:35 -05:00
J. Nick Koston
c1081fbff7 Merge branch 'integration' into memory_api 2025-09-29 14:05:43 -05:00
J. Nick Koston
07e230b6a7 Merge branch 'integration' into memory_api 2025-09-29 14:00:46 -05:00
J. Nick Koston
4f1c4ada9f Merge branch 'integration' into memory_api 2025-09-29 13:13:52 -05:00
J. Nick Koston
825d24f4d0 Merge branch 'integration' into memory_api 2025-09-29 10:02:05 -05:00
J. Nick Koston
0af79adb4a Merge branch 'integration' into memory_api 2025-09-28 21:34:32 -05:00
J. Nick Koston
1917d2b0af Merge branch 'integration' into memory_api 2025-09-28 18:54:40 -05:00
J. Nick Koston
4652bfa312 Merge branch 'integration' into memory_api 2025-09-28 18:50:46 -05:00
J. Nick Koston
d015457d76 Merge branch 'integration' into memory_api 2025-09-28 18:44:23 -05:00
J. Nick Koston
0945912979 Merge branch 'guard_trq_allocation' into memory_api 2025-09-28 18:43:06 -05:00
J. Nick Koston
e51b16a9c4 Merge branch 'integration' into memory_api 2025-09-28 18:27:26 -05:00
J. Nick Koston
1af6432c31 Merge branch 'integration' into memory_api 2025-09-27 13:59:32 -05:00
J. Nick Koston
4fa9c00158 Merge branch 'make_captive_portal_captive' into memory_api 2025-09-27 13:46:42 -05:00
J. Nick Koston
42c6a3b878 Merge branch 'integration' into memory_api 2025-09-27 13:46:33 -05:00
J. Nick Koston
5841dc58a9 Merge branch 'integration' into memory_api 2025-09-27 13:32:55 -05:00
J. Nick Koston
9e6a589ee4 Merge branch 'integration' into memory_api 2025-09-27 13:22:15 -05:00
J. Nick Koston
10c4d3396e Merge branch 'make_captive_portal_captive' into memory_api 2025-09-27 13:13:05 -05:00
J. Nick Koston
c787495273 Merge branch 'integration' into memory_api 2025-09-27 13:09:45 -05:00
J. Nick Koston
f3fd86a50d Merge branch 'integration' into memory_api 2025-09-27 13:07:38 -05:00
J. Nick Koston
45a8b641b9 Merge branch 'integration' into memory_api 2025-09-27 13:04:20 -05:00
J. Nick Koston
3aec19a4a6 Merge branch 'integration' into memory_api 2025-09-27 11:15:54 -05:00
J. Nick Koston
b86b186188 Merge branch 'imporv_name' into memory_api 2025-09-27 11:10:16 -05:00
J. Nick Koston
75adceb027 Merge branch 'imporv_name' into memory_api 2025-09-27 11:09:25 -05:00
J. Nick Koston
3c06dda9f0 Merge branch 'integration' into memory_api 2025-09-27 10:54:33 -05:00
J. Nick Koston
08cf92bec7 Merge branch 'ota_password_block' into memory_api 2025-09-27 09:29:15 -05:00
J. Nick Koston
b6e8eece18 Merge branch 'integration' into memory_api 2025-09-27 09:29:09 -05:00
J. Nick Koston
c526873d71 Merge branch 'integration' into memory_api 2025-09-27 00:04:03 -05:00
J. Nick Koston
d4026f9333 Merge branch 'integration' into memory_api 2025-09-26 18:19:51 -05:00
J. Nick Koston
7e52eb5ee3 cond 2025-09-26 17:54:56 -05:00
J. Nick Koston
78f64d493c Merge branch 'integration' into memory_api 2025-09-26 16:17:40 -05:00
J. Nick Koston
f4134f21ba Merge branch 'integration' into memory_api 2025-09-26 15:00:59 -05:00
J. Nick Koston
71f35c849d Merge branch 'integration' into memory_api 2025-09-26 14:27:10 -05:00
J. Nick Koston
7136993f31 Merge branch 'integration' into memory_api 2025-09-26 12:36:43 -05:00
J. Nick Koston
5ecdce9473 Merge branch 'integration' into memory_api 2025-09-26 10:32:23 -05:00
J. Nick Koston
70a0b4e1e4 Merge branch 'integration' into memory_api 2025-09-26 10:23:34 -05:00
J. Nick Koston
efe5057cc2 Merge branch 'integration' into memory_api 2025-09-26 10:18:10 -05:00
J. Nick Koston
75b9b56627 Merge branch 'integration' into memory_api 2025-09-26 09:15:34 -05:00
J. Nick Koston
ba88187353 Merge branch 'integration' into memory_api 2025-09-26 00:13:24 -05:00
J. Nick Koston
91b2140916 Merge branch 'integration' into memory_api 2025-09-25 22:50:16 -05:00
J. Nick Koston
e9f78238d4 Merge branch 'sha256_ota' into memory_api 2025-09-25 20:36:24 -05:00
J. Nick Koston
3ce430985a Merge branch 'integration' into memory_api 2025-09-25 14:48:12 -05:00
J. Nick Koston
24d034c674 Merge branch 'dependabot/pip/ruff-0.13.2' into memory_api 2025-09-25 14:37:14 -05:00
J. Nick Koston
d06175816c match pre-commit 2025-09-25 14:34:42 -05:00
J. Nick Koston
76a2725a25 Merge branch 'integration' into memory_api 2025-09-25 14:33:43 -05:00
J. Nick Koston
a4af23ebe4 Merge branch 'integration' into memory_api 2025-09-25 14:24:58 -05:00
J. Nick Koston
2d395d1f8d Merge branch 'integration' into memory_api 2025-09-25 14:20:58 -05:00
dependabot[bot]
a4991a1d96 Bump ruff from 0.13.1 to 0.13.2
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.13.1 to 0.13.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.13.1...0.13.2)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-25 19:01:29 +00:00
J. Nick Koston
dadc557b01 Merge branch 'integration' into memory_api 2025-09-25 11:09:51 -05:00
J. Nick Koston
c5062dab55 Merge branch 'integration' into memory_api 2025-09-25 10:56:43 -05:00
J. Nick Koston
a09ca274c3 Merge branch 'sha256_ota' into memory_api 2025-09-25 10:32:23 -05:00
J. Nick Koston
97b59f7775 Merge branch 'integration' into memory_api 2025-09-24 22:21:00 -05:00
J. Nick Koston
8c894e76e7 Merge branch 'integration' into memory_api 2025-09-24 22:07:52 -05:00
J. Nick Koston
90ffdfd650 Merge remote-tracking branch 'upstream/dev' into memory_api 2025-09-24 22:07:31 -05:00
J. Nick Koston
50b479b8f1 Merge branch 'integration' into memory_api 2025-09-24 21:20:52 -05:00
J. Nick Koston
8abdaceb51 Merge branch 'integration' into memory_api 2025-09-24 17:41:33 -05:00
J. Nick Koston
20bc9da534 Merge branch 'integration' into memory_api 2025-09-24 11:53:14 -05:00
J. Nick Koston
b91ae29142 Merge branch 'integration' into memory_api 2025-09-24 09:22:37 -05:00
J. Nick Koston
42525b981e Merge branch 'integration' into memory_api 2025-09-23 23:42:09 -05:00
J. Nick Koston
9ac0f4aa4d Merge branch 'integration' into memory_api 2025-09-23 17:59:18 -05:00
J. Nick Koston
093e70ceb8 Merge branch 'integration' into memory_api 2025-09-23 17:44:51 -05:00
J. Nick Koston
7100d65f14 Merge remote-tracking branch 'upstream/core_api_no_allocate' into memory_api 2025-09-23 15:47:08 -05:00
J. Nick Koston
886cca1095 Merge branch 'integration' into memory_api 2025-09-23 15:05:44 -05:00
J. Nick Koston
7d8c97ac3b Merge branch 'integration' into memory_api 2025-09-23 11:52:10 -05:00
J. Nick Koston
9984cfc039 Merge branch 'integration' into memory_api 2025-09-23 11:30:15 -05:00
J. Nick Koston
288b70669d Merge branch 'integration' into memory_api 2025-09-23 10:14:05 -05:00
J. Nick Koston
58add6d365 Merge branch 'integration' into memory_api 2025-09-23 09:17:25 -05:00
J. Nick Koston
1ffa10c28f Merge branch 'remove-esp32-arduino-wifi-driver' into memory_api 2025-09-23 09:16:55 -05:00
J. Nick Koston
aa687be49d Merge branch 'integration' into memory_api 2025-09-23 09:11:09 -05:00
J. Nick Koston
c800e02ee8 Merge branch 'integration' into memory_api 2025-09-23 08:41:53 -05:00
J. Nick Koston
0e85cf7ed8 Merge branch 'integration' into memory_api 2025-09-23 00:42:34 -05:00
J. Nick Koston
c0ea795348 Merge branch 'integration' into memory_api 2025-09-23 00:19:31 -05:00
J. Nick Koston
3d07a4a3c9 Merge branch 'integration' into memory_api 2025-09-22 16:23:34 -05:00
J. Nick Koston
1069ed0363 Merge branch 'sha256_ota' into memory_api 2025-09-21 15:57:03 -06:00
J. Nick Koston
0ab4f69a9c Merge branch 'integration' into memory_api 2025-09-21 15:53:38 -06:00
J. Nick Koston
199d575052 Merge branch 'integration' into memory_api 2025-09-21 15:46:50 -06:00
J. Nick Koston
05685b41cd merge 2025-09-21 12:12:53 -06:00
J. Nick Koston
7d96cf66c6 Merge branch 'integration' into memory_api 2025-09-21 12:11:12 -06:00
J. Nick Koston
8bf908a88a Merge branch 'integration' into memory_api 2025-09-21 12:06:47 -06:00
J. Nick Koston
991409d315 cleanup 2025-09-21 11:56:16 -06:00
J. Nick Koston
d5c067acfa preen 2025-09-21 11:53:37 -06:00
J. Nick Koston
85ca03345c Merge branch 'integration' into memory_api 2025-09-21 11:47:33 -06:00
J. Nick Koston
70bbe3b825 Merge branch 'integration' into memory_api 2025-09-21 11:39:44 -06:00
J. Nick Koston
863588d313 Merge branch 'integration' into memory_api 2025-09-21 11:25:51 -06:00
J. Nick Koston
cd90fb2cf7 Merge branch 'integration' into memory_api 2025-09-21 11:06:50 -06:00
J. Nick Koston
abc5604c1f Merge branch 'integration' into memory_api 2025-09-21 11:06:30 -06:00
J. Nick Koston
e5fd5425c1 Merge branch 'integration' into memory_api 2025-09-19 22:44:34 -06:00
J. Nick Koston
f8d380cb7d Merge branch 'integration' into memory_api 2025-09-17 17:45:29 -05:00
J. Nick Koston
4031dc2305 Merge branch 'integration' into memory_api 2025-09-17 17:40:18 -05:00
J. Nick Koston
c69dde4454 Merge branch 'integration' into memory_api 2025-09-17 17:25:33 -05:00
J. Nick Koston
db9b1c36f6 Merge branch 'integration' into memory_api 2025-09-16 21:31:32 -05:00
J. Nick Koston
e700ce6c61 Merge branch 'integration' into memory_api 2025-09-16 12:18:27 -05:00
J. Nick Koston
4a04f9f0f0 Merge branch 'integration' into memory_api 2025-09-16 10:53:06 -05:00
J. Nick Koston
48356ab86d Merge branch 'fix_clean_build_files_not_removing_platformio_cache' into memory_api 2025-09-16 10:52:06 -05:00
J. Nick Koston
f1f0fc858c Merge branch 'integration' into memory_api 2025-09-16 10:50:10 -05:00
J. Nick Koston
b69e6f2152 Merge branch 'integration' into memory_api 2025-09-15 23:26:46 -05:00
J. Nick Koston
f0bce77adc Merge branch 'integration' into memory_api 2025-09-15 22:01:30 -05:00
J. Nick Koston
35f50b710e preen 2025-09-15 21:28:42 -05:00
J. Nick Koston
0091a2b92b Merge branch 'integration' into memory_api 2025-09-15 21:20:26 -05:00
J. Nick Koston
5acea1252b Merge branch 'webserver_remove_lambas' into memory_api 2025-09-15 20:55:41 -05:00
J. Nick Koston
f37c833c38 Merge branch 'integration' into memory_api 2025-09-15 19:01:16 -05:00
J. Nick Koston
cd15a43d77 Merge branch 'integration' into memory_api 2025-09-15 18:45:20 -05:00
J. Nick Koston
beb80a2bb6 Merge branch 'integration' into memory_api 2025-09-15 18:00:13 -05:00
J. Nick Koston
64f267914e Merge branch 'integration' into memory_api 2025-09-15 17:45:01 -05:00
J. Nick Koston
e02f2f625f Merge branch 'integration' into memory_api 2025-09-15 12:16:10 -05:00
J. Nick Koston
d005408f71 Merge branch 'integration' into memory_api 2025-09-15 11:53:58 -05:00
J. Nick Koston
415593d05e Merge branch 'integration' into memory_api 2025-09-14 23:16:22 -05:00
J. Nick Koston
ca185cb28f Merge branch 'integration' into memory_api 2025-09-14 22:48:18 -05:00
J. Nick Koston
277b8aff73 Merge branch 'integration' into memory_api 2025-09-14 22:36:34 -05:00
J. Nick Koston
adaebf64ba Merge branch 'integration' into memory_api 2025-09-14 22:19:20 -05:00
J. Nick Koston
a8b8819826 Merge branch 'integration' into memory_api 2025-09-14 21:56:20 -05:00
J. Nick Koston
2a0567c456 Merge branch 'integration' into memory_api 2025-09-14 16:19:26 -05:00
J. Nick Koston
6378bb2ac4 Merge branch 'integration' into memory_api 2025-09-14 14:42:12 -05:00
J. Nick Koston
cb439f31b9 Merge branch 'integration' into memory_api 2025-09-14 14:21:16 -05:00
J. Nick Koston
0e9110482c Merge branch 'integration' into memory_api 2025-09-14 14:01:21 -05:00
J. Nick Koston
53ab104c6a Merge branch 'integration' into memory_api 2025-09-14 13:54:27 -05:00
J. Nick Koston
842006efa1 Merge branch 'integration' into memory_api 2025-09-14 10:50:16 -05:00
J. Nick Koston
bcf8f4ef9d comments 2025-09-14 09:25:59 -05:00
J. Nick Koston
ea26f9319b comments 2025-09-14 09:25:46 -05:00
J. Nick Koston
f78ae3aa52 Merge branch 'integration' into memory_api 2025-09-14 09:18:36 -05:00
J. Nick Koston
a8c1f6e551 Merge branch 'integration' into memory_api 2025-09-13 22:42:36 -05:00
J. Nick Koston
62c457fd87 Merge branch 'integration' into memory_api 2025-09-13 18:08:02 -05:00
J. Nick Koston
b118aa7339 Merge branch 'integration' into memory_api 2025-09-13 17:16:36 -05:00
J. Nick Koston
11691d05e2 Merge branch 'integration' into memory_api 2025-09-13 17:01:04 -05:00
J. Nick Koston
f6ebe21509 Merge branch 'integration' into memory_api 2025-09-10 21:17:19 -05:00
J. Nick Koston
185a2c2fe7 Merge branch 'integration' into memory_api 2025-09-09 17:06:57 -05:00
J. Nick Koston
af45b63d51 Merge branch 'dev' into memory_api 2025-09-09 17:06:39 -05:00
J. Nick Koston
e59928166b Merge branch 'integration' into memory_api 2025-09-08 20:31:33 -05:00
J. Nick Koston
6a7145fef8 Merge branch 'integration' into memory_api 2025-09-08 19:53:58 -05:00
J. Nick Koston
29552b951d Merge branch 'integration' into memory_api 2025-09-08 19:28:32 -05:00
J. Nick Koston
4c9fd2b800 Merge branch 'integration' into memory_api 2025-09-08 10:05:14 -05:00
J. Nick Koston
f37223c756 Merge branch 'integration' into memory_api 2025-09-07 22:03:07 -05:00
J. Nick Koston
5b4b026d1b Merge branch 'integration' into memory_api 2025-09-07 20:11:09 -05:00
J. Nick Koston
563216220d Merge branch 'integration' into memory_api 2025-09-07 18:54:50 -05:00
J. Nick Koston
d2e1135a56 Merge branch 'integration' into memory_api 2025-09-07 18:47:09 -05:00
J. Nick Koston
aec6c3ae33 Merge branch 'integration' into memory_api 2025-09-07 18:23:31 -05:00
J. Nick Koston
72a1f467f0 Merge branch 'integration' into memory_api 2025-09-07 18:05:23 -05:00
J. Nick Koston
c634ef4b12 Merge branch 'integration' into memory_api 2025-09-07 18:02:14 -05:00
J. Nick Koston
ffd607ee28 Merge branch 'integration' into memory_api 2025-09-07 17:21:57 -05:00
J. Nick Koston
1964764dd0 Merge branch 'integration' into memory_api 2025-09-07 16:50:48 -05:00
J. Nick Koston
f358f0a8f9 Merge branch 'integration' into memory_api 2025-09-07 09:48:20 -05:00
J. Nick Koston
f9d10954bb Merge branch 'integration' into memory_api 2025-09-07 09:33:29 -05:00
J. Nick Koston
68c8a67677 Merge branch 'integration' into memory_api 2025-09-07 09:02:28 -05:00
J. Nick Koston
5f8731a136 Merge branch 'integration' into memory_api 2025-09-07 08:59:12 -05:00
J. Nick Koston
2be9f42ddd Merge branch 'integration' into memory_api 2025-09-07 08:23:54 -05:00
J. Nick Koston
902619e46d Merge branch 'integration' into memory_api 2025-09-06 23:30:57 -05:00
J. Nick Koston
97957b49f1 rename 2025-09-06 23:29:11 -05:00
J. Nick Koston
871d36e303 Merge branch 'integration' into memory_api 2025-09-06 22:58:10 -05:00
J. Nick Koston
08f6286427 Merge branch 'integration' into memory_api 2025-09-06 22:53:35 -05:00
J. Nick Koston
261ab786fd Merge branch 'integration' into memory_api 2025-09-06 09:23:33 -05:00
J. Nick Koston
5e44aa2ccc Merge branch 'integration' into memory_api 2025-09-05 22:23:30 -05:00
J. Nick Koston
e9498d65c5 Merge branch 'integration' into memory_api 2025-09-05 22:15:46 -05:00
J. Nick Koston
f2dede2861 Merge branch 'integration' into memory_api 2025-09-05 22:14:32 -05:00
J. Nick Koston
a6d43b5ec9 warnings strings flash 2025-09-05 21:49:19 -05:00
J. Nick Koston
a26c769b96 Merge branch 'integration' into memory_api 2025-09-05 21:28:09 -05:00
J. Nick Koston
bf7ac26ab1 Merge branch 'integration' into memory_api 2025-09-05 17:20:13 -05:00
J. Nick Koston
8e468ff645 Merge branch 'integration' into memory_api 2025-09-05 17:11:30 -05:00
J. Nick Koston
a891b34b01 Merge branch 'integration' into memory_api 2025-09-05 14:40:56 -05:00
J. Nick Koston
48d9de7f24 Merge branch 'integration' into memory_api 2025-09-05 13:53:51 -05:00
J. Nick Koston
7ffe6459f6 Merge branch 'integration' into memory_api 2025-09-05 13:36:33 -05:00
J. Nick Koston
f6b97d3977 Merge branch 'logger_esp8266_progmem' into memory_api 2025-09-05 13:27:37 -05:00
J. Nick Koston
ce9cf27ca5 Merge branch 'integration' into memory_api 2025-09-05 13:10:56 -05:00
J. Nick Koston
2f7c1601e3 Merge branch 'integration' into memory_api 2025-09-05 13:02:18 -05:00
J. Nick Koston
bb5a973fdf Merge branch 'integration' into memory_api 2025-09-05 11:34:19 -05:00
J. Nick Koston
ba2f6027fb Merge branch 'state_class_to_string_flash' into memory_api 2025-09-05 11:34:06 -05:00
J. Nick Koston
ed7cbb9111 Merge branch 'integration' into memory_api 2025-09-05 11:20:33 -05:00
J. Nick Koston
b5dea4549c Merge branch 'integration' into memory_api 2025-09-05 11:17:17 -05:00
J. Nick Koston
c8d575aab7 revert 2025-09-05 11:15:09 -05:00
J. Nick Koston
9b882a8792 Merge branch 'integration' into memory_api 2025-09-05 11:12:43 -05:00
J. Nick Koston
210680a4cb Merge branch 'integration' into memory_api 2025-09-05 11:06:50 -05:00
J. Nick Koston
c6f8aa45eb Merge branch 'integration' into memory_api 2025-09-05 10:45:36 -05:00
J. Nick Koston
def3992af5 Merge branch 'integration' into memory_api 2025-09-05 10:43:11 -05:00
J. Nick Koston
f28691edb4 Merge branch 'integration' into memory_api 2025-09-05 10:39:27 -05:00
J. Nick Koston
4b57f1e619 beginResponse_P 2025-09-05 10:38:58 -05:00
J. Nick Koston
f9d3cddd23 Merge branch 'integration' into memory_api 2025-09-05 10:34:18 -05:00
J. Nick Koston
b7ef1cd7d4 Merge branch 'integration' into memory_api 2025-09-05 10:26:16 -05:00
J. Nick Koston
40794bca78 Merge branch 'logger_esp8266_progmem' into memory_api 2025-09-05 10:20:37 -05:00
J. Nick Koston
f4f1b9d8c3 Merge branch 'integration' into memory_api 2025-09-05 10:19:29 -05:00
J. Nick Koston
8c90675eb2 Merge branch 'integration' into memory_api 2025-09-05 10:12:10 -05:00
J. Nick Koston
51c29f7c61 Merge branch 'integration' into memory_api 2025-09-05 09:43:38 -05:00
J. Nick Koston
5760d5c995 Merge branch 'integration' into memory_api 2025-09-05 09:22:50 -05:00
J. Nick Koston
62fbda4cc3 Merge branch 'integration' into memory_api 2025-09-05 09:14:09 -05:00
J. Nick Koston
33697e95ac Merge branch 'captive_portal_progmem_8266' into memory_api 2025-09-05 08:43:02 -05:00
J. Nick Koston
894bbd27c3 Merge branch 'integration' into memory_api 2025-09-05 08:32:09 -05:00
J. Nick Koston
eb666324fe Merge branch 'integration' into memory_api 2025-09-04 23:32:23 -05:00
J. Nick Koston
2433ac4821 Merge branch 'integration' into memory_api 2025-09-04 22:58:41 -05:00
J. Nick Koston
cf7140ce1a Merge branch 'integration' into memory_api 2025-09-04 22:29:59 -05:00
J. Nick Koston
f762d3a6e2 Merge branch 'integration' into memory_api 2025-09-04 21:42:14 -05:00
J. Nick Koston
d5f855004e Merge branch 'integration' into memory_api 2025-09-04 14:45:52 -05:00
J. Nick Koston
025da5ac30 Merge branch 'integration' into memory_api 2025-09-04 14:40:26 -05:00
J. Nick Koston
ed0b1b02ed Merge branch 'integration' into memory_api 2025-09-04 13:51:40 -05:00
J. Nick Koston
2b4bf270fd Merge branch 'integration' into memory_api 2025-09-04 13:49:39 -05:00
J. Nick Koston
feecc734fb update docs 2025-09-04 13:49:10 -05:00
J. Nick Koston
a6ed4bb844 Merge branch 'integration' into memory_api 2025-09-04 13:27:13 -05:00
J. Nick Koston
56652ce763 Merge branch 'integration' into memory_api 2025-09-04 13:10:35 -05:00
J. Nick Koston
42c8624f95 Merge branch 'integration' into memory_api 2025-09-04 13:09:32 -05:00
J. Nick Koston
1528c06599 Merge branch 'integration' into memory_api 2025-09-04 13:05:31 -05:00
J. Nick Koston
2d409b017e Merge branch 'optimize_pcf8574' into memory_api 2025-09-04 13:05:15 -05:00
J. Nick Koston
20d3e4a1b8 Merge branch 'integration' into memory_api 2025-09-04 13:05:08 -05:00
J. Nick Koston
f5dbc44662 Merge branch 'optimize_pcf8574' into memory_api 2025-09-04 12:24:02 -05:00
J. Nick Koston
ec88aefebf Merge branch 'integration' into memory_api 2025-09-04 11:21:29 -05:00
J. Nick Koston
0585f05d90 Merge branch 'optimize_pcf8574' into memory_api 2025-09-04 11:20:27 -05:00
J. Nick Koston
526ba902ae Merge branch 'integration' into memory_api 2025-09-04 11:04:30 -05:00
J. Nick Koston
888a1539c5 Merge branch 'integration' into memory_api 2025-09-04 10:56:08 -05:00
J. Nick Koston
52ce1f8985 Merge branch 'integration' into memory_api 2025-09-04 10:53:37 -05:00
J. Nick Koston
30ed4717de Merge branch 'integration' into memory_api 2025-09-04 10:43:24 -05:00
J. Nick Koston
b0ec9abbc4 Merge branch 'i2c_std_vector_heap' into memory_api 2025-09-04 10:14:22 -05:00
J. Nick Koston
b1413ac0e0 Merge branch 'integration' into memory_api 2025-09-04 09:06:59 -05:00
J. Nick Koston
049606607a Merge branch 'ota_esp8266_logstr' into memory_api 2025-09-04 09:02:48 -05:00
J. Nick Koston
b5df54d900 Merge branch 'integration' into memory_api 2025-09-04 08:58:18 -05:00
J. Nick Koston
85314be7a2 Merge branch 'logger_8266_str_to_flash' into memory_api 2025-09-04 08:53:18 -05:00
J. Nick Koston
a58b7abde7 Merge branch 'integration' into memory_api 2025-09-04 08:37:41 -05:00
J. Nick Koston
85a4a61d14 [i2c] Optimize memory usage with stack allocation for small buffers 2025-09-04 08:07:22 -05:00
J. Nick Koston
e1b9b57cd7 Merge branch 'esp8266_gpio_progmem' into memory_api 2025-09-03 22:58:53 -05:00
J. Nick Koston
7587be3dfd Merge branch 'integration' into memory_api 2025-09-03 22:57:33 -05:00
J. Nick Koston
28c2af69ea Merge branch 'integration' into memory_api 2025-09-03 22:56:34 -05:00
J. Nick Koston
2d3243d631 Revert "[esp8266] Store component source strings in PROGMEM to save RAM"
This reverts commit ea01cc598b.
2025-09-03 22:16:59 -05:00
J. Nick Koston
105e94db2e Revert "preen"
This reverts commit da9a7c41d1.
2025-09-03 22:16:41 -05:00
J. Nick Koston
32fec42130 Merge branch 'integration' into memory_api 2025-09-03 22:06:30 -05:00
J. Nick Koston
4766abc461 Merge branch 'integration' into memory_api 2025-09-03 19:11:03 -05:00
J. Nick Koston
e453da6161 Merge remote-tracking branch 'origin/esp8266_prefs' into memory_api 2025-09-03 19:10:44 -05:00
J. Nick Koston
2d2ca0de52 Merge branch 'integration' into memory_api 2025-09-03 18:41:23 -05:00
J. Nick Koston
9495a885ed Merge branch 'integration' into memory_api 2025-09-03 17:56:30 -05:00
J. Nick Koston
6c3dba06ba Merge branch 'integration' into memory_api 2025-09-03 16:37:56 -05:00
J. Nick Koston
9d7f606a39 explain why its safe 2025-09-03 16:34:47 -05:00
J. Nick Koston
93c453c8f9 Merge branch 'integration' into memory_api 2025-09-03 16:23:14 -05:00
J. Nick Koston
a9bd37bacd Merge branch 'integration' into memory_api 2025-09-02 23:32:49 -05:00
J. Nick Koston
2080f881da Merge branch 'integration' into memory_api 2025-09-02 10:18:22 -05:00
J. Nick Koston
4eb744d05e Merge branch 'integration' into memory_api 2025-09-02 10:11:55 -05:00
J. Nick Koston
1855877abe Merge branch 'integration' into memory_api 2025-09-02 08:00:14 -05:00
J. Nick Koston
d738962d8d Merge branch 'integration' into memory_api 2025-09-01 23:14:34 -05:00
J. Nick Koston
64a2b688a5 Merge branch 'integration' into memory_api 2025-09-01 22:34:38 -05:00
J. Nick Koston
9ebdfde287 Merge branch 'integration' into memory_api 2025-08-29 22:11:17 -05:00
J. Nick Koston
bcea7e9fb1 Merge branch 'integration' into memory_api 2025-08-29 10:49:02 -05:00
J. Nick Koston
c828941e16 Merge branch 'integration' into memory_api 2025-08-28 13:13:27 -05:00
J. Nick Koston
c90b4c0f81 Merge branch 'integration' into memory_api 2025-08-27 09:47:26 -05:00
J. Nick Koston
2f699b3c20 Merge branch 'integration' into memory_api 2025-08-27 09:47:03 -05:00
J. Nick Koston
001d05b8f2 Merge branch 'integration' into memory_api 2025-08-26 18:22:10 -05:00
J. Nick Koston
a61300b82f Merge branch 'integration' into memory_api 2025-08-26 17:22:56 -05:00
J. Nick Koston
9e0600ec45 Merge branch 'integration' into memory_api 2025-08-26 16:34:04 -05:00
J. Nick Koston
b871456c1e Merge branch 'integration' into memory_api 2025-08-23 16:19:19 -05:00
J. Nick Koston
e44eb59e3c Merge branch 'integration' into memory_api 2025-08-22 08:52:52 -05:00
J. Nick Koston
101d98014d Merge branch 'integration' into memory_api 2025-08-21 21:47:24 -05:00
J. Nick Koston
082f795adc Merge branch 'integration' into memory_api 2025-08-21 20:27:21 -05:00
J. Nick Koston
3ac5285515 Merge branch 'integration' into memory_api 2025-08-21 09:00:18 -05:00
J. Nick Koston
2993940e1d Merge branch 'integration' into memory_api 2025-08-21 08:25:28 -05:00
J. Nick Koston
db96cfaf14 Merge branch 'integration' into memory_api 2025-08-21 08:12:51 -05:00
J. Nick Koston
bad7b0598b Merge branch 'integration' into memory_api 2025-08-20 20:26:20 -05:00
J. Nick Koston
b4f0d4b0c3 Merge branch 'integration' into memory_api 2025-08-20 20:24:31 -05:00
J. Nick Koston
df7c2473c1 Merge branch 'integration' into memory_api 2025-08-20 20:07:21 -05:00
J. Nick Koston
dde1cec3ce Merge branch 'integration' into memory_api 2025-08-20 14:54:39 -05:00
J. Nick Koston
3c6a54bb70 Merge branch 'integration' into memory_api 2025-08-20 13:26:15 -05:00
J. Nick Koston
6fd46966e2 Merge branch 'integration' into memory_api 2025-08-20 08:07:50 -05:00
J. Nick Koston
558cdda8a4 Merge branch 'integration' into memory_api 2025-08-20 08:06:47 -05:00
J. Nick Koston
856ffc2e86 Merge branch 'integration' into memory_api 2025-08-20 07:46:07 -05:00
J. Nick Koston
518443606c Merge branch 'integration' into memory_api 2025-08-19 21:53:35 -05:00
J. Nick Koston
72dd419c49 Merge branch 'integration' into memory_api 2025-08-19 21:52:31 -05:00
J. Nick Koston
997223c93e Merge branch 'integration' into memory_api 2025-08-19 21:43:20 -05:00
J. Nick Koston
d1b9902e41 Merge branch 'integration' into memory_api 2025-08-19 15:38:10 -05:00
J. Nick Koston
c5998690ba Merge branch 'integration' into memory_api 2025-08-19 09:48:25 -05:00
J. Nick Koston
db10185c7e Merge branch 'integration' into memory_api 2025-08-18 21:07:11 -05:00
J. Nick Koston
7f34757ded Merge branch 'integration' into memory_api 2025-08-18 20:03:00 -05:00
J. Nick Koston
bbd5ab1340 Merge branch 'integration' into memory_api 2025-08-18 18:33:43 -05:00
J. Nick Koston
67ae6ce00a tweak 2025-08-18 17:36:20 -05:00
J. Nick Koston
24cee8ae03 tweak 2025-08-18 17:35:21 -05:00
J. Nick Koston
58a9944601 tweak 2025-08-18 17:34:08 -05:00
J. Nick Koston
a999540d4b Merge branch 'integration' into memory_api 2025-08-18 17:13:49 -05:00
J. Nick Koston
727e04c424 Merge branch 'integration' into memory_api 2025-08-18 14:37:37 -05:00
J. Nick Koston
3d03053eb5 Merge branch 'optimize_safemode_flash' into memory_api 2025-08-18 12:42:22 -05:00
J. Nick Koston
8332893661 Merge branch 'integration' into memory_api 2025-08-18 11:06:58 -05:00
J. Nick Koston
54696eac67 Merge branch 'integration' into memory_api 2025-08-18 09:02:43 -05:00
J. Nick Koston
dbda2d5b6a Merge branch 'integration' into memory_api 2025-08-18 08:29:23 -05:00
J. Nick Koston
7e67f0432d Merge branch 'integration' into memory_api 2025-08-18 01:07:43 -05:00
J. Nick Koston
c9932342eb Merge branch 'integration' into memory_api 2025-08-18 01:01:20 -05:00
J. Nick Koston
f556ab1515 Merge branch 'frame_helper_opt' into memory_api 2025-08-18 00:57:04 -05:00
J. Nick Koston
cb157822d0 Merge branch 'decode_cleanup' into memory_api 2025-08-17 22:22:50 -05:00
J. Nick Koston
4ee84b6d53 Merge remote-tracking branch 'origin/libretiny_no_vector' into memory_api 2025-08-17 21:40:59 -05:00
J. Nick Koston
0a483012ae Update esphome/components/libretiny/preferences.cpp 2025-08-17 21:40:45 -05:00
J. Nick Koston
b12666f356 Merge branch 'integration' into memory_api 2025-08-17 21:38:18 -05:00
J. Nick Koston
a82eeabbc8 Merge branch 'libretiny_no_vector' into memory_api 2025-08-17 21:37:42 -05:00
J. Nick Koston
2b23899750 Merge branch 'integration' into memory_api 2025-08-17 21:15:01 -05:00
J. Nick Koston
b0e8aba426 Merge branch 'integration' into memory_api 2025-08-17 21:13:44 -05:00
J. Nick Koston
17467150d8 Merge branch 'integration' into memory_api 2025-08-17 08:43:10 -04:00
J. Nick Koston
1666aae105 Merge branch 'integration' into memory_api 2025-08-16 09:45:27 -04:00
J. Nick Koston
82d7255a16 Merge branch 'integration' into memory_api 2025-08-15 21:36:21 -04:00
J. Nick Koston
769a874d33 Merge branch 'integration' into memory_api 2025-08-15 21:16:44 -04:00
J. Nick Koston
15d1e1f8dd Merge branch 'integration' into memory_api 2025-08-15 15:05:19 -05:00
J. Nick Koston
e4a6dcd9c7 Merge branch 'integration' into memory_api 2025-08-15 12:33:32 -05:00
J. Nick Koston
9f8f1f5bc9 Merge branch 'integration' into memory_api 2025-08-15 09:54:57 -05:00
J. Nick Koston
57b4c65c6c Merge branch 'integration' into memory_api 2025-08-15 00:59:09 -05:00
J. Nick Koston
ce328bc9b9 Merge branch 'integration' into memory_api 2025-08-14 23:49:39 -05:00
J. Nick Koston
306f7263b2 Merge branch 'integration' into memory_api 2025-08-14 23:39:56 -05:00
J. Nick Koston
d2faac10a5 Merge branch 'integration' into memory_api 2025-08-14 23:01:08 -05:00
J. Nick Koston
7b46be523a Merge branch 'integration' into memory_api 2025-08-14 22:42:39 -05:00
J. Nick Koston
3585ed185f Merge branch 'integration' into memory_api 2025-08-14 22:22:14 -05:00
J. Nick Koston
1bd458c868 Merge branch 'integration' into memory_api 2025-08-14 22:14:23 -05:00
J. Nick Koston
9f22de449a Merge branch 'integration' into memory_api 2025-08-14 21:20:40 -05:00
J. Nick Koston
bf4070ad75 Merge branch 'integration' into memory_api 2025-08-14 21:04:59 -05:00
J. Nick Koston
00ae0fea31 Merge branch 'integration' into memory_api 2025-08-14 20:29:21 -05:00
J. Nick Koston
0d288ceef3 Merge branch 'integration' into memory_api 2025-08-14 17:46:43 -05:00
J. Nick Koston
40d35f3dff Merge branch 'integration' into memory_api 2025-08-14 16:32:51 -05:00
J. Nick Koston
4d0049aa62 Merge branch 'integration' into memory_api 2025-08-14 16:04:37 -05:00
J. Nick Koston
256f81f514 Merge branch 'clean_comp_removed' into memory_api 2025-08-14 15:59:52 -05:00
J. Nick Koston
c0c1b4738a Merge branch 'integration' into memory_api 2025-08-14 14:21:14 -05:00
J. Nick Koston
93c90124ee Merge branch 'integration' into memory_api 2025-08-14 10:07:27 -05:00
J. Nick Koston
6dd818a320 Merge branch 'integration' into memory_api 2025-08-14 09:41:12 -05:00
J. Nick Koston
6e9fb8201b Merge branch 'integration' into memory_api 2025-08-13 23:10:18 -05:00
J. Nick Koston
6fc0831762 Merge branch 'integration' into memory_api 2025-08-13 23:01:43 -05:00
J. Nick Koston
62a2b5e736 Merge branch 'integration' into memory_api 2025-08-13 22:46:00 -05:00
J. Nick Koston
3bf8624b87 Merge remote-tracking branch 'upstream/dev' into memory_api 2025-08-13 21:43:55 -05:00
J. Nick Koston
0c92dc77ad Merge branch 'integration' into memory_api 2025-08-13 11:24:22 -05:00
J. Nick Koston
bb6ce91c9d Merge branch 'integration' into memory_api 2025-08-12 21:03:55 -05:00
J. Nick Koston
9238916b32 one more 2025-08-12 20:22:10 -05:00
J. Nick Koston
ed9e717703 Merge branch 'integration' into memory_api 2025-08-12 19:33:42 -05:00
J. Nick Koston
1c409e1b51 Merge branch 'integration' into memory_api 2025-08-12 15:34:36 -05:00
J. Nick Koston
daa7633ebb Merge branch 'integration' into memory_api 2025-08-11 17:22:09 -05:00
J. Nick Koston
0813362ea8 Merge branch 'integration' into memory_api 2025-08-11 14:53:48 -05:00
J. Nick Koston
4b62f48e12 Merge branch 'integration' into memory_api 2025-08-11 14:37:19 -05:00
J. Nick Koston
11dd8ccd1e Merge branch 'integration' into memory_api 2025-08-11 13:29:31 -05:00
J. Nick Koston
073957a310 Merge branch 'integration' into memory_api 2025-08-11 00:44:05 -05:00
J. Nick Koston
cfe2bfea92 Merge branch 'integration' into memory_api 2025-08-11 00:09:51 -05:00
J. Nick Koston
336fea4251 Merge branch 'integration' into memory_api 2025-08-10 19:29:03 -05:00
J. Nick Koston
6f817fd06a Merge branch 'integration' into memory_api 2025-08-10 19:09:54 -05:00
J. Nick Koston
7c0856c460 Merge branch 'integration' into memory_api 2025-08-10 18:54:14 -05:00
J. Nick Koston
3cc916b9d8 Merge branch 'integration' into memory_api 2025-08-10 18:47:30 -05:00
J. Nick Koston
bcd4386fe4 Merge branch 'integration' into memory_api 2025-08-10 18:36:04 -05:00
J. Nick Koston
cd5f7fdc98 preen 2025-08-10 18:03:56 -05:00
J. Nick Koston
8ca671ad6f Merge branch 'integration' into memory_api 2025-08-10 17:53:46 -05:00
J. Nick Koston
3edb1e0726 Merge branch 'integration' into memory_api 2025-08-10 12:41:54 -05:00
J. Nick Koston
7ff8094be2 Merge branch 'integration' into memory_api 2025-08-10 11:12:57 -05:00
J. Nick Koston
5394ee37f9 Merge branch 'integration' into memory_api 2025-08-09 21:02:17 -05:00
J. Nick Koston
6aedcab37e Merge branch 'integration' into memory_api 2025-08-09 20:52:47 -05:00
J. Nick Koston
5b91c5f043 Merge branch 'integration' into memory_api 2025-08-09 20:46:51 -05:00
J. Nick Koston
233882e1c2 Merge branch 'integration' into memory_api 2025-08-09 14:06:01 -05:00
J. Nick Koston
48a94b686d Merge branch 'integration' into memory_api 2025-08-08 16:23:20 -05:00
J. Nick Koston
c982e35189 Merge branch 'integration' into memory_api 2025-08-08 16:05:26 -05:00
J. Nick Koston
61fbf7cd81 Merge branch 'integration' into memory_api 2025-08-07 12:55:44 -10:00
J. Nick Koston
760add7d29 Merge branch 'integration' into memory_api 2025-08-07 12:39:23 -10:00
J. Nick Koston
3f31bcacad Merge branch 'integration' into memory_api 2025-08-07 10:28:59 -10:00
J. Nick Koston
75249775ee Merge branch 'integration' into memory_api 2025-08-07 09:57:32 -10:00
J. Nick Koston
2ff418c8f9 Merge branch 'integration' into memory_api 2025-08-07 09:44:14 -10:00
J. Nick Koston
fb86bd05db Merge branch 'integration' into memory_api 2025-08-06 22:42:38 -10:00
J. Nick Koston
431a8dd374 Merge branch 'integration' into memory_api 2025-08-06 22:04:44 -10:00
J. Nick Koston
9841d7cf87 Merge branch 'integration' into memory_api 2025-08-06 17:31:53 -10:00
J. Nick Koston
28d2c86a91 Merge branch 'dev' into memory_api 2025-08-06 14:08:07 -10:00
J. Nick Koston
5e8768084b Merge branch 'integration' into memory_api 2025-08-06 10:56:41 -10:00
J. Nick Koston
e29b04bcfe Merge branch 'integration' into memory_api 2025-08-06 10:45:16 -10:00
J. Nick Koston
ddb1fcd0f9 preen 2025-08-06 10:39:44 -10:00
J. Nick Koston
2327c5bddf Merge branch 'integration' into memory_api 2025-08-06 10:28:49 -10:00
J. Nick Koston
2cdf50a025 tweak 2025-08-06 10:11:28 -10:00
J. Nick Koston
b75719d37e Merge branch 'integration' into memory_api 2025-08-06 10:03:29 -10:00
J. Nick Koston
27397593c1 Merge branch 'integration' into memory_api 2025-08-06 07:47:47 -10:00
J. Nick Koston
5511dae2fa Merge branch 'integration' into memory_api 2025-08-06 07:38:12 -10:00
J. Nick Koston
e1cb364436 Merge branch 'integration' into memory_api 2025-08-06 07:31:43 -10:00
J. Nick Koston
e5a1820708 Merge branch 'integration' into memory_api 2025-08-06 07:09:31 -10:00
J. Nick Koston
c667218f3f Merge branch 'conditional_compile_ble_adv' into memory_api 2025-08-05 22:22:42 -10:00
J. Nick Koston
2da1974a80 Merge branch 'integration' into memory_api 2025-08-05 22:02:28 -10:00
J. Nick Koston
ba713737bc Merge branch 'integration' into memory_api 2025-08-05 21:36:58 -10:00
J. Nick Koston
096b9c9651 Merge branch 'integration' into memory_api 2025-08-05 20:54:21 -10:00
J. Nick Koston
7e288126fa Merge branch 'integration' into memory_api 2025-08-05 20:30:40 -10:00
J. Nick Koston
addeec572a Merge branch 'integration' into memory_api 2025-08-05 17:26:40 -10:00
J. Nick Koston
c253eb2362 Merge branch 'integration' into memory_api 2025-08-05 17:06:06 -10:00
J. Nick Koston
eea84a43d6 Merge branch 'integration' into memory_api 2025-08-05 17:02:43 -10:00
J. Nick Koston
7344ff6941 merge 2025-08-04 21:50:36 -10:00
J. Nick Koston
2b5d035c39 Merge branch 'integration' into memory_api 2025-08-04 21:49:10 -10:00
J. Nick Koston
89cf81baaa Merge branch 'integration' into memory_api 2025-08-04 20:06:47 -10:00
J. Nick Koston
1c7200545b Merge branch 'integration' into memory_api 2025-08-04 16:52:44 -10:00
J. Nick Koston
3bbd3acea6 Merge branch 'integration' into memory_api 2025-08-04 16:26:55 -10:00
J. Nick Koston
9e1054cb87 Merge branch 'integration' into memory_api 2025-08-04 15:25:44 -10:00
J. Nick Koston
df83205997 Merge branch 'integration' into memory_api 2025-08-04 11:17:58 -10:00
J. Nick Koston
c6aeeb98b6 Merge branch 'integration' into memory_api 2025-08-04 11:10:01 -10:00
J. Nick Koston
2facd1b436 Cleanup esp32_ble_tracker 2025-08-04 09:18:30 -10:00
J. Nick Koston
d4ff83bf6e Merge branch 'integration' into memory_api 2025-08-04 08:52:25 -10:00
J. Nick Koston
15790145b2 Merge branch 'integration' into memory_api 2025-08-03 22:31:55 -10:00
J. Nick Koston
1d3cd0500e Merge branch 'integration' into memory_api 2025-08-03 22:20:15 -10:00
J. Nick Koston
5062bab73f Merge branch 'integration' into memory_api 2025-08-03 22:17:25 -10:00
J. Nick Koston
cccbe4293b Merge branch 'integration' into memory_api 2025-08-03 21:42:00 -10:00
J. Nick Koston
5126aefe13 Merge branch 'integration' into memory_api 2025-08-03 21:23:05 -10:00
J. Nick Koston
3a99929619 Merge branch 'integration' into memory_api 2025-08-03 21:02:31 -10:00
J. Nick Koston
a645c02476 Merge branch 'integration' into memory_api 2025-08-03 20:58:39 -10:00
J. Nick Koston
5ddf32b0a6 Merge branch 'integration' into memory_api 2025-08-03 19:32:46 -10:00
J. Nick Koston
85fd10f06e Merge branch 'integration' into memory_api 2025-08-03 18:06:01 -10:00
J. Nick Koston
a6c8651298 Merge branch 'integration' into memory_api 2025-08-03 16:31:11 -10:00
J. Nick Koston
7a7132f1c8 Merge branch 'integration' into memory_api 2025-08-03 16:16:40 -10:00
J. Nick Koston
367e35771e Merge branch 'integration' into memory_api 2025-08-03 15:51:48 -10:00
J. Nick Koston
27d66e5cfe Merge branch 'integration' into memory_api 2025-08-03 15:45:56 -10:00
J. Nick Koston
ef33d36d63 Merge branch 'integration' into memory_api 2025-08-03 15:04:46 -10:00
J. Nick Koston
e95baa67d5 Merge branch 'integration' into memory_api 2025-08-03 13:55:26 -10:00
J. Nick Koston
a86c0b66c8 Merge branch 'unregister_fd_flash' into memory_api 2025-08-02 22:45:29 -10:00
J. Nick Koston
f34e7a0051 Merge branch 'integration' into memory_api 2025-08-02 22:03:23 -10:00
J. Nick Koston
be701c58e1 Merge branch 'integration' into memory_api 2025-08-02 15:57:31 -10:00
J. Nick Koston
5d6a152c45 Merge branch 'integration' into memory_api 2025-08-02 15:37:27 -10:00
J. Nick Koston
7faded49d3 Merge branch 'integration' into memory_api 2025-08-02 14:23:48 -10:00
J. Nick Koston
5f0e1f8ab5 Merge branch 'integration' into memory_api 2025-08-02 13:01:22 -10:00
J. Nick Koston
3ef334c882 Merge branch 'integration' into memory_api 2025-08-02 12:54:39 -10:00
J. Nick Koston
ade5aba423 Merge branch 'integration' into memory_api 2025-08-02 12:47:00 -10:00
J. Nick Koston
178910d15e Merge branch 'integration' into memory_api 2025-08-02 12:04:28 -10:00
J. Nick Koston
18dca1a07d Merge branch 'integration' into memory_api 2025-08-02 10:30:55 -10:00
J. Nick Koston
79bc7ba206 Merge branch 'integration' into memory_api 2025-08-02 10:05:56 -10:00
J. Nick Koston
aa33baf5a2 Merge branch 'integration' into memory_api 2025-08-02 09:47:48 -10:00
J. Nick Koston
466f8d2050 remove test 2025-08-02 07:53:14 -10:00
J. Nick Koston
90b68d6fa0 Merge branch 'integration' into memory_api 2025-08-02 00:00:58 -10:00
J. Nick Koston
37827c1272 Merge branch 'integration' into memory_api 2025-08-01 23:08:30 -10:00
J. Nick Koston
9088790e63 Merge branch 'integration' into memory_api 2025-08-01 23:00:24 -10:00
J. Nick Koston
fdb437deb2 Merge branch 'integration' into memory_api 2025-08-01 22:39:01 -10:00
J. Nick Koston
9b3ee6936d Merge branch 'integration' into memory_api 2025-08-01 21:26:51 -10:00
J. Nick Koston
72d0660261 Merge branch 'integration' into memory_api 2025-08-01 21:26:29 -10:00
J. Nick Koston
9d0df67a9e Merge branch 'integration' into memory_api 2025-08-01 20:33:14 -10:00
J. Nick Koston
18fb3618a0 Merge branch 'integration' into memory_api 2025-08-01 15:41:50 -10:00
J. Nick Koston
4019bf9027 Merge branch 'integration' into memory_api 2025-08-01 15:36:16 -10:00
J. Nick Koston
082e365f82 Merge branch 'integration' into memory_api 2025-08-01 15:00:49 -10:00
J. Nick Koston
9005767b67 Merge branch 'integration' into memory_api 2025-08-01 14:13:33 -10:00
J. Nick Koston
1c469747d4 Merge branch 'integration' into memory_api 2025-08-01 13:01:25 -10:00
J. Nick Koston
7d1a816c5e Merge branch 'integration' into memory_api 2025-08-01 12:47:49 -10:00
J. Nick Koston
1a55885fc3 Merge branch 'integration' into memory_api 2025-08-01 11:21:24 -10:00
J. Nick Koston
9f52caf3b6 Merge branch 'integration' into memory_api 2025-08-01 11:19:46 -10:00
J. Nick Koston
7667325788 Merge branch 'integration' into memory_api 2025-08-01 11:17:16 -10:00
J. Nick Koston
ee7c44c3b0 Merge branch 'integration' into memory_api 2025-08-01 11:06:26 -10:00
J. Nick Koston
e079e46d99 Merge branch 'bluetooth_connection_churn' into memory_api 2025-08-01 11:06:24 -10:00
J. Nick Koston
f7c7aa9f9a Merge branch 'integration' into memory_api 2025-08-01 10:43:58 -10:00
J. Nick Koston
f3a57bd248 Merge branch 'integration' into memory_api 2025-07-31 11:51:50 -10:00
J. Nick Koston
038548500c Merge branch 'integration' into memory_api 2025-07-31 11:45:32 -10:00
J. Nick Koston
5d0323d6ea Merge branch 'btp_uuids_dynamic_services_sq' into memory_api 2025-07-31 11:45:28 -10:00
J. Nick Koston
6d40866231 Merge branch 'integration' into memory_api 2025-07-31 11:44:07 -10:00
J. Nick Koston
abb775fc53 Merge branch 'integration' into memory_api 2025-07-31 11:37:40 -10:00
J. Nick Koston
ce6aee873f Merge branch 'integration' into memory_api 2025-07-31 11:27:15 -10:00
J. Nick Koston
3988b48708 Merge branch 'btp_uuids' into memory_api 2025-07-31 05:15:41 -10:00
J. Nick Koston
ccae1bbe15 Merge branch 'integration' into memory_api 2025-07-31 04:17:55 -10:00
J. Nick Koston
6f4a8100ef Merge branch 'integration' into memory_api 2025-07-30 19:26:41 -10:00
J. Nick Koston
383f54810c Merge branch 'fix_normal_opts' into memory_api 2025-07-30 16:12:47 -10:00
J. Nick Koston
77677f3edc Merge branch 'integration' into memory_api 2025-07-30 15:39:40 -10:00
J. Nick Koston
caa9f6fdc7 Merge branch 'integration' into memory_api 2025-07-30 15:00:31 -10:00
J. Nick Koston
093e8093f5 Merge branch 'integration' into memory_api 2025-07-30 14:54:05 -10:00
J. Nick Koston
de51f0f205 Merge branch 'integration' into memory_api 2025-07-30 13:18:01 -10:00
J. Nick Koston
07bc41a900 Merge branch 'integration' into memory_api 2025-07-30 09:43:05 -10:00
J. Nick Koston
1600ab58a1 Merge branch 'integration' into memory_api 2025-07-30 00:12:36 -10:00
J. Nick Koston
24174c3eed Merge branch 'integration' into memory_api 2025-07-29 22:55:46 -10:00
J. Nick Koston
4441d0ea8d Merge branch 'integration' into memory_api 2025-07-29 15:53:43 -10:00
J. Nick Koston
4aec2a95f2 Merge branch 'integration' into memory_api 2025-07-29 14:58:15 -10:00
J. Nick Koston
579c6c57e0 Merge branch 'service_discovery' into memory_api 2025-07-29 14:32:55 -10:00
J. Nick Koston
ff1239c2a4 Merge branch 'integration' into memory_api 2025-07-29 14:27:04 -10:00
J. Nick Koston
53d68abf79 Merge branch 'integration' into memory_api 2025-07-29 10:17:46 -10:00
J. Nick Koston
11f0d0015c Merge branch 'integration' into memory_api 2025-07-29 09:55:31 -10:00
J. Nick Koston
2537c4437f cleanup 2025-07-29 07:15:12 -10:00
J. Nick Koston
9133554588 Merge branch 'integration' into memory_api 2025-07-29 07:06:56 -10:00
J. Nick Koston
e222232376 Merge branch 'integration' into memory_api 2025-07-29 07:04:07 -10:00
J. Nick Koston
aeec9a9379 Merge branch 'integration' into memory_api 2025-07-28 22:11:00 -10:00
J. Nick Koston
8b52a9a02e Merge branch 'integration' into memory_api 2025-07-28 22:10:32 -10:00
J. Nick Koston
226d465f6a Merge branch 'integration' into memory_api 2025-07-27 18:50:05 -10:00
J. Nick Koston
81cea0b2eb Merge branch 'integration' into memory_api 2025-07-27 11:36:35 -10:00
J. Nick Koston
0f5aff4d21 Merge branch 'integration' into memory_api 2025-07-27 11:08:21 -10:00
J. Nick Koston
e3b3259243 Merge branch 'integration' into memory_api 2025-07-26 22:15:15 -10:00
J. Nick Koston
9cf0535d39 Merge branch 'integration' into memory_api 2025-07-26 21:55:34 -10:00
J. Nick Koston
eb25ff0de7 Merge branch 'integration' into memory_api 2025-07-26 21:38:04 -10:00
J. Nick Koston
4f30fd9668 Merge branch 'integration' into memory_api 2025-07-26 21:36:16 -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
d9f3ecd1a3 Merge branch 'integration' into memory_api 2025-07-26 17:14:24 -10:00
J. Nick Koston
f9d0fa1c6d Merge branch 'integration' into memory_api 2025-07-26 17:09:53 -10:00
J. Nick Koston
de6686ee14 Merge branch 'integration' into memory_api 2025-07-26 13:11:37 -10:00
J. Nick Koston
cab11086ac Merge branch 'integration' into memory_api 2025-07-25 23:38:30 -10:00
J. Nick Koston
56b00f9bb7 Merge branch 'integration' into memory_api 2025-07-25 23:31:53 -10:00
J. Nick Koston
01101380ee Merge branch 'integration' into memory_api 2025-07-25 23:15:42 -10:00
J. Nick Koston
90908996b1 Merge branch 'integration' into memory_api 2025-07-25 23:13:32 -10:00
J. Nick Koston
a57daa2656 Merge branch 'integration' into memory_api 2025-07-25 23:12:04 -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
89c47c0dae Merge branch 'integration' into memory_api 2025-07-25 18:34:24 -10:00
J. Nick Koston
63e5a0b38c Merge branch 'integration' into memory_api 2025-07-25 18:28:03 -10:00
J. Nick Koston
00266e080b merge 2025-07-25 17:39:48 -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
f0a63313b1 Merge branch 'integration' into memory_api 2025-07-25 17:22:54 -10:00
J. Nick Koston
6c825def9e Merge branch 'integration' into memory_api 2025-07-25 17:15:23 -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
e28c32af15 Merge branch 'integration' into memory_api 2025-07-25 15:37:20 -10:00
J. Nick Koston
ce96c3c105 Merge branch 'integration' into memory_api 2025-07-25 14:48:21 -10:00
J. Nick Koston
6b49813084 Merge branch 'integration' into memory_api 2025-07-25 14:36:23 -10:00
J. Nick Koston
662b5a452e Merge branch 'integration' into memory_api 2025-07-25 13:34:00 -10:00
J. Nick Koston
254c70a420 Merge branch 'integration' into memory_api 2025-07-25 13:28:11 -10:00
J. Nick Koston
436ba20b7f Merge branch 'integration' into memory_api 2025-07-25 12:11:11 -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
90 changed files with 661 additions and 2050 deletions

View File

@@ -58,7 +58,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3
uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -86,6 +86,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3
uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
with:
category: "/language:${{matrix.language}}"

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.12.0-dev
PROJECT_NUMBER = 2025.11.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

@@ -1,6 +1,7 @@
"""CLI interface for memory analysis with report generation."""
from collections import defaultdict
import json
import sys
from . import (
@@ -15,11 +16,6 @@ from . import (
class MemoryAnalyzerCLI(MemoryAnalyzer):
"""Memory analyzer with CLI-specific report generation."""
# Symbol size threshold for detailed analysis
SYMBOL_SIZE_THRESHOLD: int = (
100 # Show symbols larger than this in detailed analysis
)
# Column width constants
COL_COMPONENT: int = 29
COL_FLASH_TEXT: int = 14
@@ -196,21 +192,14 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
f"{len(symbols):>{self.COL_CORE_COUNT}} | {percentage:>{self.COL_CORE_PERCENT - 1}.1f}%"
)
# All core symbols above threshold
# Top 15 largest core symbols
lines.append("")
lines.append(f"Top 15 Largest {_COMPONENT_CORE} Symbols:")
sorted_core_symbols = sorted(
self._esphome_core_symbols, key=lambda x: x[2], reverse=True
)
large_core_symbols = [
(symbol, demangled, size)
for symbol, demangled, size in sorted_core_symbols
if size > self.SYMBOL_SIZE_THRESHOLD
]
lines.append(
f"{_COMPONENT_CORE} Symbols > {self.SYMBOL_SIZE_THRESHOLD} B ({len(large_core_symbols)} symbols):"
)
for i, (symbol, demangled, size) in enumerate(large_core_symbols):
for i, (symbol, demangled, size) in enumerate(sorted_core_symbols[:15]):
lines.append(f"{i + 1}. {demangled} ({size:,} B)")
lines.append("=" * self.TABLE_WIDTH)
@@ -280,15 +269,13 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
lines.append(f"Total size: {comp_mem.flash_total:,} B")
lines.append("")
# Show all symbols above threshold for better visibility
# Show all symbols > 100 bytes for better visibility
large_symbols = [
(sym, dem, size)
for sym, dem, size in sorted_symbols
if size > self.SYMBOL_SIZE_THRESHOLD
(sym, dem, size) for sym, dem, size in sorted_symbols if size > 100
]
lines.append(
f"{comp_name} Symbols > {self.SYMBOL_SIZE_THRESHOLD} B ({len(large_symbols)} symbols):"
f"{comp_name} Symbols > 100 B ({len(large_symbols)} symbols):"
)
for i, (symbol, demangled, size) in enumerate(large_symbols):
lines.append(f"{i + 1}. {demangled} ({size:,} B)")
@@ -297,6 +284,28 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
return "\n".join(lines)
def to_json(self) -> str:
"""Export analysis results as JSON."""
data = {
"components": {
name: {
"text": mem.text_size,
"rodata": mem.rodata_size,
"data": mem.data_size,
"bss": mem.bss_size,
"flash_total": mem.flash_total,
"ram_total": mem.ram_total,
"symbol_count": mem.symbol_count,
}
for name, mem in self.components.items()
},
"totals": {
"flash": sum(c.flash_total for c in self.components.values()),
"ram": sum(c.ram_total for c in self.components.values()),
},
}
return json.dumps(data, indent=2)
def dump_uncategorized_symbols(self, output_file: str | None = None) -> None:
"""Dump uncategorized symbols for analysis."""
# Sort by size descending

View File

@@ -476,9 +476,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();
auto supported_modes = traits.get_supported_color_modes();
// Pass pointer to ColorModeMask so the iterator can encode actual ColorMode enum values
msg.supported_color_modes = &supported_modes;
msg.supported_color_modes = &traits.get_supported_color_modes();
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();
@@ -1296,8 +1295,8 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe
#ifdef USE_EVENT
void APIConnection::send_event(event::Event *event, const char *event_type) {
this->send_message_smart_(event, MessageCreator(event_type), EventResponse::MESSAGE_TYPE,
EventResponse::ESTIMATED_SIZE);
this->schedule_message_(event, MessageCreator(event_type), EventResponse::MESSAGE_TYPE,
EventResponse::ESTIMATED_SIZE);
}
uint16_t APIConnection::try_send_event_response(event::Event *event, const char *event_type, APIConnection *conn,
uint32_t remaining_size, bool is_single) {

View File

@@ -650,30 +650,21 @@ class APIConnection final : public APIServerConnection {
}
#endif
// Helper to check if a message type should bypass batching
// Returns true if:
// 1. It's an UpdateStateResponse (always send immediately to handle cases where
// the main loop is blocked, e.g., during OTA updates)
// 2. It's an EventResponse (events are edge-triggered - every occurrence matters)
// 3. OR: User has opted into immediate sending (should_try_send_immediately = true
// AND batch_delay = 0)
inline bool should_send_immediately_(uint8_t message_type) const {
return (
#ifdef USE_UPDATE
message_type == UpdateStateResponse::MESSAGE_TYPE ||
#endif
#ifdef USE_EVENT
message_type == EventResponse::MESSAGE_TYPE ||
#endif
(this->flags_.should_try_send_immediately && this->get_batch_delay_ms_() == 0));
}
// Helper method to send a message either immediately or via batching
// Tries immediate send if should_send_immediately_() returns true and buffer has space
// Falls back to batching if immediate send fails or isn't applicable
bool send_message_smart_(EntityBase *entity, MessageCreatorPtr creator, uint8_t message_type,
uint8_t estimated_size) {
if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) {
// 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)) &&
this->helper_->can_write_without_blocking()) {
// Now actually encode and send
if (creator(entity, this, MAX_BATCH_PACKET_SIZE, true) &&
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) {
@@ -691,27 +682,6 @@ class APIConnection final : public APIServerConnection {
return this->schedule_message_(entity, creator, message_type, estimated_size);
}
// Overload for MessageCreator (used by events which need to capture event_type)
bool send_message_smart_(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) {
// Try to send immediately if message type should bypass batching and buffer has space
if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) {
// Now actually encode and send
if (creator(entity, this, MAX_BATCH_PACKET_SIZE, true, message_type) &&
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) {
#ifdef HAS_PROTO_MESSAGE_DUMP
// Log the message in verbose mode
this->log_proto_message_(entity, creator, message_type);
#endif
return true;
}
// If immediate send failed, fall through to batching
}
// Fall back to scheduled batching
return this->schedule_message_(entity, std::move(creator), message_type, estimated_size);
}
// Helper function to schedule a deferred message with known message type
bool schedule_message_(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) {
this->deferred_batch_.add_item(entity, std::move(creator), message_type, estimated_size);

View File

@@ -1,12 +1,9 @@
import logging
import esphome.codegen as cg
from esphome.components import web_server_base
from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID
from esphome.config_helpers import filter_source_files_from_platform
import esphome.config_validation as cv
from esphome.const import (
CONF_AP,
CONF_ID,
PLATFORM_BK72XX,
PLATFORM_ESP32,
@@ -17,10 +14,6 @@ from esphome.const import (
)
from esphome.core import CORE, coroutine_with_priority
from esphome.coroutine import CoroPriority
import esphome.final_validate as fv
from esphome.types import ConfigType
_LOGGER = logging.getLogger(__name__)
def AUTO_LOAD() -> list[str]:
@@ -57,27 +50,6 @@ CONFIG_SCHEMA = cv.All(
)
def _final_validate(config: ConfigType) -> ConfigType:
full_config = fv.full_config.get()
wifi_conf = full_config.get("wifi")
if wifi_conf is None:
# This shouldn't happen due to DEPENDENCIES = ["wifi"], but check anyway
raise cv.Invalid("Captive portal requires the wifi component to be configured")
if CONF_AP not in wifi_conf:
_LOGGER.warning(
"Captive portal is enabled but no WiFi AP is configured. "
"The captive portal will not be accessible. "
"Add 'ap:' to your WiFi configuration to enable the captive portal."
)
return config
FINAL_VALIDATE_SCHEMA = _final_validate
@coroutine_with_priority(CoroPriority.CAPTIVE_PORTAL)
async def to_code(config):
paren = await cg.get_variable(config[CONF_WEB_SERVER_BASE_ID])

View File

@@ -49,9 +49,9 @@ void DebugComponent::dump_config() {
}
#endif // USE_TEXT_SENSOR
#if defined(USE_ESP32) || defined(USE_ZEPHYR)
this->log_partition_info_(); // Log partition information
#endif
#ifdef USE_ESP32
this->log_partition_info_(); // Log partition information for ESP32
#endif // USE_ESP32
}
void DebugComponent::loop() {

View File

@@ -62,19 +62,19 @@ class DebugComponent : public PollingComponent {
sensor::Sensor *cpu_frequency_sensor_{nullptr};
#endif // USE_SENSOR
#if defined(USE_ESP32) || defined(USE_ZEPHYR)
#ifdef USE_ESP32
/**
* @brief Logs information about the device's partition table.
*
* This function iterates through the partition table and logs details
* This function iterates through the ESP32's partition table and logs details
* about each partition, including its name, type, subtype, starting address,
* and size. The information is useful for diagnosing issues related to flash
* memory or verifying the partition configuration dynamically at runtime.
*
* Only available when compiled for ESP32 and ZEPHYR platforms.
* Only available when compiled for ESP32 platforms.
*/
void log_partition_info_();
#endif
#endif // USE_ESP32
#ifdef USE_TEXT_SENSOR
text_sensor::TextSensor *device_info_{nullptr};

View File

@@ -5,7 +5,6 @@
#include <zephyr/drivers/hwinfo.h>
#include <hal/nrf_power.h>
#include <cstdint>
#include <zephyr/storage/flash_map.h>
#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
@@ -87,37 +86,6 @@ std::string DebugComponent::get_reset_reason_() {
uint32_t DebugComponent::get_free_heap_() { return INT_MAX; }
static void fa_cb(const struct flash_area *fa, void *user_data) {
#if CONFIG_FLASH_MAP_LABELS
const char *fa_label = flash_area_label(fa);
if (fa_label == nullptr) {
fa_label = "-";
}
ESP_LOGCONFIG(TAG, "%2d 0x%0*" PRIxPTR " %-26s %-24.24s 0x%-10x 0x%-12x", (int) fa->fa_id,
sizeof(uintptr_t) * 2, (uintptr_t) fa->fa_dev, fa->fa_dev->name, fa_label, (uint32_t) fa->fa_off,
fa->fa_size);
#else
ESP_LOGCONFIG(TAG, "%2d 0x%0*" PRIxPTR " %-26s 0x%-10x 0x%-12x", (int) fa->fa_id, sizeof(uintptr_t) * 2,
(uintptr_t) fa->fa_dev, fa->fa_dev->name, (uint32_t) fa->fa_off, fa->fa_size);
#endif
}
void DebugComponent::log_partition_info_() {
#if CONFIG_FLASH_MAP_LABELS
ESP_LOGCONFIG(TAG, "ID | Device | Device Name "
"| Label | Offset | Size");
ESP_LOGCONFIG(TAG, "--------------------------------------------"
"-----------------------------------------------");
#else
ESP_LOGCONFIG(TAG, "ID | Device | Device Name "
"| Offset | Size");
ESP_LOGCONFIG(TAG, "-----------------------------------------"
"------------------------------");
#endif
flash_area_foreach(fa_cb, nullptr);
}
void DebugComponent::get_device_info_(std::string &device_info) {
std::string supply = "Main supply status: ";
if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_NORMAL) {

View File

@@ -334,14 +334,12 @@ def _is_framework_url(source: str) -> str:
# - https://github.com/espressif/arduino-esp32/releases
ARDUINO_FRAMEWORK_VERSION_LOOKUP = {
"recommended": cv.Version(3, 3, 2),
"latest": cv.Version(3, 3, 4),
"dev": cv.Version(3, 3, 4),
"latest": cv.Version(3, 3, 2),
"dev": cv.Version(3, 3, 2),
}
ARDUINO_PLATFORM_VERSION_LOOKUP = {
cv.Version(3, 3, 4): cv.Version(55, 3, 31, "2"),
cv.Version(3, 3, 3): cv.Version(55, 3, 31, "2"),
cv.Version(3, 3, 2): cv.Version(55, 3, 31, "2"),
cv.Version(3, 3, 1): cv.Version(55, 3, 31, "2"),
cv.Version(3, 3, 2): cv.Version(55, 3, 31, "1"),
cv.Version(3, 3, 1): cv.Version(55, 3, 31, "1"),
cv.Version(3, 3, 0): cv.Version(55, 3, 30, "2"),
cv.Version(3, 2, 1): cv.Version(54, 3, 21, "2"),
cv.Version(3, 2, 0): cv.Version(54, 3, 20),
@@ -359,8 +357,8 @@ ESP_IDF_FRAMEWORK_VERSION_LOOKUP = {
"dev": cv.Version(5, 5, 1),
}
ESP_IDF_PLATFORM_VERSION_LOOKUP = {
cv.Version(5, 5, 1): cv.Version(55, 3, 31, "2"),
cv.Version(5, 5, 0): cv.Version(55, 3, 31, "2"),
cv.Version(5, 5, 1): cv.Version(55, 3, 31, "1"),
cv.Version(5, 5, 0): cv.Version(55, 3, 31, "1"),
cv.Version(5, 4, 3): cv.Version(55, 3, 32),
cv.Version(5, 4, 2): cv.Version(54, 3, 21, "2"),
cv.Version(5, 4, 1): cv.Version(54, 3, 21, "2"),
@@ -375,15 +373,14 @@ ESP_IDF_PLATFORM_VERSION_LOOKUP = {
# The platform-espressif32 version
# - https://github.com/pioarduino/platform-espressif32/releases
PLATFORM_VERSION_LOOKUP = {
"recommended": cv.Version(55, 3, 31, "2"),
"latest": cv.Version(55, 3, 31, "2"),
"dev": cv.Version(55, 3, 31, "2"),
"recommended": cv.Version(55, 3, 31, "1"),
"latest": cv.Version(55, 3, 31, "1"),
"dev": cv.Version(55, 3, 31, "1"),
}
def _check_versions(config):
config = config.copy()
value = config[CONF_FRAMEWORK]
def _check_versions(value):
value = value.copy()
if value[CONF_VERSION] in PLATFORM_VERSION_LOOKUP:
if CONF_SOURCE in value or CONF_PLATFORM_VERSION in value:
@@ -448,7 +445,7 @@ def _check_versions(config):
"If there are connectivity or build issues please remove the manual version."
)
return config
return value
def _parse_platform_version(value):
@@ -498,8 +495,6 @@ def final_validate(config):
from esphome.components.psram import DOMAIN as PSRAM_DOMAIN
errs = []
conf_fw = config[CONF_FRAMEWORK]
advanced = conf_fw[CONF_ADVANCED]
full_config = fv.full_config.get()
if pio_options := full_config[CONF_ESPHOME].get(CONF_PLATFORMIO_OPTIONS):
pio_flash_size_key = "board_upload.flash_size"
@@ -516,14 +511,22 @@ def final_validate(config):
f"Please specify {CONF_FLASH_SIZE} within esp32 configuration only"
)
)
if config[CONF_VARIANT] != VARIANT_ESP32 and advanced[CONF_IGNORE_EFUSE_MAC_CRC]:
if (
config[CONF_VARIANT] != VARIANT_ESP32
and CONF_ADVANCED in (conf_fw := config[CONF_FRAMEWORK])
and CONF_IGNORE_EFUSE_MAC_CRC in conf_fw[CONF_ADVANCED]
):
errs.append(
cv.Invalid(
f"'{CONF_IGNORE_EFUSE_MAC_CRC}' is not supported on {config[CONF_VARIANT]}",
path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_IGNORE_EFUSE_MAC_CRC],
)
)
if advanced[CONF_EXECUTE_FROM_PSRAM]:
if (
config.get(CONF_FRAMEWORK, {})
.get(CONF_ADVANCED, {})
.get(CONF_EXECUTE_FROM_PSRAM)
):
if config[CONF_VARIANT] != VARIANT_ESP32S3:
errs.append(
cv.Invalid(
@@ -539,17 +542,6 @@ def final_validate(config):
)
)
if (
config[CONF_FLASH_SIZE] == "32MB"
and "ota" in full_config
and not advanced[CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES]
):
errs.append(
cv.Invalid(
f"OTA with 32MB flash requires '{CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES}' to be set in the '{CONF_ADVANCED}' section of the esp32 configuration",
path=[CONF_FLASH_SIZE],
)
)
if errs:
raise cv.MultipleInvalid(errs)
@@ -604,74 +596,89 @@ def _validate_idf_component(config: ConfigType) -> ConfigType:
FRAMEWORK_ESP_IDF = "esp-idf"
FRAMEWORK_ARDUINO = "arduino"
FRAMEWORK_SCHEMA = cv.Schema(
{
cv.Optional(CONF_TYPE): cv.one_of(FRAMEWORK_ESP_IDF, FRAMEWORK_ARDUINO),
cv.Optional(CONF_VERSION, default="recommended"): cv.string_strict,
cv.Optional(CONF_RELEASE): cv.string_strict,
cv.Optional(CONF_SOURCE): cv.string_strict,
cv.Optional(CONF_PLATFORM_VERSION): _parse_platform_version,
cv.Optional(CONF_SDKCONFIG_OPTIONS, default={}): {
cv.string_strict: cv.string_strict
},
cv.Optional(CONF_LOG_LEVEL, default="ERROR"): cv.one_of(
*LOG_LEVELS_IDF, upper=True
),
cv.Optional(CONF_ADVANCED, default={}): cv.Schema(
{
cv.Optional(CONF_ASSERTION_LEVEL): cv.one_of(
*ASSERTION_LEVELS, upper=True
),
cv.Optional(CONF_COMPILER_OPTIMIZATION, default="SIZE"): cv.one_of(
*COMPILER_OPTIMIZATIONS, upper=True
),
cv.Optional(
CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES, default=False
): cv.boolean,
cv.Optional(CONF_ENABLE_LWIP_ASSERT, default=True): cv.boolean,
cv.Optional(CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False): cv.boolean,
cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC, default=False): cv.boolean,
# DHCP server is needed for WiFi AP mode. When WiFi component is used,
# it will handle disabling DHCP server when AP is not configured.
# Default to false (disabled) when WiFi is not used.
cv.OnlyWithout(
CONF_ENABLE_LWIP_DHCP_SERVER, "wifi", default=False
): cv.boolean,
cv.Optional(CONF_ENABLE_LWIP_MDNS_QUERIES, default=True): cv.boolean,
cv.Optional(
CONF_ENABLE_LWIP_BRIDGE_INTERFACE, default=False
): cv.boolean,
cv.Optional(
CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, default=True
): cv.boolean,
cv.Optional(
CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, default=True
): cv.boolean,
cv.Optional(CONF_DISABLE_LIBC_LOCKS_IN_IRAM, default=True): cv.boolean,
cv.Optional(CONF_DISABLE_VFS_SUPPORT_TERMIOS, default=True): cv.boolean,
cv.Optional(CONF_DISABLE_VFS_SUPPORT_SELECT, default=True): cv.boolean,
cv.Optional(CONF_DISABLE_VFS_SUPPORT_DIR, default=True): cv.boolean,
cv.Optional(CONF_EXECUTE_FROM_PSRAM, default=False): cv.boolean,
cv.Optional(CONF_LOOP_TASK_STACK_SIZE, default=8192): cv.int_range(
min=8192, max=32768
),
}
),
cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list(
cv.All(
cv.Schema(
{
cv.Required(CONF_NAME): cv.string_strict,
cv.Optional(CONF_SOURCE): cv.git_ref,
cv.Optional(CONF_REF): cv.string,
cv.Optional(CONF_PATH): cv.string,
cv.Optional(CONF_REFRESH): cv.All(cv.string, cv.source_refresh),
}
),
_validate_idf_component,
)
),
}
FRAMEWORK_SCHEMA = cv.All(
cv.Schema(
{
cv.Optional(CONF_TYPE, default=FRAMEWORK_ARDUINO): cv.one_of(
FRAMEWORK_ESP_IDF, FRAMEWORK_ARDUINO
),
cv.Optional(CONF_VERSION, default="recommended"): cv.string_strict,
cv.Optional(CONF_RELEASE): cv.string_strict,
cv.Optional(CONF_SOURCE): cv.string_strict,
cv.Optional(CONF_PLATFORM_VERSION): _parse_platform_version,
cv.Optional(CONF_SDKCONFIG_OPTIONS, default={}): {
cv.string_strict: cv.string_strict
},
cv.Optional(CONF_LOG_LEVEL, default="ERROR"): cv.one_of(
*LOG_LEVELS_IDF, upper=True
),
cv.Optional(CONF_ADVANCED, default={}): cv.Schema(
{
cv.Optional(CONF_ASSERTION_LEVEL): cv.one_of(
*ASSERTION_LEVELS, upper=True
),
cv.Optional(CONF_COMPILER_OPTIMIZATION, default="SIZE"): cv.one_of(
*COMPILER_OPTIMIZATIONS, upper=True
),
cv.Optional(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES): cv.boolean,
cv.Optional(CONF_ENABLE_LWIP_ASSERT, default=True): cv.boolean,
cv.Optional(
CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False
): cv.boolean,
cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC): cv.boolean,
# DHCP server is needed for WiFi AP mode. When WiFi component is used,
# it will handle disabling DHCP server when AP is not configured.
# Default to false (disabled) when WiFi is not used.
cv.OnlyWithout(
CONF_ENABLE_LWIP_DHCP_SERVER, "wifi", default=False
): cv.boolean,
cv.Optional(
CONF_ENABLE_LWIP_MDNS_QUERIES, default=True
): cv.boolean,
cv.Optional(
CONF_ENABLE_LWIP_BRIDGE_INTERFACE, default=False
): cv.boolean,
cv.Optional(
CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, default=True
): cv.boolean,
cv.Optional(
CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, default=True
): cv.boolean,
cv.Optional(
CONF_DISABLE_LIBC_LOCKS_IN_IRAM, default=True
): cv.boolean,
cv.Optional(
CONF_DISABLE_VFS_SUPPORT_TERMIOS, default=True
): cv.boolean,
cv.Optional(
CONF_DISABLE_VFS_SUPPORT_SELECT, default=True
): cv.boolean,
cv.Optional(CONF_DISABLE_VFS_SUPPORT_DIR, default=True): cv.boolean,
cv.Optional(CONF_EXECUTE_FROM_PSRAM): cv.boolean,
cv.Optional(CONF_LOOP_TASK_STACK_SIZE, default=8192): cv.int_range(
min=8192, max=32768
),
}
),
cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list(
cv.All(
cv.Schema(
{
cv.Required(CONF_NAME): cv.string_strict,
cv.Optional(CONF_SOURCE): cv.git_ref,
cv.Optional(CONF_REF): cv.string,
cv.Optional(CONF_PATH): cv.string,
cv.Optional(CONF_REFRESH): cv.All(
cv.string, cv.source_refresh
),
}
),
_validate_idf_component,
)
),
}
),
_check_versions,
)
@@ -734,11 +741,11 @@ def _show_framework_migration_message(name: str, variant: str) -> None:
def _set_default_framework(config):
config = config.copy()
if CONF_FRAMEWORK not in config:
config[CONF_FRAMEWORK] = FRAMEWORK_SCHEMA({})
if CONF_TYPE not in config[CONF_FRAMEWORK]:
config = config.copy()
variant = config[CONF_VARIANT]
config[CONF_FRAMEWORK] = FRAMEWORK_SCHEMA({})
if variant in ARDUINO_ALLOWED_VARIANTS:
config[CONF_FRAMEWORK][CONF_TYPE] = FRAMEWORK_ARDUINO
_show_framework_migration_message(
@@ -778,7 +785,6 @@ CONFIG_SCHEMA = cv.All(
),
_detect_variant,
_set_default_framework,
_check_versions,
set_core_data,
cv.has_at_least_one_key(CONF_BOARD, CONF_VARIANT),
)
@@ -797,7 +803,9 @@ def _configure_lwip_max_sockets(conf: dict) -> None:
from esphome.components.socket import KEY_SOCKET_CONSUMERS
# Check if user manually specified CONFIG_LWIP_MAX_SOCKETS
user_max_sockets = conf[CONF_SDKCONFIG_OPTIONS].get("CONFIG_LWIP_MAX_SOCKETS")
user_max_sockets = conf.get(CONF_SDKCONFIG_OPTIONS, {}).get(
"CONFIG_LWIP_MAX_SOCKETS"
)
socket_consumers: dict[str, int] = CORE.data.get(KEY_SOCKET_CONSUMERS, {})
total_sockets = sum(socket_consumers.values())
@@ -967,18 +975,23 @@ async def to_code(config):
# WiFi component handles its own optimization when AP mode is not used
# When using Arduino with Ethernet, DHCP server functions must be available
# for the Network library to compile, even if not actively used
if advanced.get(CONF_ENABLE_LWIP_DHCP_SERVER) is False and not (
conf[CONF_TYPE] == FRAMEWORK_ARDUINO and "ethernet" in CORE.loaded_integrations
if (
CONF_ENABLE_LWIP_DHCP_SERVER in advanced
and not advanced[CONF_ENABLE_LWIP_DHCP_SERVER]
and not (
conf[CONF_TYPE] == FRAMEWORK_ARDUINO
and "ethernet" in CORE.loaded_integrations
)
):
add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False)
if not advanced[CONF_ENABLE_LWIP_MDNS_QUERIES]:
if not advanced.get(CONF_ENABLE_LWIP_MDNS_QUERIES, True):
add_idf_sdkconfig_option("CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES", False)
if not advanced[CONF_ENABLE_LWIP_BRIDGE_INTERFACE]:
if not advanced.get(CONF_ENABLE_LWIP_BRIDGE_INTERFACE, False):
add_idf_sdkconfig_option("CONFIG_LWIP_BRIDGEIF_MAX_PORTS", 0)
_configure_lwip_max_sockets(conf)
if advanced[CONF_EXECUTE_FROM_PSRAM]:
if advanced.get(CONF_EXECUTE_FROM_PSRAM, False):
add_idf_sdkconfig_option("CONFIG_SPIRAM_FETCH_INSTRUCTIONS", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True)
@@ -989,22 +1002,23 @@ async def to_code(config):
# - select() on 4 sockets: ~190μs (Arduino/core locking) vs ~235μs (ESP-IDF default)
# - Up to 200% slower under load when all operations queue through tcpip_thread
# Enabling this makes ESP-IDF socket performance match Arduino framework.
if advanced[CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING]:
if advanced.get(CONF_ENABLE_LWIP_TCPIP_CORE_LOCKING, True):
add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_CORE_LOCKING", True)
if advanced[CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY]:
if advanced.get(CONF_ENABLE_LWIP_CHECK_THREAD_SAFETY, True):
add_idf_sdkconfig_option("CONFIG_LWIP_CHECK_THREAD_SAFETY", True)
# Disable placing libc locks in IRAM to save RAM
# This is safe for ESPHome since no IRAM ISRs (interrupts that run while cache is disabled)
# use libc lock APIs. Saves approximately 1.3KB (1,356 bytes) of IRAM.
if advanced[CONF_DISABLE_LIBC_LOCKS_IN_IRAM]:
if advanced.get(CONF_DISABLE_LIBC_LOCKS_IN_IRAM, True):
add_idf_sdkconfig_option("CONFIG_LIBC_LOCKS_PLACE_IN_IRAM", False)
# Disable VFS support for termios (terminal I/O functions)
# ESPHome doesn't use termios functions on ESP32 (only used in host UART driver).
# Saves approximately 1.8KB of flash when disabled (default).
add_idf_sdkconfig_option(
"CONFIG_VFS_SUPPORT_TERMIOS", not advanced[CONF_DISABLE_VFS_SUPPORT_TERMIOS]
"CONFIG_VFS_SUPPORT_TERMIOS",
not advanced.get(CONF_DISABLE_VFS_SUPPORT_TERMIOS, True),
)
# Disable VFS support for select() with file descriptors
@@ -1018,7 +1032,8 @@ async def to_code(config):
else:
# No component needs it - allow user to control (default: disabled)
add_idf_sdkconfig_option(
"CONFIG_VFS_SUPPORT_SELECT", not advanced[CONF_DISABLE_VFS_SUPPORT_SELECT]
"CONFIG_VFS_SUPPORT_SELECT",
not advanced.get(CONF_DISABLE_VFS_SUPPORT_SELECT, True),
)
# Disable VFS support for directory functions (opendir, readdir, mkdir, etc.)
@@ -1031,7 +1046,8 @@ async def to_code(config):
else:
# No component needs it - allow user to control (default: disabled)
add_idf_sdkconfig_option(
"CONFIG_VFS_SUPPORT_DIR", not advanced[CONF_DISABLE_VFS_SUPPORT_DIR]
"CONFIG_VFS_SUPPORT_DIR",
not advanced.get(CONF_DISABLE_VFS_SUPPORT_DIR, True),
)
cg.add_platformio_option("board_build.partitions", "partitions.csv")
@@ -1045,7 +1061,7 @@ async def to_code(config):
add_idf_sdkconfig_option(flag, assertion_level == key)
add_idf_sdkconfig_option("CONFIG_COMPILER_OPTIMIZATION_DEFAULT", False)
compiler_optimization = advanced[CONF_COMPILER_OPTIMIZATION]
compiler_optimization = advanced.get(CONF_COMPILER_OPTIMIZATION)
for key, flag in COMPILER_OPTIMIZATIONS.items():
add_idf_sdkconfig_option(flag, compiler_optimization == key)
@@ -1054,20 +1070,18 @@ async def to_code(config):
conf[CONF_ADVANCED][CONF_ENABLE_LWIP_ASSERT],
)
if advanced[CONF_IGNORE_EFUSE_MAC_CRC]:
if advanced.get(CONF_IGNORE_EFUSE_MAC_CRC):
add_idf_sdkconfig_option("CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR", True)
add_idf_sdkconfig_option("CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE", False)
if advanced[CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES]:
if advanced.get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES):
_LOGGER.warning(
"Using experimental features in ESP-IDF may result in unexpected failures."
)
add_idf_sdkconfig_option("CONFIG_IDF_EXPERIMENTAL_FEATURES", True)
if config[CONF_FLASH_SIZE] == "32MB":
add_idf_sdkconfig_option(
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH", True
)
cg.add_define("ESPHOME_LOOP_TASK_STACK_SIZE", advanced[CONF_LOOP_TASK_STACK_SIZE])
cg.add_define(
"ESPHOME_LOOP_TASK_STACK_SIZE", advanced.get(CONF_LOOP_TASK_STACK_SIZE)
)
cg.add_define(
"USE_ESP_IDF_VERSION_CODE",

View File

@@ -638,13 +638,11 @@ void ESP32BLE::dump_config() {
io_capability_s = "invalid";
break;
}
char mac_s[18];
format_mac_addr_upper(mac_address, mac_s);
ESP_LOGCONFIG(TAG,
"BLE:\n"
" MAC address: %s\n"
" IO Capability: %s",
mac_s, io_capability_s);
format_mac_address_pretty(mac_address).c_str(), io_capability_s);
} else {
ESP_LOGCONFIG(TAG, "Bluetooth stack is not enabled");
}

View File

@@ -389,8 +389,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
if (this->conn_id_ != param->search_res.conn_id)
return false;
this->service_count_++;
if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE ||
this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
// V3 clients don't need services initialized since
// as they use the ESP APIs to get services.
break;

View File

@@ -15,7 +15,10 @@ Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_characteristic_on_w
Trigger<std::vector<uint8_t>, uint16_t> *on_write_trigger = // NOLINT(cppcoreguidelines-owning-memory)
new Trigger<std::vector<uint8_t>, uint16_t>();
characteristic->on_write([on_write_trigger](std::span<const uint8_t> data, uint16_t id) {
// Convert span to vector for trigger
// Convert span to vector for trigger - copy is necessary because:
// 1. Trigger stores the data for use in automation actions that execute later
// 2. The span is only valid during this callback (points to temporary BLE stack data)
// 3. User lambdas in automations need persistent data they can access asynchronously
on_write_trigger->trigger(std::vector<uint8_t>(data.begin(), data.end()), id);
});
return on_write_trigger;
@@ -27,7 +30,10 @@ Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_descriptor_on_write
Trigger<std::vector<uint8_t>, uint16_t> *on_write_trigger = // NOLINT(cppcoreguidelines-owning-memory)
new Trigger<std::vector<uint8_t>, uint16_t>();
descriptor->on_write([on_write_trigger](std::span<const uint8_t> data, uint16_t id) {
// Convert span to vector for trigger
// Convert span to vector for trigger - copy is necessary because:
// 1. Trigger stores the data for use in automation actions that execute later
// 2. The span is only valid during this callback (points to temporary BLE stack data)
// 3. User lambdas in automations need persistent data they can access asynchronously
on_write_trigger->trigger(std::vector<uint8_t>(data.begin(), data.end()), id);
});
return on_write_trigger;

View File

@@ -10,7 +10,7 @@ namespace esphome::esp32_ble_tracker {
class ESPBTAdvertiseTrigger : public Trigger<const ESPBTDevice &>, public ESPBTDeviceListener {
public:
explicit ESPBTAdvertiseTrigger(ESP32BLETracker *parent) { parent->register_listener(this); }
void set_addresses(std::initializer_list<uint64_t> addresses) { this->address_vec_ = addresses; }
void set_addresses(const std::vector<uint64_t> &addresses) { this->address_vec_ = addresses; }
bool parse_device(const ESPBTDevice &device) override {
uint64_t u64_addr = device.address_uint64();

View File

@@ -336,7 +336,7 @@ void ESP32ImprovComponent::process_incoming_data_() {
this->connecting_sta_ = sta;
wifi::global_wifi_component->set_sta(sta);
wifi::global_wifi_component->start_connecting(sta);
wifi::global_wifi_component->start_connecting(sta, false);
this->set_state_(improv::STATE_PROVISIONING);
ESP_LOGD(TAG, "Received Improv Wi-Fi settings ssid=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(),
command.password.c_str());

View File

@@ -381,10 +381,7 @@ void EthernetComponent::dump_config() {
break;
}
ESP_LOGCONFIG(TAG,
"Ethernet:\n"
" Connected: %s",
YESNO(this->is_connected()));
ESP_LOGCONFIG(TAG, "Ethernet:");
this->dump_connect_params_();
#ifdef USE_ETHERNET_SPI
ESP_LOGCONFIG(TAG,

View File

@@ -231,7 +231,7 @@ bool ImprovSerialComponent::parse_improv_payload_(improv::ImprovCommand &command
this->connecting_sta_ = sta;
wifi::global_wifi_component->set_sta(sta);
wifi::global_wifi_component->start_connecting(sta);
wifi::global_wifi_component->start_connecting(sta, false);
this->set_state_(improv::STATE_PROVISIONING);
ESP_LOGD(TAG, "Received settings: SSID=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(),
command.password.c_str());

View File

@@ -52,10 +52,8 @@ static void log_invalid_parameter(const char *name, const LogString *message) {
}
static const LogString *color_mode_to_human(ColorMode color_mode) {
if (color_mode == ColorMode::ON_OFF)
return LOG_STR("On/Off");
if (color_mode == ColorMode::BRIGHTNESS)
return LOG_STR("Brightness");
if (color_mode == ColorMode::UNKNOWN)
return LOG_STR("Unknown");
if (color_mode == ColorMode::WHITE)
return LOG_STR("White");
if (color_mode == ColorMode::COLOR_TEMPERATURE)
@@ -70,7 +68,7 @@ static const LogString *color_mode_to_human(ColorMode color_mode) {
return LOG_STR("RGB + cold/warm white");
if (color_mode == ColorMode::RGB_COLOR_TEMPERATURE)
return LOG_STR("RGB + color temperature");
return LOG_STR("Unknown");
return LOG_STR("");
}
// Helper to log percentage values
@@ -408,7 +406,7 @@ void LightCall::transform_parameters_() {
}
}
ColorMode LightCall::compute_color_mode_() {
auto supported_modes = this->parent_->get_traits().get_supported_color_modes();
const auto &supported_modes = this->parent_->get_traits().get_supported_color_modes();
int supported_count = supported_modes.size();
// Some lights don't support any color modes (e.g. monochromatic light), leave it at unknown.

View File

@@ -24,9 +24,6 @@ void LightState::setup() {
effect->init_internal(this);
}
// Start with loop disabled if idle - respects any effects/transitions set up during initialization
this->disable_loop_if_idle_();
// When supported color temperature range is known, initialize color temperature setting within bounds.
auto traits = this->get_traits();
float min_mireds = traits.get_min_mireds();
@@ -129,9 +126,6 @@ void LightState::loop() {
this->is_transformer_active_ = false;
this->transformer_ = nullptr;
this->target_state_reached_callback_.call();
// Disable loop if idle (no transformer and no effect)
this->disable_loop_if_idle_();
}
}
@@ -139,8 +133,6 @@ void LightState::loop() {
if (this->next_write_) {
this->next_write_ = false;
this->output_->write_state(this);
// Disable loop if idle (no transformer and no effect)
this->disable_loop_if_idle_();
}
}
@@ -236,8 +228,6 @@ void LightState::start_effect_(uint32_t effect_index) {
this->active_effect_index_ = effect_index;
auto *effect = this->get_active_effect_();
effect->start_internal();
// Enable loop while effect is active
this->enable_loop();
}
LightEffect *LightState::get_active_effect_() {
if (this->active_effect_index_ == 0) {
@@ -252,8 +242,6 @@ void LightState::stop_effect_() {
effect->stop();
}
this->active_effect_index_ = 0;
// Disable loop if idle (no effect and no transformer)
this->disable_loop_if_idle_();
}
void LightState::start_transition_(const LightColorValues &target, uint32_t length, bool set_remote_values) {
@@ -263,8 +251,6 @@ void LightState::start_transition_(const LightColorValues &target, uint32_t leng
if (set_remote_values) {
this->remote_values = target;
}
// Enable loop while transition is active
this->enable_loop();
}
void LightState::start_flash_(const LightColorValues &target, uint32_t length, bool set_remote_values) {
@@ -280,8 +266,6 @@ void LightState::start_flash_(const LightColorValues &target, uint32_t length, b
if (set_remote_values) {
this->remote_values = target;
};
// Enable loop while flash is active
this->enable_loop();
}
void LightState::set_immediately_(const LightColorValues &target, bool set_remote_values) {
@@ -293,14 +277,6 @@ void LightState::set_immediately_(const LightColorValues &target, bool set_remot
}
this->output_->update_state(this);
this->next_write_ = true;
this->enable_loop();
}
void LightState::disable_loop_if_idle_() {
// Only disable loop if both transformer and effect are inactive, and no pending writes
if (this->transformer_ == nullptr && this->get_active_effect_() == nullptr && !this->next_write_) {
this->disable_loop();
}
}
void LightState::save_remote_values_() {

View File

@@ -256,9 +256,6 @@ class LightState : public EntityBase, public Component {
/// Internal method to save the current remote_values to the preferences
void save_remote_values_();
/// Disable loop if neither transformer nor effect is active
void disable_loop_if_idle_();
/// Store the output to allow effects to have more access.
LightOutput *output_;
/// The currently active transformer for this light (transition/flash).

View File

@@ -18,8 +18,7 @@ class LightTraits {
public:
LightTraits() = default;
// Return by value to avoid dangling reference when get_traits() returns a temporary
ColorModeMask get_supported_color_modes() const { return this->supported_color_modes_; }
const ColorModeMask &get_supported_color_modes() const { return this->supported_color_modes_; }
void set_supported_color_modes(ColorModeMask supported_color_modes) {
this->supported_color_modes_ = supported_color_modes;
}

View File

@@ -331,7 +331,7 @@ async def to_code(configs):
# This must be done after all widgets are created
for comp in helpers.lvgl_components_required:
cg.add_define(f"USE_LVGL_{comp.upper()}")
if {"transform_angle", "transform_zoom"} & styles_used:
if "transform_angle" in styles_used:
add_define("LV_COLOR_SCREEN_TRANSP", "1")
for use in helpers.lv_uses:
add_define(f"LV_USE_{use.upper()}")

View File

@@ -1,9 +1,7 @@
import ipaddress
import logging
import esphome.codegen as cg
from esphome.components.esp32 import add_idf_sdkconfig_option
from esphome.components.psram import is_guaranteed as psram_is_guaranteed
import esphome.config_validation as cv
from esphome.const import CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT
from esphome.core import CORE, CoroPriority, coroutine_with_priority
@@ -11,13 +9,6 @@ from esphome.core import CORE, CoroPriority, coroutine_with_priority
CODEOWNERS = ["@esphome/core"]
AUTO_LOAD = ["mdns"]
_LOGGER = logging.getLogger(__name__)
# High performance networking tracking infrastructure
# Components can request high performance networking and this configures lwip and WiFi settings
KEY_HIGH_PERFORMANCE_NETWORKING = "high_performance_networking"
CONF_ENABLE_HIGH_PERFORMANCE = "enable_high_performance"
network_ns = cg.esphome_ns.namespace("network")
IPAddress = network_ns.class_("IPAddress")
@@ -56,55 +47,6 @@ def ip_address_literal(ip: str | int | None) -> cg.MockObj:
return IPAddress(str(ip))
def require_high_performance_networking() -> None:
"""Request high performance networking for network and WiFi.
Call this from components that need optimized network performance for streaming
or high-throughput data transfer. This enables high performance mode which
configures both lwip TCP settings and WiFi driver settings for improved
network performance.
Settings applied (ESP-IDF only):
- lwip: Larger TCP buffers, windows, and mailbox sizes
- WiFi: Increased RX/TX buffers, AMPDU aggregation, PSRAM allocation (set by wifi component)
Configuration is PSRAM-aware:
- With PSRAM guaranteed: Aggressive settings (512 RX buffers, 512KB TCP windows)
- Without PSRAM: Conservative optimized settings (64 buffers, 65KB TCP windows)
Example:
from esphome.components import network
def _request_high_performance_networking(config):
network.require_high_performance_networking()
return config
CONFIG_SCHEMA = cv.All(
...,
_request_high_performance_networking,
)
"""
# Only set up once (idempotent - multiple components can call this)
if not CORE.data.get(KEY_HIGH_PERFORMANCE_NETWORKING, False):
CORE.data[KEY_HIGH_PERFORMANCE_NETWORKING] = True
def has_high_performance_networking() -> bool:
"""Check if high performance networking mode is enabled.
Returns True when high performance networking has been requested by a
component or explicitly enabled in the network configuration. This indicates
that lwip and WiFi will use optimized buffer sizes and settings.
This function should be called during code generation (to_code phase) by
components that need to apply performance-related settings.
Returns:
bool: True if high performance networking is enabled, False otherwise
"""
return CORE.data.get(KEY_HIGH_PERFORMANCE_NETWORKING, False)
CONFIG_SCHEMA = cv.Schema(
{
cv.SplitDefault(
@@ -129,7 +71,6 @@ CONFIG_SCHEMA = cv.Schema(
),
),
cv.Optional(CONF_MIN_IPV6_ADDR_COUNT, default=0): cv.positive_int,
cv.Optional(CONF_ENABLE_HIGH_PERFORMANCE): cv.All(cv.boolean, cv.only_on_esp32),
}
)
@@ -139,70 +80,6 @@ async def to_code(config):
cg.add_define("USE_NETWORK")
if CORE.using_arduino and CORE.is_esp32:
cg.add_library("Networking", None)
# Apply high performance networking settings
# Config can explicitly enable/disable, or default to component-driven behavior
enable_high_perf = config.get(CONF_ENABLE_HIGH_PERFORMANCE)
component_requested = CORE.data.get(KEY_HIGH_PERFORMANCE_NETWORKING, False)
# Explicit config overrides component request
should_enable = (
enable_high_perf if enable_high_perf is not None else component_requested
)
# Log when user explicitly disables but a component requested it
if enable_high_perf is False and component_requested:
_LOGGER.info(
"High performance networking disabled by user configuration (overriding component request)"
)
if CORE.is_esp32 and CORE.using_esp_idf and should_enable:
# Check if PSRAM is guaranteed (set by psram component during final validation)
psram_guaranteed = psram_is_guaranteed()
if psram_guaranteed:
_LOGGER.info(
"Applying high-performance lwip settings (PSRAM guaranteed): 512KB TCP windows, 512 mailbox sizes"
)
# PSRAM is guaranteed - use aggressive settings
# Higher maximum values are allowed because CONFIG_LWIP_WND_SCALE is set to true
# CONFIG_LWIP_WND_SCALE can only be enabled if CONFIG_SPIRAM_IGNORE_NOTFOUND isn't set
# Based on https://github.com/espressif/esp-adf/issues/297#issuecomment-783811702
# Enable window scaling for much larger TCP windows
add_idf_sdkconfig_option("CONFIG_LWIP_WND_SCALE", True)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_RCV_SCALE", 3)
# Large TCP buffers and windows (requires PSRAM)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_SND_BUF_DEFAULT", 65534)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_WND_DEFAULT", 512000)
# Large mailboxes for high throughput
add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_RECVMBOX_SIZE", 512)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_RECVMBOX_SIZE", 512)
# TCP connection limits
add_idf_sdkconfig_option("CONFIG_LWIP_MAX_ACTIVE_TCP", 16)
add_idf_sdkconfig_option("CONFIG_LWIP_MAX_LISTENING_TCP", 16)
# TCP optimizations
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_MAXRTX", 12)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_SYNMAXRTX", 6)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_MSS", 1436)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_MSL", 60000)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_OVERSIZE_MSS", True)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_QUEUE_OOSEQ", True)
else:
_LOGGER.info(
"Applying optimized lwip settings: 65KB TCP windows, 64 mailbox sizes"
)
# PSRAM not guaranteed - use more conservative, but still optimized settings
# Based on https://github.com/espressif/esp-idf/blob/release/v5.4/examples/wifi/iperf/sdkconfig.defaults.esp32
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_SND_BUF_DEFAULT", 65534)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_WND_DEFAULT", 65534)
add_idf_sdkconfig_option("CONFIG_LWIP_TCP_RECVMBOX_SIZE", 64)
add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_RECVMBOX_SIZE", 64)
if (enable_ipv6 := config.get(CONF_ENABLE_IPV6, None)) is not None:
cg.add_define("USE_NETWORK_IPV6", enable_ipv6)
if enable_ipv6:

View File

@@ -118,10 +118,10 @@ struct IPAddress {
operator arduino_ns::IPAddress() const { return ip_addr_get_ip4_u32(&ip_addr_); }
#endif
bool is_set() const { return !ip_addr_isany(&ip_addr_); } // NOLINT(readability-simplify-boolean-expr)
bool is_ip4() const { return IP_IS_V4(&ip_addr_); }
bool is_ip6() const { return IP_IS_V6(&ip_addr_); }
bool is_multicast() const { return ip_addr_ismulticast(&ip_addr_); }
bool is_set() { return !ip_addr_isany(&ip_addr_); } // NOLINT(readability-simplify-boolean-expr)
bool is_ip4() { return IP_IS_V4(&ip_addr_); }
bool is_ip6() { return IP_IS_V6(&ip_addr_); }
bool is_multicast() { return ip_addr_ismulticast(&ip_addr_); }
std::string str() const { return str_lower_case(ipaddr_ntoa(&ip_addr_)); }
bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); }
bool operator!=(const IPAddress &other) const { return !ip_addr_cmp(&ip_addr_, &other.ip_addr_); }

View File

@@ -103,11 +103,11 @@ nrf52_ns = cg.esphome_ns.namespace("nrf52")
DeviceFirmwareUpdate = nrf52_ns.class_("DeviceFirmwareUpdate", cg.Component)
CONF_DFU = "dfu"
CONF_DCDC = "dcdc"
CONF_REG0 = "reg0"
CONF_UICR_ERASE = "uicr_erase"
VOLTAGE_LEVELS = [1.8, 2.1, 2.4, 2.7, 3.0, 3.3]
DEFAULT_VOLTAGE_LEVEL = "default"
CONFIG_SCHEMA = cv.All(
_detect_bootloader,
@@ -122,12 +122,14 @@ CONFIG_SCHEMA = cv.All(
cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema,
}
),
cv.Optional(CONF_DCDC, default=True): cv.boolean,
cv.Optional(CONF_REG0): cv.Schema(
{
cv.Required(CONF_VOLTAGE): cv.All(
cv.voltage,
cv.one_of(*VOLTAGE_LEVELS, float=True),
cv.Required(CONF_VOLTAGE): cv.Any(
cv.All(
cv.voltage,
cv.one_of(*VOLTAGE_LEVELS, float=True),
),
cv.one_of(*[DEFAULT_VOLTAGE_LEVEL], lower=True),
),
cv.Optional(CONF_UICR_ERASE, default=False): cv.boolean,
}
@@ -198,10 +200,11 @@ async def to_code(config: ConfigType) -> None:
if dfu_config := config.get(CONF_DFU):
CORE.add_job(_dfu_to_code, dfu_config)
zephyr_add_prj_conf("BOARD_ENABLE_DCDC", config[CONF_DCDC])
if reg0_config := config.get(CONF_REG0):
value = VOLTAGE_LEVELS.index(reg0_config[CONF_VOLTAGE])
value = 7 # DEFAULT_VOLTAGE_LEVEL
if reg0_config[CONF_VOLTAGE] in VOLTAGE_LEVELS:
value = VOLTAGE_LEVELS.index(reg0_config[CONF_VOLTAGE])
cg.add_define("USE_NRF52_REG0_VOUT", value)
if reg0_config[CONF_UICR_ERASE]:
cg.add_define("USE_NRF52_UICR_ERASE")

View File

@@ -69,20 +69,9 @@ static StatusFlags fix_bootloader() {
}
#endif
#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
static StatusFlags set_uicr() {
StatusFlags status = StatusFlags::OK;
#ifndef USE_BOOTLOADER_MCUBOOT
if (BOOTLOADER_VERSION_REGISTER <= 0x902) {
#ifdef CONFIG_PRINTK
printk("cannot control regout0 for %#x\n", BOOTLOADER_VERSION_REGISTER);
#endif
} else
#endif
{
status |= set_regout0();
}
status |= set_regout0();
#ifndef USE_BOOTLOADER_MCUBOOT
status |= fix_bootloader();
#endif

View File

@@ -174,9 +174,6 @@ FINAL_VALIDATE_SCHEMA = _final_validate
async def to_code(config):
cg.add_define("USE_OPENTHREAD")
# OpenThread uses esp_vfs_eventfd which requires VFS select support
require_vfs_select()
# OpenThread SRP needs access to mDNS services after setup
enable_mdns_storage()

View File

@@ -35,9 +35,6 @@ DOMAIN = "psram"
DEPENDENCIES = [PLATFORM_ESP32]
# PSRAM availability tracking for cross-component coordination
KEY_PSRAM_GUARANTEED = "psram_guaranteed"
_LOGGER = logging.getLogger(__name__)
psram_ns = cg.esphome_ns.namespace(DOMAIN)
@@ -74,23 +71,6 @@ def supported() -> bool:
return variant in SPIRAM_MODES
def is_guaranteed() -> bool:
"""Check if PSRAM is guaranteed to be available.
Returns True when PSRAM is configured with both 'disabled: false' and
'ignore_not_found: false', meaning the device will fail to boot if PSRAM
is not found. This ensures safe use of high buffer configurations that
depend on PSRAM.
This function should be called during code generation (to_code phase) by
components that need to know PSRAM availability for configuration decisions.
Returns:
bool: True if PSRAM is guaranteed, False otherwise
"""
return CORE.data.get(KEY_PSRAM_GUARANTEED, False)
def validate_psram_mode(config):
esp32_config = fv.full_config.get()[PLATFORM_ESP32]
if config[CONF_SPEED] == "120MHZ":
@@ -151,22 +131,7 @@ def get_config_schema(config):
CONFIG_SCHEMA = get_config_schema
def _store_psram_guaranteed(config):
"""Store PSRAM guaranteed status in CORE.data for other components.
PSRAM is "guaranteed" when it will fail if not found, ensuring safe use
of high buffer configurations in network/wifi components.
Called during final validation to ensure the flag is available
before any to_code() functions run.
"""
psram_guaranteed = not config[CONF_DISABLED] and not config[CONF_IGNORE_NOT_FOUND]
CORE.data[KEY_PSRAM_GUARANTEED] = psram_guaranteed
return config
FINAL_VALIDATE_SCHEMA = cv.All(validate_psram_mode, _store_psram_guaranteed)
FINAL_VALIDATE_SCHEMA = validate_psram_mode
async def to_code(config):

View File

@@ -1,14 +1,9 @@
import logging
import esphome.codegen as cg
from esphome.components import time as time_
from esphome.config_helpers import merge_config
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_PLATFORM,
CONF_SERVERS,
CONF_TIME,
PLATFORM_BK72XX,
PLATFORM_ESP32,
PLATFORM_ESP8266,
@@ -17,74 +12,13 @@ from esphome.const import (
PLATFORM_RTL87XX,
)
from esphome.core import CORE
import esphome.final_validate as fv
from esphome.types import ConfigType
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ["network"]
CONF_SNTP = "sntp"
sntp_ns = cg.esphome_ns.namespace("sntp")
SNTPComponent = sntp_ns.class_("SNTPComponent", time_.RealTimeClock)
DEFAULT_SERVERS = ["0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org"]
def _sntp_final_validate(config: ConfigType) -> None:
"""Merge multiple SNTP instances into one, similar to OTA merging behavior."""
full_conf = fv.full_config.get()
time_confs = full_conf.get(CONF_TIME, [])
sntp_configs: list[ConfigType] = []
other_time_configs: list[ConfigType] = []
for time_conf in time_confs:
if time_conf.get(CONF_PLATFORM) == CONF_SNTP:
sntp_configs.append(time_conf)
else:
other_time_configs.append(time_conf)
if len(sntp_configs) <= 1:
return
# Merge all SNTP configs into the first one
merged = sntp_configs[0]
for sntp_conf in sntp_configs[1:]:
# Validate that IDs are consistent if manually specified
if merged[CONF_ID].is_manual and sntp_conf[CONF_ID].is_manual:
raise cv.Invalid(
f"Found multiple SNTP configurations but {CONF_ID} is inconsistent"
)
merged = merge_config(merged, sntp_conf)
# Deduplicate servers while preserving order
servers = merged[CONF_SERVERS]
unique_servers = list(dict.fromkeys(servers))
# Warn if we're dropping servers due to 3-server limit
if len(unique_servers) > 3:
dropped = unique_servers[3:]
unique_servers = unique_servers[:3]
_LOGGER.warning(
"SNTP supports maximum 3 servers. Dropped excess server(s): %s",
dropped,
)
merged[CONF_SERVERS] = unique_servers
_LOGGER.warning(
"Found and merged %d SNTP time configurations into one instance",
len(sntp_configs),
)
# Replace time configs with merged SNTP + other time platforms
other_time_configs.append(merged)
full_conf[CONF_TIME] = other_time_configs
fv.full_config.set(full_conf)
CONFIG_SCHEMA = cv.All(
time_.TIME_SCHEMA.extend(
{
@@ -106,8 +40,6 @@ CONFIG_SCHEMA = cv.All(
),
)
FINAL_VALIDATE_SCHEMA = _sntp_final_validate
async def to_code(config):
servers = config[CONF_SERVERS]

View File

@@ -6,7 +6,7 @@ from pathlib import Path
from esphome import automation, external_files
import esphome.codegen as cg
from esphome.components import audio, esp32, media_player, network, psram, speaker
from esphome.components import audio, esp32, media_player, psram, speaker
import esphome.config_validation as cv
from esphome.const import (
CONF_BUFFER_SIZE,
@@ -32,7 +32,6 @@ _LOGGER = logging.getLogger(__name__)
AUTO_LOAD = ["audio"]
DEPENDENCIES = ["network"]
CODEOWNERS = ["@kahrendt", "@synesthesiam"]
DOMAIN = "media_player"
@@ -281,18 +280,6 @@ PIPELINE_SCHEMA = cv.Schema(
}
)
def _request_high_performance_networking(config):
"""Request high performance networking for streaming media.
Speaker media player streams audio data, so it always benefits from
optimized WiFi and lwip settings regardless of codec support.
Called during config validation to ensure flags are set before to_code().
"""
network.require_high_performance_networking()
return config
CONFIG_SCHEMA = cv.All(
media_player.media_player_schema(SpeakerMediaPlayer).extend(
{
@@ -317,7 +304,6 @@ CONFIG_SCHEMA = cv.All(
),
cv.only_with_esp_idf,
_validate_repeated_speaker,
_request_high_performance_networking,
)
@@ -335,10 +321,28 @@ FINAL_VALIDATE_SCHEMA = cv.All(
async def to_code(config):
if CORE.data[DOMAIN][config[CONF_ID].id][CONF_CODEC_SUPPORT_ENABLED]:
# Compile all supported audio codecs
# Compile all supported audio codecs and optimize the wifi settings
cg.add_define("USE_AUDIO_FLAC_SUPPORT", True)
cg.add_define("USE_AUDIO_MP3_SUPPORT", True)
# Based on https://github.com/espressif/esp-idf/blob/release/v5.4/examples/wifi/iperf/sdkconfig.defaults.esp32
esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM", 16)
esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM", 64)
esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM", 64)
esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_AMPDU_TX_ENABLED", True)
esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_TX_BA_WIN", 32)
esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_AMPDU_RX_ENABLED", True)
esp32.add_idf_sdkconfig_option("CONFIG_ESP_WIFI_RX_BA_WIN", 32)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCP_SND_BUF_DEFAULT", 65534)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCP_WND_DEFAULT", 65534)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCP_RECVMBOX_SIZE", 64)
esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_RECVMBOX_SIZE", 64)
# Allocate wifi buffers in PSRAM
esp32.add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True)
var = await media_player.new_media_player(config)
await cg.register_component(var, config)

View File

@@ -137,11 +137,7 @@ async def to_code(config):
cg.add(var.set_arming_night_time(config[CONF_ARMING_NIGHT_TIME]))
supports_arm_night = True
if sensors := config.get(CONF_BINARY_SENSORS, []):
# Initialize FixedVector with the exact number of sensors
cg.add(var.init_sensors(len(sensors)))
for sensor in sensors:
for sensor in config.get(CONF_BINARY_SENSORS, []):
bs = await cg.get_variable(sensor[CONF_INPUT])
flags = BinarySensorFlags[FLAG_NORMAL]

View File

@@ -20,13 +20,10 @@ void TemplateAlarmControlPanel::add_sensor(binary_sensor::BinarySensor *sensor,
// Save the flags and type. Assign a store index for the per sensor data type.
SensorDataStore sd;
sd.last_chime_state = false;
AlarmSensor alarm_sensor;
alarm_sensor.sensor = sensor;
alarm_sensor.info.flags = flags;
alarm_sensor.info.type = type;
alarm_sensor.info.store_index = this->next_store_index_++;
this->sensors_.push_back(alarm_sensor);
this->sensor_map_[sensor].flags = flags;
this->sensor_map_[sensor].type = type;
this->sensor_data_.push_back(sd);
this->sensor_map_[sensor].store_index = this->next_store_index_++;
};
static const LogString *sensor_type_to_string(AlarmSensorType type) {
@@ -48,7 +45,7 @@ void TemplateAlarmControlPanel::dump_config() {
ESP_LOGCONFIG(TAG,
"TemplateAlarmControlPanel:\n"
" Current State: %s\n"
" Number of Codes: %zu\n"
" Number of Codes: %u\n"
" Requires Code To Arm: %s\n"
" Arming Away Time: %" PRIu32 "s\n"
" Arming Home Time: %" PRIu32 "s\n"
@@ -61,8 +58,7 @@ void TemplateAlarmControlPanel::dump_config() {
(this->arming_home_time_ / 1000), (this->arming_night_time_ / 1000), (this->pending_time_ / 1000),
(this->trigger_time_ / 1000), this->get_supported_features());
#ifdef USE_BINARY_SENSOR
for (const auto &alarm_sensor : this->sensors_) {
const uint16_t flags = alarm_sensor.info.flags;
for (auto const &[sensor, info] : this->sensor_map_) {
ESP_LOGCONFIG(TAG,
" Binary Sensor:\n"
" Name: %s\n"
@@ -71,10 +67,11 @@ void TemplateAlarmControlPanel::dump_config() {
" Armed night bypass: %s\n"
" Auto bypass: %s\n"
" Chime mode: %s",
alarm_sensor.sensor->get_name().c_str(), LOG_STR_ARG(sensor_type_to_string(alarm_sensor.info.type)),
TRUEFALSE(flags & BINARY_SENSOR_MODE_BYPASS_ARMED_HOME),
TRUEFALSE(flags & BINARY_SENSOR_MODE_BYPASS_ARMED_NIGHT),
TRUEFALSE(flags & BINARY_SENSOR_MODE_BYPASS_AUTO), TRUEFALSE(flags & BINARY_SENSOR_MODE_CHIME));
sensor->get_name().c_str(), LOG_STR_ARG(sensor_type_to_string(info.type)),
TRUEFALSE(info.flags & BINARY_SENSOR_MODE_BYPASS_ARMED_HOME),
TRUEFALSE(info.flags & BINARY_SENSOR_MODE_BYPASS_ARMED_NIGHT),
TRUEFALSE(info.flags & BINARY_SENSOR_MODE_BYPASS_AUTO),
TRUEFALSE(info.flags & BINARY_SENSOR_MODE_CHIME));
}
#endif
}
@@ -124,9 +121,7 @@ void TemplateAlarmControlPanel::loop() {
#ifdef USE_BINARY_SENSOR
// Test all of the sensors regardless of the alarm panel state
for (const auto &alarm_sensor : this->sensors_) {
const auto &info = alarm_sensor.info;
auto *sensor = alarm_sensor.sensor;
for (auto const &[sensor, info] : this->sensor_map_) {
// Check for chime zones
if (info.flags & BINARY_SENSOR_MODE_CHIME) {
// Look for the transition from closed to open
@@ -247,11 +242,11 @@ void TemplateAlarmControlPanel::arm_(optional<std::string> code, alarm_control_p
void TemplateAlarmControlPanel::bypass_before_arming() {
#ifdef USE_BINARY_SENSOR
for (const auto &alarm_sensor : this->sensors_) {
for (auto const &[sensor, info] : this->sensor_map_) {
// Check for faulted bypass_auto sensors and remove them from monitoring
if ((alarm_sensor.info.flags & BINARY_SENSOR_MODE_BYPASS_AUTO) && (alarm_sensor.sensor->state)) {
ESP_LOGW(TAG, "'%s' is faulted and will be automatically bypassed", alarm_sensor.sensor->get_name().c_str());
this->bypassed_sensor_indicies_.push_back(alarm_sensor.info.store_index);
if ((info.flags & BINARY_SENSOR_MODE_BYPASS_AUTO) && (sensor->state)) {
ESP_LOGW(TAG, "'%s' is faulted and will be automatically bypassed", sensor->get_name().c_str());
this->bypassed_sensor_indicies_.push_back(info.store_index);
}
}
#endif

View File

@@ -1,12 +1,11 @@
#pragma once
#include <cinttypes>
#include <vector>
#include <map>
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h"
#include "esphome/components/alarm_control_panel/alarm_control_panel.h"
@@ -50,13 +49,6 @@ struct SensorInfo {
uint8_t store_index;
};
#ifdef USE_BINARY_SENSOR
struct AlarmSensor {
binary_sensor::BinarySensor *sensor;
SensorInfo info;
};
#endif
class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControlPanel, public Component {
public:
TemplateAlarmControlPanel();
@@ -71,12 +63,6 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl
void bypass_before_arming();
#ifdef USE_BINARY_SENSOR
/** Initialize the sensors vector with the specified capacity.
*
* @param capacity The number of sensors to allocate space for.
*/
void init_sensors(size_t capacity) { this->sensors_.init(capacity); }
/** Add a binary_sensor to the alarm_panel.
*
* @param sensor The BinarySensor instance.
@@ -136,8 +122,8 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl
protected:
void control(const alarm_control_panel::AlarmControlPanelCall &call) override;
#ifdef USE_BINARY_SENSOR
// List of binary sensors with their alarm-specific info
FixedVector<AlarmSensor> sensors_;
// This maps a binary sensor to its alarm specific info
std::map<binary_sensor::BinarySensor *, SensorInfo> sensor_map_;
// a list of automatically bypassed sensors
std::vector<uint8_t> bypassed_sensor_indicies_;
#endif

View File

@@ -945,10 +945,6 @@ async def to_code(config):
cg.add(var.set_humidity_hysteresis(config[CONF_HUMIDITY_HYSTERESIS]))
if CONF_PRESET in config:
# Separate standard and custom presets, and build preset config variables
standard_presets: list[tuple[cg.MockObj, cg.MockObj]] = []
custom_presets: list[tuple[str, cg.MockObj]] = []
for preset_config in config[CONF_PRESET]:
name = preset_config[CONF_NAME]
standard_preset = None
@@ -991,39 +987,9 @@ async def to_code(config):
)
if standard_preset is not None:
standard_presets.append((standard_preset, preset_target_variable))
cg.add(var.set_preset_config(standard_preset, preset_target_variable))
else:
custom_presets.append((name, preset_target_variable))
# Build initializer list for standard presets
if standard_presets:
cg.add(
var.set_preset_config(
[
cg.StructInitializer(
thermostat_ns.struct("ThermostatPresetEntry"),
("preset", preset),
("config", preset_var),
)
for preset, preset_var in standard_presets
]
)
)
# Build initializer list for custom presets
if custom_presets:
cg.add(
var.set_custom_preset_config(
[
cg.StructInitializer(
thermostat_ns.struct("ThermostatCustomPresetEntry"),
("name", cg.RawExpression(f'"{name}"')),
("config", preset_var),
)
for name, preset_var in custom_presets
]
)
)
cg.add(var.set_custom_preset_config(name, preset_target_variable))
if CONF_DEFAULT_PRESET in config:
default_preset_name = config[CONF_DEFAULT_PRESET]

View File

@@ -53,8 +53,8 @@ void ThermostatClimate::setup() {
if (use_default_preset) {
if (this->default_preset_ != climate::ClimatePreset::CLIMATE_PRESET_NONE) {
this->change_preset_(this->default_preset_);
} else if (this->default_custom_preset_ != nullptr) {
this->change_custom_preset_(this->default_custom_preset_);
} else if (!this->default_custom_preset_.empty()) {
this->change_custom_preset_(this->default_custom_preset_.c_str());
}
}
@@ -319,16 +319,16 @@ climate::ClimateTraits ThermostatClimate::traits() {
if (this->supports_swing_mode_vertical_)
traits.add_supported_swing_mode(climate::CLIMATE_SWING_VERTICAL);
for (const auto &entry : this->preset_config_) {
traits.add_supported_preset(entry.preset);
for (auto &it : this->preset_config_) {
traits.add_supported_preset(it.first);
}
// Extract custom preset names from the custom_preset_config_ vector
// Extract custom preset names from the custom_preset_config_ map
if (!this->custom_preset_config_.empty()) {
std::vector<const char *> custom_preset_names;
custom_preset_names.reserve(this->custom_preset_config_.size());
for (const auto &entry : this->custom_preset_config_) {
custom_preset_names.push_back(entry.name);
for (const auto &it : this->custom_preset_config_) {
custom_preset_names.push_back(it.first.c_str());
}
traits.set_supported_custom_presets(custom_preset_names);
}
@@ -1154,18 +1154,12 @@ void ThermostatClimate::dump_preset_config_(const char *preset_name, const Therm
}
void ThermostatClimate::change_preset_(climate::ClimatePreset preset) {
// Linear search through preset configurations
const ThermostatClimateTargetTempConfig *config = nullptr;
for (const auto &entry : this->preset_config_) {
if (entry.preset == preset) {
config = &entry.config;
break;
}
}
auto config = this->preset_config_.find(preset);
if (config != nullptr) {
if (config != this->preset_config_.end()) {
ESP_LOGV(TAG, "Preset %s requested", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
if (this->change_preset_internal_(*config) || (!this->preset.has_value()) || this->preset.value() != preset) {
if (this->change_preset_internal_(config->second) || (!this->preset.has_value()) ||
this->preset.value() != preset) {
// Fire any preset changed trigger if defined
Trigger<> *trig = this->preset_change_trigger_;
this->set_preset_(preset);
@@ -1184,18 +1178,11 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) {
}
void ThermostatClimate::change_custom_preset_(const char *custom_preset) {
// Linear search through custom preset configurations
const ThermostatClimateTargetTempConfig *config = nullptr;
for (const auto &entry : this->custom_preset_config_) {
if (strcmp(entry.name, custom_preset) == 0) {
config = &entry.config;
break;
}
}
auto config = this->custom_preset_config_.find(custom_preset);
if (config != nullptr) {
if (config != this->custom_preset_config_.end()) {
ESP_LOGV(TAG, "Custom preset %s requested", custom_preset);
if (this->change_preset_internal_(*config) || !this->has_custom_preset() ||
if (this->change_preset_internal_(config->second) || !this->has_custom_preset() ||
strcmp(this->get_custom_preset(), custom_preset) != 0) {
// Fire any preset changed trigger if defined
Trigger<> *trig = this->preset_change_trigger_;
@@ -1260,12 +1247,14 @@ bool ThermostatClimate::change_preset_internal_(const ThermostatClimateTargetTem
return something_changed;
}
void ThermostatClimate::set_preset_config(std::initializer_list<PresetEntry> presets) {
this->preset_config_ = presets;
void ThermostatClimate::set_preset_config(climate::ClimatePreset preset,
const ThermostatClimateTargetTempConfig &config) {
this->preset_config_[preset] = config;
}
void ThermostatClimate::set_custom_preset_config(std::initializer_list<CustomPresetEntry> presets) {
this->custom_preset_config_ = presets;
void ThermostatClimate::set_custom_preset_config(const std::string &name,
const ThermostatClimateTargetTempConfig &config) {
this->custom_preset_config_[name] = config;
}
ThermostatClimate::ThermostatClimate()
@@ -1304,16 +1293,8 @@ ThermostatClimate::ThermostatClimate()
humidity_control_humidify_action_trigger_(new Trigger<>()),
humidity_control_off_action_trigger_(new Trigger<>()) {}
void ThermostatClimate::set_default_preset(const char *custom_preset) {
// Find the preset in custom_preset_config_ and store pointer from there
for (const auto &entry : this->custom_preset_config_) {
if (strcmp(entry.name, custom_preset) == 0) {
this->default_custom_preset_ = entry.name;
return;
}
}
// If not found, it will be caught during validation
this->default_custom_preset_ = nullptr;
void ThermostatClimate::set_default_preset(const std::string &custom_preset) {
this->default_custom_preset_ = custom_preset;
}
void ThermostatClimate::set_default_preset(climate::ClimatePreset preset) { this->default_preset_ = preset; }
@@ -1624,22 +1605,19 @@ void ThermostatClimate::dump_config() {
if (!this->preset_config_.empty()) {
ESP_LOGCONFIG(TAG, " Supported PRESETS:");
for (const auto &entry : this->preset_config_) {
const auto *preset_name = LOG_STR_ARG(climate::climate_preset_to_string(entry.preset));
ESP_LOGCONFIG(TAG, " %s:%s", preset_name, entry.preset == this->default_preset_ ? " (default)" : "");
this->dump_preset_config_(preset_name, entry.config);
for (auto &it : this->preset_config_) {
const auto *preset_name = LOG_STR_ARG(climate::climate_preset_to_string(it.first));
ESP_LOGCONFIG(TAG, " %s:%s", preset_name, it.first == this->default_preset_ ? " (default)" : "");
this->dump_preset_config_(preset_name, it.second);
}
}
if (!this->custom_preset_config_.empty()) {
ESP_LOGCONFIG(TAG, " Supported CUSTOM PRESETS:");
for (const auto &entry : this->custom_preset_config_) {
const auto *preset_name = entry.name;
ESP_LOGCONFIG(TAG, " %s:%s", preset_name,
(this->default_custom_preset_ != nullptr && strcmp(entry.name, this->default_custom_preset_) == 0)
? " (default)"
: "");
this->dump_preset_config_(preset_name, entry.config);
for (auto &it : this->custom_preset_config_) {
const auto *preset_name = it.first.c_str();
ESP_LOGCONFIG(TAG, " %s:%s", preset_name, it.first == this->default_custom_preset_ ? " (default)" : "");
this->dump_preset_config_(preset_name, it.second);
}
}
}

View File

@@ -3,12 +3,12 @@
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/components/climate/climate.h"
#include "esphome/components/sensor/sensor.h"
#include <array>
#include <cinttypes>
#include <map>
namespace esphome {
namespace thermostat {
@@ -72,29 +72,14 @@ struct ThermostatClimateTargetTempConfig {
optional<climate::ClimateMode> mode_{};
};
/// Entry for standard preset lookup
struct ThermostatPresetEntry {
climate::ClimatePreset preset;
ThermostatClimateTargetTempConfig config;
};
/// Entry for custom preset lookup
struct ThermostatCustomPresetEntry {
const char *name;
ThermostatClimateTargetTempConfig config;
};
class ThermostatClimate : public climate::Climate, public Component {
public:
using PresetEntry = ThermostatPresetEntry;
using CustomPresetEntry = ThermostatCustomPresetEntry;
ThermostatClimate();
void setup() override;
void dump_config() override;
void loop() override;
void set_default_preset(const char *custom_preset);
void set_default_preset(const std::string &custom_preset);
void set_default_preset(climate::ClimatePreset preset);
void set_on_boot_restore_from(OnBootRestoreFrom on_boot_restore_from);
void set_set_point_minimum_differential(float differential);
@@ -146,8 +131,8 @@ class ThermostatClimate : public climate::Climate, public Component {
void set_supports_humidification(bool supports_humidification);
void set_supports_two_points(bool supports_two_points);
void set_preset_config(std::initializer_list<PresetEntry> presets);
void set_custom_preset_config(std::initializer_list<CustomPresetEntry> presets);
void set_preset_config(climate::ClimatePreset preset, const ThermostatClimateTargetTempConfig &config);
void set_custom_preset_config(const std::string &name, const ThermostatClimateTargetTempConfig &config);
Trigger<> *get_cool_action_trigger() const;
Trigger<> *get_supplemental_cool_action_trigger() const;
@@ -531,6 +516,9 @@ class ThermostatClimate : public climate::Climate, public Component {
Trigger<> *prev_swing_mode_trigger_{nullptr};
Trigger<> *prev_humidity_control_trigger_{nullptr};
/// Default custom preset to use on start up
std::string default_custom_preset_{};
/// Climate action timers
std::array<ThermostatClimateTimer, THERMOSTAT_TIMER_COUNT> timer_{
ThermostatClimateTimer(false, 0, 0, std::bind(&ThermostatClimate::cooling_max_run_time_timer_callback_, this)),
@@ -546,12 +534,9 @@ class ThermostatClimate : public climate::Climate, public Component {
};
/// The set of standard preset configurations this thermostat supports (Eg. AWAY, ECO, etc)
FixedVector<PresetEntry> preset_config_{};
std::map<climate::ClimatePreset, ThermostatClimateTargetTempConfig> preset_config_{};
/// The set of custom preset configurations this thermostat supports (eg. "My Custom Preset")
FixedVector<CustomPresetEntry> custom_preset_config_{};
/// Default custom preset to use on start up (pointer to entry in custom_preset_config_)
private:
const char *default_custom_preset_{nullptr};
std::map<std::string, ThermostatClimateTargetTempConfig> custom_preset_config_{};
};
} // namespace thermostat

View File

@@ -1,4 +1,3 @@
from logging import getLogger
import math
import re
@@ -36,8 +35,6 @@ from esphome.core import CORE, ID
import esphome.final_validate as fv
from esphome.yaml_util import make_data_base
_LOGGER = getLogger(__name__)
CODEOWNERS = ["@esphome/core"]
uart_ns = cg.esphome_ns.namespace("uart")
UARTComponent = uart_ns.class_("UARTComponent")
@@ -133,21 +130,6 @@ def validate_host_config(config):
return config
def validate_rx_buffer_size(config):
if CORE.is_esp32:
# ESP32 UART hardware FIFO is 128 bytes (LP UART is 16 bytes, but we use 128 as safe minimum)
# rx_buffer_size must be greater than the hardware FIFO length
min_buffer_size = 128
if config[CONF_RX_BUFFER_SIZE] <= min_buffer_size:
_LOGGER.warning(
"UART rx_buffer_size (%d bytes) is too small and must be greater than the hardware "
"FIFO size (%d bytes). The buffer size will be automatically adjusted at runtime.",
config[CONF_RX_BUFFER_SIZE],
min_buffer_size,
)
return config
def _uart_declare_type(value):
if CORE.is_esp8266:
return cv.declare_id(ESP8266UartComponent)(value)
@@ -265,7 +247,6 @@ CONFIG_SCHEMA = cv.All(
).extend(cv.COMPONENT_SCHEMA),
cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT),
validate_host_config,
validate_rx_buffer_size,
)

View File

@@ -91,16 +91,6 @@ void IDFUARTComponent::setup() {
this->uart_num_ = static_cast<uart_port_t>(next_uart_num++);
this->lock_ = xSemaphoreCreateMutex();
#if (SOC_UART_LP_NUM >= 1)
size_t fifo_len = ((this->uart_num_ < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN);
#else
size_t fifo_len = SOC_UART_FIFO_LEN;
#endif
if (this->rx_buffer_size_ <= fifo_len) {
ESP_LOGW(TAG, "rx_buffer_size is too small, must be greater than %zu", fifo_len);
this->rx_buffer_size_ = fifo_len * 2;
}
xSemaphoreTake(this->lock_, portMAX_DELAY);
this->load_settings(false);
@@ -247,12 +237,8 @@ void IDFUARTComponent::set_rx_timeout(size_t rx_timeout) {
void IDFUARTComponent::write_array(const uint8_t *data, size_t len) {
xSemaphoreTake(this->lock_, portMAX_DELAY);
int32_t write_len = uart_write_bytes(this->uart_num_, data, len);
uart_write_bytes(this->uart_num_, data, len);
xSemaphoreGive(this->lock_);
if (write_len != (int32_t) len) {
ESP_LOGW(TAG, "uart_write_bytes failed: %d != %zu", write_len, len);
this->mark_failed();
}
#ifdef USE_UART_DEBUGGER
for (size_t i = 0; i < len; i++) {
this->debug_callback_.call(UART_DIRECTION_TX, data[i]);
@@ -281,7 +267,6 @@ bool IDFUARTComponent::peek_byte(uint8_t *data) {
bool IDFUARTComponent::read_array(uint8_t *data, size_t len) {
size_t length_to_read = len;
int32_t read_len = 0;
if (!this->check_read_timeout_(len))
return false;
xSemaphoreTake(this->lock_, portMAX_DELAY);
@@ -292,31 +277,25 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) {
this->has_peek_ = false;
}
if (length_to_read > 0)
read_len = uart_read_bytes(this->uart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS);
uart_read_bytes(this->uart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS);
xSemaphoreGive(this->lock_);
#ifdef USE_UART_DEBUGGER
for (size_t i = 0; i < len; i++) {
this->debug_callback_.call(UART_DIRECTION_RX, data[i]);
}
#endif
return read_len == (int32_t) length_to_read;
return true;
}
int IDFUARTComponent::available() {
size_t available = 0;
esp_err_t err;
size_t available;
xSemaphoreTake(this->lock_, portMAX_DELAY);
err = uart_get_buffered_data_len(this->uart_num_, &available);
uart_get_buffered_data_len(this->uart_num_, &available);
if (this->has_peek_)
available++;
xSemaphoreGive(this->lock_);
if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_get_buffered_data_len failed: %s", esp_err_to_name(err));
this->mark_failed();
}
if (this->has_peek_) {
available++;
}
return available;
}

View File

@@ -1,69 +1,17 @@
import logging
import esphome.codegen as cg
from esphome.components.esp32 import add_idf_component
from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code
from esphome.config_helpers import merge_config
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_OTA, CONF_PLATFORM
from esphome.const import CONF_ID
from esphome.core import CORE, coroutine_with_priority
from esphome.coroutine import CoroPriority
import esphome.final_validate as fv
from esphome.types import ConfigType
_LOGGER = logging.getLogger(__name__)
CODEOWNERS = ["@esphome/core"]
DEPENDENCIES = ["network", "web_server_base"]
CONF_WEB_SERVER = "web_server"
web_server_ns = cg.esphome_ns.namespace("web_server")
WebServerOTAComponent = web_server_ns.class_("WebServerOTAComponent", OTAComponent)
def _web_server_ota_final_validate(config: ConfigType) -> None:
"""Merge multiple web_server OTA instances into one.
Multiple web_server OTA instances register duplicate HTTP handlers for /update,
causing undefined behavior. Merge them into a single instance.
"""
full_conf = fv.full_config.get()
ota_confs = full_conf.get(CONF_OTA, [])
web_server_ota_configs: list[ConfigType] = []
other_ota_configs: list[ConfigType] = []
for ota_conf in ota_confs:
if ota_conf.get(CONF_PLATFORM) == CONF_WEB_SERVER:
web_server_ota_configs.append(ota_conf)
else:
other_ota_configs.append(ota_conf)
if len(web_server_ota_configs) <= 1:
return
# Merge all web_server OTA configs into the first one
merged = web_server_ota_configs[0]
for ota_conf in web_server_ota_configs[1:]:
# Validate that IDs are consistent if manually specified
if merged[CONF_ID].is_manual and ota_conf[CONF_ID].is_manual:
raise cv.Invalid(
f"Found multiple web_server OTA configurations but {CONF_ID} is inconsistent"
)
merged = merge_config(merged, ota_conf)
_LOGGER.warning(
"Found and merged %d web_server OTA configurations into one instance",
len(web_server_ota_configs),
)
# Replace OTA configs with merged web_server + other OTA platforms
other_ota_configs.append(merged)
full_conf[CONF_OTA] = other_ota_configs
fv.full_config.set(full_conf)
CONFIG_SCHEMA = (
cv.Schema(
{
@@ -74,8 +22,6 @@ CONFIG_SCHEMA = (
.extend(cv.COMPONENT_SCHEMA)
)
FINAL_VALIDATE_SCHEMA = _web_server_ota_final_validate
@coroutine_with_priority(CoroPriority.WEB_SERVER_OTA)
async def to_code(config):

View File

@@ -5,13 +5,10 @@ from esphome.automation import Condition
import esphome.codegen as cg
from esphome.components.const import CONF_USE_PSRAM
from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant
from esphome.components.network import (
has_high_performance_networking,
ip_address_literal,
)
from esphome.components.psram import is_guaranteed as psram_is_guaranteed
from esphome.components.network import ip_address_literal
from esphome.config_helpers import filter_source_files_from_platform
import esphome.config_validation as cv
from esphome.config_validation import only_with_esp_idf
from esphome.const import (
CONF_AP,
CONF_BSSID,
@@ -59,8 +56,6 @@ _LOGGER = logging.getLogger(__name__)
AUTO_LOAD = ["network"]
_LOGGER = logging.getLogger(__name__)
NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4]
CONF_SAVE = "save"
CONF_MIN_AUTH_MODE = "min_auth_mode"
@@ -351,7 +346,7 @@ CONFIG_SCHEMA = cv.All(
single=True
),
cv.Optional(CONF_USE_PSRAM): cv.All(
cv.only_on_esp32, cv.requires_component("psram"), cv.boolean
only_with_esp_idf, cv.requires_component("psram"), cv.boolean
),
}
),
@@ -501,56 +496,6 @@ async def to_code(config):
if config.get(CONF_USE_PSRAM):
add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True)
# Apply high performance WiFi settings if high performance networking is enabled
if CORE.is_esp32 and CORE.using_esp_idf and has_high_performance_networking():
# Check if PSRAM is guaranteed (set by psram component during final validation)
psram_guaranteed = psram_is_guaranteed()
# Always allocate WiFi buffers in PSRAM if available
add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True)
if psram_guaranteed:
_LOGGER.info(
"Applying high-performance WiFi settings (PSRAM guaranteed): 512 RX buffers, 32 TX buffers"
)
# PSRAM is guaranteed - use aggressive settings
# Higher maximum values are allowed because CONFIG_LWIP_WND_SCALE is set to true in networking component
# Based on https://github.com/espressif/esp-adf/issues/297#issuecomment-783811702
# Large dynamic RX buffers (requires PSRAM)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM", 16)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM", 512)
# Static TX buffers for better performance
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_STATIC_TX_BUFFER", True)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_TX_BUFFER_TYPE", 0)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM", 32)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM", 8)
# AMPDU settings optimized for PSRAM
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_AMPDU_TX_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_TX_BA_WIN", 16)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_AMPDU_RX_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_RX_BA_WIN", 32)
else:
_LOGGER.info(
"Applying optimized WiFi settings: 64 RX buffers, 64 TX buffers"
)
# PSRAM not guaranteed - use more conservative, but still optimized settings
# Based on https://github.com/espressif/esp-idf/blob/release/v5.4/examples/wifi/iperf/sdkconfig.defaults.esp32
# Standard buffer counts
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM", 16)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM", 64)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM", 64)
# Standard AMPDU settings
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_AMPDU_TX_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_TX_BA_WIN", 32)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_AMPDU_RX_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_RX_BA_WIN", 32)
cg.add_define("USE_WIFI")
# must register before OTA safe mode check

View File

@@ -197,10 +197,6 @@ static constexpr uint8_t WIFI_RETRY_COUNT_PER_SSID = 1;
// Rationale: Fast connect prioritizes speed - try each AP once to find a working one quickly
static constexpr uint8_t WIFI_RETRY_COUNT_PER_AP = 1;
/// Cooldown duration in milliseconds after adapter restart or repeated failures
/// Allows WiFi hardware to stabilize before next connection attempt
static constexpr uint32_t WIFI_COOLDOWN_DURATION_MS = 1000;
static constexpr uint8_t get_max_retries_for_phase(WiFiRetryPhase phase) {
switch (phase) {
case WiFiRetryPhase::INITIAL_CONNECT:
@@ -279,7 +275,7 @@ int8_t WiFiComponent::find_next_hidden_sta_(int8_t start_index) {
ESP_LOGD(TAG, "Hidden candidate " LOG_SECRET("'%s'") " at index %d", sta.get_ssid().c_str(), static_cast<int>(i));
return static_cast<int8_t>(i);
}
ESP_LOGD(TAG, "Skipping hidden retry for visible network " LOG_SECRET("'%s'"), sta.get_ssid().c_str());
ESP_LOGD(TAG, "Skipping " LOG_SECRET("'%s'") " (visible in scan)", sta.get_ssid().c_str());
}
// No hidden SSIDs found
return -1;
@@ -293,7 +289,7 @@ void WiFiComponent::start_initial_connection_() {
this->selected_sta_index_ = 0;
this->retry_phase_ = WiFiRetryPhase::EXPLICIT_HIDDEN;
WiFiAP params = this->build_params_for_current_phase_();
this->start_connecting(params);
this->start_connecting(params, false);
} else {
ESP_LOGI(TAG, "Starting scan");
this->start_scanning();
@@ -375,13 +371,13 @@ void WiFiComponent::start() {
// Without saved data, try first configured network or use normal flow
if (loaded_fast_connect) {
ESP_LOGI(TAG, "Starting fast_connect (saved) " LOG_SECRET("'%s'"), params.get_ssid().c_str());
this->start_connecting(params);
this->start_connecting(params, false);
} else if (!this->sta_.empty() && !this->sta_[0].get_hidden()) {
// No saved data, but have configured networks - try first non-hidden network
ESP_LOGI(TAG, "Starting fast_connect (config) " LOG_SECRET("'%s'"), this->sta_[0].get_ssid().c_str());
this->selected_sta_index_ = 0;
params = this->build_params_for_current_phase_();
this->start_connecting(params);
this->start_connecting(params, false);
} else {
// No saved data and (no networks OR first is hidden) - use normal flow
this->start_initial_connection_();
@@ -421,7 +417,6 @@ void WiFiComponent::restart_adapter() {
// Don't set retry_phase_ or num_retried_ here - state machine handles transitions
this->state_ = WIFI_COMPONENT_STATE_COOLDOWN;
this->action_started_ = millis();
this->error_from_callback_ = false;
}
void WiFiComponent::loop() {
@@ -441,7 +436,7 @@ void WiFiComponent::loop() {
switch (this->state_) {
case WIFI_COMPONENT_STATE_COOLDOWN: {
this->status_set_warning(LOG_STR("waiting to reconnect"));
if (now - this->action_started_ > WIFI_COOLDOWN_DURATION_MS) {
if (millis() - this->action_started_ > 5000) {
// After cooldown we either restarted the adapter because of
// a failure, or something tried to connect over and over
// so we entered cooldown. In both cases we call
@@ -455,7 +450,8 @@ void WiFiComponent::loop() {
this->check_scanning_finished();
break;
}
case WIFI_COMPONENT_STATE_STA_CONNECTING: {
case WIFI_COMPONENT_STATE_STA_CONNECTING:
case WIFI_COMPONENT_STATE_STA_CONNECTING_2: {
this->status_set_warning(LOG_STR("associating to network"));
this->check_connecting_finished();
break;
@@ -465,8 +461,6 @@ void WiFiComponent::loop() {
if (!this->is_connected()) {
ESP_LOGW(TAG, "Connection lost; reconnecting");
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING;
// Clear error flag before reconnecting so first attempt is not seen as immediate failure
this->error_from_callback_ = false;
this->retry_connect();
} else {
this->status_clear_warning();
@@ -668,27 +662,27 @@ void WiFiComponent::save_wifi_sta(const std::string &ssid, const std::string &pa
this->set_sta(sta);
}
void WiFiComponent::start_connecting(const WiFiAP &ap) {
void WiFiComponent::start_connecting(const WiFiAP &ap, bool two) {
// Log connection attempt at INFO level with priority
char bssid_s[18];
std::string bssid_formatted;
int8_t priority = 0;
if (ap.get_bssid().has_value()) {
format_mac_addr_upper(ap.get_bssid().value().data(), bssid_s);
bssid_formatted = format_mac_address_pretty(ap.get_bssid().value().data());
priority = this->get_sta_priority(ap.get_bssid().value());
}
ESP_LOGI(TAG,
"Connecting to " LOG_SECRET("'%s'") " " LOG_SECRET("(%s)") " (priority %d, attempt %u/%u in phase %s)...",
ap.get_ssid().c_str(), ap.get_bssid().has_value() ? bssid_s : LOG_STR_LITERAL("any"), priority,
this->num_retried_ + 1, get_max_retries_for_phase(this->retry_phase_),
ap.get_ssid().c_str(), ap.get_bssid().has_value() ? bssid_formatted.c_str() : LOG_STR_LITERAL("any"),
priority, this->num_retried_ + 1, get_max_retries_for_phase(this->retry_phase_),
LOG_STR_ARG(retry_phase_to_log_string(this->retry_phase_)));
#ifdef ESPHOME_LOG_HAS_VERBOSE
ESP_LOGV(TAG, "Connection Params:");
ESP_LOGV(TAG, " SSID: '%s'", ap.get_ssid().c_str());
if (ap.get_bssid().has_value()) {
ESP_LOGV(TAG, " BSSID: %s", bssid_s);
ESP_LOGV(TAG, " BSSID: %s", format_mac_address_pretty(ap.get_bssid()->data()).c_str());
} else {
ESP_LOGV(TAG, " BSSID: Not Set");
}
@@ -735,24 +729,19 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) {
if (!this->wifi_sta_connect_(ap)) {
ESP_LOGE(TAG, "wifi_sta_connect_ failed");
// Enter cooldown to allow WiFi hardware to stabilize
// (immediate failure suggests hardware not ready, different from connection timeout)
this->state_ = WIFI_COMPONENT_STATE_COOLDOWN;
} else {
this->retry_connect();
return;
}
if (!two) {
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING;
} else {
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING_2;
}
this->action_started_ = millis();
}
const LogString *get_signal_bars(int8_t rssi) {
// Check for disconnected sentinel value first
if (rssi == WIFI_RSSI_DISCONNECTED) {
// MULTIPLICATION SIGN
// Unicode: U+00D7, UTF-8: C3 97
return LOG_STR("\033[0;31m" // red
"\xc3\x97\xc3\x97\xc3\x97\xc3\x97"
"\033[0m");
}
// LOWER ONE QUARTER BLOCK
// Unicode: U+2582, UTF-8: E2 96 82
// LOWER HALF BLOCK
@@ -797,8 +786,6 @@ const LogString *get_signal_bars(int8_t rssi) {
void WiFiComponent::print_connect_params_() {
bssid_t bssid = wifi_bssid();
char bssid_s[18];
format_mac_addr_upper(bssid.data(), bssid_s);
ESP_LOGCONFIG(TAG, " Local MAC: %s", get_mac_address_pretty().c_str());
if (this->is_disabled()) {
@@ -821,9 +808,9 @@ void WiFiComponent::print_connect_params_() {
" Gateway: %s\n"
" DNS1: %s\n"
" DNS2: %s",
wifi_ssid().c_str(), bssid_s, App.get_name().c_str(), rssi, LOG_STR_ARG(get_signal_bars(rssi)),
get_wifi_channel(), wifi_subnet_mask_().str().c_str(), wifi_gateway_ip_().str().c_str(),
wifi_dns_ip_(0).str().c_str(), wifi_dns_ip_(1).str().c_str());
wifi_ssid().c_str(), format_mac_address_pretty(bssid.data()).c_str(), App.get_name().c_str(), rssi,
LOG_STR_ARG(get_signal_bars(rssi)), get_wifi_channel(), wifi_subnet_mask_().str().c_str(),
wifi_gateway_ip_().str().c_str(), wifi_dns_ip_(0).str().c_str(), wifi_dns_ip_(1).str().c_str());
#ifdef ESPHOME_LOG_HAS_VERBOSE
if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_bssid().has_value()) {
ESP_LOGV(TAG, " Priority: %d", this->get_sta_priority(*config->get_bssid()));
@@ -1030,14 +1017,11 @@ void WiFiComponent::check_scanning_finished() {
WiFiAP params = this->build_params_for_current_phase_();
// Ensure we're in SCAN_CONNECTING phase when connecting with scan results
// (needed when scan was started directly without transition_to_phase_, e.g., initial scan)
this->start_connecting(params);
this->start_connecting(params, false);
}
void WiFiComponent::dump_config() {
ESP_LOGCONFIG(TAG,
"WiFi:\n"
" Connected: %s",
YESNO(this->is_connected()));
ESP_LOGCONFIG(TAG, "WiFi:");
this->print_connect_params_();
}
@@ -1062,10 +1046,6 @@ void WiFiComponent::check_connecting_finished() {
// Reset to initial phase on successful connection (don't log transition, just reset state)
this->retry_phase_ = WiFiRetryPhase::INITIAL_CONNECT;
this->num_retried_ = 0;
// Ensure next connection attempt does not inherit error state
// so when WiFi disconnects later we start fresh and don't see
// the first connection as a failure.
this->error_from_callback_ = false;
this->print_connect_params_();
@@ -1106,12 +1086,18 @@ void WiFiComponent::check_connecting_finished() {
uint32_t now = millis();
if (now - this->action_started_ > 30000) {
ESP_LOGW(TAG, "Connection timeout");
// Move from STA_CONNECTING_2 back to STA_CONNECTING state
// since we know the connection attempt has failed
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING;
this->retry_connect();
return;
}
if (this->error_from_callback_) {
ESP_LOGW(TAG, "Connecting to network failed (callback)");
// Move from STA_CONNECTING_2 back to STA_CONNECTING state
// since we know the connection attempt is finished
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING;
this->retry_connect();
return;
}
@@ -1120,6 +1106,9 @@ void WiFiComponent::check_connecting_finished() {
return;
}
// Move from STA_CONNECTING_2 back to STA_CONNECTING state
// since we know the connection attempt is finished
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING;
if (status == WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND) {
ESP_LOGW(TAG, "Network no longer found");
this->retry_connect();
@@ -1152,11 +1141,6 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() {
return WiFiRetryPhase::FAST_CONNECT_CYCLING_APS; // Move to next AP
}
#endif
// Check if we should try explicit hidden networks before scanning
// This handles reconnection after connection loss where first network is hidden
if (!this->sta_.empty() && this->sta_[0].get_hidden()) {
return WiFiRetryPhase::EXPLICIT_HIDDEN;
}
// No more APs to try, fall back to scan
return WiFiRetryPhase::SCAN_CONNECTING;
@@ -1415,10 +1399,8 @@ void WiFiComponent::log_and_adjust_priority_for_failed_connect_() {
this->set_sta_priority(failed_bssid.value(), new_priority);
}
char bssid_s[18];
format_mac_addr_upper(failed_bssid.value().data(), bssid_s);
ESP_LOGD(TAG, "Failed " LOG_SECRET("'%s'") " " LOG_SECRET("(%s)") ", priority %d → %d", ssid.c_str(), bssid_s,
old_priority, new_priority);
ESP_LOGD(TAG, "Failed " LOG_SECRET("'%s'") " " LOG_SECRET("(%s)") ", priority %d → %d", ssid.c_str(),
format_mac_address_pretty(failed_bssid.value().data()).c_str(), old_priority, new_priority);
// After adjusting priority, check if all priorities are now at minimum
// If so, clear the vector to save memory and reset for fresh start
@@ -1510,14 +1492,27 @@ void WiFiComponent::retry_connect() {
this->error_from_callback_ = false;
yield();
// Check if we have a valid target before building params
// After exhausting all networks in a phase, selected_sta_index_ may be -1
// In that case, skip connection and let next wifi_loop() handle phase transition
if (this->selected_sta_index_ >= 0) {
WiFiAP params = this->build_params_for_current_phase_();
this->start_connecting(params);
if (this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING) {
yield();
// Check if we have a valid target before building params
// After exhausting all networks in a phase, selected_sta_index_ may be -1
// In that case, skip connection and let next wifi_loop() handle phase transition
if (this->selected_sta_index_ >= 0) {
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING_2;
WiFiAP params = this->build_params_for_current_phase_();
this->start_connecting(params, true);
}
return;
}
// If we can't progress forward its likely because scanning failed
// or the stack is in a bad state after restart so we cooldown first
// and once it finishes, cooldown will call check_connecting_finished()
// which will progress the state machine
ESP_LOGD(TAG, "Entering cooldown from state %d and phase %s", this->state_,
LOG_STR_ARG(retry_phase_to_log_string(this->retry_phase_)));
this->state_ = WIFI_COMPONENT_STATE_COOLDOWN;
this->action_started_ = millis();
}
void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }

View File

@@ -52,9 +52,6 @@ extern "C" {
namespace esphome {
namespace wifi {
/// Sentinel value for RSSI when WiFi is not connected
static constexpr int8_t WIFI_RSSI_DISCONNECTED = -127;
struct SavedWifiSettings {
char ssid[33];
char password[65];
@@ -77,6 +74,12 @@ enum WiFiComponentState : uint8_t {
WIFI_COMPONENT_STATE_STA_SCANNING,
/** WiFi is in STA(+AP) mode and currently connecting to an AP. */
WIFI_COMPONENT_STATE_STA_CONNECTING,
/** WiFi is in STA(+AP) mode and currently connecting to an AP a second time.
*
* This is required because for some reason ESPs don't like to connect to WiFi APs directly after
* a scan.
* */
WIFI_COMPONENT_STATE_STA_CONNECTING_2,
/** WiFi is in STA(+AP) mode and successfully connected. */
WIFI_COMPONENT_STATE_STA_CONNECTED,
/** WiFi is in AP-only mode and internal AP is already enabled. */
@@ -272,9 +275,7 @@ class WiFiComponent : public Component {
bool is_disabled();
void start_scanning();
void check_scanning_finished();
void start_connecting(const WiFiAP &ap);
// Backward compatibility overload - ignores 'two' parameter
void start_connecting(const WiFiAP &ap, bool /* two */) { this->start_connecting(ap); }
void start_connecting(const WiFiAP &ap, bool two);
void check_connecting_finished();
@@ -429,7 +430,7 @@ class WiFiComponent : public Component {
bool wifi_sta_pre_setup_();
bool wifi_apply_output_power_(float output_power);
bool wifi_apply_power_save_();
bool wifi_sta_ip_config_(const optional<ManualIP> &manual_ip);
bool wifi_sta_ip_config_(optional<ManualIP> manual_ip);
bool wifi_apply_hostname_();
bool wifi_sta_connect_(const WiFiAP &ap);
void wifi_pre_setup_();
@@ -437,7 +438,7 @@ class WiFiComponent : public Component {
bool wifi_scan_start_(bool passive);
#ifdef USE_WIFI_AP
bool wifi_ap_ip_config_(const optional<ManualIP> &manual_ip);
bool wifi_ap_ip_config_(optional<ManualIP> manual_ip);
bool wifi_start_ap_(const WiFiAP &ap);
#endif // USE_WIFI_AP

View File

@@ -117,7 +117,7 @@ void netif_set_addr(struct netif *netif, const ip4_addr_t *ip, const ip4_addr_t
};
#endif
bool WiFiComponent::wifi_sta_ip_config_(const optional<ManualIP> &manual_ip) {
bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
// enable STA
if (!this->wifi_mode_(true, {}))
return false;
@@ -525,10 +525,8 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
ESP_LOGW(TAG, "Disconnected ssid='%s' reason='Probe Request Unsuccessful'", buf);
s_sta_connect_not_found = true;
} else {
char bssid_s[18];
format_mac_addr_upper(it.bssid, bssid_s);
ESP_LOGW(TAG, "Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf, bssid_s,
LOG_STR_ARG(get_disconnect_reason_str(it.reason)));
ESP_LOGW(TAG, "Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf,
format_mac_address_pretty(it.bssid).c_str(), LOG_STR_ARG(get_disconnect_reason_str(it.reason)));
s_sta_connect_error = true;
}
s_sta_connected = false;
@@ -732,7 +730,7 @@ void WiFiComponent::wifi_scan_done_callback_(void *arg, STATUS status) {
}
#ifdef USE_WIFI_AP
bool WiFiComponent::wifi_ap_ip_config_(const optional<ManualIP> &manual_ip) {
bool WiFiComponent::wifi_ap_ip_config_(optional<ManualIP> manual_ip) {
// enable AP
if (!this->wifi_mode_({}, true))
return false;
@@ -872,7 +870,7 @@ bssid_t WiFiComponent::wifi_bssid() {
return bssid;
}
std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); }
int8_t WiFiComponent::wifi_rssi() { return WiFi.status() == WL_CONNECTED ? WiFi.RSSI() : WIFI_RSSI_DISCONNECTED; }
int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); }
int32_t WiFiComponent::get_wifi_channel() { return WiFi.channel(); }
network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {(const ip_addr_t *) WiFi.subnetMask()}; }
network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {(const ip_addr_t *) WiFi.gatewayIP()}; }

View File

@@ -487,7 +487,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
return true;
}
bool WiFiComponent::wifi_sta_ip_config_(const optional<ManualIP> &manual_ip) {
bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
// enable STA
if (!this->wifi_mode_(true, {}))
return false;
@@ -746,10 +746,8 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) {
ESP_LOGI(TAG, "Disconnected ssid='%s' reason='Station Roaming'", buf);
return;
} else {
char bssid_s[18];
format_mac_addr_upper(it.bssid, bssid_s);
ESP_LOGW(TAG, "Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf, bssid_s,
get_disconnect_reason_str(it.reason));
ESP_LOGW(TAG, "Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf,
format_mac_address_pretty(it.bssid).c_str(), get_disconnect_reason_str(it.reason));
s_sta_connect_error = true;
}
s_sta_connected = false;
@@ -886,7 +884,7 @@ bool WiFiComponent::wifi_scan_start_(bool passive) {
}
#ifdef USE_WIFI_AP
bool WiFiComponent::wifi_ap_ip_config_(const optional<ManualIP> &manual_ip) {
bool WiFiComponent::wifi_ap_ip_config_(optional<ManualIP> manual_ip) {
esp_err_t err;
// enable AP
@@ -1031,8 +1029,7 @@ bssid_t WiFiComponent::wifi_bssid() {
wifi_ap_record_t info;
esp_err_t err = esp_wifi_sta_get_ap_info(&info);
if (err != ESP_OK) {
// Very verbose only: this is expected during dump_config() before connection is established (PR #9823)
ESP_LOGVV(TAG, "esp_wifi_sta_get_ap_info failed: %s", esp_err_to_name(err));
ESP_LOGW(TAG, "esp_wifi_sta_get_ap_info failed: %s", esp_err_to_name(err));
return bssid;
}
std::copy(info.bssid, info.bssid + 6, bssid.begin());
@@ -1042,8 +1039,7 @@ std::string WiFiComponent::wifi_ssid() {
wifi_ap_record_t info{};
esp_err_t err = esp_wifi_sta_get_ap_info(&info);
if (err != ESP_OK) {
// Very verbose only: this is expected during dump_config() before connection is established (PR #9823)
ESP_LOGVV(TAG, "esp_wifi_sta_get_ap_info failed: %s", esp_err_to_name(err));
ESP_LOGW(TAG, "esp_wifi_sta_get_ap_info failed: %s", esp_err_to_name(err));
return "";
}
auto *ssid_s = reinterpret_cast<const char *>(info.ssid);
@@ -1054,9 +1050,8 @@ int8_t WiFiComponent::wifi_rssi() {
wifi_ap_record_t info;
esp_err_t err = esp_wifi_sta_get_ap_info(&info);
if (err != ESP_OK) {
// Very verbose only: this is expected during dump_config() before connection is established (PR #9823)
ESP_LOGVV(TAG, "esp_wifi_sta_get_ap_info failed: %s", esp_err_to_name(err));
return WIFI_RSSI_DISCONNECTED;
ESP_LOGW(TAG, "esp_wifi_sta_get_ap_info failed: %s", esp_err_to_name(err));
return 0;
}
return info.rssi;
}

View File

@@ -68,7 +68,7 @@ bool WiFiComponent::wifi_sta_pre_setup_() {
return true;
}
bool WiFiComponent::wifi_apply_power_save_() { return WiFi.setSleep(this->power_save_ != WIFI_POWER_SAVE_NONE); }
bool WiFiComponent::wifi_sta_ip_config_(const optional<ManualIP> &manual_ip) {
bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
// enable STA
if (!this->wifi_mode_(true, {}))
return false;
@@ -299,10 +299,8 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
if (it.reason == WIFI_REASON_NO_AP_FOUND) {
ESP_LOGW(TAG, "Disconnected ssid='%s' reason='Probe Request Unsuccessful'", buf);
} else {
char bssid_s[18];
format_mac_addr_upper(it.bssid, bssid_s);
ESP_LOGW(TAG, "Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf, bssid_s,
get_disconnect_reason_str(it.reason));
ESP_LOGW(TAG, "Disconnected ssid='%s' bssid=" LOG_SECRET("%s") " reason='%s'", buf,
format_mac_address_pretty(it.bssid).c_str(), get_disconnect_reason_str(it.reason));
}
uint8_t reason = it.reason;
@@ -436,7 +434,7 @@ void WiFiComponent::wifi_scan_done_callback_() {
}
#ifdef USE_WIFI_AP
bool WiFiComponent::wifi_ap_ip_config_(const optional<ManualIP> &manual_ip) {
bool WiFiComponent::wifi_ap_ip_config_(optional<ManualIP> manual_ip) {
// enable AP
if (!this->wifi_mode_({}, true))
return false;
@@ -486,7 +484,7 @@ bssid_t WiFiComponent::wifi_bssid() {
return bssid;
}
std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); }
int8_t WiFiComponent::wifi_rssi() { return WiFi.status() == WL_CONNECTED ? WiFi.RSSI() : WIFI_RSSI_DISCONNECTED; }
int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); }
int32_t WiFiComponent::get_wifi_channel() { return WiFi.channel(); }
network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {WiFi.subnetMask()}; }
network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {WiFi.gatewayIP()}; }

View File

@@ -72,7 +72,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
bool WiFiComponent::wifi_sta_pre_setup_() { return this->wifi_mode_(true, {}); }
bool WiFiComponent::wifi_sta_ip_config_(const optional<ManualIP> &manual_ip) {
bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
if (!manual_ip.has_value()) {
return true;
}
@@ -146,7 +146,7 @@ bool WiFiComponent::wifi_scan_start_(bool passive) {
}
#ifdef USE_WIFI_AP
bool WiFiComponent::wifi_ap_ip_config_(const optional<ManualIP> &manual_ip) {
bool WiFiComponent::wifi_ap_ip_config_(optional<ManualIP> manual_ip) {
esphome::network::IPAddress ip_address, gateway, subnet, dns;
if (manual_ip.has_value()) {
ip_address = manual_ip->static_ip;
@@ -200,7 +200,7 @@ bssid_t WiFiComponent::wifi_bssid() {
return bssid;
}
std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); }
int8_t WiFiComponent::wifi_rssi() { return WiFi.status() == WL_CONNECTED ? WiFi.RSSI() : WIFI_RSSI_DISCONNECTED; }
int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); }
int32_t WiFiComponent::get_wifi_channel() { return WiFi.channel(); }
network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() {

View File

@@ -4,7 +4,7 @@ from enum import Enum
from esphome.enum import StrEnum
__version__ = "2025.12.0-dev"
__version__ = "2025.11.0-dev"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = (

View File

@@ -412,12 +412,7 @@ template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Co
void setup() override {
// Start with loop disabled - only enable when there's work to do
// IMPORTANT: Only disable if num_running_ is 0, otherwise play_complex() was already
// called before our setup() (e.g., from on_boot trigger at same priority level)
// and we must not undo its enable_loop() call
if (this->num_running_ == 0) {
this->disable_loop();
}
this->disable_loop();
}
void play_complex(const Ts &...x) override {

View File

@@ -94,10 +94,9 @@ class Scheduler {
} name_;
uint32_t interval;
// Split time to handle millis() rollover. The scheduler combines the 32-bit millis()
// with a 16-bit rollover counter to create a 48-bit time space (using 32+16 bits).
// This is intentionally limited to 48 bits, not stored as a full 64-bit value.
// With 49.7 days per 32-bit rollover, the 16-bit counter supports
// 49.7 days × 65536 = ~8900 years. This ensures correct scheduling
// with a 16-bit rollover counter to create a 48-bit time space (stored as 64-bit
// for compatibility). With 49.7 days per 32-bit rollover, the 16-bit counter
// supports 49.7 days × 65536 = ~8900 years. This ensures correct scheduling
// even when devices run for months. Split into two fields for better memory
// alignment on 32-bit systems.
uint32_t next_execution_low_; // Lower 32 bits of execution time (millis value)

View File

@@ -30,7 +30,6 @@ from esphome.const import (
from esphome.core import CORE, EsphomeError
from esphome.helpers import get_int_env, get_str_env
from esphome.log import AnsiFore, color
from esphome.types import ConfigType
from esphome.util import safe_print
_LOGGER = logging.getLogger(__name__)
@@ -155,12 +154,8 @@ def show_discover(config, username=None, password=None, client_id=None):
def get_esphome_device_ip(
config: ConfigType,
username: str | None = None,
password: str | None = None,
client_id: str | None = None,
timeout: int | float = 25,
) -> list[str]:
config, username=None, password=None, client_id=None, timeout=25
):
if CONF_MQTT not in config:
raise EsphomeError(
"Cannot discover IP via MQTT as the config does not include the mqtt: "
@@ -171,10 +166,6 @@ def get_esphome_device_ip(
"Cannot discover IP via MQTT as the config does not include the device name: "
"component"
)
if not config[CONF_MQTT].get(CONF_BROKER):
raise EsphomeError(
"Cannot discover IP via MQTT as the broker is not configured"
)
dev_name = config[CONF_ESPHOME][CONF_NAME]
dev_ip = None

View File

@@ -408,7 +408,8 @@ class IDEData:
def analyze_memory_usage(config: dict[str, Any]) -> None:
"""Analyze memory usage by component after compilation."""
# Lazy import to avoid overhead when not needed
from esphome.analyze_memory import MemoryAnalyzer
from esphome.analyze_memory.cli import MemoryAnalyzerCLI
from esphome.analyze_memory.helpers import get_esphome_components
idedata = get_idedata(config)
@@ -435,8 +436,6 @@ def analyze_memory_usage(config: dict[str, Any]) -> None:
external_components = set()
# Get the list of built-in ESPHome components
from esphome.analyze_memory import get_esphome_components
builtin_components = get_esphome_components()
# Special non-component keys that appear in configs
@@ -457,7 +456,9 @@ def analyze_memory_usage(config: dict[str, Any]) -> None:
_LOGGER.debug("Detected external components: %s", external_components)
# Create analyzer and run analysis
analyzer = MemoryAnalyzer(elf_path, objdump_path, readelf_path, external_components)
analyzer = MemoryAnalyzerCLI(
elf_path, objdump_path, readelf_path, external_components
)
analyzer.analyze()
# Generate and print report

View File

@@ -1,11 +1,11 @@
pylint==4.0.3
pylint==4.0.2
flake8==7.3.0 # also change in .pre-commit-config.yaml when updating
ruff==0.14.4 # also change in .pre-commit-config.yaml when updating
pyupgrade==3.21.1 # also change in .pre-commit-config.yaml when updating
pre-commit
# Unit tests
pytest==9.0.1
pytest==9.0.0
pytest-cov==7.0.0
pytest-mock==3.15.1
pytest-asyncio==1.3.0

View File

@@ -1,21 +1,6 @@
"""Tests for the web_server OTA platform."""
from __future__ import annotations
from collections.abc import Callable
import logging
from typing import Any
import pytest
from esphome import config_validation as cv
from esphome.components.web_server.ota import (
CONF_WEB_SERVER,
_web_server_ota_final_validate,
)
from esphome.const import CONF_ID, CONF_OTA, CONF_PLATFORM
from esphome.core import ID
import esphome.final_validate as fv
def test_web_server_ota_generated(generate_main: Callable[[str], str]) -> None:
@@ -115,111 +100,3 @@ def test_web_server_ota_esp8266(generate_main: Callable[[str], str]) -> None:
# Check web server OTA component is present
assert "WebServerOTAComponent" in main_cpp
assert "web_server::WebServerOTAComponent" in main_cpp
@pytest.mark.parametrize(
("ota_configs", "expected_count", "warning_expected"),
[
pytest.param(
[
{
CONF_PLATFORM: CONF_WEB_SERVER,
CONF_ID: ID("ota_web", is_manual=False),
}
],
1,
False,
id="single_instance_no_merge",
),
pytest.param(
[
{
CONF_PLATFORM: CONF_WEB_SERVER,
CONF_ID: ID("ota_web_1", is_manual=False),
},
{
CONF_PLATFORM: CONF_WEB_SERVER,
CONF_ID: ID("ota_web_2", is_manual=False),
},
],
1,
True,
id="two_instances_merged",
),
pytest.param(
[
{
CONF_PLATFORM: CONF_WEB_SERVER,
CONF_ID: ID("ota_web_1", is_manual=False),
},
{
CONF_PLATFORM: "esphome",
CONF_ID: ID("ota_esphome", is_manual=False),
},
{
CONF_PLATFORM: CONF_WEB_SERVER,
CONF_ID: ID("ota_web_2", is_manual=False),
},
],
2,
True,
id="mixed_platforms_web_server_merged",
),
],
)
def test_web_server_ota_instance_merging(
ota_configs: list[dict[str, Any]],
expected_count: int,
warning_expected: bool,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test web_server OTA instance merging behavior."""
full_conf = {CONF_OTA: ota_configs.copy()}
token = fv.full_config.set(full_conf)
try:
with caplog.at_level(logging.WARNING):
_web_server_ota_final_validate({})
updated_conf = fv.full_config.get()
# Verify total number of OTA platforms
assert len(updated_conf[CONF_OTA]) == expected_count
# Verify warning
if warning_expected:
assert any(
"Found and merged" in record.message
and "web_server OTA" in record.message
for record in caplog.records
), "Expected merge warning not found in log"
else:
assert len(caplog.records) == 0, "Unexpected warnings logged"
finally:
fv.full_config.reset(token)
def test_web_server_ota_inconsistent_manual_ids() -> None:
"""Test that inconsistent manual IDs raise an error."""
ota_configs = [
{
CONF_PLATFORM: CONF_WEB_SERVER,
CONF_ID: ID("ota_web_1", is_manual=True),
},
{
CONF_PLATFORM: CONF_WEB_SERVER,
CONF_ID: ID("ota_web_2", is_manual=True),
},
]
full_conf = {CONF_OTA: ota_configs}
token = fv.full_config.set(full_conf)
try:
with pytest.raises(
cv.Invalid,
match="Found multiple web_server OTA configurations but id is inconsistent",
):
_web_server_ota_final_validate({})
finally:
fv.full_config.reset(token)

View File

@@ -1 +0,0 @@
"""Tests for SNTP component."""

View File

@@ -1,22 +0,0 @@
esphome:
name: sntp-test
esp32:
board: esp32dev
framework:
type: esp-idf
wifi:
ssid: "testssid"
password: "testpassword"
# Test multiple SNTP instances that should be merged
time:
- platform: sntp
servers:
- 192.168.1.1
- pool.ntp.org
- platform: sntp
servers:
- pool.ntp.org
- 192.168.1.2

View File

@@ -1,238 +0,0 @@
"""Tests for SNTP time configuration validation."""
from __future__ import annotations
import logging
from typing import Any
import pytest
from esphome import config_validation as cv
from esphome.components.sntp.time import CONF_SNTP, _sntp_final_validate
from esphome.const import CONF_ID, CONF_PLATFORM, CONF_SERVERS, CONF_TIME
from esphome.core import ID
import esphome.final_validate as fv
@pytest.mark.parametrize(
("time_configs", "expected_count", "expected_servers", "warning_messages"),
[
pytest.param(
[
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time", is_manual=False),
CONF_SERVERS: ["192.168.1.1", "pool.ntp.org"],
}
],
1,
["192.168.1.1", "pool.ntp.org"],
[],
id="single_instance_no_merge",
),
pytest.param(
[
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_1", is_manual=False),
CONF_SERVERS: ["192.168.1.1", "pool.ntp.org"],
},
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_2", is_manual=False),
CONF_SERVERS: ["192.168.1.2"],
},
],
1,
["192.168.1.1", "pool.ntp.org", "192.168.1.2"],
["Found and merged 2 SNTP time configurations into one instance"],
id="two_instances_merged",
),
pytest.param(
[
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_1", is_manual=False),
CONF_SERVERS: ["192.168.1.1", "pool.ntp.org"],
},
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_2", is_manual=False),
CONF_SERVERS: ["pool.ntp.org", "192.168.1.2"],
},
],
1,
["192.168.1.1", "pool.ntp.org", "192.168.1.2"],
["Found and merged 2 SNTP time configurations into one instance"],
id="deduplication_preserves_order",
),
pytest.param(
[
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_1", is_manual=False),
CONF_SERVERS: ["192.168.1.1", "pool.ntp.org"],
},
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_2", is_manual=False),
CONF_SERVERS: ["192.168.1.2", "pool2.ntp.org"],
},
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_3", is_manual=False),
CONF_SERVERS: ["pool3.ntp.org"],
},
],
1,
["192.168.1.1", "pool.ntp.org", "192.168.1.2"],
[
"SNTP supports maximum 3 servers. Dropped excess server(s): ['pool2.ntp.org', 'pool3.ntp.org']",
"Found and merged 3 SNTP time configurations into one instance",
],
id="three_instances_drops_excess_servers",
),
pytest.param(
[
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_1", is_manual=False),
CONF_SERVERS: [
"192.168.1.1",
"pool.ntp.org",
"pool.ntp.org",
"192.168.1.1",
],
},
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_2", is_manual=False),
CONF_SERVERS: ["pool.ntp.org", "192.168.1.2"],
},
],
1,
["192.168.1.1", "pool.ntp.org", "192.168.1.2"],
["Found and merged 2 SNTP time configurations into one instance"],
id="deduplication_multiple_duplicates",
),
],
)
def test_sntp_instance_merging(
time_configs: list[dict[str, Any]],
expected_count: int,
expected_servers: list[str],
warning_messages: list[str],
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test SNTP instance merging behavior."""
# Create a mock full config with time configs
full_conf = {CONF_TIME: time_configs.copy()}
# Set the context var
token = fv.full_config.set(full_conf)
try:
with caplog.at_level(logging.WARNING):
_sntp_final_validate({})
# Get the updated config
updated_conf = fv.full_config.get()
# Check if merging occurred
if len(time_configs) > 1:
# Verify only one SNTP instance remains
sntp_instances = [
tc
for tc in updated_conf[CONF_TIME]
if tc.get(CONF_PLATFORM) == CONF_SNTP
]
assert len(sntp_instances) == expected_count
# Verify server list
assert sntp_instances[0][CONF_SERVERS] == expected_servers
# Verify warnings
for expected_msg in warning_messages:
assert any(
expected_msg in record.message for record in caplog.records
), f"Expected warning message '{expected_msg}' not found in log"
else:
# Single instance should not trigger merging or warnings
assert len(caplog.records) == 0
# Config should be unchanged
assert updated_conf[CONF_TIME] == time_configs
finally:
fv.full_config.reset(token)
def test_sntp_inconsistent_manual_ids() -> None:
"""Test that inconsistent manual IDs raise an error."""
# Create configs with manual IDs that are inconsistent
time_configs = [
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_1", is_manual=True),
CONF_SERVERS: ["192.168.1.1"],
},
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_2", is_manual=True),
CONF_SERVERS: ["192.168.1.2"],
},
]
full_conf = {CONF_TIME: time_configs}
token = fv.full_config.set(full_conf)
try:
with pytest.raises(
cv.Invalid,
match="Found multiple SNTP configurations but id is inconsistent",
):
_sntp_final_validate({})
finally:
fv.full_config.reset(token)
def test_sntp_with_other_time_platforms(caplog: pytest.LogCaptureFixture) -> None:
"""Test that SNTP merging doesn't affect other time platforms."""
time_configs = [
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_1", is_manual=False),
CONF_SERVERS: ["192.168.1.1"],
},
{
CONF_PLATFORM: "homeassistant",
CONF_ID: ID("homeassistant_time", is_manual=False),
},
{
CONF_PLATFORM: CONF_SNTP,
CONF_ID: ID("sntp_time_2", is_manual=False),
CONF_SERVERS: ["192.168.1.2"],
},
]
full_conf = {CONF_TIME: time_configs.copy()}
token = fv.full_config.set(full_conf)
try:
with caplog.at_level(logging.WARNING):
_sntp_final_validate({})
updated_conf = fv.full_config.get()
# Should have 2 time platforms: 1 merged SNTP + 1 homeassistant
assert len(updated_conf[CONF_TIME]) == 2
# Find the platforms
platforms = {tc[CONF_PLATFORM] for tc in updated_conf[CONF_TIME]}
assert platforms == {CONF_SNTP, "homeassistant"}
# Verify SNTP was merged
sntp_instances = [
tc for tc in updated_conf[CONF_TIME] if tc[CONF_PLATFORM] == CONF_SNTP
]
assert len(sntp_instances) == 1
assert sntp_instances[0][CONF_SERVERS] == ["192.168.1.1", "192.168.1.2"]
finally:
fv.full_config.reset(token)

View File

@@ -0,0 +1,2 @@
packages:
common: !include common.yaml

View File

@@ -0,0 +1,4 @@
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -1,27 +0,0 @@
esp32:
variant: esp32p4
flash_size: 32MB
cpu_frequency: 400MHz
framework:
type: esp-idf
advanced:
enable_idf_experimental_features: yes
ota:
platform: esphome
wifi:
ssid: MySSID
password: password1
esp32_hosted:
variant: ESP32C6
slot: 1
active_high: true
reset_pin: GPIO15
cmd_pin: GPIO13
clk_pin: GPIO12
d0_pin: GPIO11
d1_pin: GPIO10
d2_pin: GPIO9
d3_pin: GPIO8

View File

@@ -0,0 +1,15 @@
packages:
common: !include common.yaml
matrix_keypad:
id: keypad
rows:
- pin: 10
- pin: 11
columns:
- pin: 12
- pin: 13
keys: "1234"
has_pulldowns: true
on_key:
- lambda: ESP_LOGI("KEY", "key %d pressed", x);

View File

@@ -0,0 +1,4 @@
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,4 @@
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -1,4 +1 @@
<<: !include common.yaml
network:
enable_high_performance: true

View File

@@ -0,0 +1,4 @@
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -15,7 +15,6 @@ nrf52:
inverted: true
mode:
output: true
dcdc: False
reg0:
voltage: 2.1V
uicr_erase: true

View File

@@ -6,4 +6,4 @@ nrf52:
mode:
output: true
reg0:
voltage: 1.8V
voltage: default

View File

@@ -0,0 +1,4 @@
substitutions:
pin: GPIO4
<<: !include common.yaml

View File

@@ -0,0 +1,4 @@
substitutions:
pin: GPIO1
<<: !include common.yaml

View File

@@ -0,0 +1,2 @@
packages:
common: !include common.yaml

View File

@@ -0,0 +1,8 @@
substitutions:
scl_pin: GPIO40
sda_pin: GPIO41
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,2 @@
packages:
common: !include common.yaml

View File

@@ -0,0 +1,48 @@
<<: !include ../logger/common-usb_serial_jtag.yaml
esphome:
on_boot:
then:
- uart.write:
id: uart_1
data: 'Hello World'
- uart.write:
id: uart_1
data: [0x00, 0x20, 0x42]
uart:
- id: uart_1
tx_pin: 4
rx_pin: 5
flow_control_pin: 6
baud_rate: 9600
data_bits: 8
rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN
stop_bits: 2
- id: uart_2
tx_pin: 7
rx_pin: 8
flow_control_pin: 9
baud_rate: 9600
data_bits: 8
rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN
stop_bits: 2
- id: uart_3
tx_pin: 10
rx_pin: 11
flow_control_pin: 12
baud_rate: 9600
data_bits: 8
rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN
stop_bits: 2

View File

@@ -0,0 +1,9 @@
substitutions:
scl_pin: GPIO40
sda_pin: GPIO41
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
uart_bridge_2: !include ../../test_build_components/common/uart_bridge_2/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,11 @@
substitutions:
clk_pin: GPIO40
miso_pin: GPIO41
mosi_pin: GPIO6
cs_pin: GPIO19
packages:
spi: !include ../../test_build_components/common/spi/esp32-s3-idf.yaml
uart_bridge_2: !include ../../test_build_components/common/uart_bridge_2/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,9 @@
substitutions:
scl_pin: GPIO40
sda_pin: GPIO41
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
uart_bridge_4: !include ../../test_build_components/common/uart_bridge_4/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,11 @@
substitutions:
clk_pin: GPIO40
miso_pin: GPIO41
mosi_pin: GPIO6
cs_pin: GPIO19
packages:
spi: !include ../../test_build_components/common/spi/esp32-s3-idf.yaml
uart_bridge_4: !include ../../test_build_components/common/uart_bridge_4/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,9 @@
substitutions:
scl_pin: GPIO40
sda_pin: GPIO41
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
uart_bridge_4: !include ../../test_build_components/common/uart_bridge_4/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,11 @@
substitutions:
clk_pin: GPIO40
miso_pin: GPIO41
mosi_pin: GPIO6
cs_pin: GPIO19
packages:
spi: !include ../../test_build_components/common/spi/esp32-s3-idf.yaml
uart_bridge_4: !include ../../test_build_components/common/uart_bridge_4/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,9 @@
substitutions:
scl_pin: GPIO40
sda_pin: GPIO41
packages:
i2c: !include ../../test_build_components/common/i2c/esp32-s3-idf.yaml
uart_bridge_4: !include ../../test_build_components/common/uart_bridge_4/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,11 @@
substitutions:
clk_pin: GPIO40
miso_pin: GPIO41
mosi_pin: GPIO6
cs_pin: GPIO19
packages:
spi: !include ../../test_build_components/common/spi/esp32-s3-idf.yaml
uart_bridge_4: !include ../../test_build_components/common/uart_bridge_4/esp32-s3-idf.yaml
<<: !include common.yaml

View File

@@ -0,0 +1,59 @@
esphome:
name: test-user-services-union
friendly_name: Test User Services Union Storage
esp32:
board: esp32dev
framework:
type: esp-idf
logger:
level: DEBUG
wifi:
ssid: "test"
password: "password"
api:
actions:
# Test service with no arguments
- action: test_no_args
then:
- logger.log: "No args service called"
# Test service with one argument
- action: test_one_arg
variables:
value: int
then:
- logger.log:
format: "One arg service: %d"
args: [value]
# Test service with multiple arguments of different types
- action: test_multi_args
variables:
int_val: int
float_val: float
str_val: string
bool_val: bool
then:
- logger.log:
format: "Multi args: %d, %.2f, %s, %d"
args: [int_val, float_val, str_val.c_str(), bool_val]
# Test service with max typical arguments
- action: test_many_args
variables:
arg1: int
arg2: int
arg3: int
arg4: string
arg5: float
then:
- logger.log: "Many args service called"
binary_sensor:
- platform: template
name: "Test Binary Sensor"
id: test_sensor

View File

@@ -14,7 +14,6 @@ climate:
id: test_thermostat
name: Test Thermostat Custom Modes
sensor: thermostat_sensor
default_preset: "Eco Plus"
preset:
- name: Away
default_target_temperature_low: 16°C

View File

@@ -1,136 +0,0 @@
esphome:
name: template-alarm-many-sensors
friendly_name: "Template Alarm Control Panel with Many Sensors"
logger:
host:
api:
binary_sensor:
- platform: template
id: sensor1
name: "Door 1"
- platform: template
id: sensor2
name: "Door 2"
- platform: template
id: sensor3
name: "Window 1"
- platform: template
id: sensor4
name: "Window 2"
- platform: template
id: sensor5
name: "Motion 1"
- platform: template
id: sensor6
name: "Motion 2"
- platform: template
id: sensor7
name: "Glass Break 1"
- platform: template
id: sensor8
name: "Glass Break 2"
- platform: template
id: sensor9
name: "Smoke Detector"
- platform: template
id: sensor10
name: "CO Detector"
alarm_control_panel:
- platform: template
id: test_alarm
name: "Test Alarm"
codes:
- "1234"
requires_code_to_arm: true
arming_away_time: 5s
arming_home_time: 3s
arming_night_time: 3s
pending_time: 10s
trigger_time: 300s
restore_mode: ALWAYS_DISARMED
binary_sensors:
- input: sensor1
bypass_armed_home: false
bypass_armed_night: false
bypass_auto: true
chime: true
trigger_mode: DELAYED
- input: sensor2
bypass_armed_home: false
bypass_armed_night: false
bypass_auto: true
chime: true
trigger_mode: DELAYED
- input: sensor3
bypass_armed_home: true
bypass_armed_night: false
bypass_auto: false
chime: false
trigger_mode: DELAYED
- input: sensor4
bypass_armed_home: true
bypass_armed_night: false
bypass_auto: false
chime: false
trigger_mode: DELAYED
- input: sensor5
bypass_armed_home: false
bypass_armed_night: true
bypass_auto: false
chime: false
trigger_mode: INSTANT
- input: sensor6
bypass_armed_home: false
bypass_armed_night: true
bypass_auto: false
chime: false
trigger_mode: INSTANT
- input: sensor7
bypass_armed_home: false
bypass_armed_night: false
bypass_auto: false
chime: false
trigger_mode: INSTANT
- input: sensor8
bypass_armed_home: false
bypass_armed_night: false
bypass_auto: false
chime: false
trigger_mode: INSTANT
- input: sensor9
bypass_armed_home: false
bypass_armed_night: false
bypass_auto: false
chime: false
trigger_mode: INSTANT_ALWAYS
- input: sensor10
bypass_armed_home: false
bypass_armed_night: false
bypass_auto: false
chime: false
trigger_mode: INSTANT_ALWAYS
on_disarmed:
- logger.log: "Alarm disarmed"
on_arming:
- logger.log: "Alarm arming"
on_armed_away:
- logger.log: "Alarm armed away"
on_armed_home:
- logger.log: "Alarm armed home"
on_armed_night:
- logger.log: "Alarm armed night"
on_pending:
- logger.log: "Alarm pending"
on_triggered:
- logger.log: "Alarm triggered"
on_cleared:
- logger.log: "Alarm cleared"
on_chime:
- logger.log: "Chime activated"
on_ready:
- logger.log: "Sensors ready state changed"

View File

@@ -1,47 +0,0 @@
# Test for wait_until in on_boot automation
# Reproduces bug where wait_until in on_boot would hang forever
# because WaitUntilAction::setup() would disable_loop() after
# play_complex() had already enabled it.
esphome:
name: wait-until-on-boot
on_boot:
then:
- logger.log: "on_boot: Starting wait_until test"
- globals.set:
id: on_boot_started
value: 'true'
- wait_until:
condition:
lambda: return id(test_flag);
timeout: 5s
- logger.log: "on_boot: wait_until completed successfully"
host:
logger:
level: DEBUG
globals:
- id: on_boot_started
type: bool
initial_value: 'false'
- id: test_flag
type: bool
initial_value: 'false'
api:
actions:
- action: set_test_flag
then:
- globals.set:
id: test_flag
value: 'true'
- action: check_on_boot_started
then:
- lambda: |-
if (id(on_boot_started)) {
ESP_LOGI("test", "on_boot has started");
} else {
ESP_LOGI("test", "on_boot has NOT started");
}

View File

@@ -2,13 +2,9 @@
from __future__ import annotations
import asyncio
import aioesphomeapi
from aioesphomeapi import ClimateInfo, ClimatePreset, EntityState
from aioesphomeapi import ClimateInfo, ClimatePreset
import pytest
from .state_utils import InitialStateHelper
from .types import APIClientConnectedFactory, RunCompiledFunction
@@ -18,50 +14,15 @@ async def test_climate_custom_fan_modes_and_presets(
run_compiled: RunCompiledFunction,
api_client_connected: APIClientConnectedFactory,
) -> None:
"""Test that custom presets are properly exposed and can be changed."""
loop = asyncio.get_running_loop()
"""Test that custom presets are properly exposed via API."""
async with run_compiled(yaml_config), api_client_connected() as client:
states: dict[int, EntityState] = {}
super_saver_future: asyncio.Future[EntityState] = loop.create_future()
vacation_future: asyncio.Future[EntityState] = loop.create_future()
def on_state(state: EntityState) -> None:
states[state.key] = state
if isinstance(state, aioesphomeapi.ClimateState):
# Wait for Super Saver preset
if (
state.custom_preset == "Super Saver"
and state.target_temperature_low == 20.0
and state.target_temperature_high == 24.0
and not super_saver_future.done()
):
super_saver_future.set_result(state)
# Wait for Vacation Mode preset
elif (
state.custom_preset == "Vacation Mode"
and state.target_temperature_low == 15.0
and state.target_temperature_high == 18.0
and not vacation_future.done()
):
vacation_future.set_result(state)
# Get entities and set up state synchronization
# Get entities and services
entities, services = await client.list_entities_services()
initial_state_helper = InitialStateHelper(entities)
climate_infos = [e for e in entities if isinstance(e, ClimateInfo)]
assert len(climate_infos) == 1, "Expected exactly 1 climate entity"
test_climate = climate_infos[0]
# Subscribe with the wrapper that filters initial states
client.subscribe_states(initial_state_helper.on_state_wrapper(on_state))
# Wait for all initial states to be broadcast
try:
await initial_state_helper.wait_for_initial_states()
except TimeoutError:
pytest.fail("Timeout waiting for initial states")
# Verify enum presets are exposed (from preset: config map)
assert ClimatePreset.AWAY in test_climate.supported_presets, (
"Expected AWAY in enum presets"
@@ -79,43 +40,3 @@ async def test_climate_custom_fan_modes_and_presets(
assert "Vacation Mode" in custom_presets, (
"Expected 'Vacation Mode' in custom presets"
)
# Get initial state and verify default preset
initial_state = initial_state_helper.initial_states.get(test_climate.key)
assert initial_state is not None, "Climate initial state not found"
assert isinstance(initial_state, aioesphomeapi.ClimateState)
assert initial_state.custom_preset == "Eco Plus", (
f"Expected default preset 'Eco Plus', got '{initial_state.custom_preset}'"
)
assert initial_state.target_temperature_low == 18.0, (
f"Expected low temp 18.0, got {initial_state.target_temperature_low}"
)
assert initial_state.target_temperature_high == 22.0, (
f"Expected high temp 22.0, got {initial_state.target_temperature_high}"
)
# Test changing to "Super Saver" custom preset
client.climate_command(test_climate.key, custom_preset="Super Saver")
try:
super_saver_state = await asyncio.wait_for(super_saver_future, timeout=5.0)
except TimeoutError:
pytest.fail("Super Saver preset change not received within 5 seconds")
assert isinstance(super_saver_state, aioesphomeapi.ClimateState)
assert super_saver_state.custom_preset == "Super Saver"
assert super_saver_state.target_temperature_low == 20.0
assert super_saver_state.target_temperature_high == 24.0
# Test changing to "Vacation Mode" custom preset
client.climate_command(test_climate.key, custom_preset="Vacation Mode")
try:
vacation_state = await asyncio.wait_for(vacation_future, timeout=5.0)
except TimeoutError:
pytest.fail("Vacation Mode preset change not received within 5 seconds")
assert isinstance(vacation_state, aioesphomeapi.ClimateState)
assert vacation_state.custom_preset == "Vacation Mode"
assert vacation_state.target_temperature_low == 15.0
assert vacation_state.target_temperature_high == 18.0

View File

@@ -1,118 +0,0 @@
"""Integration test for template alarm control panel with many sensors."""
from __future__ import annotations
import aioesphomeapi
from aioesphomeapi.model import APIIntEnum
import pytest
from .state_utils import InitialStateHelper
from .types import APIClientConnectedFactory, RunCompiledFunction
class EspHomeACPFeatures(APIIntEnum):
"""ESPHome AlarmControlPanel feature numbers."""
ARM_HOME = 1
ARM_AWAY = 2
ARM_NIGHT = 4
TRIGGER = 8
ARM_CUSTOM_BYPASS = 16
ARM_VACATION = 32
@pytest.mark.asyncio
async def test_template_alarm_control_panel_many_sensors(
yaml_config: str,
run_compiled: RunCompiledFunction,
api_client_connected: APIClientConnectedFactory,
) -> None:
"""Test template alarm control panel with 10 binary sensors using FixedVector."""
async with run_compiled(yaml_config), api_client_connected() as client:
# Get entity info first
entities, _ = await client.list_entities_services()
# Find the alarm control panel and binary sensors
alarm_info: aioesphomeapi.AlarmControlPanelInfo | None = None
binary_sensors: list[aioesphomeapi.BinarySensorInfo] = []
for entity in entities:
if isinstance(entity, aioesphomeapi.AlarmControlPanelInfo):
alarm_info = entity
elif isinstance(entity, aioesphomeapi.BinarySensorInfo):
binary_sensors.append(entity)
assert alarm_info is not None, "Alarm control panel entity info not found"
assert alarm_info.name == "Test Alarm"
assert alarm_info.requires_code is True
assert alarm_info.requires_code_to_arm is True
# Verify we have 10 binary sensors
assert len(binary_sensors) == 10, (
f"Expected 10 binary sensors, got {len(binary_sensors)}"
)
# Verify sensor names
expected_sensor_names = {
"Door 1",
"Door 2",
"Window 1",
"Window 2",
"Motion 1",
"Motion 2",
"Glass Break 1",
"Glass Break 2",
"Smoke Detector",
"CO Detector",
}
actual_sensor_names = {sensor.name for sensor in binary_sensors}
assert actual_sensor_names == expected_sensor_names, (
f"Sensor names mismatch. Expected: {expected_sensor_names}, "
f"Got: {actual_sensor_names}"
)
# Use InitialStateHelper to wait for all initial states
state_helper = InitialStateHelper(entities)
def on_state(state: aioesphomeapi.EntityState) -> None:
# We'll receive subsequent states here after initial states
pass
client.subscribe_states(state_helper.on_state_wrapper(on_state))
# Wait for all initial states
await state_helper.wait_for_initial_states(timeout=5.0)
# Verify the alarm state is disarmed initially
alarm_state = state_helper.initial_states.get(alarm_info.key)
assert alarm_state is not None, "Alarm control panel initial state not received"
assert isinstance(alarm_state, aioesphomeapi.AlarmControlPanelEntityState)
assert alarm_state.state == aioesphomeapi.AlarmControlPanelState.DISARMED, (
f"Expected initial state DISARMED, got {alarm_state.state}"
)
# Verify all 10 binary sensors have initial states
binary_sensor_states = [
state_helper.initial_states.get(sensor.key) for sensor in binary_sensors
]
assert all(state is not None for state in binary_sensor_states), (
"Not all binary sensors have initial states"
)
# Verify all binary sensor states are BinarySensorState type
for i, state in enumerate(binary_sensor_states):
assert isinstance(state, aioesphomeapi.BinarySensorState), (
f"Binary sensor {i} state is not BinarySensorState: {type(state)}"
)
# Verify supported features
expected_features = (
EspHomeACPFeatures.ARM_HOME
| EspHomeACPFeatures.ARM_AWAY
| EspHomeACPFeatures.ARM_NIGHT
| EspHomeACPFeatures.TRIGGER
)
assert alarm_info.supported_features == expected_features, (
f"Expected supported_features={expected_features} (ARM_HOME|ARM_AWAY|ARM_NIGHT|TRIGGER), "
f"got {alarm_info.supported_features}"
)

View File

@@ -1,91 +0,0 @@
"""Integration test for wait_until in on_boot automation.
This test validates that wait_until works correctly when triggered from on_boot,
which runs at the same setup priority as WaitUntilAction itself. This was broken
before the fix because WaitUntilAction::setup() would unconditionally disable_loop(),
even if play_complex() had already been called and enabled the loop.
The bug: on_boot fires during StartupTrigger::setup(), which calls WaitUntilAction::play_complex()
before WaitUntilAction::setup() has run. Then when WaitUntilAction::setup() runs, it calls
disable_loop(), undoing the enable_loop() from play_complex(), causing wait_until to hang forever.
"""
from __future__ import annotations
import asyncio
import re
import pytest
from .types import APIClientConnectedFactory, RunCompiledFunction
@pytest.mark.asyncio
async def test_wait_until_on_boot(
yaml_config: str,
run_compiled: RunCompiledFunction,
api_client_connected: APIClientConnectedFactory,
) -> None:
"""Test that wait_until works in on_boot automation with a condition that becomes true later."""
loop = asyncio.get_running_loop()
on_boot_started = False
on_boot_completed = False
on_boot_started_pattern = re.compile(r"on_boot: Starting wait_until test")
on_boot_complete_pattern = re.compile(r"on_boot: wait_until completed successfully")
on_boot_started_future = loop.create_future()
on_boot_complete_future = loop.create_future()
def check_output(line: str) -> None:
"""Check log output for test progress."""
nonlocal on_boot_started, on_boot_completed
if on_boot_started_pattern.search(line):
on_boot_started = True
if not on_boot_started_future.done():
on_boot_started_future.set_result(True)
if on_boot_complete_pattern.search(line):
on_boot_completed = True
if not on_boot_complete_future.done():
on_boot_complete_future.set_result(True)
async with (
run_compiled(yaml_config, line_callback=check_output),
api_client_connected() as client,
):
# Wait for on_boot to start
await asyncio.wait_for(on_boot_started_future, timeout=10.0)
assert on_boot_started, "on_boot did not start"
# At this point, on_boot is blocked in wait_until waiting for test_flag to become true
# If the bug exists, wait_until's loop is disabled and it will never complete
# even after we set the flag
# Give a moment for setup to complete
await asyncio.sleep(0.5)
# Now set the flag that wait_until is waiting for
_, services = await client.list_entities_services()
set_flag_service = next(
(s for s in services if s.name == "set_test_flag"), None
)
assert set_flag_service is not None, "set_test_flag service not found"
client.execute_service(set_flag_service, {})
# If the fix works, wait_until's loop() will check the condition and proceed
# If the bug exists, wait_until is stuck with disabled loop and will timeout
try:
await asyncio.wait_for(on_boot_complete_future, timeout=2.0)
assert on_boot_completed, (
"on_boot wait_until did not complete after flag was set"
)
except TimeoutError:
pytest.fail(
"wait_until in on_boot did not complete within 2s after condition became true. "
"This indicates the bug where WaitUntilAction::setup() disables the loop "
"after play_complex() has already enabled it."
)

View File

@@ -1166,56 +1166,6 @@ def test_upload_program_ota_with_mqtt_resolution(
)
def test_upload_program_ota_with_mqtt_empty_broker(
mock_mqtt_get_ip: Mock,
mock_is_ip_address: Mock,
mock_run_ota: Mock,
tmp_path: Path,
caplog: CaptureFixture,
) -> None:
"""Test upload_program with OTA when MQTT broker is empty (issue #11653)."""
setup_core(address="192.168.1.50", platform=PLATFORM_ESP32, tmp_path=tmp_path)
mock_is_ip_address.return_value = True
mock_mqtt_get_ip.side_effect = EsphomeError(
"Cannot discover IP via MQTT as the broker is not configured"
)
mock_run_ota.return_value = (0, "192.168.1.50")
config = {
CONF_OTA: [
{
CONF_PLATFORM: CONF_ESPHOME,
CONF_PORT: 3232,
}
],
CONF_MQTT: {
CONF_BROKER: "",
},
CONF_MDNS: {
CONF_DISABLED: True,
},
}
args = MockArgs(username="user", password="pass", client_id="client")
devices = ["MQTTIP", "192.168.1.50"]
exit_code, host = upload_program(config, args, devices)
assert exit_code == 0
assert host == "192.168.1.50"
# Verify MQTT was attempted but failed gracefully
mock_mqtt_get_ip.assert_called_once_with(config, "user", "pass", "client")
# Verify we fell back to the IP address
expected_firmware = (
tmp_path / ".esphome" / "build" / "test" / ".pioenvs" / "test" / "firmware.bin"
)
mock_run_ota.assert_called_once_with(
["192.168.1.50"], 3232, None, expected_firmware
)
# Verify warning was logged
assert "MQTT IP discovery failed" in caplog.text
@patch("esphome.__main__.importlib.import_module")
def test_upload_program_platform_specific_handler(
mock_import: Mock,

View File

@@ -1,91 +0,0 @@
"""Unit tests for esphome.mqtt module."""
from __future__ import annotations
import pytest
from esphome.const import CONF_BROKER, CONF_ESPHOME, CONF_MQTT, CONF_NAME
from esphome.core import EsphomeError
from esphome.mqtt import get_esphome_device_ip
def test_get_esphome_device_ip_empty_broker() -> None:
"""Test that get_esphome_device_ip raises EsphomeError when broker is empty."""
config = {
CONF_MQTT: {
CONF_BROKER: "",
},
CONF_ESPHOME: {
CONF_NAME: "test-device",
},
}
with pytest.raises(
EsphomeError,
match="Cannot discover IP via MQTT as the broker is not configured",
):
get_esphome_device_ip(config)
def test_get_esphome_device_ip_none_broker() -> None:
"""Test that get_esphome_device_ip raises EsphomeError when broker is None."""
config = {
CONF_MQTT: {
CONF_BROKER: None,
},
CONF_ESPHOME: {
CONF_NAME: "test-device",
},
}
with pytest.raises(
EsphomeError,
match="Cannot discover IP via MQTT as the broker is not configured",
):
get_esphome_device_ip(config)
def test_get_esphome_device_ip_missing_mqtt() -> None:
"""Test that get_esphome_device_ip raises EsphomeError when mqtt config is missing."""
config = {
CONF_ESPHOME: {
CONF_NAME: "test-device",
},
}
with pytest.raises(
EsphomeError,
match="Cannot discover IP via MQTT as the config does not include the mqtt:",
):
get_esphome_device_ip(config)
def test_get_esphome_device_ip_missing_esphome() -> None:
"""Test that get_esphome_device_ip raises EsphomeError when esphome config is missing."""
config = {
CONF_MQTT: {
CONF_BROKER: "mqtt.local",
},
}
with pytest.raises(
EsphomeError,
match="Cannot discover IP via MQTT as the config does not include the device name:",
):
get_esphome_device_ip(config)
def test_get_esphome_device_ip_missing_name() -> None:
"""Test that get_esphome_device_ip raises EsphomeError when device name is missing."""
config = {
CONF_MQTT: {
CONF_BROKER: "mqtt.local",
},
CONF_ESPHOME: {},
}
with pytest.raises(
EsphomeError,
match="Cannot discover IP via MQTT as the config does not include the device name:",
):
get_esphome_device_ip(config)