Source code for nqontrol.servodevice

"""Main part of ServoDevice."""
# pylint: disable=import-outside-toplevel,too-few-public-methods,cyclic-import,too-many-arguments,too-many-branches
import json
import logging as log
import os
import sys
from pathlib import Path

from ADwin import ADwin, ADwinError
from openqlab.analysis.servo_design import ServoDesign

from nqontrol.general import MockADwin, errors, settings


[docs]class ServoDevice: """ A ServoDevice is the whole device, containing 8 (default can be changed) single servos. With this object you can control one ADwin device and manage all servos of this device. Parameters ---------- deviceNumber: :obj:`int` Number of the ADwin device on this system. The number can be skipped when loading a ServoDevice from file. You have to set it using the tool `adconfig`. See [installation](install) for configuration details. readFromFile: :obj:`str` Select a filename if you want to open a whole ServoDevice with all servos from a saved json file. keep_state: :obj:`bool` Do not change the state of a running ADwin device. """ from ._general import ( _DEFAULT_PROCESS, _DONT_SERIALIZE, _JSONPICKLE, __repr__, _bootAdwin, _greaterControlRegister, _lockControlRegister, reboot, servoDesign, timestamp, workload, ) from ._loadsave import ( _applySettingsDict, _backupSettingsFile, _getSettingsDict, _sendAllToAdwin, _writeSettingsToFile, loadDeviceFromJson, loadServoFromJson, saveDeviceToJson, ) from ._monitors import disableMonitor, enableMonitor, monitors from ._servo_handling import ( _list_servos_str, addServo, list_servos, removeServo, servo, servo_iterator, ) # The init method has to be here, otherwise mypy dies. def __init__( self, deviceNumber=0, readFromFile=None, reboot=False, keep_state=False, adw=None, ): """Create a new ServoDevice object.""" if deviceNumber is None and readFromFile is None: raise errors.UserInputError( "You have to set a deviceNumber if you do not load a ServoDevice from a file!" ) log.info(f"deviceNumber: {deviceNumber}") raiseExceptions = 1 self._servoDesign: ServoDesign = ServoDesign() # The dummy servo design object self._servos = [None] * settings.NUMBER_OF_SERVOS self._monitors = [None] * settings.NUMBER_OF_MONITORS if ( readFromFile is not None and os.path.isfile(readFromFile) and deviceNumber is None ): with open(readFromFile, "r") as file: data = json.load(file) if not data.get(self.__class__.__name__): raise Exception("Wrong file format.") self.deviceNumber = data[self.__class__.__name__]["deviceNumber"] else: self.deviceNumber = deviceNumber if adw is None: if deviceNumber == 0: log.warning("Running with mock device!") self.adw = MockADwin(deviceNumber) else: self.adw = ADwin(deviceNumber, raiseExceptions) else: self.adw = adw try: self._bootAdwin(self._DEFAULT_PROCESS, reboot=reboot) except ADwinError as e: if e.errorNumber in (2001, 11): raise errors.DeviceError("No device connected!") log.error(e) self.adw = MockADwin(deviceNumber) self._bootAdwin(self._DEFAULT_PROCESS) if readFromFile is not None and os.path.isfile(readFromFile): log.warning(f"Loaded from: {readFromFile}") self.loadDeviceFromJson(readFromFile, keep_state=keep_state) # Adding servos for i in range(1, settings.NUMBER_OF_SERVOS + 1): if self._servos[i - 1] is None: self.addServo(channel=i, keep_state=keep_state)