zwave-js-server-python 0.71.0__tar.gz → 0.73.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 (84) hide show
  1. {zwave_js_server_python-0.71.0/zwave_js_server_python.egg-info → zwave_js_server_python-0.73.0}/PKG-INFO +1 -1
  2. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/__init__.py +3 -3
  3. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/access_control.py +95 -0
  4. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/node/__init__.py +6 -0
  5. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/node/event_model.py +24 -0
  6. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/node/firmware.py +4 -2
  7. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0/zwave_js_server_python.egg-info}/PKG-INFO +1 -1
  8. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/LICENSE +0 -0
  9. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/MANIFEST.in +0 -0
  10. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/README.md +0 -0
  11. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/pyproject.toml +0 -0
  12. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/setup.cfg +0 -0
  13. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/__init__.py +0 -0
  14. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/__main__.py +0 -0
  15. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/client.py +0 -0
  16. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/__init__.py +0 -0
  17. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/access_control.py +0 -0
  18. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/barrier_operator.py +0 -0
  19. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/basic.py +0 -0
  20. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/battery.py +0 -0
  21. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/central_scene.py +0 -0
  22. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/color_switch.py +0 -0
  23. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/energy_production.py +0 -0
  24. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/entry_control.py +0 -0
  25. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/humidity_control.py +0 -0
  26. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/lock.py +0 -0
  27. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/meter.py +0 -0
  28. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/multilevel_sensor.py +0 -0
  29. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/multilevel_switch.py +0 -0
  30. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/notification.py +0 -0
  31. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/power_level.py +0 -0
  32. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/protection.py +0 -0
  33. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/scene_activation.py +0 -0
  34. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/sound_switch.py +0 -0
  35. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/thermostat.py +0 -0
  36. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/wake_up.py +0 -0
  37. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/const/command_class/window_covering.py +0 -0
  38. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/dump.py +0 -0
  39. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/event.py +0 -0
  40. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/exceptions.py +0 -0
  41. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/firmware.py +0 -0
  42. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/__init__.py +0 -0
  43. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/association.py +0 -0
  44. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/command_class.py +0 -0
  45. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/config_manager/__init__.py +0 -0
  46. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/controller/__init__.py +0 -0
  47. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/controller/data_model.py +0 -0
  48. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/controller/event_model.py +0 -0
  49. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/controller/inclusion_and_provisioning.py +0 -0
  50. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/controller/rebuild_routes.py +0 -0
  51. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/controller/statistics.py +0 -0
  52. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/device_class.py +0 -0
  53. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/device_config.py +0 -0
  54. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/driver/__init__.py +0 -0
  55. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/driver/firmware.py +0 -0
  56. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/duration.py +0 -0
  57. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/endpoint.py +0 -0
  58. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/firmware.py +0 -0
  59. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/log_config.py +0 -0
  60. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/log_message.py +0 -0
  61. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/node/data_model.py +0 -0
  62. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/node/health_check.py +0 -0
  63. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/node/statistics.py +0 -0
  64. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/notification.py +0 -0
  65. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/statistics.py +0 -0
  66. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/utils.py +0 -0
  67. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/value.py +0 -0
  68. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/model/version.py +0 -0
  69. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/py.typed +0 -0
  70. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/__init__.py +0 -0
  71. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/command_class/__init__.py +0 -0
  72. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/command_class/energy_production.py +0 -0
  73. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/command_class/meter.py +0 -0
  74. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/command_class/multilevel_sensor.py +0 -0
  75. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/helpers.py +0 -0
  76. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/lock.py +0 -0
  77. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/multicast.py +0 -0
  78. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/util/node.py +0 -0
  79. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server/version.py +0 -0
  80. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server_python.egg-info/SOURCES.txt +0 -0
  81. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server_python.egg-info/dependency_links.txt +0 -0
  82. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server_python.egg-info/entry_points.txt +0 -0
  83. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.0}/zwave_js_server_python.egg-info/requires.txt +0 -0
  84. {zwave_js_server_python-0.71.0 → zwave_js_server_python-0.73.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.71.0
3
+ Version: 0.73.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
@@ -8,12 +8,12 @@ import logging
8
8
  from typing import TypedDict
9
9
 
10
10
  PACKAGE_NAME = "zwave-js-server-python"
11
- __version__ = "0.71.0"
11
+ __version__ = "0.73.0"
12
12
 
13
13
  # minimal server schema version we can handle
14
- MIN_SERVER_SCHEMA_VERSION = 47
14
+ MIN_SERVER_SCHEMA_VERSION = 49
15
15
  # max server schema version we can handle (and our code is compatible with)
16
- MAX_SERVER_SCHEMA_VERSION = 48
16
+ MAX_SERVER_SCHEMA_VERSION = 50
17
17
 
18
18
  VALUE_UNKNOWN = "unknown"
19
19
 
@@ -107,6 +107,7 @@ class UserCapabilitiesDataType(TypedDict, total=False):
107
107
  supportedUserTypes: list[UserCredentialUserType]
108
108
  maxUserNameLength: int
109
109
  supportedCredentialRules: list[UserCredentialRule]
110
+ supportsUsersWithoutCredentials: bool
110
111
 
111
112
 
112
113
  @dataclass
@@ -117,6 +118,7 @@ class UserCapabilities:
117
118
  supported_user_types: list[UserCredentialUserType] = field(default_factory=list)
118
119
  max_user_name_length: int | None = None
119
120
  supported_credential_rules: list[UserCredentialRule] = field(default_factory=list)
121
+ supports_users_without_credentials: bool = False
120
122
 
121
123
  @classmethod
122
124
  def from_dict(cls, data: UserCapabilitiesDataType) -> Self:
@@ -132,6 +134,9 @@ class UserCapabilities:
132
134
  UserCredentialRule(rule)
133
135
  for rule in data.get("supportedCredentialRules", [])
134
136
  ],
