"""Zeroconf-based discovery of WeatherLink Live services/devices in the local network(s)."""from__future__importannotationsimportloggingimporttimefromdataclassesimportdataclassimportzeroconflogger=logging.getLogger(__name__)
[docs]@dataclassclassServiceInfo:"""WeatherLink Live service information."""name:str#: Unique name of serviceip_addresses:list[str]#: IP address of device, usually only oneport:int#: Port number, usually 80
[docs]classDiscovery(zeroconf.ServiceListener):""" Discovery for all WeatherLink Live services on local network(s). """TYPE="_weatherlinklive._tcp.local."
# pylint: disable=unused-argumentdefadd_service(self,zc:zeroconf.Zeroconf,type_:str,name:str)->None:# noqa: ARG002logger.info("Found WeatherLink Live service '%s'",name)self.services.add(name)defremove_service(self,zc:zeroconf.Zeroconf,type_:str,name:str)->None:...defupdate_service(self,zc:zeroconf.Zeroconf,type_:str,name:str)->None:...@classmethoddeffind(cls,timeout:float)->list[ServiceInfo]:zc=zeroconf.Zeroconf()listener=cls()browser=zeroconf.ServiceBrowser(zc,cls.TYPE,listener=listener)time.sleep(timeout)# wait for responsesdefget_service_infos():fornameinsorted(listener.services):zc_service_info=zc.get_service_info(cls.TYPE,name)yieldServiceInfo(name=zc_service_info.name,ip_addresses=zc_service_info.parsed_addresses(),port=zc_service_info.port,)service_infos=list(get_service_infos())browser.cancel()zc.close()returnservice_infos