def add_output_cluster(self, cluster_id): """Add an output cluster.""" from zigpy.zcl import Cluster cluster = Cluster.from_id(self, cluster_id) patch_cluster(cluster) self.out_clusters[cluster_id] = cluster
def add_input_cluster(self, cluster_id): """Add an input cluster.""" from zigpy.zcl import Cluster cluster = Cluster.from_id(self, cluster_id) patch_cluster(cluster) self.in_clusters[cluster_id] = cluster if hasattr(cluster, 'ep_attribute'): setattr(self, cluster.ep_attribute, cluster)
def from_buffer(cls, cluster_id, buffer): if buffer.length < MINIMAL_FRAME_LENGTH: raise Exception("ZclFrame length is lower than minimal length") header = ZCLHeader.deserialize(buffer) cluster = Cluster.from_id(None, cluster_id) # cluster = Utils.getCluster( # clusterID, # header.frameControl.manufacturerSpecific ? header.manufacturerCode: null # ); payload = cls.parse_payload(header, cluster, buffalo) return cls(header, payload, cluster);
def test_incomming_msg2(): ''' zigpy_cc.api DEBUG --> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 0, 'srcaddr': 4835, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 110, 'securityuse': 0, 'timestamp': 8255669, 'transseqnumber': 0, 'len': 29, 'data': b'\x1c4\x12\x02\n\x02\xffL\x06\x00\x10\x00!\xce\x0b!\xa8\x01$\x00\x00\x00\x00\x00!\xbdJ ]'} ''' epmock = mock.MagicMock() cls = Cluster.from_id(epmock, 0) hdr, data = cls.deserialize( b'\x1c\x34\x12\x02\x0a\x02\xffL\x06\x00\x10\x00!\xce\x0b!\xa8\x01$\x00\x00\x00\x00\x00!\xbdJ ]') assert str( hdr) == '<ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=True is_reply=False disable_default_response=True> manufacturer=4660 tsn=2 command_id=Command.Report_Attributes>'
def test_incomming_msg(): ''' zigpy_cc.api DEBUG --> AREQ AF incomingMsg {'groupid': 0, 'clusterid': 0, 'srcaddr': 28294, 'srcendpoint': 1, 'dstendpoint': 1, 'wasbroadcast': 0, 'linkquality': 115, 'securityuse': 0, 'timestamp': 15812278, 'transseqnumber': 0, 'len': 25, 'data': b'\x18\x00\n\x05\x00B\x12lumi.sensor_switch'} ZLC msg not ZDO ''' epmock = mock.MagicMock() cls = Cluster.from_id(epmock, 0) hdr, data = cls.deserialize(b'\x18\x00\n\x05\x00B\x12lumi.sensor_switch') assert str(data) == '[[<Attribute attrid=5 value=<TypeValue type=CharacterString, value=lumi.sensor_switch>>]]' assert str( hdr) == '<ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=False disable_default_response=True> manufacturer=None tsn=0 command_id=Command.Report_Attributes>'
def get_cluster_attr_data(cluster: Cluster) -> dict: """Return cluster attribute data.""" return { ATTRIBUTES: { f"0x{attr_id:04x}": { ATTR_ATTRIBUTE_NAME: attr_def.name, ATTR_VALUE: attr_value, } for attr_id, attr_def in cluster.attributes.items() if (attr_value := cluster.get(attr_def.name)) is not None }, UNSUPPORTED_ATTRIBUTES: { f"0x{cluster.find_attribute(u_attr).id:04x}": { ATTR_ATTRIBUTE_NAME: cluster.find_attribute(u_attr).name } for u_attr in cluster.unsupported_attributes }, }
def decode(data: dict): """Decode Silabs Z3 GatewayHost MQTT message using zigpy library. Supports ZDO payload and ZCL payload. """ try: if data["sourceEndpoint"] == "0x00": # decode ZDO if "zdo" not in CLUSTERS: zdo = CLUSTERS["zdo"] = ZDO(None) else: zdo = CLUSTERS["zdo"] cluster_id = int(data['clusterId'], 0) raw = bytes.fromhex(data['APSPlayload'][2:]) hdr, args = zdo.deserialize(cluster_id, raw) if hdr.command_id == ZDOCmd.Active_EP_rsp: return { "command": str(hdr.command_id), "status": str(args[0]), "endpoints": args[2] } elif hdr.command_id == ZDOCmd.Simple_Desc_rsp: desc: SizePrefixedSimpleDescriptor = args[2] return { "command": str(hdr.command_id), "status": str(args[0]), "device_type": desc.device_type, "device_version": desc.device_version, "endpoint": desc.endpoint, "input_clusters": desc.input_clusters, "output_clusters": desc.output_clusters, "profile": desc.profile } elif hdr.command_id == ZDOCmd.Node_Desc_rsp: desc: NodeDescriptor = args[2] return { "command": str(hdr.command_id), "status": str(args[0]), "is_mains_powered": desc.is_mains_powered, "logical_type": str(desc.logical_type), "manufacturer_code": desc.manufacturer_code, } elif hdr.command_id in (ZDOCmd.Bind_rsp, ZDOCmd.Mgmt_Leave_rsp): return { "command": str(hdr.command_id), "status": str(args[0]), } elif hdr.command_id in ( ZDOCmd.Node_Desc_req, ZDOCmd.Active_EP_req ): return {"command": str(hdr.command_id)} elif hdr.command_id == ZDOCmd.Simple_Desc_req: return { "command": str(hdr.command_id), "endpoint": args[0], } elif hdr.command_id == ZDOCmd.Bind_req: return { "command": str(hdr.command_id), "src_addr": args[0], "src_endpoint": args[1], "cluster": args[2], "dst_addr": args[3] } elif hdr.command_id == ZDOCmd.IEEE_addr_rsp: return { "command": str(hdr.command_id), "status": args[0], "ieee": args[1], "nwk": args[2], } elif hdr.command_id == ZDOCmd.Mgmt_Leave_req: return { "command": str(hdr.command_id), "ieee": args[0], } elif hdr.command_id == ZDOCmd.Mgmt_NWK_Update_rsp: return { "command": str(hdr.command_id), "status": args[0], "channels": args[1], "total": args[2], "failures": args[3], "energy": args[4], } else: raise NotImplemented # decode ZCL cluster_id = int(data['clusterId'], 0) if cluster_id not in CLUSTERS: cluster = CLUSTERS[cluster_id] = Cluster.from_id(None, cluster_id) cluster._log = lambda *_, **__: None else: cluster = CLUSTERS[cluster_id] raw = bytes.fromhex(data['APSPlayload'][2:]) try: hdr, args = cluster.deserialize(raw) hdr: ZCLHeader except ValueError as e: return {"cluster_id": cluster_id, "error": str(e)} except KeyError as e: return {"cluster_id": cluster_id, "error": f"Key error: {e}"} payload = { "endpoint": int(data["sourceEndpoint"], 0), "seq": hdr.tsn, } if cluster.ep_attribute: payload["cluster"] = cluster.ep_attribute else: payload["cluster_id"] = cluster_id if hdr.frame_control.is_general: payload["command"] = str(hdr.command_id) if (hdr.command_id == Command.Report_Attributes or hdr.command_id == Command.Write_Attributes): attrs, = args for attr in attrs: assert isinstance(attr, Attribute) if attr.attrid in cluster.attributes: name = cluster.attributes[attr.attrid][0] else: name = attr.attrid value = attr.value.value if isinstance(value, bytes) and value: payload[name] = "0x" + value.hex() elif isinstance(value, list) and \ not isinstance(value, EUI64): payload[name] = [v.value for v in value] elif isinstance(value, int): payload[name] = int(value) else: payload[name] = value elif hdr.command_id == Command.Read_Attributes_rsp: attrs, = args for attr in attrs: assert isinstance(attr, ReadAttributeRecord) if attr.attrid in cluster.attributes: name = cluster.attributes[attr.attrid][0] else: name = attr.attrid if attr.value is not None: value = attr.value.value if isinstance(value, bytes) and value: payload[name] = "0x" + value.hex() elif isinstance(value, list): payload[name] = [v.value for v in value] elif isinstance(value, int): payload[name] = int(value) else: payload[name] = value else: payload[name] = str(attr.status) elif hdr.command_id == Command.Read_Attributes: attrs, = args payload["value"] = attrs elif hdr.command_id == Command.Configure_Reporting: attrs, = args # fix __repr__ bug for attr in attrs: if not hasattr(attr, "reportable_change"): attr.reportable_change = None payload["value"] = attrs elif (hdr.command_id == Command.Write_Attributes_rsp or hdr.command_id == Command.Configure_Reporting_rsp): resp, = args payload["status"] = [str(attr.status) for attr in resp] elif hdr.command_id == Command.Discover_Commands_Received_rsp: payload["status"] = bool(args[0]) payload["value"] = args[1] elif hdr.command_id == Command.Default_Response: payload["value"] = args[0] payload["status"] = str(args[1]) else: if isinstance(args, bytes) and args: args = "0x" + args.hex() payload["command_id"] = int(hdr.command_id) payload["value"] = args elif hdr.frame_control.is_cluster: # if isinstance(args, bytes) and args: # args = "0x" + args.hex() payload["command_id"] = hdr.command_id if hdr.command_id < len(cluster.commands): payload["command"] = cluster.commands[hdr.command_id] if args: payload["value"] = args else: if isinstance(args, bytes) and args: args = "0x" + args.hex() payload.update({"command_id": hdr.command_id, "value": args}) return payload except Exception as e: _LOGGER.debug("Error while parsing zigbee", exc_info=e) return None