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
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
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
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
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
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
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
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
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
def deserialize(cls, data): args, data = t.deserialize(data, cls.SCHEMA) return cls(*args), data