def _add(devices: dict[str, Device], zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange) -> None: """Create a device object to each matching device.""" if state_change is not ServiceStateChange.Added: return if (service_info := zeroconf.get_service_info(service_type, name)) is None: return
class Discoverer: ANNOUNCE_PERIOD_SECS = 1 MAXIMUM_WAIT_CYCLES = 10 SERVICE_TYPE = "_googlemdt._tcp.local." def __init__(self, listener=None): self.discoveries = {} self.listener = listener self.zeroconf = None def discover(self): self.zeroconf = Zeroconf() self.browser = ServiceBrowser(self.zeroconf, Discoverer.SERVICE_TYPE, self) self._heard_announcement = True cycle_count = 0 # Keep waiting until we stop hearing announcements for a full second, or until we've waited 10 seconds while self._heard_announcement and cycle_count < Discoverer.MAXIMUM_WAIT_CYCLES: cycle_count += 1 self._heard_announcement = False time.sleep(Discoverer.ANNOUNCE_PERIOD_SECS) self.browser.cancel() self.browser = None self.zeroconf = None def add_service(self, zeroconf, type, name): info = self.zeroconf.get_service_info(type, name) if info: hostname = info.server.split('.')[0] address = info.parsed_addresses()[0] # Prevent duplicate announcements from extending the discovery delay if hostname not in self.discoveries: self._heard_announcement = True self.discoveries[hostname] = address if self.listener and hasattr(self.listener, "add_device"): self.listener.add_device(hostname, address) def remove_service(self, zeroconf, type, name): info = self.zeroconf.get_service_info(type, name) if info: if self.listener and hasattr(self.listener, "remove_device"): self.listener.remove_device(info.server, self.discoveries[info.server]) if info.server in self.discoveries: self._heard_announcement = True del (self.discoveries[info.server]) def update_service(self, zeroconf, type, name): """TODO(jtgans): Add this method once zeroconf figures out what it's for.""" pass
def test_service_browser_is_aware_of_port_changes(): """Test that the ServiceBrowser is aware of port changes.""" # instantiate a zeroconf instance zc = Zeroconf(interfaces=['127.0.0.1']) # start a browser type_ = "_hap._tcp.local." registration_name = "xxxyyy.%s" % type_ callbacks = [] # dummy service callback def on_service_state_change(zeroconf, service_type, state_change, name): nonlocal callbacks if name == registration_name: callbacks.append((service_type, state_change, name)) browser = ServiceBrowser(zc, type_, [on_service_state_change]) desc = {'path': '/~paulsm/'} address_parsed = "10.0.1.2" address = socket.inet_aton(address_parsed) info = ServiceInfo(type_, registration_name, 80, 0, 0, desc, "ash-2.local.", addresses=[address]) def mock_incoming_msg(records) -> r.DNSIncoming: generated = r.DNSOutgoing(const._FLAGS_QR_RESPONSE) for record in records: generated.add_answer_at_time(record, 0) return r.DNSIncoming(generated.packets()[0]) _inject_response( zc, mock_incoming_msg([info.dns_pointer(), info.dns_service(), info.dns_text(), *info.dns_addresses()]), ) zc.wait(100) assert callbacks == [('_hap._tcp.local.', ServiceStateChange.Added, 'xxxyyy._hap._tcp.local.')] assert zc.get_service_info(type_, registration_name).port == 80 info.port = 400 _inject_response( zc, mock_incoming_msg([info.dns_service()]), ) zc.wait(100) assert callbacks == [ ('_hap._tcp.local.', ServiceStateChange.Added, 'xxxyyy._hap._tcp.local.'), ('_hap._tcp.local.', ServiceStateChange.Updated, 'xxxyyy._hap._tcp.local.'), ] assert zc.get_service_info(type_, registration_name).port == 400 browser.cancel() zc.close()
class ServiceDiscoveryClient: def __init__(self, service_timeout=None): self.zeroconf = Zeroconf() self.service_args = [SRV_TYPE, srv_fqname()] if service_timeout: self.service_args.append(service_timeout) @cached_property_with_ttl(ttl=1.0) def info(self): service_info = self.zeroconf.get_service_info(*self.service_args) if not service_info: raise ZeroconfServiceNotFound( "Pilotwire Controller Zeroconf service not found" ) return service_info @property def address(self): # pylint: disable=no-member return socket.inet_ntoa(self.info.address) @property def port(self): # pylint: disable=no-member return str(self.info.port)
def _fetch_fbx_mdns_info_via_mdns(self): print('Querying mDNS about Freebox Server information...') info = {} try: r = Zeroconf() serv_info = r.get_service_info( '_fbx-api._tcp.local.', 'Freebox Server._fbx-api._tcp.local.') info['api_domain'] = serv_info.properties[b'api_domain'].decode() info['https_available'] = True if serv_info.properties[ b'https_available'] == b'1' else False info['https_port'] = int(serv_info.properties[b'https_port']) info['api_base_url'] = serv_info.properties[ b'api_base_url'].decode() info['api_version'] = serv_info.properties[b'api_version'].decode() r.close() except Exception: print('Unable to retrieve configuration, assuming bridged mode') d = requests.get("http://mafreebox.freebox.fr/api_version") data = d.json() info['api_domain'] = data['api_domain'] info['https_available'] = data['https_available'] info['https_port'] = data['https_port'] info['api_base_url'] = data['api_base_url'] info['api_version'] = data['api_version'] return info
def discover_remotes_mdns(do_thread=False): zeroconf = Zeroconf() try: properties = zeroconf.get_service_info(TYPE, NAME + '.' + TYPE).properties for _ in properties: print('{}: {}'.format(_, properties[_])) hostname = properties[b'hostname'].decode("utf-8") user = properties[b'user'].decode("utf-8") interfaces = json.loads(properties[b'interfaces'].decode("utf-8")) adapters = json.loads(properties[b'adapters'].decode("utf-8")) data = { hostname: { 'interfaces': interfaces, 'adapters': adapters, 'user': user } } print(data) if do_thread: threading.Thread(target=update_local_cloud_file, args=(LOCAL_CLOUD_FILE, data), name='avahi_local_cache_update').start() else: print('no thread') x = update_local_cloud_file(LOCAL_CLOUD_FILE, data) except AttributeError: pass finally: zeroconf.close()
class ServiceListener(object): def __init__(self): # Is this necessary, when zeroconf is being passed into add_service? self.zconf = Zeroconf() self.services = [] def remove_service(self, zeroconf, service_type, name): print "Not implemented." return True def add_service(self, zeroconf, service_type, name): this_service = {} this_service['name'] = name this_service['service_type'] = service_type this_service['address'] = '' this_service['server'] = '' info = self.zconf.get_service_info(service_type, name) if info: this_service['address'] = "%s:%d" % (socket.inet_ntoa(info.address), info.port) # Construct the link by finding service type in service_types object; or use http if not found in list. this_service['link'] = "%s%s" % (proto_dict.get(service_type, proto_dict['_http._tcp.local.']), this_service['address']) this_service['server'] = info.server # prop = info.getProperties() # if prop: # print " Properties are" # for key, value in prop.items(): # print " %s: %s" % (key, value) self.services.append(this_service)
def _onServiceAdded(self, zero_conf: Zeroconf, service_type: str, name: str) -> bool: # First try getting info from zero-conf cache info = ServiceInfo(service_type, name, properties={}) for record in zero_conf.cache.entries_with_name(name.lower()): info.update_record(zero_conf, time(), record) for record in zero_conf.cache.entries_with_name(info.server): info.update_record(zero_conf, time(), record) if info.address: break # Request more data if info is not complete if not info.address: info = zero_conf.get_service_info(service_type, name) if info: type_of_device = info.properties.get(b"type", None) if type_of_device: if type_of_device == b"printer": address = '.'.join(map(lambda n: str(n), info.address)) self.addedNetworkCluster.emit(str(name), address, info.properties) else: Logger.log( "w", "The type of the found device is '%s', not 'printer'." % type_of_device) else: Logger.log("w", "Could not get information about %s" % name) return False return True
def main(): # ToDo: test for arguments (out of bounds) firmFile = sys.argv[1] sha256_hash = hashlib.sha256() with open("/root/files/" + firmFile, "rb") as f: # Read and update hash string value in blocks of 4K for byte_block in iter(lambda: f.read(4096), b""): sha256_hash.update(byte_block) fHash = sha256_hash.hexdigest() ota_data = { 'downloadUrl': 'http://192.168.254.1/files/' + firmFile, 'sha256sum': fHash } zeroconf = Zeroconf() listener = MyListener() browser = ServiceBrowser(zeroconf, "_ewelink._tcp.local.", listener=listener) print("Waiting for device (mDNS...)") while True: if listener.all_sub_num > 0: dict = listener.all_info_dict.copy() for x in dict.keys(): info = dict[x] info = zeroconf.get_service_info(info.type, x) if info != None: nodeId = x[8:18] ipAddr = parseAddress(info.address) port = str(info.port) #startFlash(nodeId, ipAddr, port) break time.sleep(0.5) print("Tasmotizing: ", nodeId) baseURL = "http://" + ipAddr + ":" + port + "/zeroconf" data = {"deviceid": nodeId, "data": {}} print(" Turn on switch") url = baseURL + "/switch" datasw = {"deviceid": nodeId, "data": {"switch": "on"}} r = requests.post(url=url, json=datasw) ## check info to know about OTA status url = baseURL + "/info" print(" Check OTA: ", url) r = requests.post(url=url, json=data) rJ = json.loads(r.json()['data']) if rJ['otaUnlock']: print(" OTA already unlocked") else: url = baseURL + "/ota_unlock" print(" Unlocking OTA ", url) r = requests.post(url=url, json=data) ## need to verify return here. print(" Sending binary URL: ", ota_data) otaD = data otaD['data'] = ota_data url = baseURL + "/ota_flash" r = requests.post(url=url, json=otaD) print(" r = ", r.json())
def _on_service_state_change(self, zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange): """ Service handler for Zeroconf state changes. """ if state_change is ServiceStateChange.Added: service_info = zeroconf.get_service_info(service_type, name) if service_info.server.startswith("devolo-homecontrol"): self._try_local_connection(service_info.addresses)
def on_service_state_change(zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange) -> None: print("Service %s of type %s state changed: %s" % (name, service_type, state_change)) if state_change is ServiceStateChange.Added: info = zeroconf.get_service_info(service_type, name) print("Info from zeroconf.get_service_info: %r" % (info)) if info: addresses = [ "%s:%d" % (socket.inet_ntoa(addr), cast(int, info.port)) for addr in info.addresses ] print(" Addresses: %s" % ", ".join(addresses)) print(" Weight: %d, priority: %d" % (info.weight, info.priority)) print(" Server: %s" % (info.server, )) if info.properties: print(" Properties are:") for key, value in info.properties.items(): print(" %s: %s" % (key, value)) else: print(" No properties") else: print(" No info") print('\n')
def discover_mqtt_host(): from zeroconf import ServiceBrowser, Zeroconf host = None info = None def on_service_state_change(zeroconf, service_type, name, state_change): pass zeroconf = Zeroconf() browser = ServiceBrowser(zeroconf, "_mqtt._tcp.local.", handlers=[on_service_state_change]) i = 0 while not host: time.sleep(0.1) if browser.services: service = list(browser.services.values())[0] info = zeroconf.get_service_info(service.name, service.alias) ##print('info', info) ##print('info.server', info.server) host = socket.inet_ntoa(info.address) i += 1 if i > 50: break zeroconf.close() try: return info.server, host except: pass return None
def update_service(self, zeroconf: Zeroconf, type_: str, name: str): """Событие Zeroconf, которое вызывается при изменении состояния устройства. """ _LOGGER.debug(f"Update service {name}") info = zeroconf.get_service_info(type_, name) properties = { k.decode(): v.decode() if isinstance(v, bytes) else v for k, v in info.properties.items() } _LOGGER.debug(f"Properties: {properties}") # for some users devices send updates several times if self._seq == properties['seq']: return self._seq = properties['seq'] if properties.get('encrypt'): data = utils.decrypt(properties, self.config['devicekey']) # Fix Sonoff RF Bridge sintax bug if data.startswith(b'{"rf'): data = data.replace(b'"="', b'":"') else: data = ''.join([properties[f'data{i}'] for i in range(1, 4, 1) if f'data{i}' in properties]) self.state = json.loads(data) _LOGGER.debug(f"State: {self.state}") for handler in self._update_handlers: handler(self)
def update_service(self, zeroconf: Zeroconf, type: str, name: str) -> None: info = zeroconf.get_service_info(type, name) if info.properties.get(b'encrypt'): iv = info.properties.get(b'iv') data1 = info.properties.get(b'data1') if len(data1) == 249: data2 = info.properties.get(b'data2') data1 += data2 if len(data2) == 249: data3 = info.properties.get(b'data3') data1 += data3 if len(data3) == 249: data4 = info.properties.get(b'data4') data1 += data4 self.handle_encrypted_message(bytes(data1), bytes(iv)) self._encrypted = True else: data = info.properties.get(b'data1') self.handle_message(bytes(data)) self._encrypted = False
def discover_host(): """ Automatically discover WiFi ZiGate using zeroconf only compatible with WiFi firmware 2.x """ from zeroconf import ServiceBrowser, Zeroconf host = None def on_service_state_change(zeroconf, service_type, name, state_change): pass zeroconf = Zeroconf() browser = ServiceBrowser(zeroconf, "_zigate._tcp.local.", handlers=[on_service_state_change]) i = 0 while not host: time.sleep(0.1) if browser.services: service = list(browser.services.values())[0] info = zeroconf.get_service_info(service.name, service.alias) host = socket.inet_ntoa(info.address) i += 1 if i > 50: break zeroconf.close() return host
def add_service(self, zeroconf: Zeroconf, type_: str, name: str): """Стандартная функция ServiceBrowser.""" _LOGGER.debug(f"Add service {name}") info = zeroconf.get_service_info(type_, name) properties = { k.decode(): v.decode() if isinstance(v, bytes) else v for k, v in info.properties.items() } _LOGGER.debug(f"Properties: {properties}") deviceid = properties['deviceId'] device = next((p for p in self.devices if p['id'] == deviceid), None) if device: _LOGGER.info(f"Found Yandex device {deviceid}") device['host'] = str(ipaddress.ip_address(info.address)) device['port'] = info.port self._add_device(device) else: _LOGGER.warning(f"Device {deviceid} not found in Yandex account.")
def resolve_zeroconf_ip(service_name: str) -> str: """ Resolve Zeroconf service IPv4 address. Args: service_name(str): Zeroconf service name Returns: str: IPv4 address """ zc = Zeroconf() try: if not service_name.endswith('.'): service_name += '.' p = service_name.split('.') service_type = '.'.join(p[1:]) info = zc.get_service_info(service_type, service_name) if info is None: raise Exception( f'Failed to resolve zeroconf service {service_name}') addresses = info.addresses_by_version(zeroconf.IPVersion.V4Only) if len(addresses) == 0: raise Exception( f'Failed to resolve zeroconf service to IPv4 address {service_name}' ) addr = socket.inet_ntoa(addresses[0]) return addr except Exception as err: raise err finally: zc.close()
def main(): zeroconf = Zeroconf() listener = MyListener() browser = ServiceBrowser(zeroconf, "_ewelink._tcp.local.", listener=listener) #EspBuddy Addition ###################### >>> stop = 0 #EspBuddy Addition ###################### <<< while True: if listener.all_sub_num > 0: dict = listener.all_info_dict.copy() for x in dict.keys(): info = dict[x] info = zeroconf.get_service_info(info.type, x) if info != None: data = info.properties cur_str = x[8:18] + " " + parseAddress( info.address) + " " + str( info.port) + " " + str(data) print(cur_str) if len(listener.all_del_sub) > 0: for x in listener.all_del_sub: cur_str = x[8:18] + "\nDEL" print(cur_str) time.sleep(0.5) #EspBuddy Addition ###################### >>> stop = stop + 1 if stop > 5: break
def _fetch_fbx_mdns_info_via_mdns(self): print('Querying mDNS about Freebox Server information...') r = Zeroconf() info = r.get_service_info('_fbx-api._tcp.local.', 'Freebox Server._fbx-api._tcp.local.') r.close() return info
def _zeroconf_handler(self, zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange): if state_change != ServiceStateChange.Added: return info = zeroconf.get_service_info(service_type, name) properties = { k.decode(): v.decode() if isinstance(v, bytes) else v for k, v in info.properties.items() } device_id = properties['deviceId'] if device_id in self.processed: return self.processed.append(device_id) coro = self.add_handlerer({ 'device_id': device_id, 'platform': properties['platform'], 'host': str(ipaddress.ip_address(info.addresses[0])), 'port': info.port }) self.loop.create_task(coro)
def _zeroconf_on_service_state_change( self, zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange, ) -> None: """ Look for Wiser Hub in discovered services and set IP and Name in global vars """ if state_change is ServiceStateChange.Added: if "WiserHeat" in name: info = zeroconf.get_service_info(service_type, name) if info: addresses = [ "%s:%d" % (addr, cast(int, info.port)) for addr in info.parsed_addresses() ] hub = _WiserDiscoveredHub( ip = addresses[0].replace(":80", ""), hostname = info.server.replace(".local.", ".local").lower(), name = info.server.replace(".local.", ""), ) _LOGGER.debug( "Discovered Hub {} with IP Address {}".format( info.server.replace(".local.", ""), addresses[0].replace(":80", ""), ) ) self._discovered_hubs.append(hub)
def get_zeroconf_server_address(): zerocfg = Zeroconf() service_info = zerocfg.get_service_info("_snapcast._tcp.local.", "Snapcast._snapcast._tcp.local.", 3000) if service_info is None: logging.error("Failed to obtain snapserver address through zeroconf!") return None logging.debug(service_info) snapserver_address = None all_addresses = service_info.parsed_addresses(IPVersion.V4Only) for address in all_addresses: if address != "0.0.0.0": snapserver_address = address if snapserver_address is None: logging.critical( "Failed to obtain snapserver address through zeroconf, got 0.0.0.0 but expected real address!" ) logging.error(service_info) logging.error(all_addresses) return None if len(all_addresses) > 1: logging.warning( "Got more than one zeroconf address, what's happening here?!") logging.warning(service_info) logging.warning(all_addresses) logging.info("Obtained snapserver address through zeroconf: " + snapserver_address) return snapserver_address
class mDNS_BrowserThread(QThread): """ This is a QT thread that gets the MDNS information and sends it to the UI thread via the get_sub_new signal. """ get_sub_new = Signal(str) def __init__(self, parent=None, **func_task): super(mDNS_BrowserThread, self).__init__(parent) self.ID_list = [] self.zeroconf = Zeroconf() self.listener = MyListener() def __def__(self): self.wait() def run(self): """ The data of the searched device is refreshed every second, and each update is converted into a string and sent to the interface(name ip port data) """ print("mDNS_BrowserThread start !") browser = ServiceBrowser(self.zeroconf, "_ewelink._tcp.local.", listener=self.listener) while True: if self.listener.all_sub_num > 0: # Copy from the listener's dictionary to the current file dict = self.listener.all_info_dict.copy() for x in dict.keys(): # print("new updata ID:",x[8:18]) info = dict[x] info = self.zeroconf.get_service_info(info.type, x) print("updata", x, "info", "len", len(str(info)), info) if info is not None: data = info.properties cur_str = x[8:18] + "\n" + self.parseAddress( info.address) + "\n" + str( info.port) + "\n" + str(data) self.get_sub_new.emit(cur_str) # Send deleted devices if len(self.listener.all_del_sub) > 0: for x in self.listener.all_del_sub: cur_str = x[8:18] + "\nDEL" self.get_sub_new.emit(cur_str) time.sleep(0.5) def parseAddress(self, address): """ Resolve the IP address of the device :param address: :return: add_str """ add_list = [] for i in range(4): add_list.append(int(address.hex()[(i * 2):(i + 1) * 2], 16)) add_str = str(add_list[0]) + "." + str(add_list[1]) + \ "." + str(add_list[2]) + "." + str(add_list[3]) return add_str
def zeroconf_without_service_info(mocker): from zeroconf import Zeroconf zeroconf_stub = mocker.stub(name='get_service_info') zeroconf_stub.return_value = None stub_object = Zeroconf() stub_object.get_service_info = zeroconf_stub return stub_object
def add_service(self, zeroconf: Zeroconf, service_type: str, name: str) -> None: info:Dict[str,Any] = self._parse(zeroconf.get_service_info(service_type, name)) if info: if self._sid == info['id']: self._device = info self.searching.set() else: self._devices_list.append(info)
def add_service(self, zeroconf: Zeroconf, conf_type: str, name: str): """New Revolution Pi found.""" pi.logger.debug("AvahiSearchThread.add_service") info = zeroconf.get_service_info(conf_type, name) if not info: return for ip in info.parsed_addresses(IPVersion.V4Only): self.added.emit(name, info.server, info.port, conf_type, ip)
def _zeroconf_handler(self, zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange): """Стандартная функция ServiceBrowser.""" if state_change == ServiceStateChange.Removed: _LOGGER.debug(f"Local2 <= {name}") # TODO: handle removed return info = zeroconf.get_service_info(service_type, name) properties = { k.decode(): v.decode() if isinstance(v, bytes) else v for k, v in info.properties.items() } deviceid = properties['id'] device = self._devices.setdefault(deviceid, {}) if properties.get('encrypt'): devicekey = device.get('devicekey') if devicekey == 'skip': return if not devicekey: _LOGGER.warning(f"No devicekey for device {deviceid}") # skip device next time device['devicekey'] = 'skip' return data = decrypt(properties, devicekey) # Fix Sonoff RF Bridge sintax bug if data.startswith(b'{"rf'): data = data.replace(b'"="', b'":"') else: data = ''.join([properties[f'data{i}'] for i in range(1, 4, 1) if f'data{i}' in properties]) state = json.loads(data) _LOGGER.debug(f"Local{state_change.value} <= id: {properties['id']}, " f"seq: {properties.get('seq')} | {state}") host = str(ipaddress.ip_address(info.addresses[0])) # update every time device host change (alsow first time) if device.get('host') != host: # state connection for attrs update state['connection'] = 'local' # device host for local connection, state host for attrs update device['host'] = state['host'] = host # override device type with: strip, plug, light, rf device['type'] = properties['type'] # update or set device init state if 'params' in device: device['params'].update(state) else: device['params'] = state for handler in self._handlers: handler(deviceid, state, properties.get('seq'))
def zeroconf(mocker): from zeroconf import Zeroconf service_info = ServiceInfoFactory().create() zeroconf_stub = mocker.stub(name='get_service_info') zeroconf_stub.return_value = service_info stub_object = Zeroconf() stub_object.get_service_info = zeroconf_stub return stub_object
def on_service_state_change(self, zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange) -> None: #when a new mDNS service is added or updated get info on service if state_change is ServiceStateChange.Added or state_change is ServiceStateChange.Updated: info = zeroconf.get_service_info(service_type, name) #if service info exists and contains hrbeacon type property then process it if info: try: type = info.properties[b'type'] if 'nordin' in type.decode('UTF-8'): #get ip/port of printer addresses = ["%s" % (socket.inet_ntoa(addr)) for addr in info.addresses] port = [(cast(int, info.port)) for addr in info.addresses] #get printer info hostname = info.properties[b'name'].decode('UTF-8') series = info.properties[b'series'].decode('UTF-8') version = info.properties[b'version'].decode('UTF-8') #add printers to dictionary printerInfo = {"address": addresses[0], "stat": -1, "port": port[0], "series": series, "version": version} self.services[name] = info self.timestamps[name] = time.time() if type == b'nordin_printer': self.printers[hostname] = printerInfo print("PRINTER: {}: {} at {}".format(state_change, hostname, addresses)) elif type == b'nordin_device': self.devices[hostname] = printerInfo print("DEVICE: {}: {} at {}".format(state_change, hostname, addresses)) else: print("NOT ADDED: {}: {} at {}".format(state_change, hostname, addresses)) #print data #print("{}: {} at {}".format(state_change, hostname, addresses)) #print(" Hardware Series:{}".format(series)) #print(" Hardware Version:{}".format(version)) except KeyError: pass elif state_change is ServiceStateChange.Removed: try: #hostname = self.services[name] hostname = self.services[name].properties[b'name'].decode('UTF-8') #try removing as printer try: del self.printers[hostname] except KeyError: pass #else try removing as device try: del self.devices[hostname] except KeyError: pass del self.services[name] del self.timestamps[name] print("Removed: {}".format(hostname)) except KeyError: pass
def _on_service_state_change(self, zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange): """ Service handler for Zeroconf state changes. """ if state_change is ServiceStateChange.Added: service_info = zeroconf.get_service_info(service_type, name) if service_info and service_info.server.startswith( "devolo-homecontrol"): with contextlib.suppress(requests.exceptions.ReadTimeout), \ contextlib.suppress(requests.exceptions.ConnectTimeout): self._try_local_connection(service_info.addresses)
def get_zeroconf_server_stream_port(self): zerocfg = Zeroconf() service_info = zerocfg.get_service_info("_snapcast._tcp.local.", "Snapcast._snapcast._tcp.local.", 3000) logging.debug(service_info) if service_info is None or service_info.parsed_addresses(IPVersion.All)[0] != self.server_address: logging.warning("Failed to obtain snapserver streaming port through zeroconf!") return 1704 logging.info("Obtained snapserver streaming port through zeroconf: " + str(service_info.port)) return service_info.port
def on_service_state_change( zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange, ) -> None: if state_change is ServiceStateChange.Added: info = zeroconf.get_service_info(service_type, name) if info: if info.properties: open('SUs', 'a').write( info.properties[b'ipv6'].decode('UTF-8').split('%')[0])
def serviceStatus(): zeroconf = Zeroconf() info = zeroconf.get_service_info("_http._tcp.local.", "Takiyaki._http._tcp.local.") # If service registered # if info: return (socket.inet_ntoa(info.address), info.port) # No named service registered # else: print("Service doesn't exist") zeroconf.close()
def test_bonjour(self): 'Test advertising via BonJour' from calibre.srv.bonjour import BonJour if ispy3: from zeroconf import Zeroconf else: from calibre.utils.Zeroconf import Zeroconf b = BonJour(wait_for_stop=False) with TestServer(lambda data:(data.path[0] + data.read()), plugins=(b,), shutdown_timeout=5) as server: self.assertTrue(b.started.wait(5), 'BonJour not started') self.ae(b.advertised_port, server.address[1]) service = b.services[0] self.ae(service.type, '_calibre._tcp.local.') r = Zeroconf() info = r.get_service_info(service.type, service.name) self.assertIsNotNone(info) self.ae(info.text, b'\npath=/opds') self.assertTrue(b.stopped.wait(5), 'BonJour not stopped')
def on_service_state_change( zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange, ) -> None: print("Service %s of type %s state changed: %s" % (name, service_type, state_change)) if state_change is ServiceStateChange.Added: info = zeroconf.get_service_info(service_type, name) if info: print(" Address: %s:%d" % (socket.inet_ntoa(cast(bytes, info.address)), cast(int, info.port))) print(" Weight: %d, priority: %d" % (info.weight, info.priority)) print(" Server: %s" % (info.server,)) if info.properties: print(" Properties are:") for key, value in info.properties.items(): print(" %s: %s" % (key, value)) else: print(" No properties") else: print(" No info") print('\n')
def _fetch_fbx_mdns_info_via_mdns(self): print('Querying mDNS about Freebox Server information...') info = {} try: r = Zeroconf() serv_info = r.get_service_info('_fbx-api._tcp.local.', 'Freebox Server._fbx-api._tcp.local.') info['api_domain'] = serv_info.properties[b'api_domain'].decode() info['https_available'] = True if serv_info.properties[b'https_available'] == b'1' else False info['https_port'] = int(serv_info.properties[b'https_port']) info['api_base_url'] = serv_info.properties[b'api_base_url'].decode() info['api_version'] = serv_info.properties[b'api_version'].decode() r.close() except Exception: print('Unable to retrieve configuration, assuming bridged mode') d = requests.get("http://mafreebox.freebox.fr/api_version") data = d.json() info['api_domain'] = data['api_domain'] info['https_available'] = data['https_available'] info['https_port'] = data['https_port'] info['api_base_url'] = data['api_base_url'] info['api_version'] = data['api_version'] return info
def test_integration_with_listener_class(self): service_added = Event() service_removed = Event() type_ = "_http._tcp.local." name = "xxxyyy" registration_name = "%s.%s" % (name, type_) class MyListener(object): def add_service(self, zeroconf, type, name): zeroconf.get_service_info(type, name) service_added.set() def remove_service(self, zeroconf, type, name): service_removed.set() zeroconf_browser = Zeroconf() zeroconf_browser.add_service_listener(type_, MyListener()) properties = dict( prop_none=None, prop_string=b'a_prop', prop_float=1.0, prop_blank=b'a blanked string', prop_true=1, prop_false=0, ) zeroconf_registrar = Zeroconf() desc = {'path': '/~paulsm/'} desc.update(properties) info = ServiceInfo( type_, registration_name, socket.inet_aton("10.0.1.2"), 80, 0, 0, desc, "ash-2.local.") zeroconf_registrar.register_service(info) try: service_added.wait(1) assert service_added.is_set() # short pause to allow multicast timers to expire time.sleep(2) # clear the answer cache to force query for record in zeroconf_browser.cache.entries(): zeroconf_browser.cache.remove(record) # get service info without answer cache info = zeroconf_browser.get_service_info(type_, registration_name) assert info.properties[b'prop_none'] is False assert info.properties[b'prop_string'] == properties['prop_string'] assert info.properties[b'prop_float'] is False assert info.properties[b'prop_blank'] == properties['prop_blank'] assert info.properties[b'prop_true'] is True assert info.properties[b'prop_false'] is False zeroconf_registrar.unregister_service(info) service_removed.wait(1) assert service_removed.is_set() finally: zeroconf_registrar.close() zeroconf_browser.close()
def test_integration_with_listener_class(self): service_added = Event() service_removed = Event() service_updated = Event() subtype_name = "My special Subtype" type_ = "_http._tcp.local." subtype = subtype_name + "._sub." + type_ name = "xxxyyyæøå" registration_name = "%s.%s" % (name, subtype) class MyListener(r.ServiceListener): def add_service(self, zeroconf, type, name): zeroconf.get_service_info(type, name) service_added.set() def remove_service(self, zeroconf, type, name): service_removed.set() class MySubListener(r.ServiceListener): def add_service(self, zeroconf, type, name): pass def remove_service(self, zeroconf, type, name): pass def update_service(self, zeroconf, type, name): service_updated.set() listener = MyListener() zeroconf_browser = Zeroconf(interfaces=['127.0.0.1']) zeroconf_browser.add_service_listener(subtype, listener) properties = dict( prop_none=None, prop_string=b'a_prop', prop_float=1.0, prop_blank=b'a blanked string', prop_true=1, prop_false=0, ) zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1']) desc = {'path': '/~paulsm/'} # type: r.ServicePropertiesType desc.update(properties) info_service = ServiceInfo( subtype, registration_name, socket.inet_aton("10.0.1.2"), 80, 0, 0, desc, "ash-2.local." ) zeroconf_registrar.register_service(info_service) try: service_added.wait(1) assert service_added.is_set() # short pause to allow multicast timers to expire time.sleep(3) # clear the answer cache to force query for record in zeroconf_browser.cache.entries(): zeroconf_browser.cache.remove(record) # get service info without answer cache info = zeroconf_browser.get_service_info(type_, registration_name) assert info is not None assert info.properties[b'prop_none'] is False assert info.properties[b'prop_string'] == properties['prop_string'] assert info.properties[b'prop_float'] is False assert info.properties[b'prop_blank'] == properties['prop_blank'] assert info.properties[b'prop_true'] is True assert info.properties[b'prop_false'] is False info = zeroconf_browser.get_service_info(subtype, registration_name) assert info is not None assert info.properties[b'prop_none'] is False # Begin material test addition sublistener = MySubListener() zeroconf_browser.add_service_listener(registration_name, sublistener) properties['prop_blank'] = b'an updated string' desc.update(properties) info_service = ServiceInfo( subtype, registration_name, socket.inet_aton("10.0.1.2"), 80, 0, 0, desc, "ash-2.local." ) zeroconf_registrar.update_service(info_service) service_updated.wait(1) assert service_updated.is_set() info = zeroconf_browser.get_service_info(type_, registration_name) assert info is not None assert info.properties[b'prop_blank'] == properties['prop_blank'] # End material test addition zeroconf_registrar.unregister_service(info_service) service_removed.wait(1) assert service_removed.is_set() finally: zeroconf_registrar.close() zeroconf_browser.remove_service_listener(listener) zeroconf_browser.close()
def add_service( self, _zeroconf: zeroconf.Zeroconf, _type: str, name: str ) -> None: """Add service.""" self.services[name] = _zeroconf.get_service_info(_type, name)
if len(sys.argv) > 1: assert sys.argv[1:] == [u'--debug'] logging.getLogger(u'zeroconf').setLevel(logging.DEBUG) # Test a few module features, including service registration, service # query (for Zoe), and service unregistration. print(u"Multicast DNS Service Discovery for Python, version %s" % (__version__,)) r = Zeroconf() print(u"1. Testing registration of a service...") desc = {u'version': u'0.10', u'a': u'test value', u'b': u'another value'} info = ServiceInfo(u"_http._tcp.local.", u"My Service Name._http._tcp.local.", socket.inet_aton(u"127.0.0.1"), 1234, 0, 0, desc) print(u" Registering service...") r.register_service(info) print(u" Registration done.") print(u"2. Testing query of service information...") print(u" Getting ZOE service: %s" % ( r.get_service_info(u"_http._tcp.local.", u"ZOE._http._tcp.local."))) print(u" Query done.") print(u"3. Testing query of own service...") info = r.get_service_info(u"_http._tcp.local.", u"My Service Name._http._tcp.local.") assert info print(u" Getting self: %s" % (info,)) print(u" Query done.") print(u"4. Testing unregister of service information...") r.unregister_service(info) print(u" Unregister done.") r.close()
import RPi.GPIO as GPIO #Initialize a bunch of variables TABLE_NUM = 1 state = "IDLE" req_recv = True prob_occupied = .1 button_pressed = False wait30 = time.time() wait600 = time.time() zeroconf = Zeroconf() info = None while info is None: info = zeroconf.get_service_info('_http._tcp.local.', 'CentralServer._http._tcp.local.') print( "Address: %s:%d" % (socket.inet_ntoa(info.address), info.port)) print( "Server: %s" % (info.server)) if info.properties: print( "Properties: ") for key, value in info.properties.items(): print(" %s: %s" % (key, value)) print("\n") msg_recvd = threading.Event() def callback(ch, method, properties, body): print "MSG: %s" % body msg_recvd.set()
logging.basicConfig(level=logging.DEBUG) if len(sys.argv) > 1: assert sys.argv[1:] == ['--debug'] logging.getLogger('zeroconf').setLevel(logging.DEBUG) # Test a few module features, including service registration, service # query (for Zoe), and service unregistration. print("Multicast DNS Service Discovery for Python, version %s" % (__version__,)) r = Zeroconf() print("1. Testing registration of a service...") desc = {'version': '0.10', 'a': 'test value', 'b': 'another value'} info = ServiceInfo("_http._tcp.local.", "My Service Name._http._tcp.local.", socket.inet_aton("127.0.0.1"), 1234, 0, 0, desc) print(" Registering service...") r.register_service(info) print(" Registration done.") print("2. Testing query of service information...") print(" Getting ZOE service: %s" % ( r.get_service_info("_http._tcp.local.", "ZOE._http._tcp.local."))) print(" Query done.") print("3. Testing query of own service...") queried_info = r.get_service_info("_http._tcp.local.", "My Service Name._http._tcp.local.") assert queried_info print(" Getting self: %s" % (queried_info,)) print(" Query done.") print("4. Testing unregister of service information...") r.unregister_service(info) print(" Unregister done.") r.close()
#!/usr/bin/env python3 """ Example of resolving a service with a known name """ import logging import sys from zeroconf import Zeroconf TYPE = '_test._tcp.local.' NAME = 'My Service Name' if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) if len(sys.argv) > 1: assert sys.argv[1:] == ['--debug'] logging.getLogger('zeroconf').setLevel(logging.DEBUG) zeroconf = Zeroconf() try: print(zeroconf.get_service_info(TYPE, NAME + '.' + TYPE)) finally: zeroconf.close()
logging.getLogger('zeroconf').setLevel(logging.DEBUG) # Test a few module features, including service registration, service # query (for Zoe), and service unregistration. print("Multicast DNS Service Discovery for Python, version %s" % (__version__,)) r = Zeroconf() print("1. Testing registration of a service...") desc = {'version': '0.10', 'a': 'test value', 'b': 'another value'} info = ServiceInfo( "_http._tcp.local.", "My Service Name._http._tcp.local.", addresses=[socket.inet_aton("127.0.0.1")], port=1234, properties=desc, ) print(" Registering service...") r.register_service(info) print(" Registration done.") print("2. Testing query of service information...") print(" Getting ZOE service: %s" % (r.get_service_info("_http._tcp.local.", "ZOE._http._tcp.local."))) print(" Query done.") print("3. Testing query of own service...") queried_info = r.get_service_info("_http._tcp.local.", "My Service Name._http._tcp.local.") assert queried_info print(" Getting self: %s" % (queried_info,)) print(" Query done.") print("4. Testing unregister of service information...") r.unregister_service(info) print(" Unregister done.") r.close()