10 from __future__
import division, absolute_import, print_function, unicode_literals
12 from logging
import getLogger
16 logger = getLogger(__name__)
20 TIMEOUT = pyuavcan_v0.protocol.NodeStatus().OFFLINE_TIMEOUT_MS / 1000
21 TRANSFER_PRIORITY = pyuavcan_v0.TRANSFER_PRIORITY_LOWEST - 1
22 MIN_RETRY_INTERVAL = 0.5
39 self.
node_id = e.transfer.source_node_id
40 if self.
status and e.message.uptime_sec < self.
status.uptime_sec:
50 self.
node_id = e.transfer.source_node_id
51 self.
status = e.response.status
52 self.
info = e.response
65 EVENT_ID_INFO_UPDATE =
'info_update'
66 EVENT_ID_OFFLINE =
'offline'
99 callback: The specified callback will be invoked when:
101 - Node info for an existing node gets updated
103 Returns: Call remove() or try_remove() on the returned object to unregister the handler.
115 node_id: Returns True if the given node ID exists, false otherwise
122 node_id: Returns an Entry instance for the given node ID.
123 If the requested node ID does not exist, throws KeyError.
125 if (self.
_registry[node_id].monotonic_timestamp + self.
TIMEOUT) < time.monotonic():
132 """Returns a generator or an iterable containing all currently active node ID."""
136 """Returns a generator that produces a sequence of Entry objects for which the predicate returned True.
138 predicate: A callable that returns a value coercible to bool.
140 for _nid, entry
in self.
_registry.items():
145 """Reports whether there are nodes whose node info is still unknown."""
146 undiscovered = self.
find_all(
lambda e:
not e.discovered)
147 return len(list(undiscovered)) == 0
150 """Stops the instance. The registry will not be cleared."""
155 for nid, e
in list(self.
_registry.items())[:]:
156 if (e.monotonic_timestamp + self.
TIMEOUT) < time.monotonic():
161 node_id = e.transfer.source_node_id
164 entry = self.
get(node_id)
168 entry._info_requested_at = 0
173 entry._update_from_status(e)
177 should_retry_now = entry.monotonic_timestamp - entry._info_requested_at > self.
MIN_RETRY_INTERVAL
179 if not entry.discovered
and should_retry_now
and not e.node.is_anonymous:
180 entry._info_requested_at = entry.monotonic_timestamp
182 entry._register_retry()
183 e.node.request(pyuavcan_v0.protocol.GetNodeInfo.Request(), node_id,
191 entry = self.
get(e.transfer.source_node_id)
194 self.
_registry[e.transfer.source_node_id] = entry
197 entry._update_from_info(e)
199 hw_unique_id =
"".join(
format(c,
"02X")
for c
in e.response.hardware_version.unique_id)
201 "[#{0:03d}:pyuavcan_v0.protocol.GetNodeInfo] " +
202 "software_version.major={1:d} " +
203 "software_version.minor={2:d} " +
204 "software_version.vcs_commit={3:08x} " +
205 "software_version.image_crc={4:016X} " +
206 "hardware_version.major={5:d} " +
207 "hardware_version.minor={6:d} " +
208 "hardware_version.unique_id={7!s} " +
211 e.transfer.source_node_id,
212 e.response.software_version.major,
213 e.response.software_version.minor,
214 e.response.software_version.vcs_commit,
215 e.response.software_version.image_crc,
216 e.response.hardware_version.major,
217 e.response.hardware_version.minor,
219 e.response.name.decode()