@@ -1067,8 +1067,42 @@ async def _setup_node(self, node_id: int) -> None:
1067
1067
return
1068
1068
self ._nodes_in_setup .add (node_id )
1069
1069
node_logger = LOGGER .getChild (f"node_{ node_id } " )
1070
- try :
1071
- async with self ._node_setup_throttle :
1070
+ node_data = self ._nodes [node_id ]
1071
+ log_timers : dict [int , asyncio .TimerHandle ] = {}
1072
+
1073
+ def log_node_long_setup (time_start : float ) -> None :
1074
+ """Temporary measure to track a locked-up SDK issue in some (special) circumstances."""
1075
+ time_mins = int ((time .time () - time_start ) / 60 )
1076
+ node_model = node_data .attributes .get (
1077
+ "0/40/14" , node_data .attributes .get ("0/40/3" , "" )
1078
+ )
1079
+ node_name = f"Node { node_id } ({ node_model } )"
1080
+
1081
+ node_logger .error (
1082
+ f"\n \n ATTENTION: { node_name } did not complete setup in { time_mins } minutes.\n " # noqa: G004
1083
+ "This is an indication of a (connectivity) issue with this device. \n "
1084
+ "Try powercycling this device and/or relocate it closer to a Border Router or \n "
1085
+ "WiFi Access Point. If this issue persists, please create an issue report on \n "
1086
+ "the Matter channel of the Home Assistant Discord server or on Github:\n "
1087
+ "https://github.com/home-assistant/core/issues/new?assignees=&labels="
1088
+ "integration%3A%20matter&projects=&template=bug_report.yml\n " ,
1089
+ )
1090
+ # reschedule itself
1091
+ if TYPE_CHECKING :
1092
+ assert self .server .loop
1093
+ log_timers [node_id ] = self .server .loop .call_later (
1094
+ 15 * 60 , log_node_long_setup , time_start
1095
+ )
1096
+
1097
+ async with self ._node_setup_throttle :
1098
+ time_start = time .time ()
1099
+ # we want to track nodes that take too long so we log it when we detect that
1100
+ if TYPE_CHECKING :
1101
+ assert self .server .loop
1102
+ log_timers [node_id ] = self .server .loop .call_later (
1103
+ 15 * 60 , log_node_long_setup , time_start
1104
+ )
1105
+ try :
1072
1106
node_logger .info ("Setting-up node..." )
1073
1107
1074
1108
# try to resolve the node using the sdk first before do anything else
@@ -1086,7 +1120,7 @@ async def _setup_node(self, node_id: int) -> None:
1086
1120
return
1087
1121
1088
1122
# (re)interview node (only) if needed
1089
- node_data = self . _nodes [ node_id ]
1123
+
1090
1124
if (
1091
1125
# re-interview if we dont have any node attributes (empty node)
1092
1126
not node_data .attributes
@@ -1120,8 +1154,9 @@ async def _setup_node(self, node_id: int) -> None:
1120
1154
)
1121
1155
# NOTE: the node will be picked up by mdns discovery automatically
1122
1156
# when it becomes available again.
1123
- finally :
1124
- self ._nodes_in_setup .discard (node_id )
1157
+ finally :
1158
+ log_timers [node_id ].cancel ()
1159
+ self ._nodes_in_setup .discard (node_id )
1125
1160
1126
1161
async def _resolve_node (
1127
1162
self , node_id : int , retries : int = 2 , attempt : int = 1
0 commit comments