Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_size_prefixed_simple_descriptor():
sd = types.SizePrefixedSimpleDescriptor()
sd.endpoint = t.uint8_t(1)
sd.profile = t.uint16_t(2)
sd.device_type = t.uint16_t(3)
sd.device_version = t.uint8_t(4)
sd.input_clusters = t.LVList(t.uint16_t)([t.uint16_t(5), t.uint16_t(6)])
sd.output_clusters = t.LVList(t.uint16_t)([t.uint16_t(7), t.uint16_t(8)])
ser = sd.serialize()
assert ser[0] == len(ser) - 1
sd2, data = types.SizePrefixedSimpleDescriptor.deserialize(ser + b"extra")
assert sd.input_clusters == sd2.input_clusters
assert sd.output_clusters == sd2.output_clusters
assert isinstance(sd2, types.SizePrefixedSimpleDescriptor)
assert data == b"extra"
def test_lvlist():
d, r = t.LVList(t.uint8_t).deserialize(b"\x0412345")
assert r == b"5"
assert d == list(map(ord, "1234"))
assert t.LVList(t.uint8_t).serialize(d) == b"\x041234"
STATUS,
NWKI,
("NodeDescriptor", t.Optional(NodeDescriptor)),
),
ZDOCmd.Power_Desc_rsp: (
STATUS,
NWKI,
("PowerDescriptor", t.Optional(PowerDescriptor)),
),
ZDOCmd.Simple_Desc_rsp: (
STATUS,
NWKI,
("SimpleDescriptor", t.Optional(SizePrefixedSimpleDescriptor)),
),
ZDOCmd.Active_EP_rsp: (STATUS, NWKI, ("ActiveEPList", t.LVList(t.uint8_t))),
ZDOCmd.Match_Desc_rsp: (STATUS, NWKI, ("MatchList", t.LVList(t.uint8_t))),
# ZDO.Complex_Desc_rsp: (
# STATUS,
# NWKI,
# ('Length', t.uint8_t),
# ('ComplexDescriptor', t.Optional(ComplexDescriptor)),
# ),
ZDOCmd.User_Desc_rsp: (
STATUS,
NWKI,
("Length", t.uint8_t),
("UserDescriptor", t.Optional(t.fixed_list(16, t.uint8_t))),
),
ZDOCmd.Discovery_Cache_rsp: (STATUS,),
ZDOCmd.User_Desc_conf: (STATUS, NWKI),
ZDOCmd.System_Server_Discovery_rsp: (STATUS, ("ServerMask", t.uint16_t)),
ZDOCmd.Discovery_Store_rsp: (STATUS,),
"zone_status_changed",
(t.uint8_t, ZoneStatus, AudibleNotification, t.CharacterString),
False,
),
0x0004: (
"panel_status_changed",
(PanelStatus, t.uint8_t, AudibleNotification, AlarmStatus),
False,
),
0x0005: (
"panel_status_response",
(PanelStatus, t.uint8_t, AudibleNotification, AlarmStatus),
True,
),
0x0006: ("set_bypassed_zone_list", (t.LVList(t.uint8_t),), False),
0x0007: ("bypass_response", (t.LVList(BypassResponse),), True),
0x0008: ("get_zone_status_response", (t.Bool, t.LVList(ZoneStatusRsp)), True),
}
class Strobe(t.enum8):
No_strobe = 0x00
Strobe = 0x01
class _SquawkOrWarningCommand:
def __init__(self, value: int = 0) -> None:
self.value = t.uint8_t(value)
@classmethod
def deserialize(cls, data: bytes) -> Tuple["_SquawkOrWarningCommand", bytes]:
val, data = t.uint8_t.deserialize(data)
0x0007: ("energy_phases_schedule_state_request", (t.uint8_t,), False),
0x0008: (
"get_power_profile_price_extended_response",
(t.uint8_t, t.uint16_t, t.uint32_t, t.uint8_t),
True,
),
}
client_commands = {
0x0000: (
"power_profile_notification",
(t.uint8_t, t.uint8_t, t.LVList(PowerProfilePhase)),
False,
),
0x0001: (
"power_profile_response",
(t.uint8_t, t.uint8_t, t.LVList(PowerProfilePhase)),
True,
),
0x0002: ("power_profile_state_response", (t.LVList(PowerProfile),), True),
0x0003: ("get_power_profile_price", (t.uint8_t,), False),
0x0004: ("power_profile_state_notification", (t.LVList(PowerProfile),), False),
0x0005: ("get_overall_schedule_price", (), False),
0x0006: ("energy_phases_schedule_request", (), False),
0x0007: ("energy_phases_schedule_state_response", (t.uint8_t, t.uint8_t), True),
0x0008: (
"energy_phases_schedule_state_notification",
(t.uint8_t, t.uint8_t),
False,
),
0x0009: (
"power_profile_schedule_constraints_notification",
(t.uint8_t, t.uint16_t, t.uint16_t),
import zigpy.types as t
class PowerDescriptor(t.Struct):
byte_1: t.uint8_t
byte_2: t.uint8_t
# TODO: interpret the four 4-bit fields
class SimpleDescriptor(t.Struct):
endpoint: t.uint8_t
profile: t.uint16_t
device_type: t.uint16_t
device_version: t.uint8_t
input_clusters: t.LVList(t.uint16_t)
output_clusters: t.LVList(t.uint16_t)
class SizePrefixedSimpleDescriptor(SimpleDescriptor):
def serialize(self):
data = super().serialize()
return len(data).to_bytes(1, "little") + data
@classmethod
def deserialize(cls, data):
if not data or data[0] == 0:
return None, data[1:]
return super().deserialize(data[1:])
class LogicalType(t.enum8):
0x0040: ("trigger_effect", (t.uint8_t, t.uint8_t), False),
}
client_commands = {0x0000: ("identify_query_response", (t.uint16_t,), True)}
class Groups(Cluster):
"""Attributes and commands for group configuration and
manipulation."""
cluster_id = 0x0004
ep_attribute = "groups"
attributes = {0x0000: ("name_support", t.bitmap8)}
server_commands = {
0x0000: ("add", (t.Group, t.CharacterString), False),
0x0001: ("view", (t.Group,), False),
0x0002: ("get_membership", (t.LVList(t.Group),), False),
0x0003: ("remove", (t.Group,), False),
0x0004: ("remove_all", (), False),
0x0005: ("add_if_identifying", (t.Group, t.CharacterString), False),
}
client_commands = {
0x0000: ("add_response", (foundation.Status, t.Group), True),
0x0001: (
"view_response",
(foundation.Status, t.Group, t.CharacterString),
True,
),
0x0002: ("get_membership_response", (t.uint8_t, t.LVList(t.Group)), True),
0x0003: ("remove_response", (foundation.Status, t.Group), True),
}
ZoneType = IasZone.ZoneType
ZoneStatus = IasZone.ZoneStatus
class ZoneStatusRsp(t.Struct):
"""Zone status response."""
zone_id: t.uint8_t
zone_status: IasZone.ZoneStatus
cluster_id = 0x0501
name = "IAS Ancillary Control Equipment"
ep_attribute = "ias_ace"
attributes = {}
server_commands = {
0x0000: ("arm", (ArmMode, t.CharacterString, t.uint8_t), False),
0x0001: ("bypass", (t.LVList(t.uint8_t), t.CharacterString), False),
0x0002: ("emergency", (), False),
0x0003: ("fire", (), False),
0x0004: ("panic", (), False),
0x0005: ("get_zone_id_map", (), False),
0x0006: ("get_zone_info", (t.uint8_t,), False),
0x0007: ("get_panel_status", (), False),
0x0008: ("get_bypassed_zone_list", (), False),
0x0009: ("get_zone_status", (t.uint8_t, t.uint8_t, t.Bool, ZoneStatus), False),
}
client_commands = {
0x0000: ("arm_response", (ArmNotification,), True),
0x0001: ("get_zone_id_map_response", (t.List(t.bitmap16),), True),
0x0002: (
"get_zone_info_response",
(t.uint8_t, ZoneType, t.EUI64, t.CharacterString),
True,
t.Optional(t.uint8_t),
t.Optional(t.int16s),
t.Optional(t.int16s),
t.Optional(t.int16s),
t.Optional(t.uint16_t),
t.Optional(t.uint8_t),
t.Optional(t.uint8_t),
t.Optional(t.uint16_t),
),
True,
),
0x0002: ("location_data_notification", (), False),
0x0003: ("compact_location_data_notification", (), False),
0x0004: ("rssi_ping", (t.uint8_t,), False), # data8
0x0005: ("rssi_req", (), False),
0x0006: ("report_rssi_measurements", (t.EUI64, t.LVList(NeighborInfo)), False),
0x0007: ("request_own_location", (t.EUI64,), False),
}
class AnalogInput(Cluster):
cluster_id = 0x000C
ep_attribute = "analog_input"
attributes = {
0x001C: ("description", t.CharacterString),
0x0041: ("max_present_value", t.Single),
0x0045: ("min_present_value", t.Single),
0x0051: ("out_of_service", t.Bool),
0x0055: ("present_value", t.Single),
0x0067: ("reliability", t.enum8),
0x006A: ("resolution", t.Single),
0x006F: ("status_flags", t.bitmap8),