zwave-js-server-python 0.66.0__tar.gz → 0.67.1__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.
- {zwave_js_server_python-0.66.0/zwave_js_server_python.egg-info → zwave_js_server_python-0.67.1}/PKG-INFO +1 -2
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/pyproject.toml +0 -3
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/__init__.py +3 -3
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/config_manager/__init__.py +2 -2
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/driver/__init__.py +73 -13
- zwave_js_server_python-0.67.1/zwave_js_server/model/driver/firmware.py +65 -0
- zwave_js_server_python-0.67.1/zwave_js_server/model/firmware.py +210 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/node/__init__.py +2 -5
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/node/firmware.py +68 -132
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1/zwave_js_server_python.egg-info}/PKG-INFO +1 -2
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server_python.egg-info/SOURCES.txt +1 -0
- zwave_js_server_python-0.67.1/zwave_js_server_python.egg-info/requires.txt +2 -0
- zwave_js_server_python-0.66.0/zwave_js_server/model/driver/firmware.py +0 -97
- zwave_js_server_python-0.66.0/zwave_js_server_python.egg-info/requires.txt +0 -5
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/LICENSE +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/MANIFEST.in +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/README.md +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/setup.cfg +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/__init__.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/__main__.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/client.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/__init__.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/barrier_operator.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/basic.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/central_scene.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/color_switch.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/energy_production.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/entry_control.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/humidity_control.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/lock.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/meter.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/multilevel_sensor.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/multilevel_switch.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/notification.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/power_level.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/protection.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/scene_activation.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/sound_switch.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/thermostat.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/wake_up.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/command_class/window_covering.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/dump.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/event.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/exceptions.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/firmware.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/__init__.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/association.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/command_class.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/controller/__init__.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/controller/data_model.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/controller/event_model.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/controller/inclusion_and_provisioning.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/controller/rebuild_routes.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/controller/statistics.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/device_class.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/device_config.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/duration.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/endpoint.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/log_config.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/log_message.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/node/data_model.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/node/event_model.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/node/health_check.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/node/statistics.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/notification.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/statistics.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/utils.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/value.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/version.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/py.typed +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/__init__.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/command_class/__init__.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/command_class/energy_production.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/command_class/meter.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/command_class/multilevel_sensor.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/helpers.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/lock.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/multicast.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/node.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/version.py +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server_python.egg-info/dependency_links.txt +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server_python.egg-info/entry_points.txt +0 -0
- {zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/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.
|
3
|
+
Version: 0.67.1
|
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
|
@@ -19,7 +19,6 @@ Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
20
20
|
Requires-Dist: aiohttp>3
|
21
21
|
Requires-Dist: pydantic>=2.0.0
|
22
|
-
Requires-Dist: typing_extensions>=4.13.0; python_version < "3.14"
|
23
22
|
Dynamic: license-file
|
24
23
|
|
25
24
|
# zwave-js-server-python
|
@@ -22,7 +22,6 @@ classifiers = [
|
|
22
22
|
dependencies = [
|
23
23
|
"aiohttp>3",
|
24
24
|
"pydantic>=2.0.0",
|
25
|
-
"typing_extensions>=4.13.0;python_version<'3.14'",
|
26
25
|
]
|
27
26
|
dynamic = ["version"]
|
28
27
|
|
@@ -44,8 +43,6 @@ zwave_js_server = ["py.typed"]
|
|
44
43
|
|
45
44
|
[tool.mypy]
|
46
45
|
plugins = ["pydantic.mypy"]
|
47
|
-
follow_imports = "skip"
|
48
|
-
ignore_missing_imports = true
|
49
46
|
check_untyped_defs = true
|
50
47
|
disallow_incomplete_defs = true
|
51
48
|
disallow_untyped_calls = true
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/const/__init__.py
RENAMED
@@ -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.
|
11
|
+
__version__ = "0.67.1"
|
12
12
|
|
13
13
|
# minimal server schema version we can handle
|
14
|
-
MIN_SERVER_SCHEMA_VERSION =
|
14
|
+
MIN_SERVER_SCHEMA_VERSION = 44
|
15
15
|
# max server schema version we can handle (and our code is compatible with)
|
16
|
-
MAX_SERVER_SCHEMA_VERSION =
|
16
|
+
MAX_SERVER_SCHEMA_VERSION = 44
|
17
17
|
|
18
18
|
VALUE_UNKNOWN = "unknown"
|
19
19
|
|
@@ -6,7 +6,7 @@ https://zwave-js.github.io/node-zwave-js/#/api/config-manager
|
|
6
6
|
|
7
7
|
from __future__ import annotations
|
8
8
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
9
|
+
from typing import TYPE_CHECKING, Any
|
10
10
|
|
11
11
|
from ..device_config import DeviceConfig
|
12
12
|
|
@@ -26,7 +26,7 @@ class ConfigManager:
|
|
26
26
|
manufacturer_id: int,
|
27
27
|
product_type: int,
|
28
28
|
product_id: int,
|
29
|
-
firmware_version:
|
29
|
+
firmware_version: str | None = None,
|
30
30
|
) -> DeviceConfig | None:
|
31
31
|
"""Look up the definition of a given device in the configuration DB."""
|
32
32
|
cmd: dict[str, Any] = {
|
@@ -2,16 +2,20 @@
|
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
|
-
import sys
|
6
5
|
from typing import TYPE_CHECKING, Any, Literal, cast
|
7
6
|
|
8
|
-
from
|
7
|
+
from zwave_js_server.model.firmware import (
|
8
|
+
FirmwareUpdateData,
|
9
|
+
FirmwareUpdateDataDataType,
|
10
|
+
FirmwareUpdateInfo,
|
11
|
+
FirmwareUpdateInfoDataType,
|
12
|
+
)
|
9
13
|
|
10
14
|
from ...event import BaseEventModel, Event, EventBase
|
11
15
|
from ..config_manager import ConfigManager
|
12
16
|
from ..controller import Controller
|
13
17
|
from ..log_config import LogConfig, LogConfigDataType
|
14
|
-
from ..log_message import LogMessage, LogMessageDataType
|
18
|
+
from ..log_message import LogMessage, LogMessageContextDataType, LogMessageDataType
|
15
19
|
from .firmware import (
|
16
20
|
DriverFirmwareUpdateProgress,
|
17
21
|
DriverFirmwareUpdateProgressDataType,
|
@@ -19,11 +23,6 @@ from .firmware import (
|
|
19
23
|
DriverFirmwareUpdateResultDataType,
|
20
24
|
)
|
21
25
|
|
22
|
-
if sys.version_info >= (3, 14):
|
23
|
-
from annotationlib import get_annotations
|
24
|
-
else:
|
25
|
-
from typing_extensions import get_annotations
|
26
|
-
|
27
26
|
if TYPE_CHECKING:
|
28
27
|
from ...client import Client
|
29
28
|
|
@@ -56,11 +55,40 @@ class AllNodesReadyEventModel(BaseDriverEventModel):
|
|
56
55
|
event: Literal["all nodes ready"]
|
57
56
|
|
58
57
|
|
59
|
-
LoggingEventModel
|
60
|
-
"
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
class LoggingEventModel(BaseDriverEventModel):
|
59
|
+
"""Model for `logging` event data."""
|
60
|
+
|
61
|
+
event: Literal["logging"]
|
62
|
+
message: str | list[str] # required
|
63
|
+
formattedMessage: str | list[str] # required
|
64
|
+
direction: str # required
|
65
|
+
level: str # required
|
66
|
+
context: LogMessageContextDataType # required
|
67
|
+
primaryTags: str | None = None
|
68
|
+
secondaryTags: str | None = None
|
69
|
+
secondaryTagPadding: int | None = None
|
70
|
+
multiline: bool | None = None
|
71
|
+
timestamp: str | None = None
|
72
|
+
label: str | None = None
|
73
|
+
|
74
|
+
@classmethod
|
75
|
+
def from_dict(cls, data: dict) -> LoggingEventModel:
|
76
|
+
"""Initialize from dict."""
|
77
|
+
return cls(
|
78
|
+
source=data["source"],
|
79
|
+
event=data["event"],
|
80
|
+
message=data["message"],
|
81
|
+
formattedMessage=data["formattedMessage"],
|
82
|
+
direction=data["direction"],
|
83
|
+
level=data["level"],
|
84
|
+
context=data["context"],
|
85
|
+
primaryTags=data.get("primaryTags"),
|
86
|
+
secondaryTags=data.get("secondaryTags"),
|
87
|
+
secondaryTagPadding=data.get("secondaryTagPadding"),
|
88
|
+
multiline=data.get("multiline"),
|
89
|
+
timestamp=data.get("timestamp"),
|
90
|
+
label=data.get("label"),
|
91
|
+
)
|
64
92
|
|
65
93
|
|
66
94
|
class DriverReadyEventModel(BaseDriverEventModel):
|
@@ -221,6 +249,38 @@ class Driver(EventBase):
|
|
221
249
|
)
|
222
250
|
return cast(bool, result["success"])
|
223
251
|
|
252
|
+
async def async_firmware_update_otw(
|
253
|
+
self,
|
254
|
+
*,
|
255
|
+
update_data: FirmwareUpdateData | None = None,
|
256
|
+
update_info: FirmwareUpdateInfo | None = None,
|
257
|
+
) -> DriverFirmwareUpdateResult:
|
258
|
+
"""Send firmwareUpdateOTW command to Driver."""
|
259
|
+
if update_data is None and update_info is None:
|
260
|
+
raise ValueError(
|
261
|
+
"Either update_data or update_info must be provided for firmware update."
|
262
|
+
)
|
263
|
+
if update_data is not None and update_info is not None:
|
264
|
+
raise ValueError(
|
265
|
+
"Only one of update_data or update_info can be provided for firmware update."
|
266
|
+
)
|
267
|
+
params: FirmwareUpdateDataDataType | dict[str, FirmwareUpdateInfoDataType]
|
268
|
+
if update_data is not None:
|
269
|
+
params = update_data.to_dict()
|
270
|
+
elif update_info is not None:
|
271
|
+
params = {"updateInfo": update_info.to_dict()}
|
272
|
+
data = await self._async_send_command(
|
273
|
+
"firmware_update_otw", require_schema=44, **params
|
274
|
+
)
|
275
|
+
return DriverFirmwareUpdateResult(data["result"])
|
276
|
+
|
277
|
+
async def async_is_otw_firmware_update_in_progress(self) -> bool:
|
278
|
+
"""Send isOTWFirmwareUpdateInProgress command to Driver."""
|
279
|
+
result = await self._async_send_command(
|
280
|
+
"is_otw_firmware_update_in_progress", require_schema=41
|
281
|
+
)
|
282
|
+
return cast(bool, result["progress"])
|
283
|
+
|
224
284
|
async def async_set_preferred_scales(
|
225
285
|
self, scales: dict[str | int, str | int]
|
226
286
|
) -> None:
|
@@ -0,0 +1,65 @@
|
|
1
|
+
"""Provide a model for Z-Wave driver firmware."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from dataclasses import dataclass, field
|
6
|
+
from enum import IntEnum
|
7
|
+
|
8
|
+
from zwave_js_server.model.firmware import (
|
9
|
+
FirmwareUpdateData,
|
10
|
+
FirmwareUpdateDataDataType,
|
11
|
+
FirmwareUpdateProgress,
|
12
|
+
FirmwareUpdateProgressDataType,
|
13
|
+
FirmwareUpdateResult,
|
14
|
+
FirmwareUpdateResultDataType,
|
15
|
+
)
|
16
|
+
|
17
|
+
|
18
|
+
class DriverFirmwareUpdateDataDataType(FirmwareUpdateDataDataType):
|
19
|
+
"""Represent a driver firmware update data dict type."""
|
20
|
+
|
21
|
+
|
22
|
+
@dataclass
|
23
|
+
class DriverFirmwareUpdateData(FirmwareUpdateData):
|
24
|
+
"""Driver firmware update data."""
|
25
|
+
|
26
|
+
|
27
|
+
class DriverFirmwareUpdateStatus(IntEnum):
|
28
|
+
"""Enum with all driver firmware update status values.
|
29
|
+
|
30
|
+
https://zwave-js.github.io/node-zwave-js/#/api/driver?id=quotfirmware-update-finishedquot
|
31
|
+
"""
|
32
|
+
|
33
|
+
ERROR_TIMEOUT = 0
|
34
|
+
# The maximum number of retry attempts for a firmware fragments were reached
|
35
|
+
ERROR_RETRY_LIMIT_REACHED = 1
|
36
|
+
# The update was aborted by the bootloader
|
37
|
+
ERROR_ABORTED = 2
|
38
|
+
# This driver does not support firmware updates
|
39
|
+
ERROR_NOT_SUPPORTED = 3
|
40
|
+
OK = 255
|
41
|
+
|
42
|
+
|
43
|
+
class DriverFirmwareUpdateProgressDataType(FirmwareUpdateProgressDataType):
|
44
|
+
"""Represent a driver firmware update progress dict type."""
|
45
|
+
|
46
|
+
|
47
|
+
@dataclass
|
48
|
+
class DriverFirmwareUpdateProgress(FirmwareUpdateProgress):
|
49
|
+
"""Model for a driver firmware update progress data."""
|
50
|
+
|
51
|
+
data: DriverFirmwareUpdateProgressDataType = field(repr=False)
|
52
|
+
|
53
|
+
|
54
|
+
class DriverFirmwareUpdateResultDataType(FirmwareUpdateResultDataType):
|
55
|
+
"""Represent a driver firmware update result dict type."""
|
56
|
+
|
57
|
+
|
58
|
+
@dataclass
|
59
|
+
class DriverFirmwareUpdateResult(FirmwareUpdateResult):
|
60
|
+
"""Model for driver firmware update result data."""
|
61
|
+
|
62
|
+
data: DriverFirmwareUpdateResultDataType = field(repr=False)
|
63
|
+
status: DriverFirmwareUpdateStatus = field(init=False)
|
64
|
+
success: bool = field(init=False)
|
65
|
+
_status_class = DriverFirmwareUpdateStatus
|
@@ -0,0 +1,210 @@
|
|
1
|
+
"""Provide models for Z-Wave JS firmware."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from dataclasses import asdict, dataclass, field
|
6
|
+
from enum import IntEnum
|
7
|
+
from typing import Literal, Required, TypedDict, cast
|
8
|
+
|
9
|
+
from zwave_js_server.const import RFRegion
|
10
|
+
from zwave_js_server.util.helpers import convert_bytes_to_base64
|
11
|
+
|
12
|
+
|
13
|
+
@dataclass
|
14
|
+
class FirmwareUpdateData:
|
15
|
+
"""Firmware update data."""
|
16
|
+
|
17
|
+
filename: str
|
18
|
+
file: bytes
|
19
|
+
file_format: str | None = None
|
20
|
+
|
21
|
+
def to_dict(self) -> FirmwareUpdateDataDataType:
|
22
|
+
"""Convert firmware update data to dict."""
|
23
|
+
data: FirmwareUpdateDataDataType = {
|
24
|
+
"filename": self.filename,
|
25
|
+
"file": convert_bytes_to_base64(self.file),
|
26
|
+
}
|
27
|
+
if self.file_format is not None:
|
28
|
+
data["fileFormat"] = self.file_format
|
29
|
+
return data
|
30
|
+
|
31
|
+
|
32
|
+
class FirmwareUpdateDataDataType(TypedDict, total=False):
|
33
|
+
"""Represent a firmware update data dict type."""
|
34
|
+
|
35
|
+
filename: Required[str]
|
36
|
+
file: Required[str]
|
37
|
+
fileFormat: str
|
38
|
+
|
39
|
+
|
40
|
+
@dataclass
|
41
|
+
class FirmwareUpdateInfo:
|
42
|
+
"""Represent a firmware update info."""
|
43
|
+
|
44
|
+
version: str
|
45
|
+
changelog: str
|
46
|
+
channel: Literal["stable", "beta"]
|
47
|
+
files: list[FirmwareUpdateFileInfo]
|
48
|
+
downgrade: bool
|
49
|
+
normalized_version: str
|
50
|
+
device: FirmwareUpdateDeviceID
|
51
|
+
|
52
|
+
@classmethod
|
53
|
+
def from_dict(cls, data: FirmwareUpdateInfoDataType) -> FirmwareUpdateInfo:
|
54
|
+
"""Initialize from dict."""
|
55
|
+
return cls(
|
56
|
+
version=data["version"],
|
57
|
+
changelog=data["changelog"],
|
58
|
+
channel=data["channel"],
|
59
|
+
files=[FirmwareUpdateFileInfo.from_dict(file) for file in data["files"]],
|
60
|
+
downgrade=data["downgrade"],
|
61
|
+
normalized_version=data["normalizedVersion"],
|
62
|
+
device=FirmwareUpdateDeviceID.from_dict(data["device"]),
|
63
|
+
)
|
64
|
+
|
65
|
+
def to_dict(self) -> FirmwareUpdateInfoDataType:
|
66
|
+
"""Return dict representation of the object."""
|
67
|
+
return cast(
|
68
|
+
FirmwareUpdateInfoDataType,
|
69
|
+
{
|
70
|
+
"version": self.version,
|
71
|
+
"changelog": self.changelog,
|
72
|
+
"channel": self.channel,
|
73
|
+
"files": [file.to_dict() for file in self.files],
|
74
|
+
"downgrade": self.downgrade,
|
75
|
+
"normalizedVersion": self.normalized_version,
|
76
|
+
"device": self.device.to_dict(),
|
77
|
+
},
|
78
|
+
)
|
79
|
+
|
80
|
+
|
81
|
+
class FirmwareUpdateInfoDataType(TypedDict, total=False):
|
82
|
+
"""Represent a firmware update info data dict type."""
|
83
|
+
|
84
|
+
version: str
|
85
|
+
changelog: str
|
86
|
+
channel: Literal["stable", "beta"]
|
87
|
+
files: list[FirmwareUpdateFileInfoDataType]
|
88
|
+
downgrade: bool
|
89
|
+
normalizedVersion: str
|
90
|
+
device: FirmwareUpdateDeviceIDDataType
|
91
|
+
|
92
|
+
|
93
|
+
@dataclass
|
94
|
+
class FirmwareUpdateDeviceID:
|
95
|
+
"""Represent a firmware update device ID."""
|
96
|
+
|
97
|
+
manufacturer_id: int
|
98
|
+
product_type: int
|
99
|
+
product_id: int
|
100
|
+
firmware_version: str
|
101
|
+
rf_region: RFRegion | None
|
102
|
+
|
103
|
+
@classmethod
|
104
|
+
def from_dict(cls, data: FirmwareUpdateDeviceIDDataType) -> FirmwareUpdateDeviceID:
|
105
|
+
"""Initialize from dict."""
|
106
|
+
return cls(
|
107
|
+
manufacturer_id=data["manufacturerId"],
|
108
|
+
product_type=data["productType"],
|
109
|
+
product_id=data["productId"],
|
110
|
+
firmware_version=data["firmwareVersion"],
|
111
|
+
rf_region=RFRegion(data["rfRegion"]) if "rfRegion" in data else None,
|
112
|
+
)
|
113
|
+
|
114
|
+
def to_dict(self) -> FirmwareUpdateDeviceIDDataType:
|
115
|
+
"""Return dict representation of the object."""
|
116
|
+
data = {
|
117
|
+
"manufacturerId": self.manufacturer_id,
|
118
|
+
"productType": self.product_type,
|
119
|
+
"productId": self.product_id,
|
120
|
+
"firmwareVersion": self.firmware_version,
|
121
|
+
}
|
122
|
+
if self.rf_region is not None:
|
123
|
+
data["rfRegion"] = self.rf_region
|
124
|
+
return cast(FirmwareUpdateDeviceIDDataType, data)
|
125
|
+
|
126
|
+
|
127
|
+
class FirmwareUpdateDeviceIDDataType(TypedDict, total=False):
|
128
|
+
"""Represent a firmware update device ID dict type."""
|
129
|
+
|
130
|
+
manufacturerId: Required[int]
|
131
|
+
productType: Required[int]
|
132
|
+
productId: Required[int]
|
133
|
+
firmwareVersion: Required[str]
|
134
|
+
rfRegion: int
|
135
|
+
|
136
|
+
|
137
|
+
@dataclass
|
138
|
+
class FirmwareUpdateFileInfo:
|
139
|
+
"""Represent a firmware update file info."""
|
140
|
+
|
141
|
+
target: int
|
142
|
+
url: str
|
143
|
+
integrity: str
|
144
|
+
|
145
|
+
@classmethod
|
146
|
+
def from_dict(cls, data: FirmwareUpdateFileInfoDataType) -> FirmwareUpdateFileInfo:
|
147
|
+
"""Initialize from dict."""
|
148
|
+
return cls(
|
149
|
+
target=data["target"],
|
150
|
+
url=data["url"],
|
151
|
+
integrity=data["integrity"],
|
152
|
+
)
|
153
|
+
|
154
|
+
def to_dict(self) -> FirmwareUpdateFileInfoDataType:
|
155
|
+
"""Return dict representation of the object."""
|
156
|
+
return cast(FirmwareUpdateFileInfoDataType, asdict(self))
|
157
|
+
|
158
|
+
|
159
|
+
class FirmwareUpdateFileInfoDataType(TypedDict):
|
160
|
+
"""Represent a firmware update file info data dict type."""
|
161
|
+
|
162
|
+
target: int
|
163
|
+
url: str
|
164
|
+
integrity: str # sha256
|
165
|
+
|
166
|
+
|
167
|
+
@dataclass
|
168
|
+
class FirmwareUpdateProgress:
|
169
|
+
"""Model for a firmware update progress."""
|
170
|
+
|
171
|
+
data: FirmwareUpdateProgressDataType = field(repr=False)
|
172
|
+
sent_fragments: int = field(init=False)
|
173
|
+
total_fragments: int = field(init=False)
|
174
|
+
progress: float = field(init=False)
|
175
|
+
|
176
|
+
def __post_init__(self) -> None:
|
177
|
+
"""Post initialize."""
|
178
|
+
self.sent_fragments = self.data["sentFragments"]
|
179
|
+
self.total_fragments = self.data["totalFragments"]
|
180
|
+
self.progress = float(self.data["progress"])
|
181
|
+
|
182
|
+
|
183
|
+
class FirmwareUpdateProgressDataType(TypedDict):
|
184
|
+
"""Represent a firmware update progress dict type."""
|
185
|
+
|
186
|
+
sentFragments: int
|
187
|
+
totalFragments: int
|
188
|
+
progress: float
|
189
|
+
|
190
|
+
|
191
|
+
@dataclass
|
192
|
+
class FirmwareUpdateResult:
|
193
|
+
"""Model for firmware update result data."""
|
194
|
+
|
195
|
+
data: FirmwareUpdateResultDataType = field(repr=False)
|
196
|
+
status: IntEnum = field(init=False)
|
197
|
+
success: bool = field(init=False)
|
198
|
+
_status_class: type[IntEnum] = field(init=False, repr=False)
|
199
|
+
|
200
|
+
def __post_init__(self) -> None:
|
201
|
+
"""Post initialize."""
|
202
|
+
self.status = self._status_class(self.data["status"])
|
203
|
+
self.success = self.data["success"]
|
204
|
+
|
205
|
+
|
206
|
+
class FirmwareUpdateResultDataType(TypedDict):
|
207
|
+
"""Represent a driver firmware update result dict type."""
|
208
|
+
|
209
|
+
status: int
|
210
|
+
success: bool
|
@@ -395,7 +395,7 @@ class Node(EventBase):
|
|
395
395
|
values = {
|
396
396
|
value_id: value
|
397
397
|
for value_id, value in self.values.items()
|
398
|
-
if
|
398
|
+
if endpoint_idx == value.endpoint
|
399
399
|
}
|
400
400
|
if endpoint_idx in self.endpoints:
|
401
401
|
self.endpoints[endpoint_idx].update(endpoint, values)
|
@@ -503,10 +503,7 @@ class Node(EventBase):
|
|
503
503
|
if wait_for_result:
|
504
504
|
result = await self.client.async_send_command(message, **kwargs)
|
505
505
|
return result
|
506
|
-
if wait_for_result is None and self.status not in (
|
507
|
-
NodeStatus.ASLEEP,
|
508
|
-
NodeStatus.DEAD,
|
509
|
-
):
|
506
|
+
if wait_for_result is None and self.status not in (NodeStatus.ASLEEP,):
|
510
507
|
result_task = asyncio.create_task(
|
511
508
|
self.client.async_send_command(message, **kwargs)
|
512
509
|
)
|
@@ -2,52 +2,56 @@
|
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
|
-
from dataclasses import
|
5
|
+
from dataclasses import dataclass, field
|
6
6
|
from enum import IntEnum
|
7
|
-
from typing import TYPE_CHECKING,
|
8
|
-
|
9
|
-
from
|
10
|
-
|
7
|
+
from typing import TYPE_CHECKING, Required, TypedDict, cast
|
8
|
+
|
9
|
+
from zwave_js_server.model.firmware import (
|
10
|
+
FirmwareUpdateData,
|
11
|
+
FirmwareUpdateDataDataType,
|
12
|
+
FirmwareUpdateDeviceID,
|
13
|
+
FirmwareUpdateDeviceIDDataType,
|
14
|
+
FirmwareUpdateFileInfo,
|
15
|
+
FirmwareUpdateFileInfoDataType,
|
16
|
+
FirmwareUpdateInfo,
|
17
|
+
FirmwareUpdateInfoDataType,
|
18
|
+
FirmwareUpdateProgress,
|
19
|
+
FirmwareUpdateProgressDataType,
|
20
|
+
FirmwareUpdateResult,
|
21
|
+
FirmwareUpdateResultDataType,
|
22
|
+
)
|
23
|
+
|
24
|
+
from ...const import VALUE_UNKNOWN
|
11
25
|
|
12
26
|
if TYPE_CHECKING:
|
13
27
|
from . import Node
|
14
28
|
|
15
29
|
|
16
|
-
class NodeFirmwareUpdateDataDataType(
|
30
|
+
class NodeFirmwareUpdateDataDataType(FirmwareUpdateDataDataType):
|
17
31
|
"""Represent a firmware update data dict type."""
|
18
32
|
|
19
|
-
filename: str # required
|
20
|
-
file: str # required
|
21
|
-
fileFormat: str
|
22
33
|
firmwareTarget: int
|
23
34
|
|
24
35
|
|
25
36
|
@dataclass
|
26
|
-
class NodeFirmwareUpdateData:
|
37
|
+
class NodeFirmwareUpdateData(FirmwareUpdateData):
|
27
38
|
"""Firmware update data."""
|
28
39
|
|
29
|
-
filename: str
|
30
|
-
file: bytes
|
31
|
-
file_format: str | None = None
|
32
40
|
firmware_target: int | None = None
|
33
41
|
|
34
42
|
def to_dict(self) -> NodeFirmwareUpdateDataDataType:
|
35
43
|
"""Convert firmware update data to dict."""
|
36
|
-
data
|
37
|
-
|
38
|
-
"file": convert_bytes_to_base64(self.file),
|
39
|
-
}
|
40
|
-
if self.file_format is not None:
|
41
|
-
data["fileFormat"] = self.file_format
|
44
|
+
data = super().to_dict()
|
45
|
+
node_data = cast(NodeFirmwareUpdateDataDataType, data)
|
42
46
|
if self.firmware_target is not None:
|
43
|
-
|
44
|
-
return
|
47
|
+
node_data["firmwareTarget"] = self.firmware_target
|
48
|
+
return node_data
|
45
49
|
|
46
50
|
|
47
51
|
class NodeFirmwareUpdateCapabilitiesDataType(TypedDict, total=False):
|
48
52
|
"""Represent a firmware update capabilities dict type."""
|
49
53
|
|
50
|
-
firmwareUpgradable: bool
|
54
|
+
firmwareUpgradable: Required[bool]
|
51
55
|
firmwareTargets: list[int]
|
52
56
|
continuesToFunction: bool | str
|
53
57
|
supportsActivation: bool | str
|
@@ -56,7 +60,7 @@ class NodeFirmwareUpdateCapabilitiesDataType(TypedDict, total=False):
|
|
56
60
|
class NodeFirmwareUpdateCapabilitiesDict(TypedDict, total=False):
|
57
61
|
"""Represent a dict from FirmwareUpdateCapabilities."""
|
58
62
|
|
59
|
-
firmware_upgradable: bool
|
63
|
+
firmware_upgradable: Required[bool]
|
60
64
|
firmware_targets: list[int]
|
61
65
|
continues_to_function: bool | None
|
62
66
|
supports_activation: bool | None
|
@@ -133,193 +137,125 @@ class NodeFirmwareUpdateStatus(IntEnum):
|
|
133
137
|
OK_RESTART_PENDING = 255
|
134
138
|
|
135
139
|
|
136
|
-
class NodeFirmwareUpdateProgressDataType(
|
140
|
+
class NodeFirmwareUpdateProgressDataType(FirmwareUpdateProgressDataType):
|
137
141
|
"""Represent a node firmware update progress dict type."""
|
138
142
|
|
139
143
|
currentFile: int
|
140
144
|
totalFiles: int
|
141
|
-
sentFragments: int
|
142
|
-
totalFragments: int
|
143
|
-
progress: float
|
144
145
|
|
145
146
|
|
146
147
|
@dataclass
|
147
|
-
class NodeFirmwareUpdateProgress:
|
148
|
+
class NodeFirmwareUpdateProgress(FirmwareUpdateProgress):
|
148
149
|
"""Model for a node firmware update progress data."""
|
149
150
|
|
150
151
|
node: Node
|
151
152
|
data: NodeFirmwareUpdateProgressDataType = field(repr=False)
|
152
153
|
current_file: int = field(init=False)
|
153
154
|
total_files: int = field(init=False)
|
154
|
-
|
155
|
-
|
156
|
-
|
155
|
+
|
156
|
+
def __init__(self, node: Node, data: NodeFirmwareUpdateProgressDataType) -> None:
|
157
|
+
"""Initialize the node firmware update progress.
|
158
|
+
|
159
|
+
Explicit init method to retain backwards compatibility
|
160
|
+
that requires the node as first parameter.
|
161
|
+
"""
|
162
|
+
super().__init__(data)
|
163
|
+
self.node = node
|
157
164
|
|
158
165
|
def __post_init__(self) -> None:
|
159
166
|
"""Post initialize."""
|
167
|
+
super().__post_init__()
|
160
168
|
self.current_file = self.data["currentFile"]
|
161
169
|
self.total_files = self.data["totalFiles"]
|
162
|
-
self.sent_fragments = self.data["sentFragments"]
|
163
|
-
self.total_fragments = self.data["totalFragments"]
|
164
|
-
self.progress = float(self.data["progress"])
|
165
170
|
|
166
171
|
|
167
|
-
class NodeFirmwareUpdateResultDataType(
|
172
|
+
class NodeFirmwareUpdateResultDataType(FirmwareUpdateResultDataType, total=False):
|
168
173
|
"""Represent a node firmware update result dict type."""
|
169
174
|
|
170
|
-
status: int # required
|
171
|
-
success: bool # required
|
172
175
|
waitTime: int
|
173
|
-
reInterview: bool
|
176
|
+
reInterview: Required[bool]
|
174
177
|
|
175
178
|
|
176
179
|
@dataclass
|
177
|
-
class NodeFirmwareUpdateResult:
|
180
|
+
class NodeFirmwareUpdateResult(FirmwareUpdateResult):
|
178
181
|
"""Model for node firmware update result data."""
|
179
182
|
|
180
183
|
node: Node
|
181
184
|
data: NodeFirmwareUpdateResultDataType = field(repr=False)
|
182
185
|
status: NodeFirmwareUpdateStatus = field(init=False)
|
183
|
-
success: bool = field(init=False)
|
184
186
|
wait_time: int | None = field(init=False)
|
185
187
|
reinterview: bool = field(init=False)
|
188
|
+
_status_class = NodeFirmwareUpdateStatus
|
189
|
+
|
190
|
+
def __init__(self, node: Node, data: NodeFirmwareUpdateResultDataType) -> None:
|
191
|
+
"""Initialize the node firmware update result.
|
192
|
+
|
193
|
+
Explicit init method to retain backwards compatibility
|
194
|
+
that requires the node as first parameter.
|
195
|
+
"""
|
196
|
+
super().__init__(data)
|
197
|
+
self.node = node
|
186
198
|
|
187
199
|
def __post_init__(self) -> None:
|
188
200
|
"""Post initialize."""
|
189
|
-
|
190
|
-
self.success = self.data["success"]
|
201
|
+
super().__post_init__()
|
191
202
|
self.wait_time = self.data.get("waitTime")
|
192
203
|
self.reinterview = self.data["reInterview"]
|
193
204
|
|
194
205
|
|
195
|
-
class NodeFirmwareUpdateFileInfoDataType(
|
196
|
-
"""Represent a firmware update file info data dict type."""
|
197
|
-
|
198
|
-
target: int
|
199
|
-
url: str
|
200
|
-
integrity: str # sha256
|
206
|
+
class NodeFirmwareUpdateFileInfoDataType(FirmwareUpdateFileInfoDataType):
|
207
|
+
"""Represent a node firmware update file info data dict type."""
|
201
208
|
|
202
209
|
|
203
210
|
@dataclass
|
204
|
-
class NodeFirmwareUpdateFileInfo:
|
211
|
+
class NodeFirmwareUpdateFileInfo(FirmwareUpdateFileInfo):
|
205
212
|
"""Represent a firmware update file info."""
|
206
213
|
|
207
|
-
target: int
|
208
|
-
url: str
|
209
|
-
integrity: str
|
210
|
-
|
211
214
|
@classmethod
|
212
215
|
def from_dict(
|
213
216
|
cls, data: NodeFirmwareUpdateFileInfoDataType
|
214
217
|
) -> NodeFirmwareUpdateFileInfo:
|
215
218
|
"""Initialize from dict."""
|
216
|
-
return
|
217
|
-
target=data["target"],
|
218
|
-
url=data["url"],
|
219
|
-
integrity=data["integrity"],
|
220
|
-
)
|
219
|
+
return cast(NodeFirmwareUpdateFileInfo, super().from_dict(data))
|
221
220
|
|
222
221
|
def to_dict(self) -> NodeFirmwareUpdateFileInfoDataType:
|
223
222
|
"""Return dict representation of the object."""
|
224
|
-
return
|
225
|
-
|
223
|
+
return super().to_dict()
|
226
224
|
|
227
|
-
class NodeFirmwareUpdateDeviceIDDataType(TypedDict, total=False):
|
228
|
-
"""Represent a firmware update device ID dict type."""
|
229
225
|
|
230
|
-
|
231
|
-
|
232
|
-
productId: int # required
|
233
|
-
firmwareVersion: str # required
|
234
|
-
rfRegion: int
|
226
|
+
class NodeFirmwareUpdateDeviceIDDataType(FirmwareUpdateDeviceIDDataType):
|
227
|
+
"""Represent a node firmware update device ID data dict type."""
|
235
228
|
|
236
229
|
|
237
230
|
@dataclass
|
238
|
-
class NodeFirmwareUpdateDeviceID:
|
231
|
+
class NodeFirmwareUpdateDeviceID(FirmwareUpdateDeviceID):
|
239
232
|
"""Represent a firmware update device ID."""
|
240
233
|
|
241
|
-
manufacturer_id: int
|
242
|
-
product_type: int
|
243
|
-
product_id: int
|
244
|
-
firmware_version: str
|
245
|
-
rf_region: RFRegion | None
|
246
|
-
|
247
234
|
@classmethod
|
248
235
|
def from_dict(
|
249
236
|
cls, data: NodeFirmwareUpdateDeviceIDDataType
|
250
237
|
) -> NodeFirmwareUpdateDeviceID:
|
251
238
|
"""Initialize from dict."""
|
252
|
-
return
|
253
|
-
manufacturer_id=data["manufacturerId"],
|
254
|
-
product_type=data["productType"],
|
255
|
-
product_id=data["productId"],
|
256
|
-
firmware_version=data["firmwareVersion"],
|
257
|
-
rf_region=RFRegion(data["rfRegion"]) if "rfRegion" in data else None,
|
258
|
-
)
|
239
|
+
return cast(NodeFirmwareUpdateDeviceID, super().from_dict(data))
|
259
240
|
|
260
241
|
def to_dict(self) -> NodeFirmwareUpdateDeviceIDDataType:
|
261
242
|
"""Return dict representation of the object."""
|
262
|
-
|
263
|
-
"manufacturerId": self.manufacturer_id,
|
264
|
-
"productType": self.product_type,
|
265
|
-
"productId": self.product_id,
|
266
|
-
"firmwareVersion": self.firmware_version,
|
267
|
-
}
|
268
|
-
if self.rf_region is not None:
|
269
|
-
data["rfRegion"] = self.rf_region
|
270
|
-
return cast(NodeFirmwareUpdateDeviceIDDataType, data)
|
271
|
-
|
243
|
+
return super().to_dict()
|
272
244
|
|
273
|
-
class NodeFirmwareUpdateInfoDataType(TypedDict, total=False):
|
274
|
-
"""Represent a firmware update info data dict type."""
|
275
245
|
|
276
|
-
|
277
|
-
|
278
|
-
channel: Literal["stable", "beta"]
|
279
|
-
files: list[NodeFirmwareUpdateFileInfoDataType]
|
280
|
-
downgrade: bool
|
281
|
-
normalizedVersion: str
|
282
|
-
device: NodeFirmwareUpdateDeviceIDDataType
|
246
|
+
class NodeFirmwareUpdateInfoDataType(FirmwareUpdateInfoDataType):
|
247
|
+
"""Represent a node firmware update info data dict type."""
|
283
248
|
|
284
249
|
|
285
250
|
@dataclass
|
286
|
-
class NodeFirmwareUpdateInfo:
|
251
|
+
class NodeFirmwareUpdateInfo(FirmwareUpdateInfo):
|
287
252
|
"""Represent a firmware update info."""
|
288
253
|
|
289
|
-
version: str
|
290
|
-
changelog: str
|
291
|
-
channel: Literal["stable", "beta"]
|
292
|
-
files: list[NodeFirmwareUpdateFileInfo]
|
293
|
-
downgrade: bool
|
294
|
-
normalized_version: str
|
295
|
-
device: NodeFirmwareUpdateDeviceID
|
296
|
-
|
297
254
|
@classmethod
|
298
255
|
def from_dict(cls, data: NodeFirmwareUpdateInfoDataType) -> NodeFirmwareUpdateInfo:
|
299
256
|
"""Initialize from dict."""
|
300
|
-
return
|
301
|
-
version=data["version"],
|
302
|
-
changelog=data["changelog"],
|
303
|
-
channel=data["channel"],
|
304
|
-
files=[
|
305
|
-
NodeFirmwareUpdateFileInfo.from_dict(file) for file in data["files"]
|
306
|
-
],
|
307
|
-
downgrade=data["downgrade"],
|
308
|
-
normalized_version=data["normalizedVersion"],
|
309
|
-
device=NodeFirmwareUpdateDeviceID.from_dict(data["device"]),
|
310
|
-
)
|
257
|
+
return cast(NodeFirmwareUpdateInfo, super().from_dict(data))
|
311
258
|
|
312
259
|
def to_dict(self) -> NodeFirmwareUpdateInfoDataType:
|
313
260
|
"""Return dict representation of the object."""
|
314
|
-
return
|
315
|
-
NodeFirmwareUpdateInfoDataType,
|
316
|
-
{
|
317
|
-
"version": self.version,
|
318
|
-
"changelog": self.changelog,
|
319
|
-
"channel": self.channel,
|
320
|
-
"files": [file.to_dict() for file in self.files],
|
321
|
-
"downgrade": self.downgrade,
|
322
|
-
"normalizedVersion": self.normalized_version,
|
323
|
-
"device": self.device.to_dict(),
|
324
|
-
},
|
325
|
-
)
|
261
|
+
return super().to_dict()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: zwave-js-server-python
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.67.1
|
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
|
@@ -19,7 +19,6 @@ Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
20
20
|
Requires-Dist: aiohttp>3
|
21
21
|
Requires-Dist: pydantic>=2.0.0
|
22
|
-
Requires-Dist: typing_extensions>=4.13.0; python_version < "3.14"
|
23
22
|
Dynamic: license-file
|
24
23
|
|
25
24
|
# zwave-js-server-python
|
@@ -39,6 +39,7 @@ zwave_js_server/model/device_class.py
|
|
39
39
|
zwave_js_server/model/device_config.py
|
40
40
|
zwave_js_server/model/duration.py
|
41
41
|
zwave_js_server/model/endpoint.py
|
42
|
+
zwave_js_server/model/firmware.py
|
42
43
|
zwave_js_server/model/log_config.py
|
43
44
|
zwave_js_server/model/log_message.py
|
44
45
|
zwave_js_server/model/notification.py
|
@@ -1,97 +0,0 @@
|
|
1
|
-
"""Provide a model for Z-Wave driver firmware."""
|
2
|
-
|
3
|
-
from __future__ import annotations
|
4
|
-
|
5
|
-
from dataclasses import dataclass, field
|
6
|
-
from enum import IntEnum
|
7
|
-
from typing import TypedDict
|
8
|
-
|
9
|
-
from ...util.helpers import convert_bytes_to_base64
|
10
|
-
|
11
|
-
|
12
|
-
class DriverFirmwareUpdateDataDataType(TypedDict, total=False):
|
13
|
-
"""Represent a driver firmware update data dict type."""
|
14
|
-
|
15
|
-
filename: str # required
|
16
|
-
file: str # required
|
17
|
-
fileFormat: str
|
18
|
-
|
19
|
-
|
20
|
-
@dataclass
|
21
|
-
class DriverFirmwareUpdateData:
|
22
|
-
"""Driver firmware update data."""
|
23
|
-
|
24
|
-
filename: str
|
25
|
-
file: bytes
|
26
|
-
file_format: str | None = None
|
27
|
-
|
28
|
-
def to_dict(self) -> DriverFirmwareUpdateDataDataType:
|
29
|
-
"""Convert firmware update data to dict."""
|
30
|
-
data: DriverFirmwareUpdateDataDataType = {
|
31
|
-
"filename": self.filename,
|
32
|
-
"file": convert_bytes_to_base64(self.file),
|
33
|
-
}
|
34
|
-
if self.file_format is not None:
|
35
|
-
data["fileFormat"] = self.file_format
|
36
|
-
return data
|
37
|
-
|
38
|
-
|
39
|
-
class DriverFirmwareUpdateStatus(IntEnum):
|
40
|
-
"""Enum with all driver firmware update status values.
|
41
|
-
|
42
|
-
https://zwave-js.github.io/node-zwave-js/#/api/driver?id=quotfirmware-update-finishedquot
|
43
|
-
"""
|
44
|
-
|
45
|
-
ERROR_TIMEOUT = 0
|
46
|
-
# The maximum number of retry attempts for a firmware fragments were reached
|
47
|
-
ERROR_RETRY_LIMIT_REACHED = 1
|
48
|
-
# The update was aborted by the bootloader
|
49
|
-
ERROR_ABORTED = 2
|
50
|
-
# This driver does not support firmware updates
|
51
|
-
ERROR_NOT_SUPPORTED = 3
|
52
|
-
OK = 255
|
53
|
-
|
54
|
-
|
55
|
-
class DriverFirmwareUpdateProgressDataType(TypedDict):
|
56
|
-
"""Represent a driver firmware update progress dict type."""
|
57
|
-
|
58
|
-
sentFragments: int
|
59
|
-
totalFragments: int
|
60
|
-
progress: float
|
61
|
-
|
62
|
-
|
63
|
-
@dataclass
|
64
|
-
class DriverFirmwareUpdateProgress:
|
65
|
-
"""Model for a driver firmware update progress data."""
|
66
|
-
|
67
|
-
data: DriverFirmwareUpdateProgressDataType = field(repr=False)
|
68
|
-
sent_fragments: int = field(init=False)
|
69
|
-
total_fragments: int = field(init=False)
|
70
|
-
progress: float = field(init=False)
|
71
|
-
|
72
|
-
def __post_init__(self) -> None:
|
73
|
-
"""Post initialize."""
|
74
|
-
self.sent_fragments = self.data["sentFragments"]
|
75
|
-
self.total_fragments = self.data["totalFragments"]
|
76
|
-
self.progress = float(self.data["progress"])
|
77
|
-
|
78
|
-
|
79
|
-
class DriverFirmwareUpdateResultDataType(TypedDict):
|
80
|
-
"""Represent a driver firmware update result dict type."""
|
81
|
-
|
82
|
-
status: int
|
83
|
-
success: bool
|
84
|
-
|
85
|
-
|
86
|
-
@dataclass
|
87
|
-
class DriverFirmwareUpdateResult:
|
88
|
-
"""Model for driver firmware update result data."""
|
89
|
-
|
90
|
-
data: DriverFirmwareUpdateResultDataType = field(repr=False)
|
91
|
-
status: DriverFirmwareUpdateStatus = field(init=False)
|
92
|
-
success: bool = field(init=False)
|
93
|
-
|
94
|
-
def __post_init__(self) -> None:
|
95
|
-
"""Post initialize."""
|
96
|
-
self.status = DriverFirmwareUpdateStatus(self.data["status"])
|
97
|
-
self.success = self.data["success"]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/exceptions.py
RENAMED
File without changes
|
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/__init__.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/association.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/duration.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/endpoint.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/log_config.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/log_message.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/statistics.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/utils.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/value.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/model/version.py
RENAMED
File without changes
|
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/helpers.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/lock.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/multicast.py
RENAMED
File without changes
|
{zwave_js_server_python-0.66.0 → zwave_js_server_python-0.67.1}/zwave_js_server/util/node.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|