etherlab/EthercatMaster.py
changeset 2157 a2385e535cf5
parent 2152 e6946c298a42
child 2160 75349c51a34b
equal deleted inserted replaced
2156:c8eee6be2da8 2157:a2385e535cf5
     1 import os
     1 import os
     2 import cPickle
     2 import cPickle
     3 from xml.dom import minidom
     3 from lxml import etree
       
     4 from copy import deepcopy
     4 
     5 
     5 import wx
     6 import wx
     6 
     7 
     7 from xmlclass import *
     8 from xmlclass import *
     8 
     9 
    79     
    80     
    80 #--------------------------------------------------
    81 #--------------------------------------------------
    81 #                 Ethercat MASTER
    82 #                 Ethercat MASTER
    82 #--------------------------------------------------
    83 #--------------------------------------------------
    83 
    84 
    84 EtherCATConfigClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd")) 
    85 EtherCATConfigParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd")) 
    85 
    86 
    86 def sort_commands(x, y):
    87 def sort_commands(x, y):
    87     if x["Index"] == y["Index"]:
    88     if x["Index"] == y["Index"]:
    88         return cmp(x["Subindex"], y["Subindex"])
    89         return cmp(x["Subindex"], y["Subindex"])
    89     return cmp(x["Index"], y["Index"])
    90     return cmp(x["Index"], y["Index"])
    90 
    91 
    91 cls = EtherCATConfigClasses.get("Config_Slave", None)
    92 cls = EtherCATConfigParser.GetElementClass("Slave", "Config")
    92 if cls:
    93 if cls:
    93     
    94     
    94     def getType(self):
    95     def getType(self):
    95         slave_info = self.getInfo()
    96         slave_info = self.getInfo()
    96         return {"device_type": slave_info.getName(),
    97         return {"device_type": slave_info.getName(),
   150         return commands
   151         return commands
   151     setattr(cls, "getStartupCommands", getStartupCommands)
   152     setattr(cls, "getStartupCommands", getStartupCommands)
   152     
   153     
   153     def appendStartupCommand(self, command_infos):
   154     def appendStartupCommand(self, command_infos):
   154         InitCmds = self.getInitCmds(True)
   155         InitCmds = self.getInitCmds(True)
   155         command = EtherCATConfigClasses["InitCmds_InitCmd"]()
   156         command = EtherCATConfigParser.CreateElement("InitCmd", "InitCmds", 1)
       
   157         InitCmds.appendInitCmd(command)
   156         command.setIndex(command_infos["Index"])
   158         command.setIndex(command_infos["Index"])
   157         command.setSubIndex(command_infos["Subindex"])
   159         command.setSubIndex(command_infos["Subindex"])
   158         command.setData(command_infos["Value"])
   160         command.setData(command_infos["Value"])
   159         command.setComment(command_infos["Description"])
   161         command.setComment(command_infos["Description"])
   160         InitCmds.appendInitCmd(command)
       
   161         return len(InitCmds.getInitCmd()) - 1
   162         return len(InitCmds.getInitCmd()) - 1
   162     setattr(cls, "appendStartupCommand", appendStartupCommand)
   163     setattr(cls, "appendStartupCommand", appendStartupCommand)
   163     
   164     
   164     def setStartupCommand(self, command_infos):
   165     def setStartupCommand(self, command_infos):
   165         InitCmds = self.getInitCmds()
   166         InitCmds = self.getInitCmds()
   204         <xsd:attribute name="SubIndex" type="xsd:integer" use="required"/>
   205         <xsd:attribute name="SubIndex" type="xsd:integer" use="required"/>
   205       </xsd:complexType>
   206       </xsd:complexType>
   206     </xsd:schema>
   207     </xsd:schema>
   207 """
   208 """
   208 
   209 
   209 ProcessVariablesClasses = GenerateClassesFromXSDstring(ProcessVariablesXSD) 
   210 ProcessVariablesParser = GenerateParserFromXSDstring(ProcessVariablesXSD) 
   210 
   211 
   211 class _EthercatCTN:
   212 class _EthercatCTN:
   212 
   213 
   213     CTNChildrenTypes = [("EthercatSlave", _EthercatSlaveCTN, "Ethercat Slave")]
   214     CTNChildrenTypes = [("EthercatSlave", _EthercatSlaveCTN, "Ethercat Slave")]
   214     if HAS_MCL:
   215     if HAS_MCL:
   216     EditorType = MasterEditor
   217     EditorType = MasterEditor
   217     
   218     
   218     def __init__(self):
   219     def __init__(self):
   219         config_filepath = self.ConfigFileName()
   220         config_filepath = self.ConfigFileName()
   220         config_is_saved = False
   221         config_is_saved = False
   221         self.Config = EtherCATConfigClasses["EtherCATConfig"]()
       
   222         if os.path.isfile(config_filepath):
   222         if os.path.isfile(config_filepath):
   223             config_xmlfile = open(config_filepath, 'r')
   223             config_xmlfile = open(config_filepath, 'r')
   224             config_tree = minidom.parse(config_xmlfile)
   224             self.Config = etree.fromstring(
       
   225                 config_xmlfile.read(), EtherCATConfigParser)
       
   226             config_is_saved = True
   225             config_xmlfile.close()
   227             config_xmlfile.close()
   226             
   228         
   227             for child in config_tree.childNodes:
   229         else:
   228                 if child.nodeType == config_tree.ELEMENT_NODE and child.nodeName == "EtherCATConfig":
   230             self.Config = EtherCATConfigParser.CreateElement("EtherCATConfig")
   229                     self.Config.loadXMLTree(child)
       
   230                     config_is_saved = True
       
   231         
   231         
   232         process_filepath = self.ProcessVariablesFileName()
   232         process_filepath = self.ProcessVariablesFileName()
   233         process_is_saved = False
   233         process_is_saved = False
   234         self.ProcessVariables = ProcessVariablesClasses["ProcessVariables"]()
       
   235         if os.path.isfile(process_filepath):
   234         if os.path.isfile(process_filepath):
   236             process_xmlfile = open(process_filepath, 'r')
   235             process_xmlfile = open(process_filepath, 'r')
   237             process_tree = minidom.parse(process_xmlfile)
   236             self.ProcessVariables = etree.fromstring(
       
   237                 process_xmlfile.read(), ProcessVariablesParser)
       
   238             process_is_saved = True
   238             process_xmlfile.close()
   239             process_xmlfile.close()
   239             
   240             
   240             for child in process_tree.childNodes:
   241         else:
   241                 if child.nodeType == process_tree.ELEMENT_NODE and child.nodeName == "ProcessVariables":
   242             self.ProcessVariables = ProcessVariablesParser.CreateElement("ProcessVariables")
   242                     self.ProcessVariables.loadXMLTree(child)
       
   243                     process_is_saved = True
       
   244         
   243         
   245         if config_is_saved and process_is_saved:
   244         if config_is_saved and process_is_saved:
   246             self.CreateBuffer(True)
   245             self.CreateBuffer(True)
   247         else:
   246         else:
   248             self.CreateBuffer(False)
   247             self.CreateBuffer(False)
   350                 self.BufferModel()
   349                 self.BufferModel()
   351     
   350     
   352     def SetProcessVariables(self, variables):
   351     def SetProcessVariables(self, variables):
   353         vars = []
   352         vars = []
   354         for var in variables:
   353         for var in variables:
   355             variable = ProcessVariablesClasses["ProcessVariables_variable"]()
   354             variable = ProcessVariablesParser.CreateElement("variable", "ProcessVariables")
   356             variable.setName(var["Name"])
   355             variable.setName(var["Name"])
   357             variable.setComment(var["Description"])
   356             variable.setComment(var["Description"])
   358             if var["ReadFrom"] != "":
   357             if var["ReadFrom"] != "":
   359                 position, index, subindex = var["ReadFrom"]
   358                 position, index, subindex = var["ReadFrom"]
   360                 if variable.getReadFrom() is None:
   359                 if variable.getReadFrom() is None:
   454         """
   453         """
   455         newConfNodeOpj = ConfigTreeNode.CTNAddChild(self, CTNName, CTNType, IEC_Channel)
   454         newConfNodeOpj = ConfigTreeNode.CTNAddChild(self, CTNName, CTNType, IEC_Channel)
   456         
   455         
   457         slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel())
   456         slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel())
   458         if slave is None:
   457         if slave is None:
   459             slave = EtherCATConfigClasses["Config_Slave"]()
   458             slave = EtherCATConfigParser.CreateElement("Slave", "Config")
       
   459             self.Config.getConfig().appendSlave(slave)
   460             slave_infos = slave.getInfo()
   460             slave_infos = slave.getInfo()
   461             slave_infos.setName("undefined")
   461             slave_infos.setName("undefined")
   462             slave_infos.setPhysAddr(newConfNodeOpj.BaseParams.getIEC_Channel())
   462             slave_infos.setPhysAddr(newConfNodeOpj.BaseParams.getIEC_Channel())
   463             slave_infos.setAutoIncAddr(0)
   463             slave_infos.setAutoIncAddr(0)
   464             self.Config.getConfig().appendSlave(slave)
       
   465             self.BufferModel()
   464             self.BufferModel()
   466             self.OnCTNSave()
   465             self.OnCTNSave()
   467         
   466         
   468         return newConfNodeOpj
   467         return newConfNodeOpj
   469 
   468 
   540             slave = self.GetSlave(slave_pos)
   539             slave = self.GetSlave(slave_pos)
   541             if slave is not None:
   540             if slave is not None:
   542                 type_infos = slave.getType()
   541                 type_infos = slave.getType()
   543                 device, module_extra_params = self.GetModuleInfos(type_infos)
   542                 device, module_extra_params = self.GetModuleInfos(type_infos)
   544         if device is not None:
   543         if device is not None:
       
   544             print "Get Entries List", limits
   545             entries = device.GetEntriesList(limits)
   545             entries = device.GetEntriesList(limits)
   546             #print entries
   546             #print entries
   547             entries_list = entries.items()
   547             entries_list = entries.items()
   548             entries_list.sort()
   548             entries_list.sort()
   549             entries = []
   549             entries = []
   645         return self.ChangesToSave or not self.ModelIsSaved()    
   645         return self.ChangesToSave or not self.ModelIsSaved()    
   646 
   646 
   647     def OnCTNSave(self, from_project_path=None):
   647     def OnCTNSave(self, from_project_path=None):
   648         config_filepath = self.ConfigFileName()
   648         config_filepath = self.ConfigFileName()
   649         
   649         
   650         config_text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
       
   651         config_extras = {"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
       
   652                   "xsi:noNamespaceSchemaLocation" : "EtherCATInfo.xsd"}
       
   653         config_text += self.Config.generateXMLText("EtherCATConfig", 0, config_extras)
       
   654 
       
   655         config_xmlfile = open(config_filepath,"w")
   650         config_xmlfile = open(config_filepath,"w")
   656         config_xmlfile.write(config_text.encode("utf-8"))
   651         config_xmlfile.write(etree.tostring(
       
   652             self.Config, 
       
   653             pretty_print=True, 
       
   654             xml_declaration=True, 
       
   655             encoding='utf-8'))
   657         config_xmlfile.close()
   656         config_xmlfile.close()
   658         
   657         
   659         process_filepath = self.ProcessVariablesFileName()
   658         process_filepath = self.ProcessVariablesFileName()
   660         
   659         
   661         process_text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
       
   662         process_extras = {"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance"}
       
   663         process_text += self.ProcessVariables.generateXMLText("ProcessVariables", 0, process_extras)
       
   664 
       
   665         process_xmlfile = open(process_filepath,"w")
   660         process_xmlfile = open(process_filepath,"w")
   666         process_xmlfile.write(process_text.encode("utf-8"))
   661         process_xmlfile.write(etree.tostring(
       
   662             self.ProcessVariables, 
       
   663             pretty_print=True, 
       
   664             xml_declaration=True, 
       
   665             encoding='utf-8'))
   667         process_xmlfile.close()
   666         process_xmlfile.close()
   668         
   667         
   669         self.Buffer.CurrentSaved()
   668         self.Buffer.CurrentSaved()
   670         return True
   669         return True
   671 
   670 
   749 
   748 
   750     """
   749     """
   751     Return a copy of the config
   750     Return a copy of the config
   752     """
   751     """
   753     def Copy(self, model):
   752     def Copy(self, model):
   754         return cPickle.loads(cPickle.dumps(model))
   753         return deepcopy(model)
   755     
   754     
   756     def CreateBuffer(self, saved):
   755     def CreateBuffer(self, saved):
   757         self.Buffer = UndoBuffer(cPickle.dumps((self.Config, self.ProcessVariables)), saved)
   756         self.Buffer = UndoBuffer(
       
   757             (EtherCATConfigParser.Dumps(self.Config), 
       
   758              ProcessVariablesParser.Dumps(self.ProcessVariables)), 
       
   759             saved)
   758         
   760         
   759     def BufferModel(self):
   761     def BufferModel(self):
   760         self.Buffer.Buffering(cPickle.dumps((self.Config, self.ProcessVariables)))
   762         self.Buffer.Buffering(
       
   763             (EtherCATConfigParser.Dumps(self.Config), 
       
   764              ProcessVariablesParser.Dumps(self.ProcessVariables)))
   761     
   765     
   762     def ModelIsSaved(self):
   766     def ModelIsSaved(self):
   763         if self.Buffer is not None:
   767         if self.Buffer is not None:
   764             return self.Buffer.IsCurrentSaved()
   768             return self.Buffer.IsCurrentSaved()
   765         else:
   769         else:
   766             return True
   770             return True
   767 
   771 
   768     def LoadPrevious(self):
   772     def LoadPrevious(self):
   769         self.Config, self.ProcessVariables = cPickle.loads(self.Buffer.Previous())
   773         config, process_variables = self.Buffer.Previous()
       
   774         self.Config = EtherCATConfigParser.Loads(config)
       
   775         self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)
   770     
   776     
   771     def LoadNext(self):
   777     def LoadNext(self):
   772         self.Config, self.ProcessVariables = cPickle.loads(self.Buffer.Next())
   778         config, process_variables = self.Buffer.Next()
       
   779         self.Config = EtherCATConfigParser.Loads(config)
       
   780         self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)
   773     
   781     
   774     def GetBufferState(self):
   782     def GetBufferState(self):
   775         first = self.Buffer.IsFirst()
   783         first = self.Buffer.IsFirst()
   776         last = self.Buffer.IsLast()
   784         last = self.Buffer.IsLast()
   777         return not first, not last
   785         return not first, not last