diff -r 6787754b251b -r b6572d0336c3 doc/doxygen/html/eds__utils_8py-source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/doxygen/html/eds__utils_8py-source.html Mon Jun 04 17:59:50 2007 +0200 @@ -0,0 +1,758 @@ + +
+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 +