Beispiel #1
0
async def test_neighbors_scan(neighbours_f, device):
    """Test scanning."""

    data_in = (
        b'\x00\x10\x00\x03h\xf1W\xde\xcb\xaf4"\xfa\x0e\n\x00\x00\xa3"\x00)\x03%\x02'
        b'\x0f\xffh\xf1W\xde\xcb\xaf4"\x12Q\x03\xfe\xff^\xcf\xd0\xd4\x14%\x02\x0f\xfeh'
        b'\xf1W\xde\xcb\xaf4"&R \x00\x00\xa3"\x00\xd2\'%\x02\x0f\xff',
        b'\x00\x10\x03\x03h\xf1W\xde\xcb\xaf4"\x83\x19!\x00\x00\xa3"\x00\x10A%\x02\x0f'
        b'\xffh\xf1W\xde\xcb\xaf4"\xa8` \x00\x00\xa3"\x00\xe9e%\x02\x0f\xffh\xf1W\xde'
        b'\xcb\xaf4")\xb9\xda\xfe\xff\xcc\xcc\xccXw%\x02\x0f\xff',
        b'\x00\x10\x06\x03h\xf1W\xde\xcb\xaf4"`\xda!\x00\x00\xa3"\x00Z\x99%\x02\x0f'
        b'\xfeh\xf1W\xde\xcb\xaf4"\xe6\x8f\xd9\xfe\xff\xcc\xcc\xcc\xc3\x9b%\x02\x0f'
        b'\xffh\xf1W\xde\xcb\xaf4"p\xac$\xfe\xff\xd7k\x08f\xa5%\x02\x0f\xff',
        b'\x00\x10\t\x03h\xf1W\xde\xcb\xaf4"\x16\xed\x00\x00\x00\xa3"\x00\xf0\xb7%\x02'
        b'\x0f\xffh\xf1W\xde\xcb\xaf4"mn\x1c\x00\x00\xa3"\x00p\xda%\x02\x0f\xffh\xf1W'
        b'\xde\xcb\xaf4"\x80\xf4\xa6\x0c\x00o\r\x00\x9c\xda%\x02\x0f\xff',
        b'\x00\x10\x0c\x03h\xf1W\xde\xcb\xaf4"\xf48\xed\x18\x00K\x12\x009\xe8%\x02\x0f'
        b'\xfdh\xf1W\xde\xcb\xaf4"B\xd9!\x00\x00\xa3"\x00\x83\xed%\x02\x0f\xfeh\xf1W'
        b'\xde\xcb\xaf4"\xfe-\xed\x18\x00K\x12\x00\x1e\xf0%\x02\x0f\xfe',
        b'\x00\x10\x0f\x01h\xf1W\xde\xcb\xaf4"\x93\x13\x05\x00\x00\xb8\xd1\xf0\n\xf2%'
        b"\x02\x0f\xfc",
    )
    listener = MagicMock()
    neighbours_f.add_listener(listener)
    schema = zdo_t.CLUSTERS[zdo_t.ZDOCmd.Mgmt_Lqi_rsp][1]
    device.zdo.request.side_effect = (t.deserialize(d, schema)[0]
                                      for d in data_in)

    assert neighbours_f.neighbors == []
    res = await neighbours_f.scan()
    assert res
    assert neighbours_f.neighbors
    assert listener.neighbors_updated.call_count == 1
Beispiel #2
0
    def deserialize(self, data):
        hdr, data = foundation.ZCLHeader.deserialize(data)
        self.debug("ZCL deserialize: %s", hdr)
        if hdr.frame_control.frame_type == foundation.FrameType.CLUSTER_COMMAND:
            # Cluster command
            if hdr.is_reply:
                commands = self.client_commands
            else:
                commands = self.server_commands

            try:
                schema = commands[hdr.command_id][1]
                hdr.frame_control.is_reply = commands[hdr.command_id][2]
            except KeyError:
                self.warning("Unknown cluster-specific command %s",
                             hdr.command_id)
                return hdr, data
        else:
            # General command
            try:
                schema = foundation.COMMANDS[hdr.command_id][0]
                hdr.frame_control.is_reply = foundation.COMMANDS[
                    hdr.command_id][1]
            except KeyError:
                self.warning("Unknown foundation command %s", hdr.command_id)
                return hdr, data

        value, data = t.deserialize(data, schema)
        if data != b"":
            self.warning("Data remains after deserializing ZCL frame")

        return hdr, value
