zwave-js-server-python 0.68.0__tar.gz → 0.70.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. {zwave_js_server_python-0.68.0/zwave_js_server_python.egg-info → zwave_js_server_python-0.70.0}/PKG-INFO +1 -1
  2. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/__init__.py +17 -17
  3. zwave_js_server_python-0.70.0/zwave_js_server/const/command_class/battery.py +14 -0
  4. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/lock.py +6 -6
  5. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/notification.py +22 -0
  6. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/association.py +2 -2
  7. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/controller/__init__.py +160 -10
  8. zwave_js_server_python-0.70.0/zwave_js_server/model/controller/data_model.py +98 -0
  9. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/controller/event_model.py +71 -0
  10. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/controller/inclusion_and_provisioning.py +33 -15
  11. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/controller/rebuild_routes.py +1 -1
  12. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/controller/statistics.py +25 -25
  13. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/device_class.py +1 -1
  14. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/driver/__init__.py +130 -3
  15. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/driver/firmware.py +3 -3
  16. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/duration.py +5 -5
  17. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/endpoint.py +5 -3
  18. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/firmware.py +11 -11
  19. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/log_config.py +1 -1
  20. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/log_message.py +28 -24
  21. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/node/__init__.py +53 -9
  22. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/node/data_model.py +7 -0
  23. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/node/event_model.py +18 -0
  24. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/node/firmware.py +14 -14
  25. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/node/health_check.py +42 -26
  26. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/node/statistics.py +10 -10
  27. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/notification.py +65 -24
  28. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/statistics.py +4 -2
  29. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/value.py +93 -11
  30. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/version.py +1 -1
  31. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/lock.py +1 -1
  32. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/multicast.py +4 -1
  33. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0/zwave_js_server_python.egg-info}/PKG-INFO +1 -1
  34. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server_python.egg-info/SOURCES.txt +1 -0
  35. zwave_js_server_python-0.68.0/zwave_js_server/model/controller/data_model.py +0 -36
  36. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/LICENSE +0 -0
  37. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/MANIFEST.in +0 -0
  38. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/README.md +0 -0
  39. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/pyproject.toml +0 -0
  40. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/setup.cfg +0 -0
  41. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/__init__.py +0 -0
  42. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/__main__.py +0 -0
  43. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/client.py +0 -0
  44. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/__init__.py +0 -0
  45. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/barrier_operator.py +0 -0
  46. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/basic.py +0 -0
  47. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/central_scene.py +0 -0
  48. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/color_switch.py +0 -0
  49. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/energy_production.py +0 -0
  50. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/entry_control.py +0 -0
  51. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/humidity_control.py +0 -0
  52. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/meter.py +0 -0
  53. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/multilevel_sensor.py +0 -0
  54. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/multilevel_switch.py +0 -0
  55. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/power_level.py +0 -0
  56. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/protection.py +0 -0
  57. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/scene_activation.py +0 -0
  58. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/sound_switch.py +0 -0
  59. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/thermostat.py +0 -0
  60. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/wake_up.py +0 -0
  61. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/const/command_class/window_covering.py +0 -0
  62. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/dump.py +0 -0
  63. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/event.py +0 -0
  64. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/exceptions.py +0 -0
  65. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/firmware.py +0 -0
  66. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/__init__.py +0 -0
  67. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/command_class.py +0 -0
  68. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/config_manager/__init__.py +0 -0
  69. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/device_config.py +0 -0
  70. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/model/utils.py +0 -0
  71. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/py.typed +0 -0
  72. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/__init__.py +0 -0
  73. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/command_class/__init__.py +0 -0
  74. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/command_class/energy_production.py +0 -0
  75. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/command_class/meter.py +0 -0
  76. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/command_class/multilevel_sensor.py +0 -0
  77. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/helpers.py +0 -0
  78. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/util/node.py +0 -0
  79. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server/version.py +0 -0
  80. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server_python.egg-info/dependency_links.txt +0 -0
  81. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server_python.egg-info/entry_points.txt +0 -0
  82. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server_python.egg-info/requires.txt +0 -0
  83. {zwave_js_server_python-0.68.0 → zwave_js_server_python-0.70.0}/zwave_js_server_python.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zwave-js-server-python
3
- Version: 0.68.0
3
+ Version: 0.70.0
4
4
  Summary: Python wrapper for zwave-js-server
5
5
  Author-email: Home Assistant Team <hello@home-assistant.io>
6
6
  License-Expression: Apache-2.0
