zwave-js-server-python 0.57.0__py3-none-any.whl → 0.58.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,12 +8,12 @@ import logging
8
8
  from typing import TypedDict
9
9
 
10
10
  PACKAGE_NAME = "zwave-js-server-python"
11
- __version__ = "0.57.0"
11
+ __version__ = "0.58.1"
12
12
 
13
13
  # minimal server schema version we can handle
14
- MIN_SERVER_SCHEMA_VERSION = 36
14
+ MIN_SERVER_SCHEMA_VERSION = 37
15
15
  # max server schema version we can handle (and our code is compatible with)
16
- MAX_SERVER_SCHEMA_VERSION = 36
16
+ MAX_SERVER_SCHEMA_VERSION = 37
17
17
 
18
18
  VALUE_UNKNOWN = "unknown"
19
19
 
@@ -505,3 +505,16 @@ class SupervisionStatus(IntEnum):
505
505
  WORKING = 1
506
506
  FAIL = 2
507
507
  SUCCESS = 255
508
+
509
+
510
+ class AssociationCheckResult(IntEnum):
511
+ """Enum for all known association check results."""
512
+
513
+ # https://github.com/zwave-js/node-zwave-js/blob/master/packages/cc/src/lib/_Types.ts#L47
514
+ OK = 1
515
+ FORBIDDEN_DESTINATION_IS_LONG_RANGE = 2
516
+ FORBIDDEN_SOURCE_IS_LONG_RANGE = 3
517
+ FORBIDDEN_SELF_ASSOCIATION = 4
518
+ FORBIDDEN_SECURITY_CLASS_MISMATCH = 5
519
+ FORBIDDEN_DESTINATION_SECURITY_CLASS_NOT_GRANTED = 6
520
+ FORBIDDEN_NO_SUPPORTED_CCS = 7
@@ -186,6 +186,7 @@ class DoorLockCCConfigurationSetOptions:
186
186
  ),
187
187
  )