Beispiel #3
0
    def deserialize(self, tsn, frame_type, is_reply, command_id, data):
        if frame_type == 1:
            # Cluster command
            if is_reply:
                commands = self.client_commands
            else:
                commands = self.server_commands

            try:
                schema = commands[command_id][1]
                is_reply = commands[command_id][2]
            except KeyError:
                LOGGER.warning("Unknown cluster-specific command %s",
                               command_id)
                return tsn, command_id + 256, is_reply, data

            # Bad hack to differentiate foundation vs cluster
            command_id = command_id + 256
        else:
            # General command
            try:
                schema = foundation.COMMANDS[command_id][1]
                is_reply = foundation.COMMANDS[command_id][2]
            except KeyError:
                LOGGER.warning("Unknown foundation command %s", command_id)
                return tsn, command_id, is_reply, data

        value, data = t.deserialize(data, schema)
        if data != b'':
            LOGGER.warning("Data remains after deserializing ZCL frame")

        return tsn, command_id, is_reply, value
        def deserialize(self, data):
            """Deserialize."""
            hdr, data = foundation.ZCLHeader.deserialize(data)
            self.debug("ZCL deserialize: %s", hdr)
            if hdr.frame_control.frame_type == \
                    foundation.FrameType.CLUSTER_COMMAND:
                # Cluster command
                if hdr.is_reply:
                    commands = self.client_commands
                else:
                    commands = self.server_commands

                try:
                    schema = commands[hdr.command_id][1]
                    is_reply = commands[hdr.command_id][2]
                except KeyError:
                    data = struct.pack(
                        '>i',
                        hdr.tsn)[-1:] + \
                           struct.pack('>i', hdr.command_id)[-1:] + data
                    new_command_id = ON_OFF_CMD
                    try:
                        schema = commands[new_command_id][1]
                        is_reply = commands[new_command_id][2]
                    except KeyError:
                        self.warn("Unknown cluster-specific command %s",
                                  hdr.command_id)
                        return \
                            hdr.tsn, hdr.command_id + 256, hdr.is_reply, data
                    value, data = t.deserialize(data, schema)
                    return hdr.tsn, new_command_id, hdr.is_reply, value
                # Bad hack to differentiate foundation vs cluster
                hdr.command_id = hdr.command_id + 256
            else:
                # General command
                try:
                    schema = foundation.COMMANDS[hdr.command_id][0]
                    is_reply = foundation.COMMANDS[hdr.command_id][1]
                except KeyError:
                    self.warn("Unknown foundation command %s", hdr.command_id)
                    return hdr.tsn, hdr.command_id, hdr.is_reply, data

            value, data = t.deserialize(data, schema)
            if data != b'':
                _LOGGER.warning("Data remains after deserializing ZCL frame")
            return hdr.tsn, hdr.command_id, is_reply, value
Beispiel #5
0
    def deserialize(self, cluster_id, data):
        hdr, data = types.ZDOHeader.deserialize(cluster_id, data)
        try:
            cluster_details = types.CLUSTERS[cluster_id]
        except KeyError:
            self.warning("Unknown ZDO cluster 0x%04x", cluster_id)
            return hdr, data

        args, data = t.deserialize(data, cluster_details[1])
        if data != b"":
            # TODO: Seems sane to check, but what should we do?
            self.warning("Data remains after deserializing ZDO frame")

        return hdr, args
Beispiel #6
0
def deserialize(cluster_id, data):
    frame_control, data = data[0], data[1:]
    frame_type = frame_control & 0b0011
    direction = (frame_control & 0b1000) >> 3
    if frame_control & 0b0100:
        # Manufacturer specific value present
        data = data[2:]
    tsn, command_id, data = data[0], data[1], data[2:]

    is_reply = bool(direction)

    if frame_type == 1:
        # Cluster command
        if cluster_id not in Cluster._registry:
            LOGGER.debug("Ignoring unknown cluster ID 0x%04x",
                         cluster_id)
            return tsn, command_id + 256, is_reply, data
        cluster = Cluster._registry[cluster_id]
        # Cluster-specific command

        if direction:
            commands = cluster.client_commands
        else:
            commands = cluster.server_commands

        try:
            schema = commands[command_id][1]
            is_reply = commands[command_id][2]
        except KeyError:
            LOGGER.warning("Unknown cluster-specific command %s", command_id)
            return tsn, command_id + 256, is_reply, data

        # Bad hack to differentiate foundation vs cluster
        command_id = command_id + 256
    else:
        # General command
        try:
            schema = foundation.COMMANDS[command_id][1]
            is_reply = foundation.COMMANDS[command_id][2]
        except KeyError:
            LOGGER.warning("Unknown foundation command %s", command_id)
            return tsn, command_id, is_reply, data

    value, data = t.deserialize(data, schema)
    if data != b'':
        # TODO: Seems sane to check, but what should we do?
        LOGGER.warning("Data remains after deserializing ZCL frame")

    return tsn, command_id, is_reply, value
