diff -r 2cb34a4ac65a -r 6b5a4c21e061 doc/doxygen/html/eds__utils_8py-source.html --- a/doc/doxygen/html/eds__utils_8py-source.html Tue Jun 05 17:34:33 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,758 +0,0 @@ - -
-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 -00025 import node -00026 from node import nosub, var, array, rec, plurivar, pluriarray, plurirec -00027 from sets import * -00028 from types import * -00029 from time import * -00030 import os,re -00031 -00032 # Regular expression for finding index section names -00033 index_model = re.compile('([0-9A-F]{1,4})') -00034 # Regular expression for finding subindex section names -00035 subindex_model = re.compile('([0-9A-F]{1,4})SUB([0-9A-F]{1,2})') -00036 -00037 # Regular expression for finding NodeXPresent keynames -00038 nodepresent_model = re.compile('NODE([0-9]{1,3})PRESENT') -00039 # Regular expression for finding NodeXName keynames -00040 nodename_model = re.compile('NODE([0-9]{1,3})NAME') -00041 # Regular expression for finding NodeXDCFName keynames -00042 nodedcfname_model = re.compile('NODE([0-9]{1,3})DCFNAME') -00043 -00044 # Dictionary for quickly translate boolean into integer value -00045 BOOL_TRANSLATE = {True : "1", False : "0"} -00046 -00047 # Dictionary for quickly translate eds access value into canfestival access value -00048 ACCESS_TRANSLATE = {"ro" : "ro", "wo" : "wo", "rw" : "rw", "rwr" : "rw", "rww" : "rw", "const" : "ro"} -00049 -00050 # Function for verifying data values -00051 is_integer = lambda x: type(x) in (IntType, LongType) -00052 is_string = lambda x: type(x) in (StringType, UnicodeType) -00053 is_boolean = lambda x: x in (0, 1) -00054 -00055 # Define checking of value for each attribute -00056 ENTRY_ATTRIBUTES = {"SUBNUMBER" : is_integer, "PARAMETERNAME" : is_string, -00057 "OBJECTTYPE" : lambda x: x in (7, 8, 9), "DATATYPE" : is_integer, -00058 "LOWLIMIT" : is_integer, "HIGHLIMIT" : is_integer, -00059 "ACCESSTYPE" : lambda x: x in ["ro","wo", "rw", "rwr", "rww", "const"], -00060 "DEFAULTVALUE" : lambda x: True, "PDOMAPPING" : is_boolean, -00061 "OBJFLAGS" : is_integer} -00062 -00063 # Define entry parameters by entry ObjectType number -00064 ENTRY_TYPES = {7 : {"name" : " VAR", -00065 "require" : ["PARAMETERNAME", "OBJECTTYPE", "DATATYPE", "ACCESSTYPE", "PDOMAPPING"], -00066 "optional" : ["LOWLIMIT", "HIGHLIMIT", "DEFAULTVALUE", "OBJFLAGS"]}, -00067 8 : {"name" : "n ARRAY", -00068 "require" : ["SUBNUMBER", "PARAMETERNAME", "OBJECTTYPE"], -00069 "optional" : ["OBJFLAGS"]}, -00070 9 : {"name" : " RECORD", -00071 "require" : ["SUBNUMBER", "PARAMETERNAME", "OBJECTTYPE"], -00072 "optional" : ["OBJFLAGS"]}} -00073 -00074 -00075 # Function that search into Node Mappings the informations about an index or a subindex -00076 # and return the default value -00077 def GetDefaultValue(index, subIndex = None): -00078 infos = Node.GetEntryInfos(index) -00079 if infos["struct"] & node.OD_MultipleSubindexes: -00080 # First case entry is a record -00081 if infos["struct"] & node.OD_IdenticalSubindexes: -00082 subentry_infos = Node.GetSubentryInfos(index, 1) -00083 # Second case entry is an array -00084 else: -00085 subentry_infos = Node.GetSubentryInfos(index, subIndex) -00086 # If a default value is defined for this subindex, returns it -00087 if "default" in subentry_infos: -00088 return subentry_infos["default"] -00089 # If not, returns the default value for the subindex type -00090 else: -00091 return Node.GetTypeDefaultValue(subentry_infos["type"]) -00092 # Third case entry is a var -00093 else: -00094 subentry_infos = Node.GetSubentryInfos(index, 0) -00095 # If a default value is defined for this subindex, returns it -00096 if "default" in subentry_infos: -00097 return subentry_infos["default"] -00098 # If not, returns the default value for the subindex type -00099 else: -00100 return Node.GetTypeDefaultValue(subentry_infos["type"]) -00101 return None -00102 -00103 -00104 #------------------------------------------------------------------------------- -00105 # Parse file -00106 #------------------------------------------------------------------------------- -00107 -00108 -00109 # List of section names that are not index and subindex and that we can meet in -00110 # an EDS file -00111 SECTION_KEYNAMES = ["FILEINFO", "DEVICEINFO", "DUMMYUSAGE", "COMMENTS", -00112 "MANDATORYOBJECTS", "OPTIONALOBJECTS", "MANUFACTUREROBJECTS"] -00113 -00114 -00115 # Function that extract sections from a file and returns a dictionary of the informations -00116 def ExtractSections(file): -00117 return [(blocktuple[0], # EntryName : Assignements dict -00118 blocktuple[-1].splitlines()) # all the lines -00119 for blocktuple in [ # Split the eds files into -00120 block.split("]") # (EntryName,Assignements) tuple -00121 for block in # for each blocks staring with '[' -00122 file.split("[")] -00123 if blocktuple[0].isalnum()] # if EntryName exists -00124 -00125 -00126 # Function that parse an CPJ file and returns a dictionary of the informations -00127 def ParseCPJFile(filepath): -00128 networks = [] -00129 # Read file text -00130 cpj_file = open(filepath,'r').read() -00131 sections = ExtractSections(cpj_file) -00132 # Parse assignments for each section -00133 for section_name, assignments in sections: -00134 -00135 # Verify that section name is TOPOLOGY -00136 if section_name.upper() in "TOPOLOGY": -00137 -00138 # Reset values for topology -00139 topology = {"Name" : "", "Nodes" : {}} -00140 -00141 for assignment in assignments: -00142 # Escape any comment -00143 if assignment.startswith(";"): -00144 pass -00145 # Verify that line is a valid assignment -00146 elif assignment.find('=') > 0: -00147 # Split assignment into the two values keyname and value -00148 # Verify that there is only one '=' character in the line -00149 try: -00150 keyname, value = assignment.split("=") -00151 except: -00152 raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip() -00153 -00154 # keyname must be immediately followed by the "=" sign, so we -00155 # verify that there is no whitespace into keyname -00156 if keyname.isalnum(): -00157 # value can be preceded and followed by whitespaces, so we escape them -00158 value = value.strip() -00159 -00160 # First case, value starts with "0x", then it's an hexadecimal value -00161 if value.startswith("0x"): -00162 try: -00163 computed_value = int(value, 16) -00164 except: -00165 raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00166 elif value.isdigit(): -00167 # Second case, value is a number and starts with "0", then it's an octal value -00168 if value.startswith("0"): -00169 computed_value = int(value, 8) -00170 # Third case, value is a number and don't start with "0", then it's a decimal value -00171 else: -00172 computed_value = int(value) -00173 # In any other case, we keep string value -00174 else: -00175 computed_value = value -00176 -00177 # Search if the section name match any cpj expression -00178 nodepresent_result = nodepresent_model.match(keyname.upper()) -00179 nodename_result = nodename_model.match(keyname.upper()) -00180 nodedcfname_result = nodedcfname_model.match(keyname.upper()) -00181 -00182 if keyname.upper() == "NETNAME": -00183 if not is_string(computed_value): -00184 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00185 topology["Name"] = computed_value -00186 elif keyname.upper() == "NODES": -00187 if not is_integer(computed_value): -00188 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00189 topology["Number"] = computed_value -00190 elif keyname.upper() == "EDSBASENAME": -00191 if not is_string(computed_value): -00192 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00193 topology["Path"] = computed_value -00194 elif nodepresent_result: -00195 if not is_boolean(computed_value): -00196 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00197 nodeid = int(nodepresent_result.groups()[0]) -00198 if nodeid not in topology["Nodes"].keys(): -00199 topology["Nodes"][nodeid] = {} -00200 topology["Nodes"][nodeid]["Present"] = computed_value -00201 elif nodename_result: -00202 if not is_string(value): -00203 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00204 nodeid = int(nodename_result.groups()[0]) -00205 if nodeid not in topology["Nodes"].keys(): -00206 topology["Nodes"][nodeid] = {} -00207 topology["Nodes"][nodeid]["Name"] = computed_value -00208 elif nodedcfname_result: -00209 if not is_string(computed_value): -00210 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00211 nodeid = int(nodedcfname_result.groups()[0]) -00212 if nodeid not in topology["Nodes"].keys(): -00213 topology["Nodes"][nodeid] = {} -00214 topology["Nodes"][nodeid]["DCFName"] = computed_value -00215 else: -00216 raise SyntaxError, "Keyname \"%s\" not recognised for section \"[%s]\""%(keyname, section_name) -00217 -00218 # All lines that are not empty and are neither a comment neither not a valid assignment -00219 elif assignment.strip() != "": -00220 raise SyntaxError, "\"%s\" is not a valid CPJ line"%assignment.strip() -00221 -00222 if "Number" not in topology.keys(): -00223 raise SyntaxError, "\"Nodes\" keyname in \"[%s]\" section is missing"%section_name -00224 -00225 if topology["Number"] != len(topology["Nodes"]): -00226 raise SyntaxError, "\"Nodes\" value not corresponding to number of nodes defined" -00227 -00228 for nodeid, node in topology["Nodes"].items(): -00229 if "Present" not in node.keys(): -00230 raise SyntaxError, "\"Node%dPresent\" keyname in \"[%s]\" section is missing"%(nodeid, section_name) -00231 -00232 networks.append(topology) -00233 -00234 # In other case, there is a syntax problem into CPJ file -00235 else: -00236 raise SyntaxError, "Section \"[%s]\" is unrecognized"%section_name -00237 -00238 return networks -00239 -00240 # Function that parse an EDS file and returns a dictionary of the informations -00241 def ParseEDSFile(filepath): -00242 eds_dict = {} -00243 # Read file text -00244 eds_file = open(filepath,'r').read() -00245 sections = ExtractSections(eds_file) -00246 -00247 # Parse assignments for each section -00248 for section_name, assignments in sections: -00249 # Reset values of entry -00250 values = {} -00251 -00252 # Search if the section name match an index or subindex expression -00253 index_result = index_model.match(section_name.upper()) -00254 subindex_result = subindex_model.match(section_name.upper()) -00255 -00256 # Compilation of the EDS information dictionary -00257 -00258 is_entry = False -00259 # First case, section name is in SECTION_KEYNAMES -00260 if section_name.upper() in SECTION_KEYNAMES: -00261 # Verify that entry is not already defined -00262 if section_name.upper() not in eds_dict: -00263 eds_dict[section_name.upper()] = values -00264 else: -00265 raise SyntaxError, "\"[%s]\" section is defined two times"%section_name -00266 # Second case, section name is a subindex name -00267 elif subindex_result: -00268 # Extract index and subindex number -00269 index, subindex = [int(value, 16) for value in subindex_result.groups()] -00270 # If index hasn't been referenced before, we add an entry into the dictionary -00271 # that will be updated later -00272 if index not in eds_dict: -00273 eds_dict[index] = {"subindexes" : {}} -00274 if subindex not in eds_dict[index]["subindexes"]: -00275 eds_dict[index]["subindexes"][subindex] = values -00276 else: -00277 raise SyntaxError, "\"[%s]\" section is defined two times"%section_name -00278 is_entry = True -00279 # Third case, section name is an index name -00280 elif index_result: -00281 # Extract index number -00282 index = int(index_result.groups()[0], 16) -00283 # If index hasn't been referenced before, we add an entry into the dictionary -00284 if index not in eds_dict: -00285 eds_dict[index] = values -00286 eds_dict[index]["subindexes"] = {} -00287 elif eds_dict[index].keys() == ["subindexes"]: -00288 values["subindexes"] = eds_dict[index]["subindexes"] -00289 eds_dict[index] = values -00290 else: -00291 raise SyntaxError, "\"[%s]\" section is defined two times"%section_name -00292 is_entry = True -00293 # In any other case, there is a syntax problem into EDS file -00294 else: -00295 raise SyntaxError, "Section \"[%s]\" is unrecognized"%section_name -00296 -00297 for assignment in assignments: -00298 # Escape any comment -00299 if assignment.startswith(";"): -00300 pass -00301 # Verify that line is a valid assignment -00302 elif assignment.find('=') > 0: -00303 # Split assignment into the two values keyname and value -00304 # Verify that there is only one '=' character in the line -00305 try: -00306 keyname, value = assignment.split("=") -00307 except: -00308 raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip() -00309 # keyname must be immediately followed by the "=" sign, so we -00310 # verify that there is no whitespace into keyname -00311 if keyname.isalnum(): -00312 # value can be preceded and followed by whitespaces, so we escape them -00313 value = value.strip() -00314 # First case, value starts with "$NODEID", then it's a formula -00315 if value.startswith("$NODEID"): -00316 try: -00317 test = int(value.replace("$NODEID+", ""), 16) -00318 computed_value = value.replace("$NODEID", "self.ID") -00319 except: -00320 raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00321 # Second case, value starts with "0x", then it's an hexadecimal value -00322 elif value.startswith("0x"): -00323 try: -00324 computed_value = int(value, 16) -00325 except: -00326 raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00327 elif value.isdigit(): -00328 # Third case, value is a number and starts with "0", then it's an octal value -00329 if value.startswith("0"): -00330 computed_value = int(value, 8) -00331 # Forth case, value is a number and don't start with "0", then it's a decimal value -00332 else: -00333 computed_value = int(value) -00334 # In any other case, we keep string value -00335 else: -00336 computed_value = value -00337 -00338 # Add value to values dictionary -00339 if computed_value != "": -00340 # If entry is an index or a subindex -00341 if is_entry: -00342 # Verify that keyname is a possible attribute -00343 if keyname.upper() not in ENTRY_ATTRIBUTES: -00344 raise SyntaxError, "Keyname \"%s\" not recognised for section \"[%s]\""%(keyname, section_name) -00345 # Verify that value is valid -00346 elif not ENTRY_ATTRIBUTES[keyname.upper()](computed_value): -00347 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name) -00348 else: -00349 values[keyname.upper()] = computed_value -00350 else: -00351 values[keyname.upper()] = computed_value -00352 # All lines that are not empty and are neither a comment neither not a valid assignment -00353 elif assignment.strip() != "": -00354 raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip() -00355 -00356 # If entry is an index or a subindex -00357 if is_entry: -00358 # Verify that entry has an ObjectType -00359 if "OBJECTTYPE" in values.keys(): -00360 # Extract entry ObjectType -00361 objecttype = values["OBJECTTYPE"] -00362 # Extract parameters defined -00363 keys = Set(values.keys()) -00364 keys.discard("subindexes") -00365 # Extract possible parameters and parameters required -00366 possible = Set(ENTRY_TYPES[objecttype]["require"] + ENTRY_TYPES[objecttype]["optional"]) -00367 required = Set(ENTRY_TYPES[objecttype]["require"]) -00368 # Verify that parameters defined contains all the parameters required -00369 if not keys.issuperset(required): -00370 missing = required.difference(keys)._data.keys() -00371 if len(missing) > 1: -00372 attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in missing]) -00373 else: -00374 attributes = "Attribute \"%s\" is"%missing[0] -00375 raise SyntaxError, "Error on section \"[%s]\":\n%s required for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"]) -00376 # Verify that parameters defined are all in the possible parameters -00377 if not keys.issubset(possible): -00378 unsupported = keys.difference(possible)._data.keys() -00379 if len(unsupported) > 1: -00380 attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in unsupported]) -00381 else: -00382 attributes = "Attribute \"%s\" is"%unsupported[0] -00383 raise SyntaxError, "Error on section \"[%s]\":\n%s unsupported for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"]) -00384 else: -00385 raise SyntaxError, "Error on section \"[%s]\":\nAttribute OBJECTTYPE is required"%section_name -00386 -00387 return eds_dict -00388 -00389 -00390 # Function that write an EDS file after generate it's content -00391 def WriteFile(filepath, content): -00392 # Open file in write mode -00393 cfile = open(filepath,"w") -00394 # Write content -00395 cfile.write(content) -00396 # Close file -00397 cfile.close() -00398 -00399 -00400 # Function that generate the EDS file content for the current node in the manager -00401 def GenerateFileContent(filepath): -00402 # Dictionary of each index contents -00403 indexContents = {} -00404 -00405 # Extract local time -00406 current_time = localtime() -00407 # Extract node informations -00408 nodename, nodeid, nodetype, description = Manager.GetCurrentNodeInfos() -00409 -00410 # Compiling lists of indexes defined -00411 entries = [idx for name, idx in Manager.GetCurrentValidIndexes(0, 0xFFFF)] -00412 -00413 # Generate FileInfo section -00414 fileContent = "[FileInfo]\n" -00415 fileContent += "CreatedBy=CANFestival\n" -00416 fileContent += "Description=%s\n"%description -00417 fileContent += "CreationTime=%s"%strftime("%I:%M", current_time) -00418 # %p option of strftime seems not working, then generate AM/PM by hands -00419 if strftime("%I", current_time) == strftime("%H", current_time): -00420 fileContent += "AM\n" -00421 else: -00422 fileContent += "PM\n" -00423 fileContent += "CreationDate=%s\n"%strftime("%m-%d-%Y", current_time) -00424 fileContent += "FileName=%s\n"%os.path.split(filepath)[-1] -00425 fileContent += "FileVersion=1\n" -00426 fileContent += "FileRevision=1\n" -00427 fileContent += "EDSVersion=3.0\n" -00428 -00429 # Generate DeviceInfo section -00430 fileContent += "\n[DeviceInfo]\n" -00431 fileContent += "VendorName=CANFestival\n" -00432 # Use information typed by user in Identity entry -00433 fileContent += "VendorNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 1) -00434 fileContent += "ProductName=%s\n"%nodename -00435 fileContent += "ProductNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 2) -00436 fileContent += "RevisionNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 3) -00437 # CANFestival support all baudrates as soon as driver choosen support them -00438 fileContent += "BaudRate_10=1\n" -00439 fileContent += "BaudRate_20=1\n" -00440 fileContent += "BaudRate_50=1\n" -00441 fileContent += "BaudRate_125=1\n" -00442 fileContent += "BaudRate_250=1\n" -00443 fileContent += "BaudRate_500=1\n" -00444 fileContent += "BaudRate_800=1\n" -00445 fileContent += "BaudRate_1000=1\n" -00446 # Select BootUp type from the informations given by user -00447 fileContent += "SimpleBootUpMaster=%s\n"%BOOL_TRANSLATE[nodetype == "master"] -00448 fileContent += "SimpleBootUpSlave=%s\n"%BOOL_TRANSLATE[nodetype == "slave"] -00449 # CANFestival characteristics -00450 fileContent += "Granularity=8\n" -00451 fileContent += "DynamicChannelsSupported=0\n" -00452 fileContent += "CompactPDO=0\n" -00453 fileContent += "GroupMessaging=0\n" -00454 # Calculate receive and tranmit PDO numbers with the entry available -00455 fileContent += "NrOfRXPDO=%d\n"%len([idx for idx in entries if 0x1400 <= idx <= 0x15FF]) -00456 fileContent += "NrOfTXPDO=%d\n"%len([idx for idx in entries if 0x1800 <= idx <= 0x19FF]) -00457 # LSS not supported as soon as DS-302 was not fully implemented -00458 fileContent += "LSS_Supported=0\n" -00459 -00460 # Generate Dummy Usage section -00461 fileContent += "\n[DummyUsage]\n" -00462 fileContent += "Dummy0001=0\n" -00463 fileContent += "Dummy0002=1\n" -00464 fileContent += "Dummy0003=1\n" -00465 fileContent += "Dummy0004=1\n" -00466 fileContent += "Dummy0005=1\n" -00467 fileContent += "Dummy0006=1\n" -00468 fileContent += "Dummy0007=1\n" -00469 -00470 # Generate Comments section -00471 fileContent += "\n[Comments]\n" -00472 fileContent += "Lines=0\n" -00473 -00474 # List of entry by type (Mandatory, Optional or Manufacturer -00475 mandatories = [] -00476 optionals = [] -00477 manufacturers = [] -00478 -00479 # For each entry, we generate the entry section or sections if there is subindexes -00480 for entry in entries: -00481 # Extract infos and values for the entry -00482 entry_infos = Manager.GetEntryInfos(entry) -00483 values = Manager.GetCurrentEntry(entry) -00484 # Define section name -00485 text = "\n[%X]\n"%entry -00486 # If there is only one value, it's a VAR entry -00487 if type(values) != ListType: -00488 # Extract the informations of the first subindex -00489 subentry_infos = Manager.GetSubentryInfos(entry, 0) -00490 # Generate EDS informations for the entry -00491 text += "ParameterName=%s\n"%subentry_infos["name"] -00492 text += "ObjectType=0x7\n" -00493 text += "DataType=0x%4.4X\n"%subentry_infos["type"] -00494 text += "AccessType=%s\n"%subentry_infos["access"] -00495 text += "DefaultValue=%s\n"%values -00496 text += "PDOMapping=%s\n"%BOOL_TRANSLATE[subentry_infos["pdo"]] -00497 else: -00498 # Generate EDS informations for the entry -00499 text += "ParameterName=%s\n"%entry_infos["name"] -00500 if entry_infos["struct"] & node.OD_IdenticalSubindexes: -00501 text += "ObjectType=0x9\n" -00502 else: -00503 text += "ObjectType=0x8\n" -00504 -00505 # Generate EDS informations for subindexes of the entry in a separate text -00506 subtext = "" -00507 # Reset number of subindex defined -00508 nb_subentry = 0 -00509 for subentry, value in enumerate(values): -00510 # Extract the informations of each subindex -00511 subentry_infos = Manager.GetSubentryInfos(entry, subentry) -00512 # If entry is not for the compatibility, generate informations for subindex -00513 if subentry_infos["name"] != "Compatibility Entry": -00514 subtext += "\n[%Xsub%X]\n"%(entry, subentry) -00515 subtext += "ParameterName=%s\n"%subentry_infos["name"] -00516 subtext += "ObjectType=0x7\n" -00517 subtext += "DataType=0x%4.4X\n"%subentry_infos["type"] -00518 subtext += "AccessType=%s\n"%subentry_infos["access"] -00519 subtext += "DefaultValue=%s\n"%value -00520 subtext += "PDOMapping=%s\n"%BOOL_TRANSLATE[subentry_infos["pdo"]] -00521 # Increment number of subindex defined -00522 nb_subentry += 1 -00523 # Write number of subindex defined for the entry -00524 text += "SubNumber=%d\n"%nb_subentry -00525 # Write subindex definitions -00526 text += subtext -00527 -00528 # Then we add the entry in the right list -00529 -00530 # First case, entry is between 0x2000 and 0x5FFF, then it's a manufacturer entry -00531 if 0x2000 <= entry <= 0x5FFF: -00532 manufacturers.append(entry) -00533 # Second case, entry is required, then it's a mandatory entry -00534 elif entry_infos["need"]: -00535 mandatories.append(entry) -00536 # In any other case, it's an optional entry -00537 else: -00538 optionals.append(entry) -00539 # Save text of the entry in the dictiionary of contents -00540 indexContents[entry] = text -00541 -00542 # Before generate File Content we sort the entry list -00543 manufacturers.sort() -00544 mandatories.sort() -00545 optionals.sort() -00546 -00547 # Generate Definition of mandatory objects -00548 fileContent += "\n[MandatoryObjects]\n" -00549 fileContent += "SupportedObjects=%d\n"%len(mandatories) -00550 for idx, entry in enumerate(mandatories): -00551 fileContent += "%d=0x%4.4X\n"%(idx, entry) -00552 # Write mandatory entries -00553 for entry in mandatories: -00554 fileContent += indexContents[entry] -00555 -00556 # Generate Definition of optional objects -00557 fileContent += "\n[OptionalObjects]\n" -00558 fileContent += "SupportedObjects=%d\n"%len(optionals) -00559 for idx, entry in enumerate(optionals): -00560 fileContent += "%d=0x%4.4X\n"%(idx, entry) -00561 # Write optional entries -00562 for entry in optionals: -00563 fileContent += indexContents[entry] -00564 -00565 # Generate Definition of manufacturer objects -00566 fileContent += "\n[ManufacturerObjects]\n" -00567 fileContent += "SupportedObjects=%d\n"%len(manufacturers) -00568 for idx, entry in enumerate(manufacturers): -00569 fileContent += "%d=0x%4.4X\n"%(idx, entry) -00570 # Write manufacturer entries -00571 for entry in manufacturers: -00572 fileContent += indexContents[entry] -00573 -00574 # Return File Content -00575 return fileContent -00576 -00577 -00578 # Function that generates EDS file from current node edited -00579 def GenerateEDSFile(filepath, manager): -00580 global Manager -00581 Manager = manager -00582 try: -00583 # Generate file content -00584 content = GenerateFileContent(filepath) -00585 # Write file -00586 WriteFile(filepath, content) -00587 return None -00588 except ValueError, message: -00589 return "Unable to generate EDS file\n%s"%message -00590 -00591 # Function that generate the CPJ file content for the nodelist -00592 def GenerateCPJContent(nodelist): -00593 nodes = nodelist.SlaveNodes.keys() -00594 nodes.sort() -00595 -00596 fileContent = "[TOPOLOGY]\n" -00597 fileContent += "NetName=%s\n"%nodelist.GetNetworkName() -00598 fileContent += "Nodes=0x%2.2X\n"%len(nodes) -00599 -00600 for nodeid in nodes: -00601 fileContent += "Node%dPresent=0x01\n"%nodeid -00602 fileContent += "Node%dName=%s\n"%(nodeid, nodelist.SlaveNodes[nodeid]["Name"]) -00603 fileContent += "Node%dDCFName=%s\n"%(nodeid, nodelist.SlaveNodes[nodeid]["EDS"]) -00604 -00605 fileContent += "EDSBaseName=eds\n" -00606 return fileContent -00607 -00608 # Function that generates Node from an EDS file -00609 def GenerateNode(filepath, cwd, nodeID = 0): -00610 global Node -00611 # Create a new node -00612 Node = node.Node(id = nodeID) -00613 try: -00614 # Parse file and extract dictionary of EDS entry -00615 eds_dict = ParseEDSFile(filepath) -00616 # Extract Profile Number from Device Type entry -00617 ProfileNb = eds_dict[0x1000]["DEFAULTVALUE"] & 0x0000ffff -00618 # If profile is not DS-301 or DS-302 -00619 if ProfileNb not in [301, 302]: -00620 # Compile Profile name and path to .prf file -00621 ProfileName = "DS-%d"%ProfileNb -00622 ProfilePath = os.path.join(cwd, "config/%s.prf"%ProfileName) -00623 # Verify that profile is available -00624 if os.path.isfile(ProfilePath): -00625 try: -00626 # Load Profile -00627 execfile(ProfilePath) -00628 Node.SetProfileName(ProfileName) -00629 Node.SetProfile(Mapping) -00630 Node.SetSpecificMenu(AddMenuEntries) -00631 except: -00632 pass -00633 # Read all entries in the EDS dictionary -00634 for entry, values in eds_dict.items(): -00635 # All sections with a name in keynames are escaped -00636 if entry in SECTION_KEYNAMES: -00637 pass -00638 else: -00639 # Extract informations for the entry -00640 entry_infos = Node.GetEntryInfos(entry) -00641 -00642 # If no informations are available, then we write them -00643 if not entry_infos: -00644 # First case, entry is a VAR -00645 if values["OBJECTTYPE"] == 7: -00646 # Add mapping for entry -00647 Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1) -00648 # Add mapping for first subindex -00649 Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], -00650 "type" : values["DATATYPE"], -00651 "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"]], -00652 "pdo" : values["PDOMAPPING"] == 1}) -00653 # Second case, entry is an ARRAY -00654 elif values["OBJECTTYPE"] == 8: -00655 # Extract maximum subindex number defined -00656 try: -00657 max_subindex = values["subindexes"][0]["DEFAULTVALUE"] -00658 except: -00659 raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY entry"%entry -00660 # Add mapping for entry -00661 Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 3) -00662 # Add mapping for first subindex -00663 Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False}) -00664 # Add mapping for other subindexes -00665 for subindex in xrange(1, int(max_subindex) + 1): -00666 # if subindex is defined -00667 if subindex in values["subindexes"]: -00668 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], -00669 "type" : values["subindexes"][subindex]["DATATYPE"], -00670 "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"]], -00671 "pdo" : values["subindexes"][subindex]["PDOMAPPING"] == 1}) -00672 # if not, we add a mapping for compatibility -00673 else: -00674 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False}) -00675 # Third case, entry is an RECORD -00676 elif values["OBJECTTYPE"] == 9: -00677 # Verify that the first subindex is defined -00678 if 0 not in values["subindexes"]: -00679 raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for a RECORD entry"%entry -00680 # Add mapping for entry -00681 Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 7) -00682 # Add mapping for first subindex -00683 Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False}) -00684 # Verify that second subindex is defined -00685 if 1 in values: -00686 Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", -00687 "type" : values["subindexes"][1]["DATATYPE"], -00688 "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"]], -00689 "pdo" : values["subindexes"][1]["PDOMAPPING"] == 1}) -00690 else: -00691 raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry -00692 -00693 # Define entry for the new node -00694 -00695 # First case, entry is a VAR -00696 if values["OBJECTTYPE"] == 7: -00697 # Take default value if it is defined -00698 if "DEFAULTVALUE" in values: -00699 value = values["DEFAULTVALUE"] -00700 # Find default value for value type of the entry -00701 else: -00702 value = GetDefaultValue(entry) -00703 Node.AddEntry(entry, 0, value) -00704 # Second case, entry is an ARRAY or a RECORD -00705 elif values["OBJECTTYPE"] in (8, 9): -00706 # Verify that "Subnumber" attribute is defined and has a valid value -00707 if "SUBNUMBER" in values and values["SUBNUMBER"] > 0: -00708 # Extract maximum subindex number defined -00709 try: -00710 max_subindex = values["subindexes"][0]["DEFAULTVALUE"] -00711 except: -00712 raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry -00713 # Define value for all subindexes except the first -00714 for subindex in xrange(1, int(max_subindex) + 1): -00715 # Take default value if it is defined and entry is defined -00716 if subindex in values["subindexes"] and "DEFAULTVALUE" in values["subindexes"][subindex]: -00717 value = values["subindexes"][subindex]["DEFAULTVALUE"] -00718 # Find default value for value type of the subindex -00719 else: -00720 value = GetDefaultValue(entry, subindex) -00721 Node.AddEntry(entry, subindex, value) -00722 else: -00723 raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry -00724 return Node -00725 except SyntaxError, message: -00726 return "Unable to import EDS file\n%s"%message -00727 -00728 #------------------------------------------------------------------------------- -00729 # Main Function -00730 #------------------------------------------------------------------------------- -00731 -00732 if __name__ == '__main__': -00733 print ParseEDSFile("examples/PEAK MicroMod.eds") -00734 -