zwave-js-server-python 0.55.2__tar.gz → 0.55.4__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.2 → zwave_js_server_python-0.55.4}/PKG-INFO +1 -1
  2. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/client.py +1 -0
  3. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/__init__.py +2 -1
  4. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/barrier_operator.py +1 -0
  5. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/basic.py +1 -0
  6. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/central_scene.py +1 -0
  7. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/color_switch.py +1 -0
  8. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/energy_production.py +1 -0
  9. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/entry_control.py +1 -0
  10. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/humidity_control.py +1 -0
  11. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/lock.py +1 -0
  12. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/meter.py +1 -0
  13. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/multilevel_switch.py +1 -0
  14. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/power_level.py +1 -0
  15. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/protection.py +1 -0
  16. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/scene_activation.py +1 -0
  17. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/sound_switch.py +1 -0
  18. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/thermostat.py +1 -0
  19. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/wake_up.py +1 -0
  20. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/window_covering.py +1 -0
  21. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/dump.py +1 -0
  22. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/event.py +5 -1
  23. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/exceptions.py +1 -0
  24. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/firmware.py +1 -0
  25. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/association.py +1 -0
  26. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/command_class.py +1 -0
  27. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/controller/__init__.py +9 -6
  28. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/controller/data_model.py +1 -0
  29. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/controller/event_model.py +1 -0
  30. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/controller/firmware.py +1 -0
  31. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/controller/inclusion_and_provisioning.py +1 -0
  32. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/controller/rebuild_routes.py +1 -0
  33. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/controller/statistics.py +1 -0
  34. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/device_class.py +11 -6
  35. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/device_config.py +1 -0
  36. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/driver.py +1 -0
  37. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/duration.py +1 -0
  38. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/endpoint.py +7 -3
  39. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/log_config.py +1 -0
  40. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/log_message.py +1 -0
  41. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/node/__init__.py +56 -44
  42. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/node/data_model.py +1 -0
  43. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/node/event_model.py +1 -0
  44. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/node/firmware.py +1 -0
  45. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/node/health_check.py +1 -0
  46. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/node/statistics.py +1 -0
  47. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/notification.py +1 -0
  48. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/statistics.py +8 -5
  49. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/utils.py +1 -0
  50. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/value.py +1 -0
  51. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/version.py +1 -0
  52. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/command_class/energy_production.py +1 -0
  53. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/command_class/meter.py +1 -0
  54. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/command_class/multilevel_sensor.py +1 -0
  55. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/helpers.py +1 -0
  56. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/lock.py +1 -0
  57. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/multicast.py +1 -0
  58. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/node.py +1 -0
  59. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/version.py +1 -0
  60. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server_python.egg-info/PKG-INFO +1 -1
  61. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/LICENSE +0 -0
  62. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/MANIFEST.in +0 -0
  63. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/README.md +0 -0
  64. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/pyproject.toml +0 -0
  65. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/setup.cfg +0 -0
  66. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/__init__.py +0 -0
  67. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/__main__.py +1 -1
  68. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/__init__.py +0 -0
  69. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/multilevel_sensor.py +0 -0
  70. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/const/command_class/notification.py +0 -0
  71. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/model/__init__.py +0 -0
  72. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/py.typed +0 -0
  73. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/__init__.py +0 -0
  74. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server/util/command_class/__init__.py +0 -0
  75. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server_python.egg-info/SOURCES.txt +0 -0
  76. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server_python.egg-info/dependency_links.txt +0 -0
  77. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server_python.egg-info/entry_points.txt +0 -0
  78. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/zwave_js_server_python.egg-info/requires.txt +0 -0
  79. {zwave-js-server-python-0.55.2 → zwave_js_server_python-0.55.4}/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.2
3
+ Version: 0.55.4
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,7 +8,7 @@ import logging
7
8
  from typing import TypedDict
8
9
 
9
10
  PACKAGE_NAME = "zwave-js-server-python"
10
- __version__ = "0.55.2"
11
+ __version__ = "0.55.4"
11
12
 
