コード例 #1
0
 async def discover(self, timeout):
     """Start discovery of devices and services."""
     zeroconf = Zeroconf(self.loop, address_family=[netifaces.AF_INET])
     try:
         ServiceBrowser(zeroconf, HOMESHARING_SERVICE, self)
         ServiceBrowser(zeroconf, DEVICE_SERVICE, self)
         ServiceBrowser(zeroconf, MEDIAREMOTE_SERVICE, self)
         ServiceBrowser(zeroconf, AIRPLAY_SERVICE, self)
         _LOGGER.debug('Discovering devices for %d seconds', timeout)
         await asyncio.sleep(timeout)
     finally:
         await zeroconf.close()
     return self._found_devices
コード例 #2
0
async def _discover(id: str, dns_type: str, single: bool):
    queue = asyncio.Queue()
    conf = Zeroconf(asyncio.get_event_loop(), address_family=[AF_INET])

    async def add_service(service_type, name):
        info = await conf.get_service_info(service_type, name)
        await queue.put(info)

    def sync_change_handler(_, service_type, name, state_change):
        if state_change is ServiceStateChange.Added:
            asyncio.create_task(add_service(service_type, name))

    try:
        ServiceBrowser(conf, dns_type, handlers=[sync_change_handler])
        match = f'{id}.local.'.lower() if id else None

        while True:
            info = await queue.get()
            addr = inet_ntoa(info.address)
            if addr == '0.0.0.0':
                continue  # discard simulators
            if match is None or info.server.lower() == match:
                serial = info.server[:-len('.local.')]
                yield addr, info.port, serial
                if single:
                    return
    finally:
        await conf.close()
コード例 #3
0
 def __start_service_discovery(self):
     '''Start zeroconf service discovery'''
     self.__zc = Zeroconf(self.__loop, address_family=[netifaces.AF_INET])
     self.__browser = ServiceBrowser(
         self.__zc,
         self.__service_type,
         handlers=[self.__on_service_state_change])
コード例 #4
0
    async def run_me(loop):
        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(loop, [netifaces.AF_INET], iface="lo")
        browser = ServiceBrowser(zeroconf_browser, type_,
                                 [on_service_state_change])

        zeroconf_registrar = Zeroconf(loop, [netifaces.AF_INET], iface="lo")
        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:
            await asyncio.sleep(1)
            assert service_added.is_set()
            # Don't remove service, allow close() to cleanup

        finally:
            await zeroconf_registrar.close()
            browser.cancel()
            await zeroconf_browser.close()
コード例 #5
0
ファイル: conftest.py プロジェクト: agmangas/wot-py
def asyncio_zeroconf():
    """Builds an aiozeroconf service instance and starts browsing for WoT Servient services.
    Provides a deque that contains the service state change history."""

    from aiozeroconf import Zeroconf, ServiceBrowser
    from wotpy.wot.discovery.dnssd.service import DNSSDDiscoveryService

    loop = tornado.ioloop.IOLoop.current()

    service_history = collections.deque([])

    def on_change(zc, service_type, name, state_change):
        service_history.append((service_type, name, state_change))

    aio_zc = Zeroconf(loop.asyncio_loop, address_family=[socket.AF_INET])
    ServiceBrowser(aio_zc,
                   DNSSDDiscoveryService.WOT_SERVICE_TYPE,
                   handlers=[on_change])

    yield {"zeroconf": aio_zc, "service_history": service_history}

    @tornado.gen.coroutine
    def close():
        yield aio_zc.close()

    loop.run_sync(close)
