zwave-js-server-python 0.57.0__tar.gz → 0.58.1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/PKG-INFO +1 -1
  2. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/pyproject.toml +19 -14
  3. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/__init__.py +16 -3
  4. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/lock.py +1 -0
  5. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/meter.py +3 -1
  6. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/event.py +9 -1
  7. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/association.py +13 -0
  8. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/command_class.py +4 -0
  9. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/controller/__init__.py +10 -7
  10. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/controller/event_model.py +141 -2
  11. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/device_class.py +12 -3
  12. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/driver.py +10 -1
  13. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/node/__init__.py +1 -1
  14. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/node/event_model.py +127 -0
  15. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/node/firmware.py +5 -1
  16. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server_python.egg-info/PKG-INFO +1 -1
  17. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/LICENSE +0 -0
  18. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/MANIFEST.in +0 -0
  19. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/README.md +0 -0
  20. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/setup.cfg +0 -0
  21. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/__init__.py +0 -0
  22. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/__main__.py +0 -0
  23. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/client.py +0 -0
  24. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/__init__.py +0 -0
  25. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/barrier_operator.py +0 -0
  26. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/basic.py +0 -0
  27. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/central_scene.py +0 -0
  28. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/color_switch.py +0 -0
  29. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/energy_production.py +0 -0
  30. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/entry_control.py +0 -0
  31. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/humidity_control.py +0 -0
  32. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/multilevel_sensor.py +0 -0
  33. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/multilevel_switch.py +0 -0
  34. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/notification.py +0 -0
  35. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/power_level.py +0 -0
  36. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/protection.py +0 -0
  37. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/scene_activation.py +0 -0
  38. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/sound_switch.py +0 -0
  39. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/thermostat.py +0 -0
  40. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/wake_up.py +0 -0
  41. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/const/command_class/window_covering.py +0 -0
  42. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/dump.py +0 -0
  43. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/exceptions.py +0 -0
  44. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/firmware.py +0 -0
  45. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/__init__.py +0 -0
  46. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/controller/data_model.py +0 -0
  47. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/controller/firmware.py +0 -0
  48. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/controller/inclusion_and_provisioning.py +0 -0
  49. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/controller/rebuild_routes.py +0 -0
  50. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/controller/statistics.py +0 -0
  51. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/device_config.py +0 -0
  52. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/duration.py +0 -0
  53. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/endpoint.py +0 -0
  54. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/log_config.py +0 -0
  55. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/log_message.py +0 -0
  56. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/node/data_model.py +0 -0
  57. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/node/health_check.py +0 -0
  58. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/node/statistics.py +0 -0
  59. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/notification.py +0 -0
  60. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/statistics.py +0 -0
  61. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/utils.py +0 -0
  62. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/value.py +0 -0
  63. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/model/version.py +0 -0
  64. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/py.typed +0 -0
  65. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/__init__.py +0 -0
  66. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/command_class/__init__.py +0 -0
  67. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/command_class/energy_production.py +0 -0
  68. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/command_class/meter.py +0 -0
  69. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/command_class/multilevel_sensor.py +0 -0
  70. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/helpers.py +0 -0
  71. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/lock.py +0 -0
  72. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/multicast.py +0 -0
  73. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/util/node.py +0 -0
  74. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server/version.py +0 -0
  75. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server_python.egg-info/SOURCES.txt +0 -0
  76. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server_python.egg-info/dependency_links.txt +0 -0
  77. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server_python.egg-info/entry_points.txt +0 -0
  78. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server_python.egg-info/requires.txt +0 -0
  79. {zwave_js_server_python-0.57.0 → zwave_js_server_python-0.58.1}/zwave_js_server_python.egg-info/top_level.txt +0 -0
@@ -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
@@ -84,10 +84,27 @@ max-attributes = 15
84
84
  [tool.pylint.FORMAT]
85
85
  expected-line-ending-format = "LF"
86
86
 
87
+ [tool.pylint.MESSAGE_CONTROL]
88
+ disable="too-many-positional-arguments"
89
+
87
90
  [tool.pytest.ini_options]
88
91
  asyncio_mode = "auto"
89
92
 
90
93
  [tool.ruff]
94
+ exclude = [
95
+ ".venv",
96
+ ".git",
97
+ ".tox",
98
+ "docs",
99
+ "venv",
100
+ "bin",
101
+ "lib",
102
+ "deps",
103
+ "build",
104
+ ]
105
+ line-length = 88
106
+
107
+ [tool.ruff.lint]
91
108
  select = ["D", "E", "F", "G", "I", "PLC", "PLE", "PLR", "PLW", "UP", "W"]
92
109
  ignore = [
93
110
  "D202",
@@ -104,22 +121,10 @@ ignore = [
104
121
  "UP006", # keep type annotation style as is
105
122
  "UP007", # keep type annotation style as is
106
123
  ]
107
- exclude = [
108
- ".venv",
109
- ".git",
110
- ".tox",
111
- "docs",
112
- "venv",
113
- "bin",
114
- "lib",
115
- "deps",
116
- "build",
117
- ]
118
- line-length = 88
119
124
 
120
- [tool.ruff.isort]
125
+ [tool.ruff.lint.isort]
121
126
  force-sort-within-sections = true
122
- known-first-party = ["zwave_js_server"]
127
+ known-first-party = ["zwave_js_server", "test"]
123
128
  combine-as-imports = true
124
129
  split-on-trailing-comma = false
125
130
  case-sensitive = true
@@ -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
@@ -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