Skip to content

Commit aafbc61

Browse files
committed
Support local updates with the same version string
For development it is sometimes useful to just reuse the same version string but increment the underlying build number (which is the actual version devices typically care about). This change supports multiple local updates with the same version string, and updating to an explicit version by version integer.
1 parent 7d89b02 commit aafbc61

File tree

2 files changed

+22
-13
lines changed

2 files changed

+22
-13
lines changed

matter_server/server/device_controller.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1099,10 +1099,12 @@ async def _check_node_update(
10991099
raise UpdateCheckError("Update found, but no OTA URL provided.")
11001100

11011101
node_logger.info(
1102-
"New software update found: %s on %s (current %s).",
1102+
"Software update found: %s (%s) from %s, current %s (%s)).",
11031103
update["softwareVersionString"],
1104+
update["softwareVersion"],
11041105
update_source,
11051106
software_version_string,
1107+
software_version,
11061108
)
11071109
return update_source, update
11081110

matter_server/server/ota/__init__.py

+19-12
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
from matter_server.common.models import UpdateSource
99
from matter_server.server.ota import dcl
1010

11-
_local_updates: dict[tuple[int, int], dict] = {}
11+
MatterProduct = tuple[int, int]
12+
13+
_local_updates: dict[MatterProduct, dict[int | str, dict]] = {}
1214

1315

1416
async def load_local_updates(ota_provider_dir: Path) -> None:
@@ -21,9 +23,12 @@ def _load_update(ota_provider_dir: Path) -> None:
2123
with open(update_file) as f:
2224
update = json.load(f)
2325
model_version = update["modelVersion"]
24-
_local_updates[(model_version["vid"], model_version["pid"])] = (
25-
model_version
26-
)
26+
model_key = (model_version["vid"], model_version["pid"])
27+
update_dict = _local_updates.get(model_key, {})
28+
# Store by string or integer, this allows update by both
29+
update_dict[model_version["softwareVersion"]] = model_version
30+
update_dict[model_version["softwareVersionString"]] = model_version
31+
_local_updates[model_key] = update_dict
2732

2833
await asyncio.get_running_loop().run_in_executor(
2934
None, _load_update, ota_provider_dir
@@ -38,14 +43,16 @@ async def check_for_update(
3843
requested_software_version: int | str | None = None,
3944
) -> tuple[UpdateSource, dict] | tuple[None, None]:
4045
"""Check for software updates."""
41-
if (vid, pid) in _local_updates:
42-
local_update = _local_updates[(vid, pid)]
43-
if (
44-
requested_software_version is None
45-
or local_update["softwareVersion"] == requested_software_version
46-
or local_update["softwareVersionString"] == requested_software_version
47-
):
48-
return UpdateSource.LOCAL, local_update
46+
if local_updates := _local_updates.get((vid, pid)):
47+
logger.info("Local updates found for this device")
48+
if requested_software_version is None:
49+
# Use integer version to reliably determine absolute latest version
50+
versions = filter(
51+
lambda version: isinstance(version, int), local_updates.keys()
52+
)
53+
return UpdateSource.LOCAL, local_updates[max(versions)]
54+
if requested_software_version in local_updates:
55+
return UpdateSource.LOCAL, local_updates[requested_software_version]
4956

5057
if dcl_update := await dcl.check_for_update(
5158
logger, vid, pid, current_software_version, requested_software_version

0 commit comments

Comments
 (0)