@@ -3,17 +3,17 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from dataclasses import dataclass, field
6
- from enum import Enum, IntEnum
6
+ from enum import IntEnum, StrEnum
7
7
  import logging
8
8
  from typing import TypedDict
9
9
 
10
10
  PACKAGE_NAME = "zwave-js-server-python"
11
- __version__ = "0.68.0"
11
+ __version__ = "0.70.0"
12
12
 
13
13
  # minimal server schema version we can handle
14
- MIN_SERVER_SCHEMA_VERSION = 44
14
+ MIN_SERVER_SCHEMA_VERSION = 47
15
15
  # max server schema version we can handle (and our code is compatible with)
16
- MAX_SERVER_SCHEMA_VERSION = 44
16
+ MAX_SERVER_SCHEMA_VERSION = 47
17
17
 
18
18
  VALUE_UNKNOWN = "unknown"
19
19
 
@@ -30,7 +30,7 @@ TRANSITION_DURATION_OPTION = "transitionDuration"
30
30
  VOLUME_OPTION = "volume"
31
31
 
32
32
 
33
- class CommandStatus(str, Enum):
33
+ class CommandStatus(StrEnum):
34
34
  """Status of a command sent to zwave-js-server."""
35
35
 
36
36
  ACCEPTED = "accepted"
@@ -39,7 +39,7 @@ class CommandStatus(str, Enum):
39
39
 
40
40
  # Multiple inheritance so that LogLevel will JSON serialize properly
41
41
  # Reference: https://stackoverflow.com/a/51976841
42
- class LogLevel(str, Enum):
42
+ class LogLevel(StrEnum):
43
43
  """Enum for log levels used by node-zwave-js."""
44
44
 
45
45
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/log/shared.ts#L12
@@ -212,7 +212,7 @@ class NodeStatus(IntEnum):
212
212
  ALIVE = 4
213
213
 
214
214
 
215
- class ConfigurationValueType(str, Enum):
215
+ class ConfigurationValueType(StrEnum):
216
216
  """Enum for configuration value types."""
217
217
 
218
218
  BOOLEAN = "boolean"
@@ -457,7 +457,7 @@ class DateAndTimeDataType(TypedDict, total=False):
457
457
  standardOffset: int
458
458
 
459
459
 
460
- @dataclass
460
+ @dataclass(frozen=True)
461
461
  class DateAndTime:
462
462
  """Represent a date and time."""
463
463
 
@@ -474,16 +474,16 @@ class DateAndTime:
474
474
 
475
475
  def __post_init__(self) -> None:
476
476
  """Post initialization."""
477
- self.hour = self.data.get("hour")
478
- self.minute = self.data.get("minute")
477
+ object.__setattr__(self, "hour", self.data.get("hour"))
478
+ object.__setattr__(self, "minute", self.data.get("minute"))
479
479
  if weekday := self.data.get("weekday"):
480
- self.weekday = Weekday(weekday)
481
- self.second = self.data.get("second")
482
- self.year = self.data.get("year")
483
- self.month = self.data.get("month")
484
- self.day = self.data.get("day")
485
- self.dst_offset = self.data.get("dstOffset")
486
- self.standard_offset = self.data.get("standardOffset")
480
+ object.__setattr__(self, "weekday", Weekday(weekday))
481
+ object.__setattr__(self, "second", self.data.get("second"))
482
+ object.__setattr__(self, "year", self.data.get("year"))
483
+ object.__setattr__(self, "month", self.data.get("month"))
484
+ object.__setattr__(self, "day", self.data.get("day"))
485
+ object.__setattr__(self, "dst_offset", self.data.get("dstOffset"))
486
+ object.__setattr__(self, "standard_offset", self.data.get("standardOffset"))
487
487
 
488
488
 
489
489
  class ControllerStatus(IntEnum):
