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