zwave-js-server-python 0.55.3__tar.gz → 0.56.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 (79) hide show
  1. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/PKG-INFO +1 -1
  2. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/client.py +1 -0
  3. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/__init__.py +4 -3
  4. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/barrier_operator.py +1 -0
  5. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/basic.py +1 -0
  6. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/central_scene.py +1 -0
  7. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/color_switch.py +1 -0
  8. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/energy_production.py +1 -0
  9. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/entry_control.py +1 -0
  10. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/humidity_control.py +1 -0
  11. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/lock.py +1 -0
  12. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/meter.py +1 -0
  13. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/multilevel_switch.py +1 -0
  14. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/power_level.py +1 -0
  15. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/protection.py +1 -0
  16. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/scene_activation.py +1 -0
  17. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/sound_switch.py +1 -0
  18. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/thermostat.py +1 -0
  19. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/wake_up.py +1 -0
  20. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/window_covering.py +1 -0
  21. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/dump.py +1 -0
  22. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/event.py +1 -0
  23. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/exceptions.py +1 -0
  24. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/firmware.py +1 -0
  25. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/association.py +1 -0
  26. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/command_class.py +1 -0
  27. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/controller/__init__.py +14 -6
  28. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/controller/data_model.py +2 -0
  29. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/controller/event_model.py +1 -0
  30. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/controller/firmware.py +1 -0
  31. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/controller/inclusion_and_provisioning.py +6 -0
  32. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/controller/rebuild_routes.py +1 -0
  33. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/controller/statistics.py +1 -0
  34. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/device_class.py +11 -6
  35. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/device_config.py +1 -0
  36. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/driver.py +1 -0
  37. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/duration.py +1 -0
  38. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/endpoint.py +7 -3
  39. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/log_config.py +1 -0
  40. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/log_message.py +1 -0
  41. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/node/__init__.py +64 -44
  42. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/node/data_model.py +2 -0
  43. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/node/event_model.py +1 -0
  44. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/node/firmware.py +1 -0
  45. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/node/health_check.py +1 -0
  46. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/node/statistics.py +1 -0
  47. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/notification.py +1 -0
  48. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/statistics.py +8 -5
  49. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/utils.py +1 -0
  50. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/value.py +1 -0
  51. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/version.py +1 -0
  52. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/command_class/energy_production.py +1 -0
  53. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/command_class/meter.py +1 -0
  54. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/command_class/multilevel_sensor.py +1 -0
  55. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/helpers.py +1 -0
  56. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/lock.py +1 -0
  57. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/multicast.py +1 -0
  58. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/node.py +1 -0
  59. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/version.py +1 -0
  60. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server_python.egg-info/PKG-INFO +1 -1
  61. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/LICENSE +0 -0
  62. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/MANIFEST.in +0 -0
  63. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/README.md +0 -0
  64. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/pyproject.toml +0 -0
  65. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/setup.cfg +0 -0
  66. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/__init__.py +0 -0
  67. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/__main__.py +1 -1
  68. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/__init__.py +0 -0
  69. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/multilevel_sensor.py +0 -0
  70. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/const/command_class/notification.py +0 -0
  71. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/model/__init__.py +0 -0
  72. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/py.typed +0 -0
  73. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/__init__.py +0 -0
  74. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server/util/command_class/__init__.py +0 -0
  75. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server_python.egg-info/SOURCES.txt +0 -0
  76. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server_python.egg-info/dependency_links.txt +0 -0
  77. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server_python.egg-info/entry_points.txt +0 -0
  78. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/zwave_js_server_python.egg-info/requires.txt +0 -0
  79. {zwave-js-server-python-0.55.3 → zwave_js_server_python-0.56.0}/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.55.3
3
+ Version: 0.56.0
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
@@ -1,4 +1,5 @@
1
1
  """Client."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import asyncio
@@ -1,4 +1,5 @@
1
1
  """Constants for the Z-Wave JS python library."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass, field