@@ -0,0 +1,14 @@
1
+ """Constants for the Battery CC."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from enum import IntEnum
6
+
7
+
8
+ class BatteryReplacementStatus(IntEnum):
9
+ """Enum with all (known/used) Z-Wave Battery Replacement Statuses."""
10
+
11
+ # https://github.com/zwave-js/node-zwave-js/blob/master/packages/cc/src/lib/_Types.ts#L328
12
+ NO = 0
13
+ SOON = 1
14
+ NOW = 2
@@ -7,7 +7,7 @@ Includes Door Lock and Lock CCs.
7
7
  from __future__ import annotations
8
8
 
9
9
  from dataclasses import dataclass, field
10
- from enum import Enum, IntEnum
10
+ from enum import IntEnum, StrEnum
11
11
  from typing import TypedDict
12
12
 
13
13
  from .. import CommandClass
@@ -49,7 +49,7 @@ DOOR_LOCK_CC_UNSECURED_MAP = {
49
49
  }
50
50
 
51
51
 
52
- class LatchStatus(str, Enum):
52
+ class LatchStatus(StrEnum):
53
53
  """Enum with all (known/used) Z-Wave latch statuses."""
54
54
 
55
55
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/cc/src/cc/DoorLockCC.ts#L854
@@ -57,7 +57,7 @@ class LatchStatus(str, Enum):
57
57
  CLOSED = "closed"
58
58
 
59
59
 
60
- class BoltStatus(str, Enum):
60
+ class BoltStatus(StrEnum):
61
61
  """Enum with all (known/used) Z-Wave bolt statuses."""
62
62
 
63
63
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/cc/src/cc/DoorLockCC.ts#L854
@@ -65,7 +65,7 @@ class BoltStatus(str, Enum):
65
65
  UNLOCKED = "unlocked"
66
66
 
67
67
 
68
- class DoorStatus(str, Enum):
68
+ class DoorStatus(StrEnum):
69
69
  """Enum with all (known/used) Z-Wave door statuses."""
70
70
 
71
71
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/cc/src/cc/DoorLockCC.ts#L854
@@ -151,7 +151,7 @@ class DoorLockCCConfigurationSetOptionsDataType(TypedDict, total=False):
151
151
  DEFAULT_HANDLE_CONFIGURATION = [True, True, True, True]
152
152
 
153
153
 
154
- @dataclass
154
+ @dataclass(frozen=True)
155
155
  class DoorLockCCConfigurationSetOptions:
156
156
  """Door Lock CC Configuration Set command options."""
157
157
 
@@ -173,7 +173,7 @@ class DoorLockCCConfigurationSetOptions:
173
173
  "outside_handles_can_open_door_configuration",
174
174
  ):
175
175
  if not getattr(self, attr_name):
176
- setattr(self, attr_name, DEFAULT_HANDLE_CONFIGURATION)
176
+ object.__setattr__(self, attr_name, list(DEFAULT_HANDLE_CONFIGURATION))
177
177
 
178
178
  def to_dict(self) -> DoorLockCCConfigurationSetOptionsDataType:
179
179
  """Convert command options to dict."""
@@ -89,6 +89,7 @@ class AccessControlNotificationEvent(NotificationEvent):
89
89
  DOOR_HANDLE_STATE_WINDOW_DOOR_HANDLE_IS_OPEN = 24
90
90
  DOOR_STATE_WINDOW_DOOR_IS_CLOSED = 23
91
91
  DOOR_STATE_WINDOW_DOOR_IS_OPEN = 22
92
+ IDLE = 0
92
93
  INVALID_CREDENTIAL_USED = 50
93
94
  KEYPAD_LOCK_OPERATION = 5
94
95
  KEYPAD_STATE_KEYPAD_BUSY = 17
@@ -212,6 +213,7 @@ class ApplianceNotificationEvent(NotificationEvent):
212
213
  DRAINING_FAILURE = 15
213
214
  DRYING_FAILURE = 19
214
215
  FAN_FAILURE = 20
216
+ IDLE = 0
215
217
  MAINTENANCE_STATUS_REPLACE_MAIN_FILTER = 4
216
218
  PROGRAM_STATUS_PROGRAM_COMPLETED = 3
217
219
  PROGRAM_STATUS_PROGRAM_IN_PROGRESS = 2
@@ -235,6 +237,7 @@ class ClockNotificationEvent(NotificationEvent):
235
237
 
236
238
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
237
239
  UNKNOWN = -1
240
+ IDLE = 0
238
241
  TIME_REMAINING = 3
239
242
  TIMER_ENDED = 2
240
243
  WAKE_UP_ALERT = 1
@@ -251,6 +254,7 @@ class CoAlarmNotificationEvent(NotificationEvent):
251
254
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
252
255
  UNKNOWN = -1
253
256
  ALARM_STATUS_ALARM_SILENCED = 6
257
+ IDLE = 0
254
258
  MAINTENANCE_STATUS_REPLACEMENT_REQUIRED = 4
255
259
  MAINTENANCE_STATUS_REPLACEMENT_REQUIRED_END_OF_LIFE = 5
256
260
  PERIODIC_INSPECTION_STATUS_MAINTENANCE_REQUIRED_PLANNED_PERIODIC_INSPECTION = 7
@@ -286,6 +290,7 @@ class Co2AlarmNotificationEvent(NotificationEvent):
286
290
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
287
291
  UNKNOWN = -1
288
292
  ALARM_STATUS_ALARM_SILENCED = 6
293
+ IDLE = 0
289
294
  MAINTENANCE_STATUS_REPLACEMENT_REQUIRED = 4
290
295
  MAINTENANCE_STATUS_REPLACEMENT_REQUIRED_END_OF_LIFE = 5
291
296
  PERIODIC_INSPECTION_STATUS_MAINTENANCE_REQUIRED_PLANNED_PERIODIC_INSPECTION = 7
@@ -325,6 +330,7 @@ class EmergencyAlarmNotificationEvent(NotificationEvent):
325
330
  CONTACT_FIRE_SERVICE = 2
326
331
  CONTACT_MEDICAL_SERVICE = 3
327
332
  CONTACT_POLICE = 1
333
+ IDLE = 0
328
334
 
329
335
  @classmethod
330
336
  def _missing_(
@@ -342,6 +348,7 @@ class GasAlarmNotificationEvent(NotificationEvent):
342
348
  ALARM_STATUS_GAS_ALARM_TEST = 5
343
349
  COMBUSTIBLE_GAS_STATUS_COMBUSTIBLE_GAS_DETECTED = 2
344
350
  COMBUSTIBLE_GAS_STATUS_COMBUSTIBLE_GAS_DETECTED_LOCATION_PROVIDED = 1
351
+ IDLE = 0
345
352
  MAINTENANCE_STATUS_REPLACEMENT_REQUIRED = 6
346
353
  TOXIC_GAS_STATUS_TOXIC_GAS_DETECTED = 4
347
354
  TOXIC_GAS_STATUS_TOXIC_GAS_DETECTED_LOCATION_PROVIDED = 3
@@ -366,6 +373,7 @@ class HeatAlarmNotificationEvent(NotificationEvent):
366
373
  HEAT_SENSOR_STATUS_OVERHEAT_DETECTED_LOCATION_PROVIDED = 1
367
374
  HEAT_SENSOR_STATUS_UNDERHEAT_DETECTED = 6
368
375
  HEAT_SENSOR_STATUS_UNDERHEAT_DETECTED_LOCATION_PROVIDED = 5
376
+ IDLE = 0
369
377
  MAINTENANCE_STATUS_REPLACEMENT_REQUIRED_END_OF_LIFE = 8
370
378
  PERIODIC_INSPECTION_STATUS_MAINTENANCE_REQUIRED_PLANNED_PERIODIC_INSPECTION = 11
371
379
  RAPID_TEMPERATURE_FALL = 13
@@ -387,6 +395,7 @@ class HomeHealthNotificationEvent(NotificationEvent):
387
395
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
388
396
  UNKNOWN = -1
389
397
  FALL_DETECTED = 12
398
+ IDLE = 0
390
399
  POSITION_STATUS_LEAVING_BED = 1
391
400
  POSITION_STATUS_LYING_ON_BED = 3
392
401
  POSITION_STATUS_SITTING_ON_BED = 2
@@ -452,6 +461,7 @@ class HomeMonitoringNotificationEvent(NotificationEvent):
452
461
  UNKNOWN = -1
453
462
  HOME_OCCUPANCY_STATUS_HOME_OCCUPIED = 2
454
463
  HOME_OCCUPANCY_STATUS_HOME_OCCUPIED_LOCATION_PROVIDED = 1
464
+ IDLE = 0
455
465
 
456
466
  @classmethod
457
467
  def _missing_(
@@ -469,6 +479,7 @@ class HomeSecurityNotificationEvent(NotificationEvent):
469
479
  COVER_STATUS_TAMPERING_PRODUCT_COVER_REMOVED = 3
470
480
  GLASS_BREAKAGE = 6
471
481
  GLASS_BREAKAGE_LOCATION_PROVIDED = 5
482
+ IDLE = 0
472
483
  IMPACT_DETECTED = 10
473
484
  MAGNETIC_INTERFERENCE_STATUS_MAGNETIC_FIELD_INTERFERENCE_DETECTED = 11
474
485
  MOTION_SENSOR_STATUS_MOTION_DETECTION = 8
@@ -493,6 +504,7 @@ class IrrigationNotificationEvent(NotificationEvent):
493
504
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
494
505
  UNKNOWN = -1
495
506
  DEVICE_CONFIGURATION_STATUS_DEVICE_IS_NOT_CONFIGURED = 5
507
+ IDLE = 0
496
508
  SCHEDULE_ID_STATUS_SCHEDULE_FINISHED = 2
497
509
  SCHEDULE_ID_STATUS_SCHEDULE_STARTED = 1
498
510
  VALVE_ID_RUN_STATUS_VALVE_TABLE_RUN_FINISHED = 4
@@ -511,6 +523,7 @@ class LightSensorNotificationEvent(NotificationEvent):
511
523
 
512
524
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
513
525
  UNKNOWN = -1
526
+ IDLE = 0
514
527
  LIGHT_COLOR_TRANSITION_DETECTED = 2
515
528
  LIGHT_DETECTION_STATUS_LIGHT_DETECTED = 1
516
529
 
@@ -527,6 +540,7 @@ class PestControlNotificationEvent(NotificationEvent):
527
540
 
528
541
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
529
542
  UNKNOWN = -1
543
+ IDLE = 0
530
544
  PEST_DETECTED = 6
531
545
  PEST_DETECTED_LOCATION_PROVIDED = 5
532
546
  PEST_EXTERMINATED = 8
@@ -558,6 +572,7 @@ class PowerManagementNotificationEvent(NotificationEvent):
558
572
  BATTERY_MAINTENANCE_STATUS_BATTERY_FLUID_IS_LOW = 17
559
573
  BATTERY_MAINTENANCE_STATUS_REPLACE_BATTERY_NOW = 11
560
574
  BATTERY_MAINTENANCE_STATUS_REPLACE_BATTERY_SOON = 10
575
+ IDLE = 0
561
576
  LOAD_ERROR = 9
562
577
  MAINS_STATUS_AC_MAINS_DISCONNECTED = 2
563
578
  MAINS_STATUS_AC_MAINS_RE_CONNECTED = 3
@@ -581,6 +596,7 @@ class SirenNotificationEvent(NotificationEvent):
581
596
 
582
597
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
583
598
  UNKNOWN = -1
599
+ IDLE = 0
584
600
  SIREN_STATUS_SIREN_ACTIVE = 1
585
601
 
586
602
  @classmethod
@@ -597,6 +613,7 @@ class SmokeAlarmNotificationEvent(NotificationEvent):
597
613
  ALARM_STATUS_ALARM_SILENCED = 6
598
614
  ALARM_STATUS_SMOKE_ALARM_TEST = 3
599
615
  DUST_IN_DEVICE_STATUS_MAINTENANCE_REQUIRED_DUST_IN_DEVICE = 8
616
+ IDLE = 0
600
617
  MAINTENANCE_STATUS_REPLACEMENT_REQUIRED = 4
601
618
  MAINTENANCE_STATUS_REPLACEMENT_REQUIRED_END_OF_LIFE = 5
602
619
  PERIODIC_INSPECTION_STATUS_MAINTENANCE_REQUIRED_PLANNED_PERIODIC_INSPECTION = 7
@@ -621,6 +638,7 @@ class SystemNotificationEvent(NotificationEvent):
621
638
  HARDWARE_STATUS_SYSTEM_HARDWARE_FAILURE = 1
622
639
  HARDWARE_STATUS_SYSTEM_HARDWARE_FAILURE_WITH_FAILURE_CODE = 3
623
640
  HEARTBEAT = 5
641
+ IDLE = 0
624
642
  SOFTWARE_STATUS_SYSTEM_SOFTWARE_FAILURE = 2
625
643
  SOFTWARE_STATUS_SYSTEM_SOFTWARE_FAILURE_WITH_FAILURE_CODE = 4
626
644
 
@@ -635,6 +653,7 @@ class WaterAlarmNotificationEvent(NotificationEvent):
635
653
 
636
654
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
637
655
  UNKNOWN = -1
656
+ IDLE = 0
638
657
  MAINTENANCE_STATUS_REPLACE_WATER_FILTER = 5
639
658
  PUMP_STATUS_SUMP_PUMP_ACTIVE = 10
640
659
  PUMP_STATUS_SUMP_PUMP_FAILURE = 11
@@ -741,6 +760,7 @@ class WaterQualityMonitoringNotificationEvent(NotificationEvent):
741
760
  FILTER_PUMP_STATUS_FILTER_PUMP_OPERATION_ONGOING = 11
742
761
  FRESHWATER_FLOW_STATUS_FRESHWATER_OPERATION_ONGOING = 12
743
762
  HEATING_STATUS_HEATING_OPERATION_ONGOING = 10
763
+ IDLE = 0
744
764
  WATER_OXIDATION_ALARM = 3
745
765
  WATER_TANK_STATUS_WATER_TANK_IS_EMPTY = 14
746
766
  WATER_TANK_STATUS_WATER_TANK_IS_FULL = 16
@@ -811,6 +831,7 @@ class WaterValveNotificationEvent(NotificationEvent):
811
831
 
812
832
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
813
833
  UNKNOWN = -1
834
+ IDLE = 0
814
835
  MASTER_VALVE_CURRENT_ALARM = 6
815
836
  MASTER_VALVE_OPERATION = 2
816
837
  MASTER_VALVE_SHORT_CIRCUIT = 4
@@ -901,6 +922,7 @@ class WeatherAlarmNotificationEvent(NotificationEvent):
901
922
  # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/registries/Notifications.ts
902
923
  UNKNOWN = -1
903
924
  FREEZE_ALARM = 3
925
+ IDLE = 0
904
926
  MOISTURE_ALARM = 2
905
927
  RAIN_ALARM = 1
906
928
 
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
10
10
  from .node import Node
11
11
 
12
12
 
13
- @dataclass
13
+ @dataclass(frozen=True)
14
14
  class AssociationGroup:
15
15
  """Represent a association group dict type."""
16
16
 
@@ -22,7 +22,7 @@ class AssociationGroup:
22
22
  issued_commands: dict[int, list[int]] = field(default_factory=dict)
23
23
 
24
24
 
25
- @dataclass
25
+ @dataclass(frozen=True)
26
26
  class AssociationAddress:
27
27
  """Represent a association dict type."""
28
28
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from dataclasses import dataclass
5
+ from functools import cached_property
6
6
  import logging
7
7
  from typing import TYPE_CHECKING, Any, Literal, cast
8
8
 
@@ -26,7 +26,13 @@ from ...util.helpers import convert_base64_to_bytes, convert_bytes_to_base64
26
26
  from ..association import AssociationAddress, AssociationGroup
27
27
  from ..node import Node
28
28
  from ..node.firmware import NodeFirmwareUpdateResult
29
- from .data_model import ControllerDataType
29
+ from .data_model import (
30
+ BackgroundRSSI,
31
+ ControllerDataType,
32
+ NVMProgress,
33
+ ZWaveApiVersionDataType,
34
+ ZWaveChipType,
35
+ )
30
36
  from .event_model import CONTROLLER_EVENT_MODEL_MAP
31
37
  from .inclusion_and_provisioning import (
32
38
  InclusionGrant,
@@ -64,14 +70,6 @@ DEFAULT_CONTROLLER_STATISTICS = ( # pylint: disable=invalid-name
64
70
  )
65
71
 
66
72
 
67
- @dataclass
68
- class NVMProgress:
69
- """Class to represent an NVM backup/restore progress event."""
70
-
71
- bytes_read_or_written: int
72
- total_bytes: int
73
-
74
-
75
73
  class Controller(EventBase):
76
74
  """Represent a Z-Wave JS controller."""
77
75
 
@@ -247,9 +245,37 @@ class Controller(EventBase):
247
245
  """Return whether controller supports long range or not."""
248
246
  return self.data.get("supportsLongRange")
249
247
 
248
+ @property
249
+ def is_sis(self) -> bool | None:
250
+ """Return whether the controller is the SIS (Static Information Source)."""
251
+ return self.data.get("isSIS")
252
+
253
+ @property
254
+ def max_payload_size(self) -> int | None:
255
+ """Return the maximum Z-Wave payload size in bytes."""
256
+ return self.data.get("maxPayloadSize")
257
+
258
+ @property
259
+ def max_payload_size_lr(self) -> int | None:
260
+ """Return the maximum Long Range payload size in bytes."""
261
+ return self.data.get("maxPayloadSizeLR")
262
+
263
+ @property
264
+ def zwave_api_version(self) -> ZWaveApiVersionDataType | None:
265
+ """Return the Z-Wave API version (kind + version) supported by the controller."""
266
+ return self.data.get("zwaveApiVersion")
267
+
268
+ @cached_property
269
+ def zwave_chip_type(self) -> ZWaveChipType | None:
270
+ """Return the Z-Wave chip type."""
271
+ if (raw := self.data.get("zwaveChipType")) is None:
272
+ return None
273
+ return ZWaveChipType.from_dict(raw)
274
+
250
275
  def update(self, data: ControllerDataType) -> None:
251
276
  """Update controller data."""
252
277
  self.data = data
278
+ self.__dict__.pop("zwave_chip_type", None)
253
279
  self._statistics = ControllerStatistics(
254
280
  self.data.get("statistics", DEFAULT_CONTROLLER_STATISTICS)
255
281
  )
@@ -887,6 +913,107 @@ class Controller(EventBase):
887
913
  )
888
914
  return cast(bool, data["progress"])
889
915
 
916
+ async def async_get_background_rssi(self) -> BackgroundRSSI:
917
+ """Send getBackgroundRSSI command to Controller."""
918
+ data = await self.client.async_send_command(
919
+ {"command": "controller.get_background_rssi"},
920
+ require_schema=47,
921
+ )
922
+ return BackgroundRSSI(
923
+ channel_0=data["rssiChannel0"],
924
+ channel_1=data["rssiChannel1"],
925
+ channel_2=data.get("rssiChannel2"),
926
+ channel_3=data.get("rssiChannel3"),
927
+ )
928
+
929
+ async def async_get_long_range_nodes(self) -> list[Node]:
930
+ """Send getLongRangeNodes command to Controller."""
931
+ data = await self.client.async_send_command(
932
+ {"command": "controller.get_long_range_nodes"},
933
+ require_schema=47,
934
+ )
935
+ return [self.nodes[nid] for nid in data["nodeIds"]]
936
+
937
+ async def async_get_all_association_groups(
938
+ self, node: Node
939
+ ) -> dict[int, dict[int, AssociationGroup]]:
940
+ """Send getAllAssociationGroups command to Controller."""
941
+ data = await self.client.async_send_command(
942
+ {
943
+ "command": "controller.get_all_association_groups",
944
+ "nodeId": node.node_id,
945
+ },
946
+ require_schema=47,
947
+ )
948
+ return {
949
+ int(endpoint_id): {
950
+ int(group_id): AssociationGroup(
951
+ max_nodes=group["maxNodes"],
952
+ is_lifeline=group["isLifeline"],
953
+ multi_channel=group["multiChannel"],
954
+ label=group["label"],
955
+ profile=group.get("profile"),
956
+ issued_commands={
957
+ int(cc): cmds
958
+ for cc, cmds in group.get("issuedCommands", {}).items()
959
+ },
960
+ )
961
+ for group_id, group in groups.items()
962
+ }
963
+ for endpoint_id, groups in data["groups"].items()
964
+ }
965
+
966
+ async def async_get_all_associations(
967
+ self, node: Node
968
+ ) -> dict[int, dict[int, dict[int, list[AssociationAddress]]]]:
969
+ """Send getAllAssociations command to Controller."""
970
+ data = await self.client.async_send_command(
971
+ {
972
+ "command": "controller.get_all_associations",
973
+ "nodeId": node.node_id,
974
+ },
975
+ require_schema=47,
976
+ )
977
+ return {
978
+ int(node_id_str): {
979
+ int(endpoint_id): {
980
+ int(group_id): [
981
+ AssociationAddress(
982
+ self,
983
+ node_id=addr["nodeId"],
984
+ endpoint=addr.get("endpoint"),
985
+ )
986
+ for addr in addresses
987
+ ]
988
+ for group_id, addresses in groups.items()
989
+ }
990
+ for endpoint_id, groups in endpoints.items()
991
+ }
992
+ for node_id_str, endpoints in data["associations"].items()
993
+ }
994
+
995
+ async def async_get_all_available_firmware_updates(
996
+ self,
997
+ api_key: str,
998
+ include_prereleases: bool = True,
999
+ rf_region: RFRegion | None = None,
1000
+ ) -> dict[int, list[NodeFirmwareUpdateInfo]]:
1001
+ """Send getAllAvailableFirmwareUpdates command to Controller."""
1002
+ cmd: dict[str, Any] = {
1003
+ "command": "controller.get_all_available_firmware_updates",
1004
+ "apiKey": api_key,
1005
+ "includePrereleases": include_prereleases,
1006
+ }
1007
+ if rf_region is not None:
1008
+ cmd["rfRegion"] = rf_region.value
1009
+ data = await self.client.async_send_command(cmd, require_schema=47)
1010
+ return {
1011
+ int(node_id): [
1012
+ NodeFirmwareUpdateInfo.from_dict(update) for update in updates
1013
+ ]
1014
+ for node_id, updates in data["updates"].items()
1015
+ }
1016
+
890
1017
  def receive_event(self, event: Event) -> None:
891
1018
  """Receive an event."""
892
1019
  if event.data["source"] == "node":
@@ -1014,3 +1141,26 @@ class Controller(EventBase):
1014
1141
  """Process a status changed event."""
1015
1142
  self.data["status"] = event.data["status"]
1016
1143
  event.data["status"] = ControllerStatus(event.data["status"])
1144
+
1145
+ def handle_network_found(self, _event: Event) -> None:
1146
+ """Process a `network found` event without mutating controller identity."""
1147
+ # TODO: Revisit whether `homeId` / `ownNodeId` from this event should
1148
+ # update `self.data` once upstream semantics are confirmed.
1149
+
1150
+ def handle_network_joined(self, event: Event) -> None:
1151
+ """Process a `network joined` event (schema 47+)."""
1152
+
1153
+ def handle_network_left(self, event: Event) -> None:
1154
+ """Process a `network left` event (schema 47+)."""
1155
+
1156
+ def handle_joining_network_failed(self, event: Event) -> None:
1157
+ """Process a `joining network failed` event (schema 47+)."""
1158
+
1159
+ def handle_joining_network_show_dsk(self, event: Event) -> None:
1160
+ """Process a `joining network show dsk` event (schema 47+)."""
1161
+
1162
+ def handle_joining_network_done(self, event: Event) -> None:
1163
+ """Process a `joining network done` event (schema 47+)."""
1164
+
1165
+ def handle_leaving_network_failed(self, event: Event) -> None:
1166
+ """Process a `leaving network failed` event (schema 47+)."""
@@ -0,0 +1,98 @@
1
+ """Data model for a Z-Wave JS controller."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Literal, TypedDict
7
+
8
+ from .statistics import ControllerStatisticsDataType
9
+
10
+
11
+ class ZWaveApiVersionDataType(TypedDict):
12
+ """Represent a Z-Wave API version (schema 47+)."""
13
+
14
+ kind: Literal["official", "legacy"]
15
+ version: int
16
+
17
+
18
+ class UnknownZWaveChipTypeDataType(TypedDict):
19
+ """Represent an unknown Z-Wave chip type descriptor (schema 47+)."""
20
+
21
+ type: int
22
+ version: int
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class ZWaveChipType:
27
+ """Z-Wave chip type descriptor (schema 47+).
28
+
29
+ For known chips, `name` is set (e.g. ``"ZW0700"``).
30
+ For unknown chips, `type` and `version` are set instead.
31
+ """
32
+
33
+ name: str | None = None
34
+ type: int | None = None
35
+ version: int | None = None
36
+
37
+ @classmethod
38
+ def from_dict(cls, data: str | UnknownZWaveChipTypeDataType) -> ZWaveChipType:
39
+ """Initialize from dict."""
40
+ if isinstance(data, str):
41
+ return cls(name=data)
42
+ return cls(type=data["type"], version=data["version"])
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class NVMProgress:
47
+ """Class to represent an NVM operation progress event.
48
+
49
+ Used for backup, restore, and convert progress updates.
50
+ """
51
+
52
+ bytes_read_or_written: int
53
+ total_bytes: int
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class BackgroundRSSI:
58
+ """Background RSSI noise levels for all channels."""
59
+
60
+ channel_0: int
61
+ channel_1: int
62
+ channel_2: int | None = None
63
+ channel_3: int | None = None
64
+
65
+
66
+ class ControllerDataType(TypedDict, total=False):
67
+ """Represent a controller data dict type."""
68
+
69
+ sdkVersion: str
70
+ type: int
71
+ homeId: int
72
+ ownNodeId: int
73
+ isPrimary: bool
74
+ isSUC: bool
75
+ nodeType: int
76
+ isUsingHomeIdFromOtherNetwork: bool
77
+ isSISPresent: bool
78
+ wasRealPrimary: bool
79
+ firmwareVersion: str
80
+ manufacturerId: int
81
+ productType: int
82
+ productId: int
83
+ supportedFunctionTypes: list[int]
84
+ sucNodeId: int
85
+ supportsTimers: bool
86
+ isRebuildingRoutes: bool
87
+ statistics: ControllerStatisticsDataType
88
+ inclusionState: int
89
+ rfRegion: int
90
+ status: int
91
+ rebuildRoutesProgress: dict[str, str]
92
+ supportsLongRange: bool
93
+ # Schema 47+ properties
94
+ isSIS: bool
95
+ maxPayloadSize: int
96
+ maxPayloadSizeLR: int
97
+ zwaveApiVersion: ZWaveApiVersionDataType
98
+ zwaveChipType: str | UnknownZWaveChipTypeDataType