etherlab/EthercatMaster.py
changeset 2355 fec77f2b9e07
parent 2353 8f1a2846b2f5
child 2356 c26e0c66d8d5
equal deleted inserted replaced
2354:9460872f1440 2355:fec77f2b9e07
    77 
    77 
    78     def Generate_C(self, buildpath, varlist, IECCFLAGS):
    78     def Generate_C(self, buildpath, varlist, IECCFLAGS):
    79         etherlab_ext_file = open(GetLocalPath("etherlab_ext.c"), 'r')
    79         etherlab_ext_file = open(GetLocalPath("etherlab_ext.c"), 'r')
    80         etherlab_ext_code = etherlab_ext_file.read()
    80         etherlab_ext_code = etherlab_ext_file.read()
    81         etherlab_ext_file.close()
    81         etherlab_ext_file.close()
    82         
    82 
    83         Gen_etherlabfile_path = os.path.join(buildpath, "etherlab_ext.c")
    83         Gen_etherlabfile_path = os.path.join(buildpath, "etherlab_ext.c")
    84         ethelabfile = open(Gen_etherlabfile_path,'w')
    84         ethelabfile = open(Gen_etherlabfile_path,'w')
    85         ethelabfile.write(etherlab_ext_code)
    85         ethelabfile.write(etherlab_ext_code)
    86         ethelabfile.close()
    86         ethelabfile.close()
    87         
    87 
    88         runtimefile_path = os.path.join(os.path.split(__file__)[0], "runtime_etherlab.py")
    88         runtimefile_path = os.path.join(os.path.split(__file__)[0], "runtime_etherlab.py")
    89         return ((["etherlab_ext"], [(Gen_etherlabfile_path, IECCFLAGS)], True), "", 
    89         return ((["etherlab_ext"], [(Gen_etherlabfile_path, IECCFLAGS)], True), "",
    90                 ("runtime_etherlab.py", file(GetLocalPath("runtime_etherlab.py"))))
    90                 ("runtime_etherlab.py", file(GetLocalPath("runtime_etherlab.py"))))
    91     
    91 
    92 #--------------------------------------------------
    92 #--------------------------------------------------
    93 #                 Ethercat MASTER
    93 #                 Ethercat MASTER
    94 #--------------------------------------------------
    94 #--------------------------------------------------
    95 
    95 
    96 EtherCATConfigParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd")) 
    96 EtherCATConfigParser = GenerateParserFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATConfig.xsd"))
    97 
    97 
    98 def sort_commands(x, y):
    98 def sort_commands(x, y):
    99     if x["Index"] == y["Index"]:
    99     if x["Index"] == y["Index"]:
   100         return cmp(x["Subindex"], y["Subindex"])
   100         return cmp(x["Subindex"], y["Subindex"])
   101     return cmp(x["Index"], y["Index"])
   101     return cmp(x["Index"], y["Index"])
   102 
   102 
   103 cls = EtherCATConfigParser.GetElementClass("Slave", "Config")
   103 cls = EtherCATConfigParser.GetElementClass("Slave", "Config")
   104 if cls:
   104 if cls:
   105     
   105 
   106     def getType(self):
   106     def getType(self):
   107         slave_info = self.getInfo()
   107         slave_info = self.getInfo()
   108         return {"device_type": slave_info.getName(),
   108         return {"device_type": slave_info.getName(),
   109                 "vendor": GenerateHexDecValue(slave_info.getVendorId()),
   109                 "vendor": GenerateHexDecValue(slave_info.getVendorId()),
   110                 "product_code": GenerateHexDecValue(slave_info.getProductCode(), 16),
   110                 "product_code": GenerateHexDecValue(slave_info.getProductCode(), 16),
   116         slave_info.setName(type_infos["device_type"])
   116         slave_info.setName(type_infos["device_type"])
   117         slave_info.setVendorId(ExtractHexDecValue(type_infos["vendor"]))
   117         slave_info.setVendorId(ExtractHexDecValue(type_infos["vendor"]))
   118         slave_info.setProductCode(ExtractHexDecValue(type_infos["product_code"]))
   118         slave_info.setProductCode(ExtractHexDecValue(type_infos["product_code"]))
   119         slave_info.setRevisionNo(ExtractHexDecValue(type_infos["revision_number"]))
   119         slave_info.setRevisionNo(ExtractHexDecValue(type_infos["revision_number"]))
   120     setattr(cls, "setType", setType)
   120     setattr(cls, "setType", setType)
   121     
   121 
   122     def getInitCmds(self, create_default=False):
   122     def getInitCmds(self, create_default=False):
   123         Mailbox = self.getMailbox()
   123         Mailbox = self.getMailbox()
   124         if Mailbox is None:
   124         if Mailbox is None:
   125             if create_default:
   125             if create_default:
   126                 self.addMailbox()
   126                 self.addMailbox()
   138         if InitCmds is None and create_default:
   138         if InitCmds is None and create_default:
   139             CoE.addInitCmds()
   139             CoE.addInitCmds()
   140             InitCmds = CoE.getInitCmds()
   140             InitCmds = CoE.getInitCmds()
   141         return InitCmds
   141         return InitCmds
   142     setattr(cls, "getInitCmds", getInitCmds)
   142     setattr(cls, "getInitCmds", getInitCmds)
   143     
   143 
   144     def getStartupCommands(self):
   144     def getStartupCommands(self):
   145         pos = self.getInfo().getPhysAddr()
   145         pos = self.getInfo().getPhysAddr()
   146         InitCmds = self.getInitCmds()
   146         InitCmds = self.getInitCmds()
   147         if InitCmds is None:
   147         if InitCmds is None:
   148             return []
   148             return []
   159                 "Value": InitCmd.getData(),
   159                 "Value": InitCmd.getData(),
   160                 "Description": comment})
   160                 "Description": comment})
   161         commands.sort(sort_commands)
   161         commands.sort(sort_commands)
   162         return commands
   162         return commands
   163     setattr(cls, "getStartupCommands", getStartupCommands)
   163     setattr(cls, "getStartupCommands", getStartupCommands)
   164     
   164 
   165     def appendStartupCommand(self, command_infos):
   165     def appendStartupCommand(self, command_infos):
   166         InitCmds = self.getInitCmds(True)
   166         InitCmds = self.getInitCmds(True)
   167         command = EtherCATConfigParser.CreateElement("InitCmd", "InitCmds", 1)
   167         command = EtherCATConfigParser.CreateElement("InitCmd", "InitCmds", 1)
   168         InitCmds.appendInitCmd(command)
   168         InitCmds.appendInitCmd(command)
   169         command.setIndex(command_infos["Index"])
   169         command.setIndex(command_infos["Index"])
   170         command.setSubIndex(command_infos["Subindex"])
   170         command.setSubIndex(command_infos["Subindex"])
   171         command.setData(command_infos["Value"])
   171         command.setData(command_infos["Value"])
   172         command.setComment(command_infos["Description"])
   172         command.setComment(command_infos["Description"])
   173         return len(InitCmds.getInitCmd()) - 1
   173         return len(InitCmds.getInitCmd()) - 1
   174     setattr(cls, "appendStartupCommand", appendStartupCommand)
   174     setattr(cls, "appendStartupCommand", appendStartupCommand)
   175     
   175 
   176     def setStartupCommand(self, command_infos):
   176     def setStartupCommand(self, command_infos):
   177         InitCmds = self.getInitCmds()
   177         InitCmds = self.getInitCmds()
   178         if InitCmds is not None:
   178         if InitCmds is not None:
   179             commands = InitCmds.getInitCmd()
   179             commands = InitCmds.getInitCmd()
   180             if command_infos["command_idx"] < len(commands):
   180             if command_infos["command_idx"] < len(commands):
   182                 command.setIndex(command_infos["Index"])
   182                 command.setIndex(command_infos["Index"])
   183                 command.setSubIndex(command_infos["Subindex"])
   183                 command.setSubIndex(command_infos["Subindex"])
   184                 command.setData(command_infos["Value"])
   184                 command.setData(command_infos["Value"])
   185                 command.setComment(command_infos["Description"])
   185                 command.setComment(command_infos["Description"])
   186     setattr(cls, "setStartupCommand", setStartupCommand)
   186     setattr(cls, "setStartupCommand", setStartupCommand)
   187     
   187 
   188     def removeStartupCommand(self, command_idx):
   188     def removeStartupCommand(self, command_idx):
   189         InitCmds = self.getInitCmds()
   189         InitCmds = self.getInitCmds()
   190         if InitCmds is not None:
   190         if InitCmds is not None:
   191             if command_idx < len(InitCmds.getInitCmd()):
   191             if command_idx < len(InitCmds.getInitCmd()):
   192                 InitCmds.removeInitCmd(command_idx)
   192                 InitCmds.removeInitCmd(command_idx)
   216         <xsd:attribute name="SubIndex" type="xsd:integer" use="required"/>
   216         <xsd:attribute name="SubIndex" type="xsd:integer" use="required"/>
   217       </xsd:complexType>
   217       </xsd:complexType>
   218     </xsd:schema>
   218     </xsd:schema>
   219 """
   219 """
   220 
   220 
   221 ProcessVariablesParser = GenerateParserFromXSDstring(ProcessVariablesXSD) 
   221 ProcessVariablesParser = GenerateParserFromXSDstring(ProcessVariablesXSD)
   222 
   222 
   223 class _EthercatCTN:
   223 class _EthercatCTN:
   224 
   224 
   225     CTNChildrenTypes = [("EthercatSlave", _EthercatSlaveCTN, "Ethercat Slave")]
   225     CTNChildrenTypes = [("EthercatSlave", _EthercatSlaveCTN, "Ethercat Slave")]
   226     if HAS_MCL:
   226     if HAS_MCL:
   227         CTNChildrenTypes.append(("EthercatCIA402Slave", _EthercatCIA402SlaveCTN, "Ethercat CIA402 Slave"))
   227         CTNChildrenTypes.append(("EthercatCIA402Slave", _EthercatCIA402SlaveCTN, "Ethercat CIA402 Slave"))
   228     EditorType = MasterEditor
   228     EditorType = MasterEditor
   229     
   229 
   230     def __init__(self):
   230     def __init__(self):
   231         config_filepath = self.ConfigFileName()
   231         config_filepath = self.ConfigFileName()
   232         config_is_saved = False
   232         config_is_saved = False
   233         self.Config = None
   233         self.Config = None
   234         if os.path.isfile(config_filepath):
   234         if os.path.isfile(config_filepath):
   239                 if error is None:
   239                 if error is None:
   240                     config_is_saved = True
   240                     config_is_saved = True
   241             except Exception, e:
   241             except Exception, e:
   242                 error = e.message
   242                 error = e.message
   243             config_xmlfile.close()
   243             config_xmlfile.close()
   244             
   244 
   245             if error is not None:
   245             if error is not None:
   246                 self.GetCTRoot().logger.write_error(
   246                 self.GetCTRoot().logger.write_error(
   247                     _("Couldn't load %s network configuration file.") % CTNName)    
   247                     _("Couldn't load %s network configuration file.") % CTNName)
   248             
   248 
   249         if self.Config is None:
   249         if self.Config is None:
   250             self.Config = EtherCATConfigParser.CreateElement("EtherCATConfig")
   250             self.Config = EtherCATConfigParser.CreateElement("EtherCATConfig")
   251         
   251 
   252         process_filepath = self.ProcessVariablesFileName()
   252         process_filepath = self.ProcessVariablesFileName()
   253         process_is_saved = False
   253         process_is_saved = False
   254         self.ProcessVariables = None
   254         self.ProcessVariables = None
   255         if os.path.isfile(process_filepath):
   255         if os.path.isfile(process_filepath):
   256             process_xmlfile = open(process_filepath, 'r')
   256             process_xmlfile = open(process_filepath, 'r')
   260                 if error is None:
   260                 if error is None:
   261                     process_is_saved = True
   261                     process_is_saved = True
   262             except Exception, e:
   262             except Exception, e:
   263                 error = e.message
   263                 error = e.message
   264             process_xmlfile.close()
   264             process_xmlfile.close()
   265             
   265 
   266             if error is not None:
   266             if error is not None:
   267                 self.GetCTRoot().logger.write_error(
   267                 self.GetCTRoot().logger.write_error(
   268                     _("Couldn't load %s network process variables file.") % CTNName)    
   268                     _("Couldn't load %s network process variables file.") % CTNName)
   269             
   269 
   270         if self.ProcessVariables is None:
   270         if self.ProcessVariables is None:
   271             self.ProcessVariables = ProcessVariablesParser.CreateElement("ProcessVariables")
   271             self.ProcessVariables = ProcessVariablesParser.CreateElement("ProcessVariables")
   272         
   272 
   273         if config_is_saved and process_is_saved:
   273         if config_is_saved and process_is_saved:
   274             self.CreateBuffer(True)
   274             self.CreateBuffer(True)
   275         else:
   275         else:
   276             self.CreateBuffer(False)
   276             self.CreateBuffer(False)
   277             self.OnCTNSave()
   277             self.OnCTNSave()
   278          
   278 
   279         # ----------- call ethercat mng. function --------------
   279         # ----------- call ethercat mng. function --------------
   280         self.CommonMethod = _CommonSlave(self)
   280         self.CommonMethod = _CommonSlave(self)
   281     
   281 
   282     def GetIconName(self):
   282     def GetIconName(self):
   283         return "Ethercat"
   283         return "Ethercat"
   284     
   284 
   285     def GetContextualMenuItems(self):
   285     def GetContextualMenuItems(self):
   286         return [("Add Ethercat Slave", "Add Ethercat Slave to Master", self.OnAddEthercatSlave)]
   286         return [("Add Ethercat Slave", "Add Ethercat Slave to Master", self.OnAddEthercatSlave)]
   287     
   287 
   288     def OnAddEthercatSlave(self, event):
   288     def OnAddEthercatSlave(self, event):
   289         app_frame = self.GetCTRoot().AppFrame
   289         app_frame = self.GetCTRoot().AppFrame
   290         dialog = BrowseValuesLibraryDialog(app_frame, 
   290         dialog = BrowseValuesLibraryDialog(app_frame,
   291             "Ethercat Slave Type", self.GetSlaveTypesLibrary())
   291             "Ethercat Slave Type", self.GetSlaveTypesLibrary())
   292         if dialog.ShowModal() == wx.ID_OK:
   292         if dialog.ShowModal() == wx.ID_OK:
   293             type_infos = dialog.GetValueInfos()
   293             type_infos = dialog.GetValueInfos()
   294             device, module_extra_params = self.GetModuleInfos(type_infos)
   294             device, module_extra_params = self.GetModuleInfos(type_infos)
   295             if device is not None:
   295             if device is not None:
   301                 new_child.SetParamsAttribute("SlaveParams.Type", type_infos)
   301                 new_child.SetParamsAttribute("SlaveParams.Type", type_infos)
   302                 self.CTNRequestSave()
   302                 self.CTNRequestSave()
   303                 new_child._OpenView()
   303                 new_child._OpenView()
   304                 app_frame._Refresh(TITLE, FILEMENU, PROJECTTREE)
   304                 app_frame._Refresh(TITLE, FILEMENU, PROJECTTREE)
   305         dialog.Destroy()
   305         dialog.Destroy()
   306     
   306 
   307     def ExtractHexDecValue(self, value):
   307     def ExtractHexDecValue(self, value):
   308         return ExtractHexDecValue(value)
   308         return ExtractHexDecValue(value)
   309 
   309 
   310     def GetSizeOfType(self, type):
   310     def GetSizeOfType(self, type):
   311         return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None)
   311         return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None)
   312 
   312 
   313     def ConfigFileName(self):
   313     def ConfigFileName(self):
   314         return os.path.join(self.CTNPath(), "config.xml")
   314         return os.path.join(self.CTNPath(), "config.xml")
   315     
   315 
   316     def ProcessVariablesFileName(self):
   316     def ProcessVariablesFileName(self):
   317         return os.path.join(self.CTNPath(), "process_variables.xml")
   317         return os.path.join(self.CTNPath(), "process_variables.xml")
   318     
   318 
   319     def FilterSlave(self, slave, vendor=None, slave_pos=None, slave_profile=None):
   319     def FilterSlave(self, slave, vendor=None, slave_pos=None, slave_profile=None):
   320         if slave_pos is not None and slave.getInfo().getPhysAddr() != slave_pos:
   320         if slave_pos is not None and slave.getInfo().getPhysAddr() != slave_pos:
   321             return False
   321             return False
   322         type_infos = slave.getType()
   322         type_infos = slave.getType()
   323         if vendor is not None and ExtractHexDecValue(type_infos["vendor"]) != vendor:
   323         if vendor is not None and ExtractHexDecValue(type_infos["vendor"]) != vendor:
   353         for slave in self.Config.getConfig().getSlave():
   353         for slave in self.Config.getConfig().getSlave():
   354             if self.FilterSlave(slave, vendor, slave_pos, slave_profile):
   354             if self.FilterSlave(slave, vendor, slave_pos, slave_profile):
   355                 commands.append((slave.getInfo().getPhysAddr(), slave.getStartupCommands()))
   355                 commands.append((slave.getInfo().getPhysAddr(), slave.getStartupCommands()))
   356         commands.sort()
   356         commands.sort()
   357         return reduce(lambda x, y: x + y[1], commands, [])
   357         return reduce(lambda x, y: x + y[1], commands, [])
   358     
   358 
   359     def AppendStartupCommand(self, command_infos):
   359     def AppendStartupCommand(self, command_infos):
   360         slave = self.GetSlave(command_infos["Position"])
   360         slave = self.GetSlave(command_infos["Position"])
   361         if slave is not None:
   361         if slave is not None:
   362             command_idx = slave.appendStartupCommand(command_infos)
   362             command_idx = slave.appendStartupCommand(command_infos)
   363             self.BufferModel()
   363             self.BufferModel()
   364             return command_idx
   364             return command_idx
   365         return None
   365         return None
   366     
   366 
   367     def SetStartupCommandInfos(self, command_infos):
   367     def SetStartupCommandInfos(self, command_infos):
   368         slave = self.GetSlave(command_infos["Position"])
   368         slave = self.GetSlave(command_infos["Position"])
   369         if slave is not None:
   369         if slave is not None:
   370             slave.setStartupCommand(command_infos)
   370             slave.setStartupCommand(command_infos)
   371             self.BufferModel()
   371             self.BufferModel()
   372     
   372 
   373     def RemoveStartupCommand(self, slave_pos, command_idx, buffer=True):
   373     def RemoveStartupCommand(self, slave_pos, command_idx, buffer=True):
   374         slave = self.GetSlave(slave_pos)
   374         slave = self.GetSlave(slave_pos)
   375         if slave is not None:
   375         if slave is not None:
   376             slave.removeStartupCommand(command_idx)
   376             slave.removeStartupCommand(command_idx)
   377             if buffer:
   377             if buffer:
   378                 self.BufferModel()
   378                 self.BufferModel()
   379     
   379 
   380     def SetProcessVariables(self, variables):
   380     def SetProcessVariables(self, variables):
   381         vars = []
   381         vars = []
   382         for var in variables:
   382         for var in variables:
   383             variable = ProcessVariablesParser.CreateElement("variable", "ProcessVariables")
   383             variable = ProcessVariablesParser.CreateElement("variable", "ProcessVariables")
   384             variable.setName(var["Name"])
   384             variable.setName(var["Name"])
   404             elif variable.getWriteTo() is not None:
   404             elif variable.getWriteTo() is not None:
   405                 variable.deleteWriteTo()
   405                 variable.deleteWriteTo()
   406             vars.append(variable)
   406             vars.append(variable)
   407         self.ProcessVariables.setvariable(vars)
   407         self.ProcessVariables.setvariable(vars)
   408         self.BufferModel()
   408         self.BufferModel()
   409         
   409 
   410     def GetProcessVariables(self):
   410     def GetProcessVariables(self):
   411         variables = []
   411         variables = []
   412         idx = 0
   412         idx = 0
   413         for variable in self.ProcessVariables.getvariable():
   413         for variable in self.ProcessVariables.getvariable():
   414             var = {"Name": variable.getName(),
   414             var = {"Name": variable.getName(),
   429             else:
   429             else:
   430                 var["WriteTo"] = ""
   430                 var["WriteTo"] = ""
   431             variables.append(var)
   431             variables.append(var)
   432             idx += 1
   432             idx += 1
   433         return variables
   433         return variables
   434     
   434 
   435     def _ScanNetwork(self):
   435     def _ScanNetwork(self):
   436         app_frame = self.GetCTRoot().AppFrame
   436         app_frame = self.GetCTRoot().AppFrame
   437         
   437 
   438         execute = True
   438         execute = True
   439         if len(self.Children) > 0:
   439         if len(self.Children) > 0:
   440             dialog = wx.MessageDialog(app_frame, 
   440             dialog = wx.MessageDialog(app_frame,
   441                 _("The current network configuration will be deleted.\nDo you want to continue?"), 
   441                 _("The current network configuration will be deleted.\nDo you want to continue?"),
   442                 _("Scan Network"), 
   442                 _("Scan Network"),
   443                 wx.YES_NO|wx.ICON_QUESTION)
   443                 wx.YES_NO|wx.ICON_QUESTION)
   444             execute = dialog.ShowModal() == wx.ID_YES
   444             execute = dialog.ShowModal() == wx.ID_YES
   445             dialog.Destroy()
   445             dialog.Destroy()
   446         
   446 
   447         if execute:
   447         if execute:
   448             error, returnVal = self.RemoteExec(SCAN_COMMAND, returnVal = None)
   448             error, returnVal = self.RemoteExec(SCAN_COMMAND, returnVal = None)
   449             if error != 0:
   449             if error != 0:
   450                 dialog = wx.MessageDialog(app_frame, returnVal, "Error", wx.OK|wx.ICON_ERROR)
   450                 dialog = wx.MessageDialog(app_frame, returnVal, "Error", wx.OK|wx.ICON_ERROR)
   451                 dialog.ShowModal()
   451                 dialog.ShowModal()
   452                 dialog.Destroy()
   452                 dialog.Destroy()
   453             elif returnVal is not None:
   453             elif returnVal is not None:
   454                 for child in self.IECSortedChildren():
   454                 for child in self.IECSortedChildren():
   455                     self._doRemoveChild(child)
   455                     self._doRemoveChild(child)
   456                 
   456 
   457                 for slave in returnVal:
   457                 for slave in returnVal:
   458                     type_infos = {
   458                     type_infos = {
   459                         "vendor": slave["vendor_id"],
   459                         "vendor": slave["vendor_id"],
   460                         "product_code": slave["product_code"],
   460                         "product_code": slave["product_code"],
   461                         "revision_number":slave["revision_number"],
   461                         "revision_number":slave["revision_number"],
   468                             CTNType = "EthercatSlave"
   468                             CTNType = "EthercatSlave"
   469                         self.CTNAddChild("slave%s" % slave["idx"], CTNType, slave["idx"])
   469                         self.CTNAddChild("slave%s" % slave["idx"], CTNType, slave["idx"])
   470                         self.SetSlaveAlias(slave["idx"], slave["alias"])
   470                         self.SetSlaveAlias(slave["idx"], slave["alias"])
   471                         type_infos["device_type"] = device.getType().getcontent()
   471                         type_infos["device_type"] = device.getType().getcontent()
   472                         self.SetSlaveType(slave["idx"], type_infos)
   472                         self.SetSlaveType(slave["idx"], type_infos)
   473             
   473 
   474                 if app_frame:
   474                 if app_frame:
   475                     app_frame.RefreshProjectTree()
   475                     app_frame.RefreshProjectTree()
   476             
   476 
   477     def CTNAddChild(self, CTNName, CTNType, IEC_Channel=0):
   477     def CTNAddChild(self, CTNName, CTNType, IEC_Channel=0):
   478         """
   478         """
   479         Create the confnodes that may be added as child to this node self
   479         Create the confnodes that may be added as child to this node self
   480         @param CTNType: string desining the confnode class name (get name from CTNChildrenTypes)
   480         @param CTNType: string desining the confnode class name (get name from CTNChildrenTypes)
   481         @param CTNName: string for the name of the confnode instance
   481         @param CTNName: string for the name of the confnode instance
   482         """
   482         """
   483         newConfNodeOpj = ConfigTreeNode.CTNAddChild(self, CTNName, CTNType, IEC_Channel)
   483         newConfNodeOpj = ConfigTreeNode.CTNAddChild(self, CTNName, CTNType, IEC_Channel)
   484         
   484 
   485         slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel())
   485         slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel())
   486         if slave is None:
   486         if slave is None:
   487             slave = EtherCATConfigParser.CreateElement("Slave", "Config")
   487             slave = EtherCATConfigParser.CreateElement("Slave", "Config")
   488             self.Config.getConfig().appendSlave(slave)
   488             self.Config.getConfig().appendSlave(slave)
   489             slave_infos = slave.getInfo()
   489             slave_infos = slave.getInfo()
   490             slave_infos.setName("undefined")
   490             slave_infos.setName("undefined")
   491             slave_infos.setPhysAddr(newConfNodeOpj.BaseParams.getIEC_Channel())
   491             slave_infos.setPhysAddr(newConfNodeOpj.BaseParams.getIEC_Channel())
   492             slave_infos.setAutoIncAddr(0)
   492             slave_infos.setAutoIncAddr(0)
   493             self.BufferModel()
   493             self.BufferModel()
   494             self.OnCTNSave()
   494             self.OnCTNSave()
   495         
   495 
   496         return newConfNodeOpj
   496         return newConfNodeOpj
   497 
   497 
   498     def _doRemoveChild(self, CTNInstance):
   498     def _doRemoveChild(self, CTNInstance):
   499         slave_pos = CTNInstance.GetSlavePos()
   499         slave_pos = CTNInstance.GetSlavePos()
   500         config = self.Config.getConfig()
   500         config = self.Config.getConfig()
   521             self.CreateBuffer(True)
   521             self.CreateBuffer(True)
   522             self.CTNRequestSave()
   522             self.CTNRequestSave()
   523             if self._View is not None:
   523             if self._View is not None:
   524                 self._View.RefreshView()
   524                 self._View.RefreshView()
   525                 self._View.RefreshBuffer()
   525                 self._View.RefreshBuffer()
   526     
   526 
   527     def GetSlaveAlias(self, slave_pos):
   527     def GetSlaveAlias(self, slave_pos):
   528         slave = self.GetSlave(slave_pos)
   528         slave = self.GetSlave(slave_pos)
   529         if slave is not None:
   529         if slave is not None:
   530             slave_info = slave.getInfo()
   530             slave_info = slave.getInfo()
   531             return slave_info.getAutoIncAddr()
   531             return slave_info.getAutoIncAddr()
   532         return None
   532         return None
   533     
   533 
   534     def SetSlaveAlias(self, slave_pos, alias):
   534     def SetSlaveAlias(self, slave_pos, alias):
   535         slave = self.GetSlave(slave_pos)
   535         slave = self.GetSlave(slave_pos)
   536         if slave is not None:
   536         if slave is not None:
   537             slave_info = slave.getInfo()
   537             slave_info = slave.getInfo()
   538             slave_info.setAutoIncAddr(alias)
   538             slave_info.setAutoIncAddr(alias)
   539             self.BufferModel()
   539             self.BufferModel()
   540     
   540 
   541     def GetSlaveType(self, slave_pos):
   541     def GetSlaveType(self, slave_pos):
   542         slave = self.GetSlave(slave_pos)
   542         slave = self.GetSlave(slave_pos)
   543         if slave is not None:
   543         if slave is not None:
   544             return slave.getType()
   544             return slave.getType()
   545         return None
   545         return None
   546     
   546 
   547     def SetSlaveType(self, slave_pos, type_infos):
   547     def SetSlaveType(self, slave_pos, type_infos):
   548         slave = self.GetSlave(slave_pos)
   548         slave = self.GetSlave(slave_pos)
   549         if slave is not None:
   549         if slave is not None:
   550             slave.setType(type_infos)
   550             slave.setType(type_infos)
   551             self.BufferModel()
   551             self.BufferModel()
   552     
   552 
   553     def GetSlaveInfos(self, slave_pos):
   553     def GetSlaveInfos(self, slave_pos):
   554         slave = self.GetSlave(slave_pos)
   554         slave = self.GetSlave(slave_pos)
   555         if slave is not None:
   555         if slave is not None:
   556             type_infos = slave.getType()
   556             type_infos = slave.getType()
   557             device, module_extra_params = self.GetModuleInfos(type_infos)
   557             device, module_extra_params = self.GetModuleInfos(type_infos)
   560                 infos.update({"physics": device.getPhysics(),
   560                 infos.update({"physics": device.getPhysics(),
   561                               "sync_managers": device.GetSyncManagers(),
   561                               "sync_managers": device.GetSyncManagers(),
   562                               "entries": self.GetSlaveVariables(device)})
   562                               "entries": self.GetSlaveVariables(device)})
   563                 return infos
   563                 return infos
   564         return None
   564         return None
   565     
   565 
   566     def GetSlaveVariables(self, slave_pos=None, limits=None, device=None):
   566     def GetSlaveVariables(self, slave_pos=None, limits=None, device=None):
   567         if device is None and slave_pos is not None:
   567         if device is None and slave_pos is not None:
   568             slave = self.GetSlave(slave_pos)
   568             slave = self.GetSlave(slave_pos)
   569             if slave is not None:
   569             if slave is not None:
   570                 type_infos = slave.getType()
   570                 type_infos = slave.getType()
   590                     current_entry["children"].append(entry)
   590                     current_entry["children"].append(entry)
   591                 else:
   591                 else:
   592                     entries.append(entry)
   592                     entries.append(entry)
   593             return entries
   593             return entries
   594         return []
   594         return []
   595     
   595 
   596     def GetSlaveVariableDataType(self, slave_pos, index, subindex):
   596     def GetSlaveVariableDataType(self, slave_pos, index, subindex):
   597         slave = self.GetSlave(slave_pos)
   597         slave = self.GetSlave(slave_pos)
   598         if slave is not None:
   598         if slave is not None:
   599             device, module_extra_params = self.GetModuleInfos(slave.getType())
   599             device, module_extra_params = self.GetModuleInfos(slave.getType())
   600             if device is not None:
   600             if device is not None:
   601                 entries = device.GetEntriesList()
   601                 entries = device.GetEntriesList()
   602                 entry_infos = entries.get((index, subindex))
   602                 entry_infos = entries.get((index, subindex))
   603                 if entry_infos is not None:
   603                 if entry_infos is not None:
   604                     return entry_infos["Type"]
   604                     return entry_infos["Type"]
   605         return None
   605         return None
   606     
   606 
   607     def GetNodesVariables(self, vendor=None, slave_pos=None, slave_profile=None, limits=None):
   607     def GetNodesVariables(self, vendor=None, slave_pos=None, slave_profile=None, limits=None):
   608         entries = []
   608         entries = []
   609         for slave_position in self.GetSlaves():
   609         for slave_position in self.GetSlaves():
   610             if slave_pos is not None and slave_position != slave_pos:
   610             if slave_pos is not None and slave_position != slave_pos:
   611                 continue
   611                 continue
   616             device, module_extra_params = self.GetModuleInfos(type_infos)
   616             device, module_extra_params = self.GetModuleInfos(type_infos)
   617             if slave_profile is not None and slave_profile not in device.GetProfileNumbers():
   617             if slave_profile is not None and slave_profile not in device.GetProfileNumbers():
   618                 continue
   618                 continue
   619             entries.extend(self.GetSlaveVariables(slave_position, limits, device))
   619             entries.extend(self.GetSlaveVariables(slave_position, limits, device))
   620         return entries
   620         return entries
   621      
   621 
   622     def GetModuleInfos(self, type_infos):
   622     def GetModuleInfos(self, type_infos):
   623         return self.CTNParent.GetModuleInfos(type_infos)
   623         return self.CTNParent.GetModuleInfos(type_infos)
   624     
   624 
   625     def GetSlaveTypesLibrary(self, profile_filter=None):
   625     def GetSlaveTypesLibrary(self, profile_filter=None):
   626         return self.CTNParent.GetModulesLibrary(profile_filter)
   626         return self.CTNParent.GetModulesLibrary(profile_filter)
   627     
   627 
   628     def GetLibraryVendors(self):
   628     def GetLibraryVendors(self):
   629         return self.CTNParent.GetVendors()
   629         return self.CTNParent.GetVendors()
   630     
   630 
   631     def GetDeviceLocationTree(self, slave_pos, current_location, device_name):
   631     def GetDeviceLocationTree(self, slave_pos, current_location, device_name):
   632         slave = self.GetSlave(slave_pos)
   632         slave = self.GetSlave(slave_pos)
   633         vars = []    
   633         vars = []
   634         if slave is not None:
   634         if slave is not None:
   635             type_infos = slave.getType()
   635             type_infos = slave.getType()
   636         
   636 
   637             device, module_extra_params = self.GetModuleInfos(type_infos)
   637             device, module_extra_params = self.GetModuleInfos(type_infos)
   638             if device is not None:
   638             if device is not None:
   639                 sync_managers = []
   639                 sync_managers = []
   640                 for sync_manager in device.getSm():
   640                 for sync_manager in device.getSm():
   641                     sync_manager_control_byte = ExtractHexDecValue(sync_manager.getControlByte())
   641                     sync_manager_control_byte = ExtractHexDecValue(sync_manager.getControlByte())
   642                     sync_manager_direction = sync_manager_control_byte & 0x0c
   642                     sync_manager_direction = sync_manager_control_byte & 0x0c
   643                     if sync_manager_direction:
   643                     if sync_manager_direction:
   644                         sync_managers.append(LOCATION_VAR_OUTPUT)
   644                         sync_managers.append(LOCATION_VAR_OUTPUT)
   645                     else:
   645                     else:
   646                         sync_managers.append(LOCATION_VAR_INPUT)
   646                         sync_managers.append(LOCATION_VAR_INPUT)
   647                 
   647 
   648                 entries = device.GetEntriesList().items()
   648                 entries = device.GetEntriesList().items()
   649                 entries.sort()
   649                 entries.sort()
   650                 for (index, subindex), entry in entries:
   650                 for (index, subindex), entry in entries:
   651                     var_size = self.GetSizeOfType(entry["Type"])
   651                     var_size = self.GetSizeOfType(entry["Type"])
   652                     if var_size is not None:
   652                     if var_size is not None:
   653                         var_class = VARCLASSCONVERSION.get(entry["PDOMapping"], None)
   653                         var_class = VARCLASSCONVERSION.get(entry["PDOMapping"], None)
   654                         if var_class is not None:
   654                         if var_class is not None:
   655                             if var_class == LOCATION_VAR_INPUT:
   655                             if var_class == LOCATION_VAR_INPUT:
   656                                 var_dir = "%I"
   656                                 var_dir = "%I"
   657                             else:
   657                             else:
   658                                 var_dir = "%Q"    
   658                                 var_dir = "%Q"
   659                         
   659 
   660                             vars.append({"name": "0x%4.4x-0x%2.2x: %s" % (index, subindex, entry["Name"]),
   660                             vars.append({"name": "0x%4.4x-0x%2.2x: %s" % (index, subindex, entry["Name"]),
   661                                          "type": var_class,
   661                                          "type": var_class,
   662                                          "size": var_size,
   662                                          "size": var_size,
   663                                          "IEC_type": entry["Type"],
   663                                          "IEC_type": entry["Type"],
   664                                          "var_name": "%s_%4.4x_%2.2x" % ("_".join(device_name.split()), index, subindex),
   664                                          "var_name": "%s_%4.4x_%2.2x" % ("_".join(device_name.split()), index, subindex),
   665                                          "location": "%s%s%s"%(var_dir, var_size, ".".join(map(str, current_location + 
   665                                          "location": "%s%s%s"%(var_dir, var_size, ".".join(map(str, current_location +
   666                                                                                                     (index, subindex)))),
   666                                                                                                     (index, subindex)))),
   667                                          "description": "",
   667                                          "description": "",
   668                                          "children": []})
   668                                          "children": []})
   669         
   669 
   670         return vars
   670         return vars
   671     
   671 
   672     def CTNTestModified(self):
   672     def CTNTestModified(self):
   673         return self.ChangesToSave or not self.ModelIsSaved()    
   673         return self.ChangesToSave or not self.ModelIsSaved()
   674 
   674 
   675     def OnCTNSave(self, from_project_path=None):
   675     def OnCTNSave(self, from_project_path=None):
   676         config_filepath = self.ConfigFileName()
   676         config_filepath = self.ConfigFileName()
   677         
   677 
   678         config_xmlfile = open(config_filepath,"w")
   678         config_xmlfile = open(config_filepath,"w")
   679         config_xmlfile.write(etree.tostring(
   679         config_xmlfile.write(etree.tostring(
   680             self.Config, 
   680             self.Config,
   681             pretty_print=True, 
   681             pretty_print=True,
   682             xml_declaration=True, 
   682             xml_declaration=True,
   683             encoding='utf-8'))
   683             encoding='utf-8'))
   684         config_xmlfile.close()
   684         config_xmlfile.close()
   685         
   685 
   686         process_filepath = self.ProcessVariablesFileName()
   686         process_filepath = self.ProcessVariablesFileName()
   687         
   687 
   688         process_xmlfile = open(process_filepath,"w")
   688         process_xmlfile = open(process_filepath,"w")
   689         process_xmlfile.write(etree.tostring(
   689         process_xmlfile.write(etree.tostring(
   690             self.ProcessVariables, 
   690             self.ProcessVariables,
   691             pretty_print=True, 
   691             pretty_print=True,
   692             xml_declaration=True, 
   692             xml_declaration=True,
   693             encoding='utf-8'))
   693             encoding='utf-8'))
   694         process_xmlfile.close()
   694         process_xmlfile.close()
   695         
   695 
   696         self.Buffer.CurrentSaved()
   696         self.Buffer.CurrentSaved()
   697         return True
   697         return True
   698 
   698 
   699     def GetProcessVariableName(self, location, var_type):
   699     def GetProcessVariableName(self, location, var_type):
   700         return "__M%s_%s" % (self.GetSizeOfType(var_type), "_".join(map(str, location)))
   700         return "__M%s_%s" % (self.GetSizeOfType(var_type), "_".join(map(str, location)))
   701 
   701 
   702     def _Generate_C(self, buildpath, locations):
   702     def _Generate_C(self, buildpath, locations):
   703         current_location = self.GetCurrentLocation()
   703         current_location = self.GetCurrentLocation()
   704         # define a unique name for the generated C file
   704         # define a unique name for the generated C file
   705         location_str = "_".join(map(lambda x:str(x), current_location))
   705         location_str = "_".join(map(lambda x:str(x), current_location))
   706         
   706 
   707         Gen_Ethercatfile_path = os.path.join(buildpath, "ethercat_%s.c"%location_str)
   707         Gen_Ethercatfile_path = os.path.join(buildpath, "ethercat_%s.c"%location_str)
   708         
   708 
   709         self.FileGenerator = _EthercatCFileGenerator(self)
   709         self.FileGenerator = _EthercatCFileGenerator(self)
   710         
   710 
   711         LocationCFilesAndCFLAGS, LDFLAGS, extra_files = ConfigTreeNode._Generate_C(self, buildpath, locations)
   711         LocationCFilesAndCFLAGS, LDFLAGS, extra_files = ConfigTreeNode._Generate_C(self, buildpath, locations)
   712         
   712 
   713         for idx, variable in enumerate(self.ProcessVariables.getvariable()):
   713         for idx, variable in enumerate(self.ProcessVariables.getvariable()):
   714             name = None
   714             name = None
   715             var_type = None
   715             var_type = None
   716             read_from = variable.getReadFrom()
   716             read_from = variable.getReadFrom()
   717             write_to = variable.getWriteTo()
   717             write_to = variable.getWriteTo()
   732                     location = current_location + (idx, )
   732                     location = current_location + (idx, )
   733                     var_type = self.GetSlaveVariableDataType(pos, index, subindex)
   733                     var_type = self.GetSlaveVariableDataType(pos, index, subindex)
   734                     name = self.GetProcessVariableName(location, var_type)
   734                     name = self.GetProcessVariableName(location, var_type)
   735                 self.FileGenerator.DeclareVariable(
   735                 self.FileGenerator.DeclareVariable(
   736                             pos, index, subindex, var_type, "Q", name, True)
   736                             pos, index, subindex, var_type, "Q", name, True)
   737         
   737 
   738         self.FileGenerator.GenerateCFile(Gen_Ethercatfile_path, location_str, self.BaseParams.getIEC_Channel())
   738         self.FileGenerator.GenerateCFile(Gen_Ethercatfile_path, location_str, self.BaseParams.getIEC_Channel())
   739         
   739 
   740         LocationCFilesAndCFLAGS.insert(0, 
   740         LocationCFilesAndCFLAGS.insert(0,
   741             (current_location, 
   741             (current_location,
   742              [(Gen_Ethercatfile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))], 
   742              [(Gen_Ethercatfile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))],
   743              True))
   743              True))
   744         LDFLAGS.append("-lethercat_rtdm -lrtdm")
   744         LDFLAGS.append("-lethercat_rtdm -lrtdm")
   745         
   745 
   746         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
   746         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
   747 
   747 
   748     ConfNodeMethods = [
   748     ConfNodeMethods = [
   749         {"bitmap" : "ScanNetwork",
   749         {"bitmap" : "ScanNetwork",
   750          "name" : _("Scan Network"), 
   750          "name" : _("Scan Network"),
   751          "tooltip" : _("Scan Network"),
   751          "tooltip" : _("Scan Network"),
   752          "method" : "_ScanNetwork"},
   752          "method" : "_ScanNetwork"},
   753     ]
   753     ]
   754 
   754 
   755     def CTNGenerate_C(self, buildpath, locations):
   755     def CTNGenerate_C(self, buildpath, locations):
   756         current_location = self.GetCurrentLocation()
   756         current_location = self.GetCurrentLocation()
   757         
   757 
   758         slaves = self.GetSlaves()
   758         slaves = self.GetSlaves()
   759         for slave_pos in slaves:
   759         for slave_pos in slaves:
   760             slave = self.GetSlave(slave_pos)
   760             slave = self.GetSlave(slave_pos)
   761             if slave is not None:
   761             if slave is not None:
   762                 self.FileGenerator.DeclareSlave(slave_pos, slave)
   762                 self.FileGenerator.DeclareSlave(slave_pos, slave)
   763         
   763 
   764         for location in locations:
   764         for location in locations:
   765             loc = location["LOC"][len(current_location):]
   765             loc = location["LOC"][len(current_location):]
   766             slave_pos = loc[0]
   766             slave_pos = loc[0]
   767             if slave_pos in slaves and len(loc) == 3 and location["DIR"] != "M":
   767             if slave_pos in slaves and len(loc) == 3 and location["DIR"] != "M":
   768                 self.FileGenerator.DeclareVariable(
   768                 self.FileGenerator.DeclareVariable(
   769                     slave_pos, loc[1], loc[2], location["IEC_TYPE"], location["DIR"], location["NAME"])
   769                     slave_pos, loc[1], loc[2], location["IEC_TYPE"], location["DIR"], location["NAME"])
   770         
   770 
   771         return [],"",False
   771         return [],"",False
   772         
   772 
   773 #-------------------------------------------------------------------------------
   773 #-------------------------------------------------------------------------------
   774 #                      Current Buffering Management Functions
   774 #                      Current Buffering Management Functions
   775 #-------------------------------------------------------------------------------
   775 #-------------------------------------------------------------------------------
   776 
   776 
   777     """
   777     """
   778     Return a copy of the config
   778     Return a copy of the config
   779     """
   779     """
   780     def Copy(self, model):
   780     def Copy(self, model):
   781         return deepcopy(model)
   781         return deepcopy(model)
   782     
   782 
   783     def CreateBuffer(self, saved):
   783     def CreateBuffer(self, saved):
   784         self.Buffer = UndoBuffer(
   784         self.Buffer = UndoBuffer(
   785             (EtherCATConfigParser.Dumps(self.Config), 
   785             (EtherCATConfigParser.Dumps(self.Config),
   786              ProcessVariablesParser.Dumps(self.ProcessVariables)), 
   786              ProcessVariablesParser.Dumps(self.ProcessVariables)),
   787             saved)
   787             saved)
   788         
   788 
   789     def BufferModel(self):
   789     def BufferModel(self):
   790         self.Buffer.Buffering(
   790         self.Buffer.Buffering(
   791             (EtherCATConfigParser.Dumps(self.Config), 
   791             (EtherCATConfigParser.Dumps(self.Config),
   792              ProcessVariablesParser.Dumps(self.ProcessVariables)))
   792              ProcessVariablesParser.Dumps(self.ProcessVariables)))
   793     
   793 
   794     def ModelIsSaved(self):
   794     def ModelIsSaved(self):
   795         if self.Buffer is not None:
   795         if self.Buffer is not None:
   796             return self.Buffer.IsCurrentSaved()
   796             return self.Buffer.IsCurrentSaved()
   797         else:
   797         else:
   798             return True
   798             return True
   799 
   799 
   800     def LoadPrevious(self):
   800     def LoadPrevious(self):
   801         config, process_variables = self.Buffer.Previous()
   801         config, process_variables = self.Buffer.Previous()
   802         self.Config = EtherCATConfigParser.Loads(config)
   802         self.Config = EtherCATConfigParser.Loads(config)
   803         self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)
   803         self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)
   804     
   804 
   805     def LoadNext(self):
   805     def LoadNext(self):
   806         config, process_variables = self.Buffer.Next()
   806         config, process_variables = self.Buffer.Next()
   807         self.Config = EtherCATConfigParser.Loads(config)
   807         self.Config = EtherCATConfigParser.Loads(config)
   808         self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)
   808         self.ProcessVariables = ProcessVariablesParser.Loads(process_variables)
   809     
   809 
   810     def GetBufferState(self):
   810     def GetBufferState(self):
   811         first = self.Buffer.IsFirst()
   811         first = self.Buffer.IsFirst()
   812         last = self.Buffer.IsLast()
   812         last = self.Buffer.IsLast()
   813         return not first, not last
   813         return not first, not last
   814