137
+ supports_users_without_credentials=data.get(
138
+ "supportsUsersWithoutCredentials", False
139
+ ),
135
140
  )
136
141
 
137
142
  def to_dict(self) -> UserCapabilitiesDataType:
@@ -140,6 +145,9 @@ class UserCapabilities:
140
145
  "maxUsers": self.max_users,
141
146
  "supportedUserTypes": list(self.supported_user_types),
142
147
  "supportedCredentialRules": list(self.supported_credential_rules),
148
+ "supportsUsersWithoutCredentials": (
149
+ self.supports_users_without_credentials
150
+ ),
143
151
  }
144
152
  if self.max_user_name_length is not None:
145
153
  data["maxUserNameLength"] = self.max_user_name_length
@@ -291,6 +299,31 @@ class SetUserOptions:
291
299
  return data
292
300
 
293
301
 
302
+ class AddUserCredentialDataType(TypedDict):
303
+ """Represent a credential serialized for an add-user command."""
304
+
305
+ credentialType: UserCredentialType
306
+ credentialSlot: int
307
+ data: str | BufferObjectDataType
308
+
309
+
310
+ @dataclass
311
+ class AddUserCredential:
312
+ """Credential to write together with a new user via add_user."""
313
+
314
+ credential_type: UserCredentialType
315
+ credential_slot: int
316
+ data: str | bytes
317
+
318
+ def to_dict(self) -> AddUserCredentialDataType:
319
+ """Return the serialized credential for an add-user command."""
320
+ return {
321
+ "credentialType": self.credential_type,
322
+ "credentialSlot": self.credential_slot,
323
+ "data": serialize_credential_data(self.data),
324
+ }
325
+
326
+
294
327
  class CredentialDataDataType(TypedDict, total=False):
295
328
  """Represent access-control credential payload."""
296
329
 
@@ -331,6 +364,43 @@ class CredentialData:
331
364
  return data
332
365
 
333
366
 
367
+ class AddUserResultDataType(TypedDict, total=False):
368
+ """Represent the result of an add-user command."""
369
+
370
+ user: SetUserResult
371
+ credential: SetCredentialResult
372
+
373
+
374
+ @dataclass
375
+ class AddUserResult:
376
+ """Result of an add-user command.
377
+
378
+ Mirrors zwave-js's ``addUser`` return value: the result of adding the user
379
+ and, when a credential was provided, the result of writing it.
380
+ """
381
+
382
+ user: SetUserResult
383
+ credential: SetCredentialResult | None = None
384
+
385
+ @classmethod
386
+ def from_dict(cls, data: AddUserResultDataType) -> Self:
387
+ """Return add-user result from serialized payload."""
388
+ credential = data.get("credential")
389
+ return cls(
390
+ user=SetUserResult(data["user"]),
391
+ credential=(
392
+ SetCredentialResult(credential) if credential is not None else None
393
+ ),
394
+ )
395
+
396
+ def to_dict(self) -> AddUserResultDataType:
397
+ """Return the serialized add-user result."""
398
+ data: AddUserResultDataType = {"user": self.user}
399
+ if self.credential is not None:
400
+ data["credential"] = self.credential
401
+ return data
402
+
403
+
334
404
  class UserDeletedArgsDataType(TypedDict):
335
405
  """Represent access-control user deleted event args."""
336
406
 
@@ -622,6 +692,31 @@ class AccessControlAPI:
622
692
  assert result is not None
623
693
  return SetUserResult(result["result"])
624
694
 