@@ -7,12 +8,12 @@ import logging
7
8
  from typing import TypedDict
8
9
 
9
10
  PACKAGE_NAME = "zwave-js-server-python"
10
- __version__ = "0.55.3"
11
+ __version__ = "0.56.0"
11
12
 
12
13
  # minimal server schema version we can handle
13
- MIN_SERVER_SCHEMA_VERSION = 33
14
+ MIN_SERVER_SCHEMA_VERSION = 35
14
15
  # max server schema version we can handle (and our code is compatible with)
15
- MAX_SERVER_SCHEMA_VERSION = 34
16
+ MAX_SERVER_SCHEMA_VERSION = 35
16
17
 
17
18
  VALUE_UNKNOWN = "unknown"
18
19
 
@@ -1,4 +1,5 @@
1
1
  """Constants for the Barrier Operator CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -1,4 +1,5 @@
1
1
  """Constants for the Basic CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  EVENT_PROPERTY = "event"
@@ -1,4 +1,5 @@
1
1
  """Constants for the Central Scene CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  SCENE_PROPERTY = "scene"
@@ -1,4 +1,5 @@
1
1
  """Constants for the Color Switch CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -1,4 +1,5 @@
1
1
  """Constants for the Energy Production CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -1,4 +1,5 @@
1
1
  """Constants for the Entry Control CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -4,6 +4,7 @@ Constants for the Humidity Control CCs.
4
4
  Includes Humidity Control Mode, Humidity Control Operating State,
5
5
  and Humidity Control Setpoint CCs.
6
6
  """
7
+
7
8
  from __future__ import annotations
8
9
 
9
10
  from enum import IntEnum
@@ -3,6 +3,7 @@ Constants for lock related CCs.
3
3
 
4
4
  Includes Door Lock and Lock CCs.
5
5
  """
6
+
6
7
  from __future__ import annotations
7
8
 
8
9
  from dataclasses import dataclass, field
@@ -1,4 +1,5 @@
1
1
  """Constants for Meter CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -1,4 +1,5 @@
1
1
  """Constants for the Multilevel Switch CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -1,4 +1,5 @@
1
1
  """Constants for the Power Level Command Class."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -1,4 +1,5 @@
1
1
  """Constants for the Protection CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  LOCAL_PROPERTY = "local"
@@ -1,4 +1,5 @@
1
1
  """Constants for the Scene Activation CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  SCENE_ID_PROPERTY = "sceneId"
@@ -1,4 +1,5 @@
1
1
  """Constants for the Sound Switch CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -4,6 +4,7 @@ Constants for the Thermostat CCs.
4
4
  Includes Thermostat Fan Mode, Thermostat Fan State, Thermostat Mode, Thermostat
5
5
  Operating State, Thermostat Setback, and Thermostat Setpoint CCs.
6
6
  """
7
+
7
8
  from __future__ import annotations
8
9
 
9
10
  from enum import IntEnum
@@ -1,4 +1,5 @@
1
1
  """Constants for the Wake Up CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  WAKE_UP_INTERVAL_PROPERTY = "wakeUpInterval"
@@ -1,4 +1,5 @@
1
1
  """Constants for the Barrier Operator CC."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from enum import IntEnum
@@ -1,4 +1,5 @@
1
1
  """Dump helper."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import asyncio
@@ -1,4 +1,5 @@
1
1
  """Provide Event base classes for Z-Wave JS."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from collections.abc import Callable
@@ -1,4 +1,5 @@
1
1
  """Exceptions for zwave-js-server."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import TYPE_CHECKING
@@ -1,4 +1,5 @@
1
1
  """Firmware update helper."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import asyncio
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the association."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass, field
@@ -3,6 +3,7 @@ Model for Zwave Command Class Info.
3
3
 
4
4
  https://zwave-js.github.io/node-zwave-js/#/api/endpoint?id=commandclasses
5
5
  """
6
+
6
7
  from __future__ import annotations
7
8
 