コード例 #6
0
ファイル: __main__.py プロジェクト: jnj16180340/aiozeroconf
def main():
    parser = argparse.ArgumentParser(
        description="Zeroconf service discovery tool")
    parser.add_argument('-i',
                        "--iface",
                        default="",
                        help="Name of the inteface to use.")
    parser.add_argument('-p',
                        "--protocol",
                        choices=['ipv4', 'ipv6', 'both'],
                        default="ipv4",
                        help="What IP protocol to use.")
    parser.add_argument("-s",
                        "--service",
                        default="_http._tcp.local.",
                        help="The service to browse.")
    parser.add_argument("-f",
                        "--find",
                        action='store_true',
                        default=False,
                        help="Find services")
    parser.add_argument("-d",
                        "--debug",
                        action='store_true',
                        default=False,
                        help="Set debug mode.")
    try:
        opts = parser.parse_args()
    except Exception as e:
        parser.error("Error: " + str(e))

    if opts.protocol == "ipv4":
        proto = [netifaces.AF_INET]
    elif opts.protocol == "ipv6":
        proto = [netifaces.AF_INET6]
    else:
        proto = [netifaces.AF_INET, netifaces.AF_INET6]

    loop = asyncio.get_event_loop()
    logging.basicConfig(level=logging.CRITICAL)
    if opts.debug:
        logging.getLogger('zeroconf').setLevel(logging.DEBUG)
        loop.set_debug(True)

    zc = Zeroconf(loop, proto, iface=opts.iface)
    print("\nBrowsing services, press Ctrl-C to exit...\n")

    try:
        if opts.find:
            loop.run_until_complete(list_service(zc))
        else:
            ServiceBrowser(zc,
                           guess(opts.service),
                           handlers=[on_service_state_change])
            loop.run_forever()
    except KeyboardInterrupt:
        print("Unregistering...")
        loop.run_until_complete(do_close(zc))
    finally:
        loop.close()
コード例 #7
0
ファイル: __init__.py プロジェクト: kdschlosser/pyatv
    async def discover(self, timeout):
        """Start discovery of devices and services."""
        zeroconf = Zeroconf(self.loop, address_family=[netifaces.AF_INET])
        browsers = []
        try:
            browsers += [
                ServiceBrowser(zeroconf, HOMESHARING_SERVICE, self),
                ServiceBrowser(zeroconf, DEVICE_SERVICE, self),
                ServiceBrowser(zeroconf, MEDIAREMOTE_SERVICE, self),
                ServiceBrowser(zeroconf, AIRPLAY_SERVICE, self),
            ]
            _LOGGER.debug("Discovering devices for %d seconds", timeout)
            await asyncio.sleep(timeout)

            if self.pending:
                await asyncio.wait(self.pending)
        finally:
            for browser in browsers:
                browser.cancel()
            await zeroconf.close()
        return self._found_devices
コード例 #8
0
    async def find(cls, zc, service, timeout=5, stop_after_first=STOP_AFTER_FIRST):
        """
        Return all of the advertised services on any local networks.
        :param zc: Zeroconf() instance.  Pass in an instance running
        :param timeout: seconds to wait for any responses
        :return: tuple of service type strings
        """
        listener = cls()
        browser = ServiceBrowser(zc, service, listener=listener)

        # wait for responses
        for i in range(100):
            await asyncio.sleep(timeout / 100)
            if len(listener.found_services) > 0 and STOP_AFTER_FIRST:
                break

        browser.cancel()
        # print(listener.found_services)
        return listener.found_services
コード例 #9
0
async def _discover(
    desired_id: Optional[str],
    dns_type: str,
) -> Generator[ConnectInfo, None, None]:
    queue: asyncio.Queue[ServiceInfo] = asyncio.Queue()
    conf = Zeroconf(asyncio.get_event_loop(), address_family=[AF_INET])

    async def add_service(service_type, name):
        info = await conf.get_service_info(service_type, name)
        await queue.put(info)

    def sync_change_handler(_, service_type, name, state_change):
        if state_change is ServiceStateChange.Added:
            asyncio.create_task(add_service(service_type, name))

    try:
        ServiceBrowser(conf, dns_type, handlers=[sync_change_handler])

        while True:
            info = await queue.get()
            if info.address in [None, SIM_ADDR]:
                continue  # discard unknown addresses and simulators

            addr = inet_ntoa(info.address)
            id = info.properties.get(b'ID', bytes()).decode().lower()

            if not id:
                LOGGER.error(
                    f'Invalid device: {info.name} @ {addr}:{info.port} has no ID TXT property'
                )
                continue
            elif desired_id is None or desired_id.lower() == id:
                LOGGER.info(f'Discovered {id} @ {addr}:{info.port}')
                yield ConnectInfo(addr, info.port, id)
            else:
                LOGGER.info(f'Discarding {info.name} @ {addr}:{info.port}')
    finally:
        await conf.close()
