zwave-js-server-python 0.64.0__py3-none-any.whl → 0.66.0__py3-none-any.whl

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.
@@ -8,7 +8,7 @@ import logging
8
8
  from typing import TypedDict
9
9
 
10
10
  PACKAGE_NAME = "zwave-js-server-python"
11
- __version__ = "0.64.0"
11
+ __version__ = "0.66.0"
12
12
 
13
13
  # minimal server schema version we can handle
14
14
  MIN_SERVER_SCHEMA_VERSION = 41
zwave_js_server/event.py CHANGED
@@ -7,10 +7,7 @@ from dataclasses import dataclass, field
7
7
  import logging
8
8
  from typing import Literal
9
9
 
10
- try:
11
- from pydantic.v1 import BaseModel
12
- except ImportError:
13
- from pydantic import BaseModel
10
+ from pydantic import BaseModel
14
11
 
15
12
  LOGGER = logging.getLogger(__package__)
16
13
 
@@ -736,14 +736,17 @@ class Controller(EventBase):
736
736
  )
737
737
  return convert_base64_to_bytes(data["nvmData"])
738
738
 
739
- async def async_restore_nvm(self, file: bytes) -> None:
739
+ async def async_restore_nvm(
740
+ self, file: bytes, options: dict[str, bool] | None = None
741
+ ) -> None:
740
742
  """Send restoreNVM command to Controller."""
741
743
  await self.client.async_send_command(
742
744
  {
743
745
  "command": "controller.restore_nvm",
744
746
  "nvmData": convert_bytes_to_base64(file),
747
+ "migrateOptions": {} if options is None else options,
745
748
  },
746
- require_schema=14,
749
+ require_schema=42,
747
750
  )
748
751
 
749
752
  async def async_backup_nvm_raw_base64(self) -> str:
@@ -753,14 +756,17 @@ class Controller(EventBase):
753
756
  )
754
757
  return data["nvmData"]
755
758
 
756
- async def async_restore_nvm_base64(self, base64_data: str) -> None:
759
+ async def async_restore_nvm_base64(
760
+ self, base64_data: str, options: dict[str, bool] | None = None
761
+ ) -> None:
757
762
  """Send restoreNVM command to Controller with base64 data directly."""
758
763
  await self.client.async_send_command(
759
764
  {
760
765
  "command": "controller.restore_nvm",
761
766
  "nvmData": base64_data,
767
+ "migrateOptions": {} if options is None else options,
762
768
  },
763
- require_schema=14,
769
+ require_schema=42,
764
770
  )
765
771
 
766
772
  async def async_get_power_level(self) -> dict[str, int]:
@@ -53,6 +53,7 @@ class BackgroundRSSIDataType(TypedDict, total=False):
53
53
  channel0: ChannelRSSIDataType # required
54
54
  channel1: ChannelRSSIDataType # required
55
55
  channel2: ChannelRSSIDataType
56
+ channel3: ChannelRSSIDataType
56
57
 
57
58
 
58
59
  class ControllerStatisticsDataType(TypedDict, total=False):
@@ -94,16 +95,20 @@ class BackgroundRSSI:
94
95
  channel_0: ChannelRSSI = field(init=False)
95
96
  channel_1: ChannelRSSI = field(init=False)
96
97
  channel_2: ChannelRSSI | None = field(init=False)
98
+ channel_3: ChannelRSSI | None = field(init=False)
97
99
 
98
100
  def __post_init__(self) -> None:
99
101
  """Post initialize."""
100
102
  self.timestamp = self.data["timestamp"]
101
103
  self.channel_0 = ChannelRSSI(self.data["channel0"])
102
104
  self.channel_1 = ChannelRSSI(self.data["channel1"])
103
- if not (channel_2 := self.data.get("channel2")):
104
- self.channel_2 = None
105
- return
106
- self.channel_2 = ChannelRSSI(channel_2)
105
+ # Channels 2 and 3 may not be present, but 3 requires 2 to be present
106
+ self.channel_2 = None
107
+ self.channel_3 = None
108
+ if channel_2 := self.data.get("channel2"):
109
+ self.channel_2 = ChannelRSSI(channel_2)
110
+ if channel_3 := self.data.get("channel3"):
111
+ self.channel_3 = ChannelRSSI(channel_3)
107
112
 
108
113
 
109
114
  @dataclass
@@ -12,8 +12,8 @@ from typing import Any, Literal, TypedDict
12
12
  class DeviceDeviceDataType(TypedDict, total=False):
