Skip to content

Trying to implement restore settings on Exception #34

@kjhazelwood

Description

@kjhazelwood

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is neededquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions