objdictgen/eds_utils.py
changeset 182 988f2b302aa6
child 205 dac0f9b4e3f8
equal deleted inserted replaced
181:44d812a41d49 182:988f2b302aa6
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of CanFestival, a library implementing CanOpen Stack. 
       
     5 #
       
     6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
       
     7 #
       
     8 #See COPYING file for copyrights details.
       
     9 #
       
    10 #This library is free software; you can redistribute it and/or
       
    11 #modify it under the terms of the GNU Lesser General Public
       
    12 #License as published by the Free Software Foundation; either
       
    13 #version 2.1 of the License, or (at your option) any later version.
       
    14 #
       
    15 #This library is distributed in the hope that it will be useful,
       
    16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    18 #Lesser General Public License for more details.
       
    19 #
       
    20 #You should have received a copy of the GNU Lesser General Public
       
    21 #License along with this library; if not, write to the Free Software
       
    22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    23 
       
    24 
       
    25 import node
       
    26 from sets import *
       
    27 from types import *
       
    28 from time import *
       
    29 import os,re
       
    30 
       
    31 # Regular expression for finding index section names
       
    32 index_model = re.compile('([0-9a-fA-F]{1,4})')
       
    33 # Regular expression for finding subindex section names
       
    34 subindex_model = re.compile('([0-9a-fA-F]{1,4})sub([0-9a-fA-F]{1,2})')
       
    35 
       
    36 # Dictionary for quickly translate boolean into integer value
       
    37 BOOL_TRANSLATE = {True : "1", False : "0"}
       
    38 
       
    39 # Function for verifying data values
       
    40 is_integer = lambda x: type(x) == IntType
       
    41 is_string = lambda x: type(x) == StringType
       
    42 
       
    43 # Define checking of value for each attribute
       
    44 ENTRY_ATTRIBUTES = {"SUBNUMBER" : is_integer, "PARAMETERNAME" : is_string, 
       
    45                     "OBJECTTYPE" : lambda x: x in (7, 8, 9), "DATATYPE" : is_integer, 
       
    46                     "LOWLIMIT" : is_integer, "HIGHLIMIT" : is_integer,
       
    47                     "ACCESSTYPE" : lambda x: x in ["ro","wo", "rw", "rwr", "rww", "const"],
       
    48                     "DEFAULTVALUE" : lambda x: True, "PDOMAPPING" : lambda x: x in (0, 1),
       
    49                     "OBJFLAGS" : is_integer}
       
    50 
       
    51 # Define entry parameters by entry ObjectType number
       
    52 ENTRY_TYPES = {7 : {"name" : " VAR",
       
    53                     "require" : ["PARAMETERNAME", "OBJECTTYPE", "DATATYPE", "ACCESSTYPE", "PDOMAPPING"],
       
    54                     "optional" : ["LOWLIMIT", "HIGHLIMIT", "DEFAULTVALUE", "OBJFLAGS"]},
       
    55                8 : {"name" : "n ARRAY",
       
    56                     "require" : ["SUBNUMBER", "PARAMETERNAME", "OBJECTTYPE"],
       
    57                     "optional" : ["OBJFLAGS"]},
       
    58                9 : {"name" : " RECORD",
       
    59                     "require" : ["SUBNUMBER", "PARAMETERNAME", "OBJECTTYPE"],
       
    60                     "optional" : ["OBJFLAGS"]}}
       
    61 
       
    62 
       
    63 # Function that search into Node Mappings the informations about an index or a subindex
       
    64 # and return the default value
       
    65 def GetDefaultValue(index, subIndex = None):
       
    66     infos = Manager.GetEntryInfos(index, Node)
       
    67     if infos["struct"] & node.OD_MultipleSubindexes:
       
    68         # First case entry is a record
       
    69         if infos["struct"] & node.OD_IdenticalSubindexes:
       
    70             subentry_infos = Manager.GetSubentryInfos(index, 1, Node)
       
    71         # Second case entry is an array
       
    72         else:
       
    73             subentry_infos = Manager.GetSubentryInfos(index, subIndex, Node)
       
    74         # If a default value is defined for this subindex, returns it
       
    75         if "default" in subentry_infos:
       
    76             return subentry_infos["default"]
       
    77         # If not, returns the default value for the subindex type
       
    78         else:
       
    79             return Manager.GetTypeDefaultValue(subentry_infos["type"], Node)
       
    80     # Third case entry is a var
       
    81     else:
       
    82         subentry_infos = Manager.GetSubentryInfos(index, 0, Node)
       
    83         # If a default value is defined for this subindex, returns it
       
    84         if "default" in subentry_infos:
       
    85             return subentry_infos["default"]
       
    86         # If not, returns the default value for the subindex type
       
    87         else:
       
    88             return Manager.GetTypeDefaultValue(subentry_infos["type"], Node)
       
    89     return None
       
    90 
       
    91 
       
    92 #-------------------------------------------------------------------------------
       
    93 #                               Parse file
       
    94 #-------------------------------------------------------------------------------
       
    95 
       
    96 
       
    97 # List of section names that are not index and subindex and that we can meet in
       
    98 # an EDS file
       
    99 SECTION_KEYNAMES = ["FILEINFO", "DEVICEINFO", "DUMMYUSAGE", "COMMENTS", 
       
   100                     "MANDATORYOBJECTS", "OPTIONALOBJECTS", "MANUFACTUREROBJECTS"]
       
   101 
       
   102 
       
   103 # Function that parse an EDS file and returns a dictionary of the informations
       
   104 def ParseFile(filepath):
       
   105     eds_dict = {}
       
   106     # Read file text
       
   107     eds_file = open(filepath,'r').read()
       
   108     sections = [(blocktuple[0],                # EntryName : Assignements dict
       
   109                  blocktuple[-1].splitlines())  # all the lines
       
   110                  for blocktuple in [           # Split the eds files into
       
   111                  block.split("]")              # (EntryName,Assignements) tuple
       
   112                  for block in                  # for each blocks staring with '['
       
   113                  eds_file.split("[")]
       
   114                  if blocktuple[0].isalnum()]   # if EntryName exists
       
   115     
       
   116     # Parse assignments for each section
       
   117     for section_name, assignments in sections:
       
   118         # Reset values of entry
       
   119         values = {}
       
   120         
       
   121         # Search if the section name match an index or subindex expression
       
   122         index_result = index_model.match(section_name)
       
   123         subindex_result = subindex_model.match(section_name)
       
   124         
       
   125         # Compilation of the EDS information dictionary
       
   126         
       
   127         is_entry = False
       
   128         # First case, section name is in SECTION_KEYNAMES 
       
   129         if section_name.upper() in SECTION_KEYNAMES:
       
   130             # Verify that entry is not already defined
       
   131             if section_name.upper() not in eds_dict:
       
   132                 eds_dict[section_name.upper()] = values
       
   133             else:
       
   134                 raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
       
   135         # Second case, section name is a subindex name 
       
   136         elif subindex_result:
       
   137             # Extract index and subindex number
       
   138             index, subindex = [int(value, 16) for value in subindex_result.groups()]
       
   139             # If index hasn't been referenced before, we add an entry into the dictionary
       
   140             # that will be updated later
       
   141             if index not in eds_dict:
       
   142                 eds_dict[index] = {"subindexes" : {}}
       
   143             if subindex not in eds_dict[index]["subindexes"]:
       
   144                 eds_dict[index]["subindexes"][subindex] = values
       
   145             else:
       
   146                 raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
       
   147             is_entry = True
       
   148         # Third case, section name is an index name 
       
   149         elif index_result:
       
   150             # Extract index number
       
   151             index = int(index_result.groups()[0], 16)
       
   152             # If index hasn't been referenced before, we add an entry into the dictionary
       
   153             if index not in eds_dict:
       
   154                 eds_dict[index] = values
       
   155                 eds_dict[index]["subindexes"] = {}
       
   156             elif eds_dict[index].keys() == ["subindexes"]:
       
   157                 values["subindexes"] = eds_dict[index]["subindexes"]
       
   158                 eds_dict[index] = values
       
   159             else:
       
   160                 raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
       
   161             is_entry = True
       
   162         # In any other case, there is a syntax problem into EDS file
       
   163         else:
       
   164             raise SyntaxError, "Section \"[%s]\" is unrecognized"%section_name
       
   165         
       
   166         for assignment in assignments:
       
   167             # Escape any comment
       
   168             if assignment.startswith(";"):
       
   169                 pass
       
   170             # Verify that line is a valid assignment
       
   171             elif assignment.find('=') > 0:
       
   172                 # Split assignment into the two values keyname and value
       
   173                 try:
       
   174                     keyname, value = assignment.split("=")
       
   175                 except:
       
   176                     raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip()
       
   177                 # keyname must be immediately followed by the "=" sign, so we
       
   178                 # verify that there is no whitespace into keyname
       
   179                 if keyname.isalnum():
       
   180                     # value can be preceded and followed by whitespaces, so we escape them
       
   181                     value = value.strip()
       
   182                     # First case, value starts with "$NODEID", then it's a formula
       
   183                     if value.startswith("$NODEID"):
       
   184                         try:
       
   185                             computed_value = int(value.replace("$NODEID+", ""), 16)
       
   186                         except:
       
   187                             raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   188                     # Second case, value starts with "0x", then it's an hexadecimal value
       
   189                     elif value.startswith("0x"):
       
   190                         try:
       
   191                             computed_value = int(value, 16)
       
   192                         except:
       
   193                             raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   194                     elif value.isdigit():
       
   195                         # Third case, value is a number and starts with "0", then it's an octal value
       
   196                         if value.startswith("0"):
       
   197                             computed_value = int(value, 8)
       
   198                         # Forth case, value is a number and don't start with "0", then it's a decimal value
       
   199                         else:
       
   200                             computed_value = int(value)
       
   201                     # In any other case, we keep string value
       
   202                     else:
       
   203                         computed_value = value
       
   204                     
       
   205                     # Add value to values dictionary
       
   206                     if computed_value != "":
       
   207                         # If entry is an index or a subindex
       
   208                         if is_entry:
       
   209                             # Verify that keyname is a possible attribute
       
   210                             if keyname.upper() not in ENTRY_ATTRIBUTES:
       
   211                                 raise SyntaxError, "Keyname \"%s\" not recognised for section \"[%s]\""%(keyname, section_name)
       
   212                             # Verify that value is valid
       
   213                             elif not ENTRY_ATTRIBUTES[keyname.upper()](computed_value):
       
   214                                 raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
       
   215                             else:
       
   216                                 values[keyname.upper()] = computed_value
       
   217                         else:
       
   218                             values[keyname.upper()] = computed_value
       
   219             # All lines that are not empty and are neither a comment neither not a valid assignment
       
   220             elif assignment.strip() != "":
       
   221                 raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip()
       
   222         
       
   223         # If entry is an index or a subindex
       
   224         if is_entry:
       
   225             # Verify that entry has an ObjectType
       
   226             if "OBJECTTYPE" in values.keys():
       
   227                 # Extract entry ObjectType
       
   228                 objecttype = values["OBJECTTYPE"]
       
   229                 # Extract parameters defined
       
   230                 keys = Set(values.keys())
       
   231                 keys.discard("subindexes")
       
   232                 # Extract possible parameters and parameters required
       
   233                 possible = Set(ENTRY_TYPES[objecttype]["require"] + ENTRY_TYPES[objecttype]["optional"])
       
   234                 required = Set(ENTRY_TYPES[objecttype]["require"])
       
   235                 # Verify that parameters defined contains all the parameters required
       
   236                 if not keys.issuperset(required):
       
   237                     missing = required.difference(keys)._data.keys()
       
   238                     if len(missing) > 1:
       
   239                         attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in missing])
       
   240                     else:
       
   241                         attributes = "Attribute \"%s\" is"%missing[0]
       
   242                     raise SyntaxError, "Error on section \"[%s]\":\n%s required for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"])
       
   243                 # Verify that parameters defined are all in the possible parameters
       
   244                 if not keys.issubset(possible):
       
   245                     unsupported = keys.difference(possible)._data.keys()
       
   246                     if len(unsupported) > 1:
       
   247                         attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in unsupported])
       
   248                     else:
       
   249                         attributes = "Attribute \"%s\" is"%unsupported[0]
       
   250                     raise SyntaxError, "Error on section \"[%s]\":\n%s unsupported for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"])
       
   251             else:
       
   252                 raise SyntaxError, "Error on section \"[%s]\":\nAttribute OBJECTTYPE is required"%section_name
       
   253         
       
   254     return eds_dict
       
   255 
       
   256 
       
   257 # Function that write an EDS file after generate it's content
       
   258 def WriteFile(filepath, content):
       
   259     # Open file in write mode
       
   260     cfile = open(filepath,"w")
       
   261     # Write content
       
   262     cfile.write(content)
       
   263     # Close file
       
   264     cfile.close()
       
   265 
       
   266 
       
   267 # Function that generate the EDS file content for the current node in the manager
       
   268 def GenerateFileContent(filepath):
       
   269     # Dictionary of each index contents
       
   270     indexContents = {}
       
   271     
       
   272     # Extract local time
       
   273     current_time = localtime()
       
   274     # Extract node informations
       
   275     nodename, nodeid, nodetype, description = Manager.GetCurrentNodeInfos()
       
   276     
       
   277     # Compiling lists of indexes defined
       
   278     entries = [idx for name, idx in Manager.GetCurrentValidIndexes(0, 0xFFFF)]
       
   279     
       
   280     # Generate FileInfo section
       
   281     fileContent = "[FileInfo]\n"
       
   282     fileContent += "CreatedBy=CANFestival\n"
       
   283     fileContent += "Description=%s\n"%description
       
   284     fileContent += "CreationTime=%s"%strftime("%I:%M", current_time)
       
   285     # %p option of strftime seems not working, then generate AM/PM by hands
       
   286     if strftime("%I", current_time) == strftime("%H", current_time):
       
   287         fileContent += "AM\n"
       
   288     else:
       
   289         fileContent += "PM\n"
       
   290     fileContent += "CreationDate=%s\n"%strftime("%m-%d-%Y", current_time)
       
   291     fileContent += "FileName=%s\n"%os.path.split(filepath)[-1]
       
   292     fileContent += "FileVersion=1\n"
       
   293     fileContent += "FileRevision=1\n"
       
   294     fileContent += "EDSVersion=3.0\n"
       
   295     
       
   296     # Generate DeviceInfo section
       
   297     fileContent += "\n[DeviceInfo]\n"
       
   298     fileContent += "VendorName=CANFestival\n"
       
   299     # Use information typed by user in Identity entry
       
   300     fileContent += "VendorNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 1)
       
   301     fileContent += "ProductName=%s\n"%nodename
       
   302     fileContent += "ProductNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 2)
       
   303     fileContent += "RevisionNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 3)
       
   304     # CANFestival support all baudrates as soon as driver choosen support them
       
   305     fileContent += "BaudRate_10=1\n"
       
   306     fileContent += "BaudRate_20=1\n"
       
   307     fileContent += "BaudRate_50=1\n"
       
   308     fileContent += "BaudRate_125=1\n"
       
   309     fileContent += "BaudRate_250=1\n"
       
   310     fileContent += "BaudRate_500=1\n"
       
   311     fileContent += "BaudRate_800=1\n"
       
   312     fileContent += "BaudRate_1000=1\n"
       
   313     # Select BootUp type from the informations given by user
       
   314     fileContent += "SimpleBootUpMaster=%s\n"%BOOL_TRANSLATE[nodetype == "master"]
       
   315     fileContent += "SimpleBootUpSlave=%s\n"%BOOL_TRANSLATE[nodetype == "slave"]
       
   316     # CANFestival characteristics
       
   317     fileContent += "Granularity=8\n"
       
   318     fileContent += "DynamicChannelsSupported=0\n"
       
   319     fileContent += "CompactPDO=0\n"
       
   320     fileContent += "GroupMessaging=0\n"
       
   321     # Calculate receive and tranmit PDO numbers with the entry available
       
   322     fileContent += "NrOfRXPDO=%d\n"%len([idx for idx in entries if 0x1400 <= idx <= 0x15FF])
       
   323     fileContent += "NrOfTXPDO=%d\n"%len([idx for idx in entries if 0x1400 <= idx <= 0x15FF])
       
   324     # LSS not supported as soon as DS-302 was not fully implemented
       
   325     fileContent += "LSS_Supported=0\n"
       
   326     
       
   327     # Generate Dummy Usage section
       
   328     fileContent += "\n[DummyUsage]\n"
       
   329     fileContent += "Dummy0001=0\n"
       
   330     fileContent += "Dummy0002=1\n"
       
   331     fileContent += "Dummy0003=1\n"
       
   332     fileContent += "Dummy0004=1\n"
       
   333     fileContent += "Dummy0005=1\n"
       
   334     fileContent += "Dummy0006=1\n"
       
   335     fileContent += "Dummy0007=1\n"
       
   336 
       
   337     # Generate Comments section
       
   338     fileContent += "\n[Comments]\n"
       
   339     fileContent += "Lines=0\n"
       
   340     
       
   341     # List of entry by type (Mandatory, Optional or Manufacturer
       
   342     mandatories = []
       
   343     optionals = []
       
   344     manufacturers = []
       
   345     
       
   346     # For each entry, we generate the entry section or sections if there is subindexes
       
   347     for entry in entries:
       
   348         # Extract infos and values for the entry
       
   349         entry_infos = Manager.GetEntryInfos(entry)
       
   350         values = Manager.GetCurrentEntry(entry)
       
   351         # Define section name
       
   352         text = "\n[%X]\n"%entry
       
   353         # If there is only one value, it's a VAR entry
       
   354         if type(values) != ListType:
       
   355             # Extract the informations of the first subindex
       
   356             subentry_infos = Manager.GetSubentryInfos(entry, 0)
       
   357             # Generate EDS informations for the entry
       
   358             text += "ParameterName=%s\n"%subentry_infos["name"]
       
   359             text += "ObjectType=0x7\n"
       
   360             text += "DataType=0x%4.4X\n"%subentry_infos["type"]
       
   361             text += "AccessType=%s\n"%subentry_infos["access"]
       
   362             text += "DefaultValue=%s\n"%values
       
   363             text += "PDOMapping=%s\n"%BOOL_TRANSLATE[subentry_infos["pdo"]]
       
   364         else:
       
   365             # Generate EDS informations for the entry
       
   366             text += "ParameterName=%s\n"%entry_infos["name"]
       
   367             if entry_infos["struct"] & node.OD_IdenticalSubindexes:
       
   368                 text += "ObjectType=0x9\n"
       
   369             else:
       
   370                 text += "ObjectType=0x8\n"
       
   371             
       
   372             # Generate EDS informations for subindexes of the entry in a separate text
       
   373             subtext = ""
       
   374             # Reset number of subindex defined 
       
   375             nb_subentry = 0
       
   376             for subentry, value in enumerate(values):
       
   377                 # Extract the informations of each subindex
       
   378                 subentry_infos = Manager.GetSubentryInfos(entry, subentry)
       
   379                 # If entry is not for the compatibility, generate informations for subindex
       
   380                 if subentry_infos["name"] != "Compatibility Entry":
       
   381                     subtext += "\n[%Xsub%X]\n"%(entry, subentry)
       
   382                     subtext += "ParameterName=%s\n"%subentry_infos["name"]
       
   383                     subtext += "ObjectType=0x7\n"
       
   384                     subtext += "DataType=0x%4.4X\n"%subentry_infos["type"]
       
   385                     subtext += "AccessType=%s\n"%subentry_infos["access"]
       
   386                     subtext += "DefaultValue=%s\n"%value
       
   387                     subtext += "PDOMapping=%s\n"%BOOL_TRANSLATE[subentry_infos["pdo"]]
       
   388                     # Increment number of subindex defined 
       
   389                     nb_subentry += 1
       
   390             # Write number of subindex defined for the entry
       
   391             text += "SubNumber=%d\n"%nb_subentry
       
   392             # Write subindex definitions
       
   393             text += subtext
       
   394         
       
   395         # Then we add the entry in the right list
       
   396         
       
   397         # First case, entry is between 0x2000 and 0x5FFF, then it's a manufacturer entry
       
   398         if 0x2000 <= entry <= 0x5FFF:
       
   399             manufacturers.append(entry)
       
   400         # Second case, entry is required, then it's a mandatory entry
       
   401         elif entry_infos["need"]:
       
   402             mandatories.append(entry)
       
   403         # In any other case, it's an optional entry
       
   404         else:
       
   405             optionals.append(entry)
       
   406         # Save text of the entry in the dictiionary of contents
       
   407         indexContents[entry] = text
       
   408     
       
   409     # Before generate File Content we sort the entry list
       
   410     manufacturers.sort()
       
   411     mandatories.sort()
       
   412     optionals.sort()
       
   413     
       
   414     # Generate Definition of mandatory objects
       
   415     fileContent += "\n[MandatoryObjects]\n"
       
   416     fileContent += "SupportedObjects=%d\n"%len(mandatories)
       
   417     for idx, entry in enumerate(mandatories):
       
   418         fileContent += "%d=0x%4.4X\n"%(idx, entry)
       
   419     # Write mandatory entries
       
   420     for entry in mandatories:
       
   421         fileContent += indexContents[entry]
       
   422     
       
   423     # Generate Definition of optional objects
       
   424     fileContent += "\n[OptionalObjects]\n"
       
   425     fileContent += "SupportedObjects=%d\n"%len(optionals)
       
   426     for idx, entry in enumerate(optionals):
       
   427         fileContent += "%d=0x%4.4X\n"%(idx, entry)
       
   428     # Write optional entries
       
   429     for entry in optionals:
       
   430         fileContent += indexContents[entry]
       
   431 
       
   432     # Generate Definition of manufacturer objects
       
   433     fileContent += "\n[ManufacturerObjects]\n"
       
   434     fileContent += "SupportedObjects=%d\n"%len(manufacturers)
       
   435     for idx, entry in enumerate(manufacturers):
       
   436         fileContent += "%d=0x%4.4X\n"%(idx, entry)
       
   437     # Write manufacturer entries
       
   438     for entry in manufacturers:
       
   439         fileContent += indexContents[entry]
       
   440     
       
   441     # Return File Content
       
   442     return fileContent
       
   443 
       
   444 
       
   445 # Function that generates EDS file from current node edited
       
   446 def GenerateEDSFile(filepath, manager):
       
   447     global Manager
       
   448     Manager = manager
       
   449     try:
       
   450         # Generate file content
       
   451         content = GenerateFileContent(filepath)
       
   452         # Write file
       
   453         WriteFile(filepath, content)
       
   454         return None
       
   455     except ValueError, message:
       
   456         return "Unable to generate EDS file\n%s"%message
       
   457     
       
   458 
       
   459 # Function that generates Node from an EDS file
       
   460 def GenerateNode(filepath, manager, cwd):
       
   461     global Node
       
   462     global Manager
       
   463     Manager = manager
       
   464     # Create a new node
       
   465     Node = node.Node()
       
   466     try:
       
   467         # Parse file and extract dictionary of EDS entry
       
   468         eds_dict = ParseFile(filepath)
       
   469         # Extract Profile Number from Device Type entry
       
   470         ProfileNb = eds_dict[0x1000]["DEFAULTVALUE"] & 0x0000ffff
       
   471         # If profile is not DS-301 or DS-302
       
   472         if ProfileNb not in [301, 302]:
       
   473             # Compile Profile name and path to .prf file
       
   474             ProfileName = "DS-%d"%ProfileNb
       
   475             ProfilePath = os.path.join(cwd, "config/%s.prf"%ProfileName)
       
   476             # Verify that profile is available
       
   477             if os.path.isfile(ProfilePath):
       
   478                 try:
       
   479                     # Load Profile
       
   480                     execfile(ProfilePath)
       
   481                     Node.SetProfileName(ProfileName)
       
   482                     Node.SetProfile(Mapping)
       
   483                     Node.SetSpecificMenu(AddMenuEntries)
       
   484                 except:
       
   485                     pass
       
   486         # Read all entries in the EDS dictionary 
       
   487         for entry, values in eds_dict.items():
       
   488             # All sections with a name in keynames are escaped
       
   489             if entry in SECTION_KEYNAMES:
       
   490                 pass
       
   491             else:
       
   492                 # Extract informations for the entry
       
   493                 entry_infos = Manager.GetEntryInfos(entry, Node)
       
   494                 
       
   495                 # If no informations are available, then we write them
       
   496                 if not entry_infos:
       
   497                     # First case, entry is a VAR
       
   498                     if values["OBJECTTYPE"] == 7:
       
   499                         # Add mapping for entry
       
   500                         Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1)
       
   501                         # Add mapping for first subindex
       
   502                         Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"], 
       
   503                                                                  "type" : values["DATATYPE"], 
       
   504                                                                  "access" : values["ACCESSTYPE"], 
       
   505                                                                  "pdo" : values["PDOMAPPING"] == 1})
       
   506                     # Second case, entry is an ARRAY
       
   507                     elif values["OBJECTTYPE"] == 8:
       
   508                         # Extract maximum subindex number defined
       
   509                         try:
       
   510                             max_subindex = values["subindexes"][0]["DEFAULTVALUE"]
       
   511                         except:
       
   512                             raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY entry"%entry
       
   513                         # Add mapping for entry
       
   514                         Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 3)
       
   515                         # Add mapping for first subindex
       
   516                         Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
       
   517                         # Add mapping for other subindexes
       
   518                         for subindex in xrange(1, int(max_subindex) + 1):
       
   519                             # if subindex is defined
       
   520                             if subindex in values["subindexes"]:
       
   521                                 Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"], 
       
   522                                                                                 "type" : values["subindexes"][subindex]["DATATYPE"], 
       
   523                                                                                 "access" : values["subindexes"][subindex]["ACCESSTYPE"], 
       
   524                                                                                 "pdo" : values["subindexes"][subindex]["PDOMAPPING"] == 1})
       
   525                             # if not, we add a mapping for compatibility 
       
   526                             else:
       
   527                                 Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False})
       
   528                     # Third case, entry is an RECORD
       
   529                     elif values["OBJECTTYPE"] == 9:
       
   530                         # Verify that the first subindex is defined
       
   531                         if 0 not in values["subindexes"]:
       
   532                             raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for a RECORD entry"%entry
       
   533                         # Add mapping for entry
       
   534                         Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 7)
       
   535                         # Add mapping for first subindex
       
   536                         Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
       
   537                         # Verify that second subindex is defined
       
   538                         if 1 in values:
       
   539                             Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]", 
       
   540                                                                      "type" : values["subindexes"][1]["DATATYPE"], 
       
   541                                                                      "access" : values["subindexes"][1]["ACCESSTYPE"], 
       
   542                                                                      "pdo" : values["subindexes"][1]["PDOMAPPING"] == 1})
       
   543                         else:
       
   544                             raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry
       
   545                 
       
   546                 # Define entry for the new node
       
   547                 
       
   548                 # First case, entry is a VAR
       
   549                 if values["OBJECTTYPE"] == 7:
       
   550                     # Take default value if it is defined
       
   551                     if "DEFAULTVALUE" in values:
       
   552                         value = values["DEFAULTVALUE"]
       
   553                     # Find default value for value type of the entry
       
   554                     else:
       
   555                         value = GetDefaultValue(entry)
       
   556                     Node.AddEntry(entry, 0, value)
       
   557                 # Second case, entry is an ARRAY or a RECORD
       
   558                 elif values["OBJECTTYPE"] in (8, 9):
       
   559                     # Verify that "Subnumber" attribute is defined and has a valid value
       
   560                     if "SUBNUMBER" in values and values["SUBNUMBER"] > 0:
       
   561                         # Extract maximum subindex number defined
       
   562                         try:
       
   563                             max_subindex = values["subindexes"][0]["DEFAULTVALUE"]
       
   564                         except:
       
   565                             raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry
       
   566                         # Define value for all subindexes except the first 
       
   567                         for subindex in xrange(1, int(max_subindex) + 1):
       
   568                             # Take default value if it is defined and entry is defined
       
   569                             if subindex in values["subindexes"] and "DEFAULTVALUE" in values["subindexes"][subindex]:
       
   570                                 value = values["subindexes"][subindex]["DEFAULTVALUE"]
       
   571                             # Find default value for value type of the subindex
       
   572                             else:
       
   573                                 value = GetDefaultValue(entry, subindex)
       
   574                             Node.AddEntry(entry, subindex, value)
       
   575                     else:
       
   576                         raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry
       
   577         return Node
       
   578     except SyntaxError, message:
       
   579         return "Unable to import EDS File\n%s"%message
       
   580 
       
   581 #-------------------------------------------------------------------------------
       
   582 #                             Main Function
       
   583 #-------------------------------------------------------------------------------
       
   584 
       
   585 if __name__ == '__main__':
       
   586     print ParseFile("examples/PEAK MicroMod.eds")
       
   587