コード例 #10
0
ファイル: discovery.py プロジェクト: ohm-made/py-ohm-made
async def scan_devices(timeout=5):
    """
    Scan for devices on the network.

    :return: A list of devices found.
    """
    loop = asyncio.get_running_loop()
    zeroconf = Zeroconf(loop)
    devices = []

    def on_service_state_change(zc, service_type, name, change):
        host = name.split(".")[0] + ".local"
        host = socket.gethostbyname(host)
        device = Device(base_url=f"http://{host}")
        devices.append(device)

    ServiceBrowser(zeroconf,
                   "_ohm-led._tcp.local.",
                   handlers=[on_service_state_change])

    await asyncio.sleep(timeout)
    await zeroconf.close()

    return devices
コード例 #11
0
        async def run_me(loop):
            # instantiate a zeroconf instance
            zc = Zeroconf(loop, [netifaces.AF_INET], iface="lo")

            # 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
                await asyncio.sleep(0.1)

            browser.cancel()
            await asyncio.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 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))
            await asyncio.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()
            loop = asyncio.get_event_loop()
            loop.run_until_complete(run_me(loop))
コード例 #12
0
    else:
        print("  No info")
    print('\n')


async def do_close(zc):
    await zc.close()


if __name__ == '__main__':
    logging.basicConfig(level=logging.CRITICAL)
    if len(sys.argv) > 1:
        assert sys.argv[1:] == ['--debug']
        logging.getLogger('zeroconf').setLevel(logging.DEBUG)

    loop = asyncio.get_event_loop()
    loop.set_debug(True)

    zc = Zeroconf(loop)
    print("\nBrowsing services, press Ctrl-C to exit...\n")
    browser = ServiceBrowser(zc,
                             "_http._tcp.local.",
                             handlers=[on_service_state_change])
    try:
        loop.run_forever()
    except KeyboardInterrupt:
        print("Unregistering...")
        loop.run_until_complete(do_close(zc))
    finally:
        loop.close()
コード例 #13
0
 def start_yeelight_discovery(handler, gone_handler=None, iface=None):
     loop = aio.get_event_loop()
     zeroconf = Zeroconf(loop, iface=iface)
     listener = YeelightListener(handler, gone_handler)
     browser = ServiceBrowser(zeroconf, "_miio._udp.local.", listener)
     return zeroconf, browser
コード例 #14
0
ファイル: discovery.py プロジェクト: dduransseau/aiohue
 async def find_hue(zc):
     browser = ServiceBrowser(zc,
                              "_hue._tcp.local.",
                              handlers=[on_service_state_change])
     await asyncio.sleep(timeout)
     browser.cancel()
コード例 #15
0
                    default=False,
                    help="Set debug mode.")
try:
    opts = parser.parse_args()
except Exception as e:
    parser.error("Error: " + str(e))

if opts.protocol == "ipv4":
    proto = [netifaces.AF_INET]
elif opts.protocol == "ipv6":
    proto = [netifaces.AF_INET6]
else:
    proto = [netifaces.AF_INET, netifaces.AF_INET6]

loop = asyncio.get_event_loop()
logging.basicConfig(level=logging.CRITICAL)
if opts.debug:
    logging.getLogger('zeroconf').setLevel(logging.DEBUG)
    loop.set_debug(True)

zc = Zeroconf(loop, proto, iface=opts.iface)
print("\nBrowsing services, press Ctrl-C to exit...\n")
browser = ServiceBrowser(zc, opts.service, handlers=[on_service_state_change])
try:
    loop.run_forever()
except KeyboardInterrupt:
    print("Unregistering...")
    loop.run_until_complete(do_close(zc))
finally:
    loop.close()