8
9
  from typing import TypedDict
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS controller."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass
@@ -243,6 +244,11 @@ class Controller(EventBase):
243
244
  """Return status."""
244
245
  return ControllerStatus(self.data["status"])
245
246
 
247
+ @property
248
+ def supports_long_range(self) -> bool | None:
249
+ """Return whether controller supports long range or not."""
250
+ return self.data.get("supportsLongRange")
251
+
246
252
  def update(self, data: ControllerDataType) -> None:
247
253
  """Update controller data."""
248
254
  self.data = data
@@ -350,9 +356,11 @@ class Controller(EventBase):
350
356
  await self.client.async_send_command(
351
357
  {
352
358
  "command": "controller.provision_smart_start_node",
353
- "entry": provisioning_info
354
- if isinstance(provisioning_info, str)
355
- else provisioning_info.to_dict(),
359
+ "entry": (
360
+ provisioning_info
361
+ if isinstance(provisioning_info, str)
362
+ else provisioning_info.to_dict()
363
+ ),
356
364
  },
357
365
  require_schema=11,
358
366
  )
@@ -870,9 +878,9 @@ class Controller(EventBase):
870
878
 
871
879
  def handle_firmware_update_progress(self, event: Event) -> None:
872
880
  """Process a firmware update progress event."""
873
- self._firmware_update_progress = event.data[
874
- "firmware_update_progress"
875
- ] = ControllerFirmwareUpdateProgress(event.data["progress"])
881
+ self._firmware_update_progress = event.data["firmware_update_progress"] = (
882
+ ControllerFirmwareUpdateProgress(event.data["progress"])
883
+ )
876
884
 
877
885
  def handle_firmware_update_finished(self, event: Event) -> None:
878
886
  """Process a firmware update finished event."""
@@ -1,4 +1,5 @@
1
1
  """Data model for a Z-Wave JS controller."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import TypedDict
@@ -32,3 +33,4 @@ class ControllerDataType(TypedDict, total=False):
32
33
  rfRegion: int
33
34
  status: int
34
35
  rebuildRoutesProgress: dict[str, str]
36
+ supportsLongRange: bool
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS controller's events."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import Literal, TypedDict
@@ -1,4 +1,5 @@
1
1
  """Provide a model for Z-Wave controller firmware."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass, field
@@ -1,4 +1,5 @@
1
1
  """Provide a model for inclusion and provisioning."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass
@@ -48,6 +49,7 @@ class ProvisioningEntry:
48
49
  security_classes: list[SecurityClass]
49
50
  requested_security_classes: list[SecurityClass] | None = None
50
51
  status: ProvisioningEntryStatus = ProvisioningEntryStatus.ACTIVE
52
+ protocol: Protocols | None = None
51
53
  additional_properties: dict[str, Any] | None = None
52
54
 
53
55
  def to_dict(self) -> dict[str, Any]:
@@ -62,6 +64,8 @@ class ProvisioningEntry:
62
64
  data["requestedSecurityClasses"] = [
63
65
  sec_cls.value for sec_cls in self.requested_security_classes
64
66
  ]
67
+ if self.protocol is not None:
68
+ data["protocol"] = self.protocol.value
65
69
  return data
66
70
 
67
71
  @classmethod
@@ -85,6 +89,8 @@ class ProvisioningEntry:
85
89
  ]
86
90
  if "status" in data:
87
91
  cls_instance.status = ProvisioningEntryStatus(data["status"])
92
+ if "protocol" in data:
93
+ cls_instance.protocol = Protocols(data["protocol"])
88
94
  return cls_instance
89
95
 
90
96
 
@@ -1,4 +1,5 @@
1
1
  """Provide models for rebuilding routes."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS controller's statistics."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from contextlib import suppress
@@ -3,6 +3,7 @@ Model for a Zwave Node's device class.
3
3
 
4
4
  https://zwave-js.github.io/node-zwave-js/#/api/node?id=deviceclass