188
188
  for prop_name, val in (
189
+ (TARGET_LOCK_TIMEOUT_PROPERTY, self.lock_timeout_configuration),
189
190
  (TARGET_AUTO_RELOCK_TIME_PROPERTY, self.auto_relock_time),
190
191
  (TARGET_HOLD_AND_RELEASE_TIME_PROPERTY, self.hold_and_release_time),
191
192
  (TARGET_TWIST_ASSIST_PROPERTY, self.twist_assist),
@@ -14,9 +14,11 @@ CC_SPECIFIC_RATE_TYPE = "rateType"
14
14
  RESET_METER_CC_API = "reset"
15
15
 
16
16
  # optional attributes when calling the Meter CC reset API.
17
- # https://github.com/zwave-js/node-zwave-js/blob/master/packages/zwave-js/src/lib/commandclass/MeterCC.ts#L873-L881
17
+ # https://github.com/zwave-js/node-zwave-js/blob/master/packages/cc/src/cc/MeterCC.ts
18
18
  RESET_METER_OPTION_TARGET_VALUE = "targetValue"
19
19
  RESET_METER_OPTION_TYPE = "type"
20
+ RESET_METER_OPTION_SCALE = "scale"
21
+ RESET_METER_OPTION_RATE_TYPE = "rateType"
20
22
 
21
23
 
22
24
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/config/config/meters.json
zwave_js_server/event.py CHANGED
@@ -21,6 +21,14 @@ class BaseEventModel(BaseModel):
21
21
  source: Literal["controller", "driver", "node"]
22
22
  event: str
23
23
 
24
+ @classmethod
25
+ def from_dict(cls, data: dict) -> BaseEventModel:
26
+ """Initialize from dict."""
27
+ return cls(
28
+ source=data["source"],
29
+ event=data["event"],
30
+ )
31
+
24
32
 
25
33
  @dataclass
26
34
  class Event:
@@ -74,4 +82,4 @@ class EventBase:
74
82
  if handler is None:
75
83
  LOGGER.debug("Received unknown event: %s", event)
76
84
  return
77
- handler(event)
85
+ handler(event) # pylint: disable=not-callable
@@ -3,6 +3,11 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from dataclasses import dataclass, field
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from .controller import Controller
10
+ from .node import Node
6
11
 
7
12
 
8
13
  @dataclass
@@ -21,5 +26,13 @@ class AssociationGroup:
21
26
  class AssociationAddress:
22
27
  """Represent a association dict type."""
23
28
 
29
+ controller: Controller
24
30
  node_id: int
25
31
  endpoint: int | None = None
32
+
33
+ @property
34
+ def node(self) -> Node | None:
35
+ """Return the node."""
36
+ if self.node_id in self.controller.nodes:
37
+ return self.controller.nodes[self.node_id]
38
+ return None
@@ -51,3 +51,7 @@ class CommandClassInfo:
51
51
  def is_secure(self) -> bool:
52
52
  """Return if the CommandClass is used securely on this node/endpoint."""
53
53
  return self.data["isSecure"]
54
+
55
+ def to_dict(self) -> CommandClassInfoDataType:
56
+ """Create a dictionary from itself."""
57
+ return self.data.copy()
@@ -9,6 +9,7 @@ from zwave_js_server.model.node.firmware import NodeFirmwareUpdateInfo
9
9
 
10
10
  from ...const import (
11
11
  MINIMUM_QR_STRING_LENGTH,
12
+ AssociationCheckResult,
12
13
  ControllerStatus,
13
14
  ExclusionStrategy,
14
15
  InclusionState,
@@ -574,6 +575,7 @@ class Controller(EventBase):
574
575
  for key, association_addresses in data["associations"].items():
575
576
  associations[int(key)] = [
576
577
  AssociationAddress(
578
+ self,
577
579
  node_id=association_address["nodeId"],
578
580
  endpoint=association_address.get("endpoint"),
579
581
  )
@@ -581,10 +583,10 @@ class Controller(EventBase):
581
583
  ]
582
584
  return associations
583
585
 
584
- async def async_is_association_allowed(
586
+ async def async_check_association(
585
587
  self, source: AssociationAddress, group: int, association: AssociationAddress
586
- ) -> bool:
587
- """Send isAssociationAllowed command to Controller."""
588
+ ) -> AssociationCheckResult:
589
+ """Send checkAssociation command to Controller."""
588
590
  source_data = {"nodeId": source.node_id}
589
591
  if source.endpoint is not None:
590
592
  source_data["endpoint"] = source.endpoint
@@ -594,13 +596,14 @@ class Controller(EventBase):
594
596
  association_data["endpoint"] = association.endpoint
595
597
  data = await self.client.async_send_command(
596
598
  {
597
- "command": "controller.is_association_allowed",
599
+ "command": "controller.check_association",
598
600
  **source_data,
599
601
  "group": group,
600
602
  "association": association_data,
601
- }
603
+ },
604
+ require_schema=37,
602
605
  )
603
- return cast(bool, data["allowed"])
606
+ return AssociationCheckResult(data["result"])
604
607
 
605
608
  async def async_add_associations(
606
609
  self,
@@ -869,7 +872,7 @@ class Controller(EventBase):
869
872
  f"{event.data}"
870
873
  )
871
874
 
872
- CONTROLLER_EVENT_MODEL_MAP[event.type](**event.data)
875
+ CONTROLLER_EVENT_MODEL_MAP[event.type].from_dict(event.data)
873
876
 
874
877
  self._handle_event_protocol(event)
875
878
 
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Literal, TypedDict
6
6
 
7
- from ...const import RemoveNodeReason
7
+ from ...const import InclusionStrategy, RemoveNodeReason
8
8
  from ...event import BaseEventModel
9
9
  from ..node.data_model import FoundNodeDataType, NodeDataType
10
10
  from .firmware import (
@@ -52,6 +52,15 @@ class FirmwareUpdateFinishedEventModel(BaseControllerEventModel):
52
52
  event: Literal["firmware update finished"]
53
53
  result: ControllerFirmwareUpdateResultDataType
54
54
 
55
+ @classmethod
56
+ def from_dict(cls, data: dict) -> FirmwareUpdateFinishedEventModel:
57
+ """Initialize from dict."""
58
+ return cls(
59
+ source=data["source"],
60
+ event=data["event"],
61
+ result=data["result"],
62
+ )
63
+
55
64
 
56
65
  class FirmwareUpdateProgressEventModel(BaseControllerEventModel):
57
66
  """Model for `firmware update progress` event data."""
@@ -59,6 +68,15 @@ class FirmwareUpdateProgressEventModel(BaseControllerEventModel):
59
68
  event: Literal["firmware update progress"]
60
69
  progress: ControllerFirmwareUpdateProgressDataType
61
70
 
71
+ @classmethod
72
+ def from_dict(cls, data: dict) -> FirmwareUpdateProgressEventModel:
73
+ """Initialize from dict."""
74
+ return cls(
75
+ source=data["source"],
76
+ event=data["event"],
77
+ progress=data["progress"],
78
+ )
79
+
62
80
 
63
81
  class GrantSecurityClassesEventModel(BaseControllerEventModel):
64
82
  """Model for `grant security classes` event data."""
@@ -66,6 +84,15 @@ class GrantSecurityClassesEventModel(BaseControllerEventModel):
66
84
  event: Literal["grant security classes"]
67
85
  requested: InclusionGrantDataType
68
86
 
87
+ @classmethod
88
+ def from_dict(cls, data: dict) -> GrantSecurityClassesEventModel:
89
+ """Initialize from dict."""
90
+ return cls(
91
+ source=data["source"],
92
+ event=data["event"],
93
+ requested=data["requested"],
94
+ )
95
+
69
96
 
70
97
  class RebuildRoutesDoneEventModel(BaseControllerEventModel):
71
98
  """Model for `rebuild routes done` event data."""
@@ -73,6 +100,15 @@ class RebuildRoutesDoneEventModel(BaseControllerEventModel):
73
100
  event: Literal["rebuild routes done"]
74
101
  result: dict[str, str]
75
102
 
103
+ @classmethod
104
+ def from_dict(cls, data: dict) -> RebuildRoutesDoneEventModel:
105
+ """Initialize from dict."""
106
+ return cls(
107
+ source=data["source"],
108
+ event=data["event"],
109
+ result=data["result"],
110
+ )
111
+
76
112
 
77
113
  class RebuildRoutesProgressEventModel(BaseControllerEventModel):
78
114
  """Model for `rebuild routes progress` event data."""
@@ -80,6 +116,15 @@ class RebuildRoutesProgressEventModel(BaseControllerEventModel):
80
116
  event: Literal["rebuild routes progress"]
81
117
  progress: dict[str, str]
82
118
 
119
+ @classmethod
120
+ def from_dict(cls, data: dict) -> RebuildRoutesProgressEventModel:
121
+ """Initialize from dict."""
122
+ return cls(
123
+ source=data["source"],
124
+ event=data["event"],
125
+ progress=data["progress"],
126
+ )
127
+
83
128
 
84
129
  class InclusionAbortedEventModel(BaseControllerEventModel):
85
130
  """Model for `inclusion aborted` event data."""
@@ -97,7 +142,16 @@ class InclusionStartedEventModel(BaseControllerEventModel):
97
142
  """Model for `inclusion started` event data."""
98
143
 
99
144
  event: Literal["inclusion started"]
100
- secure: bool
145
+ strategy: InclusionStrategy
146
+
147
+ @classmethod
148
+ def from_dict(cls, data: dict) -> InclusionStartedEventModel:
149
+ """Initialize from dict."""
150
+ return cls(
151
+ source=data["source"],
152
+ event=data["event"],
153
+ strategy=data["strategy"],
154
+ )
101
155
 
102
156
 
103
157
  class InclusionStoppedEventModel(BaseControllerEventModel):
@@ -113,6 +167,16 @@ class NodeAddedEventModel(BaseControllerEventModel):
113
167
  node: NodeDataType
114
168
  result: InclusionResultDataType
115
169
 
170
+ @classmethod
171
+ def from_dict(cls, data: dict) -> NodeAddedEventModel:
172
+ """Initialize from dict."""
173
+ return cls(
174
+ source=data["source"],
175
+ event=data["event"],
176
+ node=data["node"],
177
+ result=data["result"],
178
+ )
179
+
116
180
 
117
181
  class NodeFoundEventModel(BaseControllerEventModel):
118
182
  """Model for `node found` event data."""
@@ -120,6 +184,15 @@ class NodeFoundEventModel(BaseControllerEventModel):
120
184
  event: Literal["node found"]
121
185
  node: FoundNodeDataType
122
186
 
187
+ @classmethod
188
+ def from_dict(cls, data: dict) -> NodeFoundEventModel:
189
+ """Initialize from dict."""
190
+ return cls(
191
+ source=data["source"],
192
+ event=data["event"],
193
+ node=data["node"],
194
+ )
195
+
123
196
 
124
197
  class NodeRemovedEventModel(BaseControllerEventModel):
125
198
  """Model for `node removed` event data."""
@@ -128,6 +201,16 @@ class NodeRemovedEventModel(BaseControllerEventModel):
128
201
  node: NodeDataType
129
202
  reason: RemoveNodeReason
130
203
 
204
+ @classmethod
205
+ def from_dict(cls, data: dict) -> NodeRemovedEventModel:
206
+ """Initialize from dict."""
207
+ return cls(
208
+ source=data["source"],
209
+ event=data["event"],
210
+ node=data["node"],
211
+ reason=data["reason"],
212
+ )
213
+
131
214
 
132
215
  class NVMBackupAndConvertProgressEventModel(BaseControllerEventModel):
133
216
  """Base model for `nvm backup progress` and `nvm convert progress` event data."""
@@ -135,6 +218,16 @@ class NVMBackupAndConvertProgressEventModel(BaseControllerEventModel):
135
218
  bytesRead: int
136
219
  total: int
137
220
 
221
+ @classmethod
222
+ def from_dict(cls, data: dict) -> NVMBackupAndConvertProgressEventModel:
223
+ """Initialize from dict."""
224
+ return cls(
225
+ source=data["source"],
226
+ event=data["event"],
227
+ bytesRead=data["bytesRead"],
228
+ total=data["total"],
229
+ )
230
+
138
231
 
139
232
  class NVMBackupProgressEventModel(NVMBackupAndConvertProgressEventModel):
140
233
  """Model for `nvm backup progress` event data."""
@@ -155,6 +248,16 @@ class NVMRestoreProgressEventModel(BaseControllerEventModel):
155
248
  bytesWritten: int
156
249
  total: int
157
250
 
251
+ @classmethod
252
+ def from_dict(cls, data: dict) -> NVMRestoreProgressEventModel:
253
+ """Initialize from dict."""
254
+ return cls(
255
+ source=data["source"],
256
+ event=data["event"],
257
+ bytesWritten=data["bytesWritten"],
258
+ total=data["total"],
259
+ )
260
+
158
261
 
159
262
  class StatisticsUpdatedEventModel(BaseControllerEventModel):
160
263
  """Model for `statistics updated` event data."""
@@ -162,6 +265,15 @@ class StatisticsUpdatedEventModel(BaseControllerEventModel):
162
265
  event: Literal["statistics updated"]
163
266
  statistics: ControllerStatisticsDataType
164
267
 
268
+ @classmethod
269
+ def from_dict(cls, data: dict) -> StatisticsUpdatedEventModel:
270
+ """Initialize from dict."""
271
+ return cls(
272
+ source=data["source"],
273
+ event=data["event"],
274
+ statistics=data["statistics"],
275
+ )
276
+
165
277
 
166
278
  class ValidateDSKAndEnterPINEventModel(BaseControllerEventModel):
167
279
  """Model for `validate dsk and enter pin` event data."""
@@ -169,6 +281,15 @@ class ValidateDSKAndEnterPINEventModel(BaseControllerEventModel):
169
281
  event: Literal["validate dsk and enter pin"]
170
282
  dsk: str
171
283
 
284
+ @classmethod
285
+ def from_dict(cls, data: dict) -> ValidateDSKAndEnterPINEventModel:
286
+ """Initialize from dict."""
287
+ return cls(
288
+ source=data["source"],
289
+ event=data["event"],
290
+ dsk=data["dsk"],
291
+ )
292
+
172
293
 
173
294
  class IdentifyEventModel(BaseControllerEventModel):
174
295
  """Model for `identify` event data."""
@@ -176,6 +297,15 @@ class IdentifyEventModel(BaseControllerEventModel):
176
297
  event: Literal["identify"]
177
298
  nodeId: int
178
299
 
300
+ @classmethod
301
+ def from_dict(cls, data: dict) -> IdentifyEventModel:
302
+ """Initialize from dict."""
303
+ return cls(
304
+ source=data["source"],
305
+ event=data["event"],
306
+ nodeId=data["nodeId"],
307
+ )
308
+
179
309
 
180
310
  class StatusChangedEventModel(BaseControllerEventModel):
181
311
  """Model for `status changed` event data."""
@@ -183,6 +313,15 @@ class StatusChangedEventModel(BaseControllerEventModel):
183
313
  event: Literal["status changed"]
184
314
  status: int
185
315
 
316
+ @classmethod
317
+ def from_dict(cls, data: dict) -> StatusChangedEventModel:
318
+ """Initialize from dict."""
319
+ return cls(
320
+ source=data["source"],
321
+ event=data["event"],
322
+ status=data["status"],
323
+ )
324
+
186
325
 
187
326
  CONTROLLER_EVENT_MODEL_MAP: dict[str, type[BaseControllerEventModel]] = {
188
327
  "exclusion failed": ExclusionFailedEventModel,
@@ -38,9 +38,18 @@ class DeviceClass:
38
38
 
39
39
  def __init__(self, data: DeviceClassDataType) -> None:
40
40
  """Initialize."""
41
- self._basic = DeviceClassItem(**data["basic"])
42
- self._generic = DeviceClassItem(**data["generic"])
43
- self._specific = DeviceClassItem(**data["specific"])
41
+ self._basic = DeviceClassItem(
42
+ key=data["basic"]["key"],
43
+ label=data["basic"]["label"],
44
+ )
45
+ self._generic = DeviceClassItem(
46
+ key=data["generic"]["key"],
47
+ label=data["generic"]["label"],
48
+ )
49
+ self._specific = DeviceClassItem(
50
+ key=data["specific"]["key"],
51
+ label=data["specific"]["label"],
52
+ )
44
53
 
45
54
  @property
46
55
  def basic(self) -> DeviceClassItem:
@@ -30,6 +30,15 @@ class LogConfigUpdatedEventModel(BaseDriverEventModel):
30
30
  event: Literal["log config updated"]
31
31
  config: LogConfigDataType
32
32
 
33
+ @classmethod
34
+ def from_dict(cls, data: dict) -> LogConfigUpdatedEventModel:
35
+ """Initialize from dict."""
36
+ return cls(
37
+ source=data["source"],
38
+ event=data["event"],
39
+ config=data["config"],
40
+ )
41
+
33
42
 
34
43
  class AllNodesReadyEventModel(BaseDriverEventModel):
35
44
  """Model for `all nodes ready` event data."""
@@ -87,7 +96,7 @@ class Driver(EventBase):
87
96
  self.controller.receive_event(event)
88
97
  return
89
98
 
90
- DRIVER_EVENT_MODEL_MAP[event.type](**event.data)
99
+ DRIVER_EVENT_MODEL_MAP[event.type].from_dict(event.data)
91
100
 
92
101
  self._handle_event_protocol(event)
93
102
 
@@ -475,7 +475,7 @@ class Node(EventBase):
475
475
 
476
476
  def receive_event(self, event: Event) -> None:
477
477
  """Receive an event."""
478
- NODE_EVENT_MODEL_MAP[event.type](**event.data)
478
+ NODE_EVENT_MODEL_MAP[event.type].from_dict(event.data)
479
479
 
480
480
  self._handle_event_protocol(event)
481
481
  event.data["node"] = self
@@ -32,6 +32,15 @@ class BaseNodeEventModel(BaseEventModel):
32
32
  source: Literal["node"]
33
33
  nodeId: int
34
34
 
35
+ @classmethod
36
+ def from_dict(cls, data: dict) -> BaseNodeEventModel:
37
+ """Initialize from dict."""
38
+ return cls(
39
+ source=data["source"],
40
+ event=data["event"],
41
+ nodeId=data["nodeId"],
42
+ )
43
+
35
44
 
36
45
  class AliveEventModel(BaseNodeEventModel):
37
46
  """Model for `alive` event data."""
@@ -50,6 +59,18 @@ class CheckHealthProgressEventModel(BaseNodeEventModel):
50
59
  totalRounds: int
51
60
  lastRating: int
52
61
 
62
+ @classmethod
63
+ def from_dict(cls, data: dict) -> CheckHealthProgressEventModel:
64
+ """Initialize from dict."""
65
+ return cls(
66
+ source=data["source"],
67
+ event=data["event"],
68
+ nodeId=data["nodeId"],
69
+ rounds=data["rounds"],
70
+ totalRounds=data["totalRounds"],
71
+ lastRating=data["lastRating"],
72
+ )
73
+
53
74
 
54
75
  class CheckLifelineHealthProgressEventModel(CheckHealthProgressEventModel):
55
76
  """Model for `check lifeline health progress` event data."""
@@ -83,6 +104,19 @@ class InterviewFailedEventArgsModel(BaseModel):
83
104
  attempt: int | None
84
105
  maxAttempts: int | None
85
106
 
107
+ @classmethod
108
+ def from_dict(cls, data: dict) -> InterviewFailedEventArgsModel:
109
+ """Initialize from dict."""
110
+ return cls(
111
+ source=data["source"],
112
+ event=data["event"],
113
+ nodeId=data["nodeId"],
114
+ errorMessage=data["errorMessage"],
115
+ isFinal=data["isFinal"],
116
+ attempt=data["attempt"],
117
+ maxAttempts=data["maxAttempts"],
118
+ )
119
+
86
120
 
87
121
  class InterviewFailedEventModel(BaseNodeEventModel):
88
122
  """Model for `interview failed` event data."""
@@ -90,6 +124,16 @@ class InterviewFailedEventModel(BaseNodeEventModel):
90
124
  event: Literal["interview failed"]
91
125
  args: InterviewFailedEventArgsModel
92
126
 
127
+ @classmethod
128
+ def from_dict(cls, data: dict) -> InterviewFailedEventModel:
129
+ """Initialize from dict."""
130
+ return cls(
131
+ source=data["source"],
132
+ event=data["event"],
133
+ nodeId=data["nodeId"],
134
+ args=data["args"],
135
+ )
136
+
93
137
 
94
138
  class InterviewStageCompletedEventModel(BaseNodeEventModel):
95
139
  """Model for `interview stage completed` event data."""
@@ -97,6 +141,16 @@ class InterviewStageCompletedEventModel(BaseNodeEventModel):
97
141
  event: Literal["interview stage completed"]
98
142
  stageName: str
99
143
 
144
+ @classmethod
145
+ def from_dict(cls, data: dict) -> InterviewStageCompletedEventModel:
146
+ """Initialize from dict."""
147
+ return cls(
148
+ source=data["source"],
149
+ event=data["event"],
150
+ nodeId=data["nodeId"],
151
+ stageName=data["stageName"],
152
+ )
153
+
100
154
 
101
155
  class InterviewStartedEventModel(BaseNodeEventModel):
102
156
  """Model for `interview started` event data."""
@@ -118,6 +172,18 @@ class NotificationEventModel(BaseNodeEventModel):
118
172
  | MultilevelSwitchNotificationArgsDataType
119
173
  )
120
174
 
175
+ @classmethod
176
+ def from_dict(cls, data: dict) -> NotificationEventModel:
177
+ """Initialize from dict."""
178
+ return cls(
179
+ source=data["source"],
180
+ event=data["event"],
181
+ nodeId=data["nodeId"],
182
+ endpointIndex=data["endpointIndex"],
183
+ ccId=data["ccId"],
184
+ args=data["args"],
185
+ )
186
+
121
187
 
122
188
  class ReadyEventModel(BaseNodeEventModel):
123
189
  """Model for `ready` event data."""
@@ -125,6 +191,16 @@ class ReadyEventModel(BaseNodeEventModel):
125
191
  event: Literal["ready"]
126
192
  nodeState: NodeDataType
127
193
 
194
+ @classmethod
195
+ def from_dict(cls, data: dict) -> ReadyEventModel:
196
+ """Initialize from dict."""
197
+ return cls(
198
+ source=data["source"],
199
+ event=data["event"],
200
+ nodeId=data["nodeId"],
201
+ nodeState=data["nodeState"],
202
+ )
203
+
128
204
 
129
205
  class SleepEventModel(BaseNodeEventModel):
130
206
  """Model for `sleep` event data."""
@@ -138,6 +214,16 @@ class StatisticsUpdatedEventModel(BaseNodeEventModel):
138
214
  event: Literal["statistics updated"]
139
215
  statistics: NodeStatisticsDataType
140
216
 
217
+ @classmethod
218
+ def from_dict(cls, data: dict) -> StatisticsUpdatedEventModel:
219
+ """Initialize from dict."""
220
+ return cls(
221
+ source=data["source"],
222
+ event=data["event"],
223
+ nodeId=data["nodeId"],
224
+ statistics=data["statistics"],
225
+ )
226
+
141
227
 
142
228
  class TestPowerLevelProgressEventModel(BaseNodeEventModel):
143
229
  """Model for `test powerlevel progress` event data."""
@@ -146,6 +232,17 @@ class TestPowerLevelProgressEventModel(BaseNodeEventModel):
146
232
  acknowledged: int
147
233
  total: int
148
234
 
235
+ @classmethod
236
+ def from_dict(cls, data: dict) -> TestPowerLevelProgressEventModel:
237
+ """Initialize from dict."""
238
+ return cls(
239
+ source=data["source"],
240
+ event=data["event"],
241
+ nodeId=data["nodeId"],
242
+ acknowledged=data["acknowledged"],
243
+ total=data["total"],
244
+ )
245
+
149
246
 
150
247
  class ValueEventModel(BaseNodeEventModel):
151
248
  """
@@ -157,6 +254,16 @@ class ValueEventModel(BaseNodeEventModel):
157
254
 
158
255
  args: ValueDataType
159
256
 
257
+ @classmethod
258
+ def from_dict(cls, data: dict) -> ValueEventModel:
259
+ """Initialize from dict."""
260
+ return cls(
261
+ source=data["source"],
262
+ event=data["event"],
263
+ nodeId=data["nodeId"],
264
+ args=data["args"],
265
+ )
266
+
160
267
 
161
268
  class MetadataUpdatedEventModel(ValueEventModel):
162
269
  """Model for `metadata updated` event data."""
@@ -200,6 +307,16 @@ class FirmwareUpdateFinishedEventModel(BaseNodeEventModel):
200
307
  event: Literal["firmware update finished"]
201
308
  result: NodeFirmwareUpdateResultDataType
202
309
 
310
+ @classmethod
311
+ def from_dict(cls, data: dict) -> FirmwareUpdateFinishedEventModel:
312
+ """Initialize from dict."""
313
+ return cls(
314
+ source=data["source"],
315
+ event=data["event"],
316
+ nodeId=data["nodeId"],
317
+ result=data["result"],
318
+ )
319
+
203
320
 
204
321
  class FirmwareUpdateProgressEventModel(BaseNodeEventModel):
205
322
  """Model for `firmware update progress` event data."""
@@ -207,6 +324,16 @@ class FirmwareUpdateProgressEventModel(BaseNodeEventModel):
207
324
  event: Literal["firmware update progress"]
208
325
  progress: NodeFirmwareUpdateProgressDataType
209
326
 
327
+ @classmethod
328
+ def from_dict(cls, data: dict) -> FirmwareUpdateProgressEventModel:
329
+ """Initialize from dict."""
330
+ return cls(
331
+ source=data["source"],
332
+ event=data["event"],
333
+ nodeId=data["nodeId"],
334
+ progress=data["progress"],
335
+ )
336
+
210
337
 
211
338
  NODE_EVENT_MODEL_MAP: dict[str, type[BaseNodeEventModel]] = {
212
339
  "alive": AliveEventModel,
@@ -213,7 +213,11 @@ class NodeFirmwareUpdateFileInfo:
213
213
  cls, data: NodeFirmwareUpdateFileInfoDataType
214
214
  ) -> NodeFirmwareUpdateFileInfo:
215
215
  """Initialize from dict."""
216
- return cls(**data)
216
+ return cls(
217
+ target=data["target"],
218
+ url=data["url"],
219
+ integrity=data["integrity"],
220
+ )
217
221
 
218
222
  def to_dict(self) -> NodeFirmwareUpdateFileInfoDataType:
219
223
  """Return dict representation of the object."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zwave-js-server-python
3
- Version: 0.57.0
3
+ Version: 0.58.1
4
4
  Summary: Python wrapper for zwave-js-server
5
5
  Author-email: Home Assistant Team <hello@home-assistant.io>
6
6
  License: Apache License
@@ -2,12 +2,12 @@ zwave_js_server/__init__.py,sha256=Ey3O4Tha56uU-M92oLJmQHupCJ7B9oZmxlQTo8pGUM8,4
2
2
  zwave_js_server/__main__.py,sha256=X6Zdbtv6QmYjsWeQ5OvtIRhtEyT1o3o0XvAmXtRrgoY,3659
3
3
  zwave_js_server/client.py,sha256=i9TaYZ8SArj1P1Z2HeAFnKr43dmXYXPJmPVFNxQ8ZIw,19829
4
4
  zwave_js_server/dump.py,sha256=ZBhkC07ndrFd784zpogfjRJtAdEh8-y8ZycvrGf34sE,1523
5
- zwave_js_server/event.py,sha256=EgNBgCNqPpRIL3zPQnRcPSfotdM-naYTqBH4r1gF4MM,2197
5
+ zwave_js_server/event.py,sha256=zz6hzhommpsqWOZul9JtI_RlX5hyn2KVNuAqH_0Cgsg,2435
6
6
  zwave_js_server/exceptions.py,sha256=8SY6FA8NiTEQgtauLR83F7m69gBGQviJ6O2obirH2po,6148
7
7
  zwave_js_server/firmware.py,sha256=KXB_-MgBDlNg289bPibUeWtF4l8WtEq9jmiFFMYg1KM,2381
8
8
  zwave_js_server/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  zwave_js_server/version.py,sha256=PUwxOVcUMk5pOguQP9zAjiPjs1Nnmiwj3fcA4HJLiBg,401
10
- zwave_js_server/const/__init__.py,sha256=LWxaeMHr6vT5AbQ6I3yjz19eqsxoOlGdHkytoaTqYsQ,13808
10
+ zwave_js_server/const/__init__.py,sha256=maen49xJRj_9YtRS-Ln3G1h-AxrGEMXJybt-ZosbYGs,14263
11
11
  zwave_js_server/const/command_class/__init__.py,sha256=WilOppnr9CXahDjEEkAXyh_j7iCq_qZ1GtBkjWLoQUg,37
12
12
  zwave_js_server/const/command_class/barrier_operator.py,sha256=IJ195hGKEi1FLLqKWMtC2ZhY9Jt5PACr7GYTyVPjkKM,820
13
13
  zwave_js_server/const/command_class/basic.py,sha256=cs0k7p5qxrwpR8-NvXQLtnfEsC6IlBAYiW79DaM_6Eg,96
@@ -16,8 +16,8 @@ zwave_js_server/const/command_class/color_switch.py,sha256=tuKpgZSERdcVxo48YheeR
16
16
  zwave_js_server/const/command_class/energy_production.py,sha256=Ah9Zzb3EHFrN28v-DrblXVS9I40VnhO57fLyq-d-zBk,1501
17
17
  zwave_js_server/const/command_class/entry_control.py,sha256=WetdiEx0K4QaasYS1wEYndxz5lFqpvVcLR5Slz03T1s,972
18
18
  zwave_js_server/const/command_class/humidity_control.py,sha256=AtrhAaDst7LC7c-PZeLmdgoo5D6996PfwuJrdni-yr8,1894
19
- zwave_js_server/const/command_class/lock.py,sha256=HTLnjVYrLnGbWhrvETeaCbHXKemklDfzOHsD4D0uHh4,6629
20
- zwave_js_server/const/command_class/meter.py,sha256=XAm68dz48_mSW2Uahb06EGC3vpbrdhvhyni3UZLd44Q,4023
19
+ zwave_js_server/const/command_class/lock.py,sha256=0HtTwW6ifAeCk3FhupCXRIKOvvay_w1Lc6w83FACZtY,6706
20
+ zwave_js_server/const/command_class/meter.py,sha256=OY5QeAViJnlwjLeDO-_CgTi9JD5r0hpu8ofMbuc2iyw,4070
21
21
  zwave_js_server/const/command_class/multilevel_sensor.py,sha256=Js5ZIORRkGAEfJa491m91Jf8L0Owxg9ibUBQTSaUSP4,37067
22
22
  zwave_js_server/const/command_class/multilevel_switch.py,sha256=yBDE9O9Ad1eMK_rgqs7l-DPJxnB-fi9CGclgpFc-QRk,576
23
23
  zwave_js_server/const/command_class/notification.py,sha256=psLLSYNsBaKq3lEOTXdChvLrNPwZK2CD3BCGWmD1QGs,37899
@@ -29,11 +29,11 @@ zwave_js_server/const/command_class/thermostat.py,sha256=VqgKCF_Itfdq29cCzA0hN_K
29
29
  zwave_js_server/const/command_class/wake_up.py,sha256=Rvnr1-_BPmWe8-dxpBoqEMo9feew5imdtZar5a9C9H8,175
30
30
  zwave_js_server/const/command_class/window_covering.py,sha256=o2_CBQ5DSbDNmJQxrcCH8pUXPNGMyGZTtlgUA-7SbYE,2088
31
31
  zwave_js_server/model/__init__.py,sha256=XfyKH8lxZ3CB7CbRkOr5sR-eV0GrklZiBtNPmlnCJ_8,123
32
- zwave_js_server/model/association.py,sha256=nRFEC2ysQlIq3Xezh9Hqx9BTdL0b5PNDN7XguIKhhvU,527
33
- zwave_js_server/model/command_class.py,sha256=_YimyLtb3aFHdhbYURNZZQlAf-lc3CC8HW8Vbk-Vrqc,1263
34
- zwave_js_server/model/device_class.py,sha256=8cApdA1FgMWJeQ-yhlVpCzrfOwNykg7lOCiP16nu0uE,1382
32
+ zwave_js_server/model/association.py,sha256=4rpf8PbafCYCfNJGISAmnpfcvJZTo_jPDGm2M-BuiPk,878
33
+ zwave_js_server/model/command_class.py,sha256=SDTyGKlz5tDUoBb4RgKwPGwPuJvZ77a_q2EllN4bnzU,1394
34
+ zwave_js_server/model/device_class.py,sha256=WTeYuR9PoIMzfjNhE21XIlHoTA9yDNEuRPkFS1W6nts,1609
35
35
  zwave_js_server/model/device_config.py,sha256=PV13U1T0zlBJ4CvoLziFW2SUJHHumYiez-n2qOapaQw,6423
36
- zwave_js_server/model/driver.py,sha256=w4PXh90OYSI7hEHA7VjIMYrY-NS-wV32H5u2ykrdTLI,6518
36
+ zwave_js_server/model/driver.py,sha256=6g-8VmrCGLJuPa2O1NNdTaHNMxqMwnXbgzUIhQCRcl8,6779
37
37
  zwave_js_server/model/duration.py,sha256=OW2OqReexL6GXxxLs__i5Vs3JCVoODgLpwPHU48yynU,1153
38
38
  zwave_js_server/model/endpoint.py,sha256=0ZbT3I82xcCH-GRx_6MDgyNJB1bUBpFtSsU0slOpUeM,12609
39
39
  zwave_js_server/model/log_config.py,sha256=uF7gJlr2dSBP2mBMYzOyFiV_T45PwGU98AM5c7qs2g0,1574
@@ -43,17 +43,17 @@ zwave_js_server/model/statistics.py,sha256=in7S8oxWlG38tCEz1k3lxLjEsfY5yfsnD0bol
43
43
  zwave_js_server/model/utils.py,sha256=VMoJQ99QRkpJleJhXR4eojbgObdZZeEfse5gonmK7Ic,1157
44
44
  zwave_js_server/model/value.py,sha256=Ku_VnX79WL82SD6Up01qQUNRldnCvi37HeEuTrTdBPU,13266
45
45
  zwave_js_server/model/version.py,sha256=EnyL6O8r2gSv7qLIuZ-sWnybG5JnJWw-IEE5UtIUjiM,1272
46
- zwave_js_server/model/controller/__init__.py,sha256=HkVk2on8qljAvYw7jcSHv2p1lIs0UDD1QDu20J4SRdo,36544
46
+ zwave_js_server/model/controller/__init__.py,sha256=MMABFVu7GG1rYywM01gHWokGBpcwI1i-DmTunT20TBo,36653
47
47
  zwave_js_server/model/controller/data_model.py,sha256=5e6M0t7RkSJytovmDz1tULMFFoCQ1TsGHe56scrZRqI,851
48
- zwave_js_server/model/controller/event_model.py,sha256=-pqe316I7MVdIm8btovsw5ZXZbillDyH7AnGoYtvZWg,6207
48
+ zwave_js_server/model/controller/event_model.py,sha256=mJzx6m6I3maXk2JAbUdgSQQM7cBYSCKiic2N02EhbJY,10210
49
49
  zwave_js_server/model/controller/firmware.py,sha256=GnctTeLitmUVf3wfJgZsDBAlQP4eDU6ytohXqigjGEg,2907
50
50
  zwave_js_server/model/controller/inclusion_and_provisioning.py,sha256=PAO5HQE_yyTMxoVN3Woth1qC_oL6EzJNJ7NEvMtpBEA,7667
51
51
  zwave_js_server/model/controller/rebuild_routes.py,sha256=ElAZdSLiDaQLbGgfJQMnuilTpsSbCz3qag3lFBt2JoM,1073
52
52
  zwave_js_server/model/controller/statistics.py,sha256=iU2wiRvWvHzYGwydOqs8Y7CBdKA3DgL6tI1NW1zBTfU,4672
53
- zwave_js_server/model/node/__init__.py,sha256=e60y2LPetcUmIJDjQYegp7IsfKbe_jAUYOHpwRqK8mI,41110
53
+ zwave_js_server/model/node/__init__.py,sha256=6YZd1Xo-ZNrd2AB0OgY2X3VWJNQLl4E6NAzNvX0THAo,41118
54
54
  zwave_js_server/model/node/data_model.py,sha256=sQp0Mlp0SBkPv170cD0MjIX4BAMmrr4HtTZaKbIA0kQ,1845
55
- zwave_js_server/model/node/event_model.py,sha256=Xaw_P3IlefSA-sFCJSJE4qmYeptQGSuYHNlnYPJlImg,6281
56
- zwave_js_server/model/node/firmware.py,sha256=rPWNYSxHpxviZ2272r_FY8WdAv-qMurXNOsFlAyZDuA,10106
55
+ zwave_js_server/model/node/event_model.py,sha256=mSRqCIBt6LXvCmMaOGmWz_cLrfPqot_ScZLmVr_z2w4,10055
56
+ zwave_js_server/model/node/firmware.py,sha256=jF1CrI6hnETj8oZsXuwQVnIkTJ9qQ8uJEdY7JAthpC0,10214
57
57
  zwave_js_server/model/node/health_check.py,sha256=GuDFPfk5BL7aK4q5aEtGcpyZz_F-aLEIGeVw_4shq5E,5341
58
58
  zwave_js_server/model/node/statistics.py,sha256=f8JElpXEtT7y9cLhH6UhOGVwrGprtfL5GQX1VIKAGcQ,2871
59
59
  zwave_js_server/util/__init__.py,sha256=ArF1K885aW0GdVd7Lo8fl8Atf70gvsxO5Ra_WoJTG28,42
@@ -65,9 +65,9 @@ zwave_js_server/util/command_class/__init__.py,sha256=sRxti47ekLTzfk8B609CMQumIb
65
65
  zwave_js_server/util/command_class/energy_production.py,sha256=K1VmGDlqXmKDfQRpTu5o99sjnDShBMV_crEb49o-O_4,1489
66
66
  zwave_js_server/util/command_class/meter.py,sha256=tJ7rbwWUZbJCS7xEJWS_KnqUUGR8RN0f2S8iLkufae0,1258
67
67
  zwave_js_server/util/command_class/multilevel_sensor.py,sha256=wG4GQ0kjrP6d3x5DpEkUHrZd8-0LbvXoYdIxZAf6bso,1427
68
- zwave_js_server_python-0.57.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
69
- zwave_js_server_python-0.57.0.dist-info/METADATA,sha256=sv9yB4ZaMDT5ESayBhmbfQvCRb7zbuBjZRknheryO6E,14767
70
- zwave_js_server_python-0.57.0.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
71
- zwave_js_server_python-0.57.0.dist-info/entry_points.txt,sha256=lvzma7Rd_3FW_k-_xGuTfpvcvA2MR_22DOz5f1t7-xg,73
72
- zwave_js_server_python-0.57.0.dist-info/top_level.txt,sha256=-hwsl-i4Av5Op_yfOHC_OP56KPmzp_iVEkeohRIN5Ng,16
73
- zwave_js_server_python-0.57.0.dist-info/RECORD,,
68
+ zwave_js_server_python-0.58.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
69
+ zwave_js_server_python-0.58.1.dist-info/METADATA,sha256=v98EyZV72Dz-jzLOMvb37YzaKJKQ4I41F9EArT8F4mw,14767
70
+ zwave_js_server_python-0.58.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
71
+ zwave_js_server_python-0.58.1.dist-info/entry_points.txt,sha256=lvzma7Rd_3FW_k-_xGuTfpvcvA2MR_22DOz5f1t7-xg,73
72
+ zwave_js_server_python-0.58.1.dist-info/top_level.txt,sha256=-hwsl-i4Av5Op_yfOHC_OP56KPmzp_iVEkeohRIN5Ng,16
73
+ zwave_js_server_python-0.58.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.0)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5