diff -r 000000000000 -r 4472ee7c6c3e objdictgen/xml_in.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/objdictgen/xml_in.py Wed May 10 16:59:40 2006 +0200 @@ -0,0 +1,453 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +#This file is part of CanFestival, a library implementing CanOpen Stack. +# +#Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD +# +#See COPYING file for copyrights details. +# +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +# +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#Lesser General Public License for more details. +# +#You should have received a copy of the GNU Lesser General Public +#License along with this library; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from xml.parsers import expat + +import node +from node import * + +maxObjects = 8 + +currentPDOIndex = 0 +currentBitsMapped = 0 +currentMaxObjects = 0 +currentNbMappedObjects = 0 + +nextPdoIndex = {"rx":0x1400,"tx":0x1800} + +valid_elements = ["node","heartbeat_consumers","sdo_clients","pdo","mapped_object", + "pdo_param","pdo_receive","pdo_transmit","mapped_variable","mapped_table", + "mapped_string_variable","mapped_string_table"] + +#------------------------------------------------------------------------------- +# Callback method of parse +#------------------------------------------------------------------------------- + +def StartElement(name, attrs): + if name in valid_elements: + if name == "node": + startNode(attrs) + elif name == "heartbeat_consumers": + startHeartBeatConsumers(attrs) + elif name == "sdo_clients": + startSdoClients(attrs) + elif name in ["pdo_param","pdo_receive","pdo_transmit"]: + raise ValueError, """!!! The XML grammar has changed. +Please, open your xml file, delete the tags pdo_param, pdo_receive and pdo_transmit. +Use instead the tag pdo for each pdo to create, and (optional) use the tag mapped_object (menu pdo/map and object ...).""" + elif name == "pdo": + startPdo(attrs) + elif name == "mapped_object": + startMappedObject(attrs) + elif name == "mapped_variable": + startMappedVariable(attrs) + elif name == "mapped_table": + startMappedTable(attrs) + elif name == "mapped_string_variable": + startMappedVariable(attrs) + elif name == "mapped_string_table": + startMappedTable(attrs) + +def EndElement(name): + if name in valid_elements: + if name == "node": + stopNode() + +def CharacterData(data): + pass + +#------------------------------------------------------------------------------- +# Creation of Node +#------------------------------------------------------------------------------- + +def startNode(attrs): + name = attrs["name"] + Node.SetNodeName(name) + + if "node_id" in attrs and len(attrs["node_id"]) > 0: + node_id = eval(attrs["node_id"]) + else: + node_id = 0x01 # We define here a default node_id. + Node.SetNodeID(node_id) + + typeNode = attrs["type_node"] + Node.SetNodeType(typeNode) + + if "device_type_1000" in attrs: + device_type = eval(attrs["device_type_1000"]) + else: + device_type = 0 + Node.AddEntry(0x1000, 0, device_type) + Node.AddEntry(0x1001, 0, 0) + Node.AddEntry(0x1005, 0, 0x00000080) + Node.AddEntry(0x1006, 0, 0) + Node.AddEntry(0x1007, 0, 0) + + if "manufacturer_device_name_1008" in attrs: + manufacturer_device_name = attrs["manufacturer_device_name_1008"] + else: + manufacturer_device_name = "" + Node.AddEntry(0x1008, 0, manufacturer_device_name) + + if "manufacturer_hardware_version_1009" in attrs: + manufacturer_hardware_version = attrs["manufacturer_hardware_version_1009"] + else: + manufacturer_hardware_version = "__DATE__" + Node.AddEntry(0x1009, 0, manufacturer_hardware_version) + + if "manufacturer_software_version_100A" in attrs: + manufacturer_software_version = attrs["manufacturer_software_version_100A"] + else: + manufacturer_software_version = 0 + Node.AddEntry(0x100A, 0, manufacturer_software_version) + + if "vendor_id_1018" in attrs: + vendor_id = eval(attrs["vendor_id_1018"]) + else: + vendor_id = 0 + if "product_code_1018" in attrs: + product_code = eval(attrs["product_code_1018"]) + else: + product_code = 0 + if "revision_number_1018" in attrs: + revision_number = eval(attrs["revision_number_1018"]) + else: + revision_number = 0 + if "serial_number_1018" in attrs: + serial_number = eval(attrs["serial_number_1018"]) + else: + serial_number = 0 + Node.AddEntry(0x1018, 1, vendor_id) + Node.AddEntry(0x1018, 2, product_code) + Node.AddEntry(0x1018, 3, revision_number) + Node.AddEntry(0x1018, 4, serial_number) + +def stopNode(): + heartBeatProducer() + sdoServer() + +#------------------------------------------------------------------------------- +# Creation of PDO in Object Dictionary +#------------------------------------------------------------------------------- + +def startPdo(attrs): + global currentPdoIndex + global currentMaxObjects + global currentNbMappedObjects + global currentBitsMapped + global maxObjects + + cobId = 0 + transmissionType = 253 # Default is on request. Why not ? + + # Find the type of the PDO and search the index of the last added + type = attrs["type_rx_tx"] + index = nextPdoIndex[type] + + # If the index of the PDO is define, verify that it has a good index + if "index_communication_parameter" in attrs: + index = eval(attrs["index_communication_parameter"]) + if type == "rx" and not 0x1400 <= index <= 0x15FF: + raise ValueError, """!!! Abort because Index PDO receive : 0x%04X not valid. +Valid index is 0x1400 ... 0x15FF"""%index + if type == "tx" and not 0x1800 <= index <= 0x19FF: + raise ValueError, """!!! Abort because Index PDO transmit : 0x%04X not valid. +Valid index is 0x1800 ... 0x19FF"""%index + + # Extract the PDO communication parameters + if "cob_id" == attrs: + cobId = eval(attrs["cob_id"]) + if "max_objects_in_pdo" == attrs: + maxObjects = eval(attrs["max_objects_in_pdo"]) + if "transmission_type" in attrs: + transmissionType = eval(attrs["transmission_type"]) + + if Node.IsEntry(index): + raise ValueError, """!!! Abort because the PDO at index : 0x%04X have been already defined."""%index + + # Communication parameters + Node.AddEntry(index, 1, cobId) + Node.AddEntry(index, 2, transmissionType) + + # Mapping parameters + mapping_index = index + 0x200 + for i in xrange(1, maxObjects + 1): + Node.AddEntry(mapping_index, i, 0x0) + + currentPdoIndex = index + currentMaxObjects = maxObjects + currentBitsMapped = 0 + currentNbMappedObjects = 0 + + nextPdoIndex[type] = index + 1 + +def startMappedObject(attrs): + global currentPdoIndex + global currentMaxObjects + global currentNbMappedObjects + global currentBitsMapped + + index = currentPdoIndex + mapping_index = index + 0x200 + + indexObject = eval(attrs["index"]) + subIndexObject = eval(attrs["sub_index"]) + sizeInBitsObject = eval(attrs["size_in_bits"]) + + if currentMaxObjects == 0: + raise ValueError, """!!! Abort because of a bogue for mapped object (defined at index 0x%04X, subIndex 0x%025X) +in PDO. index : 0x%04X is undefined."""%(indexObject,subindexObject,mapping_index) + if currentNbMappedObjects >= currentMaxObjects: + raise ValueError, """!!! Abort mapping object (defined at index 0x%04X, subIndex 0x%02X) +in PDO index 0x%04X. max objects (%d) reached."""%(IndexObject,subIndexObject,mapping_index,pdo[mapping_index]["maxObjects"]) + if currentBitsMapped + sizeInBitsObject > 64: + raise ValueError, """!!! Abort mapping object (defined at index 0x%04X, subIndex 0x%02X) +in PDO index 0x%04X. No room to put %d bits in the PDO."""%(IndexObject,subIndexObject,mapping_index,sizeInBitsObject) + + value = eval("0x%04X%02X%02X"%(indexObject,subIndexObject,sizeInBitsObject)) + Node.SetEntry(mapping_index, currentNbMappedObjects + 1, value) + + currentNbMappedObjects += 1 + currentBitsMapped += sizeInBitsObject + +#------------------------------------------------------------------------------- +# Creation of mapped variable and table +#------------------------------------------------------------------------------- + +def startMappedVariable(attrs): + name = attrs["name"] + index = eval(attrs["index"]) + subIndex = eval(attrs["sub_index"]) + + if "size_in_bits" in attrs: + size = eval(attrs["size_in_bits"]) # Numeric variable + if "type" in attrs: + type = attrs["type"] + if (type == "UNS"): + type = "UNSIGNED" + else: # Default type + type = "UNSIGNED" + typename = "%s%d"%(type,size) + + type_index = Manager.GetTypeIndex(typename, False) + if type_index == None: + raise ValueError, """!!! ERROR : For variable "%s" at index 0x%04X, subindex 0x%02X : Unrecognized type : %s"""%(name,index,subIndex,typename) + + # Begin ValueRange support + if "min_value" in attrs or "max_value" in attrs: + if "min_value" in attrs and "max_value" in attrs: + minValue = eval(attrs["min_value"]) + maxValue = eval(attrs["max_value"]) + if (minValue > maxValue): + raise ValueError, """!!! ERROR : For variable "%s" at index 0x%04X, subindex 0x%02X : error in value-range : min > max"""%(name,index,subIndex) + else: + raise ValueError, """!!! ERROR : For variable "%s" at index 0x%04X, subindex 0x%02X : You have defined only a min or a max value. \nIf you define one, you must define both."""%(name,index,subIndex) + + type_index = findRangeType(type_index, minValue, maxValue) + if type_index == None: + raise ValueError, """!!! Sorry, too many different value range have been defined""" + # End ValueRange support + + if "size_in_byte" in attrs: + size = eval(attrs["size_in_byte"]) # String variable + type_index = findStringType(Manager.GetTypeIndex("VISIBLE_STRING", False), size) + if type_index == None: + raise ValueError, """!!! Sorry, too many different string length have been defined""" + + if "access" in attrs: + access = attrs["access"].lower() + else: + access = "rw" # default value + + if index < 0x2000 or index > 0xBFFF: + raise ValueError, """!!! ERROR : For variable "%s" at index 0x%04X, subindex 0x%02X : Variable can't be defined using this index-subindex."""%(name,index,subIndex) + + if subIndex == 0: + Node.AddMappingEntry(index, name = name, struct = 1) + elif subIndex == 1: + Node.AddMappingEntry(index, struct = 3) + Node.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False}) + result = Node.AddMappingEntry(index, subIndex, values = {"name" : name, "type" : type_index, "access" : access, "pdo" : True}) + + if result: + Node.AddEntry(index, subIndex, 0) + else: + raise ValueError, """!!! ERROR : For variable "%s" at index 0x%04X, subindex 0x%02X : Unable to map"""%(name,index,subIndex) + +def startMappedTable(attrs): + name = attrs["name"] + number_elements = eval(attrs["number_elements"]) + index = eval(attrs["index"]) + + if "size_in_bits" in attrs: + size = eval(attrs["size_in_bits"]) # Numeric variable + if "type" in attrs: + type = attrs["type"] + if (type == "UNS"): + type = "UNSIGNED" + else: # Default type + type = "UNSIGNED" + typename = "%s%d"%(type,size) + + type_index = Manager.GetTypeIndex(typename, False) + if type_index == None: + raise ValueError, """!!! ERROR : For table \"%s\" at index 0x%04X : Unrecognized type : %s"""%(name,index,typename) + + # Begin ValueRange support + if "min_value" in attrs or "max_value" in attrs: + if "min_value" in attrs and "max_value" in attrs: + minValue = eval(attrs["min_value"]) + maxValue = eval(attrs["max_value"]) + if (minValue > maxValue): + raise ValueError, """!!! ERROR : For table \"%s\" at index 0x%04X : error in value-range : min > max"""%(name,index) + else: + raise ValueError, """!!! ERROR : For table \"%s\" at index 0x%04X : You have defined only a min or a max value. \nIf you define one, you must define both."""%(name,index) + + type_index = findRangeType(type_index, minValue, maxValue) + if type_index == None: + raise ValueError, """!!! Sorry, too many different value range have been defined""" + # End ValueRange support + + if "size_in_byte" in attrs: + size = eval(attrs["size_in_byte"]) # String variable + type_index = findStringType(Manager.GetTypeIndex("VISIBLE_STRING", False), size) + if type_index == None: + raise ValueError, """!!! Sorry, too many different string length have been defined""" + + if "access" in attrs: + access = attrs["access"].lower() + else: + access = "rw" # default value + + if index < 0x2000 or index > 0xBFFF: + raise ValueError, """!!! ERROR : For table \"%s\" at index 0x%04X : Variable can't be defined using this index-subindex."""%(name,index) + + result = Node.AddMappingEntry(index, name = name, struct = 7) + if not result: + raise ValueError, """!!! ERROR : For table \"%s\" at index 0x%04X : Unable to map because a variable or a table is using this index"""%(name,index) + Node.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False}) + Node.AddMappingEntry(index, 1, values = {"name" : name, "type" : type_index, "access" : access, "pdo" : True, "nbmax" : number_elements}) + + for subIndex in xrange(1,number_elements+1): + Node.AddEntry(index, subIndex, 0) + +def findRangeType(type, minValue, maxValue): + index = 0xA0 + while index < 0x100 and Node.IsEntry(index): + current_type = Node.GetEntry(index, 1) + if current_type == type: + current_minValue = Node.GetEntry(index, 2) + current_maxValue = Node.GetEntry(index, 3) + if current_minValue == minValue and current_maxValue == maxValue: + return index + index += 1 + if index < 0x100: + infos = Manager.GetEntryInfos(type, False) + name = "%s[%d-%d]"%(infos["name"], minValue, maxValue) + Node.AddMappingEntry(index, name = name, struct = 3, size = infos["size"], default = infos["default"]) + Node.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False}) + Node.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False}) + Node.AddMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False}) + Node.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False}) + Node.AddEntry(index, 1, type) + Node.AddEntry(index, 2, minValue) + Node.AddEntry(index, 3, maxValue) + return index + return None + +def findStringType(type, length): + index = 0xA0 + while index < 0x100 and Node.IsEntry(index): + current_type = Node.GetEntry(index, 1) + if current_type == type: + current_length = Node.GetEntry(index, 2) + if current_length == length: + return index + index += 1 + if index < 0x100: + infos = Manager.GetEntryInfos(type, False) + name = "%s%d"%(Manager.GetTypeName(type), length) + Node.AddMappingEntry(index, name = name, struct = 3, size = infos["size"], default = infos["default"]) + Node.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False}) + Node.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False}) + Node.AddMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False}) + Node.AddEntry(index, 1, type) + Node.AddEntry(index, 2, length) + return index + return None + +#------------------------------------------------------------------------------- +# Creation HeartBeat Producer & Consumers +#------------------------------------------------------------------------------- + +def heartBeatProducer(): + Node.AddEntry(0x1017, 0, 0) + +def startHeartBeatConsumers(attrs): + nombre = eval(attrs["nombre"]) + for i in xrange(nombre): + Node.AddEntry(0x1016, i + 1, 0) + +#------------------------------------------------------------------------------- +# Creation of SDO Server & Clients +#------------------------------------------------------------------------------- + +def sdoServer(): + Node.AddEntry(0x1200, 1, 0x600 + Node.GetNodeID()) + Node.AddEntry(0x1200, 2, 0x580 + Node.GetNodeID()) + +def startSdoClients(attrs): + nombre = eval(attrs["nombre"]) + for i in xrange(nombre): + Node.AddEntry(0x1280 + i, 1, 0x600) + Node.AddEntry(0x1280 + i, 2, 0x580) + Node.AddEntry(0x1280 + i, 3, 0) + +#------------------------------------------------------------------------------- +# Parse file with Saxe +#------------------------------------------------------------------------------- + +def ParseFile(filepath): + xmlfile = open(filepath,"r") + Parser = expat.ParserCreate() + Parser.StartElementHandler = StartElement + Parser.EndElementHandler = EndElement + Parser.CharacterDataHandler = CharacterData + ParserStatus = Parser.ParseFile(xmlfile) + xmlfile.close() + +def GenerateNode(filepath, manager): + global Node + global Manager + Manager = manager + Node = node.Node() + ParseFile(filepath) + return Node + +#------------------------------------------------------------------------------- +# Main Function +#------------------------------------------------------------------------------- + +if __name__ == '__main__': + ParseFile("test.xml") +