/home/epimerde/documents/tc11/CanFestival-3/objdictgen/xml_in.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003 
00004 #This file is part of CanFestival, a library implementing CanOpen Stack. 
00005 #
00006 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
00007 #
00008 #See COPYING file for copyrights details.
00009 #
00010 #This library is free software; you can redistribute it and/or
00011 #modify it under the terms of the GNU Lesser General Public
00012 #License as published by the Free Software Foundation; either
00013 #version 2.1 of the License, or (at your option) any later version.
00014 #
00015 #This library is distributed in the hope that it will be useful,
00016 #but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 #Lesser General Public License for more details.
00019 #
00020 #You should have received a copy of the GNU Lesser General Public
00021 #License along with this library; if not, write to the Free Software
00022 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 
00024 from xml.parsers import expat
00025 
00026 import node
00027 from node import *
00028 
00029 maxObjects = 8
00030 
00031 currentPDOIndex = 0
00032 currentBitsMapped = 0
00033 currentMaxObjects = 0
00034 currentNbMappedObjects = 0
00035 
00036 nextPdoIndex = {"rx":0x1400,"tx":0x1800}
00037 
00038 valid_elements = ["node","heartbeat_consumers","sdo_clients","pdo","mapped_object",
00039     "pdo_param","pdo_receive","pdo_transmit","mapped_variable","mapped_table",
00040     "mapped_string_variable","mapped_string_table"]
00041 
00042 #-------------------------------------------------------------------------------
00043 #                       Callback method of parse
00044 #-------------------------------------------------------------------------------
00045 
00046 def StartElement(name, attrs):
00047     if name in valid_elements:
00048         if name == "node":
00049             startNode(attrs)
00050         elif name == "heartbeat_consumers":
00051             startHeartBeatConsumers(attrs)
00052         elif name == "sdo_clients":
00053             startSdoClients(attrs)
00054         elif name in ["pdo_param","pdo_receive","pdo_transmit"]:
00055             raise ValueError, """!!! The XML grammar has changed.
00056 Please, open your xml file, delete the tags pdo_param, pdo_receive and pdo_transmit.
00057 Use instead the tag pdo for each pdo to create, and (optional) use the tag mapped_object (menu pdo/map and object ...)."""
00058         elif name == "pdo":
00059             startPdo(attrs)
00060         elif name == "mapped_object":
00061             startMappedObject(attrs)
00062         elif name == "mapped_variable":
00063             startMappedVariable(attrs)
00064         elif name == "mapped_table":
00065             startMappedTable(attrs)
00066         elif name == "mapped_string_variable":
00067             startMappedVariable(attrs)
00068         elif name == "mapped_string_table":
00069             startMappedTable(attrs)
00070 
00071 def EndElement(name):
00072     if name in valid_elements:
00073        if name == "node":
00074            stopNode()
00075 
00076 def CharacterData(data):
00077     pass
00078 
00079 #-------------------------------------------------------------------------------
00080 #                          Creation of Node
00081 #-------------------------------------------------------------------------------
00082 
00083 def startNode(attrs):
00084     name = attrs["name"]
00085     Node.SetNodeName(name)
00086     
00087     if "node_id" in attrs and len(attrs["node_id"]) > 0:
00088         node_id = eval(attrs["node_id"])
00089     else:
00090         node_id = 0x01  # We define here a default node_id. 
00091     Node.SetNodeID(node_id)
00092     
00093     typeNode = attrs["type_node"]
00094     Node.SetNodeType(typeNode)
00095     
00096     if "device_type_1000" in attrs:
00097         device_type = eval(attrs["device_type_1000"])
00098     else:
00099         device_type = 0
00100     Node.AddEntry(0x1000, 0, device_type)
00101     Node.AddEntry(0x1001, 0, 0)
00102     Node.AddEntry(0x1005, 0, 0x00000080)
00103     Node.AddEntry(0x1006, 0, 0)
00104     Node.AddEntry(0x1007, 0, 0)
00105 
00106     if "manufacturer_device_name_1008" in attrs:
00107         manufacturer_device_name = attrs["manufacturer_device_name_1008"]
00108     else:
00109         manufacturer_device_name = ""
00110     Node.AddEntry(0x1008, 0, manufacturer_device_name)
00111     
00112     if "manufacturer_hardware_version_1009" in attrs:
00113         manufacturer_hardware_version = attrs["manufacturer_hardware_version_1009"]
00114     else:
00115         manufacturer_hardware_version = "__DATE__"
00116     Node.AddEntry(0x1009, 0, manufacturer_hardware_version)
00117 
00118     if "manufacturer_software_version_100A" in attrs:
00119         manufacturer_software_version = attrs["manufacturer_software_version_100A"]
00120     else:
00121         manufacturer_software_version = 0
00122     Node.AddEntry(0x100A, 0,  manufacturer_software_version)
00123 
00124     if "vendor_id_1018" in attrs:
00125         vendor_id = eval(attrs["vendor_id_1018"])
00126     else:
00127         vendor_id = 0
00128     if "product_code_1018" in attrs:
00129         product_code = eval(attrs["product_code_1018"])
00130     else:
00131         product_code = 0
00132     if "revision_number_1018" in attrs:
00133         revision_number = eval(attrs["revision_number_1018"])
00134     else:
00135         revision_number = 0
00136     if "serial_number_1018" in attrs:
00137         serial_number = eval(attrs["serial_number_1018"])
00138     else:
00139         serial_number = 0
00140     Node.AddEntry(0x1018, 1, vendor_id)
00141     Node.AddEntry(0x1018, 2, product_code)
00142     Node.AddEntry(0x1018, 3, revision_number)
00143     Node.AddEntry(0x1018, 4, serial_number)
00144 
00145 def stopNode():
00146     heartBeatProducer()
00147     sdoServer()
00148 
00149 #-------------------------------------------------------------------------------
00150 #                      Creation of PDO in Object Dictionary
00151 #-------------------------------------------------------------------------------
00152 
00153 def startPdo(attrs):
00154     global currentPdoIndex
00155     global currentMaxObjects
00156     global currentNbMappedObjects
00157     global currentBitsMapped
00158     global maxObjects
00159     
00160     cobId = 0
00161     transmissionType = 253 # Default is on request. Why not ?
00162 
00163     # Find the type of the PDO and search the index of the last added
00164     type = attrs["type_rx_tx"]
00165     index = nextPdoIndex[type]
00166     
00167     # If the index of the PDO is define, verify that it has a good index
00168     if "index_communication_parameter" in attrs:
00169         index = eval(attrs["index_communication_parameter"])
00170     if type == "rx" and not 0x1400 <= index <= 0x15FF:
00171         raise ValueError, """!!! Abort because Index PDO receive : 0x%04X not valid.
00172 Valid index is 0x1400 ... 0x15FF"""%index
00173     if type == "tx" and not 0x1800 <= index <= 0x19FF:
00174         raise ValueError, """!!! Abort because Index PDO transmit : 0x%04X not valid.
00175 Valid index is 0x1800 ... 0x19FF"""%index
00176     
00177     # Extract the PDO communication parameters
00178     if "cob_id" == attrs:
00179         cobId = eval(attrs["cob_id"])
00180     if "max_objects_in_pdo" == attrs:
00181         maxObjects = eval(attrs["max_objects_in_pdo"])
00182     if "transmission_type" in attrs:
00183         transmissionType = eval(attrs["transmission_type"])
00184 
00185     if Node.IsEntry(index):
00186         raise ValueError, """!!! Abort because the PDO at index : 0x%04X have been already defined."""%index
00187 
00188     # Communication parameters
00189     Node.AddEntry(index, 1, cobId)
00190     Node.AddEntry(index, 2, transmissionType)
00191     
00192     # Mapping parameters
00193     mapping_index = index + 0x200
00194     for i in xrange(1, maxObjects + 1):
00195         Node.AddEntry(mapping_index, i, 0x0)
00196 
00197     currentPdoIndex = index
00198     currentMaxObjects = maxObjects
00199     currentBitsMapped = 0
00200     currentNbMappedObjects = 0
00201     
00202     nextPdoIndex[type] = index + 1
00203 
00204 def startMappedObject(attrs):
00205     global currentPdoIndex
00206     global currentMaxObjects
00207     global currentNbMappedObjects
00208     global currentBitsMapped
00209     
00210     index = currentPdoIndex
00211     mapping_index = index + 0x200
00212     
00213     indexObject = eval(attrs["index"])
00214     subIndexObject = eval(attrs["sub_index"])
00215     sizeInBitsObject = eval(attrs["size_in_bits"])
00216 
00217     if currentMaxObjects == 0:
00218         raise ValueError, """!!! Abort because of a bogue for mapped object (defined at index 0x%04X, subIndex 0x%025X)
00219 in PDO. index : 0x%04X is undefined."""%(indexObject,subindexObject,mapping_index)
00220     if currentNbMappedObjects >= currentMaxObjects:
00221         raise ValueError, """!!! Abort mapping object (defined at index 0x%04X, subIndex 0x%02X)
00222 in PDO index 0x%04X. max objects (%d) reached."""%(IndexObject,subIndexObject,mapping_index,pdo[mapping_index]["maxObjects"])
00223     if currentBitsMapped + sizeInBitsObject > 64:
00224         raise ValueError, """!!! Abort mapping object (defined at index 0x%04X, subIndex 0x%02X)
00225 in PDO index 0x%04X. No room to put %d bits in the PDO."""%(IndexObject,subIndexObject,mapping_index,sizeInBitsObject)
00226 
00227     value = eval("0x%04X%02X%02X"%(indexObject,subIndexObject,sizeInBitsObject))
00228     Node.SetEntry(mapping_index, currentNbMappedObjects + 1, value)
00229     
00230     currentNbMappedObjects += 1
00231     currentBitsMapped += sizeInBitsObject
00232 
00233 #-------------------------------------------------------------------------------
00234 #                    Creation of mapped variable and table 
00235 #-------------------------------------------------------------------------------
00236 
00237 def startMappedVariable(attrs):
00238     name = attrs["name"]
00239     index = eval(attrs["index"])
00240     subIndex = eval(attrs["sub_index"])
00241     
00242     if "size_in_bits" in attrs:
00243         size = eval(attrs["size_in_bits"]) # Numeric variable
00244         if "type" in attrs:
00245             type = attrs["type"]
00246             if (type == "UNS"):
00247                 type = "UNSIGNED"
00248         else: # Default type
00249             type = "UNSIGNED"
00250         typename = "%s%d"%(type,size)
00251 
00252         type_index = Manager.GetTypeIndex(typename, False)
00253         if type_index == None:
00254             raise ValueError, """!!! ERROR : For variable "%s" at index 0x%04X, subindex 0x%02X : Unrecognized type : %s"""%(name,index,subIndex,typename)
00255         
00256         # Begin ValueRange support
00257         if "min_value" in attrs or "max_value" in attrs:
00258             if "min_value" in attrs and "max_value" in attrs:
00259                 minValue = eval(attrs["min_value"])
00260                 maxValue = eval(attrs["max_value"])
00261                 if (minValue > maxValue):
00262                     raise ValueError, """!!! ERROR : For variable "%s" at index 0x%04X, subindex 0x%02X : error in value-range : min > max"""%(name,index,subIndex)
00263             else:
00264                 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)
00265         
00266             type_index = findRangeType(type_index, minValue, maxValue)
00267             if type_index == None:
00268                 raise ValueError, """!!! Sorry, too many different value range have been defined"""
00269         # End ValueRange support    
00270 
00271     if "size_in_byte" in attrs:
00272         size = eval(attrs["size_in_byte"]) # String variable
00273         type_index = findStringType(Manager.GetTypeIndex("VISIBLE_STRING", False), size)
00274         if type_index == None:
00275             raise ValueError, """!!! Sorry, too many different string length have been defined"""
00276           
00277     if "access" in attrs:
00278         access = attrs["access"].lower()
00279     else: 
00280         access = "rw" # default value
00281  
00282     if index < 0x2000 or index > 0xBFFF:
00283         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)
00284 
00285     if subIndex == 0:
00286         Node.AddMappingEntry(index, name = name, struct = 1)
00287     elif subIndex == 1:
00288         Node.AddMappingEntry(index, struct = 3)
00289         Node.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})    
00290     result = Node.AddMappingEntry(index, subIndex, values = {"name" : name, "type" : type_index, "access" : access, "pdo" : True})
00291     
00292     if result:
00293         Node.AddEntry(index, subIndex, 0)
00294     else:
00295         raise ValueError, """!!! ERROR : For variable "%s" at index 0x%04X, subindex 0x%02X : Unable to map"""%(name,index,subIndex)
00296 
00297 def startMappedTable(attrs):
00298     name = attrs["name"]
00299     number_elements = eval(attrs["number_elements"])
00300     index = eval(attrs["index"])
00301 
00302     if "size_in_bits" in attrs:
00303         size = eval(attrs["size_in_bits"]) # Numeric variable
00304         if "type" in attrs:
00305             type = attrs["type"]
00306             if (type == "UNS"):
00307                 type = "UNSIGNED"
00308         else: # Default type
00309             type = "UNSIGNED"
00310         typename = "%s%d"%(type,size)
00311 
00312         type_index = Manager.GetTypeIndex(typename, False)
00313         if type_index == None:
00314             raise ValueError, """!!! ERROR : For table \"%s\" at index 0x%04X : Unrecognized type : %s"""%(name,index,typename)
00315         
00316         # Begin ValueRange support
00317         if "min_value" in attrs or "max_value" in attrs:
00318             if "min_value" in attrs and "max_value" in attrs:
00319                 minValue = eval(attrs["min_value"])
00320                 maxValue = eval(attrs["max_value"])
00321                 if (minValue > maxValue):
00322                     raise ValueError, """!!! ERROR : For table \"%s\" at index 0x%04X : error in value-range : min > max"""%(name,index)
00323             else:
00324                 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)
00325         
00326             type_index = findRangeType(type_index, minValue, maxValue)
00327             if type_index == None:
00328                 raise ValueError, """!!! Sorry, too many different value range have been defined"""
00329         # End ValueRange support
00330 
00331     if "size_in_byte" in attrs:
00332         size = eval(attrs["size_in_byte"]) # String variable
00333         type_index = findStringType(Manager.GetTypeIndex("VISIBLE_STRING", False), size)
00334         if type_index == None:
00335             raise ValueError, """!!! Sorry, too many different string length have been defined"""
00336               
00337     if "access" in attrs:
00338         access = attrs["access"].lower()
00339     else:
00340         access = "rw" # default value    
00341 
00342     if index < 0x2000 or index > 0xBFFF:
00343         raise ValueError, """!!! ERROR : For table \"%s\" at index 0x%04X : Variable can't be defined using this index-subindex."""%(name,index)
00344 
00345     result = Node.AddMappingEntry(index, name = name, struct = 7)
00346     if not result:
00347         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)
00348     Node.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
00349     Node.AddMappingEntry(index, 1, values = {"name" : name, "type" : type_index, "access" : access, "pdo" : True, "nbmax" : number_elements})
00350     
00351     for subIndex in xrange(1,number_elements+1):
00352         Node.AddEntry(index, subIndex, 0)
00353 
00354 def findRangeType(type, minValue, maxValue):
00355     index = 0xA0
00356     while index < 0x100 and Node.IsEntry(index):
00357         current_type = Node.GetEntry(index, 1)
00358         if current_type == type:
00359             current_minValue = Node.GetEntry(index, 2)
00360             current_maxValue = Node.GetEntry(index, 3)
00361             if current_minValue == minValue and current_maxValue == maxValue:
00362                 return index
00363         index += 1
00364     if index < 0x100:
00365         infos = Manager.GetEntryInfos(type, False)
00366         name = "%s[%d-%d]"%(infos["name"], minValue, maxValue)
00367         Node.AddMappingEntry(index, name = name, struct = 3, size = infos["size"], default = infos["default"])
00368         Node.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
00369         Node.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
00370         Node.AddMappingEntry(index, 2, values = {"name" : "Minimum Value", "type" : type, "access" : "ro", "pdo" : False})
00371         Node.AddMappingEntry(index, 3, values = {"name" : "Maximum Value", "type" : type, "access" : "ro", "pdo" : False})
00372         Node.AddEntry(index, 1, type)
00373         Node.AddEntry(index, 2, minValue)
00374         Node.AddEntry(index, 3, maxValue)
00375         return index
00376     return None
00377 
00378 def findStringType(type, length):
00379     index = 0xA0
00380     while index < 0x100 and Node.IsEntry(index):
00381         current_type = Node.GetEntry(index, 1)
00382         if current_type == type:
00383             current_length = Node.GetEntry(index, 2)
00384             if current_length == length:
00385                 return index
00386         index += 1
00387     if index < 0x100:
00388         infos = Manager.GetEntryInfos(type, False)
00389         name = "%s%d"%(Manager.GetTypeName(type), length)
00390         Node.AddMappingEntry(index, name = name, struct = 3, size = infos["size"], default = infos["default"])
00391         Node.AddMappingEntry(index, 0, values = {"name" : "Number of Entries", "type" : 0x02, "access" : "ro", "pdo" : False})
00392         Node.AddMappingEntry(index, 1, values = {"name" : "Type", "type" : 0x02, "access" : "ro", "pdo" : False})
00393         Node.AddMappingEntry(index, 2, values = {"name" : "Length", "type" : 0x02, "access" : "ro", "pdo" : False})
00394         Node.AddEntry(index, 1, type)
00395         Node.AddEntry(index, 2, length)
00396         return index
00397     return None
00398 
00399 #-------------------------------------------------------------------------------
00400 #                   Creation HeartBeat Producer & Consumers
00401 #-------------------------------------------------------------------------------
00402 
00403 def heartBeatProducer():
00404     Node.AddEntry(0x1017, 0, 0)
00405     
00406 def startHeartBeatConsumers(attrs):
00407     nombre = eval(attrs["nombre"])
00408     for i in xrange(nombre):
00409         Node.AddEntry(0x1016, i + 1, 0)             
00410 
00411 #-------------------------------------------------------------------------------
00412 #                       Creation of SDO Server & Clients
00413 #-------------------------------------------------------------------------------
00414 
00415 def sdoServer():
00416     Node.AddEntry(0x1200, 1, 0x600 + Node.GetNodeID())
00417     Node.AddEntry(0x1200, 2, 0x580 + Node.GetNodeID())
00418     
00419 def startSdoClients(attrs):
00420     nombre = eval(attrs["nombre"])
00421     for i in xrange(nombre):
00422         Node.AddEntry(0x1280 + i, 1, 0x600)
00423         Node.AddEntry(0x1280 + i, 2, 0x580)
00424         Node.AddEntry(0x1280 + i, 3, 0)
00425     
00426 #-------------------------------------------------------------------------------
00427 #                           Parse file with Saxe
00428 #-------------------------------------------------------------------------------
00429 
00430 def ParseFile(filepath):
00431     xmlfile = open(filepath,"r")
00432     Parser = expat.ParserCreate()
00433     Parser.StartElementHandler = StartElement
00434     Parser.EndElementHandler = EndElement
00435     Parser.CharacterDataHandler = CharacterData
00436     ParserStatus = Parser.ParseFile(xmlfile)
00437     xmlfile.close()    
00438 
00439 def GenerateNode(filepath, manager):
00440     global Node
00441     global Manager
00442     Manager = manager
00443     Node = node.Node()
00444     ParseFile(filepath)
00445     return Node
00446 
00447 #-------------------------------------------------------------------------------
00448 #                             Main Function
00449 #-------------------------------------------------------------------------------
00450 
00451 if __name__ == '__main__':
00452     ParseFile("test.xml")
00453 

Generated on Mon Jun 4 16:29:06 2007 for CanFestival by  doxygen 1.5.1