diff --git a/src/calng/CalibrationManager.py b/src/calng/CalibrationManager.py index ab4eb34d8e1883a1e1987c49d706a7026d48b5c0..accc5ee5b360e4b2e50064507385d31ef32a06ef 100644 --- a/src/calng/CalibrationManager.py +++ b/src/calng/CalibrationManager.py @@ -465,14 +465,6 @@ class CalibrationManager(DeviceClientBase, Device): defaultValue=[], accessMode=AccessMode.READONLY) - @Slot( - displayedName='Discover managed devices', - description='', - allowedStates=[State.ACTIVE]) - async def discoverManagedDevices(self): - self.state = State.CHANGING - background(self._discover_managed_devices()) - @Slot( displayedName='Apply managed values', description='Set all managed keys to the values currently active on ' @@ -581,7 +573,6 @@ class CalibrationManager(DeviceClientBase, Device): if info['type'] == 'device': self._check_new_device(instance_id, info['serverId'], info['classId']) - self._update_managed_devices() @slot def slotInstanceGone(self, instance_id, info): @@ -590,12 +581,7 @@ class CalibrationManager(DeviceClientBase, Device): super().slotInstanceGone(instance_id, info) if info['type'] == 'device': - self._daq_device_ids.discard(instance_id) - self._domain_device_ids.discard(instance_id) - self._managed_device_ids.discard(instance_id) - self._correction_device_ids.discard(instance_id) - self._assembler_device_ids.discard(instance_id) - self._update_managed_devices() + self._remove_managed_device(instance_id) async def _async_init(self): # Set-up Tornado. @@ -651,6 +637,16 @@ class CalibrationManager(DeviceClientBase, Device): # This device is also an assembler self._assembler_device_ids.add(device_id) + self._update_managed_devices() + + def _remove_managed_device(self, device_id): + self._daq_device_ids.discard(device_id) + self._domain_device_ids.discard(device_id) + self._managed_device_ids.discard(device_id) + self._correction_device_ids.discard(device_id) + self._assembler_device_ids.discard(device_id) + self._update_managed_devices() + async def _check_topology(self): for i in range(10): try: @@ -673,34 +669,30 @@ class CalibrationManager(DeviceClientBase, Device): self._check_new_device(device_id, devices[device_id, 'serverId'], devices[device_id, 'classId']) - self._update_managed_devices(True) - - async def _discover_managed_devices(self): - self._daq_device_ids.clear() - self._domain_device_ids.clear() - self._managed_device_ids.clear() - self._correction_device_ids.clear() - self._assembler_device_ids.clear() + async def _ping_managed_devices(self): + device_ids = sorted(self._managed_device_ids) - await self._check_topology() + device_infos = await gather( + *[wait_for(getInstanceInfo(device_id), timeout=5) + for device_id in device_ids], + return_exceptions=True) - self.state = State.ACTIVE + for device_id, device_info in zip(device_ids, device_infos): + if isinstance(device_info, AsyncTimeoutError): + self._remove_managed_device(device_id) async def _delayed_managed_devices_update(self): await sleep(1.0) # Throttle updates to at most once a second. self.managedDevices = sorted(self._managed_device_ids) self._managed_devices_updater = None # Clear task again. - def _update_managed_devices(self, forced=False): + def _update_managed_devices(self): if self._managed_devices_updater is not None: # Update already in progress, ignore. return - if forced or len(self._managed_device_ids) != len(self.managedDevices): - # Trigger an update either if forced or the number of - # devices changed. - self._managed_devices_updater = background( - self._delayed_managed_devices_update()) + self._managed_devices_updater = background( + self._delayed_managed_devices_update()) async def _get_shared_keys(self, device_ids, keys): """Find the most common property values on devices.""" @@ -1277,6 +1269,9 @@ class CalibrationManager(DeviceClientBase, Device): 'listed in the device servers ' 'configuration') + # Ping all known managed devices to make sure they're alive. + await self._ping_managed_devices() + # Instantiate modules. modules_by_group = defaultdict(list) correct_device_id_by_module = {}