Skip to content

Commit 45e693e

Browse files
committed
Support specific version by string
Support updating to a specific software version by string. This requires fetching all versions one by one, but is much more user friendly. The code still checks that all restrictions are met (min/max version, etc).
1 parent c3ef2a9 commit 45e693e

File tree

4 files changed

+36
-12
lines changed

4 files changed

+36
-12
lines changed

matter_server/client/client.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,11 @@ async def check_node_update(self, node_id: int) -> dict[str, Any]:
523523
)
524524
return cast(dict[str, Any], node_update)
525525

526-
async def update_node(self, node_id: int, software_version: int) -> None:
526+
async def update_node(
527+
self,
528+
node_id: int,
529+
software_version: int | str,
530+
) -> None:
527531
"""Start node update to a particular version."""
528532
await self.send_command(
529533
APICommand.UPDATE_NODE, node_id=node_id, software_version=software_version

matter_server/server/device_controller.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,9 @@ async def check_node_update(self, node_id: int) -> dict | None:
897897
return await self._check_node_update(node_id)
898898

899899
@api_command(APICommand.UPDATE_NODE)
900-
async def update_node(self, node_id: int, software_version: int) -> dict | None:
900+
async def update_node(
901+
self, node_id: int, software_version: int | str
902+
) -> dict | None:
901903
"""
902904
Update a node to a new software version.
903905
@@ -927,7 +929,7 @@ async def update_node(self, node_id: int, software_version: int) -> dict | None:
927929
async def _check_node_update(
928930
self,
929931
node_id: int,
930-
requested_software_version: int | None = None,
932+
requested_software_version: int | str | None = None,
931933
) -> dict | None:
932934
node_logger = LOGGER.getChild(f"node_{node_id}")
933935
node = self._nodes[node_id]

matter_server/server/ota/__init__.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,18 @@ async def check_for_update(
3838
vid: int,
3939
pid: int,
4040
current_software_version: int,
41-
requested_software_version: int | None = None,
41+
requested_software_version: int | str | None = None,
4242
) -> None | dict:
4343
"""Check for software updates."""
4444
if (vid, pid) in HARDCODED_UPDATES:
4545
update = HARDCODED_UPDATES[(vid, pid)]
4646
if (
4747
requested_software_version is None
4848
or update["softwareVersion"] == requested_software_version
49+
or update["softwareVersionString"] == requested_software_version
4950
):
5051
return update
5152

52-
return await dcl.check_for_update(vid, pid, current_software_version)
53+
return await dcl.check_for_update(
54+
vid, pid, current_software_version, requested_software_version
55+
)

matter_server/server/ota/dcl.py

+22-7
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@ async def _get_software_version(vid: int, pid: int, software_version: int) -> An
3232

3333

3434
async def _check_update_version(
35-
vid: int, pid: int, version: int, current_software_version: int
35+
vid: int,
36+
pid: int,
37+
current_software_version: int,
38+
requested_software_version: int,
39+
requested_software_version_string: str | None = None,
3640
) -> None | dict:
37-
version_res: dict = await _get_software_version(vid, pid, version)
41+
version_res: dict = await _get_software_version(
42+
vid, pid, requested_software_version
43+
)
3844
if not isinstance(version_res, dict):
3945
raise TypeError("Unexpected DCL response.")
4046

@@ -43,6 +49,14 @@ async def _check_update_version(
4349

4450
version_candidate: dict = cast(dict, version_res["modelVersion"])
4551

52+
# If we are looking for a specific version by string, check if it matches
53+
if (
54+
requested_software_version_string is not None
55+
and version_candidate["softwareVersionString"]
56+
!= requested_software_version_string
57+
):
58+
return None
59+
4660
# Check minApplicableSoftwareVersion/maxApplicableSoftwareVersion
4761
min_sw_version = version_candidate["minApplicableSoftwareVersion"]
4862
max_sw_version = version_candidate["maxApplicableSoftwareVersion"]
@@ -59,13 +73,14 @@ async def check_for_update(
5973
vid: int,
6074
pid: int,
6175
current_software_version: int,
62-
requested_software_version: int | None = None,
76+
requested_software_version: int | str | None = None,
6377
) -> None | dict:
6478
"""Check if there is a software update available on the DCL."""
6579
try:
66-
if requested_software_version is not None:
80+
# If a specific version as integer is requested, just fetch it (and hope it exists)
81+
if isinstance(requested_software_version, int):
6782
return await _check_update_version(
68-
vid, pid, requested_software_version, current_software_version
83+
vid, pid, current_software_version, requested_software_version
6984
)
7085

7186
# Get all versions and check each one of them.
@@ -78,15 +93,15 @@ async def check_for_update(
7893
if version > current_software_version
7994
]
8095

81-
# Check if there is a newer software version available
96+
# Check if there is a newer software version available, no downgrade possible
8297
if not newer_software_versions:
8398
LOGGER.info("No newer software version available.")
8499
return None
85100

86101
# Check if latest firmware is applicable, and backtrack from there
87102
for version in sorted(newer_software_versions, reverse=True):
88103
if version_candidate := await _check_update_version(
89-
vid, pid, version, current_software_version
104+
vid, pid, current_software_version, version, requested_software_version
90105
):
91106
return version_candidate
92107
LOGGER.debug("Software version %d not applicable.", version)

0 commit comments

Comments
 (0)