12
13
  # minimal server schema version we can handle
13
14
  MIN_SERVER_SCHEMA_VERSION = 33
@@ -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
@@ -62,7 +63,10 @@ class EventBase:
62
63
  def emit(self, event_name: str, data: dict) -> None:
63
64
  """Run all callbacks for an event."""
64
65
  for listener in self._listeners.get(event_name, []).copy():
65
- listener(data)
66
+ try:
67
+ listener(data)
68
+ except Exception: # pylint: disable=broad-exception-caught
69
+ LOGGER.exception("Error handling event: %s", event_name)
66
70
 
67
71
  def _handle_event_protocol(self, event: Event) -> None:
68
72
  """Process an event based on event protocol."""
@@ -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
@@ -350,9 +351,11 @@ class Controller(EventBase):
350
351
  await self.client.async_send_command(
351
352
  {
352
353
  "command": "controller.provision_smart_start_node",
353
- "entry": provisioning_info
354
- if isinstance(provisioning_info, str)
355
- else provisioning_info.to_dict(),
354
+ "entry": (
355
+ provisioning_info
356
+ if isinstance(provisioning_info, str)
357
+ else provisioning_info.to_dict()
358
+ ),
356
359
  },
357
360
  require_schema=11,
358
361
  )
@@ -870,9 +873,9 @@ class Controller(EventBase):
870
873
 
871
874
  def handle_firmware_update_progress(self, event: Event) -> None:
872
875
  """Process a firmware update progress event."""
873
- self._firmware_update_progress = event.data[
874
- "firmware_update_progress"
875
- ] = ControllerFirmwareUpdateProgress(event.data["progress"])
876
+ self._firmware_update_progress = event.data["firmware_update_progress"] = (
877
+ ControllerFirmwareUpdateProgress(event.data["progress"])
878
+ )
876
879
 
877
880
  def handle_firmware_update_finished(self, event: Event) -> None:
