Change subscription logic for Matter devices (#95387)

This commit is contained in:
Marcel van der Veldt 2023-06-27 21:12:29 +02:00 committed by GitHub
parent a885ceefa2
commit ed2daf1f65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 110 additions and 30 deletions

View file

@ -52,13 +52,62 @@ class MatterAdapter:
async def setup_nodes(self) -> None:
"""Set up all existing nodes and subscribe to new nodes."""
for node in await self.matter_client.get_nodes():
for node in self.matter_client.get_nodes():
self._setup_node(node)
def node_added_callback(event: EventType, node: MatterNode) -> None:
"""Handle node added event."""
self._setup_node(node)
def endpoint_added_callback(event: EventType, data: dict[str, int]) -> None:
"""Handle endpoint added event."""
node = self.matter_client.get_node(data["node_id"])
self._setup_endpoint(node.endpoints[data["endpoint_id"]])
def endpoint_removed_callback(event: EventType, data: dict[str, int]) -> None:
"""Handle endpoint removed event."""
server_info = cast(ServerInfoMessage, self.matter_client.server_info)
try:
node = self.matter_client.get_node(data["node_id"])
except KeyError:
return # race condition
device_registry = dr.async_get(self.hass)
endpoint = node.endpoints.get(data["endpoint_id"])
if not endpoint:
return # race condition
node_device_id = get_device_id(
server_info,
node.endpoints[data["endpoint_id"]],
)
identifier = (DOMAIN, f"{ID_TYPE_DEVICE_ID}_{node_device_id}")
if device := device_registry.async_get_device({identifier}):
device_registry.async_remove_device(device.id)
def node_removed_callback(event: EventType, node_id: int) -> None:
"""Handle node removed event."""
try:
node = self.matter_client.get_node(node_id)
except KeyError:
return # race condition
for endpoint_id in node.endpoints:
endpoint_removed_callback(
EventType.ENDPOINT_REMOVED,
{"node_id": node_id, "endpoint_id": endpoint_id},
)
self.config_entry.async_on_unload(
self.matter_client.subscribe(
endpoint_added_callback, EventType.ENDPOINT_ADDED
)
)
self.config_entry.async_on_unload(
self.matter_client.subscribe(
endpoint_removed_callback, EventType.ENDPOINT_REMOVED
)
)
self.config_entry.async_on_unload(
self.matter_client.subscribe(node_removed_callback, EventType.NODE_REMOVED)
)
self.config_entry.async_on_unload(
self.matter_client.subscribe(node_added_callback, EventType.NODE_ADDED)
)

View file

@ -75,9 +75,11 @@ class MatterEntity(Entity):
await super().async_added_to_hass()
# Subscribe to attribute updates.
sub_paths: list[str] = []
for attr_cls in self._entity_info.attributes_to_watch:
attr_path = self.get_matter_attribute_path(attr_cls)
self._attributes_map[attr_cls] = attr_path
sub_paths.append(attr_path)
self._unsubscribes.append(
self.matter_client.subscribe(
callback=self._on_matter_event,
@ -86,6 +88,9 @@ class MatterEntity(Entity):
attr_path_filter=attr_path,
)
)
await self.matter_client.subscribe_attribute(
self._endpoint.node.node_id, sub_paths
)
# subscribe to node (availability changes)
self._unsubscribes.append(
self.matter_client.subscribe(

View file

@ -95,7 +95,7 @@ async def get_node_from_device_entry(
node = next(
(
node
for node in await matter_client.get_nodes()
for node in matter_client.get_nodes()
for endpoint in node.endpoints.values()
if get_device_id(server_info, endpoint) == device_id
),

View file

@ -6,5 +6,5 @@
"dependencies": ["websocket_api"],
"documentation": "https://www.home-assistant.io/integrations/matter",
"iot_class": "local_push",
"requirements": ["python-matter-server==3.5.1"]
"requirements": ["python-matter-server==3.6.0"]
}

View file

@ -2103,7 +2103,7 @@ python-kasa==0.5.1
# python-lirc==1.2.3
# homeassistant.components.matter
python-matter-server==3.5.1
python-matter-server==3.6.0
# homeassistant.components.xiaomi_miio
python-miio==0.5.12

View file

@ -1541,7 +1541,7 @@ python-juicenet==1.1.0
python-kasa==0.5.1
# homeassistant.components.matter
python-matter-server==3.5.1
python-matter-server==3.6.0
# homeassistant.components.xiaomi_miio
python-miio==0.5.12

View file

@ -669,7 +669,9 @@
"1/1030/65529": [],
"1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"is_bridge": false,
"attribute_subscriptions": []
}
],
"events": []

View file

@ -482,7 +482,9 @@
"1/1030/65529": [],
"1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"is_bridge": false,
"attribute_subscriptions": []
}
],
"events": []

