--- a/etherlab/EthercatMaster.py Tue Jun 25 00:55:38 2013 +0200
+++ b/etherlab/EthercatMaster.py Tue Sep 24 00:48:21 2013 +0200
@@ -1,6 +1,7 @@
-from xml.dom import minidom
+from copy import deepcopy @@ -81,14 +82,14 @@
#--------------------------------------------------
-EtherCATConfigClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd"))
+EtherCATConfigParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd")) if x["Index"] == y["Index"]:
return cmp(x["Subindex"], y["Subindex"])
return cmp(x["Index"], y["Index"])
-cls = EtherCATConfigClasses.get("Config_Slave", None)
+cls = EtherCATConfigParser.GetElementClass("Slave", "Config") @@ -152,12 +153,12 @@
def appendStartupCommand(self, command_infos):
InitCmds = self.getInitCmds(True)
- command = EtherCATConfigClasses["InitCmds_InitCmd"]()
+ command = EtherCATConfigParser.CreateElement("InitCmd", "InitCmds", 1) + InitCmds.appendInitCmd(command) command.setIndex(command_infos["Index"])
command.setSubIndex(command_infos["Subindex"])
command.setData(command_infos["Value"])
command.setComment(command_infos["Description"])
- InitCmds.appendInitCmd(command)
return len(InitCmds.getInitCmd()) - 1
setattr(cls, "appendStartupCommand", appendStartupCommand)
@@ -206,7 +207,7 @@
-ProcessVariablesClasses = GenerateClassesFromXSDstring(ProcessVariablesXSD)
+ProcessVariablesParser = GenerateParserFromXSDstring(ProcessVariablesXSD) @@ -218,29 +219,27 @@
config_filepath = self.ConfigFileName()
- self.Config = EtherCATConfigClasses["EtherCATConfig"]()
if os.path.isfile(config_filepath):
config_xmlfile = open(config_filepath, 'r')
- config_tree = minidom.parse(config_xmlfile)
+ self.Config = etree.fromstring( + config_xmlfile.read(), EtherCATConfigParser)
- for child in config_tree.childNodes:
- if child.nodeType == config_tree.ELEMENT_NODE and child.nodeName == "EtherCATConfig":
- self.Config.loadXMLTree(child)
+ self.Config = EtherCATConfigParser.CreateElement("EtherCATConfig") process_filepath = self.ProcessVariablesFileName()
- self.ProcessVariables = ProcessVariablesClasses["ProcessVariables"]()
if os.path.isfile(process_filepath):
process_xmlfile = open(process_filepath, 'r')
- process_tree = minidom.parse(process_xmlfile)
+ self.ProcessVariables = etree.fromstring( + process_xmlfile.read(), ProcessVariablesParser) + process_is_saved = True - for child in process_tree.childNodes:
- if child.nodeType == process_tree.ELEMENT_NODE and child.nodeName == "ProcessVariables":
- self.ProcessVariables.loadXMLTree(child)
- process_is_saved = True
+ self.ProcessVariables = ProcessVariablesParser.CreateElement("ProcessVariables") if config_is_saved and process_is_saved:
@@ -352,7 +351,7 @@
def SetProcessVariables(self, variables):
- variable = ProcessVariablesClasses["ProcessVariables_variable"]()
+ variable = ProcessVariablesParser.CreateElement("variable", "ProcessVariables") variable.setName(var["Name"])
variable.setComment(var["Description"])
if var["ReadFrom"] != "":
@@ -456,12 +455,12 @@
slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel())
- slave = EtherCATConfigClasses["Config_Slave"]()
+ slave = EtherCATConfigParser.CreateElement("Slave", "Config") + self.Config.getConfig().appendSlave(slave) slave_infos = slave.getInfo()
slave_infos.setName("undefined")
slave_infos.setPhysAddr(newConfNodeOpj.BaseParams.getIEC_Channel())
slave_infos.setAutoIncAddr(0)
- self.Config.getConfig().appendSlave(slave)
@@ -542,6 +541,7 @@
type_infos = slave.getType()
device, module_extra_params = self.GetModuleInfos(type_infos)
+ print "Get Entries List", limits entries = device.GetEntriesList(limits)
entries_list = entries.items()
@@ -647,23 +647,22 @@
def OnCTNSave(self, from_project_path=None):
config_filepath = self.ConfigFileName()
- config_text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
- config_extras = {"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
- "xsi:noNamespaceSchemaLocation" : "EtherCATInfo.xsd"}
- config_text += self.Config.generateXMLText("EtherCATConfig", 0, config_extras)
config_xmlfile = open(config_filepath,"w")
- config_xmlfile.write(config_text.encode("utf-8"))
+ config_xmlfile.write(etree.tostring( process_filepath = self.ProcessVariablesFileName()
- process_text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
- process_extras = {"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance"}
- process_text += self.ProcessVariables.generateXMLText("ProcessVariables", 0, process_extras)
process_xmlfile = open(process_filepath,"w")
- process_xmlfile.write(process_text.encode("utf-8"))
+ process_xmlfile.write(etree.tostring( self.Buffer.CurrentSaved()
@@ -751,13 +750,18 @@
Return a copy of the config
- return cPickle.loads(cPickle.dumps(model))
def CreateBuffer(self, saved):
- self.Buffer = UndoBuffer(cPickle.dumps((self.Config, self.ProcessVariables)), saved)
+ self.Buffer = UndoBuffer( + (EtherCATConfigParser.Dumps(self.Config), + ProcessVariablesParser.Dumps(self.ProcessVariables)), - self.Buffer.Buffering(cPickle.dumps((self.Config, self.ProcessVariables)))
+ (EtherCATConfigParser.Dumps(self.Config), + ProcessVariablesParser.Dumps(self.ProcessVariables))) if self.Buffer is not None:
@@ -766,10 +770,14 @@
- self.Config, self.ProcessVariables = cPickle.loads(self.Buffer.Previous())
+ config, process_variables = self.Buffer.Previous() + self.Config = EtherCATConfigParser.Loads(config) + self.ProcessVariables = ProcessVariablesParser.Loads(process_variables) - self.Config, self.ProcessVariables = cPickle.loads(self.Buffer.Next())
+ config, process_variables = self.Buffer.Next() + self.Config = EtherCATConfigParser.Loads(config) + self.ProcessVariables = ProcessVariablesParser.Loads(process_variables) def GetBufferState(self):
first = self.Buffer.IsFirst()
--- a/etherlab/etherlab.py Tue Jun 25 00:55:38 2013 +0200
+++ b/etherlab/etherlab.py Tue Sep 24 00:48:21 2013 +0200
@@ -1,5 +1,5 @@
-from xml.dom import minidom
@@ -13,81 +13,79 @@
from EthercatMaster import _EthercatCTN
from ConfigEditor import LibraryEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE
+ScriptDirectory = os.path.split(os.path.realpath(__file__))[0] #--------------------------------------------------
#--------------------------------------------------
-EtherCATInfoClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd"))
+EtherCATInfoParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) +EtherCATInfo_XPath = lambda xpath: etree.XPath(xpath) + return "#x%4.4X" % int(el.text) + if el.tag == "PDOMapping": +def extract_pdo_infos(pdo_infos): + pdo_infos.tag + " " + el.tag: extract_param(el) -cls = EtherCATInfoClasses["EtherCATBase.xsd"].get("DictionaryType", None)
- cls.loadXMLTreeArgs = None
- setattr(cls, "_loadXMLTree", getattr(cls, "loadXMLTree"))
+def HexDecValue(ctxt, values): + return str(ExtractHexDecValue(values[0])) +def EntryName(ctxt, values): + if element.tag == "Default": + return ExtractName(names, default) +class AddEntry(etree.XSLTExtension): + def __init__(self, entries): + etree.XSLTExtension.__init__(self) - def loadXMLTree(self, *args):
- self.loadXMLTreeArgs = args
- setattr(cls, "loadXMLTree", loadXMLTree)
+ def execute(self, context, self_node, input_node, output_parent): + infos = etree.Element('entry_infos') + self.process_children(context, infos) + lambda x: int(infos.find(x).text), + el.tag: extract_param(el) + for el in infos if el.tag != "PDO"} + if (index, subindex) != (0, 0): + entry_infos = self.Entries.get((index, subindex)) + if entry_infos is not None: + PDO_infos = infos.find("PDO") + if PDO_infos is not None: + entry_infos.update(extract_pdo_infos(PDO_infos)) + self.Entries[(index, subindex)] = new_entry_infos
- if self.loadXMLTreeArgs is not None:
- self._loadXMLTree(*self.loadXMLTreeArgs)
- self.loadXMLTreeArgs = None
- setattr(cls, "load", load)
+entries_list_xslt = etree.parse( + os.path.join(ScriptDirectory, "entries_list.xslt")) -cls = EtherCATInfoClasses["EtherCATInfo.xsd"].get("DeviceType", None)
+cls = EtherCATInfoParser.GetElementClass("DeviceType")
+ profile_numbers_xpath = EtherCATInfo_XPath("Profile/ProfileNo") def GetProfileNumbers(self):
- for profile in self.getProfile():
- profile_content = profile.getcontent()
- if profile_content is None:
- for content_element in profile_content["value"]:
- if content_element["name"] == "ProfileNo":
- profiles.append(content_element["value"])
+ return [number.text for number in profile_numbers_xpath(self)] setattr(cls, "GetProfileNumbers", GetProfileNumbers)
- def GetProfileDictionaries(self):
- for profile in self.getProfile():
- profile_content = profile.getcontent()
- if profile_content is None:
- for content_element in profile_content["value"]:
- if content_element["name"] == "Dictionary":
- dictionaries.append(content_element["value"])
- elif content_element["name"] == "DictionaryFile":
- raise ValueError, "DictionaryFile for defining Device Profile is not yet supported!"
- setattr(cls, "GetProfileDictionaries", GetProfileDictionaries)
- def ExtractDataTypes(self):
- for dictionary in self.GetProfileDictionaries():
- datatypes = dictionary.getDataTypes()
- if datatypes is not None:
- for datatype in datatypes.getDataType():
- content = datatype.getcontent()
- if content is not None and content["name"] == "SubItem":
- self.DataTypes[datatype.getName()] = datatype
- setattr(cls, "ExtractDataTypes", ExtractDataTypes)
mailbox = self.getMailbox()
@@ -96,78 +94,22 @@
setattr(cls, "getCoE", getCoE)
def GetEntriesList(self, limits=None):
- if self.DataTypes is None:
- self.ExtractDataTypes()
- for dictionary in self.GetProfileDictionaries():
- for object in dictionary.getObjects().getObject():
- entry_index = object.getIndex().getcontent()
- index = ExtractHexDecValue(entry_index)
- if limits is None or limits[0] <= index <= limits[1]:
- entry_type = object.getType()
- entry_name = ExtractName(object.getName())
- entry_type_infos = self.DataTypes.get(entry_type, None)
- if entry_type_infos is not None:
- content = entry_type_infos.getcontent()
- for subitem in content["value"]:
- entry_subidx = subitem.getSubIdx()
- if entry_subidx is None:
- subidx = ExtractHexDecValue(entry_subidx)
- subitem_pdomapping = ""
- subitem_flags = subitem.getFlags()
- if subitem_flags is not None:
- access = subitem_flags.getAccess()
- subitem_access = access.getcontent()
- pdomapping = subitem_flags.getPdoMapping()
- if pdomapping is not None:
- subitem_pdomapping = pdomapping.upper()
- entries[(index, subidx)] = {
- "SubIndex": entry_subidx,
- (entry_name.decode("utf-8"),
- ExtractName(subitem.getDisplayName(),
- subitem.getName()).decode("utf-8")),
- "Type": subitem.getType(),
- "BitSize": subitem.getBitSize(),
- "Access": subitem_access,
- "PDOMapping": subitem_pdomapping}
- entry_flags = object.getFlags()
- if entry_flags is not None:
- access = entry_flags.getAccess()
- entry_access = access.getcontent()
- pdomapping = entry_flags.getPdoMapping()
- if pdomapping is not None:
- entry_pdomapping = pdomapping.upper()
- entries[(index, 0)] = {
- "BitSize": object.getBitSize(),
- "Access": entry_access,
- "PDOMapping": entry_pdomapping}
- for TxPdo in self.getTxPdo():
- ExtractPdoInfos(TxPdo, "Transmit", entries, limits)
- for RxPdo in self.getRxPdo():
- ExtractPdoInfos(RxPdo, "Receive", entries, limits)
+ entries_list_xslt_tree = etree.XSLT( + entries_list_xslt, extensions = { + ("entries_list_ns", "add_entry"): AddEntry(entries), + ("entries_list_ns", "HexDecValue"): HexDecValue, + ("entries_list_ns", "EntryName"): EntryName}) + entries_list_xslt_tree(self, **dict(zip( + ["min_index", "max_index"], + map(lambda x: etree.XSLT.strparam(str(x)), + limits if limits is not None else [0x0000, 0xFFFF]) setattr(cls, "GetEntriesList", GetEntriesList)
def GetSyncManagers(self):
for sync_manager in self.getSm():
@@ -200,38 +142,6 @@
group["children"].sort(GroupItemCompare)
-def ExtractPdoInfos(pdo, pdo_type, entries, limits=None):
- pdo_index = pdo.getIndex().getcontent()
- pdo_name = ExtractName(pdo.getName())
- for pdo_entry in pdo.getEntry():
- entry_index = pdo_entry.getIndex().getcontent()
- entry_subindex = pdo_entry.getSubIndex()
- index = ExtractHexDecValue(entry_index)
- subindex = ExtractHexDecValue(entry_subindex)
- if limits is None or limits[0] <= index <= limits[1]:
- entry = entries.get((index, subindex), None)
- entry["PDO index"] = pdo_index
- entry["PDO name"] = pdo_name
- entry["PDO type"] = pdo_type
- entry_type = pdo_entry.getDataType()
- if entry_type is not None:
- if pdo_type == "Transmit":
- entries[(index, subindex)] = {
- "SubIndex": entry_subindex,
- "Name": ExtractName(pdo_entry.getName()),
- "Type": entry_type.getcontent(),
- "PDOMapping": pdomapping}
@@ -276,6 +186,8 @@
def GetModulesExtraParamsFilePath(self):
return os.path.join(self.Path, "modules_extra_params.cfg")
+ groups_xpath = EtherCATInfo_XPath("Descriptions/Groups/Group") + devices_xpath = EtherCATInfo_XPath("Descriptions/Devices/Device") @@ -283,37 +195,40 @@
filepath = os.path.join(self.Path, file)
if os.path.isfile(filepath) and os.path.splitext(filepath)[-1] == ".xml":
- xmlfile = open(filepath, 'r')
- xml_tree = minidom.parse(xmlfile)
+ self.modules_infos = None - self.modules_infos = None
- for child in xml_tree.childNodes:
- if child.nodeType == xml_tree.ELEMENT_NODE and child.nodeName == "EtherCATInfo":
- self.modules_infos = EtherCATInfoClasses["EtherCATInfo.xsd"]["EtherCATInfo"]()
- self.modules_infos.loadXMLTree(child)
+ xmlfile = open(filepath, 'r') + self.modules_infos = etree.fromstring( + xmlfile.read(), EtherCATInfoParser) if self.modules_infos is not None:
vendor = self.modules_infos.getVendor()
- vendor_category = self.Library.setdefault(ExtractHexDecValue(vendor.getId()),
- {"name": ExtractName(vendor.getName(), _("Miscellaneous")),
+ vendor_category = self.Library.setdefault( + ExtractHexDecValue(vendor.getId()), + {"name": ExtractName(vendor.getName(), _("Miscellaneous")), - for group in self.modules_infos.getDescriptions().getGroups().getGroup():
+ for group in self.groups_xpath(self.modules_infos): group_type = group.getType()
- vendor_category["groups"].setdefault(group_type, {"name": ExtractName(group.getName(), group_type),
- "parent": group.getParentGroup(),
- "order": group.getSortOrder(),
- "value": group.getcontent()["value"],
+ vendor_category["groups"].setdefault(group_type, + {"name": ExtractName(group.getName(), group_type), + "parent": group.getParentGroup(), + "order": group.getSortOrder(), + #"value": group.getcontent()["value"], - for device in self.modules_infos.getDescriptions().getDevices().getDevice():
+ for device in self.devices_xpath(self.modules_infos): device_group = device.getGroupType()
if not vendor_category["groups"].has_key(device_group):
raise ValueError, "Not such group \"%\"" % device_group
- vendor_category["groups"][device_group]["devices"].append((device.getType().getcontent(), device))
+ vendor_category["groups"][device_group]["devices"].append( + (device.getType().getcontent(), device)) @@ -464,8 +379,8 @@
CTNChildrenTypes = [("EthercatNode",_EthercatCTN,"Ethercat Master")]
EditorType = LibraryEditor
self.ModulesLibrary = None
self.LoadModulesLibrary()