Beispiel #7
0
    def deserialize(self, cluster_id, data):
        tsn, data = data[0], data[1:]

        is_reply = bool(cluster_id & 0x8000)
        try:
            cluster_details = types.CLUSTERS[cluster_id]
        except KeyError:
            LOGGER.warning("Unknown ZDO cluster 0x%02x", cluster_id)
            return tsn, cluster_id, is_reply, data

        args, data = t.deserialize(data, cluster_details[2])
        if data != b'':
            # TODO: Seems sane to check, but what should we do?
            LOGGER.warning("Data remains after deserializing ZDO frame")

        return tsn, cluster_id, is_reply, args
Beispiel #8
0
async def test_neighbors_invalid_ieee(neighbours_f, device):
    """Test scanning."""

    data_in = (
        b'\x00\x02\x00\x02h\xf1W\xde\xcb\xaf4"\xff\xff\xff\xff\xff\xff\xff\xff)\x03'
        b'%\x02\x0f\xffh\xf1W\xde\xcb\xaf4"\x00\x00\x00\x00\x00\x00\x00\x00\x15\x14'
        b"%\x02\x0f\xfe", )

    listener = MagicMock()
    neighbours_f.add_listener(listener)
    schema = zdo_t.CLUSTERS[zdo_t.ZDOCmd.Mgmt_Lqi_rsp][1]
    device.zdo.request.side_effect = (t.deserialize(d, schema)[0]
                                      for d in data_in)

    assert neighbours_f.neighbors == []
    res = await neighbours_f.scan()
    assert res == []
    assert neighbours_f.neighbors == []
    assert listener.neighbors_updated.call_count == 1
Beispiel #9
0
    def deserialize(self, cluster_id, data):
        tsn, data = data[0], data[1:]

        is_reply = bool(cluster_id & 0x8000)
        try:
            cluster_id = types.ZDOCmd(cluster_id)
        except ValueError:
            self.warn("Unsupported ZDO cluster id 0x%04x", cluster_id)
        try:
            cluster_details = types.CLUSTERS[cluster_id]
        except KeyError:
            self.warn("Unknown ZDO cluster 0x%04x", cluster_id)
            return tsn, cluster_id, is_reply, data

        args, data = t.deserialize(data, cluster_details[1])
        if data != b"":
            # TODO: Seems sane to check, but what should we do?
            self.warn("Data remains after deserializing ZDO frame")

        return tsn, cluster_id, is_reply, args
Beispiel #10
0
def handle_quick_init(
    sender: zigpy.device.Device,
    profile: int,
    cluster: int,
    src_ep: int,
    dst_ep: int,
    message: bytes,
) -> Optional[bool]:
    """Handle message from an uninitialized device which could be a xiaomi."""
    if src_ep == 0:
        return

    hdr, data = foundation.ZCLHeader.deserialize(message)
    sender.debug(
        """Received ZCL while uninitialized on endpoint id %s, cluster 0x%04x """
        """id, hdr: %s, payload: %s""",
        src_ep,
        cluster,
        hdr,
        data,
    )
    if hdr.frame_control.is_cluster:
        return

    try:
        schema = foundation.COMMANDS[hdr.command_id][0]
        args, data = t.deserialize(data, schema)
    except (KeyError, ValueError):
        sender.debug("Failed to deserialize ZCL global command")
        return

    sender.debug("Uninitialized device command '%s' args: %s", hdr.command_id,
                 args)
    if hdr.command_id != foundation.Command.Report_Attributes or cluster != 0:
        return

    for attr_rec in args[0]:
        if attr_rec.attrid == 5:
            break
    else:
        return

    model = attr_rec.value.value
    if not model:
        return

    for quirk in zigpy.quirks.get_quirk_list(LUMI, model):
        if issubclass(quirk, XiaomiQuickInitDevice):
            sender.debug("Found '%s' quirk for '%s' model", quirk.__name__,
                         model)
            try:
                sender = quirk.from_signature(sender, model)
            except (AssertionError, KeyError) as ex:
                _LOGGER.debug(
                    "Found quirk for quick init, but failed to init: %s",
                    str(ex))
                continue
            break
    else:
        return

    sender.cancel_initialization()
    sender.application.device_initialized(sender)
    sender.info("Was quickly initialized from '%s.%s' quirk", quirk.__module__,
                quirk.__name__)
    return True
Beispiel #11
0
 def deserialize(cls, data):
     args, data = t.deserialize(data, cls.SCHEMA)
     return cls(*args), data