-
Notifications
You must be signed in to change notification settings - Fork 2
Description
I'm writing a script that collects readings, makes settings and upon exiting the script or exception it attempts to restore the intitial setting. I feel like the code below should work, but when the outermost finally block executes and tries to restore, it says the the current DPMContext no longer has an entry for the specified tags [17 -37]. I'm guessing this is because the DPMContext is now dead because an exception was raised in the async dpm reply loop. I've been able to create the desired functionallity by having the finally block create a new DPMContext and then perform the settings but it is unreliable as a good portion of the time the attempt to create another DPMContext so soon after the first one died I get either a [1 -34] or [1-6] timeout or busy error.
Any thoughts how to implement restore on exception reliably?
async def run(connection):
async with acsys.dpm.DPMContext(connection, dpm_node=None) as dpm:
try:
await dpm.enable_settings(role="testing")
for i, device in enumerate(self.devices):
await dpm.add_entry(i, "%s.SETTING@%s" % (device["name"], self.iteration_event))
await dpm.start()
iteration = 0
async for reply in dpm:
if isinstance(reply, ItemData):
logger.debug("%s %d %s: %.4f" % (reply.stamp, reply.tag, reply.meta["name"], reply.data))
#Calculate new bounded random setting
current_device_setting = reply.data
new_device_setting = random.random()*(self.devices[reply.tag]["max"]-self.devices[reply.tag]["min"]) + self.devices[reply.tag]["min"]
#Fill array of device initial settings for restore, once filled it stays filled
if np.isnan(self.devices_settings[reply.tag]["initial"]):
self.devices_settings[reply.tag]["initial"] = current_device_setting
#Fill array of device current settings for logging current readings, cleared after each bulk setting
if np.isnan(self.devices_settings[reply.tag]["current"]):
self.devices_settings[reply.tag]["current"] = current_device_setting
#Fill array of device new settings for bulk setting of all devices at once, cleared after each bulk setting
if np.isnan(self.devices_settings[reply.tag]["new"]):
self.devices_settings[reply.tag]["new"] = new_device_setting
#Send new setting
if not np.isnan(np.asarray([device_settings["new"] for device_settings in self.devices_settings])).any():
if self.iteration_count != None and iteration >= self.iteration_count:
raise Exception("Desired iteration count met")
settings = []
for i, device_settings in enumerate(self.devices_settings):
settings.append((i, device_settings["new"]))
await dpm.apply_settings(settings)
logger.info(self.devices_settings)
for i, device_settings in enumerate(self.devices_settings):
device_settings["current"] = np.nan
device_settings["new"] = np.nan
iteration += 1
elif isinstance(reply, ItemStatus):
if reply.status.isFatal:
logger.crtical(reply)
raise Exception("Fatal status returned from ACNET")
elif reply.status.isWarning:
logger.warning(reply)
except Exception as e:
if not isinstance(e, KeyboardInterrupt):
logger.critical(traceback.print_exc())
finally:
try:
if True: #self.restore_devices_on_exit:
logger.info("Restoring initial device settings...")
settings = []
for i, device_settings in enumerate(self.devices_settings):
settings.append((i, device_settings["initial"]))
await dpm.apply_settings(settings)
logger.info("Initial device settings restored.")
except Exception as e:
logger.critical("Failed to restore all settings!")
logger.critical(traceback.print_exc())
finally:
logger.info("Device de-tuner stopped.")
acsys.run_client(run)EDIT: Add "Python" to code block for syntax highlighting - @beauremus