etherlab/etherlab.py
changeset 2048 5726f2bbdace
parent 2047 b0b7bd288b6e
child 2049 438a4a1ff188
equal deleted inserted replaced
2047:b0b7bd288b6e 2048:5726f2bbdace
     3 from xml.dom import minidom
     3 from xml.dom import minidom
     4 
     4 
     5 import wx
     5 import wx
     6 
     6 
     7 from xmlclass import *
     7 from xmlclass import *
     8 from plugger import PlugTemplate
     8 from ConfigTreeNode import ConfigTreeNode
     9 from PLCControler import UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
     9 from PLCControler import UndoBuffer, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
    10 from ConfigEditor import NodeEditor, CIA402NodeEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE
    10 from ConfigEditor import NodeEditor, CIA402NodeEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE
    11 
    11 
    12 try:
    12 try:
    13     from plugins.motion import Headers, AxisXSD
    13     from confnodes.motion import Headers, AxisXSD
    14     HAS_MCL = True
    14     HAS_MCL = True
    15 except:
    15 except:
    16     HAS_MCL = False
    16     HAS_MCL = False
    17 
    17 
    18 PLUGINFOLDER = os.path.split(os.path.realpath(__file__))[0]
    18 CONFNODEFOLDER = os.path.split(os.path.realpath(__file__))[0]
    19 
    19 
    20 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
    20 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
    21     "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", 
    21     "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", 
    22     "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L"}
    22     "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L"}
    23 
    23 
    59 
    59 
    60 #--------------------------------------------------
    60 #--------------------------------------------------
    61 #                    Ethercat Node
    61 #                    Ethercat Node
    62 #--------------------------------------------------
    62 #--------------------------------------------------
    63 
    63 
    64 class _EthercatSlavePlug:
    64 class _EthercatSlaveCTN:
    65 
    65 
    66     NODE_PROFILE = None
    66     NODE_PROFILE = None
    67     EditorType = NodeEditor
    67     EditorType = NodeEditor
    68     
    68     
    69     def GetIconPath(self, icon):
    69     def GetIconPath(self, icon):
    70         return os.path.join(PLUGINFOLDER, "images", icon)
    70         return os.path.join(CONFNODEFOLDER, "images", icon)
    71     
    71     
    72     def ExtractHexDecValue(self, value):
    72     def ExtractHexDecValue(self, value):
    73         return ExtractHexDecValue(value)
    73         return ExtractHexDecValue(value)
    74     
    74     
    75     def GetSizeOfType(self, type):
    75     def GetSizeOfType(self, type):
    76         return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None)
    76         return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None)
    77     
    77     
    78     def GetSlavePos(self):
    78     def GetSlavePos(self):
    79         return self.BaseParams.getIEC_Channel()
    79         return self.BaseParams.getIEC_Channel()
    80     
    80     
    81     def GetParamsAttributes(self, path = None):
    81     def GetParamsAttributes(self, path = None):
    82         if path:
    82         if path:
    83             parts = path.split(".", 1)
    83             parts = path.split(".", 1)
    84             if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
    84             if self.MandatoryParams and parts[0] == self.MandatoryParams[0]:
    85                 return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
    85                 return self.MandatoryParams[1].getElementInfos(parts[0], parts[1])
    86             elif self.PlugParams and parts[0] == self.PlugParams[0]:
    86             elif self.CTNParams and parts[0] == self.CTNParams[0]:
    87                 return self.PlugParams[1].getElementInfos(parts[0], parts[1])
    87                 return self.CTNParams[1].getElementInfos(parts[0], parts[1])
    88         else:
    88         else:
    89             params = []
    89             params = []
    90             if wx.VERSION < (2, 8, 0) and self.MandatoryParams:
    90             if wx.VERSION < (2, 8, 0) and self.MandatoryParams:
    91                 params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0]))
    91                 params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0]))
    92             slave_type = self.PlugParent.GetSlaveType(self.GetSlavePos())
    92             slave_type = self.CTNParent.GetSlaveType(self.GetSlavePos())
    93             params.append({
    93             params.append({
    94                 'use': 'required', 
    94                 'use': 'required', 
    95                 'type': 'element', 
    95                 'type': 'element', 
    96                 'name': 'SlaveParams', 
    96                 'name': 'SlaveParams', 
    97                 'value': None, 
    97                 'value': None, 
    98                 'children': [{
    98                 'children': [{
    99                     'use': 'optional', 
    99                     'use': 'optional', 
   100                     'type': self.PlugParent.GetSlaveTypesLibrary(self.NODE_PROFILE), 
   100                     'type': self.CTNParent.GetSlaveTypesLibrary(self.NODE_PROFILE), 
   101                     'name': 'Type', 
   101                     'name': 'Type', 
   102                     'value': (slave_type["device_type"], slave_type)}, 
   102                     'value': (slave_type["device_type"], slave_type)}, 
   103                    {'use': 'optional', 
   103                    {'use': 'optional', 
   104                     'type': 'unsignedLong', 
   104                     'type': 'unsignedLong', 
   105                     'name': 'Alias', 
   105                     'name': 'Alias', 
   106                     'value': self.PlugParent.GetSlaveAlias(self.GetSlavePos())}]
   106                     'value': self.CTNParent.GetSlaveAlias(self.GetSlavePos())}]
   107             })
   107             })
   108             if self.PlugParams:
   108             if self.CTNParams:
   109                 params.append(self.PlugParams[1].getElementInfos(self.PlugParams[0]))
   109                 params.append(self.CTNParams[1].getElementInfos(self.CTNParams[0]))
   110             return params
   110             return params
   111         
   111         
   112     def SetParamsAttribute(self, path, value):
   112     def SetParamsAttribute(self, path, value):
   113         position = self.BaseParams.getIEC_Channel()
   113         position = self.BaseParams.getIEC_Channel()
   114         value, changed = PlugTemplate.SetParamsAttribute(self, path, value)
   114         value, changed = ConfigTreeNode.SetParamsAttribute(self, path, value)
   115         # Filter IEC_Channel, Slave_Type and Alias that have specific behavior
   115         # Filter IEC_Channel, Slave_Type and Alias that have specific behavior
   116         if path == "BaseParams.IEC_Channel":
   116         if path == "BaseParams.IEC_Channel":
   117             self.PlugParent.SetSlavePosition(position, value)
   117             self.CTNParent.SetSlavePosition(position, value)
   118         elif path == "SlaveParams.Type":
   118         elif path == "SlaveParams.Type":
   119             self.PlugParent.SetSlaveType(position, value)
   119             self.CTNParent.SetSlaveType(position, value)
   120             slave_type = self.PlugParent.GetSlaveType(self.GetSlavePos())
   120             slave_type = self.CTNParent.GetSlaveType(self.GetSlavePos())
   121             value = (slave_type["device_type"], slave_type)
   121             value = (slave_type["device_type"], slave_type)
   122             changed = True
   122             changed = True
   123         elif path == "SlaveParams.Alias":
   123         elif path == "SlaveParams.Alias":
   124             self.PlugParent.SetSlaveAlias(position, value)
   124             self.CTNParent.SetSlaveAlias(position, value)
   125             changed = True
   125             changed = True
   126         return value, changed
   126         return value, changed
   127 
   127 
   128     def GetSlaveInfos(self):
   128     def GetSlaveInfos(self):
   129         return self.PlugParent.GetSlaveInfos(self.GetSlavePos())
   129         return self.CTNParent.GetSlaveInfos(self.GetSlavePos())
   130     
   130     
   131     def GetVariableLocationTree(self):
   131     def GetVariableLocationTree(self):
   132         return  {"name": self.BaseParams.getName(),
   132         return  {"name": self.BaseParams.getName(),
   133                  "type": LOCATION_PLUGIN,
   133                  "type": LOCATION_CONFNODE,
   134                  "location": self.GetFullIEC_Channel(),
   134                  "location": self.GetFullIEC_Channel(),
   135                  "children": self.PlugParent.GetDeviceLocationTree(self.GetSlavePos(), self.GetCurrentLocation(), self.BaseParams.getName())
   135                  "children": self.CTNParent.GetDeviceLocationTree(self.GetSlavePos(), self.GetCurrentLocation(), self.BaseParams.getName())
   136         }
   136         }
   137 
   137 
   138     PluginMethods = [
   138     ConfNodeMethods = [
   139         {"bitmap" : os.path.join(PLUGINFOLDER, "images", "editSlave"),
   139         {"bitmap" : os.path.join(CONFNODEFOLDER, "images", "editSlave"),
   140          "name" : _("Edit Slave"), 
   140          "name" : _("Edit Slave"), 
   141          "tooltip" : _("Edit Slave"),
   141          "tooltip" : _("Edit Slave"),
   142          "method" : "_OpenView"},
   142          "method" : "_OpenView"},
   143     ]
   143     ]
   144 
   144 
   145     def PlugGenerate_C(self, buildpath, locations):
   145     def CTNGenerate_C(self, buildpath, locations):
   146         """
   146         """
   147         Generate C code
   147         Generate C code
   148         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   148         @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
   149         @param locations: List of complete variables locations \
   149         @param locations: List of complete variables locations \
   150             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
   150             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
   151             "NAME" : name of the variable (generally "__IW0_1_2" style)
   151             "NAME" : name of the variable (generally "__IW0_1_2" style)
   152             "DIR" : direction "Q","I" or "M"
   152             "DIR" : direction "Q","I" or "M"
   153             "SIZE" : size "X", "B", "W", "D", "L"
   153             "SIZE" : size "X", "B", "W", "D", "L"
   170         ("StatusWord", 0x6041, 0x00, "UINT", "I"),
   170         ("StatusWord", 0x6041, 0x00, "UINT", "I"),
   171         ("ModesOfOperationDisplay", 0x06061, 0x00, "SINT", "I"),
   171         ("ModesOfOperationDisplay", 0x06061, 0x00, "SINT", "I"),
   172         ("ActualPosition", 0x6064, 0x00, "DINT", "I"),
   172         ("ActualPosition", 0x6064, 0x00, "DINT", "I"),
   173     ]
   173     ]
   174     
   174     
   175     class _EthercatCIA402SlavePlug(_EthercatSlavePlug):
   175     class _EthercatCIA402SlaveCTN(_EthercatSlaveCTN):
   176         XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   176         XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   177         <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   177         <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   178           <xsd:element name="CIA402SlaveParams">
   178           <xsd:element name="CIA402SlaveParams">
   179             <xsd:complexType>
   179             <xsd:complexType>
   180               %s
   180               %s
   184         """ % AxisXSD
   184         """ % AxisXSD
   185         
   185         
   186         NODE_PROFILE = 402
   186         NODE_PROFILE = 402
   187         EditorType = CIA402NodeEditor
   187         EditorType = CIA402NodeEditor
   188         
   188         
   189         PluginMethods = [
   189         ConfNodeMethods = [
   190             {"bitmap" : os.path.join(PLUGINFOLDER, "images", "editCIA402Slave"),
   190             {"bitmap" : os.path.join(CONFNODEFOLDER, "images", "editCIA402Slave"),
   191              "name" : _("Edit CIA402 Slave"), 
   191              "name" : _("Edit CIA402 Slave"), 
   192              "tooltip" : _("Edit CIA402 Slave"),
   192              "tooltip" : _("Edit CIA402 Slave"),
   193              "method" : "_OpenView"},
   193              "method" : "_OpenView"},
   194         ]
   194         ]
   195         
   195         
   196         def PlugGenerate_C(self, buildpath, locations):
   196         def CTNGenerate_C(self, buildpath, locations):
   197             """
   197             """
   198             Generate C code
   198             Generate C code
   199             @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   199             @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
   200             @param locations: List of complete variables locations \
   200             @param locations: List of complete variables locations \
   201                 [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
   201                 [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
   202                 "NAME" : name of the variable (generally "__IW0_1_2" style)
   202                 "NAME" : name of the variable (generally "__IW0_1_2" style)
   203                 "DIR" : direction "Q","I" or "M"
   203                 "DIR" : direction "Q","I" or "M"
   204                 "SIZE" : size "X", "B", "W", "D", "L"
   204                 "SIZE" : size "X", "B", "W", "D", "L"
   235                 str_completion["entry_variables"].append(
   235                 str_completion["entry_variables"].append(
   236                         "    IEC_%(var_type)s *%(name)s;" % var_infos)
   236                         "    IEC_%(var_type)s *%(name)s;" % var_infos)
   237                 str_completion["init_entry_variables"].append(
   237                 str_completion["init_entry_variables"].append(
   238                         "    __CIA402Node_%(location)s.%(name)s = %(var_name)s;" % var_infos)
   238                         "    __CIA402Node_%(location)s.%(name)s = %(var_name)s;" % var_infos)
   239                 
   239                 
   240                 self.PlugParent.FileGenerator.DeclareVariable(
   240                 self.CTNParent.FileGenerator.DeclareVariable(
   241                         self.GetSlavePos(), var_infos["index"], var_infos["subindex"], 
   241                         self.GetSlavePos(), var_infos["index"], var_infos["subindex"], 
   242                         var_infos["var_type"], var_infos["dir"], var_infos["var_name"])
   242                         var_infos["var_type"], var_infos["dir"], var_infos["var_name"])
   243             
   243             
   244             params = self.PlugParams[1].getElementInfos(self.PlugParams[0])
   244             params = self.CTNParams[1].getElementInfos(self.CTNParams[0])
   245             for param in params["children"]:
   245             for param in params["children"]:
   246                 if param["value"] is not None:
   246                 if param["value"] is not None:
   247                     param_infos = {
   247                     param_infos = {
   248                         "location": location_str,
   248                         "location": location_str,
   249                         "param_name": param["name"],
   249                         "param_name": param["name"],
   264             Gen_CIA402Nodefile_path = os.path.join(buildpath, "cia402node_%s.c"%location_str)
   264             Gen_CIA402Nodefile_path = os.path.join(buildpath, "cia402node_%s.c"%location_str)
   265             cia402nodefile = open(Gen_CIA402Nodefile_path, 'w')
   265             cia402nodefile = open(Gen_CIA402Nodefile_path, 'w')
   266             cia402nodefile.write(plc_cia402node_code % str_completion)
   266             cia402nodefile.write(plc_cia402node_code % str_completion)
   267             cia402nodefile.close()
   267             cia402nodefile.close()
   268             
   268             
   269             return [(Gen_CIA402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath()))],"",True
   269             return [(Gen_CIA402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))],"",True
   270 
   270 
   271 #--------------------------------------------------
   271 #--------------------------------------------------
   272 #                 Ethercat MASTER
   272 #                 Ethercat MASTER
   273 #--------------------------------------------------
   273 #--------------------------------------------------
   274 
   274 
   309         slave_info.setVendorId(ExtractHexDecValue(type_infos["vendor"]))
   309         slave_info.setVendorId(ExtractHexDecValue(type_infos["vendor"]))
   310         slave_info.setProductCode(ExtractHexDecValue(type_infos["product_code"]))
   310         slave_info.setProductCode(ExtractHexDecValue(type_infos["product_code"]))
   311         slave_info.setRevisionNo(ExtractHexDecValue(type_infos["revision_number"]))
   311         slave_info.setRevisionNo(ExtractHexDecValue(type_infos["revision_number"]))
   312     setattr(cls, "setType", setType)
   312     setattr(cls, "setType", setType)
   313 
   313 
   314 class _EthercatPlug:
   314 class _EthercatCTN:
   315     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   315     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   316     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   316     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   317       <xsd:element name="EtherlabNode">
   317       <xsd:element name="EtherlabNode">
   318         <xsd:complexType>
   318         <xsd:complexType>
   319           <xsd:attribute name="MasterNumber" type="xsd:integer" use="optional" default="0"/>
   319           <xsd:attribute name="MasterNumber" type="xsd:integer" use="optional" default="0"/>
   321         </xsd:complexType>
   321         </xsd:complexType>
   322       </xsd:element>
   322       </xsd:element>
   323     </xsd:schema>
   323     </xsd:schema>
   324     """
   324     """
   325     
   325     
   326     PlugChildsTypes = [("EthercatSlave", _EthercatSlavePlug, "Ethercat Slave")]
   326     CTNChildrenTypes = [("EthercatSlave", _EthercatSlaveCTN, "Ethercat Slave")]
   327     if HAS_MCL:
   327     if HAS_MCL:
   328         PlugChildsTypes.append(("EthercatCIA402Slave", _EthercatCIA402SlavePlug, "Ethercat CIA402 Slave"))
   328         CTNChildrenTypes.append(("EthercatCIA402Slave", _EthercatCIA402SlaveCTN, "Ethercat CIA402 Slave"))
   329     
   329     
   330     def __init__(self):
   330     def __init__(self):
   331         filepath = self.ConfigFileName()
   331         filepath = self.ConfigFileName()
   332         
   332         
   333         self.Config = EtherCATConfigClasses["EtherCATConfig"]()
   333         self.Config = EtherCATConfigClasses["EtherCATConfig"]()
   340                 if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "EtherCATConfig":
   340                 if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "EtherCATConfig":
   341                     self.Config.loadXMLTree(child, ["xmlns:xsi", "xsi:noNamespaceSchemaLocation"])
   341                     self.Config.loadXMLTree(child, ["xmlns:xsi", "xsi:noNamespaceSchemaLocation"])
   342                     self.CreateConfigBuffer(True)
   342                     self.CreateConfigBuffer(True)
   343         else:
   343         else:
   344             self.CreateConfigBuffer(False)
   344             self.CreateConfigBuffer(False)
   345             self.OnPlugSave()
   345             self.OnCTNSave()
   346 
   346 
   347     def ExtractHexDecValue(self, value):
   347     def ExtractHexDecValue(self, value):
   348         return ExtractHexDecValue(value)
   348         return ExtractHexDecValue(value)
   349 
   349 
   350     def GetSizeOfType(self, type):
   350     def GetSizeOfType(self, type):
   351         return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None)
   351         return TYPECONVERSION.get(self.GetCTRoot().GetBaseType(type), None)
   352 
   352 
   353     def ConfigFileName(self):
   353     def ConfigFileName(self):
   354         return os.path.join(self.PlugPath(), "config.xml")
   354         return os.path.join(self.CTNPath(), "config.xml")
   355 
   355 
   356     def GetSlaves(self):
   356     def GetSlaves(self):
   357         slaves = []
   357         slaves = []
   358         for slave in self.Config.getConfig().getSlave():
   358         for slave in self.Config.getConfig().getSlave():
   359             slaves.append(slave.getInfo().getPhysAddr())
   359             slaves.append(slave.getInfo().getPhysAddr())
   366             if slave_info.getPhysAddr() == slave_pos:
   366             if slave_info.getPhysAddr() == slave_pos:
   367                 return slave
   367                 return slave
   368         return None
   368         return None
   369 
   369 
   370     def _ScanNetwork(self):
   370     def _ScanNetwork(self):
   371         app_frame = self.GetPlugRoot().AppFrame
   371         app_frame = self.GetCTRoot().AppFrame
   372         
   372         
   373         execute = True
   373         execute = True
   374         if len(self.PluggedChilds) > 0:
   374         if len(self.Children) > 0:
   375             dialog = wx.MessageDialog(app_frame, 
   375             dialog = wx.MessageDialog(app_frame, 
   376                 _("The current network configuration will be deleted.\nDo you want to continue?"), 
   376                 _("The current network configuration will be deleted.\nDo you want to continue?"), 
   377                 _("Scan Network"), 
   377                 _("Scan Network"), 
   378                 wx.YES_NO|wx.ICON_QUESTION)
   378                 wx.YES_NO|wx.ICON_QUESTION)
   379             execute = dialog.ShowModal() == wx.ID_YES
   379             execute = dialog.ShowModal() == wx.ID_YES
   384             if error != 0:
   384             if error != 0:
   385                 dialog = wx.MessageDialog(app_frame, returnVal, "Error", wx.OK|wx.ICON_ERROR)
   385                 dialog = wx.MessageDialog(app_frame, returnVal, "Error", wx.OK|wx.ICON_ERROR)
   386                 dialog.ShowModal()
   386                 dialog.ShowModal()
   387                 dialog.Destroy()
   387                 dialog.Destroy()
   388             elif returnVal is not None:
   388             elif returnVal is not None:
   389                 for child in self.IECSortedChilds():
   389                 for child in self.IECSortedChildren():
   390                     self._doRemoveChild(child)
   390                     self._doRemoveChild(child)
   391                 
   391                 
   392                 for slave in returnVal:
   392                 for slave in returnVal:
   393                     type_infos = {
   393                     type_infos = {
   394                         "vendor": slave["vendor_id"],
   394                         "vendor": slave["vendor_id"],
   395                         "product_code": slave["product_code"],
   395                         "product_code": slave["product_code"],
   396                         "revision_number":slave["revision_number"],
   396                         "revision_number":slave["revision_number"],
   397                     }
   397                     }
   398                     device = self.GetModuleInfos(type_infos)
   398                     device = self.GetModuleInfos(type_infos)
   399                     if device is not None:
   399                     if device is not None:
   400                         if HAS_MCL and _EthercatCIA402SlavePlug.NODE_PROFILE in device.GetProfileNumbers():
   400                         if HAS_MCL and _EthercatCIA402SlaveCTN.NODE_PROFILE in device.GetProfileNumbers():
   401                             PlugType = "EthercatCIA402Slave"
   401                             CTNType = "EthercatCIA402Slave"
   402                         else:
   402                         else:
   403                             PlugType = "EthercatSlave"
   403                             CTNType = "EthercatSlave"
   404                         self.PlugAddChild("slave%s" % slave["idx"], PlugType, slave["idx"])
   404                         self.CTNAddChild("slave%s" % slave["idx"], CTNType, slave["idx"])
   405                         self.SetSlaveAlias(slave["idx"], slave["alias"])
   405                         self.SetSlaveAlias(slave["idx"], slave["alias"])
   406                         type_infos["device_type"] = device.getType().getcontent()
   406                         type_infos["device_type"] = device.getType().getcontent()
   407                         self.SetSlaveType(slave["idx"], type_infos)
   407                         self.SetSlaveType(slave["idx"], type_infos)
   408 
   408 
   409     def PlugAddChild(self, PlugName, PlugType, IEC_Channel=0):
   409     def CTNAddChild(self, CTNName, CTNType, IEC_Channel=0):
   410         """
   410         """
   411         Create the plugins that may be added as child to this node self
   411         Create the confnodes that may be added as child to this node self
   412         @param PlugType: string desining the plugin class name (get name from PlugChildsTypes)
   412         @param CTNType: string desining the confnode class name (get name from CTNChildrenTypes)
   413         @param PlugName: string for the name of the plugin instance
   413         @param CTNName: string for the name of the confnode instance
   414         """
   414         """
   415         newPluginOpj = PlugTemplate.PlugAddChild(self, PlugName, PlugType, IEC_Channel)
   415         newConfNodeOpj = ConfigTreeNode.CTNAddChild(self, CTNName, CTNType, IEC_Channel)
   416         
   416         
   417         slave = self.GetSlave(newPluginOpj.BaseParams.getIEC_Channel())
   417         slave = self.GetSlave(newConfNodeOpj.BaseParams.getIEC_Channel())
   418         if slave is None:
   418         if slave is None:
   419             slave = EtherCATConfigClasses["Config_Slave"]()
   419             slave = EtherCATConfigClasses["Config_Slave"]()
   420             slave_infos = slave.getInfo()
   420             slave_infos = slave.getInfo()
   421             slave_infos.setName("undefined")
   421             slave_infos.setName("undefined")
   422             slave_infos.setPhysAddr(newPluginOpj.BaseParams.getIEC_Channel())
   422             slave_infos.setPhysAddr(newConfNodeOpj.BaseParams.getIEC_Channel())
   423             slave_infos.setAutoIncAddr(0)
   423             slave_infos.setAutoIncAddr(0)
   424             self.Config.getConfig().appendSlave(slave)
   424             self.Config.getConfig().appendSlave(slave)
   425             self.BufferConfig()
   425             self.BufferConfig()
   426             self.OnPlugSave()
   426             self.OnCTNSave()
   427         
   427         
   428         return newPluginOpj
   428         return newConfNodeOpj
   429 
   429 
   430     def _doRemoveChild(self, PlugInstance):
   430     def _doRemoveChild(self, CTNInstance):
   431         slave_pos = PlugInstance.GetSlavePos()
   431         slave_pos = CTNInstance.GetSlavePos()
   432         config = self.Config.getConfig()
   432         config = self.Config.getConfig()
   433         for idx, slave in enumerate(config.getSlave()):
   433         for idx, slave in enumerate(config.getSlave()):
   434             slave_infos = slave.getInfo()
   434             slave_infos = slave.getInfo()
   435             if slave_infos.getPhysAddr() == slave_pos:
   435             if slave_infos.getPhysAddr() == slave_pos:
   436                 config.removeSlave(idx)
   436                 config.removeSlave(idx)
   437                 self.BufferConfig()
   437                 self.BufferConfig()
   438                 self.OnPlugSave()
   438                 self.OnCTNSave()
   439         PlugTemplate._doRemoveChild(self, PlugInstance)
   439         ConfigTreeNode._doRemoveChild(self, CTNInstance)
   440 
   440 
   441     def SetSlavePosition(self, slave_pos, new_pos):
   441     def SetSlavePosition(self, slave_pos, new_pos):
   442         slave = self.GetSlave(slave_pos)
   442         slave = self.GetSlave(slave_pos)
   443         if slave is not None:
   443         if slave is not None:
   444             slave_info = slave.getInfo()
   444             slave_info = slave.getInfo()
   499                               "entries": entries})
   499                               "entries": entries})
   500                 return infos
   500                 return infos
   501         return None
   501         return None
   502     
   502     
   503     def GetModuleInfos(self, type_infos):
   503     def GetModuleInfos(self, type_infos):
   504         return self.PlugParent.GetModuleInfos(type_infos)
   504         return self.CTNParent.GetModuleInfos(type_infos)
   505     
   505     
   506     def GetSlaveTypesLibrary(self, profile_filter=None):
   506     def GetSlaveTypesLibrary(self, profile_filter=None):
   507         return self.PlugParent.GetModulesLibrary(profile_filter)
   507         return self.CTNParent.GetModulesLibrary(profile_filter)
   508     
   508     
   509     def GetDeviceLocationTree(self, slave_pos, current_location, device_name):
   509     def GetDeviceLocationTree(self, slave_pos, current_location, device_name):
   510         slave = self.GetSlave(slave_pos)
   510         slave = self.GetSlave(slave_pos)
   511         if slave is not None:
   511         if slave is not None:
   512             type_infos = slave.getType()
   512             type_infos = slave.getType()
   546                                          "description": "",
   546                                          "description": "",
   547                                          "children": []})
   547                                          "children": []})
   548         
   548         
   549         return vars
   549         return vars
   550     
   550     
   551     def PlugTestModified(self):
   551     def CTNTestModified(self):
   552         return self.ChangesToSave or not self.ConfigIsSaved()    
   552         return self.ChangesToSave or not self.ConfigIsSaved()    
   553 
   553 
   554     def OnPlugSave(self):
   554     def OnCTNSave(self):
   555         filepath = self.ConfigFileName()
   555         filepath = self.ConfigFileName()
   556         
   556         
   557         text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
   557         text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
   558         extras = {"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
   558         extras = {"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
   559                   "xsi:noNamespaceSchemaLocation" : "EtherCATInfo.xsd"}
   559                   "xsi:noNamespaceSchemaLocation" : "EtherCATInfo.xsd"}
   573         
   573         
   574         Gen_Ethercatfile_path = os.path.join(buildpath, "ethercat_%s.c"%location_str)
   574         Gen_Ethercatfile_path = os.path.join(buildpath, "ethercat_%s.c"%location_str)
   575         
   575         
   576         self.FileGenerator = _EthercatCFileGenerator(self)
   576         self.FileGenerator = _EthercatCFileGenerator(self)
   577         
   577         
   578         LocationCFilesAndCFLAGS, LDFLAGS, extra_files = PlugTemplate._Generate_C(self, buildpath, locations)
   578         LocationCFilesAndCFLAGS, LDFLAGS, extra_files = ConfigTreeNode._Generate_C(self, buildpath, locations)
   579         
   579         
   580         self.FileGenerator.GenerateCFile(Gen_Ethercatfile_path, location_str, self.EtherlabNode)
   580         self.FileGenerator.GenerateCFile(Gen_Ethercatfile_path, location_str, self.EtherlabNode)
   581         
   581         
   582         LocationCFilesAndCFLAGS.append(
   582         LocationCFilesAndCFLAGS.append(
   583             (current_location, 
   583             (current_location, 
   584              [(Gen_Ethercatfile_path, '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath()))], 
   584              [(Gen_Ethercatfile_path, '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()))], 
   585              True))
   585              True))
   586         LDFLAGS.append("-lethercat -lrtdm")
   586         LDFLAGS.append("-lethercat -lrtdm")
   587         
   587         
   588         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
   588         return LocationCFilesAndCFLAGS, LDFLAGS, extra_files
   589 
   589 
   590     PluginMethods = [
   590     ConfNodeMethods = [
   591         {"bitmap" : os.path.join(PLUGINFOLDER, "images", "ScanNetwork"),
   591         {"bitmap" : os.path.join(CONFNODEFOLDER, "images", "ScanNetwork"),
   592          "name" : _("Scan Network"), 
   592          "name" : _("Scan Network"), 
   593          "tooltip" : _("Scan Network"),
   593          "tooltip" : _("Scan Network"),
   594          "method" : "_ScanNetwork"},
   594          "method" : "_ScanNetwork"},
   595     ]
   595     ]
   596 
   596 
   597     def PlugGenerate_C(self, buildpath, locations):
   597     def CTNGenerate_C(self, buildpath, locations):
   598         """
   598         """
   599         Generate C code
   599         Generate C code
   600         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   600         @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
   601         @param locations: List of complete variables locations \
   601         @param locations: List of complete variables locations \
   602             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
   602             [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
   603             "NAME" : name of the variable (generally "__IW0_1_2" style)
   603             "NAME" : name of the variable (generally "__IW0_1_2" style)
   604             "DIR" : direction "Q","I" or "M"
   604             "DIR" : direction "Q","I" or "M"
   605             "SIZE" : size "X", "B", "W", "D", "L"
   605             "SIZE" : size "X", "B", "W", "D", "L"
   931                                         message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
   931                                         message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
   932                                         if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != 
   932                                         if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != 
   933                                             self.Controler.GetSizeOfType(entry_type)):
   933                                             self.Controler.GetSizeOfType(entry_type)):
   934                                             raise ValueError, message
   934                                             raise ValueError, message
   935                                         else:
   935                                         else:
   936                                             self.Controler.GetPlugRoot().logger.write_warning(message + "\n")
   936                                             self.Controler.GetCTRoot().logger.write_warning(message + "\n")
   937                                     
   937                                     
   938                                     if (entry_infos["dir"] == "I" and pdo_type != "Inputs" or 
   938                                     if (entry_infos["dir"] == "I" and pdo_type != "Inputs" or 
   939                                         entry_infos["dir"] == "Q" and pdo_type != "Outputs"):
   939                                         entry_infos["dir"] == "Q" and pdo_type != "Outputs"):
   940                                         raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"]
   940                                         raise ValueError, _("Wrong direction for location \"%s\"!") % entry_infos["var_name"]
   941                                     
   941                                     
  1013                                 message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
  1013                                 message = _("Wrong type for location \"%s\"!") % entry_infos["var_name"]
  1014                                 if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != 
  1014                                 if (self.Controler.GetSizeOfType(entry_infos["var_type"]) != 
  1015                                     self.Controler.GetSizeOfType(entry["Type"])):
  1015                                     self.Controler.GetSizeOfType(entry["Type"])):
  1016                                     raise ValueError, message
  1016                                     raise ValueError, message
  1017                                 else:
  1017                                 else:
  1018                                     self.Controler.GetPlugRoot().logger.write_warning(message + "\n")
  1018                                     self.Controler.GetCTRoot().logger.write_warning(message + "\n")
  1019                             
  1019                             
  1020                             if entry_infos["dir"] == "I" and entry["PDOMapping"] in ["T", "RT"]:
  1020                             if entry_infos["dir"] == "I" and entry["PDOMapping"] in ["T", "RT"]:
  1021                                 pdo_type = "Inputs"
  1021                                 pdo_type = "Inputs"
  1022                             elif entry_infos["dir"] == "Q" and entry["PDOMapping"] in ["R", "RT"]:
  1022                             elif entry_infos["dir"] == "Q" and entry["PDOMapping"] in ["R", "RT"]:
  1023                                 pdo_type = "Outputs"
  1023                                 pdo_type = "Outputs"
  1092         etherlabfile = open(filepath, 'w')
  1092         etherlabfile = open(filepath, 'w')
  1093         etherlabfile.write(plc_etherlab_code % str_completion)
  1093         etherlabfile.write(plc_etherlab_code % str_completion)
  1094         etherlabfile.close()
  1094         etherlabfile.close()
  1095 
  1095 
  1096 #--------------------------------------------------
  1096 #--------------------------------------------------
  1097 #                 Ethercat Plugin
  1097 #                 Ethercat ConfNode
  1098 #--------------------------------------------------
  1098 #--------------------------------------------------
  1099 
  1099 
  1100 EtherCATInfoClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
  1100 EtherCATInfoClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "EtherCATInfo.xsd")) 
  1101 
  1101 
  1102 cls = EtherCATInfoClasses["EtherCATInfo.xsd"].get("DeviceType", None)
  1102 cls = EtherCATInfoClasses["EtherCATInfo.xsd"].get("DeviceType", None)
  1315                     "PDO name": pdo_name, 
  1315                     "PDO name": pdo_name, 
  1316                     "PDO type": pdo_type}
  1316                     "PDO type": pdo_type}
  1317 
  1317 
  1318 class RootClass:
  1318 class RootClass:
  1319     
  1319     
  1320     PlugChildsTypes = [("EthercatNode",_EthercatPlug,"Ethercat Master")]
  1320     CTNChildrenTypes = [("EthercatNode",_EthercatCTN,"Ethercat Master")]
  1321     
  1321     
  1322     def __init__(self):
  1322     def __init__(self):
  1323         self.LoadModulesLibrary()
  1323         self.LoadModulesLibrary()
  1324     
  1324     
  1325     def GetModulesLibraryPath(self):
  1325     def GetModulesLibraryPath(self):
  1326         library_path = os.path.join(self.PlugPath(), "modules")
  1326         library_path = os.path.join(self.CTNPath(), "modules")
  1327         if not os.path.exists(library_path):
  1327         if not os.path.exists(library_path):
  1328             os.mkdir(library_path)
  1328             os.mkdir(library_path)
  1329         return library_path
  1329         return library_path
  1330     
  1330     
  1331     def _ImportModuleLibrary(self):
  1331     def _ImportModuleLibrary(self):
  1332         dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, _("Choose an XML file"), os.getcwd(), "",  _("XML files (*.xml)|*.xml|All files|*.*"), wx.OPEN)
  1332         dialog = wx.FileDialog(self.GetCTRoot().AppFrame, _("Choose an XML file"), os.getcwd(), "",  _("XML files (*.xml)|*.xml|All files|*.*"), wx.OPEN)
  1333         if dialog.ShowModal() == wx.ID_OK:
  1333         if dialog.ShowModal() == wx.ID_OK:
  1334             filepath = dialog.GetPath()
  1334             filepath = dialog.GetPath()
  1335             if os.path.isfile(filepath):
  1335             if os.path.isfile(filepath):
  1336                 shutil.copy(filepath, self.GetModulesLibraryPath())
  1336                 shutil.copy(filepath, self.GetModulesLibraryPath())
  1337                 self.LoadModulesLibrary()
  1337                 self.LoadModulesLibrary()
  1338             else:
  1338             else:
  1339                 self.GetPlugRoot().logger.write_error(_("No such XML file: %s\n") % filepath)
  1339                 self.GetCTRoot().logger.write_error(_("No such XML file: %s\n") % filepath)
  1340         dialog.Destroy()  
  1340         dialog.Destroy()  
  1341     
  1341     
  1342     PluginMethods = [
  1342     ConfNodeMethods = [
  1343         {"bitmap" : os.path.join(PLUGINFOLDER, "images", "ImportESI"),
  1343         {"bitmap" : os.path.join(CONFNODEFOLDER, "images", "ImportESI"),
  1344          "name" : _("Import module library"), 
  1344          "name" : _("Import module library"), 
  1345          "tooltip" : _("Import module library"),
  1345          "tooltip" : _("Import module library"),
  1346          "method" : "_ImportModuleLibrary"},
  1346          "method" : "_ImportModuleLibrary"},
  1347     ]
  1347     ]
  1348     
  1348     
  1349     def PlugGenerate_C(self, buildpath, locations):
  1349     def CTNGenerate_C(self, buildpath, locations):
  1350         return [],"",False
  1350         return [],"",False
  1351     
  1351     
  1352     def LoadModulesLibrary(self):
  1352     def LoadModulesLibrary(self):
  1353         self.ModulesLibrary = {}
  1353         self.ModulesLibrary = {}
  1354         
  1354