View file

@ -313,5 +313,6 @@
"1/4/65529": [0, 5, 2, 4, 3, 1],
"1/4/65531": [0, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -85,5 +85,6 @@
"1/69/65529": [],
"1/69/65531": [0, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -467,5 +467,7 @@
"1/1030/65529": [],
"1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"is_bridge": false,
"attribute_subscriptions": []
}

View file

@ -407,5 +407,6 @@
"1/1030/65529": [],
"1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -505,5 +505,6 @@
0, 1, 2, 3, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 33, 35, 36,
37, 38, 41, 43, 48, 49, 51, 65528, 65529, 65530, 65531, 65532, 65533
]
}
},
"attribute_subscriptions": []
}

View file

@ -313,5 +313,6 @@
"1/4/65529": [0, 5, 2, 4, 3, 1],
"1/4/65531": [0, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -78,5 +78,6 @@
"1/1028/65529": [],
"1/1028/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -77,5 +77,6 @@
"1/1029/65529": [],
"1/1029/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -85,5 +85,6 @@
"1/1024/65529": [],
"1/1024/65531": [0, 1, 2, 3, 4, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -93,5 +93,6 @@
"1/1030/65529": [],
"1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -136,5 +136,6 @@
"1/29/65529": [],
"1/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -407,5 +407,6 @@
"1/1030/65529": [],
"1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -407,5 +407,6 @@
"1/1030/65529": [],
"1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -407,5 +407,6 @@
"1/1030/65529": [],
"1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -77,5 +77,6 @@
"1/1027/65529": [],
"1/1027/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -83,5 +83,6 @@
"1/1026/65529": [],
"1/1026/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533]
},
"available": true
"available": true,
"attribute_subscriptions": []
}

View file

@ -264,5 +264,6 @@
65528, 65529, 65531, 65532, 65533, 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 23, 26, 6
]
}
},
"attribute_subscriptions": []
}

View file

@ -245,5 +245,6 @@
"1/258/65528": [],
"1/258/65529": [0, 1, 2, 5],
"1/258/65531": [65528, 65529, 65531, 65532, 65533, 0, 1, 5, 7, 10, 13, 23]
}
},
"attribute_subscriptions": []
}

View file

@ -349,5 +349,6 @@
0, 1, 3, 5, 7, 8, 10, 11, 13, 14, 16, 17, 23, 65528, 65529, 65531, 65532,
65533
]
}
},
"attribute_subscriptions": []
}

View file

@ -250,5 +250,6 @@
"1/258/65531": [
65528, 65529, 65531, 65532, 65533, 0, 7, 9, 10, 12, 13, 15, 23, 6
]
}
},
"attribute_subscriptions": []
}

View file

@ -245,5 +245,6 @@
"1/258/65528": [],
"1/258/65529": [0, 1, 2, 8],
"1/258/65531": [65528, 65529, 65531, 65532, 65533, 0, 7, 10, 13, 23, 6]
}
},
"attribute_subscriptions": []
}

View file

@ -136,7 +136,7 @@ async def test_node_added_subscription(
integration: MagicMock,
) -> None:
"""Test subscription to new devices work."""
assert matter_client.subscribe.call_count == 1
assert matter_client.subscribe.call_count == 4
assert matter_client.subscribe.call_args[0][1] == EventType.NODE_ADDED
node_added_callback = matter_client.subscribe.call_args[0][0]

View file

@ -168,7 +168,7 @@ async def test_listen_failure_config_entry_not_loaded(
matter_client.connect.side_effect = MatterError("Boom")
raise error
async def get_nodes() -> list[MagicMock]:
def get_nodes() -> list[MagicMock]:
"""Mock the client get_nodes method."""
listen_block.set()
return []