def from_smdx(self, element): smdx_data = '' for m in element.findall(smdx.SMDX_MODEL): if True: self.id = int(m.attrib.get(smdx.SMDX_ATTR_ID)) self.len = m.attrib.get(smdx.SMDX_ATTR_LEN) self.name = m.attrib.get(smdx.SMDX_ATTR_NAME) if self.name is None: self.name = 'model_' + str(self.id) if self.len is None: raise SunSpecError('Module len error') self.len = int(self.len) for b in m.findall(smdx.SMDX_BLOCK): block = BlockType(model_type=self) block.from_smdx(b) if block.type == suns.SUNS_BLOCK_FIXED: if self.fixed_block is None: self.fixed_block = block else: raise SunSpecError( 'Duplicate fixed block type definition') elif block.type == suns.SUNS_BLOCK_REPEATING: if self.repeating_block is None: self.repeating_block = block else: raise SunSpecError( 'Duplicate repeating block type definition') break else: raise SunSpecError('Unexpected smdx element: %s' % m.tag) for s in element.findall(smdx.SMDX_STRINGS): if s.attrib.get(smdx.SMDX_ATTR_ID) == str(self.id): m = s.find(smdx.SMDX_MODEL) if m is not None: for e in m.findall('*'): if e.tag == smdx.SMDX_LABEL: self.label = e.text elif e.tag == smdx.SMDX_DESCRIPTION: self.description = e.text elif e.tag == smdx.SMDX_NOTES: self.notes = e.text for e in s.findall(smdx.SMDX_POINT): pid = e.attrib.get(smdx.SMDX_ATTR_ID) point_type = None if self.fixed_block is not None: point_type = self.fixed_block.points.get(pid) if point_type is None and self.repeating_block is not None: point_type = self.repeating_block.points.get(pid) if point_type: point_type.from_smdx(e, strings=True) if self.fixed_block is None: self.fixed_block = BlockType(suns.SUNS_BLOCK_FIXED, model_type=self)
def from_smdx(self, element): """ Sets the block type attributes based on an element tree block type element contained in an SMDX model definition. Parameters: element : Element Tree block type element. """ btype = element.attrib.get(smdx.SMDX_ATTR_TYPE, smdx.SMDX_ATTR_TYPE_FIXED) if btype != smdx.SMDX_ATTR_TYPE_FIXED and btype != smdx.SMDX_ATTR_TYPE_REPEATING: raise SunSpecError('Invalid block type') self.type = smdx.smdx_block_types.get(btype) self.len = element.attrib.get(smdx.SMDX_ATTR_LEN) if self.len is None: raise SunSpecError('Block len error') self.name = element.attrib.get(smdx.SMDX_ATTR_NAME) if self.name is None: self.name = self.type # process points for e in element.findall(smdx.SMDX_POINT): pt = PointType(block_type=self) pt.from_smdx(e) if self.points.get(pt.id) is not None: ET.dump(e) raise SunSpecError('Duplicate point definition: %s' % (pt.id)) self.points_list.append(pt) self.points[pt.id] = pt
def from_pics(self, element): # update index if present self.index = element.attrib.get(pics.PICS_ATTR_INDEX, self.index) for b in element.findall('*'): if b.tag != pics.PICS_BLOCK: raise SunSpecError("Unexpected '%s' element in '%s' element" % (b.tag, element.tag)) block_type = pics.pics_block_types.get( b.attrib.get(pics.PICS_ATTR_TYPE, pics.PICS_TYPE_FIXED)) if block_type is None: raise SunSpecError('Unknown block type') if block_type == suns.SUNS_BLOCK_FIXED: if len(self.blocks) > 0: self.blocks[0].from_pics(b) elif block_type == suns.SUNS_BLOCK_REPEATING: block_index = b.attrib.get(pics.PICS_ATTR_INDEX) # if no index specified, apply to all repeating blocks if block_index is None: if len(self.blocks) > 1: for block in self.blocks[1:]: block.from_pics(b) else: block_index = int(block_index) if len(self.blocks) < block_index: raise SunSpecError('Block index out of range: %s' % (str(block_index))) self.blocks[block_index].from_pics(b) else: raise SunSpecError('Internal block type error')
def from_pics(self, element): """Sets the block contents based on an element tree model type element contained in a SunSpec PICS document. Parameters: element : Element Tree model element. """ for p in element.findall('*'): if p.tag != pics.PICS_POINT: raise SunSpecError("Unexpected '%s' element in '%s' element" % (p.tag, element.tag)) pid = p.attrib.get(pics.PICS_ATTR_ID) point = self.points.get(pid) if point is None: point = self.points_sf.get(pid) if point is not None: point.from_pics(p) # resolve scale factor values in points, must be done after all points in block are read for point in self.points_list: if point.sf_point is not None: point.value_sf = point.sf_point.value_base
def from_smdx(self, element, strings=False): for e in element.findall('*'): if e.tag == smdx.SMDX_LABEL: self.label = e.text elif e.tag == smdx.SMDX_DESCRIPTION: self.description = e.text elif e.tag == smdx.SMDX_NOTES: self.notes = e.text elif e.tag == smdx.SMDX_SYMBOL: sid = e.attrib.get(smdx.SMDX_ATTR_ID) symbol = self.block_type.model_type.symbol_get(sid) if symbol is None: symbol = Symbol() symbol.from_smdx(e, strings) self.block_type.model_type.symbol_add(symbol) if self.symbol_get(sid) is None: self.symbols.append(symbol) symbol.from_smdx(e, strings) if strings is False: self.id = element.attrib.get(smdx.SMDX_ATTR_ID) self.offset = int(element.attrib.get(smdx.SMDX_ATTR_OFFSET)) ptype = element.attrib.get(smdx.SMDX_ATTR_TYPE) plen = element.attrib.get(smdx.SMDX_ATTR_LEN) mandatory = element.attrib.get(smdx.SMDX_ATTR_MANDATORY, smdx.SMDX_MANDATORY_FALSE) access = element.attrib.get(smdx.SMDX_ATTR_ACCESS, smdx.SMDX_ACCESS_R) self.units = element.attrib.get(smdx.SMDX_ATTR_UNITS) if self.id is None: raise SunSpecError('Missing point id attribute') if self.offset is None: raise SunSpecError('Missing offset attribute for point: %s' % self.id) if ptype is None: raise SunSpecError('Missing type attribute for point: %s' % self.id) if ptype == smdx.SMDX_TYPE_STRING and plen is None: raise SunSpecError('Missing len attribute for point: %s' % self.id) self.type = smdx.smdx_point_types.get(ptype) if self.type is None: raise SunSpecError('Unknown point type: %s' % ptype) self.mandatory = smdx.smdx_mandatory_types.get(mandatory) if self.mandatory is None: raise SunSpecError('Unknown mandatory type: %s' % mandatory) self.access = smdx.smdx_access_types.get(access) if self.access is None: raise SunSpecError('Unknown access type: %s' % access) self.sf = element.attrib.get(smdx.SMDX_ATTR_SF) info = suns.suns_point_type_info.get(self.type) if info is not None: self.len, self.is_impl, self.data_to, self.to_data, self.to_value, self.value_default = info if plen is not None: self.len = int(plen)
def model_type_get(model_id): global file_pathlist global model_types model_type = model_types.get(str(model_id)) if model_type is None: smdx_data = '' # create model file name filename = smdx.model_id_to_filename(model_id) # check in file path list if set if file_pathlist is not None: try: smdx_data = file_pathlist.read(filename) except NameError: pass if not smdx_data: if not os.path.exists(filename): filename = os.path.join(model_type_path_default, filename) if os.path.exists(filename): try: f = open(filename, 'r') smdx_data = f.read() f.close() except Exception as e: raise SunSpecError('Error loading model {} at {}: {}'.format(model_id, filename, str(e))) if smdx_data: root = ET.fromstring(smdx_data) # load model type try: model_type = ModelType() model_type.from_smdx(root) model_types[model_type.id] = model_type except Exception as e: raise SunSpecError('Error loading model {} at {}: {}'.format(model_id, filename, str(e))) else: raise SunSpecError('Model file for model %s not found' % (str(model_id))) return model_type
def from_smdx(self, element, strings=False): for e in element.findall('*'): if e.tag == smdx.SMDX_LABEL: self.label = e.text elif e.tag == smdx.SMDX_DESCRIPTION: self.description = e.text elif e.tag == smdx.SMDX_NOTES: self.notes = e.text if strings is False: self.id = element.attrib.get(smdx.SMDX_ATTR_ID) self.value = element.text if self.id is None: raise SunSpecError('Missing point id attribute')
def from_pics(self, element): """ Sets the model contents based on an element tree model type element contained in a SunSpec PICS document. Parameters: element : Element Tree model element. """ # update index if present self.index = element.attrib.get(pics.PICS_ATTR_INDEX, self.index) for b in element.findall('*'): if b.tag != pics.PICS_BLOCK: raise SunSpecError("Unexpected '{}' element in '{}' element".format(b.tag, element.tag)) block_type = pics.pics_block_types.get(b.attrib.get(pics.PICS_ATTR_TYPE, pics.PICS_TYPE_FIXED)) if block_type is None: raise SunSpecError('Unknown block type') if block_type == suns.SUNS_BLOCK_FIXED: if len(self.blocks) > 0: self.blocks[0].from_pics(b) elif block_type == suns.SUNS_BLOCK_REPEATING: block_index = b.attrib.get(pics.PICS_ATTR_INDEX) # if no index specified, apply to all repeating blocks if block_index is None: if len(self.blocks) > 1: for block in self.blocks[1:]: block.from_pics(b) else: block_index = int(block_index) if len(self.blocks) < block_index: raise SunSpecError('Block index out of range: %s' % (str(block_index))) self.blocks[block_index].from_pics(b) else: raise SunSpecError('Internal block type error')
def from_pics(self, element): for p in element.findall('*'): if p.tag != pics.PICS_POINT: raise SunSpecError("Unexpected '%s' element in '%s' element" % (p.tag, element.tag)) pid = p.attrib.get(pics.PICS_ATTR_ID) point = self.points.get(pid) if point is None: point = self.points_sf.get(pid) if point is not None: point.from_pics(p) # resolve scale factor values in points, must be done after all points in block are read for point in self.points_list: if point.sf_point is not None: point.value_sf = point.sf_point.value_base
def from_pics(self, element=None, filename=None, pathlist=None): """The PICS information for the device can be either an Element Tree element for a device from a document already being processed or the file name of document in the file system. Populates the device based on the elements within the device element. Parameters: element : Element Tree device element. filename : File name of the PICS document. pathlist : Pathlist object containing alternate paths to the PICS document. """ global file_pathlist pics_data = '' try: if element is None: # try supplied path list if pathlist is not None: try: pics_data = pathlist.read(filename) except NameError: pass # try device file path list if not pics_data and file_pathlist is not None: try: pics_data = file_pathlist.read(filename) except NameError: pass # try local directory if not pics_data: f = open(filename, 'r') pics_data = f.read() f.close() root = ET.fromstring(pics_data) if root.tag != pics.PICS_ROOT: raise SunSpecError("Unexpected root element: %s" % (root.tag)) d = root.find(pics.PICS_DEVICE) if d is None: raise SunSpecError( "No '%s' elements found in '%s' element" % (pics.PICS_DEVICE, root.tag)) else: d = element if d.tag != pics.PICS_DEVICE: raise SunSpecError("Unexpected device tag: '%s'" % (d.tag)) self.base_addr = d.attrib.get(pics.PICS_ATTR_BASE_ADDR, pics.PICS_BASE_ADDR_DEFAULT) addr = self.base_addr + 2 for m in d.findall('*'): if m is None: raise SunSpecError( "No '%s' elements found in '%s' element" % (pics.PICS_MODEL, d.tag)) if m.tag != pics.PICS_MODEL: raise SunSpecError( "Unexpected '%s' element in '%s' element" % (m.tag, d.tag)) model_id = m.attrib.get(pics.PICS_ATTR_ID) if model_id is None: raise SunSpecError('Module id error') model_len = m.attrib.get(pics.PICS_ATTR_LEN) if model_len is not None: # raise SunSpecError('Module len error in model %d' % (model_id)) model_len = int(model_len) # move address past model id and length (even though address is not real in the case) model = Model(self, model_id, addr + 2, model_len) try: model.load() except Exception, e: model.load_error = str(e) model.from_pics(m) self.add_model(model) addr += model.len + 2 except Exception, e: raise SunSpecError('Error loading PICS: %s' % str(e))
def load(self, block_class=Block, point_class=Point): """Loads the model instance with blocks and points based on the SunSpec model type definition. Parameters: block_class : Block class to use to create block instances. point_class : Point class to use to create point instances. """ last_read_addr = self.addr self.read_blocks.append(last_read_addr) self.model_type = model_type_get(self.id) if self.model_type is not None: if self.len == 0: self.len = self.model_type.len end_addr = self.addr + self.len index = 0 # model type always has a fixed block defined block_type = self.model_type.fixed_block block_addr = self.addr block_len = int(block_type.len) # adjustment for legacy common model len = 65 if self.id == 1 and self.len == 65: block_len = self.len # while another block while end_addr >= block_addr + block_len: block = block_class(self, block_addr, block_len, block_type, index) self.blocks.append(block) for point_type in block_type.points_list: if point_type.type != suns.SUNS_TYPE_PAD: point_addr = int(block_addr) + int(point_type.offset) point = point_class(block, point_type, str(point_addr)) if point_addr + point.point_type.len - last_read_addr > MAX_READ_COUNT: last_read_addr = point_addr self.read_blocks.append(last_read_addr) if point_type.type == suns.SUNS_TYPE_SUNSSF: block.points_sf[point_type.id] = point else: block.points_list.append(point) block.points[point_type.id] = point # resolve scale factor addresses for repeating block for point in block.points_list: if point.point_type.sf is not None and point.sf_point is None: # check for constant scale factor try: sf_value = int(point.point_type.sf) point.sf_point = ScaleFactor(sf_value) except Exception: pass # try local repeating block first if point.sf_point is None: point.sf_point = block.points_sf.get( point.point_type.sf) if point.sf_point is None: # if repeating block, try fixed block if index > 0: point.sf_point = self.blocks[0].points_sf.get( point.point_type.sf) if point.sf_point is None: # ### what state should model be left in on exception raise SunSpecError( 'Unable to resolve scale factor point %s for point %s in model %s' % point.point_type.sf, point.point_type.pid, self.id) block_addr += block_len block_type = self.model_type.repeating_block if block_type is None: ### check for extra registers? break index += 1 block_len = int(block_type.len) else: raise SunSpecError('Unknown model type - id: %s' % str(self.id)) # expose fixed block points at model level if present try: self.points_list = self.blocks[0].points_list self.points = self.blocks[0].points self.points_sf = self.blocks[0].points_sf except IndexError: pass
raise SunSpecError('Error loading model %s at %s: %s' % (model_id, filename, str(e))) if smdx_data: root = ET.fromstring(smdx_data) # load model type try: model_type = ModelType() model_type.from_smdx(root) model_types[model_type.id] = model_type except Exception, e: raise SunSpecError('Error loading model %s at %s: %s' % (model_id, filename, str(e))) else: raise SunSpecError('Model file for model %s not found' % (str(model_id))) return model_type class ModelType(object): """ Parameters: mid : Model id that identifies a specific SunSpec model type definition. Attributes: id Model id that identifies a specific SunSpec model type definition.
def from_pics(self, element=None, filename=None, pathlist=None): global file_pathlist pics_data = '' try: if element is None: # try supplied path list if pathlist is not None: try: pics_data = pathlist.read(filename) except NameError: pass # try device file path list if not pics_data and file_pathlist is not None: try: pics_data = file_pathlist.read(filename) except NameError: pass # try local directory if not pics_data: f = open(filename, 'r') pics_data = f.read() f.close() root = ET.fromstring(pics_data) if root.tag != pics.PICS_ROOT: raise SunSpecError("Unexpected root element: %s" % (root.tag)) d = root.find(pics.PICS_DEVICE) if d is None: raise SunSpecError( "No '%s' elements found in '%s' element" % (pics.PICS_DEVICE, root.tag)) else: d = element if d.tag != pics.PICS_DEVICE: raise SunSpecError("Unexpected device tag: '%s'" % (d.tag)) self.base_addr = d.attrib.get(pics.PICS_ATTR_BASE_ADDR, pics.PICS_BASE_ADDR_DEFAULT) addr = self.base_addr + 2 for m in d.findall('*'): if m is None: raise SunSpecError( "No '%s' elements found in '%s' element" % (pics.PICS_MODEL, d.tag)) if m.tag != pics.PICS_MODEL: raise SunSpecError( "Unexpected '%s' element in '%s' element" % (m.tag, d.tag)) model_id = m.attrib.get(pics.PICS_ATTR_ID) if model_id is None: raise SunSpecError('Module id error') model_len = m.attrib.get(pics.PICS_ATTR_LEN) if model_len is not None: # raise SunSpecError('Module len error in model %d' % (model_id)) model_len = int(model_len) # move address past model id and length (even though address is not real in the case) model = Model(self, model_id, addr + 2, model_len) try: model.load() except Exception, e: model.load_error = str(e) model.from_pics(m) self.add_model(model) addr += model.len + 2 except Exception, e: raise SunSpecError('Error loading PICS: %s' % str(e))