Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent duplicate interviews #539

Merged
merged 1 commit into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions matter_server/common/helpers/util.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Utils for Matter server (and client)."""

from __future__ import annotations

import base64
Expand Down Expand Up @@ -257,6 +258,7 @@ def dataclass_from_dict(cls: type[_T], dict_obj: dict, strict: bool = False) ->
dict_obj.get(field.name),
type_hints[field.name],
field.default,
allow_none=not strict,
)
for field in dc_fields
if field.init
Expand Down
23 changes: 17 additions & 6 deletions matter_server/server/device_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from matter_server.server.helpers.attributes import parse_attributes_from_read_result
from matter_server.server.helpers.utils import ping_ip

from ..common.const import SCHEMA_VERSION
from ..common.errors import (
NodeCommissionFailed,
NodeInterviewFailed,
Expand Down Expand Up @@ -156,11 +155,23 @@ async def start(self) -> None:
# as this can no longer happen.
orphaned_nodes.add(node_id_str)
continue
if node_dict.get("interview_version") != SCHEMA_VERSION:
# Invalidate node attributes data if schema mismatch,
# the node will automatically be scheduled for re-interview.
node_dict["attributes"] = {}
node = dataclass_from_dict(MatterNodeData, node_dict)
try:
node = dataclass_from_dict(MatterNodeData, node_dict, strict=True)
except (KeyError, ValueError):
# constructing MatterNodeData from the cached dict is not possible,
# revert to a fallback object and the node will be re-interviewed
node = MatterNodeData(
node_id=node_id,
date_commissioned=node_dict.get(
"date_commissioned",
datetime(1970, 1, 1),
),
last_interview=node_dict.get(
"last_interview",
datetime(1970, 1, 1),
),
interview_version=0,
)
# always mark node as unavailable at startup until subscriptions are ready
node.available = False
self._nodes[node_id] = node
Expand Down