695
+ async def add_user(
696
+ self,
697
+ user_id: int,
698
+ options: SetUserOptions,
699
+ credential: AddUserCredential | None = None,
700
+ ) -> AddUserResult:
701
+ """Create a new user, optionally writing a credential in the same call.
702
+
703
+ On devices using User Code CC, users and credentials cannot be stored
704
+ separately, so ``credential`` is required there.
705
+ """
706
+ cmd_kwargs: dict[str, Any] = {}
707
+ if credential is not None:
708
+ cmd_kwargs["credential"] = credential.to_dict()
709
+ result = await self._endpoint.async_send_command(
710
+ "access_control.add_user",
711
+ userId=user_id,
712
+ options=options.to_dict(),
713
+ require_schema=49,
714
+ wait_for_result=True,
715
+ **cmd_kwargs,
716
+ )
717
+ assert result is not None
718
+ return AddUserResult.from_dict(cast(AddUserResultDataType, result["result"]))
719
+
625
720
  async def delete_user(self, user_id: int) -> SetUserResult:
626
721
  """Delete an access-control user."""
627
722
  result = await self._endpoint.async_send_command(
@@ -1114,6 +1114,12 @@ class Node(EventBase):
1114
1114
  self.data["ready"] = False
1115
1115
  self.data["interviewStage"] = None
1116
1116
 
1117
+ def handle_interview_progress(self, event: Event) -> None:
1118
+ """Process a node interview progress event."""
1119
+ # Do not override the interview stage here. The stage of the
1120
+ # `interview progress` event is the _current_ one, while the
1121
+ # `interviewStage` field is the _last completed_ stage.
1122
+
1117
1123
  def handle_interview_stage_completed(self, event: Event) -> None:
1118
1124
  """Process a node interview stage completed event."""
1119
1125
  self.data["interviewStage"] = event.data["stageName"]
@@ -163,6 +163,29 @@ class InterviewFailedEventModel(BaseNodeEventModel):
163
163
  )
164
164
 
165
165
 
166
+ class InterviewProgressEventModel(BaseNodeEventModel):
167
+ """Model for `interview progress` event data."""
168
+
169
+ event: Literal["interview progress"]
170
+ stage: str
171
+ progress: float
172
+ endpoint: int | None = None
173
+ commandClass: int | None = None
174
+
175
+ @classmethod
176
+ def from_dict(cls, data: dict) -> InterviewProgressEventModel:
177
+ """Initialize from dict."""
178
+ return cls(
179
+ source=data["source"],
180
+ event=data["event"],
181
+ nodeId=data["nodeId"],
182
+ stage=data["stage"],
183
+ progress=data["progress"],
184
+ endpoint=data.get("endpoint"),
185
+ commandClass=data.get("commandClass"),
186
+ )
187
+
188
+
166
189
  class InterviewStageCompletedEventModel(BaseNodeEventModel):
167
190
  """Model for `interview stage completed` event data."""
168
191
 
@@ -452,6 +475,7 @@ NODE_EVENT_MODEL_MAP: dict[str, type[BaseNodeEventModel]] = {
452
475
  "firmware update progress": FirmwareUpdateProgressEventModel,
453
476
  "interview completed": InterviewCompletedEventModel,
454
477
  "interview failed": InterviewFailedEventModel,
478
+ "interview progress": InterviewProgressEventModel,
455
479
  "interview stage completed": InterviewStageCompletedEventModel,
456
480
  "interview started": InterviewStartedEventModel,
457
481
  "metadata updated": MetadataUpdatedEventModel,
@@ -89,7 +89,9 @@ class NodeFirmwareUpdateCapabilities:
89
89
  """Return whether node continues to function during update."""
90
90
  if not self.firmware_upgradable:
91
91
  raise TypeError("Firmware is not upgradeable.")
92
- if (val := self.data["continuesToFunction"]) == VALUE_UNKNOWN:
92
+ if (
93
+ val := self.data.get("continuesToFunction", VALUE_UNKNOWN)
94
+ ) == VALUE_UNKNOWN:
93
95
  return None
94
96
  assert isinstance(val, bool)
95
97
  return val
@@ -99,7 +101,7 @@ class NodeFirmwareUpdateCapabilities:
99
101
  """Return whether node supports delayed activation of the new firmware."""
100
102
  if not self.firmware_upgradable:
101
103
  raise TypeError("Firmware is not upgradeable.")
102
- if (val := self.data["supportsActivation"]) == VALUE_UNKNOWN:
104
+ if (val := self.data.get("supportsActivation", VALUE_UNKNOWN)) == VALUE_UNKNOWN:
103
105
  return None
104
106
  assert isinstance(val, bool)
105
107
  return val
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zwave-js-server-python
3
- Version: 0.71.0
3
+ Version: 0.73.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