878
881
  """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
@@ -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
@@ -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
@@ -26,7 +27,7 @@ from ...exceptions import (
26
27
  from ..command_class import CommandClassInfo
27
28
  from ..device_class import DeviceClass
28
29
  from ..device_config import DeviceConfig
29
- from ..endpoint import Endpoint
30
+ from ..endpoint import Endpoint, EndpointDataType
30
31
  from ..notification import (
31
32
  EntryControlNotification,
32
33
  EntryControlNotificationDataType,
@@ -114,6 +115,8 @@ class Node(EventBase):
114
115
  client, data.get("statistics", DEFAULT_NODE_STATISTICS)
115
116
  )
116
117
  self._firmware_update_progress: NodeFirmwareUpdateProgress | None = None
118
+ self._device_class: DeviceClass | None = None
119
+ self._last_seen: datetime | None = None
117
120
  self.values: dict[str, ConfigurationValue | Value] = {}
118
121
  self.endpoints: dict[int, Endpoint] = {}
119
122
  self.status_event = asyncio.Event()
@@ -148,9 +151,7 @@ class Node(EventBase):
148
151
  @property
149
152
  def device_class(self) -> DeviceClass | None:
150
153
  """Return the device_class."""
151
- if (device_class := self.data.get("deviceClass")) is None:
152
- return None
153
- return DeviceClass(device_class)
154
+ return self._device_class
154
155
 
155
156
  @property
156
157
  def installer_icon(self) -> int | None:
@@ -358,9 +359,7 @@ class Node(EventBase):
358
359
  @property
359
360
  def last_seen(self) -> datetime | None:
360
361
  """Return when the node was last seen."""
361
- if last_seen := self.data.get("lastSeen"):
362
- return datetime.fromisoformat(last_seen)
363
- return None
362
+ return self._last_seen
364
363
 
365
364
  @property
366
365
  def default_volume(self) -> int | float | None:
@@ -372,17 +371,35 @@ class Node(EventBase):
372
371
  """Return the default transition duration."""
373
372
  return self.data.get("defaultTransitionDuration")
374
373
 
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
- )
374
+ def _update_endpoints(self, endpoints: list[EndpointDataType]) -> None:
375
+ """Update the endpoints data."""
376
+ new_endpoints_data = {endpoint["index"]: endpoint for endpoint in endpoints}
377
+ new_endpoint_idxs = set(new_endpoints_data)
378
+ stale_endpoint_idxs = set(self.endpoints) - new_endpoint_idxs
379
+
380
+ # Remove stale endpoints
381
+ for endpoint_idx in stale_endpoint_idxs:
382
+ self.endpoints.pop(endpoint_idx)
383
+
384
+ # Add new endpoints or update existing ones
385
+ for endpoint_idx in new_endpoint_idxs:
386
+ endpoint = new_endpoints_data[endpoint_idx]
387
+ values = {
388
+ value_id: value
389
+ for value_id, value in self.values.items()
390
+ if self.index == value.endpoint
391
+ }
392
+ if endpoint_idx in self.endpoints:
393
+ self.endpoints[endpoint_idx].update(endpoint, values)
394
+ else:
395
+ self.endpoints[endpoint_idx] = Endpoint(
396
+ self.client, self, endpoint, values
397
+ )
382
398
 
399
+ def _update_values(self, values: list[ValueDataType]) -> None:
400
+ """Update the values data."""
383
401
  new_values_data = {
384
- _get_value_id_str_from_dict(self, val): val
385
- for val in self.data.pop("values")
402
+ _get_value_id_str_from_dict(self, val): val for val in values
386
403
  }
387
404
  new_value_ids = set(new_values_data)
388
405
  stale_value_ids = set(self.values) - new_value_ids
@@ -409,30 +426,25 @@ class Node(EventBase):
409
426
  # If we can't parse the value, don't store it
410
427
  pass
411
428
 
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
429
+ def update(self, data: NodeDataType) -> None:
430
+ """Update the internal state data."""
431
+ self.data = copy.deepcopy(data)
432
+ self._device_config = DeviceConfig(self.data.get("deviceConfig", {}))
433
+ if (device_class := self.data.get("deviceClass")) is None:
434
+ self._device_class = None
435
+ else:
436
+ self._device_class = DeviceClass(device_class)
417
437
 
418
- # Remove stale endpoints
419
- for endpoint_idx in stale_endpoint_idxs:
420
- self.endpoints.pop(endpoint_idx)
438
+ self._statistics = NodeStatistics(
439
+ self.client, self.data.get("statistics", DEFAULT_NODE_STATISTICS)
440
+ )
441
+ if last_seen := data.get("lastSeen"):
442
+ self._last_seen = datetime.fromisoformat(last_seen)
443
+ if not self._statistics.last_seen:
444
+ self._statistics.last_seen = self.last_seen
421
445
 
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
- )
446
+ self._update_values(self.data.pop("values"))
447
+ self._update_endpoints(self.data.pop("endpoints"))
436
448
 
437
449
  def get_command_class_values(
438
450
  self, command_class: CommandClass, endpoint: int | None = None
@@ -1099,10 +1111,10 @@ class Node(EventBase):
1099
1111
 
1100
1112
  def handle_firmware_update_progress(self, event: Event) -> None:
1101
1113
  """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"])
1114
+ self._firmware_update_progress = event.data["firmware_update_progress"] = (
1115
+ NodeFirmwareUpdateProgress(
1116
+ self, cast(NodeFirmwareUpdateProgressDataType, event.data["progress"])
1117
+ )
1106
1118
  )
1107
1119
 
1108
1120
  def handle_firmware_update_finished(self, event: Event) -> None:
@@ -1118,5 +1130,5 @@ class Node(EventBase):
1118
1130
  event.data["statistics_updated"] = self._statistics = NodeStatistics(
1119
1131
  self.client, statistics
1120
1132
  )
1121
- if last_seen := statistics.get("lastSeen"):
1122
- self.data["lastSeen"] = last_seen
1133
+ if self._statistics.last_seen:
1134
+ 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
@@ -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.2
3
+ Version: 0.55.4
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(