esphome 2025.9.0b1__py3-none-any.whl → 2025.9.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +146 -68
- esphome/components/adc/__init__.py +1 -26
- esphome/components/adc/sensor.py +20 -0
- esphome/components/api/api_connection.cpp +4 -11
- esphome/components/api/api_connection.h +0 -1
- esphome/components/api/api_pb2.cpp +0 -8
- esphome/components/api/api_pb2.h +0 -4
- esphome/components/api/api_pb2_dump.cpp +1 -7
- esphome/components/api/api_pb2_service.cpp +0 -14
- esphome/components/api/api_pb2_service.h +1 -3
- esphome/components/api/client.py +5 -3
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +3 -1
- esphome/components/captive_portal/captive_index.h +77 -97
- esphome/components/esp32_ble/ble_uuid.cpp +30 -9
- esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +4 -3
- esphome/components/esp32_ble_client/ble_client_base.h +8 -5
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -3
- esphome/components/ethernet/ethernet_component.cpp +48 -2
- esphome/components/ethernet/ethernet_component.h +2 -0
- esphome/components/factory_reset/button/factory_reset_button.cpp +18 -1
- esphome/components/factory_reset/button/factory_reset_button.h +6 -1
- esphome/components/factory_reset/switch/factory_reset_switch.cpp +18 -1
- esphome/components/factory_reset/switch/factory_reset_switch.h +5 -1
- esphome/components/ina2xx_base/__init__.py +4 -2
- esphome/components/md5/md5.cpp +3 -2
- esphome/components/openthread/openthread.cpp +41 -7
- esphome/components/openthread/openthread.h +11 -0
- esphome/components/web_server/server_index_v2.h +149 -149
- esphome/components/wifi/wifi_component.cpp +1 -1
- esphome/components/wifi_info/wifi_info_text_sensor.h +3 -2
- esphome/const.py +2 -1
- esphome/core/helpers.cpp +8 -7
- esphome/core/helpers.h +29 -0
- esphome/core/scheduler.cpp +4 -4
- esphome/core/scheduler.h +1 -1
- {esphome-2025.9.0b1.dist-info → esphome-2025.9.0b2.dist-info}/METADATA +2 -2
- {esphome-2025.9.0b1.dist-info → esphome-2025.9.0b2.dist-info}/RECORD +41 -41
- {esphome-2025.9.0b1.dist-info → esphome-2025.9.0b2.dist-info}/WHEEL +0 -0
- {esphome-2025.9.0b1.dist-info → esphome-2025.9.0b2.dist-info}/entry_points.txt +0 -0
- {esphome-2025.9.0b1.dist-info → esphome-2025.9.0b2.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.9.0b1.dist-info → esphome-2025.9.0b2.dist-info}/top_level.txt +0 -0
esphome/__main__.py
CHANGED
@@ -15,9 +15,11 @@ import argcomplete
|
|
15
15
|
|
16
16
|
from esphome import const, writer, yaml_util
|
17
17
|
import esphome.codegen as cg
|
18
|
+
from esphome.components.mqtt import CONF_DISCOVER_IP
|
18
19
|
from esphome.config import iter_component_configs, read_config, strip_default_ids
|
19
20
|
from esphome.const import (
|
20
21
|
ALLOWED_NAME_CHARS,
|
22
|
+
CONF_API,
|
21
23
|
CONF_BAUD_RATE,
|
22
24
|
CONF_BROKER,
|
23
25
|
CONF_DEASSERT_RTS_DTR,
|
@@ -43,6 +45,7 @@ from esphome.const import (
|
|
43
45
|
SECRETS_FILES,
|
44
46
|
)
|
45
47
|
from esphome.core import CORE, EsphomeError, coroutine
|
48
|
+
from esphome.enum import StrEnum
|
46
49
|
from esphome.helpers import get_bool_env, indent, is_ip_address
|
47
50
|
from esphome.log import AnsiFore, color, setup_log
|
48
51
|
from esphome.types import ConfigType
|
@@ -106,13 +109,15 @@ def choose_prompt(options, purpose: str = None):
|
|
106
109
|
return options[opt - 1][1]
|
107
110
|
|
108
111
|
|
112
|
+
class Purpose(StrEnum):
|
113
|
+
UPLOADING = "uploading"
|
114
|
+
LOGGING = "logging"
|
115
|
+
|
116
|
+
|
109
117
|
def choose_upload_log_host(
|
110
118
|
default: list[str] | str | None,
|
111
119
|
check_default: str | None,
|
112
|
-
|
113
|
-
show_mqtt: bool,
|
114
|
-
show_api: bool,
|
115
|
-
purpose: str | None = None,
|
120
|
+
purpose: Purpose,
|
116
121
|
) -> list[str]:
|
117
122
|
# Convert to list for uniform handling
|
118
123
|
defaults = [default] if isinstance(default, str) else default or []
|
@@ -132,13 +137,30 @@ def choose_upload_log_host(
|
|
132
137
|
]
|
133
138
|
resolved.append(choose_prompt(options, purpose=purpose))
|
134
139
|
elif device == "OTA":
|
135
|
-
|
136
|
-
|
137
|
-
|
140
|
+
# ensure IP adresses are used first
|
141
|
+
if is_ip_address(CORE.address) and (
|
142
|
+
(purpose == Purpose.LOGGING and has_api())
|
143
|
+
or (purpose == Purpose.UPLOADING and has_ota())
|
138
144
|
):
|
139
145
|
resolved.append(CORE.address)
|
140
|
-
|
141
|
-
|
146
|
+
|
147
|
+
if purpose == Purpose.LOGGING:
|
148
|
+
if has_api() and has_mqtt_ip_lookup():
|
149
|
+
resolved.append("MQTTIP")
|
150
|
+
|
151
|
+
if has_mqtt_logging():
|
152
|
+
resolved.append("MQTT")
|
153
|
+
|
154
|
+
if has_api() and has_non_ip_address():
|
155
|
+
resolved.append(CORE.address)
|
156
|
+
|
157
|
+
elif purpose == Purpose.UPLOADING:
|
158
|
+
if has_ota() and has_mqtt_ip_lookup():
|
159
|
+
resolved.append("MQTTIP")
|
160
|
+
|
161
|
+
if has_ota() and has_non_ip_address():
|
162
|
+
resolved.append(CORE.address)
|
163
|
+
|
142
164
|
else:
|
143
165
|
resolved.append(device)
|
144
166
|
if not resolved:
|
@@ -149,39 +171,111 @@ def choose_upload_log_host(
|
|
149
171
|
options = [
|
150
172
|
(f"{port.path} ({port.description})", port.path) for port in get_serial_ports()
|
151
173
|
]
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
174
|
+
|
175
|
+
if purpose == Purpose.LOGGING:
|
176
|
+
if has_mqtt_logging():
|
177
|
+
mqtt_config = CORE.config[CONF_MQTT]
|
178
|
+
options.append((f"MQTT ({mqtt_config[CONF_BROKER]})", "MQTT"))
|
179
|
+
|
180
|
+
if has_api():
|
181
|
+
if has_resolvable_address():
|
182
|
+
options.append((f"Over The Air ({CORE.address})", CORE.address))
|
183
|
+
if has_mqtt_ip_lookup():
|
184
|
+
options.append(("Over The Air (MQTT IP lookup)", "MQTTIP"))
|
185
|
+
|
186
|
+
elif purpose == Purpose.UPLOADING and has_ota():
|
187
|
+
if has_resolvable_address():
|
188
|
+
options.append((f"Over The Air ({CORE.address})", CORE.address))
|
189
|
+
if has_mqtt_ip_lookup():
|
190
|
+
options.append(("Over The Air (MQTT IP lookup)", "MQTTIP"))
|
157
191
|
|
158
192
|
if check_default is not None and check_default in [opt[1] for opt in options]:
|
159
193
|
return [check_default]
|
160
194
|
return [choose_prompt(options, purpose=purpose)]
|
161
195
|
|
162
196
|
|
163
|
-
def
|
197
|
+
def has_mqtt_logging() -> bool:
|
198
|
+
"""Check if MQTT logging is available."""
|
199
|
+
if CONF_MQTT not in CORE.config:
|
200
|
+
return False
|
201
|
+
|
202
|
+
mqtt_config = CORE.config[CONF_MQTT]
|
203
|
+
|
204
|
+
# enabled by default
|
205
|
+
if CONF_LOG_TOPIC not in mqtt_config:
|
206
|
+
return True
|
207
|
+
|
164
208
|
log_topic = mqtt_config[CONF_LOG_TOPIC]
|
165
209
|
if log_topic is None:
|
166
210
|
return False
|
211
|
+
|
167
212
|
if CONF_TOPIC not in log_topic:
|
168
213
|
return False
|
169
|
-
return log_topic.get(CONF_LEVEL, None) != "NONE"
|
170
214
|
|
215
|
+
return log_topic[CONF_LEVEL] != "NONE"
|
216
|
+
|
217
|
+
|
218
|
+
def has_mqtt() -> bool:
|
219
|
+
"""Check if MQTT is available."""
|
220
|
+
return CONF_MQTT in CORE.config
|
221
|
+
|
222
|
+
|
223
|
+
def has_api() -> bool:
|
224
|
+
"""Check if API is available."""
|
225
|
+
return CONF_API in CORE.config
|
226
|
+
|
227
|
+
|
228
|
+
def has_ota() -> bool:
|
229
|
+
"""Check if OTA is available."""
|
230
|
+
return CONF_OTA in CORE.config
|
171
231
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
232
|
+
|
233
|
+
def has_mqtt_ip_lookup() -> bool:
|
234
|
+
"""Check if MQTT is available and IP lookup is supported."""
|
235
|
+
if CONF_MQTT not in CORE.config:
|
236
|
+
return False
|
237
|
+
# Default Enabled
|
238
|
+
if CONF_DISCOVER_IP not in CORE.config[CONF_MQTT]:
|
239
|
+
return True
|
240
|
+
return CORE.config[CONF_MQTT][CONF_DISCOVER_IP]
|
241
|
+
|
242
|
+
|
243
|
+
def has_mdns() -> bool:
|
244
|
+
"""Check if MDNS is available."""
|
245
|
+
return CONF_MDNS not in CORE.config or not CORE.config[CONF_MDNS][CONF_DISABLED]
|
246
|
+
|
247
|
+
|
248
|
+
def has_non_ip_address() -> bool:
|
249
|
+
"""Check if CORE.address is set and is not an IP address."""
|
250
|
+
return CORE.address is not None and not is_ip_address(CORE.address)
|
251
|
+
|
252
|
+
|
253
|
+
def has_ip_address() -> bool:
|
254
|
+
"""Check if CORE.address is a valid IP address."""
|
255
|
+
return CORE.address is not None and is_ip_address(CORE.address)
|
256
|
+
|
257
|
+
|
258
|
+
def has_resolvable_address() -> bool:
|
259
|
+
"""Check if CORE.address is resolvable (via mDNS or is an IP address)."""
|
260
|
+
return has_mdns() or has_ip_address()
|
261
|
+
|
262
|
+
|
263
|
+
def mqtt_get_ip(config: ConfigType, username: str, password: str, client_id: str):
|
264
|
+
from esphome import mqtt
|
265
|
+
|
266
|
+
return mqtt.get_esphome_device_ip(config, username, password, client_id)
|
267
|
+
|
268
|
+
|
269
|
+
_PORT_TO_PORT_TYPE = {
|
270
|
+
"MQTT": "MQTT",
|
271
|
+
"MQTTIP": "MQTTIP",
|
272
|
+
}
|
177
273
|
|
178
274
|
|
179
275
|
def get_port_type(port: str) -> str:
|
180
276
|
if port.startswith("/") or port.startswith("COM"):
|
181
277
|
return "SERIAL"
|
182
|
-
|
183
|
-
return "MQTT"
|
184
|
-
return "NETWORK"
|
278
|
+
return _PORT_TO_PORT_TYPE.get(port, "NETWORK")
|
185
279
|
|
186
280
|
|
187
281
|
def run_miniterm(config: ConfigType, port: str, args) -> int:
|
@@ -226,7 +320,9 @@ def run_miniterm(config: ConfigType, port: str, args) -> int:
|
|
226
320
|
.replace(b"\n", b"")
|
227
321
|
.decode("utf8", "backslashreplace")
|
228
322
|
)
|
229
|
-
|
323
|
+
time_ = datetime.now()
|
324
|
+
nanoseconds = time_.microsecond // 1000
|
325
|
+
time_str = f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}.{nanoseconds:03}]"
|
230
326
|
safe_print(parser.parse_line(line, time_str))
|
231
327
|
|
232
328
|
backtrace_state = platformio_api.process_stacktrace(
|
@@ -437,23 +533,9 @@ def upload_program(
|
|
437
533
|
password = ota_conf.get(CONF_PASSWORD, "")
|
438
534
|
binary = args.file if getattr(args, "file", None) is not None else CORE.firmware_bin
|
439
535
|
|
440
|
-
#
|
441
|
-
|
442
|
-
|
443
|
-
CONF_MQTT in config # pylint: disable=too-many-boolean-expressions
|
444
|
-
and (not devices or host in ("MQTT", "OTA"))
|
445
|
-
and (
|
446
|
-
((config[CONF_MDNS][CONF_DISABLED]) and not is_ip_address(CORE.address))
|
447
|
-
or get_port_type(host) == "MQTT"
|
448
|
-
)
|
449
|
-
):
|
450
|
-
from esphome import mqtt
|
451
|
-
|
452
|
-
devices = [
|
453
|
-
mqtt.get_esphome_device_ip(
|
454
|
-
config, args.username, args.password, args.client_id
|
455
|
-
)
|
456
|
-
]
|
536
|
+
# MQTT address resolution
|
537
|
+
if get_port_type(host) in ("MQTT", "MQTTIP"):
|
538
|
+
devices = mqtt_get_ip(config, args.username, args.password, args.client_id)
|
457
539
|
|
458
540
|
return espota2.run_ota(devices, remote_port, password, binary)
|
459
541
|
|
@@ -474,20 +556,28 @@ def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int
|
|
474
556
|
if get_port_type(port) == "SERIAL":
|
475
557
|
check_permissions(port)
|
476
558
|
return run_miniterm(config, port, args)
|
477
|
-
if get_port_type(port) == "NETWORK" and "api" in config:
|
478
|
-
addresses_to_use = devices
|
479
|
-
if config[CONF_MDNS][CONF_DISABLED] and CONF_MQTT in config:
|
480
|
-
from esphome import mqtt
|
481
559
|
|
482
|
-
|
560
|
+
port_type = get_port_type(port)
|
561
|
+
|
562
|
+
# Check if we should use API for logging
|
563
|
+
if has_api():
|
564
|
+
addresses_to_use: list[str] | None = None
|
565
|
+
|
566
|
+
if port_type == "NETWORK" and (has_mdns() or is_ip_address(port)):
|
567
|
+
addresses_to_use = devices
|
568
|
+
elif port_type in ("NETWORK", "MQTT", "MQTTIP") and has_mqtt_ip_lookup():
|
569
|
+
# Only use MQTT IP lookup if the first condition didn't match
|
570
|
+
# (for MQTT/MQTTIP types, or for NETWORK when mdns/ip check fails)
|
571
|
+
addresses_to_use = mqtt_get_ip(
|
483
572
|
config, args.username, args.password, args.client_id
|
484
|
-
)
|
485
|
-
|
573
|
+
)
|
574
|
+
|
575
|
+
if addresses_to_use is not None:
|
576
|
+
from esphome.components.api.client import run_logs
|
486
577
|
|
487
|
-
|
578
|
+
return run_logs(config, addresses_to_use)
|
488
579
|
|
489
|
-
|
490
|
-
if get_port_type(port) in ("NETWORK", "MQTT") and "mqtt" in config:
|
580
|
+
if port_type in ("NETWORK", "MQTT") and has_mqtt_logging():
|
491
581
|
from esphome import mqtt
|
492
582
|
|
493
583
|
return mqtt.show_logs(
|
@@ -553,10 +643,7 @@ def command_upload(args: ArgsProtocol, config: ConfigType) -> int | None:
|
|
553
643
|
devices = choose_upload_log_host(
|
554
644
|
default=args.device,
|
555
645
|
check_default=None,
|
556
|
-
|
557
|
-
show_mqtt=False,
|
558
|
-
show_api=False,
|
559
|
-
purpose="uploading",
|
646
|
+
purpose=Purpose.UPLOADING,
|
560
647
|
)
|
561
648
|
|
562
649
|
exit_code, _ = upload_program(config, args, devices)
|
@@ -581,10 +668,7 @@ def command_logs(args: ArgsProtocol, config: ConfigType) -> int | None:
|
|
581
668
|
devices = choose_upload_log_host(
|
582
669
|
default=args.device,
|
583
670
|
check_default=None,
|
584
|
-
|
585
|
-
show_mqtt=True,
|
586
|
-
show_api=True,
|
587
|
-
purpose="logging",
|
671
|
+
purpose=Purpose.LOGGING,
|
588
672
|
)
|
589
673
|
return show_logs(config, args, devices)
|
590
674
|
|
@@ -610,10 +694,7 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
|
|
610
694
|
devices = choose_upload_log_host(
|
611
695
|
default=args.device,
|
612
696
|
check_default=None,
|
613
|
-
|
614
|
-
show_mqtt=False,
|
615
|
-
show_api=True,
|
616
|
-
purpose="uploading",
|
697
|
+
purpose=Purpose.UPLOADING,
|
617
698
|
)
|
618
699
|
|
619
700
|
exit_code, successful_device = upload_program(config, args, devices)
|
@@ -630,10 +711,7 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
|
|
630
711
|
devices = choose_upload_log_host(
|
631
712
|
default=successful_device,
|
632
713
|
check_default=successful_device,
|
633
|
-
|
634
|
-
show_mqtt=True,
|
635
|
-
show_api=True,
|
636
|
-
purpose="logging",
|
714
|
+
purpose=Purpose.LOGGING,
|
637
715
|
)
|
638
716
|
return show_logs(config, args, devices)
|
639
717
|
|
@@ -11,15 +11,8 @@ from esphome.components.esp32.const import (
|
|
11
11
|
VARIANT_ESP32S2,
|
12
12
|
VARIANT_ESP32S3,
|
13
13
|
)
|
14
|
-
from esphome.config_helpers import filter_source_files_from_platform
|
15
14
|
import esphome.config_validation as cv
|
16
|
-
from esphome.const import
|
17
|
-
CONF_ANALOG,
|
18
|
-
CONF_INPUT,
|
19
|
-
CONF_NUMBER,
|
20
|
-
PLATFORM_ESP8266,
|
21
|
-
PlatformFramework,
|
22
|
-
)
|
15
|
+
from esphome.const import CONF_ANALOG, CONF_INPUT, CONF_NUMBER, PLATFORM_ESP8266
|
23
16
|
from esphome.core import CORE
|
24
17
|
|
25
18
|
CODEOWNERS = ["@esphome/core"]
|
@@ -273,21 +266,3 @@ def validate_adc_pin(value):
|
|
273
266
|
)(value)
|
274
267
|
|
275
268
|
raise NotImplementedError
|
276
|
-
|
277
|
-
|
278
|
-
FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
279
|
-
{
|
280
|
-
"adc_sensor_esp32.cpp": {
|
281
|
-
PlatformFramework.ESP32_ARDUINO,
|
282
|
-
PlatformFramework.ESP32_IDF,
|
283
|
-
},
|
284
|
-
"adc_sensor_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
|
285
|
-
"adc_sensor_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO},
|
286
|
-
"adc_sensor_libretiny.cpp": {
|
287
|
-
PlatformFramework.BK72XX_ARDUINO,
|
288
|
-
PlatformFramework.RTL87XX_ARDUINO,
|
289
|
-
PlatformFramework.LN882X_ARDUINO,
|
290
|
-
},
|
291
|
-
"adc_sensor_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR},
|
292
|
-
}
|
293
|
-
)
|
esphome/components/adc/sensor.py
CHANGED
@@ -9,6 +9,7 @@ from esphome.components.zephyr import (
|
|
9
9
|
zephyr_add_prj_conf,
|
10
10
|
zephyr_add_user,
|
11
11
|
)
|
12
|
+
from esphome.config_helpers import filter_source_files_from_platform
|
12
13
|
import esphome.config_validation as cv
|
13
14
|
from esphome.const import (
|
14
15
|
CONF_ATTENUATION,
|
@@ -20,6 +21,7 @@ from esphome.const import (
|
|
20
21
|
PLATFORM_NRF52,
|
21
22
|
STATE_CLASS_MEASUREMENT,
|
22
23
|
UNIT_VOLT,
|
24
|
+
PlatformFramework,
|
23
25
|
)
|
24
26
|
from esphome.core import CORE
|
25
27
|
|
@@ -174,3 +176,21 @@ async def to_code(config):
|
|
174
176
|
}};
|
175
177
|
"""
|
176
178
|
)
|
179
|
+
|
180
|
+
|
181
|
+
FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
182
|
+
{
|
183
|
+
"adc_sensor_esp32.cpp": {
|
184
|
+
PlatformFramework.ESP32_ARDUINO,
|
185
|
+
PlatformFramework.ESP32_IDF,
|
186
|
+
},
|
187
|
+
"adc_sensor_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
|
188
|
+
"adc_sensor_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO},
|
189
|
+
"adc_sensor_libretiny.cpp": {
|
190
|
+
PlatformFramework.BK72XX_ARDUINO,
|
191
|
+
PlatformFramework.RTL87XX_ARDUINO,
|
192
|
+
PlatformFramework.LN882X_ARDUINO,
|
193
|
+
},
|
194
|
+
"adc_sensor_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR},
|
195
|
+
}
|
196
|
+
)
|
@@ -42,6 +42,8 @@ static constexpr uint8_t MAX_PING_RETRIES = 60;
|
|
42
42
|
static constexpr uint16_t PING_RETRY_INTERVAL = 1000;
|
43
43
|
static constexpr uint32_t KEEPALIVE_DISCONNECT_TIMEOUT = (KEEPALIVE_TIMEOUT_MS * 5) / 2;
|
44
44
|
|
45
|
+
static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION);
|
46
|
+
|
45
47
|
static const char *const TAG = "api.connection";
|
46
48
|
#ifdef USE_CAMERA
|
47
49
|
static const int CAMERA_STOP_STREAM = 5000;
|
@@ -1081,12 +1083,6 @@ void APIConnection::on_get_time_response(const GetTimeResponse &value) {
|
|
1081
1083
|
}
|
1082
1084
|
#endif
|
1083
1085
|
|
1084
|
-
bool APIConnection::send_get_time_response(const GetTimeRequest &msg) {
|
1085
|
-
GetTimeResponse resp;
|
1086
|
-
resp.epoch_seconds = ::time(nullptr);
|
1087
|
-
return this->send_message(resp, GetTimeResponse::MESSAGE_TYPE);
|
1088
|
-
}
|
1089
|
-
|
1090
1086
|
#ifdef USE_BLUETOOTH_PROXY
|
1091
1087
|
void APIConnection::subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) {
|
1092
1088
|
bluetooth_proxy::global_bluetooth_proxy->subscribe_api_connection(this, msg.flags);
|
@@ -1376,9 +1372,8 @@ bool APIConnection::send_hello_response(const HelloRequest &msg) {
|
|
1376
1372
|
HelloResponse resp;
|
1377
1373
|
resp.api_version_major = 1;
|
1378
1374
|
resp.api_version_minor = 12;
|
1379
|
-
//
|
1380
|
-
|
1381
|
-
resp.set_server_info(StringRef(server_info));
|
1375
|
+
// Send only the version string - the client only logs this for debugging and doesn't use it otherwise
|
1376
|
+
resp.set_server_info(ESPHOME_VERSION_REF);
|
1382
1377
|
resp.set_name(StringRef(App.get_name()));
|
1383
1378
|
|
1384
1379
|
#ifdef USE_API_PASSWORD
|
@@ -1425,8 +1420,6 @@ bool APIConnection::send_device_info_response(const DeviceInfoRequest &msg) {
|
|
1425
1420
|
std::string mac_address = get_mac_address_pretty();
|
1426
1421
|
resp.set_mac_address(StringRef(mac_address));
|
1427
1422
|
|
1428
|
-
// Compile-time StringRef constants
|
1429
|
-
static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION);
|
1430
1423
|
resp.set_esphome_version(ESPHOME_VERSION_REF);
|
1431
1424
|
|
1432
1425
|
resp.set_compilation_time(App.get_compilation_time_ref());
|
@@ -219,7 +219,6 @@ class APIConnection final : public APIServerConnection {
|
|
219
219
|
#ifdef USE_API_HOMEASSISTANT_STATES
|
220
220
|
void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) override;
|
221
221
|
#endif
|
222
|
-
bool send_get_time_response(const GetTimeRequest &msg) override;
|
223
222
|
#ifdef USE_API_SERVICES
|
224
223
|
void execute_service(const ExecuteServiceRequest &msg) override;
|
225
224
|
#endif
|
@@ -921,14 +921,6 @@ bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
|
921
921
|
}
|
922
922
|
return true;
|
923
923
|
}
|
924
|
-
void GetTimeResponse::encode(ProtoWriteBuffer buffer) const {
|
925
|
-
buffer.encode_fixed32(1, this->epoch_seconds);
|
926
|
-
buffer.encode_string(2, this->timezone_ref_);
|
927
|
-
}
|
928
|
-
void GetTimeResponse::calculate_size(ProtoSize &size) const {
|
929
|
-
size.add_fixed32(1, this->epoch_seconds);
|
930
|
-
size.add_length(1, this->timezone_ref_.size());
|
931
|
-
}
|
932
924
|
#ifdef USE_API_SERVICES
|
933
925
|
void ListEntitiesServicesArgument::encode(ProtoWriteBuffer buffer) const {
|
934
926
|
buffer.encode_string(1, this->name_ref_);
|
esphome/components/api/api_pb2.h
CHANGED
@@ -1180,10 +1180,6 @@ class GetTimeResponse final : public ProtoDecodableMessage {
|
|
1180
1180
|
#endif
|
1181
1181
|
uint32_t epoch_seconds{0};
|
1182
1182
|
std::string timezone{};
|
1183
|
-
StringRef timezone_ref_{};
|
1184
|
-
void set_timezone(const StringRef &ref) { this->timezone_ref_ = ref; }
|
1185
|
-
void encode(ProtoWriteBuffer buffer) const override;
|
1186
|
-
void calculate_size(ProtoSize &size) const override;
|
1187
1183
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
1188
1184
|
void dump_to(std::string &out) const override;
|
1189
1185
|
#endif
|
@@ -1113,13 +1113,7 @@ void GetTimeRequest::dump_to(std::string &out) const { out.append("GetTimeReques
|
|
1113
1113
|
void GetTimeResponse::dump_to(std::string &out) const {
|
1114
1114
|
MessageDumpHelper helper(out, "GetTimeResponse");
|
1115
1115
|
dump_field(out, "epoch_seconds", this->epoch_seconds);
|
1116
|
-
out
|
1117
|
-
if (!this->timezone_ref_.empty()) {
|
1118
|
-
out.append("'").append(this->timezone_ref_.c_str()).append("'");
|
1119
|
-
} else {
|
1120
|
-
out.append("'").append(this->timezone).append("'");
|
1121
|
-
}
|
1122
|
-
out.append("\n");
|
1116
|
+
dump_field(out, "timezone", this->timezone);
|
1123
1117
|
}
|
1124
1118
|
#ifdef USE_API_SERVICES
|
1125
1119
|
void ListEntitiesServicesArgument::dump_to(std::string &out) const {
|
@@ -160,15 +160,6 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
|
|
160
160
|
break;
|
161
161
|
}
|
162
162
|
#endif
|
163
|
-
case GetTimeRequest::MESSAGE_TYPE: {
|
164
|
-
GetTimeRequest msg;
|
165
|
-
// Empty message: no decode needed
|
166
|
-
#ifdef HAS_PROTO_MESSAGE_DUMP
|
167
|
-
ESP_LOGVV(TAG, "on_get_time_request: %s", msg.dump().c_str());
|
168
|
-
#endif
|
169
|
-
this->on_get_time_request(msg);
|
170
|
-
break;
|
171
|
-
}
|
172
163
|
case GetTimeResponse::MESSAGE_TYPE: {
|
173
164
|
GetTimeResponse msg;
|
174
165
|
msg.decode(msg_data, msg_size);
|
@@ -656,11 +647,6 @@ void APIServerConnection::on_subscribe_home_assistant_states_request(const Subsc
|
|
656
647
|
}
|
657
648
|
}
|
658
649
|
#endif
|
659
|
-
void APIServerConnection::on_get_time_request(const GetTimeRequest &msg) {
|
660
|
-
if (this->check_connection_setup_() && !this->send_get_time_response(msg)) {
|
661
|
-
this->on_fatal_error();
|
662
|
-
}
|
663
|
-
}
|
664
650
|
#ifdef USE_API_SERVICES
|
665
651
|
void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest &msg) {
|
666
652
|
if (this->check_authenticated_()) {
|
@@ -71,7 +71,7 @@ class APIServerConnectionBase : public ProtoService {
|
|
71
71
|
#ifdef USE_API_HOMEASSISTANT_STATES
|
72
72
|
virtual void on_home_assistant_state_response(const HomeAssistantStateResponse &value){};
|
73
73
|
#endif
|
74
|
-
|
74
|
+
|
75
75
|
virtual void on_get_time_response(const GetTimeResponse &value){};
|
76
76
|
|
77
77
|
#ifdef USE_API_SERVICES
|
@@ -226,7 +226,6 @@ class APIServerConnection : public APIServerConnectionBase {
|
|
226
226
|
#ifdef USE_API_HOMEASSISTANT_STATES
|
227
227
|
virtual void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) = 0;
|
228
228
|
#endif
|
229
|
-
virtual bool send_get_time_response(const GetTimeRequest &msg) = 0;
|
230
229
|
#ifdef USE_API_SERVICES
|
231
230
|
virtual void execute_service(const ExecuteServiceRequest &msg) = 0;
|
232
231
|
#endif
|
@@ -348,7 +347,6 @@ class APIServerConnection : public APIServerConnectionBase {
|
|
348
347
|
#ifdef USE_API_HOMEASSISTANT_STATES
|
349
348
|
void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) override;
|
350
349
|
#endif
|
351
|
-
void on_get_time_request(const GetTimeRequest &msg) override;
|
352
350
|
#ifdef USE_API_SERVICES
|
353
351
|
void on_execute_service_request(const ExecuteServiceRequest &msg) override;
|
354
352
|
#endif
|
esphome/components/api/client.py
CHANGED
@@ -62,9 +62,11 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None:
|
|
62
62
|
time_ = datetime.now()
|
63
63
|
message: bytes = msg.message
|
64
64
|
text = message.decode("utf8", "backslashreplace")
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
nanoseconds = time_.microsecond // 1000
|
66
|
+
timestamp = (
|
67
|
+
f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}.{nanoseconds:03}]"
|
68
|
+
)
|
69
|
+
for parsed_msg in parse_log_message(text, timestamp):
|
68
70
|
print(parsed_msg.replace("\033", "\\033") if dashboard else parsed_msg)
|
69
71
|
|
70
72
|
stop = await async_run(cli, on_log, name=name)
|
@@ -130,7 +130,9 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, publ
|
|
130
130
|
|
131
131
|
std::string get_bluetooth_mac_address_pretty() {
|
132
132
|
const uint8_t *mac = esp_bt_dev_get_address();
|
133
|
-
|
133
|
+
char buf[18];
|
134
|
+
format_mac_addr_upper(mac, buf);
|
135
|
+
return std::string(buf);
|
134
136
|
}
|
135
137
|
|
136
138
|
protected:
|