5
5
  """
6
+
6
7
  from __future__ import annotations
7
8
 
8
9
  from dataclasses import dataclass
@@ -39,29 +40,33 @@ class DeviceClass:
39
40
 
40
41
  def __init__(self, data: DeviceClassDataType) -> None:
41
42
  """Initialize."""
42
- self.data = data
43
+ self._basic = DeviceClassItem(**data["basic"])
44
+ self._generic = DeviceClassItem(**data["generic"])
45
+ self._specific = DeviceClassItem(**data["specific"])
46
+ self._mandatory_supported_ccs: list[int] = data["mandatorySupportedCCs"]
47
+ self._mandatory_controlled_ccs: list[int] = data["mandatoryControlledCCs"]
43
48
 
44
49
  @property
45
50
  def basic(self) -> DeviceClassItem:
46
51
  """Return basic DeviceClass."""
47
- return DeviceClassItem(**self.data["basic"])
52
+ return self._basic
48
53
 
49
54
  @property
50
55
  def generic(self) -> DeviceClassItem:
51
56
  """Return generic DeviceClass."""
52
- return DeviceClassItem(**self.data["generic"])
57
+ return self._generic
53
58
 
54
59
  @property
55
60
  def specific(self) -> DeviceClassItem:
56
61
  """Return specific DeviceClass."""
57
- return DeviceClassItem(**self.data["specific"])
62
+ return self._specific
58
63
 
59
64
  @property
60
65
  def mandatory_supported_ccs(self) -> list[int]:
61
66
  """Return list of mandatory Supported CC id's."""
62
- return self.data["mandatorySupportedCCs"]
67
+ return self._mandatory_supported_ccs
63
68
 
64
69
  @property
65
70
  def mandatory_controlled_ccs(self) -> list[int]:
66
71
  """Return list of mandatory Controlled CC id's."""
67
- return self.data["mandatoryControlledCCs"]
72
+ return self._mandatory_controlled_ccs
@@ -3,6 +3,7 @@ Model for a Zwave Node's device config.
3
3
 
4
4
  https://zwave-js.github.io/node-zwave-js/#/api/node?id=deviceconfig
5
5
  """
6
+
6
7
  from __future__ import annotations
7
8
 
8
9
  from typing import Any, Literal, TypedDict
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS Driver."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import TYPE_CHECKING, Any, Literal, cast
@@ -1,4 +1,5 @@
1
1
  """Provide a model for Z-Wave JS Duration."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass, field
@@ -3,6 +3,7 @@ Model for a Zwave Node's endpoints.
3
3
 
4
4
  https://zwave-js.github.io/node-zwave-js/#/api/endpoint?id=endpoint-properties
5
5
  """
6
+
6
7
  from __future__ import annotations
7
8
 
8
9
  import asyncio
@@ -56,6 +57,7 @@ class Endpoint(EventBase):
56
57
  self.node = node
57
58
  self.data: EndpointDataType = data
58
59
  self.values: dict[str, ConfigurationValue | Value] = {}
60
+ self._device_class: DeviceClass | None = None
59
61
  self.update(data, values)
60
62
 
61
63
  def __repr__(self) -> str:
@@ -89,9 +91,7 @@ class Endpoint(EventBase):
89
91
  @property
90
92
  def device_class(self) -> DeviceClass | None:
91
93
  """Return the device_class."""
92
- if (device_class := self.data.get("deviceClass")) is None:
93
- return None
94
- return DeviceClass(device_class)
94
+ return self._device_class
95
95
 
96
96
  @property
97
97
  def installer_icon(self) -> int | None:
@@ -118,6 +118,10 @@ class Endpoint(EventBase):
118
118
  ) -> None:
119
119
  """Update the endpoint data."""
120
120
  self.data = data
121
+ if (device_class := self.data.get("deviceClass")) is None:
122
+ self._device_class = None
123
+ else:
124
+ self._device_class = DeviceClass(device_class)
121
125
 
122
126
  # Remove stale values
123
127
  self.values = {
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the log config."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass
@@ -1,4 +1,5 @@
1
1
  """Provide a model for a log message event."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass, field
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS node."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import asyncio
@@ -14,6 +15,7 @@ from ...const import (
14
15
  DateAndTime,
15
16
  NodeStatus,
16
17
  PowerLevel,
18
+ Protocols,
17
19
  SecurityClass,
18
20
  )
