Пример #1
0
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
Пример #3
0
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()
Пример #4
0
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)
Пример #5
0
 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
Пример #6
0
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()
Пример #7
0
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)
Пример #8
0
    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
Пример #9
0
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())
Пример #10
0
 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')
Пример #12
0
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
Пример #13
0
    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
Пример #15
0
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
Пример #16
0
    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.")
Пример #17
0
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()
Пример #18
0
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
Пример #19
0
 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
Пример #20
0
    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)
Пример #21
0
 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)
Пример #22
0
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
Пример #23
0
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
Пример #24
0
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
Пример #25
0
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
Пример #26
0
 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)
Пример #27
0
    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)
Пример #28
0
    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'))
Пример #29
0
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
Пример #30
0
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
Пример #31
0
    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
Пример #32
0
 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)
Пример #33
0
 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
Пример #34
0
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()
Пример #36
0
    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')
Пример #37
0
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')
Пример #38
0
 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
Пример #39
0
    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()
Пример #40
0
    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()
Пример #41
0
 def add_service(
     self, _zeroconf: zeroconf.Zeroconf, _type: str, name: str
 ) -> None:
     """Add service."""
     self.services[name] = _zeroconf.get_service_info(_type, name)
Пример #42
0
    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()
Пример #43
0
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()
Пример #44
0
    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()
Пример #45
0
#!/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()
Пример #46
0
 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
Пример #47
0
        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()