1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-13 14:18:14 +00:00

scan for nodes with mac_suffix

This commit is contained in:
Mischa Siekmann 2025-01-04 21:13:47 +01:00
parent 387bde665e
commit 4e8deb8232
2 changed files with 60 additions and 4 deletions

View File

@ -51,6 +51,8 @@ from esphome.util import (
safe_print,
)
from esphome.zeroconf import get_mac_suffix_nodes
_LOGGER = logging.getLogger(__name__)
@ -95,9 +97,13 @@ def choose_upload_log_host(
if default == "SERIAL":
return choose_prompt(options, purpose=purpose)
if (show_ota and "ota" in CORE.config) or (show_api and "api" in CORE.config):
options.append((f"Over The Air ({CORE.address})", CORE.address))
if default == "OTA":
return CORE.address
if CORE.config["esphome"]["name_add_mac_suffix"] :
for addr in get_mac_suffix_nodes(CORE.config["esphome"]["name"]):
options.append((f"Over The Air ({addr})", addr))
else:
options.append((f"Over The Air ({CORE.address})", CORE.address))
if default == "OTA":
return CORE.address
if (
show_mqtt
and (mqtt_config := CORE.config.get(CONF_MQTT))

View File

@ -2,8 +2,9 @@ from __future__ import annotations
import asyncio
from dataclasses import dataclass
import time
import logging
from typing import Callable
from typing import Callable, Optional
from zeroconf import IPVersion, ServiceInfo, ServiceStateChange, Zeroconf
from zeroconf.asyncio import AsyncServiceBrowser, AsyncServiceInfo, AsyncZeroconf
@ -199,3 +200,52 @@ class AsyncEsphomeZeroconf(AsyncZeroconf):
) and (addresses := info.parsed_scoped_addresses(IPVersion.All)):
return addresses
return None
NODE_SCAN_TIME_SEC = 2
class NodeScanner:
def __init__(self, node_raw_name: str) -> None:
self.node_raw_name = node_raw_name
self.aiobrowser: Optional[AsyncServiceBrowser] = None
self.aiozc: Optional[AsyncZeroconf] = None
self.found_nodes = []
def async_on_service_state_change(self,
zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange
) -> None:
if state_change is not ServiceStateChange.Added:
return
if name.startswith(self.node_raw_name):
self.found_nodes.append(name.split(".")[0] + ".local")
async def async_run(self) -> None:
self.aiozc = AsyncZeroconf(ip_version=IPVersion.V4Only)
services = ["_esphomelib._tcp.local."]
self.aiobrowser = AsyncServiceBrowser(
self.aiozc.zeroconf, services, handlers=[self.async_on_service_state_change]
)
start_time = time.time()
while time.time() - start_time < NODE_SCAN_TIME_SEC:
await asyncio.sleep(1)
await self.async_close()
async def async_close(self) -> None:
assert self.aiozc is not None
assert self.aiobrowser is not None
await self.aiobrowser.async_cancel()
await self.aiozc.async_close()
def get_mac_suffix_nodes(node_name:str) -> list[str]:
loop = asyncio.get_event_loop()
runner = NodeScanner(node_name)
try:
loop.run_until_complete(runner.async_run())
except KeyboardInterrupt:
loop.run_until_complete(runner.async_close())
return runner.found_nodes