19
21
  from ...event import Event, EventBase
@@ -26,7 +28,7 @@ from ...exceptions import (
26
28
  from ..command_class import CommandClassInfo
27
29
  from ..device_class import DeviceClass
28
30
  from ..device_config import DeviceConfig
29
- from ..endpoint import Endpoint
31
+ from ..endpoint import Endpoint, EndpointDataType
30
32
  from ..notification import (
31
33
  EntryControlNotification,
32
34
  EntryControlNotificationDataType,
@@ -114,6 +116,8 @@ class Node(EventBase):
114
116
  client, data.get("statistics", DEFAULT_NODE_STATISTICS)
115
117
  )
116
118
  self._firmware_update_progress: NodeFirmwareUpdateProgress | None = None
119
+ self._device_class: DeviceClass | None = None
120
+ self._last_seen: datetime | None = None
117
121
  self.values: dict[str, ConfigurationValue | Value] = {}
118
122
  self.endpoints: dict[int, Endpoint] = {}
119
123
  self.status_event = asyncio.Event()
@@ -148,9 +152,7 @@ class Node(EventBase):
148
152
  @property
149
153
  def device_class(self) -> DeviceClass | None:
150
154
  """Return the device_class."""
151
- if (device_class := self.data.get("deviceClass")) is None:
152
- return None
153
- return DeviceClass(device_class)
155
+ return self._device_class
154
156
 
155
157
  @property
156
158
  def installer_icon(self) -> int | None:
@@ -358,9 +360,7 @@ class Node(EventBase):
358
360
  @property
359
361
  def last_seen(self) -> datetime | None:
360
362
  """Return when the node was last seen."""
361
- if last_seen := self.data.get("lastSeen"):
362
- return datetime.fromisoformat(last_seen)
363
- return None
363
+ return self._last_seen
364
364
 
365
365
  @property
366
366
  def default_volume(self) -> int | float | None:
@@ -372,17 +372,42 @@ class Node(EventBase):
372
372
  """Return the default transition duration."""
373
373
  return self.data.get("defaultTransitionDuration")
374
374
 
375
- def update(self, data: NodeDataType) -> None:
376
- """Update the internal state data."""
377
- self.data = copy.deepcopy(data)
378
- self._device_config = DeviceConfig(self.data.get("deviceConfig", {}))
379
- self._statistics = NodeStatistics(
380
- self.client, self.data.get("statistics", DEFAULT_NODE_STATISTICS)
381
- )
375
+ @property
376
+ def protocol(self) -> Protocols | None:
377
+ """Return the protocol used to communicate with this node."""
378
+ if "protocol" in self.data:
379
+ return Protocols(self.data["protocol"])
380
+ return None
381
+
382
+ def _update_endpoints(self, endpoints: list[EndpointDataType]) -> None:
383
+ """Update the endpoints data."""
384
+ new_endpoints_data = {endpoint["index"]: endpoint for endpoint in endpoints}
385
+ new_endpoint_idxs = set(new_endpoints_data)
386
+ stale_endpoint_idxs = set(self.endpoints) - new_endpoint_idxs
382
387
 
388
+ # Remove stale endpoints
389
+ for endpoint_idx in stale_endpoint_idxs:
390
+ self.endpoints.pop(endpoint_idx)
391
+
392
+ # Add new endpoints or update existing ones
393
+ for endpoint_idx in new_endpoint_idxs:
394
+ endpoint = new_endpoints_data[endpoint_idx]
395
+ values = {
396
+ value_id: value
397
+ for value_id, value in self.values.items()
398
+ if self.index == value.endpoint
399
+ }
400
+ if endpoint_idx in self.endpoints:
401
+ self.endpoints[endpoint_idx].update(endpoint, values)
402
+ else:
403
+ self.endpoints[endpoint_idx] = Endpoint(
404
+ self.client, self, endpoint, values
405
+ )
406
+
407
+ def _update_values(self, values: list[ValueDataType]) -> None:
408
+ """Update the values data."""
383
409
  new_values_data = {
384
- _get_value_id_str_from_dict(self, val): val
385
- for val in self.data.pop("values")
410
+ _get_value_id_str_from_dict(self, val): val for val in values
386
411
  }
387
412
  new_value_ids = set(new_values_data)
388
413
  stale_value_ids = set(self.values) - new_value_ids
@@ -409,30 +434,25 @@ class Node(EventBase):
409
434
  # If we can't parse the value, don't store it
410
435
  pass
411
436
 
412
- new_endpoints_data = {
413
- endpoint["index"]: endpoint for endpoint in self.data.pop("endpoints")
414
- }
415
- new_endpoint_idxs = set(new_endpoints_data)
416
- stale_endpoint_idxs = set(self.endpoints) - new_endpoint_idxs
437
+ def update(self, data: NodeDataType) -> None:
438
+ """Update the internal state data."""
439
+ self.data = copy.deepcopy(data)
440
+ self._device_config = DeviceConfig(self.data.get("deviceConfig", {}))
441
+ if (device_class := self.data.get("deviceClass")) is None:
442
+ self._device_class = None
443
+ else:
444
+ self._device_class = DeviceClass(device_class)
417
445
 
418
- # Remove stale endpoints
419
- for endpoint_idx in stale_endpoint_idxs:
420
- self.endpoints.pop(endpoint_idx)
446
+ self._statistics = NodeStatistics(
447
+ self.client, self.data.get("statistics", DEFAULT_NODE_STATISTICS)
448
+ )
449
+ if last_seen := data.get("lastSeen"):
450
+ self._last_seen = datetime.fromisoformat(last_seen)
451
+ if not self._statistics.last_seen:
452
+ self._statistics.last_seen = self.last_seen
421
453
 
422
- # Add new endpoints or update existing ones
423
- for endpoint_idx in new_endpoint_idxs - stale_endpoint_idxs:
424
- endpoint = new_endpoints_data[endpoint_idx]
425
- values = {
426
- value_id: value
427
- for value_id, value in self.values.items()
428
- if self.index == value.endpoint
429
- }
430
- if endpoint_idx in self.endpoints:
431
- self.endpoints[endpoint_idx].update(endpoint, values)
432
- else:
433
- self.endpoints[endpoint_idx] = Endpoint(
434
- self.client, self, endpoint, values
435
- )
454
+ self._update_values(self.data.pop("values"))
455
+ self._update_endpoints(self.data.pop("endpoints"))
436
456
 
437
457
  def get_command_class_values(
438
458
  self, command_class: CommandClass, endpoint: int | None = None
@@ -1099,10 +1119,10 @@ class Node(EventBase):
1099
1119
 
1100
1120
  def handle_firmware_update_progress(self, event: Event) -> None:
1101
1121
  """Process a node firmware update progress event."""
1102
- self._firmware_update_progress = event.data[
1103
- "firmware_update_progress"
1104
- ] = NodeFirmwareUpdateProgress(
1105
- self, cast(NodeFirmwareUpdateProgressDataType, event.data["progress"])
1122
+ self._firmware_update_progress = event.data["firmware_update_progress"] = (
1123
+ NodeFirmwareUpdateProgress(
1124
+ self, cast(NodeFirmwareUpdateProgressDataType, event.data["progress"])
1125
+ )
1106
1126
  )
1107
1127
 
1108
1128
  def handle_firmware_update_finished(self, event: Event) -> None:
@@ -1118,5 +1138,5 @@ class Node(EventBase):
1118
1138
  event.data["statistics_updated"] = self._statistics = NodeStatistics(
1119
1139
  self.client, statistics
1120
1140
  )
1121
- if last_seen := statistics.get("lastSeen"):
1122
- self.data["lastSeen"] = last_seen
1141
+ if self._statistics.last_seen:
1142
+ self._last_seen = self._statistics.last_seen
@@ -1,4 +1,5 @@
1
1
  """Data model for a Z-Wave JS node."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import TypedDict
@@ -65,3 +66,4 @@ class NodeDataType(TypedDict, total=False):
65
66
  lastSeen: str
66
67
  defaultVolume: int | float | None
67
68
  defaultTransitionDuration: int | float | None
69
+ protocol: int
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS node's events."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import Literal
@@ -1,4 +1,5 @@
1
1
  """Provide a model for Z-Wave firmware."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import asdict, dataclass, field
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS node's health checks and power tests."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass, field
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS node's statistics."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from contextlib import suppress
@@ -3,6 +3,7 @@ Model for a Zwave Node's Notification Event.
3
3
 
4
4
  https://zwave-js.github.io/node-zwave-js/#/api/node?id=quotnotificationquot
5
5
  """
6
+
6
7
  from __future__ import annotations
7
8
 
8
9
  from dataclasses import dataclass, field
@@ -1,4 +1,5 @@
1
1
  """Common models for statistics."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass, field
@@ -94,9 +95,11 @@ class RouteStatistics:
94
95
  "rssi": self.data.get("rssi"),
95
96
  "repeater_rssi": self.data.get("repeaterRSSI", []),
96
97
  "route_failed_between": (
97
- self.route_failed_between[0],
98
- self.route_failed_between[1],
99
- )
100
- if self.route_failed_between
101
- else None,
98
+ (
99
+ self.route_failed_between[0],
100
+ self.route_failed_between[1],
101
+ )
102
+ if self.route_failed_between
103
+ else None
104
+ ),
102
105
  }
@@ -1,4 +1,5 @@
1
1
  """Model for utils commands."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from ..client import Client
@@ -1,4 +1,5 @@
1
1
  """Provide a model for the Z-Wave JS value."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass, field
@@ -1,4 +1,5 @@
1
1
  """Represents the version from the server."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from dataclasses import dataclass
@@ -1,4 +1,5 @@
1
1
  """Energy Production Command Class specific utility functions for values."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from ...const import CommandClass
@@ -1,4 +1,5 @@
1
1
  """Meter Command Class specific utility functions for values."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from ...const import CommandClass
@@ -1,4 +1,5 @@
1
1
  """Multilevel Sensor Command Class specific utility functions for values."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from ...const import CommandClass
@@ -1,4 +1,5 @@
1
1
  """Generic Utility helper functions."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import base64
@@ -1,4 +1,5 @@
1
1
  """Utility functions for Z-Wave JS locks."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import TypedDict, cast
@@ -1,4 +1,5 @@
1
1
  """Support for multicast commands."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import Any, cast
@@ -1,4 +1,5 @@
1
1
  """Utility functions for Z-Wave JS nodes."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import logging
@@ -1,4 +1,5 @@
1
1
  """Version helper."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import aiohttp
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zwave-js-server-python
3
- Version: 0.55.3
3
+ Version: 0.56.0
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
@@ -1,4 +1,5 @@
1
1
  """Basic CLI to test Z-Wave JS server."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import argparse
@@ -17,7 +18,6 @@ LOGGER = logging.getLogger(__package__)
17
18
 
18
19
  def get_arguments() -> argparse.Namespace:
19
20
  """Get parsed passed in arguments."""
20
-
21
21
  parser = argparse.ArgumentParser(description="Z-Wave JS Server Python")
22
22
  parser.add_argument("--debug", action="store_true", help="Log with debug level")
23
23
  parser.add_argument(