Source code for ingenialink.ipb.dictionary

import collections

from .._ingenialink import ffi, lib
from ingenialink.utils._utils import cstr, pstr, raise_null, raise_err

from ingenialink.ipb.register import LabelsDictionary, ipb_register_from_cffi
from ..dictionary import Dictionary, Categories
from ..constants import SINGLE_AXIS_MINIMUM_SUBNODES

import xml.etree.ElementTree as ET


[docs]class IPBSubCategories: """Sub-categories. Args: dict_ (CData): Ingenia dictionary instance. cat_id (str): Category ID. """ def __init__(self, dict_, cat_id): self._dict = dict_ self._cat_id = cat_id self._load_scat_ids() def _load_scat_ids(self): """Load sub-category IDs from dictionary.""" scat_ids = lib.il_dict_scat_ids_get(self._dict, cstr(self._cat_id)) self._scat_ids = [] i = 0 scat_id = scat_ids[0] while scat_id != ffi.NULL: self._scat_ids.append(pstr(scat_id)) i += 1 scat_id = scat_ids[i] lib.il_dict_scat_ids_destroy(scat_ids)
[docs] def labels(self, scat_id): """Obtain labels for a certain sub-category identifiers. Returns: dict: Labels dictionary. """ labels_p = ffi.new('il_dict_labels_t **') r = lib.il_dict_scat_get(self._dict, cstr(self._cat_id), cstr(scat_id), labels_p) raise_err(r) return LabelsDictionary._from_labels(labels_p[0])
@property def subcategory_ids(self): """Obtain all sub-category identifiers. Returns: list: Sub-category identifiers. """ return self._scat_ids
[docs]class IPBErrors: """Errors for the IPB dictionary. Args: dict_ (str): Path to the Ingenia dictionary. """ def __init__(self, dict_): self._dict = dict_ self._errors = {} # { cat_id : label } self.load_errors()
[docs] def load_errors(self): """Load errors from dictionary.""" with open(self._dict, 'r', encoding='utf-8') as xml_file: tree = ET.parse(xml_file) root = tree.getroot() for element in root.findall('./Body/Errors/Error'): label = element.find('./Labels/Label') self._errors[int(element.attrib['id'], 16)] = [ element.attrib['id'], element.attrib['affected_module'], element.attrib['error_type'].capitalize(), label.text ]
[docs]class IPBCategories(Categories): """IPB Categories for the dictionary. Args: ipb_dictionary (IPBDictionary): Ingenia dictionary instance. """ def __init__(self, ipb_dictionary): super(IPBCategories, self).__init__(ipb_dictionary) self.__ipb_dictionary = ipb_dictionary self._load_cat_ids() def _load_cat_ids(self): """Load category IDs from dictionary.""" cat_ids = lib.il_dict_cat_ids_get(self.__ipb_dictionary._cffi_dictionary) self._cat_ids = [] i = 0 cat_id = cat_ids[0] while cat_id != ffi.NULL: self._cat_ids.append(pstr(cat_id)) i += 1 cat_id = cat_ids[i] lib.il_dict_cat_ids_destroy(cat_ids)
[docs] def labels(self, category_id): """Obtain labels for a certain category ID. Returns: dict: Labels dictionary. """ labels_p = ffi.new('il_dict_labels_t **') r = lib.il_dict_cat_get(self.__ipb_dictionary._cffi_dictionary, cstr(category_id), labels_p) raise_err(r) return LabelsDictionary._from_labels(labels_p[0])
[docs] def subcategories(self, cat_id): """Obtain all sub-categories. Returns: IPBSubCategories: Sub-categories. """ return IPBSubCategories(self.__ipb_dictionary._cffi_dictionary, cat_id)
@property def category_ids(self): """Obtain all Category Identifiers. Returns: list: Category IDs. """ return self._cat_ids
[docs]class IPBRegistersDictionary(collections.Mapping): """Registers dictionary. Args: dict_ (CData): Ingenia dictionary instance. """ def __init__(self, dict_, subnode): self._dict = dict_ self._subnode = subnode self._load_reg_ids() def _load_reg_ids(self): """Load register IDs from dictionary.""" self._ids = [] ids = lib.il_dict_reg_ids_get(self._dict, self._subnode) i = 0 _id = ids[0] while _id != ffi.NULL: self._ids.append(pstr(_id)) i += 1 _id = ids[i] lib.il_dict_reg_ids_destroy(ids) def __getitem__(self, _id): reg_p = ffi.new('il_reg_t **') r = lib.il_dict_reg_get(self._dict, cstr(_id), reg_p, self._subnode) if r < 0: raise KeyError(_id) return ipb_register_from_cffi(reg_p[0]) def __len__(self): return len(self._ids) def __iter__(self): return iter(self._ids)
[docs]class IPBDictionary(Dictionary): """IPB Ingenia Dictionary. Args: dictionary_path (str): Dictionary file name. cffi_servo (CData): CFFI instance of the current Servo. Raises: ILCreationError: If the dictionary could not be created. """ def __init__(self, dictionary_path, cffi_servo): super(IPBDictionary, self).__init__(dictionary_path) self._cffi_dictionary = lib.il_servo_dict_get(cffi_servo) self.version = pstr(lib.il_dict_version_get(self._cffi_dictionary)) self.subnodes = SINGLE_AXIS_MINIMUM_SUBNODES self.__get_subnode() self.__regs = [] for subnode in range(self.subnodes): register = IPBRegistersDictionary(self._cffi_dictionary, subnode) self.__regs.append(register) self.categories = IPBCategories(self) self.errors = IPBErrors(self.path) self.__read_device_info() def __read_device_info(self): tree = ET.parse(self.path) root = tree.getroot() device = root.find('./Body/Device') self.firmware_version = device.attrib.get('firmwareVersion') product_code = device.attrib.get('ProductCode') if product_code is not None and product_code.isdecimal(): self.product_code = int(product_code) self.part_number = device.attrib.get('PartNumber') revision_number = device.attrib.get('RevisionNumber') if revision_number is not None and revision_number.isdecimal(): self.revision_number = int(revision_number) self.interface = device.attrib.get('Interface')
[docs] def save(self, filename): """Save dictionary. Args: filename (str): Output file name/path. """ r = lib.il_dict_save(self._cffi_dictionary, cstr(filename)) raise_err(r)
def __get_subnode(self): with open(self.path, 'r', encoding='utf-8') as xml_file: tree = ET.parse(xml_file) root = tree.getroot() if root.findall('./Body/Device/Axes/'): self.subnodes = len(root.findall('./Body/Device/Axes/Axis'))
[docs] def registers(self, subnode): """Obtain all the registers of a subnode. Args: subnode (int): Subnode. Returns: array: List of registers. """ if subnode < self.subnodes: return self.__regs[subnode]