Example #1
0
    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
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
    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);
Example #5
0
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>'
Example #6
0
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>'
Example #7
0
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
        },
    }
Example #8
0
 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
Example #9
0
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