import os,re
# Regular expression for finding index section names
-index_model = re.compile('([0-9A-F]{1,4})')
+index_model = re.compile('([0-9A-F]{1,4}$)')
# Regular expression for finding subindex section names
-subindex_model = re.compile('([0-9A-F]{1,4})SUB([0-9A-F]{1,2})')
+subindex_model = re.compile('([0-9A-F]{1,4})SUB([0-9A-F]{1,2}$)')
+# Regular expression for finding index section names
+index_objectlinks_model = re.compile('([0-9A-F]{1,4}OBJECTLINKS$)')
# Regular expression for finding NodeXPresent keynames
-nodepresent_model = re.compile('NODE([0-9]{1,3})PRESENT')
+nodepresent_model = re.compile('NODE([0-9]{1,3})PRESENT$')
# Regular expression for finding NodeXName keynames
-nodename_model = re.compile('NODE([0-9]{1,3})NAME')
+nodename_model = re.compile('NODE([0-9]{1,3})NAME$')
# Regular expression for finding NodeXDCFName keynames
-nodedcfname_model = re.compile('NODE([0-9]{1,3})DCFNAME')
+nodedcfname_model = re.compile('NODE([0-9]{1,3})DCFNAME$')
# Dictionary for quickly translate boolean into integer value
BOOL_TRANSLATE = {True : "1", False : "0"}
# Dictionary for quickly translate eds access value into canfestival access value
-ACCESS_TRANSLATE = {"ro" : "ro", "wo" : "wo", "rw" : "rw", "rwr" : "rw", "rww" : "rw", "const" : "ro"}
+ACCESS_TRANSLATE = {"RO" : "ro", "WO" : "wo", "RW" : "rw", "RWR" : "rw", "RWW" : "rw", "CONST" : "ro"}
# Function for verifying data values
is_integer = lambda x: type(x) in (IntType, LongType)
ENTRY_ATTRIBUTES = {"SUBNUMBER" : is_integer, "PARAMETERNAME" : is_string,
"OBJECTTYPE" : lambda x: x in (7, 8, 9), "DATATYPE" : is_integer,
"LOWLIMIT" : is_integer, "HIGHLIMIT" : is_integer,
- "ACCESSTYPE" : lambda x: x in ["ro","wo", "rw", "rwr", "rww", "const"],
+ "ACCESSTYPE" : lambda x: x.upper() in ACCESS_TRANSLATE.keys(),
"DEFAULTVALUE" : lambda x: True, "PDOMAPPING" : is_boolean,
- "OBJFLAGS" : is_integer}
+ "OBJFLAGS" : is_integer, "PARAMETERVALUE" : lambda x: True,}
# Define entry parameters by entry ObjectType number
ENTRY_TYPES = {7 : {"name" : " VAR",
"require" : ["PARAMETERNAME", "DATATYPE", "ACCESSTYPE"],
- "optional" : ["OBJECTTYPE", "DEFAULTVALUE", "PDOMAPPING", "LOWLIMIT", "HIGHLIMIT", "OBJFLAGS"]},
+ "optional" : ["OBJECTTYPE", "DEFAULTVALUE", "PDOMAPPING", "LOWLIMIT", "HIGHLIMIT", "OBJFLAGS", "PARAMETERVALUE"]},
8 : {"name" : "n ARRAY",
"require" : ["PARAMETERNAME", "OBJECTTYPE", "SUBNUMBER"],
"optional" : ["OBJFLAGS"]},
# Function that search into Node Mappings the informations about an index or a subindex
# and return the default value
-def GetDefaultValue(index, subIndex = None):
+def GetDefaultValue(Node, index, subIndex = None):
infos = Node.GetEntryInfos(index)
if infos["struct"] & node.OD_MultipleSubindexes:
# First case entry is a record
# an EDS file
SECTION_KEYNAMES = ["FILEINFO", "DEVICEINFO", "DUMMYUSAGE", "COMMENTS",
"MANDATORYOBJECTS", "OPTIONALOBJECTS", "MANUFACTUREROBJECTS",
- "STANDARDDATATYPES"]
+ "STANDARDDATATYPES", "SUPPORTEDMODULES"]
# Function that extract sections from a file and returns a dictionary of the informations
# value can be preceded and followed by whitespaces, so we escape them
value = value.strip()
- # First case, value starts with "0x", then it's an hexadecimal value
- if value.startswith("0x"):
+ # First case, value starts with "0x" or "-0x", then it's an hexadecimal value
+ if value.startswith("0x") or value.startswith("-0x"):
try:
computed_value = int(value, 16)
except:
raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
- elif value.isdigit():
- # Second case, value is a number and starts with "0", then it's an octal value
- if value.startswith("0"):
+ elif value.isdigit() or value.startswith("-") and value[1:].isdigit():
+ # Second case, value is a number and starts with "0" or "-0", then it's an octal value
+ if value.startswith("0") or value.startswith("-0"):
computed_value = int(value, 8)
# Third case, value is a number and don't start with "0", then it's a decimal value
else:
# Search if the section name match an index or subindex expression
index_result = index_model.match(section_name.upper())
subindex_result = subindex_model.match(section_name.upper())
+ index_objectlinks_result = index_objectlinks_model.match(section_name.upper())
# Compilation of the EDS information dictionary
eds_dict[section_name.upper()] = values
else:
raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
- # Second case, section name is a subindex name
- elif subindex_result:
- # Extract index and subindex number
- index, subindex = [int(value, 16) for value in subindex_result.groups()]
- # If index hasn't been referenced before, we add an entry into the dictionary
- # that will be updated later
- if index not in eds_dict:
- eds_dict[index] = {"subindexes" : {}}
- if subindex not in eds_dict[index]["subindexes"]:
- eds_dict[index]["subindexes"][subindex] = values
- else:
- raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
- is_entry = True
- # Third case, section name is an index name
+ # Second case, section name is an index name
elif index_result:
# Extract index number
index = int(index_result.groups()[0], 16)
else:
raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
is_entry = True
+ # Third case, section name is a subindex name
+ elif subindex_result:
+ # Extract index and subindex number
+ index, subindex = [int(value, 16) for value in subindex_result.groups()]
+ # If index hasn't been referenced before, we add an entry into the dictionary
+ # that will be updated later
+ if index not in eds_dict:
+ eds_dict[index] = {"subindexes" : {}}
+ if subindex not in eds_dict[index]["subindexes"]:
+ eds_dict[index]["subindexes"][subindex] = values
+ else:
+ raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
+ is_entry = True
+ # Third case, section name is a subindex name
+ elif index_objectlinks_result:
+ pass
# In any other case, there is a syntax problem into EDS file
else:
raise SyntaxError, "Section \"[%s]\" is unrecognized"%section_name
except:
raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
# Second case, value starts with "0x", then it's an hexadecimal value
- elif value.startswith("0x"):
+ elif value.startswith("0x") or value.startswith("-0x"):
try:
computed_value = int(value, 16)
except:
raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
- elif value.isdigit():
+ elif value.isdigit() or value.startswith("-") and value[1:].isdigit():
# Third case, value is a number and starts with "0", then it's an octal value
- if value.startswith("0"):
+ if value.startswith("0") or value.startswith("-0"):
computed_value = int(value, 8)
# Forth case, value is a number and don't start with "0", then it's a decimal value
else:
attributes = "Attribute \"%s\" is"%unsupported[0]
raise SyntaxError, "Error on section \"[%s]\":\n%s unsupported for a%s entry"%(section_name, attributes, ENTRY_TYPES[objecttype]["name"])
+ if "PARAMETERVALUE" in values:
+ try:
+ if values["DATATYPE"] in (0x09, 0x0A, 0x0B, 0x0F):
+ values["PARAMETERVALUE"] = str(values["PARAMETERVALUE"])
+ elif values["DATATYPE"] in (0x08, 0x11):
+ values["PARAMETERVALUE"] = float(values["PARAMETERVALUE"])
+ elif values["DATATYPE"] == 0x01:
+ values["PARAMETERVALUE"] = {0 : False, 1 : True}[values["PARAMETERVALUE"]]
+ else:
+ if type(values["PARAMETERVALUE"]) != IntType and values["PARAMETERVALUE"].find("$NODEID") == -1:
+ raise
+ except:
+ raise SyntaxError, "Error on section \"[%s]\":\nParameterValue incompatible with DataType"%section_name
+
if "DEFAULTVALUE" in values:
try:
if values["DATATYPE"] in (0x09, 0x0A, 0x0B, 0x0F):
# Function that generate the EDS file content for the current node in the manager
-def GenerateFileContent(filepath):
+def GenerateFileContent(Node, filepath):
# Dictionary of each index contents
indexContents = {}
# Extract local time
current_time = localtime()
# Extract node informations
- nodename, nodeid, nodetype, description = Manager.GetCurrentNodeInfos()
+ nodename = Node.GetNodeName()
+ nodeid = Node.GetNodeID()
+ nodetype = Node.GetNodeType()
+ description = Node.GetNodeDescription()
- # Compiling lists of indexes defined
- entries = [idx for name, idx in Manager.GetCurrentValidIndexes(0, 0xFFFF)]
+ # Retreiving lists of indexes defined
+ entries = Node.GetIndexes()
# Generate FileInfo section
fileContent = "[FileInfo]\n"
fileContent += "\n[DeviceInfo]\n"
fileContent += "VendorName=CANFestival\n"
# Use information typed by user in Identity entry
- fileContent += "VendorNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 1)
+ fileContent += "VendorNumber=0x%8.8X\n"%Node.GetEntry(0x1018, 1)
fileContent += "ProductName=%s\n"%nodename
- fileContent += "ProductNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 2)
- fileContent += "RevisionNumber=0x%8.8X\n"%Manager.GetCurrentEntry(0x1018, 3)
+ fileContent += "ProductNumber=0x%8.8X\n"%Node.GetEntry(0x1018, 2)
+ fileContent += "RevisionNumber=0x%8.8X\n"%Node.GetEntry(0x1018, 3)
# CANFestival support all baudrates as soon as driver choosen support them
fileContent += "BaudRate_10=1\n"
fileContent += "BaudRate_20=1\n"
# For each entry, we generate the entry section or sections if there is subindexes
for entry in entries:
# Extract infos and values for the entry
- entry_infos = Manager.GetEntryInfos(entry)
- values = Manager.GetCurrentEntry(entry, compute = False)
+ entry_infos = Node.GetEntryInfos(entry)
+ values = Node.GetEntry(entry, compute = False)
# Define section name
text = "\n[%X]\n"%entry
# If there is only one value, it's a VAR entry
if type(values) != ListType:
# Extract the informations of the first subindex
- subentry_infos = Manager.GetSubentryInfos(entry, 0)
+ subentry_infos = Node.GetSubentryInfos(entry, 0)
# Generate EDS informations for the entry
text += "ParameterName=%s\n"%subentry_infos["name"]
text += "ObjectType=0x7\n"
text += "DataType=0x%4.4X\n"%subentry_infos["type"]
text += "AccessType=%s\n"%subentry_infos["access"]
- text += "DefaultValue=%s\n"%values
+ if subentry_infos["type"] == 1:
+ text += "DefaultValue=%s\n"%BOOL_TRANSLATE[values]
+ else:
+ text += "DefaultValue=%s\n"%values
text += "PDOMapping=%s\n"%BOOL_TRANSLATE[subentry_infos["pdo"]]
else:
# Generate EDS informations for the entry
nb_subentry = 0
for subentry, value in enumerate(values):
# Extract the informations of each subindex
- subentry_infos = Manager.GetSubentryInfos(entry, subentry)
+ subentry_infos = Node.GetSubentryInfos(entry, subentry)
# If entry is not for the compatibility, generate informations for subindex
if subentry_infos["name"] != "Compatibility Entry":
subtext += "\n[%Xsub%X]\n"%(entry, subentry)
subtext += "ObjectType=0x7\n"
subtext += "DataType=0x%4.4X\n"%subentry_infos["type"]
subtext += "AccessType=%s\n"%subentry_infos["access"]
- subtext += "DefaultValue=%s\n"%value
+ if subentry_infos["type"] == 1:
+ subtext += "DefaultValue=%s\n"%BOOL_TRANSLATE[value]
+ else:
+ subtext += "DefaultValue=%s\n"%value
subtext += "PDOMapping=%s\n"%BOOL_TRANSLATE[subentry_infos["pdo"]]
# Increment number of subindex defined
nb_subentry += 1
# Function that generates EDS file from current node edited
-def GenerateEDSFile(filepath, manager):
- global Manager
- Manager = manager
+def GenerateEDSFile(filepath, node):
try:
# Generate file content
- content = GenerateFileContent(filepath)
+ content = GenerateFileContent(node, filepath)
# Write file
WriteFile(filepath, content)
return None
# Function that generates Node from an EDS file
def GenerateNode(filepath, nodeID = 0):
- global Node
# Create a new node
Node = node.Node(id = nodeID)
try:
# Add mapping for first subindex
Node.AddMappingEntry(entry, 0, values = {"name" : values["PARAMETERNAME"],
"type" : values["DATATYPE"],
- "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"]],
+ "access" : ACCESS_TRANSLATE[values["ACCESSTYPE"].upper()],
"pdo" : values.get("PDOMAPPING", 0) == 1})
- # Second case, entry is an ARRAY
- elif values["OBJECTTYPE"] == 8:
+ # Second case, entry is an ARRAY or RECORD
+ elif values["OBJECTTYPE"] in [8, 9]:
# Extract maximum subindex number defined
try:
max_subindex = values["subindexes"][0]["DEFAULTVALUE"]
except:
- raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY entry"%entry
+ max_subindex = max(*values["subindexes"].keys())
+ #raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or RECORD entry"%entry
# Add mapping for entry
Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 3)
# Add mapping for first subindex
if subindex in values["subindexes"]:
Node.AddMappingEntry(entry, subindex, values = {"name" : values["subindexes"][subindex]["PARAMETERNAME"],
"type" : values["subindexes"][subindex]["DATATYPE"],
- "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"]],
+ "access" : ACCESS_TRANSLATE[values["subindexes"][subindex]["ACCESSTYPE"].upper()],
"pdo" : values["subindexes"][subindex].get("PDOMAPPING", 0) == 1})
# if not, we add a mapping for compatibility
else:
Node.AddMappingEntry(entry, subindex, values = {"name" : "Compatibility Entry", "type" : 0x05, "access" : "rw", "pdo" : False})
- # Third case, entry is an RECORD
- elif values["OBJECTTYPE"] == 9:
- # Verify that the first subindex is defined
- if 0 not in values["subindexes"]:
- raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for a RECORD entry"%entry
- # Add mapping for entry
- Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 7)
- # Add mapping for first subindex
- Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
- # Verify that second subindex is defined
- if 1 in values:
- Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]",
- "type" : values["subindexes"][1]["DATATYPE"],
- "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"]],
- "pdo" : values["subindexes"][1].get("PDOMAPPING", 0) == 1})
- else:
- raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry
+## # Third case, entry is an RECORD
+## elif values["OBJECTTYPE"] == 9:
+## # Verify that the first subindex is defined
+## if 0 not in values["subindexes"]:
+## raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for a RECORD entry"%entry
+## # Add mapping for entry
+## Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 7)
+## # Add mapping for first subindex
+## Node.AddMappingEntry(entry, 0, values = {"name" : "Number of Entries", "type" : 0x05, "access" : "ro", "pdo" : False})
+## # Verify that second subindex is defined
+## if 1 in values["subindexes"]:
+## Node.AddMappingEntry(entry, 1, values = {"name" : values["PARAMETERNAME"] + " %d[(sub)]",
+## "type" : values["subindexes"][1]["DATATYPE"],
+## "access" : ACCESS_TRANSLATE[values["subindexes"][1]["ACCESSTYPE"].upper()],
+## "pdo" : values["subindexes"][1].get("PDOMAPPING", 0) == 1,
+## "nbmax" : 0xFE})
+## else:
+## raise SyntaxError, "Error on entry 0x%4.4X:\nA RECORD entry must have at least 2 subindexes"%entry
# Define entry for the new node
# First case, entry is a VAR
if values["OBJECTTYPE"] == 7:
# Take default value if it is defined
- if "DEFAULTVALUE" in values:
+ if "PARAMETERVALUE" in values:
+ value = values["PARAMETERVALUE"]
+ elif "DEFAULTVALUE" in values:
value = values["DEFAULTVALUE"]
# Find default value for value type of the entry
else:
- value = GetDefaultValue(entry)
+ value = GetDefaultValue(Node, entry)
Node.AddEntry(entry, 0, value)
# Second case, entry is an ARRAY or a RECORD
elif values["OBJECTTYPE"] in (8, 9):
# Verify that "Subnumber" attribute is defined and has a valid value
if "SUBNUMBER" in values and values["SUBNUMBER"] > 0:
+ consecutive = False
# Extract maximum subindex number defined
try:
max_subindex = values["subindexes"][0]["DEFAULTVALUE"]
except:
- raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry
+ max_subindex = values["SUBNUMBER"] - 1
+ consecutive = True
+ #raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry
Node.AddEntry(entry, value = [])
# Define value for all subindexes except the first
for subindex in xrange(1, int(max_subindex) + 1):
# Take default value if it is defined and entry is defined
- if subindex in values["subindexes"] and "DEFAULTVALUE" in values["subindexes"][subindex]:
+ if subindex in values["subindexes"] and "PARAMETERVALUE" in values["subindexes"][subindex]:
+ value = values["subindexes"][subindex]["PARAMETERVALUE"]
+ elif subindex in values["subindexes"] and "DEFAULTVALUE" in values["subindexes"][subindex]:
value = values["subindexes"][subindex]["DEFAULTVALUE"]
# Find default value for value type of the subindex
+ elif subindex in values["subindexes"] or not consecutive:
+ value = GetDefaultValue(Node, entry, subindex)
else:
- value = GetDefaultValue(entry, subindex)
+ raise SyntaxError, "Error on entry 0x%4.4X:\nCan't recompose implemented subindexes in this ARRAY or RECORD entry"%entry
Node.AddEntry(entry, subindex, value)
else:
raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry