zwave-js-server-python 0.37.2__py3-none-any.whl → 0.38.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.
- zwave_js_server/const/__init__.py +3 -2
- zwave_js_server/firmware.py +5 -1
- zwave_js_server/model/controller/__init__.py +3 -0
- zwave_js_server/model/controller/event_model.py +8 -0
- zwave_js_server/model/firmware.py +71 -2
- zwave_js_server/model/node/__init__.py +40 -2
- {zwave_js_server_python-0.37.2.dist-info → zwave_js_server_python-0.38.0.dist-info}/METADATA +1 -1
- {zwave_js_server_python-0.37.2.dist-info → zwave_js_server_python-0.38.0.dist-info}/RECORD +12 -12
- {zwave_js_server_python-0.37.2.dist-info → zwave_js_server_python-0.38.0.dist-info}/LICENSE +0 -0
- {zwave_js_server_python-0.37.2.dist-info → zwave_js_server_python-0.38.0.dist-info}/WHEEL +0 -0
- {zwave_js_server_python-0.37.2.dist-info → zwave_js_server_python-0.38.0.dist-info}/entry_points.txt +0 -0
- {zwave_js_server_python-0.37.2.dist-info → zwave_js_server_python-0.38.0.dist-info}/top_level.txt +0 -0
|
@@ -3,14 +3,15 @@ import sys
|
|
|
3
3
|
from enum import Enum, IntEnum
|
|
4
4
|
|
|
5
5
|
# minimal server schema version we can handle
|
|
6
|
-
MIN_SERVER_SCHEMA_VERSION =
|
|
6
|
+
MIN_SERVER_SCHEMA_VERSION = 18
|
|
7
7
|
# max server schema version we can handle (and our code is compatible with)
|
|
8
|
-
MAX_SERVER_SCHEMA_VERSION =
|
|
8
|
+
MAX_SERVER_SCHEMA_VERSION = 18
|
|
9
9
|
|
|
10
10
|
TYPING_EXTENSION_FOR_TYPEDDICT_REQUIRED = sys.version_info < (3, 9, 2)
|
|
11
11
|
|
|
12
12
|
VALUE_UNKNOWN = "unknown"
|
|
13
13
|
|
|
14
|
+
NOT_INTERVIEWED = "None"
|
|
14
15
|
INTERVIEW_FAILED = "Failed"
|
|
15
16
|
|
|
16
17
|
CURRENT_STATE_PROPERTY = "currentState"
|
zwave_js_server/firmware.py
CHANGED
|
@@ -16,6 +16,7 @@ async def begin_firmware_update(
|
|
|
16
16
|
file: bytes,
|
|
17
17
|
session: aiohttp.ClientSession,
|
|
18
18
|
file_format: Optional[str] = None,
|
|
19
|
+
target: Optional[int] = None,
|
|
19
20
|
) -> None:
|
|
20
21
|
"""Send beginFirmwareUpdate command to Node."""
|
|
21
22
|
client = Client(url, session)
|
|
@@ -33,7 +34,10 @@ async def begin_firmware_update(
|
|
|
33
34
|
if file_format is not None:
|
|
34
35
|
cmd["firmwareFileFormat"] = file_format
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
if target is not None:
|
|
38
|
+
cmd["target"] = target
|
|
39
|
+
|
|
40
|
+
await client.async_send_command(cmd, require_schema=18)
|
|
37
41
|
await client.disconnect()
|
|
38
42
|
if not receive_task.done():
|
|
39
43
|
receive_task.cancel()
|
|
@@ -733,6 +733,9 @@ class Controller(EventBase):
|
|
|
733
733
|
def handle_exclusion_stopped(self, event: Event) -> None:
|
|
734
734
|
"""Process an exclusion stopped event."""
|
|
735
735
|
|
|
736
|
+
def handle_node_found(self, event: Event) -> None:
|
|
737
|
+
"""Process a node found event."""
|
|
738
|
+
|
|
736
739
|
def handle_node_added(self, event: Event) -> None:
|
|
737
740
|
"""Process a node added event."""
|
|
738
741
|
node = event.data["node"] = Node(self.client, event.data["node"])
|
|
@@ -97,6 +97,13 @@ class NodeAddedEventModel(BaseControllerEventModel):
|
|
|
97
97
|
result: InclusionResultDataType
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
class NodeFoundEventModel(BaseControllerEventModel):
|
|
101
|
+
"""Model for `node found` event data."""
|
|
102
|
+
|
|
103
|
+
event: Literal["node found"]
|
|
104
|
+
node: NodeDataType
|
|
105
|
+
|
|
106
|
+
|
|
100
107
|
class NodeRemovedEventModel(BaseControllerEventModel):
|
|
101
108
|
"""Model for `node removed` event data."""
|
|
102
109
|
|
|
@@ -158,6 +165,7 @@ CONTROLLER_EVENT_MODEL_MAP: Dict[str, Type["BaseControllerEventModel"]] = {
|
|
|
158
165
|
"inclusion started": InclusionStartedEventModel,
|
|
159
166
|
"inclusion stopped": InclusionStoppedEventModel,
|
|
160
167
|
"node added": NodeAddedEventModel,
|
|
168
|
+
"node found": NodeFoundEventModel,
|
|
161
169
|
"node removed": NodeRemovedEventModel,
|
|
162
170
|
"nvm backup progress": NVMBackupProgressEventModel,
|
|
163
171
|
"nvm convert progress": NVMConvertProgressEventModel,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""Provide a model for Z-Wave firmware."""
|
|
2
2
|
from enum import IntEnum
|
|
3
|
-
from typing import TYPE_CHECKING, Optional
|
|
3
|
+
from typing import TYPE_CHECKING, List, Optional, Union
|
|
4
4
|
|
|
5
|
-
from ..const import TYPING_EXTENSION_FOR_TYPEDDICT_REQUIRED
|
|
5
|
+
from ..const import TYPING_EXTENSION_FOR_TYPEDDICT_REQUIRED, VALUE_UNKNOWN
|
|
6
6
|
|
|
7
7
|
if TYPING_EXTENSION_FOR_TYPEDDICT_REQUIRED:
|
|
8
8
|
from typing_extensions import TypedDict
|
|
@@ -13,6 +13,75 @@ if TYPE_CHECKING:
|
|
|
13
13
|
from .node import Node
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
class FirmwareUpdateCapabilitiesDataType(TypedDict, total=False):
|
|
17
|
+
"""Represent a firmware update capabilities dict type."""
|
|
18
|
+
|
|
19
|
+
firmwareUpgradable: bool # required
|
|
20
|
+
firmwareTargets: List[int]
|
|
21
|
+
continuesToFunction: Union[bool, str]
|
|
22
|
+
supportsActivation: Union[bool, str]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FirmwareUpdateCapabilitiesDict(TypedDict, total=False):
|
|
26
|
+
"""Represent a dict from FirmwareUpdateCapabilities."""
|
|
27
|
+
|
|
28
|
+
firmware_upgradable: bool # required
|
|
29
|
+
firmware_targets: List[int]
|
|
30
|
+
continues_to_function: Optional[bool]
|
|
31
|
+
supports_activation: Optional[bool]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class FirmwareUpdateCapabilities:
|
|
35
|
+
"""Model for firmware update capabilities."""
|
|
36
|
+
|
|
37
|
+
def __init__(self, data: FirmwareUpdateCapabilitiesDataType) -> None:
|
|
38
|
+
"""Initialize class."""
|
|
39
|
+
self.data = data
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def firmware_upgradable(self) -> bool:
|
|
43
|
+
"""Return whether firmware is upgradable."""
|
|
44
|
+
return self.data["firmwareUpgradable"]
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def firmware_targets(self) -> List[int]:
|
|
48
|
+
"""Return firmware targets."""
|
|
49
|
+
if not self.firmware_upgradable:
|
|
50
|
+
raise TypeError("Firmware is not upgradeable.")
|
|
51
|
+
return self.data["firmwareTargets"]
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def continues_to_function(self) -> Optional[bool]:
|
|
55
|
+
"""Return whether node continues to function during update."""
|
|
56
|
+
if not self.firmware_upgradable:
|
|
57
|
+
raise TypeError("Firmware is not upgradeable.")
|
|
58
|
+
if (val := self.data["continuesToFunction"]) == VALUE_UNKNOWN:
|
|
59
|
+
return None
|
|
60
|
+
assert isinstance(val, bool)
|
|
61
|
+
return val
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def supports_activation(self) -> Optional[bool]:
|
|
65
|
+
"""Return whether node supports delayed activation of the new firmware."""
|
|
66
|
+
if not self.firmware_upgradable:
|
|
67
|
+
raise TypeError("Firmware is not upgradeable.")
|
|
68
|
+
if (val := self.data["supportsActivation"]) == VALUE_UNKNOWN:
|
|
69
|
+
return None
|
|
70
|
+
assert isinstance(val, bool)
|
|
71
|
+
return val
|
|
72
|
+
|
|
73
|
+
def to_dict(self) -> FirmwareUpdateCapabilitiesDict:
|
|
74
|
+
"""Return dict representation of the object."""
|
|
75
|
+
if not self.firmware_upgradable:
|
|
76
|
+
return {"firmware_upgradable": self.firmware_upgradable}
|
|
77
|
+
return {
|
|
78
|
+
"firmware_upgradable": self.firmware_upgradable,
|
|
79
|
+
"firmware_targets": self.firmware_targets,
|
|
80
|
+
"continues_to_function": self.continues_to_function,
|
|
81
|
+
"supports_activation": self.supports_activation,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
16
85
|
class FirmwareUpdateStatus(IntEnum):
|
|
17
86
|
"""Enum with all Firmware update status values.
|
|
18
87
|
|
|
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union, cast
|
|
|
4
4
|
|
|
5
5
|
from ...const import (
|
|
6
6
|
INTERVIEW_FAILED,
|
|
7
|
+
NOT_INTERVIEWED,
|
|
7
8
|
CommandClass,
|
|
8
9
|
NodeStatus,
|
|
9
10
|
PowerLevel,
|
|
@@ -21,6 +22,8 @@ from ..device_class import DeviceClass
|
|
|
21
22
|
from ..device_config import DeviceConfig
|
|
22
23
|
from ..endpoint import Endpoint
|
|
23
24
|
from ..firmware import (
|
|
25
|
+
FirmwareUpdateCapabilities,
|
|
26
|
+
FirmwareUpdateCapabilitiesDataType,
|
|
24
27
|
FirmwareUpdateFinished,
|
|
25
28
|
FirmwareUpdateFinishedDataType,
|
|
26
29
|
FirmwareUpdateProgress,
|
|
@@ -269,7 +272,16 @@ class Node(EventBase):
|
|
|
269
272
|
@property
|
|
270
273
|
def in_interview(self) -> bool:
|
|
271
274
|
"""Return whether node is currently being interviewed."""
|
|
272
|
-
return
|
|
275
|
+
return (
|
|
276
|
+
not self.ready
|
|
277
|
+
and not self.awaiting_manual_interview
|
|
278
|
+
and self.interview_stage != INTERVIEW_FAILED
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
@property
|
|
282
|
+
def awaiting_manual_interview(self) -> bool:
|
|
283
|
+
"""Return whether node requires a manual interview."""
|
|
284
|
+
return self.interview_stage in (None, NOT_INTERVIEWED)
|
|
273
285
|
|
|
274
286
|
@property
|
|
275
287
|
def command_classes(self) -> List[CommandClassInfo]:
|
|
@@ -496,9 +508,23 @@ class Node(EventBase):
|
|
|
496
508
|
)
|
|
497
509
|
return ValueMetadata(cast(MetaDataType, data))
|
|
498
510
|
|
|
511
|
+
async def async_get_firmware_update_capabilities(
|
|
512
|
+
self,
|
|
513
|
+
) -> FirmwareUpdateCapabilities:
|
|
514
|
+
"""Send getFirmwareUpdateCapabilities command to Node."""
|
|
515
|
+
data = await self.async_send_command(
|
|
516
|
+
"get_firmware_update_capabilities",
|
|
517
|
+
require_schema=7,
|
|
518
|
+
wait_for_result=True,
|
|
519
|
+
)
|
|
520
|
+
assert data
|
|
521
|
+
return FirmwareUpdateCapabilities(
|
|
522
|
+
cast(FirmwareUpdateCapabilitiesDataType, data["capabilities"])
|
|
523
|
+
)
|
|
524
|
+
|
|
499
525
|
async def async_abort_firmware_update(self) -> None:
|
|
500
526
|
"""Send abortFirmwareUpdate command to Node."""
|
|
501
|
-
await self.async_send_command("abort_firmware_update", wait_for_result=
|
|
527
|
+
await self.async_send_command("abort_firmware_update", wait_for_result=True)
|
|
502
528
|
|
|
503
529
|
async def async_poll_value(self, val: Union[Value, str]) -> None:
|
|
504
530
|
"""Send pollValue command to Node for given value (or value_id)."""
|
|
@@ -644,6 +670,18 @@ class Node(EventBase):
|
|
|
644
670
|
)
|
|
645
671
|
self.data["location"] = location
|
|
646
672
|
|
|
673
|
+
async def async_get_firmware_update_progress(self) -> bool:
|
|
674
|
+
"""
|
|
675
|
+
Send getFirmwareUpdateProgress command to Node.
|
|
676
|
+
|
|
677
|
+
If `True`, a firmware update for this node is in progress.
|
|
678
|
+
"""
|
|
679
|
+
data = await self.async_send_command(
|
|
680
|
+
"get_firmware_update_progress", require_schema=18, wait_for_result=True
|
|
681
|
+
)
|
|
682
|
+
assert data
|
|
683
|
+
return cast(bool, data["progress"])
|
|
684
|
+
|
|
647
685
|
async def async_set_keep_awake(self, keep_awake: bool) -> None:
|
|
648
686
|
"""Set node keep awake state."""
|
|
649
687
|
await self.async_send_command(
|
|
@@ -4,10 +4,10 @@ zwave_js_server/client.py,sha256=Fu_QlYYo-HrpENdcUxFDsSQmEQBxW6kA3_JAYo8LPgs,149
|
|
|
4
4
|
zwave_js_server/dump.py,sha256=hTyeW8fPleyQyYyPjFeR_JxwmFRHvtpmpn1L9uNpfiw,1213
|
|
5
5
|
zwave_js_server/event.py,sha256=E2bIEb635al9MsCB5rkk3ZklU4-YkmqmXtifzlbxXaQ,1958
|
|
6
6
|
zwave_js_server/exceptions.py,sha256=guJlsUNQMGl-P8dVydup686_xzpbzCkd1870RbqZ6PE,5623
|
|
7
|
-
zwave_js_server/firmware.py,sha256=
|
|
7
|
+
zwave_js_server/firmware.py,sha256=Wo_o2e_jHeuX0mDTFUEJ-l_m3QOkXIwVFsLxBLYAC8E,1139
|
|
8
8
|
zwave_js_server/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
zwave_js_server/version.py,sha256=RDFP2kSU3cCVIQbgMWggdeDnvhtVsZzzZg9pOjH7CC8,364
|
|
10
|
-
zwave_js_server/const/__init__.py,sha256=
|
|
10
|
+
zwave_js_server/const/__init__.py,sha256=hmYMLOcJKwHOOqXYF7N7lNMvA8dl9L4YFnkvApcFKlI,8506
|
|
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=NBhTp5T-6T31glpIKrEOLgbKTndkB5gqdQmCJlXFFUA,783
|
|
13
13
|
zwave_js_server/const/command_class/color_switch.py,sha256=9jIDdmz8gJ5d1RdINHiK7Yh0NXg1I0U1xVzkrQJICk8,918
|
|
@@ -30,7 +30,7 @@ zwave_js_server/model/device_class.py,sha256=KpSM101bGa_3Mig4C-_rkE4CzqImK2JPIUt
|
|
|
30
30
|
zwave_js_server/model/device_config.py,sha256=7NaMa4BZ5tGe2p0YtOQFIUjBwRVF7GYWVExLwAgIUtE,6659
|
|
31
31
|
zwave_js_server/model/driver.py,sha256=u5jOFZ2-mRWqAbiNB5yX_3qC7Uw1mjJdxLgeNignnho,6289
|
|
32
32
|
zwave_js_server/model/endpoint.py,sha256=YGZts5-5y1ok6gIi7NsjM8puLwpv4XDVJhfUUTJ4rJQ,6001
|
|
33
|
-
zwave_js_server/model/firmware.py,sha256
|
|
33
|
+
zwave_js_server/model/firmware.py,sha256=-ercachu45pHd8cafzhDey5XpxX4b0CCufSFistJQYQ,4996
|
|
34
34
|
zwave_js_server/model/log_config.py,sha256=F-QM7oHUXAfAxbdkrvmi6k6woM4VOwxB3qRrGmTQiQA,1722
|
|
35
35
|
zwave_js_server/model/log_message.py,sha256=IxZ4USpXTeHsuRNS61NDPYMSIflv1KDO_EjUy4_vavE,5859
|
|
36
36
|
zwave_js_server/model/notification.py,sha256=yLTUgOa_N0wedIsuJNDdhXEbfPVSIdXof7h_A_aibEU,6706
|
|
@@ -38,12 +38,12 @@ zwave_js_server/model/statistics.py,sha256=uG87o-iNGKHxJc4Kfr2ZJ0VY7NjCbdxwgWOqu
|
|
|
38
38
|
zwave_js_server/model/utils.py,sha256=fLs1pOKG53yWQggBWUKvPgzlT0JkK3biLzRkhPBNArI,814
|
|
39
39
|
zwave_js_server/model/value.py,sha256=dV6a3QMga1T-KfCQsle6lauK9rxSzd6rhF-eldRaJOU,8754
|
|
40
40
|
zwave_js_server/model/version.py,sha256=W1H-UbhKdgMW5KdnY9MUfRFibfMZSOD3nljXOv1ZVVM,1398
|
|
41
|
-
zwave_js_server/model/controller/__init__.py,sha256=
|
|
41
|
+
zwave_js_server/model/controller/__init__.py,sha256=L4tBNDlocsQy3Xbi1u51IyZqUt99URrXG5oD8BHCBFs,29775
|
|
42
42
|
zwave_js_server/model/controller/data_model.py,sha256=On7ZCEe5-vbVPs_ucFqlquxpjilT2TDGtiZwE8odtV4,970
|
|
43
|
-
zwave_js_server/model/controller/event_model.py,sha256=
|
|
43
|
+
zwave_js_server/model/controller/event_model.py,sha256=PseC6YMT4NSRovUKbdYy_lZtB0qe1ujspK3W7miJ1rU,5137
|
|
44
44
|
zwave_js_server/model/controller/inclusion_and_provisioning.py,sha256=01YUq4YBhQe3gmJAIsN6ctMM3pcLEaGMSyIySBI9v2c,7497
|
|
45
45
|
zwave_js_server/model/controller/statistics.py,sha256=7aeFjKq_-TvcHBWc-a4xQP6wvO3GoGjr9P-m8uyOco8,4031
|
|
46
|
-
zwave_js_server/model/node/__init__.py,sha256=
|
|
46
|
+
zwave_js_server/model/node/__init__.py,sha256=69UwPFVPApQ8uxknIoYvOkf-FU0c5B2kOLomXSp1GaI,30564
|
|
47
47
|
zwave_js_server/model/node/data_model.py,sha256=Zdl68Oa9vUn2wegriFOcU70Q2yJO41rGKpdAdIbbtAU,1730
|
|
48
48
|
zwave_js_server/model/node/event_model.py,sha256=kY-HxdRpJUGiQaM4T7DInQBJ4rf4pw1JY-nImsF-1kY,6055
|
|
49
49
|
zwave_js_server/model/node/health_check.py,sha256=EAOMBkMKd5q--fhax2GvJhWdhuuv5dX_-2Hf_mczODs,6054
|
|
@@ -56,9 +56,9 @@ zwave_js_server/util/node.py,sha256=KUg-Z-7hdDLGKKCYLktc4oOgiPbDT7ZUYqUH_IPLwO4,
|
|
|
56
56
|
zwave_js_server/util/command_class/__init__.py,sha256=sRxti47ekLTzfk8B609CMQumIbcD6mon2ZS0zwh9omY,59
|
|
57
57
|
zwave_js_server/util/command_class/meter.py,sha256=Qkif1ul4KpV_k6Dc7yNXlSjlJLLTH8mCitgQk9J9W0A,1277
|
|
58
58
|
zwave_js_server/util/command_class/multilevel_sensor.py,sha256=p92YLNRze5z3UWhfIDJO95F-j5tqx1PKUG9oamo9Dng,1446
|
|
59
|
-
zwave_js_server_python-0.
|
|
60
|
-
zwave_js_server_python-0.
|
|
61
|
-
zwave_js_server_python-0.
|
|
62
|
-
zwave_js_server_python-0.
|
|
63
|
-
zwave_js_server_python-0.
|
|
64
|
-
zwave_js_server_python-0.
|
|
59
|
+
zwave_js_server_python-0.38.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
60
|
+
zwave_js_server_python-0.38.0.dist-info/METADATA,sha256=oIWlUj5T-6dPuxhpqQJa59Y6WqFekvIeCn5exT2PRLk,1712
|
|
61
|
+
zwave_js_server_python-0.38.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
62
|
+
zwave_js_server_python-0.38.0.dist-info/entry_points.txt,sha256=_8Swg1yhKiBElo6k1fxIEd6E8uPz8PDxQpwQoZ29FZE,74
|
|
63
|
+
zwave_js_server_python-0.38.0.dist-info/top_level.txt,sha256=-hwsl-i4Av5Op_yfOHC_OP56KPmzp_iVEkeohRIN5Ng,16
|
|
64
|
+
zwave_js_server_python-0.38.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{zwave_js_server_python-0.37.2.dist-info → zwave_js_server_python-0.38.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{zwave_js_server_python-0.37.2.dist-info → zwave_js_server_python-0.38.0.dist-info}/top_level.txt
RENAMED
|
File without changes
|