13
13
  """Represent a device device data dict type."""
14
14
 
15
- productType: str
16
- productId: str
15
+ productType: str | int
16
+ productId: str | int
17
17
 
18
18
 
19
19
  class DeviceDevice:
@@ -24,12 +24,12 @@ class DeviceDevice:
24
24
  self.data = data
25
25
 
26
26
  @property
27
- def product_type(self) -> str | None:
27
+ def product_type(self) -> str | int | None:
28
28
  """Return product type."""
29
29
  return self.data.get("productType")
30
30
 
31
31
  @property
32
- def product_id(self) -> str | None:
32
+ def product_id(self) -> str | int | None:
33
33
  """Return product id."""
34
34
  return self.data.get("productId")
35
35
 
@@ -125,7 +125,7 @@ class DeviceConfigDataType(TypedDict, total=False):
125
125
 
126
126
  filename: str
127
127
  manufacturer: str
128
- manufacturerId: str
128
+ manufacturerId: int
129
129
  label: str
130
130
  description: str
131
131
  devices: list[DeviceDeviceDataType]
@@ -164,8 +164,8 @@ class DeviceConfig:
164
164
  return self.data.get("manufacturer")
165
165
 
166
166
  @property
167
- def manufacturer_id(self) -> str | None: # TODO: In the dump this is an int.
168
- """Return manufacturer id (as defined in specs) as a 4-digit hex string."""
167
+ def manufacturer_id(self) -> int | None:
168
+ """Return manufacturer id (as defined in specs)."""
169
169
  return self.data.get("manufacturerId")
170
170
 
171
171
  @property
@@ -2,8 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import sys
5
6
  from typing import TYPE_CHECKING, Any, Literal, cast
6
7
 
8
+ from pydantic import create_model
9
+
7
10
  from ...event import BaseEventModel, Event, EventBase
8
11
  from ..config_manager import ConfigManager
9
12
  from ..controller import Controller
@@ -16,10 +19,10 @@ from .firmware import (
16
19
  DriverFirmwareUpdateResultDataType,
17
20
  )
18
21
 
19
- try:
20
- from pydantic.v1 import create_model_from_typeddict
21
- except ImportError:
22
- from pydantic import create_model_from_typeddict
22
+ if sys.version_info >= (3, 14):
23
+ from annotationlib import get_annotations
24
+ else:
25
+ from typing_extensions import get_annotations
23
26
 
24
27
  if TYPE_CHECKING:
25
28
  from ...client import Client
@@ -53,8 +56,10 @@ class AllNodesReadyEventModel(BaseDriverEventModel):
53
56
  event: Literal["all nodes ready"]
54
57
 
55
58
 
