def test_integration(): service_added = Event() service_removed = Event() type_ = "_http._tcp.local." registration_name = "xxxyyy.%s" % type_ def on_service_state_change(zeroconf, service_type, state_change, name): if name == registration_name: if state_change is ServiceStateChange.Added: service_added.set() elif state_change is ServiceStateChange.Removed: service_removed.set() zeroconf_browser = Zeroconf() browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change]) zeroconf_registrar = Zeroconf() desc = {'path': '/~paulsm/'} 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() # Don't remove service, allow close() to cleanup finally: zeroconf_registrar.close() browser.cancel() zeroconf_browser.close()
def test_integration(): service_added = Event() service_removed = Event() type_ = "_http._tcp.local." registration_name = "xxxyyy.%s" % type_ class MyListener(object): def remove_service(self, zeroconf, type_, name): if name == registration_name: service_removed.set() def add_service(self, zeroconf, type_, name): if name == registration_name: service_added.set() zeroconf_browser = Zeroconf() listener = MyListener() browser = ServiceBrowser(zeroconf_browser, type_, listener) zeroconf_registrar = Zeroconf() desc = {'path': '/~paulsm/'} 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() zeroconf_registrar.unregister_service(info) service_removed.wait(1) assert service_removed.is_set() finally: zeroconf_registrar.close() browser.cancel() zeroconf_browser.close()
def discover_chromecasts(max_devices=None, timeout=DISCOVER_TIMEOUT): """ Discover chromecasts on the network. """ try: zconf = Zeroconf() listener = CastListener() browser = ServiceBrowser(zconf, "_googlecast._tcp.local.", listener) if max_devices is None: time.sleep(timeout) return listener.devices else: start = time.time() while (time.time() - start < timeout and listener.count < max_devices): time.sleep(.1) return listener.devices finally: browser.cancel() zconf.close()
def discover_chromecasts(max_devices=None, timeout=DISCOVER_TIMEOUT): try: zconf = Zeroconf() listener = CastListener() browser = ServiceBrowser(zconf, "_googlecast._tcp.local.", listener) t = 0 if max_devices is None: time.sleep(DISCOVER_TIMEOUT) return listener.devices else: while t < DISCOVER_TIMEOUT: time.sleep(.1) if listener.count >= max_devices: return listener.devices return listener.devices finally: browser.cancel() zconf.close()
@app.route('/LED', methods=['GET']) @auth.login_required def get_color(): if (LEDOK): com = request.args.get('command', '') if (com == ''): return "bad request" else: comarr = com.split('-') if (len(comarr) == 3): status = comarr[0] color = comarr[1] intensity = comarr[2] url = "http://pumpkin-pi.local:8081/LED?status=" + status + "&color=" + color + "&intensity=" + intensity r = req.get(url) return "Sending" else: return "bad request" else: return "Haven't found LED Pi" if __name__ == '__main__': zeroconf = Zeroconf() listener = MyListener() browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener) app.run(debug=True, port="8081", host='0.0.0.0')
def discover_homekit_devices(max_seconds=10): """ This method discovers all HomeKit Accessories. It browses for devices in the _hap._tcp.local. domain and checks if all required fields are set in the text record. It one field is missing, it will be excluded from the result list. :param max_seconds: the number of seconds we will wait for the devices to be discovered :return: a list of dicts containing all fields as described in table 5.7 page 69 """ zeroconf = Zeroconf() listener = CollectingListener() ServiceBrowser(zeroconf, '_hap._tcp.local.', listener) sleep(max_seconds) tmp = [] for info in listener.get_data(): # from Bonjour discovery d = { 'name': info.name, 'address': inet_ntoa(info.address), 'port': info.port } props = info.properties # stuff taken from the Bonjour TXT record (see table 5-7 on page 69) conf_number = get_from_properties(props, b'c#', case_sensitive=False) if conf_number: d['c#'] = conf_number else: continue ff = get_from_properties(props, b'ff', case_sensitive=False) if ff: flags = int(ff) else: flags = 0 d['ff'] = flags # d['flags'] = FeatureFlags[flags] id = get_from_properties(props, b'id', case_sensitive=False) if id: d['id'] = id md = get_from_properties(props, b'md', case_sensitive=False) if md: d['md'] = md else: continue pv = get_from_properties(props, b'pv', case_sensitive=False, default='1.0') if pv: d['pv'] = pv s = get_from_properties(props, b's#', case_sensitive=False) if s: d['s#'] = s sf = get_from_properties(props, b'sf', case_sensitive=False) if sf: d['sf'] = sf d['statusflags'] = IpStatusFlags[int(sf)] ci = get_from_properties(props, b'ci', case_sensitive=False) if ci: category = info.properties[b'ci'].decode() d['ci'] = category d['category'] = Categories[int(category)] # append device, it has all data tmp.append(d) zeroconf.close() return tmp
def setup(hass, config): """Set up Zeroconf and make Home Assistant discoverable.""" zeroconf = Zeroconf() zeroconf_name = f"{hass.config.location_name}.{ZEROCONF_TYPE}" params = { "version": __version__, "base_url": hass.config.api.base_url, # always needs authentication "requires_api_password": True, } host_ip = util.get_local_ip() try: host_ip_pton = socket.inet_pton(socket.AF_INET, host_ip) except socket.error: host_ip_pton = socket.inet_pton(socket.AF_INET6, host_ip) info = ServiceInfo( ZEROCONF_TYPE, zeroconf_name, None, addresses=[host_ip_pton], port=hass.http.server_port, properties=params, ) def zeroconf_hass_start(_event): """Expose Home Assistant on zeroconf when it starts. Wait till started or otherwise HTTP is not up and running. """ _LOGGER.info("Starting Zeroconf broadcast") zeroconf.register_service(info) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, zeroconf_hass_start) def service_update(zeroconf, service_type, name, state_change): """Service state changed.""" if state_change != ServiceStateChange.Added: return service_info = zeroconf.get_service_info(service_type, name) info = info_from_service(service_info) _LOGGER.debug("Discovered new device %s %s", name, info) # If we can handle it as a HomeKit discovery, we do that here. if service_type == HOMEKIT_TYPE and handle_homekit(hass, info): return for domain in ZEROCONF[service_type]: hass.add_job( hass.config_entries.flow.async_init(domain, context={"source": DOMAIN}, data=info)) for service in ZEROCONF: ServiceBrowser(zeroconf, service, handlers=[service_update]) if HOMEKIT_TYPE not in ZEROCONF: ServiceBrowser(zeroconf, HOMEKIT_TYPE, handlers=[service_update]) def stop_zeroconf(_): """Stop Zeroconf.""" zeroconf.unregister_service(info) zeroconf.close() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zeroconf) return True
ServiceInfo( type='_sciabc._tcp.local.', name='SupercomputerInABriefcase on tom-xps._sciabc._tcp.local.', address=b'\n\xb7\xcd\xb6', port=34343, weight=0, priority=0, server='tom-xps.local.', properties={} ) """ info = zeroconf.get_service_info(type, name) print("Service %s added, service info: %s" % (name, info)) ip = ipaddress.ip_address(info.address) append_ip_to_nodes_file(str(ip)) if __name__ == '__main__': zeroconf = Zeroconf() listener = MyListener() browser = ServiceBrowser(zeroconf, "_sciabc._tcp.local.", listener) reset_nodes_file() try: input("Press Ctrl-C to exit...\n\n") except KeyboardInterrupt: print('Exiting.') finally: zeroconf.close()
def start(self): # Use self as the listener class because I have add_service and remove_service methods self.browser = ServiceBrowser(self._zeroconf, self._service_type, self)
import sys from zeroconf import ServiceBrowser, Zeroconf class MyListener: def remove_service(self, zeroconf, type, name): print("Service %s removed" % (name,)) def add_service(self, zeroconf, type, name): info = zeroconf.get_service_info(type, name) print("Service %s added, service info: %s" % (name, info)) try: arg = sys.argv[1] except IndexError: raise SystemExit("Usage: {sys.argv[0]} <service to browse>") zeroconf = Zeroconf() listener = MyListener() browser = ServiceBrowser(zeroconf, arg, listener) try: input("Press enter to exit...\n\n") finally: zeroconf.close()
def test_integration(): service_added = Event() service_removed = Event() unexpected_ttl = Event() got_query = Event() type_ = "_http._tcp.local." registration_name = "xxxyyy.%s" % type_ def on_service_state_change(zeroconf, service_type, state_change, name): if name == registration_name: if state_change is ServiceStateChange.Added: service_added.set() elif state_change is ServiceStateChange.Removed: service_removed.set() zeroconf_browser = Zeroconf(interfaces=['127.0.0.1']) # we are going to monkey patch the zeroconf send to check packet sizes old_send = zeroconf_browser.send time_offset = 0 def current_time_millis(): """Current system time in milliseconds""" return time.time() * 1000 + time_offset * 1000 expected_ttl = r._DNS_TTL # needs to be a list so that we can modify it in our phony send nbr_queries = [0, None] def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT): """Sends an outgoing packet.""" pout = r.DNSIncoming(out.packet()) for answer in pout.answers: nbr_queries[0] += 1 if not answer.ttl > expected_ttl / 2: unexpected_ttl.set() got_query.set() old_send(out, addr=addr, port=port) # monkey patch the zeroconf send zeroconf_browser.send = send # monkey patch the zeroconf current_time_millis r.current_time_millis = current_time_millis service_added = Event() service_removed = Event() browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change]) zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1']) desc = {'path': '/~paulsm/'} 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() sleep_count = 0 while nbr_queries[0] < 50: time_offset += expected_ttl / 4 zeroconf_browser.notify_all() sleep_count += 1 got_query.wait(1) got_query.clear() assert not unexpected_ttl.is_set() # Don't remove service, allow close() to cleanup finally: zeroconf_registrar.close() browser.cancel() zeroconf_browser.close()
def find_servers(self, timeout=AUTO_DISCOVERY_WAIT): log.info('searching for game servers') service_browser = ServiceBrowser(Zeroconf(), '%s.local.' % AUTO_DISCOVERY_TYPE, self) service_browser.join(timeout=timeout) return self.servers
class ZeroConfClient: # The discovery protocol name for Ultimaker printers. ZERO_CONF_NAME = u"_ultimaker._tcp.local." # Signals emitted when new services were discovered or removed on the network. addedNetworkCluster = Signal() removedNetworkCluster = Signal() def __init__(self) -> None: self._zero_conf = None # type: Optional[Zeroconf] self._zero_conf_browser = None # type: Optional[ServiceBrowser] self._service_changed_request_queue = None # type: Optional[Queue] self._service_changed_request_event = None # type: Optional[Event] self._service_changed_request_thread = None # type: Optional[Thread] ## The ZeroConf service changed requests are handled in a separate thread so we don't block the UI. # We can also re-schedule the requests when they fail to get detailed service info. # Any new or re-reschedule requests will be appended to the request queue and the thread will process them. def start(self) -> None: self._service_changed_request_queue = Queue() self._service_changed_request_event = Event() self._service_changed_request_thread = Thread( target=self._handleOnServiceChangedRequests, daemon=True) self._service_changed_request_thread.start() self._zero_conf = Zeroconf() self._zero_conf_browser = ServiceBrowser(self._zero_conf, self.ZERO_CONF_NAME, [self._queueService]) # Cleanup ZeroConf resources. def stop(self) -> None: if self._zero_conf is not None: self._zero_conf.close() self._zero_conf = None if self._zero_conf_browser is not None: self._zero_conf_browser.cancel() self._zero_conf_browser = None ## Handles a change is discovered network services. def _queueService(self, zeroconf: Zeroconf, service_type, name: str, state_change: ServiceStateChange) -> None: item = (zeroconf, service_type, name, state_change) if not self._service_changed_request_queue or not self._service_changed_request_event: return self._service_changed_request_queue.put(item) self._service_changed_request_event.set() ## Callback for when a ZeroConf service has changes. def _handleOnServiceChangedRequests(self) -> None: if not self._service_changed_request_queue or not self._service_changed_request_event: return while True: # Wait for the event to be set self._service_changed_request_event.wait(timeout=5.0) # Stop if the application is shutting down if CuraApplication.getInstance().isShuttingDown(): return self._service_changed_request_event.clear() # Handle all pending requests reschedule_requests = [ ] # A list of requests that have failed so later they will get re-scheduled while not self._service_changed_request_queue.empty(): request = self._service_changed_request_queue.get() zeroconf, service_type, name, state_change = request try: result = self._onServiceChanged(zeroconf, service_type, name, state_change) if not result: reschedule_requests.append(request) except Exception: Logger.logException( "e", "Failed to get service info for [%s] [%s], the request will be rescheduled", service_type, name) reschedule_requests.append(request) # Re-schedule the failed requests if any if reschedule_requests: for request in reschedule_requests: self._service_changed_request_queue.put(request) ## Handler for zeroConf detection. # Return True or False indicating if the process succeeded. # Note that this function can take over 3 seconds to complete. Be careful calling it from the main thread. def _onServiceChanged(self, zero_conf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange) -> bool: if state_change == ServiceStateChange.Added: return self._onServiceAdded(zero_conf, service_type, name) elif state_change == ServiceStateChange.Removed: return self._onServiceRemoved(name) return True ## Handler for when a ZeroConf service was added. 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 ## Handler for when a ZeroConf service was removed. def _onServiceRemoved(self, name: str) -> bool: Logger.log("d", "ZeroConf service removed: %s" % name) self.removedNetworkCluster.emit(str(name)) return True
def test_lots_of_names(self): # instantiate a zeroconf instance zc = Zeroconf(interfaces=['127.0.0.1']) # create a bunch of servers type_ = "_my-service._tcp.local." name = 'a wonderful service' server_count = 300 self.generate_many_hosts(zc, type_, name, server_count) # verify that name changing works self.verify_name_change(zc, type_, name, server_count) # we are going to monkey patch the zeroconf send to check packet sizes old_send = zc.send # needs to be a list so that we can modify it in our phony send longest_packet = [0, None] def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT): """Sends an outgoing packet.""" packet = out.packet() if longest_packet[0] < len(packet): longest_packet[0] = len(packet) longest_packet[1] = out old_send(out, addr=addr, port=port) # monkey patch the zeroconf send zc.send = send # dummy service callback def on_service_state_change(zeroconf, service_type, state_change, name): pass # start a browser browser = ServiceBrowser(zc, type_, [on_service_state_change]) # wait until the browse request packet has maxed out in size sleep_count = 0 while sleep_count < 100 and \ longest_packet[0] < r._MAX_MSG_ABSOLUTE - 100: sleep_count += 1 time.sleep(0.1) browser.cancel() time.sleep(0.5) import zeroconf zeroconf.log.debug('sleep_count %d, sized %d', sleep_count, longest_packet[0]) # now the browser has sent at least one request, verify the size assert longest_packet[0] <= r._MAX_MSG_ABSOLUTE assert longest_packet[0] >= r._MAX_MSG_ABSOLUTE - 100 # mock zeroconf's logger warning() and debug() from unittest.mock import patch patch_warn = patch('zeroconf.log.warning') patch_debug = patch('zeroconf.log.debug') mocked_log_warn = patch_warn.start() mocked_log_debug = patch_debug.start() # now that we have a long packet in our possession, let's verify the # exception handling. out = longest_packet[1] out.data.append(b'\0' * 1000) # mock the zeroconf logger and check for the correct logging backoff call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count # try to send an oversized packet zc.send(out) assert mocked_log_warn.call_count == call_counts[0] + 1 assert mocked_log_debug.call_count == call_counts[0] zc.send(out) assert mocked_log_warn.call_count == call_counts[0] + 1 assert mocked_log_debug.call_count == call_counts[0] + 1 # force a receive of an oversized packet packet = out.packet() s = zc._respond_sockets[0] # mock the zeroconf logger and check for the correct logging backoff call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count # force receive on oversized packet s.sendto(packet, 0, (r._MDNS_ADDR, r._MDNS_PORT)) s.sendto(packet, 0, (r._MDNS_ADDR, r._MDNS_PORT)) time.sleep(2.0) zeroconf.log.debug('warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts) assert mocked_log_debug.call_count > call_counts[0] # close our zeroconf which will close the sockets zc.close() # pop the big chunk off the end of the data and send on a closed socket out.data.pop() zc._GLOBAL_DONE = False # mock the zeroconf logger and check for the correct logging backoff call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count # send on a closed socket (force a socket error) zc.send(out) zeroconf.log.debug('warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts) assert mocked_log_warn.call_count > call_counts[0] assert mocked_log_debug.call_count > call_counts[0] zc.send(out) zeroconf.log.debug('warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts) assert mocked_log_debug.call_count > call_counts[0] + 2 mocked_log_warn.stop() mocked_log_debug.stop()
from OSCServer import ClientHandler, ClientScanner, ClientBasedOSCUDPServer from OSCClient import OSCClient from config import * # StudioLive object sl = StudioLive1602(debug=True, local=False) sl.connect(args.slip) sl.start() #while(not sl.loaded): time.sleep(2) # Client handler object client_handler = ClientHandler(OSCClient, sl, 8080) # OSC UDP Server server = ClientBasedOSCUDPServer((args.oscip, args.oscport), client_handler) server_thread = threading.Thread(target=server.serve_forever) server_thread.start() print("Serving OSC UDP server on {}".format(server.server_address)) # Zeroconf server & client zeroconf_service = "_osc._udp.local." zeroconf = Zeroconf([args.oscip]) print("OSCServer" + zeroconf_service) zeroconf.register_service( ServiceInfo(zeroconf_service, "OSCServer" + "." + zeroconf_service, socket.inet_aton(args.oscip), args.oscport, 0, 0, {})) browser = ServiceBrowser(zeroconf, zeroconf_service, ClientScanner(client_handler))
def listen(self, add_device: Callable): self._add_device = add_device zeroconf = Zeroconf() ServiceBrowser(zeroconf, '_yandexio._tcp.local.', listener=self)
def start(self): self.browser = ServiceBrowser(self.zeroconf, utils.TYPE, handlers=[self.handler])
def mdns_query(self, dst='ff02::fb', service='_meshcop._udp.local', addrs_blacklist=[]): print('mdns_query %s %s %s' % (dst, service, addrs_blacklist)) # For BBR-TC-03 or DH test cases just send a query if dst == 'ff02::fb' and not addrs_blacklist: self.bash('dig -p 5353 @%s %s ptr' % (dst, service)) return # For MATN-TC-17 and MATN-TC-18 use Zeroconf to get the BBR address and border agent port from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf, DNSAddress, DNSService, DNSText def on_service_state_change(zeroconf, service_type, name, state_change): if state_change is ServiceStateChange.Added: zeroconf.get_service_info(service_type, name) class BorderAgent(object): alias = None server_name = None link_local_addr = None port = None thread_status = None def __init__(self, alias): self.alias = alias def __repr__(self): return '%s # [%s]:%s TIS=%s' % (self.alias, self.link_local_addr, self.port, self.thread_status) def parse_cache(cache): border_agents = [] # Find all border routers for ptr in cache['_meshcop._udp.local.']: border_agents.append(BorderAgent(ptr.alias)) # Find server name, port and Thread Interface status for each border router for ba in border_agents: for record in cache[ba.alias.lower()]: if isinstance(record, DNSService): ba.server_name = record.server ba.port = record.port elif isinstance(record, DNSText): text = bytearray(record.text) sb = text.split(b'sb=')[1][0:4] ba.thread_status = (sb[3] & 0x18) >> 3 # Find link local address for each border router for ba in border_agents: for record in cache[ba.server_name]: if isinstance(record, DNSAddress): addr = ipaddress.ip_address(record.address) if isinstance( addr, ipaddress.IPv6Address) and addr.is_link_local: ba.link_local_addr = str(addr) break return border_agents # Browse border agents zeroconf = Zeroconf() ServiceBrowser(zeroconf, "_meshcop._udp.local.", handlers=[on_service_state_change]) time.sleep(2) cache = zeroconf.cache.cache zeroconf.close() # Find an active border agent not in the blacklist border_agents = parse_cache(cache) for ba in border_agents: if ba.thread_status == 2 and ba.link_local_addr not in addrs_blacklist: return ('%s%%eth0' % ba.link_local_addr, ba.port) raise Exception('No active Border Agents found')
print(" Address: %s:%d" % (socket.inet_ntoa(info.address), 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') 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() print("\nBrowsing services, press Ctrl-C to exit...\n") browser = ServiceBrowser(zeroconf, "_http._tcp.local.", handlers=[on_service_state_change]) browser.start() try: while True: sleep(0.1) except KeyboardInterrupt: pass finally: zeroconf.close()
def start(self, handlerer: Callable, zeroconf: Zeroconf): self.add_handlerer = handlerer self.browser = ServiceBrowser(zeroconf, '_yandexio._tcp.local.', handlers=[self._zeroconf_handler])
def test_backoff(): got_query = Event() type_ = "_http._tcp.local." zeroconf_browser = Zeroconf(interfaces=['127.0.0.1']) # we are going to monkey patch the zeroconf send to check query transmission old_send = zeroconf_browser.send time_offset = 0.0 start_time = time.time() * 1000 initial_query_interval = r._BROWSER_TIME / 1000 def current_time_millis(): """Current system time in milliseconds""" return start_time + time_offset * 1000 def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT): """Sends an outgoing packet.""" got_query.set() old_send(out, addr=addr, port=port) # monkey patch the zeroconf send setattr(zeroconf_browser, "send", send) # monkey patch the zeroconf current_time_millis r.current_time_millis = current_time_millis # monkey patch the backoff limit to prevent test running forever r._BROWSER_BACKOFF_LIMIT = 10 # seconds # dummy service callback def on_service_state_change(zeroconf, service_type, state_change, name): pass browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change]) try: # Test that queries are sent at increasing intervals sleep_count = 0 next_query_interval = 0.0 expected_query_time = 0.0 while True: zeroconf_browser.notify_all() sleep_count += 1 got_query.wait(0.1) if time_offset == expected_query_time: assert got_query.is_set() got_query.clear() if next_query_interval == r._BROWSER_BACKOFF_LIMIT: # Only need to test up to the point where we've seen a query # after the backoff limit has been hit break elif next_query_interval == 0: next_query_interval = initial_query_interval expected_query_time = initial_query_interval else: next_query_interval = min(2 * next_query_interval, r._BROWSER_BACKOFF_LIMIT) expected_query_time += next_query_interval else: assert not got_query.is_set() time_offset += initial_query_interval finally: browser.cancel() zeroconf_browser.close()
def test_integration(): service_added = Event() service_removed = Event() unexpected_ttl = Event() got_query = Event() type_ = "_http._tcp.local." registration_name = "xxxyyy.%s" % type_ def on_service_state_change(zeroconf, service_type, state_change, name): if name == registration_name: if state_change is ServiceStateChange.Added: service_added.set() elif state_change is ServiceStateChange.Removed: service_removed.set() zeroconf_browser = Zeroconf(interfaces=['127.0.0.1']) # we are going to monkey patch the zeroconf send to check packet sizes old_send = zeroconf_browser.send time_offset = 0 def current_time_millis(): """Current system time in milliseconds""" return time.time() * 1000 + time_offset * 1000 expected_ttl = r._DNS_TTL # needs to be a list so that we can modify it in our phony send nbr_queries = [0, None] def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT): """Sends an outgoing packet.""" pout = r.DNSIncoming(out.packet()) for answer in pout.answers: nbr_queries[0] += 1 if not answer.ttl > expected_ttl / 2: unexpected_ttl.set() got_query.set() old_send(out, addr=addr, port=port) # monkey patch the zeroconf send zeroconf_browser.send = send # monkey patch the zeroconf current_time_millis r.current_time_millis = current_time_millis service_added = Event() service_removed = Event() browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change]) zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1']) desc = {'path': '/~paulsm/'} 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() sleep_count = 0 while nbr_queries[0] < 50: time_offset += expected_ttl / 4 zeroconf_browser.notify_all() sleep_count += 1 got_query.wait(1) got_query.clear() assert not unexpected_ttl.is_set() # Don't remove service, allow close() to cleanup finally: zeroconf_registrar.close() browser.cancel() zeroconf_browser.close()
def main(): IP = requests.get('http://ip.42.pl/raw').text print(IP) user = os.environ['USER'] connections = [] opponents = dict() TIMEOUT = 0.001 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) HOST = '' PORT = 9876 sock.bind((HOST, PORT)) sock.listen(8) sock.settimeout(TIMEOUT) class ZListener(object): def remove_service(self, zeroconf, tpe, name): print("Service %s removed" % (name, )) def add_service(self, zeroconf, tpe, name): info = zeroconf.get_service_info(tpe, name) print("Service %s added, service info: %s" % (name, info)) address = socket.inet_ntoa(info.address) port = info.port print(address) print(port) if address == IP: return mutex.acquire() n_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) n_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) n_sock.connect((address, port)) n_sock.settimeout(TIMEOUT) found = False for c in connections: if c.getpeername()[0] == address: found = True if not found: print("ADDING CONNECTION ZCONF") connections.append(n_sock) mutex.release() desc = {'path': '/stuff/'} zeroconf = Zeroconf() listener = ZListener() browser = ServiceBrowser(zeroconf, "_hackathonator._tcp.local.", listener) info = ServiceInfo("_hackathonator._tcp.local.", user + "._hackathonator._tcp.local.", socket.inet_aton(IP), 9876, 0, 0, desc, "ash-2.local.") zeroconf.register_service(info) pygame.init() width = 1200 height = 720 win = pygame.display.set_mode((width, height)) pygame.display.set_caption('Hackathonator') sprites = dict() sprites['l_hand'] = HandSprite(yellow, (width // 2 - 140, height), 20) sprites['r_hand'] = HandSprite(yellow, (width // 2 + 140, height), 20) my_clock = pygame.time.Clock() string = '' wrong_string = '' font = pygame.font.Font('RobotoMono-Medium.ttf', 14) code_line = 'I may be slow but watch me go' code_index = 0 line_height = 40 finished_lines = [] mods = [304, 303, 13, 301] time_limit = 60 clock = pygame.time.Clock() ticks = 0 other_lost = False other_score = 0 try: while time_limit > 0: # Event handling and game logic ticks += clock.tick() if ticks > 1000: time_limit -= 1 ticks = 0 events = pygame.event.get() for event in events: if event.type == pygame.QUIT: pygame.quit() elif event.type == pygame.KEYDOWN: if event.key != pygame.K_BACKSPACE: hand = random.randint(0, 1) if hand == 0: sprites['l_hand'].move() else: sprites['r_hand'].move() if code_index < len(code_line): if (event.unicode == code_line[code_index] and len(string) == len(wrong_string) ) or event.key == pygame.K_LALT: string += event.unicode wrong_string += event.unicode code_index += 1 if code_index == len( code_line ) or event.key == pygame.K_LALT: time_limit += 5 finished_lines.append( (code_line, len(finished_lines) + 1)) code_line = code_lines[random.randint( 0, len(code_lines) - 1)] string = '' wrong_string = '' code_index = 0 reply_str = user + ',' + str( len(finished_lines)) print(connections) for conn in connections: conn.sendall( bytearray(reply_str, 'utf-8')) else: if event.key not in mods and len( string) == len(wrong_string): if code_line[code_index] == ' ': wrong_string += '_' else: wrong_string += code_line[code_index] code_index += 1 else: if (code_index > 0): if len(string) == len(wrong_string): string = string[:-1] wrong_string = wrong_string[:-1] code_index -= 1 sprites['r_hand'].move() for sprite_name, sprite in sprites.items(): sprite.update() # Networking mutex.acquire() try: conn, addr = sock.accept() conn.settimeout(TIMEOUT) found = False for c in connections: print(addr) print(c.getpeername()[0]) if c.getpeername()[0] == addr[0]: found = True print('REMOVING CONNECTION') connections.remove(c) break print("ADDING CONNECTION SERVER") connections.append(conn) print(connections) except socket.timeout: try: new_conns = [] for conn in connections: msg = conn.recv(256) if msg is not None and msg != b'': msg = str(msg).strip('b').strip('\'') if ',' in msg: sender, s_line = msg.split(',') opponents[sender] = s_line other_score = int(s_line) else: other_lost = True game_over_line = msg print(msg) new_conns.append(conn) else: print('Closing') conn.close() connections = new_conns except socket.timeout: pass mutex.release() # Rendering win.fill((0, 0, 0)) screen_bezel = pygame.draw.rect(win, white, (30, 10, width - 60, height - 70)) screen = pygame.draw.rect(win, gray, (50, 30, width - 100, height - 110)) camera = pygame.draw.circle(win, black, (width // 2, 20), 5) head = pygame.draw.circle(win, yellow, (width // 2, height), 100) if code_index != len(code_line): cursor = font.render(code_line[code_index], 1, black, white) code = font.render(code_line, 1, white) wrong_text = font.render(wrong_string, 1, white, red) text = font.render(string, 1, orange, gray) l_num = font.render(str(len(finished_lines) + 1) + '.', 1, white) time = font.render("Time Left: " + str(time_limit), 1, white) if other_lost: other_lost_line = font.render(game_over_line, 1, white, black) if len(finished_lines) > 0: your_score = finished_lines[-1][1] else: your_score = 0 if other_score > your_score: end_msg = font.render("You lost", 1, white, black) else: end_msg = font.render("You won!", 1, white, black) line_h = line_height for line in finished_lines[-38:]: f_line = font.render(line[0], 1, orange) win.blit(f_line, (55 + font.size(str(line[1]) + '. ')[0], line_h)) l_number = font.render(str(line[1]) + '. ', 1, white) win.blit(l_number, (55, line_h)) line_h = min(line_h + 15, 625) start_line_x = font.size(str(len(finished_lines) + 1) + '. ')[0] win.blit(code, (55 + start_line_x, line_h)) win.blit(cursor, (55 + start_line_x + (font.size(string)[0]), line_h)) win.blit(wrong_text, (55 + start_line_x, line_h)) win.blit(text, (55 + start_line_x, line_h)) win.blit(l_num, (55, line_h)) win.blit(time, (width - 200, height - 20)) if other_lost: win.blit(other_lost_line, ((width // 2) - (font.size(game_over_line)[0] // 2), height // 2)) win.blit(end_msg, ((width // 2) - (font.size("You won!")[0] // 2), height // 2 + 20)) head = pygame.draw.circle(win, yellow, (width // 2, height), 100) for sprite_name, sprite in sprites.items(): sprite.draw(win) sorted_opps = sorted(opponents.items(), key=operator.itemgetter(1), reverse=True) if len(sorted_opps) != 0: opp = sorted_opps[0] opponent = font.render(opp[0] + ": " + opp[1], 1, white) win.blit(opponent, (55, height - 20)) pygame.display.flip() my_clock.tick(240) if other_lost: break if not other_lost: for conn in connections: conn.sendall(bytearray(user + " ran out of time", 'utf-8')) while True and not other_lost: events = pygame.event.get() for event in events: if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: pygame.quit() sock.close() zeroconf.unregister_service(info) if event.type == pygame.QUIT: pygame.quit() sock.close() zeroconf.unregister_service(info) if len(finished_lines) > 0: your_score = finished_lines[-1][1] else: your_score = 0 if other_score > your_score: end_msg = font.render("You lost", 1, white, black) else: end_msg = font.render("You won!", 1, white, black) game_over = font.render("Game Over", 1, white, black) win.blit(game_over, (width // 2 - (font.size("Game Over")[0] // 2), height // 2)) win.blit(end_msg, (width // 2 - (font.size("You won!")[0] // 2), height // 2 + 20)) pygame.display.flip() my_clock.tick(240) while True and other_lost: events = pygame.event.get() for event in events: if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: break pygame.quit() sock.close() zeroconf.unregister_service(info) if event.type == pygame.QUIT: pygame.quit() sock.close() zeroconf.unregister_service(info) win.blit(other_lost_line, (width // 2 - (font.size(game_over_line)[0] // 2), height // 2)) win.blit(end_msg, ((width // 2) - (font.size("You won!")[0] // 2), height // 2 + 20)) pygame.display.flip() my_clock.tick(240) except pygame.error: pass
class EWeLinkLocal: _devices: dict = None _handlers = None browser = None # cut temperature for sync to cloud API sync_temperature = False def __init__(self, session: ClientSession): self.session = session self.loop = asyncio.get_event_loop() @property def started(self) -> bool: return self.browser is not None def start(self, handlers: List[Callable], devices: dict, zeroconf): self._handlers = handlers self._devices = devices self.browser = ServiceBrowser(zeroconf, '_ewelink._tcp.local.', handlers=[self._zeroconf_handler]) # for beautiful logs self.browser.name = 'Sonoff_LAN' def stop(self, *args): self.browser.cancel() self.browser.zc.close() def _zeroconf_handler(self, zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange): if state_change == ServiceStateChange.Removed: _LOGGER.debug(f"Zeroconf Removed: {name}") # TTL of record 5 minutes deviceid = name[8:18] # _LOGGER.debug(f"{deviceid} <= Local2 | Zeroconf Removed Event") # check if device added if 'handlers' in self._devices[deviceid]: coro = self.check_offline(deviceid) self.loop.create_task(coro) 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, {}) log = f"{deviceid} <= Local{state_change.value}" if properties.get('encrypt'): devicekey = device.get('devicekey') if devicekey == 'skip': return if not devicekey: _LOGGER.info(f"{log} | No devicekey for device") # skip device next time device['devicekey'] = 'skip' return data = decrypt(properties, devicekey) # Fix Sonoff RF Bridge sintax bug if data and 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) seq = properties.get('seq') _LOGGER.debug(f"{log} | {state} | {seq}") # TH bug in local mode https://github.com/AlexxIT/SonoffLAN/issues/110 if state.get('temperature') == 0 and state.get('humidity') == 0: del state['temperature'], state['humidity'] elif 'temperature' in state and self.sync_temperature: # cloud API send only one decimal (not round) state['temperature'] = int(state['temperature'] * 10) / 10.0 if properties['type'] == 'fan_light': state = ifan03to02(state) device['uiid'] = 'fan_light' 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['local'] = 'online' # device host for local connection device['host'] = host # update or set device init state if 'params' in device: device['params'].update(state) else: device['params'] = state # set uiid with: strip, plug, light, rf device['uiid'] = properties['type'] for handler in self._handlers: handler(deviceid, state, seq) async def check_offline(self, deviceid: str): """Try to get response from device after received Zeroconf Removed.""" log = f"{deviceid} => Local4" device = self._devices[deviceid] if device.get('check_offline') or device['host'] is None: _LOGGER.debug(f"{log} | Skip parallel checks") return device['check_offline'] = True sequence = str(int(time.time() * 1000)) for t in range(20, 61, 20): _LOGGER.debug(f"{log} | Check offline with timeout {t}s") t0 = time.time() conn = await self.send(deviceid, {'cmd': 'info'}, sequence, t) if conn == 'online': device['check_offline'] = False _LOGGER.debug(f"{log} | Welcome back!") return if t < 60 and conn != 'timeout': # sometimes need to wait more await asyncio.sleep(t - time.time() + t0) _LOGGER.debug(f"{log} | Device offline") device['check_offline'] = False device['host'] = None for handler in self._handlers: handler(deviceid, {'local': 'offline'}, None) async def send(self, deviceid: str, data: dict, sequence: str, timeout=5): device: dict = self._devices[deviceid] if '_query' in data: data = {'cmd': 'signal_strength'} \ if data['_query'] is None else \ {'sledonline': data['_query']} if device['uiid'] == 'fan_light' and 'switches' in data: data = ifan02to03(data) # cmd for D1 and RF Bridge 433 command = data.get('cmd') or next(iter(data)) payload = { 'sequence': sequence, 'deviceid': deviceid, 'selfApikey': '123', 'data': data } if 'devicekey' in device: payload = encrypt(payload, device['devicekey']) log = f"{deviceid} => Local4 | {data}" try: r = await self.session.post( f"http://{device['host']}:8081/zeroconf/{command}", json=payload, headers=LOCAL_HEADERS, timeout=timeout) resp = await r.json() err = resp['error'] # no problem with any response from device for info command if err == 0 or command == 'info': _LOGGER.debug(f"{log} <= {resp}") return 'online' else: _LOGGER.warning(f"{log} <= {resp}") return f"E#{err}" except asyncio.TimeoutError: _LOGGER.debug(f"{log} !! Timeout {timeout}") return 'timeout' except ClientOSError as e: _LOGGER.debug(f"{log} !! {e.args}") return 'E#COS' except: _LOGGER.exception(log) return 'E#???'
) print( "Attempting to connect to Tally Arbiter server: {}:{} (UUID {}, server version {})" .format(info.server, str(info.port), server_uuid, server_version)) sio.connect("http://" + info.server + ":" + str(info.port)) sio.wait() except socketio.exceptions.ConnectionError: time.sleep(15) try: if "useMDNS" in config["DEFAULT"] and config["DEFAULT"]["useMDNS"]: zeroconf = Zeroconf() listener = TallyArbiterServerListener() browser = ServiceBrowser(zeroconf, "_tally-arbiter._tcp.local.", listener) while True: time.sleep(0.1) else: while 1: try: print( "Tally Arbiter Blink1 Listener Running. Press CTRL-C to exit." ) print("Attempting to connect to Tally Arbiter server: {}:{}". format(config["DEFAULT"]["host"], str(config["DEFAULT"]["port"]))) sio.connect("http://" + config["DEFAULT"]["host"] + ":" + str(config["DEFAULT"]["port"])) sio.wait() except socketio.exceptions.ConnectionError:
def test_lots_of_names(self): # instantiate a zeroconf instance zc = Zeroconf(interfaces=['127.0.0.1']) # create a bunch of servers type_ = "_my-service._tcp.local." name = 'a wonderful service' server_count = 300 self.generate_many_hosts(zc, type_, name, server_count) # verify that name changing works self.verify_name_change(zc, type_, name, server_count) # we are going to monkey patch the zeroconf send to check packet sizes old_send = zc.send longest_packet_len = 0 longest_packet = None # type: Optional[r.DNSOutgoing] def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT): """Sends an outgoing packet.""" packet = out.packet() nonlocal longest_packet_len, longest_packet if longest_packet_len < len(packet): longest_packet_len = len(packet) longest_packet = out old_send(out, addr=addr, port=port) # monkey patch the zeroconf send setattr(zc, "send", send) # dummy service callback def on_service_state_change(zeroconf, service_type, state_change, name): pass # start a browser browser = ServiceBrowser(zc, type_, [on_service_state_change]) # wait until the browse request packet has maxed out in size sleep_count = 0 while sleep_count < 100 and longest_packet_len < r._MAX_MSG_ABSOLUTE - 100: sleep_count += 1 time.sleep(0.1) browser.cancel() time.sleep(0.5) import zeroconf zeroconf.log.debug('sleep_count %d, sized %d', sleep_count, longest_packet_len) # now the browser has sent at least one request, verify the size assert longest_packet_len <= r._MAX_MSG_ABSOLUTE assert longest_packet_len >= r._MAX_MSG_ABSOLUTE - 100 # mock zeroconf's logger warning() and debug() from unittest.mock import patch patch_warn = patch('zeroconf.log.warning') patch_debug = patch('zeroconf.log.debug') mocked_log_warn = patch_warn.start() mocked_log_debug = patch_debug.start() # now that we have a long packet in our possession, let's verify the # exception handling. out = longest_packet assert out is not None out.data.append(b'\0' * 1000) # mock the zeroconf logger and check for the correct logging backoff call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count # try to send an oversized packet zc.send(out) assert mocked_log_warn.call_count == call_counts[0] + 1 assert mocked_log_debug.call_count == call_counts[0] zc.send(out) assert mocked_log_warn.call_count == call_counts[0] + 1 assert mocked_log_debug.call_count == call_counts[0] + 1 # force a receive of an oversized packet packet = out.packet() s = zc._respond_sockets[0] # mock the zeroconf logger and check for the correct logging backoff call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count # force receive on oversized packet s.sendto(packet, 0, (r._MDNS_ADDR, r._MDNS_PORT)) s.sendto(packet, 0, (r._MDNS_ADDR, r._MDNS_PORT)) time.sleep(2.0) zeroconf.log.debug( 'warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts ) assert mocked_log_debug.call_count > call_counts[0] # close our zeroconf which will close the sockets zc.close() # pop the big chunk off the end of the data and send on a closed socket out.data.pop() zc._GLOBAL_DONE = False # mock the zeroconf logger and check for the correct logging backoff call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count # send on a closed socket (force a socket error) zc.send(out) zeroconf.log.debug( 'warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts ) assert mocked_log_warn.call_count > call_counts[0] assert mocked_log_debug.call_count > call_counts[0] zc.send(out) zeroconf.log.debug( 'warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts ) assert mocked_log_debug.call_count > call_counts[0] + 2 mocked_log_warn.stop() mocked_log_debug.stop()
(dest.ip, dest.port)) sleep(0.01) class ZeroConfListener: def __init__(self): self.streamer = SensorStreamThread() self.streamer.start() def remove_service(self, zeroconf, type, name): info = zeroconf.get_service_info(type, name) print("Service %s removed, $s" % (name, info)) self.streamer.rm_destination(Dest(ip=info.addresses[0], port=info.port)) def add_service(self, zeroconf, type, name): info = zeroconf.get_service_info(type, name) print("Sensor sink %s added, service info: %s" % (name, info)) self.streamer.add_destination( Dest(ip=socket.inet_ntoa(info.addresses[0]), port=info.port)) zeroconf = Zeroconf() listener = ZeroConfListener() browser = ServiceBrowser(zeroconf, "_sensor._udp.local.", listener) try: input("Press enter to exit...\n\n") finally: zeroconf.close()
def test_integration(): service_added = Event() service_removed = Event() unexpected_ttl = Event() got_query = Event() type_ = "_http._tcp.local." registration_name = "xxxyyy.%s" % type_ def on_service_state_change(zeroconf, service_type, state_change, name): if name == registration_name: if state_change is ServiceStateChange.Added: service_added.set() elif state_change is ServiceStateChange.Removed: service_removed.set() zeroconf_browser = Zeroconf(interfaces=['127.0.0.1']) # we are going to monkey patch the zeroconf send to check packet sizes old_send = zeroconf_browser.send time_offset = 0.0 def current_time_millis(): """Current system time in milliseconds""" return time.time() * 1000 + time_offset * 1000 expected_ttl = r._DNS_HOST_TTL nbr_answers = 0 def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT): """Sends an outgoing packet.""" pout = r.DNSIncoming(out.packet()) nonlocal nbr_answers for answer in pout.answers: nbr_answers += 1 if not answer.ttl > expected_ttl / 2: unexpected_ttl.set() got_query.set() old_send(out, addr=addr, port=port) # monkey patch the zeroconf send setattr(zeroconf_browser, "send", send) # monkey patch the zeroconf current_time_millis r.current_time_millis = current_time_millis # monkey patch the backoff limit to ensure we always get one query every 1/4 of the DNS TTL r._BROWSER_BACKOFF_LIMIT = int(expected_ttl / 4) service_added = Event() service_removed = Event() browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change]) zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1']) desc = {'path': '/~paulsm/'} 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() # Test that we receive queries containing answers only if the remaining TTL # is greater than half the original TTL sleep_count = 0 test_iterations = 50 while nbr_answers < test_iterations: # Increase simulated time shift by 1/4 of the TTL in seconds time_offset += expected_ttl / 4 zeroconf_browser.notify_all() sleep_count += 1 got_query.wait(0.1) got_query.clear() # Prevent the test running indefinitely in an error condition assert sleep_count < test_iterations * 4 assert not unexpected_ttl.is_set() # Don't remove service, allow close() to cleanup finally: zeroconf_registrar.close() service_removed.wait(1) assert service_removed.is_set() browser.cancel() zeroconf_browser.close()
if info is None: self._lock.acquire() self._pending.append((type, name)) self._lock.release() else: print "Found IoThing at %s" % (inet_ntoa(info.address),) def update(self): self._lock.acquire() unresolved = list() for type, name in self._pending: info = zeroconf.get_service_info(type, name) if info is None: unresolved.append((type, name)) else: print "Found IoThing at %s" % (inet_ntoa(info.address),) self._pending = unresolved self._lock.release() if __name__ == "__main__": # Set up the listener zeroconf = Zeroconf() listener = IoThingListener() browser = ServiceBrowser(zeroconf, "_iothing._tcp.local.", listener) try: while True: listener.update() sleep(0.5) finally: zeroconf.close()
def listen(self, add_device: Callable): from homeassistant.components.zeroconf import Zeroconf self._add_device = add_device self._zeroconf = Zeroconf() ServiceBrowser(self._zeroconf, '_yandexio._tcp.local.', listener=self)
def resolve(self, type, timeout=10): browser = ServiceBrowser(self.zeroconf, type, self) self.discover_complete.wait(timeout) if not self.discover_complete.is_set(): return None # else return [self.ip_address, self.port]