Skip to content

Commit 18294b1

Browse files
reubenbijlraman325
andauthored
Add support for Multilevel Switch Notification (#397)
* Adding Multilevel Switch Notification Type Support * Adding Multilevel Switch Notification Support * Update zwave_js_server/model/notification.py Co-authored-by: Raman Gupta <[email protected]> * Added enum for possible MultilevelSwitch Command Values * import IntEnum * add . * fix key * Addition of tests for Multilevel Switch CC Notification * remove whitespace * lint changes * Update test_node.py Co-authored-by: Raman Gupta <[email protected]>
1 parent 156caf4 commit 18294b1

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
lines changed

test/model/test_node.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
EntryControlEventType,
2020
)
2121
from zwave_js_server.const.command_class.power_level import PowerLevelTestStatus
22+
from zwave_js_server.const.command_class.multilevel_switch import (
23+
MultilevelSwitchCommand,
24+
)
2225
from zwave_js_server.event import Event
2326
from zwave_js_server.exceptions import (
2427
FailedCommand,
@@ -804,6 +807,48 @@ async def test_notification(lock_schlage_be469: node_pkg.Node):
804807
assert event.data["notification"].status == PowerLevelTestStatus.FAILED
805808
assert event.data["notification"].acknowledged_frames == 2
806809

810+
# Validate that Multilevel Switch CC notification event is received as expected
811+
event = Event(
812+
type="notification",
813+
data={
814+
"source": "node",
815+
"event": "notification",
816+
"nodeId": 23,
817+
"ccId": CommandClass.SWITCH_MULTILEVEL.value,
818+
"args": {"direction": "up", "eventType": 4},
819+
},
820+
)
821+
822+
node.handle_notification(event)
823+
assert event.data["notification"].command_class == CommandClass.SWITCH_MULTILEVEL
824+
assert event.data["notification"].node_id == 23
825+
assert event.data["notification"].direction == "up"
826+
assert (
827+
event.data["notification"].event_type
828+
== MultilevelSwitchCommand.START_LEVEL_CHANGE
829+
)
830+
831+
# Validate that Multilevel Switch CC notification event without a direction is valid
832+
event = Event(
833+
type="notification",
834+
data={
835+
"source": "node",
836+
"event": "notification",
837+
"nodeId": 23,
838+
"ccId": CommandClass.SWITCH_MULTILEVEL.value,
839+
"args": {"eventType": 4},
840+
},
841+
)
842+
843+
node.handle_notification(event)
844+
assert event.data["notification"].command_class == CommandClass.SWITCH_MULTILEVEL
845+
assert event.data["notification"].node_id == 23
846+
assert event.data["notification"].direction is None
847+
assert (
848+
event.data["notification"].event_type
849+
== MultilevelSwitchCommand.START_LEVEL_CHANGE
850+
)
851+
807852

808853
async def test_notification_unknown(lock_schlage_be469: node_pkg.Node, caplog):
809854
"""Test unrecognized command class notification events."""
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
"""Constants for the Multilevel Switch CC."""
2+
from enum import IntEnum
23

34
COVER_OPEN_PROPERTY = "Open"
45
COVER_UP_PROPERTY = "Up"
56
COVER_ON_PROPERTY = "On"
67
COVER_CLOSE_PROPERTY = "Close"
78
COVER_DOWN_PROPERTY = "Down"
89
COVER_OFF_PROPERTY = "Off"
10+
11+
12+
class MultilevelSwitchCommand(IntEnum):
13+
"""Enum for known multilevel switch notifications."""
14+
15+
START_LEVEL_CHANGE = 4
16+
STOP_LEVEL_CHANGE = 5

zwave_js_server/model/node/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
NotificationNotificationDataType,
3434
PowerLevelNotification,
3535
PowerLevelNotificationDataType,
36+
MultilevelSwitchNotification,
37+
MultilevelSwitchNotificationDataType,
3638
)
3739
from ..value import (
3840
ConfigurationValue,
@@ -783,6 +785,10 @@ def handle_notification(self, event: Event) -> None:
783785
event.data["notification"] = NotificationNotification(
784786
self, cast(NotificationNotificationDataType, event.data)
785787
)
788+
elif command_class == CommandClass.SWITCH_MULTILEVEL:
789+
event.data["notification"] = MultilevelSwitchNotification(
790+
self, cast(MultilevelSwitchNotificationDataType, event.data)
791+
)
786792
elif command_class == CommandClass.ENTRY_CONTROL:
787793
event.data["notification"] = EntryControlNotification(
788794
self, cast(EntryControlNotificationDataType, event.data)

zwave_js_server/model/notification.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from ..const import TYPING_EXTENSION_FOR_TYPEDDICT_REQUIRED
1010
from ..const.command_class.power_level import PowerLevelTestStatus
11+
from ..const.command_class.multilevel_switch import MultilevelSwitchCommand
1112
from ..util.helpers import parse_buffer
1213

1314
if TYPING_EXTENSION_FOR_TYPEDDICT_REQUIRED:
@@ -184,3 +185,49 @@ def status(self) -> PowerLevelTestStatus:
184185
def acknowledged_frames(self) -> int:
185186
"""Return acknowledged frames property."""
186187
return self.data["args"]["acknowledgedFrames"]
188+
189+
190+
class MultilevelSwitchNotificationArgsDataType(TypedDict, total=False):
191+
"""Represent args for a Multi Level Switch CC notification event data dict type."""
192+
193+
eventType: int # required
194+
direction: str
195+
196+
197+
class MultilevelSwitchNotificationDataType(BaseNotificationDataType):
198+
"""Represent a Multi Level Switch CC notification event data dict type."""
199+
200+
args: MultilevelSwitchNotificationArgsDataType # required
201+
202+
203+
class MultilevelSwitchNotification:
204+
"""Model for a Zwave Node's Multi Level CC notification event."""
205+
206+
def __init__(
207+
self, node: "Node", data: MultilevelSwitchNotificationDataType
208+
) -> None:
209+
"""Initialize."""
210+
self.node = node
211+
self.data = data
212+
213+
@property
214+
def node_id(self) -> int:
215+
"""Return node ID property."""
216+
return self.data["nodeId"]
217+
218+
@property
219+
def command_class(self) -> int:
220+
"""Return command class."""
221+
return self.data["ccId"]
222+
223+
@property
224+
def event_type(self) -> MultilevelSwitchCommand:
225+
"""Return event type property."""
226+
return MultilevelSwitchCommand(self.data["args"]["eventType"])
227+
228+
@property
229+
def direction(self) -> Optional[str]:
230+
"""Return direction property."""
231+
if direction := self.data["args"].get("direction"):
232+
return direction
233+
return None

0 commit comments

Comments
 (0)