56
- LoggingEventModel = create_model_from_typeddict(
57
- LogMessageDataType, __base__=BaseDriverEventModel
59
+ LoggingEventModel = create_model(
60
+ "LoggingEventModel",
61
+ **{k: (v, None) for k, v in get_annotations(LogMessageDataType).items()},
62
+ __base__=BaseDriverEventModel,
58
63
  )
59
64
 
60
65
 
@@ -4,6 +4,8 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Literal
6
6
 
7
+ from pydantic import BaseModel
8
+
7
9
  from ...const import CommandClass
8
10
  from ...event import BaseEventModel
9
11
  from ..notification import (
@@ -20,11 +22,6 @@ from .firmware import (
20
22
  )
21
23
  from .statistics import NodeStatisticsDataType
22
24
 
23
- try:
24
- from pydantic.v1 import BaseModel
25
- except ImportError:
26
- from pydantic import BaseModel
27
-
28
25
 
29
26
  class BaseNodeEventModel(BaseEventModel):
30
27
  """Base model for a node event."""
@@ -101,8 +98,8 @@ class InterviewFailedEventArgsModel(BaseModel):
101
98
 
102
99
  errorMessage: str
103
100
  isFinal: bool
104
- attempt: int | None
105
- maxAttempts: int | None
101
+ attempt: int | None = None
102
+ maxAttempts: int | None = None
106
103
 
107
104
  @classmethod
108
105
  def from_dict(cls, data: dict) -> InterviewFailedEventArgsModel:
@@ -25,7 +25,7 @@ class NodeStatisticsDataType(TypedDict, total=False):
25
25
  commandsDroppedTX: int # required
26
26
  commandsDroppedRX: int # required
27
27
  timeoutResponse: int # required
28
- rtt: int
28
+ rtt: float
29
29
  rssi: int
30
30
  lwr: RouteStatisticsDataType
31
31
  nlwr: RouteStatisticsDataType
@@ -43,7 +43,7 @@ class NodeStatistics:
43
43
  commands_dropped_rx: int = field(init=False)
44
44
  commands_dropped_tx: int = field(init=False)
45
45
  timeout_response: int = field(init=False)
46
- rtt: int | None = field(init=False)
46
+ rtt: float | None = field(init=False)
47
47
  lwr: RouteStatistics | None = field(init=False, default=None)
48
48
  nlwr: RouteStatistics | None = field(init=False, default=None)
49
49
  last_seen: datetime | None = field(init=False, default=None)
@@ -40,7 +40,7 @@ class MetaDataType(TypedDict, total=False):
40
40
  label: str
41
41
  min: int | None
42
42
  max: int | None
43
- unit: str
43
+ unit: str | None
44
44
  states: dict[str, str]
45
45
  ccSpecific: dict[str, Any]
46
46
  valueChangeOptions: list[str]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zwave-js-server-python
3
- Version: 0.64.0
3
+ Version: 0.66.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
@@ -18,7 +18,8 @@ Requires-Python: >=3.12
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: aiohttp>3
21
- Requires-Dist: pydantic>=1.10.0
21
+ Requires-Dist: pydantic>=2.0.0
22
+ Requires-Dist: typing_extensions>=4.13.0; python_version < "3.14"
22
23
  Dynamic: license-file
23
24
 
24
25
  # zwave-js-server-python
@@ -2,12 +2,12 @@ zwave_js_server/__init__.py,sha256=Ey3O4Tha56uU-M92oLJmQHupCJ7B9oZmxlQTo8pGUM8,4
2
2
  zwave_js_server/__main__.py,sha256=X6Zdbtv6QmYjsWeQ5OvtIRhtEyT1o3o0XvAmXtRrgoY,3659
3
3
  zwave_js_server/client.py,sha256=1kwujigWJU84-vT61vvYED2EeB-4JS_7gMqu4ipjlEI,19589
4
4
  zwave_js_server/dump.py,sha256=ZBhkC07ndrFd784zpogfjRJtAdEh8-y8ZycvrGf34sE,1523
5
- zwave_js_server/event.py,sha256=zz6hzhommpsqWOZul9JtI_RlX5hyn2KVNuAqH_0Cgsg,2435
5
+ zwave_js_server/event.py,sha256=FBZ86ns4bEi95UAMrcinNs2WKHUbR7plAErIc1Ed0lg,2368
6
6
  zwave_js_server/exceptions.py,sha256=8SY6FA8NiTEQgtauLR83F7m69gBGQviJ6O2obirH2po,6148
7
7
  zwave_js_server/firmware.py,sha256=57L7olhmtJ0FosEi3GtinNjfayudbQxYRYhpgrzsj90,2328
8
8
  zwave_js_server/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  zwave_js_server/version.py,sha256=PUwxOVcUMk5pOguQP9zAjiPjs1Nnmiwj3fcA4HJLiBg,401
10
- zwave_js_server/const/__init__.py,sha256=gZNzO4KQY1t8MMSGj079-VBC44Mg9pkcdqUTF_Y6f0o,14264
10
+ zwave_js_server/const/__init__.py,sha256=4hSxTO1UyxMGPRV_mJX_JcYEF9ya-Tj6e3YGvLXAoe8,14264
11
11
  zwave_js_server/const/command_class/__init__.py,sha256=WilOppnr9CXahDjEEkAXyh_j7iCq_qZ1GtBkjWLoQUg,37
12
12
  zwave_js_server/const/command_class/barrier_operator.py,sha256=IJ195hGKEi1FLLqKWMtC2ZhY9Jt5PACr7GYTyVPjkKM,820
13
13
  zwave_js_server/const/command_class/basic.py,sha256=cs0k7p5qxrwpR8-NvXQLtnfEsC6IlBAYiW79DaM_6Eg,96
@@ -32,7 +32,7 @@ zwave_js_server/model/__init__.py,sha256=XfyKH8lxZ3CB7CbRkOr5sR-eV0GrklZiBtNPmln
32
32
  zwave_js_server/model/association.py,sha256=4rpf8PbafCYCfNJGISAmnpfcvJZTo_jPDGm2M-BuiPk,878
33
33
  zwave_js_server/model/command_class.py,sha256=SDTyGKlz5tDUoBb4RgKwPGwPuJvZ77a_q2EllN4bnzU,1394
34
34
  zwave_js_server/model/device_class.py,sha256=WTeYuR9PoIMzfjNhE21XIlHoTA9yDNEuRPkFS1W6nts,1609
35
- zwave_js_server/model/device_config.py,sha256=HpM-DchbhcyjhkDrp-6b8YaX2Qqo7KZbWk60xcMIhFY,6562
35
+ zwave_js_server/model/device_config.py,sha256=ANKQLGpXYAk6ibZTr6zRQEj6i70sby7ctsRN1XwYjc4,6525
36
36
  zwave_js_server/model/duration.py,sha256=OW2OqReexL6GXxxLs__i5Vs3JCVoODgLpwPHU48yynU,1153
37
37
  zwave_js_server/model/endpoint.py,sha256=V_OWg4PLwExOSdY4cAiY5IkiJ2FH5MHF3tKG8O0X1Lo,11911
38
38
  zwave_js_server/model/log_config.py,sha256=uF7gJlr2dSBP2mBMYzOyFiV_T45PwGU98AM5c7qs2g0,1574
@@ -40,23 +40,23 @@ zwave_js_server/model/log_message.py,sha256=SNicnss7LUZd6woMecNQ0ZKwghC9OmxNdA1v
40
40
  zwave_js_server/model/notification.py,sha256=-M9MZ1RUWmUCHuIU_So6h5sYhMILKxntGx3zBkKaqeo,6165
41
41
  zwave_js_server/model/statistics.py,sha256=in7S8oxWlG38tCEz1k3lxLjEsfY5yfsnD0bolcEeuHg,3233
42
42
  zwave_js_server/model/utils.py,sha256=VMoJQ99QRkpJleJhXR4eojbgObdZZeEfse5gonmK7Ic,1157
43
- zwave_js_server/model/value.py,sha256=Ku_VnX79WL82SD6Up01qQUNRldnCvi37HeEuTrTdBPU,13266
43
+ zwave_js_server/model/value.py,sha256=aHiWfmFym8t5aok2uxQoVHw375wbv-frNjAMAs6MSMg,13273
44
44
  zwave_js_server/model/version.py,sha256=EnyL6O8r2gSv7qLIuZ-sWnybG5JnJWw-IEE5UtIUjiM,1272
45
45
  zwave_js_server/model/config_manager/__init__.py,sha256=g1qEnadcfG7P8AJrUjxTeke9OBaKFiLVelgTQQJRMx4,1246
46
- zwave_js_server/model/controller/__init__.py,sha256=iIpxFeyPhsredhh8fMKc2y4TWCIU12F4dPFSylMVMP4,37130
46
+ zwave_js_server/model/controller/__init__.py,sha256=d2htuMJhnwF9CdcaIK7sRExDJ1ljH6ypsKOk5mu6k4M,37378
47
47
  zwave_js_server/model/controller/data_model.py,sha256=5e6M0t7RkSJytovmDz1tULMFFoCQ1TsGHe56scrZRqI,851
48
48
  zwave_js_server/model/controller/event_model.py,sha256=BtacPbezXVByd9kuMSHysywLP3eCz5VgTdWs2NmA65M,9518
49
49
  zwave_js_server/model/controller/inclusion_and_provisioning.py,sha256=PAO5HQE_yyTMxoVN3Woth1qC_oL6EzJNJ7NEvMtpBEA,7667
50
50
  zwave_js_server/model/controller/rebuild_routes.py,sha256=ElAZdSLiDaQLbGgfJQMnuilTpsSbCz3qag3lFBt2JoM,1073
51
- zwave_js_server/model/controller/statistics.py,sha256=iU2wiRvWvHzYGwydOqs8Y7CBdKA3DgL6tI1NW1zBTfU,4672
52
- zwave_js_server/model/driver/__init__.py,sha256=VMqZAdbIq4h-udwTvLfQR1zyxA3QEoAojfkgMNwz6Lg,9275
51
+ zwave_js_server/model/controller/statistics.py,sha256=s1wg-npEtXp-2yprych8BuQfG1NHq0fAZypqFz2T8hI,4954
52
+ zwave_js_server/model/driver/__init__.py,sha256=JyXBTqSg77FsGZXw2_cxLe0ICZHmxukpPPQrHfjqZrg,9390
53
53
  zwave_js_server/model/driver/firmware.py,sha256=pWSI6QYt4mJ-ff3Wd4Hyc3r-MeiJPkaAz24lFcz40Vs,2815
54
54
  zwave_js_server/model/node/__init__.py,sha256=OeHGrrjzsviGXWRv6HrLTlw70pmAagP6NwiRQACNxrE,41489
55
55
  zwave_js_server/model/node/data_model.py,sha256=lhCUcOkJ-PYAJ6ItnDwX4WkrBCMHZTDtSerf3YAdbEE,1872
56
- zwave_js_server/model/node/event_model.py,sha256=mSRqCIBt6LXvCmMaOGmWz_cLrfPqot_ScZLmVr_z2w4,10055
56
+ zwave_js_server/model/node/event_model.py,sha256=Xx_4U6HVsw1j4Hpt63CrxX4JtiVSVf9e-opaP0grZDk,10002
57
57
  zwave_js_server/model/node/firmware.py,sha256=jF1CrI6hnETj8oZsXuwQVnIkTJ9qQ8uJEdY7JAthpC0,10214
58
58
  zwave_js_server/model/node/health_check.py,sha256=GuDFPfk5BL7aK4q5aEtGcpyZz_F-aLEIGeVw_4shq5E,5341
59
- zwave_js_server/model/node/statistics.py,sha256=f8JElpXEtT7y9cLhH6UhOGVwrGprtfL5GQX1VIKAGcQ,2871
59
+ zwave_js_server/model/node/statistics.py,sha256=PkD_vsOcT_6Iwwlqy5ISBZRXFQ-alTOZwIpatRg0PFQ,2875
60
60
  zwave_js_server/util/__init__.py,sha256=ArF1K885aW0GdVd7Lo8fl8Atf70gvsxO5Ra_WoJTG28,42
61
61
  zwave_js_server/util/helpers.py,sha256=BNEaa5xSGlFwJrIIWt-Ne8BdHFOdcUnZOhZ-nsfDk2c,1638
62
62
  zwave_js_server/util/lock.py,sha256=QKl6BuzDhIP25HBB0Ba9Fl6drARXnyqV3u5ywQl0Te8,7422
@@ -66,9 +66,9 @@ zwave_js_server/util/command_class/__init__.py,sha256=sRxti47ekLTzfk8B609CMQumIb
66
66
  zwave_js_server/util/command_class/energy_production.py,sha256=K1VmGDlqXmKDfQRpTu5o99sjnDShBMV_crEb49o-O_4,1489
67
67
  zwave_js_server/util/command_class/meter.py,sha256=tJ7rbwWUZbJCS7xEJWS_KnqUUGR8RN0f2S8iLkufae0,1258
68
68
  zwave_js_server/util/command_class/multilevel_sensor.py,sha256=wG4GQ0kjrP6d3x5DpEkUHrZd8-0LbvXoYdIxZAf6bso,1427
69
- zwave_js_server_python-0.64.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
70
- zwave_js_server_python-0.64.0.dist-info/METADATA,sha256=JQb47TZYIr0rpJg_5VotGDyghTPJrf9C1QQNyxVaxDs,1927
71
- zwave_js_server_python-0.64.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
- zwave_js_server_python-0.64.0.dist-info/entry_points.txt,sha256=lvzma7Rd_3FW_k-_xGuTfpvcvA2MR_22DOz5f1t7-xg,73
73
- zwave_js_server_python-0.64.0.dist-info/top_level.txt,sha256=-hwsl-i4Av5Op_yfOHC_OP56KPmzp_iVEkeohRIN5Ng,16
74
- zwave_js_server_python-0.64.0.dist-info/RECORD,,
69
+ zwave_js_server_python-0.66.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
70
+ zwave_js_server_python-0.66.0.dist-info/METADATA,sha256=qyZN26WKUNlgK7M0o1CzFHHu7j26neqsP7trli2TseU,1992
71
+ zwave_js_server_python-0.66.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
+ zwave_js_server_python-0.66.0.dist-info/entry_points.txt,sha256=lvzma7Rd_3FW_k-_xGuTfpvcvA2MR_22DOz5f1t7-xg,73
73
+ zwave_js_server_python-0.66.0.dist-info/top_level.txt,sha256=-hwsl-i4Av5Op_yfOHC_OP56KPmzp_iVEkeohRIN5Ng,16
74
+ zwave_js_server_python-0.66.0.dist-info/RECORD,,