Source code for pydgilib_extra.dgilib_interface_power

"""This module wraps the calls to the Power Interface."""

from time import sleep

from pydgilib.dgilib_config import (
    CALIBRATING, DONE, IDLE, OVERFLOWED, RUNNING, XAM, CHANNEL_A,
    POWER_CURRENT)
from pydgilib_extra.dgilib_extra_config import (INTERFACE_POWER, POWER)
from pydgilib_extra.dgilib_extra_exceptions import (
    PowerReadError, PowerStatusError, InterfaceNotAvailableError)

from pydgilib_extra.dgilib_interface import DGILibInterface
from pydgilib_extra.dgilib_data import InterfaceData


[docs]class DGILibInterfacePower(DGILibInterface): """Wraps the calls to the Power interface.""" interface_id = INTERFACE_POWER name = "power" csv_header = ["timestamp", "current"] polling_type = POWER def __init__(self, *args, **kwargs): """Instantiate DGILibInterfacePower object.""" # Set default values for attributes self.power_buffers = [] # Instantiate base class DGILibInterface.__init__(self, *args, **kwargs) # Parse arguments if self.verbose: print("power_buffers: ", self.power_buffers)
[docs] def get_config(self): """get_config Get the power config options. Returns ------- list(dict) Power buffers configuration list of dictionaries like ``[{"channel": CHANNEL_A, "power_type": POWER_CURRENT}]``. """ # Return the configuration return self.power_buffers
[docs] def set_config(self, *args, **kwargs): """set_config Set the power config options. Register buffers inside the library for the buffers specified in power_buffers and removes ones that are not present. Parameters ---------- power_buffers: list(dict) Power buffers configuration list of dictionaries like ``[{"channel": CHANNEL_A, "power_type": POWER_CURRENT}]``. """ # Parse arguments power_buffers = kwargs.get( "power_buffers", [{"channel": CHANNEL_A, "power_type": POWER_CURRENT}],) # Initialize the power handle if it is None if self.dgilib_extra.power_hndl is None: self.dgilib_extra.power_hndl = \ self.dgilib_extra.auxiliary_power_initialize() # Enable the configurations that are in the new config and not in # self.power_buffers # BUG: This probably needs multiple power handles for power_buffer in power_buffers: if power_buffer not in self.power_buffers: self.dgilib_extra.auxiliary_power_register_buffer_pointers( channel=power_buffer["channel"], power_type=power_buffer["power_type"]) self.power_buffers.append(power_buffer) # Disable the configurations that are not in the new config and remove # them from self.power_buffers for power_buffer in self.power_buffers: if power_buffer not in power_buffers: self.dgilib_extra.auxiliary_power_unregister_buffer_pointers( channel=power_buffer["channel"], power_type=power_buffer["power_type"],) self.power_buffers.remove(power_buffer) # Uninitialize the power handle if there are no power buffers left if not self.power_buffers: self.dgilib_extra.auxiliary_power_uninitialize()
[docs] def enable(self): """enable Enable the interface. """ if self.interface_id not in self.dgilib_extra.available_interfaces: raise InterfaceNotAvailableError( f"Interface {self.interface_id} not available. Available " + f"interfaces: {self.dgilib_extra.available_interfaces}") # Check if calibration is valid and trigger calibration if it is not self.calibrate() if self.interface_id not in self.dgilib_extra.enabled_interfaces: self.dgilib_extra.enabled_interfaces.append(self.interface_id)
[docs] def disable(self): """disable Disable the interface. """ # NOTE: This currently also removes the configuration!!! # TODO # BUG if self.interface_id in self.dgilib_extra.enabled_interfaces: self.set_config() # BUG self.dgilib_extra.enabled_interfaces.remove(self.interface_id)
[docs] def read(self, buffer_num=0): """read Read data from the interface. Returns ------- InterfaceData Interface data """ # Return the data return self.read_buffer(self.power_buffers[buffer_num])
[docs] def read_buffer(self, power_buffer): """read_buffer Read power data of the specified buffer. Returns ------- tuple(list(float), list(float)) Tuple of list of power samples in Ampere and list of timestamps in seconds. """ # TODO: Copies parsed power data into the specified buffer. Remember to # lock the buffers first. If the count parameter is the same as # max_count there is probably more data to be read. Do another read to # get the remaining data. # Check if power_buffer is in self.power_buffers if power_buffer not in self.power_buffers: raise PowerReadError( f"Power Buffer {power_buffer} does not exist in " f"self.power_buffers: {self.power_buffers}.") # Check if auxiliary_power_get_status() is in # - IDLE = 0x00, # - RUNNING = 0x01, # - DONE = 0x02 or # - OVERFLOWED = 0x11 # and raise PowerStatusError if it is. power_status = self.dgilib_extra.auxiliary_power_get_status() if self.verbose: print(f"power_status: {power_status}") # if power_status <= DONE or power_status == OVERFLOWED: if power_status not in (IDLE, RUNNING, DONE, OVERFLOWED): raise PowerStatusError(f"Power Status {power_status}.") if power_status == OVERFLOWED: print( f"BUFFER OVERFLOW, call this function more frequently or " f"increase the buffer size.") # Create variables to the store data in interface_data = InterfaceData() # TODO: Check implementation in case of buffer overflow. # Should auxiliary_power_lock_data_for_reading() be inside the loop # or before? # Get the data from the buffer in the library while True: self.dgilib_extra.auxiliary_power_lock_data_for_reading() interface_data += self.dgilib_extra.auxiliary_power_copy_data( power_buffer["channel"], power_buffer["power_type"]) # BUG: This probably clears all channels! (channels might not be # working on XAM anyway) self.dgilib_extra.auxiliary_power_free_data() # Repeat the loop until there is no buffer overflow (which should # always be avoided.) if self.dgilib_extra.auxiliary_power_get_status() != OVERFLOWED: break if self.verbose >= 2: print(f"Collected {len(interface_data)} power samples") if self.verbose >= 4: print(interface_data) return interface_data
[docs] def calibrate(self, force=False): """calibrate Calibrate the Auxiliary Power interface of the device. Check if calibration is valid and trigger calibration if it is not. Parameters ---------- force : bool Force calibration, even if it is valid (default: `False`) Raises ------ PowerReadError `No description given.` PowerStatusError `No description given.` """ # TODO: Give descriptions to the exceptions under 'Raises' above. self.circuit_type = self.dgilib_extra.auxiliary_power_get_circuit_type() if force or not self.dgilib_extra.auxiliary_power_calibration_is_valid(): self.auxiliary_power_calibration()
[docs] def auxiliary_power_calibration(self, circuit_type=XAM): """auxiliary_power_calibration Calibrate the Auxiliary Power interface of the device. Parameters ---------- circuit_type : int Type of calibration to trigger(defaults to XAM) """ self.dgilib_extra.auxiliary_power_trigger_calibration(circuit_type) while self.dgilib_extra.auxiliary_power_get_status() == CALIBRATING: sleep(0.1)