Skip to content

Commit 89ea58d

Browse files
committed
Add skeleton
1 parent 4fcf1c1 commit 89ea58d

File tree

4 files changed

+459
-0
lines changed

4 files changed

+459
-0
lines changed

tests/test_schneiderelectric.py

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
"""Tests for Schneider Electric."""
2+
from unittest import mock
3+
4+
import zigpy.device
5+
import zigpy.endpoint
6+
import zigpy.quirks
7+
from zigpy.zcl import foundation
8+
import zigpy.zdo.types as zdo_t
9+
10+
import zhaquirks
11+
import zhaquirks.kof.kof_mr101z
12+
13+
from tests.conftest import CoroutineMock
14+
15+
zhaquirks.setup()
16+
17+
Default_Response = foundation.GENERAL_COMMANDS[
18+
foundation.GeneralCommand.Default_Response
19+
].schema
20+
21+
22+
async def test_nhpb_shutter_1_signature(assert_signature_matches_quirk):
23+
signature = {
24+
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4190, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)",
25+
"endpoints": {
26+
"5": {
27+
"profile_id": 260,
28+
"device_type": "0x0202",
29+
"in_clusters": [
30+
"0x0000",
31+
"0x0003",
32+
"0x0004",
33+
"0x0005",
34+
"0x0102",
35+
"0x0b05",
36+
],
37+
"out_clusters": ["0x0019"],
38+
},
39+
"21": {
40+
"profile_id": 260,
41+
"device_type": "0x0104",
42+
"in_clusters": ["0x0000", "0x0003", "0x0b05", "0xff17"],
43+
"out_clusters": [
44+
"0x0003",
45+
"0x0004",
46+
"0x0005",
47+
"0x0006",
48+
"0x0008",
49+
"0x0102",
50+
],
51+
},
52+
"242": {
53+
"profile_id": 41440,
54+
"device_type": "0x0061",
55+
"in_clusters": [],
56+
"out_clusters": ["0x0021"],
57+
},
58+
},
59+
"manufacturer": "Schneider Electric",
60+
"model": "NHPB/SHUTTER/1",
61+
"class": "zigpy.device.Device",
62+
}
63+
assert_signature_matches_quirk(
64+
zhaquirks.schneiderelectric.shutter.NHPBShutter1, signature
65+
)
66+
67+
68+
async def test_fls_air_link_4_signature(assert_signature_matches_quirk):
69+
signature = {
70+
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4190, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
71+
"endpoints": {
72+
"21": {
73+
"profile_id": 260,
74+
"device_type": "0x0104",
75+
"in_clusters": ["0x0000", "0x0001", "0x0003", "0x0020", "0xff17"],
76+
"out_clusters": [
77+
"0x0003",
78+
"0x0004",
79+
"0x0005",
80+
"0x0006",
81+
"0x0008",
82+
"0x0019",
83+
"0x0102",
84+
],
85+
},
86+
"22": {
87+
"profile_id": 260,
88+
"device_type": "0x0104",
89+
"in_clusters": ["0x0000", "0x0001", "0x0003", "0xff17"],
90+
"out_clusters": [
91+
"0x0003",
92+
"0x0004",
93+
"0x0005",
94+
"0x0006",
95+
"0x0008",
96+
"0x0102",
97+
],
98+
},
99+
"23": {
100+
"profile_id": 260,
101+
"device_type": "0x0104",
102+
"in_clusters": ["0x0000", "0x0001", "0x0003", "0xff17"],
103+
"out_clusters": [
104+
"0x0003",
105+
"0x0004",
106+
"0x0005",
107+
"0x0006",
108+
"0x0008",
109+
"0x0102",
110+
],
111+
},
112+
"24": {
113+
"profile_id": 260,
114+
"device_type": "0x0104",
115+
"in_clusters": ["0x0000", "0x0001", "0x0003", "0xff17"],
116+
"out_clusters": [
117+
"0x0003",
118+
"0x0004",
119+
"0x0005",
120+
"0x0006",
121+
"0x0008",
122+
"0x0102",
123+
],
124+
},
125+
},
126+
"manufacturer": "Schneider Electric",
127+
"model": "FLS/AIRLINK/4",
128+
"class": "zigpy.device.Device",
129+
}
130+
assert_signature_matches_quirk(
131+
zhaquirks.schneiderelectric.switches.FLSAirlink4, signature
132+
)
133+
134+
135+
async def test_fls_air_link_4_signature(assert_signature_matches_quirk):
136+
signature = {
137+
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4190, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)",
138+
"endpoints": {
139+
"1": {
140+
"profile_id": 260,
141+
"device_type": "0x0100",
142+
"in_clusters": [
143+
"0x0000",
144+
"0x0003",
145+
"0x0004",
146+
"0x0005",
147+
"0x0006",
148+
"0x0b05",
149+
],
150+
"out_clusters": ["0x0019"],
151+
},
152+
"21": {
153+
"profile_id": 260,
154+
"device_type": "0x0104",
155+
"in_clusters": ["0x0000", "0x0003", "0x0b05", "0xff17"],
156+
"out_clusters": [
157+
"0x0003",
158+
"0x0004",
159+
"0x0005",
160+
"0x0006",
161+
"0x0008",
162+
"0x0102",
163+
],
164+
},
165+
"242": {
166+
"profile_id": 41440,
167+
"device_type": "0x0061",
168+
"in_clusters": [],
169+
"out_clusters": ["0x0021"],
170+
},
171+
},
172+
"manufacturer": "Schneider Electric",
173+
"model": "CH10AX/SWITCH/1",
174+
"class": "zigpy.device.Device",
175+
}
176+
assert_signature_matches_quirk(
177+
zhaquirks.schneiderelectric.switches.CH10AXSwitch1, signature
178+
)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""Module for Schneider Electric devices quirks."""
2+
import logging
3+
4+
from zigpy.quirks import CustomCluster, CustomDevice
5+
import zigpy.types as t
6+
from zigpy.zcl.clusters.closures import WindowCovering
7+
8+
from zhaquirks import Bus, EventableCluster, LocalDataCluster
9+
10+
_LOGGER = logging.getLogger(__name__)
11+
12+
SE = "Schneider Electric"
13+
14+
class SEManufCluster(CustomCluster):
15+
"""Schneider Electric manufacturer specific cluster."""
16+
17+
name = "Schneider Electric Manufacturer Specicific"
18+
ep_attribute = "schneider_electric_manufacturer"
19+
20+
21+
class SEManufSwitchCluster(SEManufCluster):
22+
name = "Schneider Electric Manufacturer Specicific"
23+
cluster_id = 0xFF17
24+
25+
26+
class SEWindowCoverControl(CustomCluster, WindowCovering):
27+
"""Manufacturer Specific Cluster of Device cover."""
28+
29+
attributes = WindowCovering.attributes.copy()
30+
31+
attributes.update({0xE000: ("lift_duration", t.uint16_t)})
32+
33+
# def __init__(self, *args, **kwargs):
34+
# """Initialize instance."""
35+
# super().__init__(*args, **kwargs)
36+
# self.endpoint.device.cover_bus.add_listener(self)
37+
38+
# def cover_event(self, attribute, value):
39+
# """Event listener for cover events."""
40+
# if attribute == "lift_duration":
41+
# lift_duration_attr = self._attr_cache.get("lift_duration") == 1
42+
# self._update_attribute(attribute, value)
43+
# _LOGGER.debug(
44+
# "%s Schneider Attribute Cache : [%s]",
45+
# self.endpoint.device.ieee,
46+
# self._attr_cache,
47+
# )
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"""Quirk for shutters."""
2+
from zigpy.profiles import zha
3+
from zigpy.quirks import CustomCluster, CustomDevice
4+
from zigpy.zcl.clusters.closures import WindowCovering
5+
from zigpy.zcl.clusters.general import (
6+
Basic,
7+
GreenPowerProxy,
8+
Groups,
9+
Identify,
10+
LevelControl,
11+
OnOff,
12+
Ota,
13+
Scenes,
14+
)
15+
from zigpy.zcl.clusters.homeautomation import (
16+
Diagnostic,
17+
ElectricalMeasurement,
18+
MeterIdentification,
19+
)
20+
from zigpy.zcl.clusters.smartenergy import Metering
21+
22+
from zhaquirks.const import (
23+
DEVICE_TYPE,
24+
ENDPOINTS,
25+
INPUT_CLUSTERS,
26+
MODELS_INFO,
27+
OUTPUT_CLUSTERS,
28+
PROFILE_ID,
29+
)
30+
from zhaquirks.schneiderelectric import SE, SEManufSwitchCluster
31+
32+
33+
class NHPBShutter1(CustomDevice):
34+
"""NHPB/SHUTTER/1 from Schneider Electric."""
35+
36+
# NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0,
37+
# user_descriptor_available=0, reserved=0, aps_flags=0,
38+
# frequency_band=<FrequencyBand.Freq2400MHz: 8>,
39+
# mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>,
40+
# manufacturer_code=4190, maximum_buffer_size=82, maximum_incoming_transfer_size=82,
41+
# server_mask=11264, maximum_outgoing_transfer_size=82,
42+
# descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True,
43+
# *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False,
44+
# *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True,
45+
# *is_router=True, *is_security_capable=False)
46+
signature = {
47+
MODELS_INFO: [(SE, "NHPB/SHUTTER/1")],
48+
ENDPOINTS: {
49+
5: {
50+
PROFILE_ID: zha.PROFILE_ID,
51+
DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE, # 0x0202
52+
INPUT_CLUSTERS: [
53+
Basic.cluster_id, # 0x0000
54+
Identify.cluster_id, # 0x0003
55+
Groups.cluster_id, # 0x0004
56+
Scenes.cluster_id, # 0x0005
57+
WindowCovering.cluster_id, # 0x0102
58+
Diagnostic.cluster_id, # 0x0B05
59+
],
60+
OUTPUT_CLUSTERS: [Ota.cluster_id], # 0x0019
61+
},
62+
21: {
63+
PROFILE_ID: zha.PROFILE_ID,
64+
DEVICE_TYPE: zha.DeviceType.DIMMER_SWITCH, # 0x0104
65+
INPUT_CLUSTERS: [
66+
Basic.cluster_id, # 0x0000
67+
Identify.cluster_id, # 0x0003
68+
Diagnostic.cluster_id, # 0x0B05
69+
SEManufSwitchCluster.cluster_id, # 0xff17
70+
],
71+
OUTPUT_CLUSTERS: [
72+
Identify.cluster_id, # 0x0003
73+
Groups.cluster_id, # 0x0004
74+
Scenes.cluster_id, # 0x0005
75+
OnOff.cluster_id, # 0x0006
76+
LevelControl.cluster_id, # 0x0008
77+
WindowCovering.cluster_id, # 0x0102
78+
],
79+
},
80+
242: {
81+
PROFILE_ID: 41440,
82+
DEVICE_TYPE: 0x0061,
83+
INPUT_CLUSTERS: [],
84+
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id], # 0x0021
85+
},
86+
},
87+
}
88+
replacement = {}

0 commit comments

Comments
 (0)