canfestival/canfestival.py
changeset 1784 64beb9e9c749
parent 1783 3311eea28d56
child 1828 396da88d7b5c
equal deleted inserted replaced
1729:31e63e25b4cc 1784:64beb9e9c749
    21 #
    21 #
    22 # You should have received a copy of the GNU General Public License
    22 # You should have received a copy of the GNU General Public License
    23 # along with this program; if not, write to the Free Software
    23 # along with this program; if not, write to the Free Software
    24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    25 
    25 
    26 import os, sys, shutil
    26 import os
       
    27 import sys
       
    28 import shutil
       
    29 import wx
       
    30 from gnosis.xml.pickle import *
       
    31 from gnosis.xml.pickle.util import setParanoia
       
    32 
    27 import util.paths as paths
    33 import util.paths as paths
    28 
    34 from util.TranslationCatalogs import AddCatalog
    29 base_folder = paths.AbsParentDir(__file__, 2)
    35 from ConfigTreeNode import ConfigTreeNode
    30 CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
    36 from PLCControler import \
    31 sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
    37     LOCATION_CONFNODE, \
    32 
    38     LOCATION_MODULE, \
    33 import wx
    39     LOCATION_GROUP, \
    34 
    40     LOCATION_VAR_INPUT, \
    35 from nodelist import NodeList
    41     LOCATION_VAR_OUTPUT, \
       
    42     LOCATION_VAR_MEMORY
       
    43 
       
    44 try:
       
    45     from nodelist import NodeList
       
    46 except ImportError:
       
    47     base_folder = paths.AbsParentDir(__file__, 2)
       
    48     CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
       
    49     sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
       
    50 
       
    51     from nodelist import NodeList
       
    52 
       
    53 
    36 from nodemanager import NodeManager
    54 from nodemanager import NodeManager
    37 import config_utils, gen_cfile, eds_utils
    55 import config_utils
       
    56 import gen_cfile
       
    57 import eds_utils
    38 import canfestival_config as local_canfestival_config
    58 import canfestival_config as local_canfestival_config
    39 from ConfigTreeNode import ConfigTreeNode
    59 
    40 from commondialogs import CreateNodeDialog
    60 from commondialogs import CreateNodeDialog
    41 from subindextable import IECTypeConversion, SizeConversion
    61 from subindextable import IECTypeConversion, SizeConversion
    42 
       
    43 from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
       
    44 from SlaveEditor import SlaveEditor, MasterViewer
    62 from SlaveEditor import SlaveEditor, MasterViewer
    45 from NetworkEditor import NetworkEditor
    63 from NetworkEditor import NetworkEditor
    46 
    64 
    47 from gnosis.xml.pickle import *
    65 
    48 from gnosis.xml.pickle.util import setParanoia
    66 AddCatalog(os.path.join(CanFestivalPath, "objdictgen", "locale"))
    49 setParanoia(0)
    67 setParanoia(0)
    50 
    68 
    51 from util.TranslationCatalogs import AddCatalog
    69 
    52 AddCatalog(os.path.join(CanFestivalPath, "objdictgen", "locale"))
    70 # --------------------------------------------------
    53 
       
    54 #--------------------------------------------------
       
    55 #              Location Tree Helper
    71 #              Location Tree Helper
    56 #--------------------------------------------------
    72 # --------------------------------------------------
       
    73 
    57 
    74 
    58 def GetSlaveLocationTree(slave_node, current_location, name):
    75 def GetSlaveLocationTree(slave_node, current_location, name):
    59     entries = []
    76     entries = []
    60     for index, subindex, size, entry_name in slave_node.GetMapVariableList():
    77     for index, subindex, size, entry_name in slave_node.GetMapVariableList():
    61         subentry_infos = slave_node.GetSubentryInfos(index, subindex)
    78         subentry_infos = slave_node.GetSubentryInfos(index, subindex)
    65                 "name": "0x%4.4x-0x%2.2x: %s" % (index, subindex, entry_name),
    82                 "name": "0x%4.4x-0x%2.2x: %s" % (index, subindex, entry_name),
    66                 "type": LOCATION_VAR_MEMORY,
    83                 "type": LOCATION_VAR_MEMORY,
    67                 "size": size,
    84                 "size": size,
    68                 "IEC_type": IECTypeConversion.get(typeinfos["name"]),
    85                 "IEC_type": IECTypeConversion.get(typeinfos["name"]),
    69                 "var_name": "%s_%4.4x_%2.2x" % ("_".join(name.split()), index, subindex),
    86                 "var_name": "%s_%4.4x_%2.2x" % ("_".join(name.split()), index, subindex),
    70                 "location": "%s%s"%(SizeConversion[size], ".".join(map(str, current_location + 
    87                 "location": "%s%s" % (SizeConversion[size], ".".join(map(str, current_location +
    71                                                                                 (index, subindex)))),
    88                                                                          (index, subindex)))),
    72                 "description": "",
    89                 "description": "",
    73                 "children": []})
    90                 "children": []})
    74     return  {"name": name,
    91     return {"name": name,
    75              "type": LOCATION_CONFNODE,
    92             "type": LOCATION_CONFNODE,
    76              "location": ".".join([str(i) for i in current_location]) + ".x",
    93             "location": ".".join([str(i) for i in current_location]) + ".x",
    77              "children": entries
    94             "children": entries}
    78     }
    95 
    79 
    96 # --------------------------------------------------
    80 #--------------------------------------------------
       
    81 #                    SLAVE
    97 #                    SLAVE
    82 #--------------------------------------------------
    98 # --------------------------------------------------
       
    99 
    83 
   100 
    84 class _SlaveCTN(NodeManager):
   101 class _SlaveCTN(NodeManager):
    85     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   102     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    86     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   103     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    87       <xsd:element name="CanFestivalSlaveNode">
   104       <xsd:element name="CanFestivalSlaveNode">
   100           </xsd:attribute>
   117           </xsd:attribute>
   101         </xsd:complexType>
   118         </xsd:complexType>
   102       </xsd:element>
   119       </xsd:element>
   103     </xsd:schema>
   120     </xsd:schema>
   104     """
   121     """
   105     
   122 
   106     EditorType = SlaveEditor
   123     EditorType = SlaveEditor
   107     IconPath = os.path.join(CanFestivalPath, "objdictgen", "networkedit.png")
   124     IconPath = os.path.join(CanFestivalPath, "objdictgen", "networkedit.png")
   108 
   125 
   109     def __init__(self):
   126     def __init__(self):
   110         # TODO change netname when name change
   127         # TODO change netname when name change
   120             if dialog.ShowModal() == wx.ID_OK:
   137             if dialog.ShowModal() == wx.ID_OK:
   121                 name, id, nodetype, description = dialog.GetValues()
   138                 name, id, nodetype, description = dialog.GetValues()
   122                 profile, filepath = dialog.GetProfile()
   139                 profile, filepath = dialog.GetProfile()
   123                 NMT = dialog.GetNMTManagement()
   140                 NMT = dialog.GetNMTManagement()
   124                 options = dialog.GetOptions()
   141                 options = dialog.GetOptions()
   125                 self.CreateNewNode(name,       # Name - will be changed at build time
   142                 self.CreateNewNode(name,         # Name - will be changed at build time
   126                                    id,         # NodeID - will be changed at build time
   143                                    id,           # NodeID - will be changed at build time
   127                                    "slave",    # Type
   144                                    "slave",      # Type
   128                                    description,# description 
   145                                    description,  # description
   129                                    profile,    # profile
   146                                    profile,      # profile
   130                                    filepath,   # prfile filepath
   147                                    filepath,     # prfile filepath
   131                                    NMT,        # NMT
   148                                    NMT,          # NMT
   132                                    options)     # options
   149                                    options)      # options
   133             else:
   150             else:
   134                 self.CreateNewNode("SlaveNode",  # Name - will be changed at build time
   151                 self.CreateNewNode("SlaveNode",  # Name - will be changed at build time
   135                                    0x00,         # NodeID - will be changed at build time
   152                                    0x00,         # NodeID - will be changed at build time
   136                                    "slave",      # Type
   153                                    "slave",      # Type
   137                                    "",           # description 
   154                                    "",           # description
   138                                    "None",       # profile
   155                                    "None",       # profile
   139                                    "", # prfile filepath
   156                                    "",           # prfile filepath
   140                                    "heartbeat",  # NMT
   157                                    "heartbeat",  # NMT
   141                                    [])           # options
   158                                    [])           # options
   142             dialog.Destroy()
   159             dialog.Destroy()
   143             self.OnCTNSave()
   160             self.OnCTNSave()
   144 
   161 
   154     def _OpenView(self, name=None, onlyopened=False):
   171     def _OpenView(self, name=None, onlyopened=False):
   155         ConfigTreeNode._OpenView(self, name, onlyopened)
   172         ConfigTreeNode._OpenView(self, name, onlyopened)
   156         if self._View is not None:
   173         if self._View is not None:
   157             self._View.SetBusId(self.GetCurrentLocation())
   174             self._View.SetBusId(self.GetCurrentLocation())
   158         return self._View
   175         return self._View
   159     
   176 
   160     def _ExportSlave(self):
   177     def _ExportSlave(self):
   161         dialog = wx.FileDialog(self.GetCTRoot().AppFrame, 
   178         dialog = wx.FileDialog(self.GetCTRoot().AppFrame,
   162                                _("Choose a file"), 
   179                                _("Choose a file"),
   163                                os.path.expanduser("~"), 
   180                                os.path.expanduser("~"),
   164                                "%s.eds" % self.CTNName(),  
   181                                "%s.eds" % self.CTNName(),
   165                                _("EDS files (*.eds)|*.eds|All files|*.*"),
   182                                _("EDS files (*.eds)|*.eds|All files|*.*"),
   166                                wx.SAVE|wx.OVERWRITE_PROMPT)
   183                                wx.SAVE | wx.OVERWRITE_PROMPT)
   167         if dialog.ShowModal() == wx.ID_OK:
   184         if dialog.ShowModal() == wx.ID_OK:
   168             result = eds_utils.GenerateEDSFile(dialog.GetPath(), self.GetCurrentNodeCopy())
   185             result = eds_utils.GenerateEDSFile(dialog.GetPath(), self.GetCurrentNodeCopy())
   169             if result:
   186             if result:
   170                 self.GetCTRoot().logger.write_error(_("Error: Export slave failed\n"))
   187                 self.GetCTRoot().logger.write_error(_("Error: Export slave failed\n"))
   171         dialog.Destroy()  
   188         dialog.Destroy()
   172         
   189 
   173     ConfNodeMethods = [
   190     ConfNodeMethods = [
   174         {"bitmap" : "ExportSlave",
   191         {
   175          "name" : _("Export slave"), 
   192             "bitmap":    "ExportSlave",
   176          "tooltip" : _("Export CanOpen slave to EDS file"),
   193             "name":    _("Export slave"),
   177          "method" : "_ExportSlave"},
   194             "tooltip": _("Export CanOpen slave to EDS file"),
       
   195             "method":   "_ExportSlave"
       
   196         },
   178     ]
   197     ]
   179     
   198 
   180     def CTNTestModified(self):
   199     def CTNTestModified(self):
   181         return self.ChangesToSave or self.OneFileHasChanged()
   200         return self.ChangesToSave or self.OneFileHasChanged()
   182         
   201 
   183     def OnCTNSave(self, from_project_path=None):
   202     def OnCTNSave(self, from_project_path=None):
   184         return self.SaveCurrentInFile(self.GetSlaveODPath())
   203         return self.SaveCurrentInFile(self.GetSlaveODPath())
   185 
   204 
   186     def SetParamsAttribute(self, path, value):
   205     def SetParamsAttribute(self, path, value):
   187         result = ConfigTreeNode.SetParamsAttribute(self, path, value)
   206         result = ConfigTreeNode.SetParamsAttribute(self, path, value)
   188         
   207 
   189         # Filter IEC_Channel and Name, that have specific behavior
   208         # Filter IEC_Channel and Name, that have specific behavior
   190         if path == "BaseParams.IEC_Channel" and self._View is not None:
   209         if path == "BaseParams.IEC_Channel" and self._View is not None:
   191             self._View.SetBusId(self.GetCurrentLocation())
   210             self._View.SetBusId(self.GetCurrentLocation())
   192         
   211 
   193         return result
   212         return result
   194     
   213 
   195     def GetVariableLocationTree(self):
   214     def GetVariableLocationTree(self):
   196         current_location = self.GetCurrentLocation()
   215         current_location = self.GetCurrentLocation()
   197         return GetSlaveLocationTree(self.CurrentNode, 
   216         return GetSlaveLocationTree(self.CurrentNode,
   198                                     self.GetCurrentLocation(), 
   217                                     self.GetCurrentLocation(),
   199                                     self.BaseParams.getName())
   218                                     self.BaseParams.getName())
   200     
   219 
   201     def CTNGenerate_C(self, buildpath, locations):
   220     def CTNGenerate_C(self, buildpath, locations):
   202         """
   221         """
   203         Generate C code
   222         Generate C code
   204         @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
   223         @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
   205         @param locations: List of complete variables locations \
   224         @param locations: List of complete variables locations \
   212         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   231         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   213         """
   232         """
   214         current_location = self.GetCurrentLocation()
   233         current_location = self.GetCurrentLocation()
   215         # define a unique name for the generated C file
   234         # define a unique name for the generated C file
   216         prefix = "_".join(map(str, current_location))
   235         prefix = "_".join(map(str, current_location))
   217         Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
   236         Gen_OD_path = os.path.join(buildpath, "OD_%s.c" % prefix)
   218         # Create a new copy of the model
   237         # Create a new copy of the model
   219         slave = self.GetCurrentNodeCopy()
   238         slave = self.GetCurrentNodeCopy()
   220         slave.SetNodeName("OD_%s"%prefix)
   239         slave.SetNodeName("OD_%s" % prefix)
   221         # allow access to local OD from Slave PLC
   240         # allow access to local OD from Slave PLC
   222         pointers = config_utils.LocalODPointers(locations, current_location, slave)
   241         pointers = config_utils.LocalODPointers(locations, current_location, slave)
   223         res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
   242         res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
   224         if res :
   243         if res:
   225             raise Exception, res
   244             raise Exception(res)
   226         res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave)
   245         res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds" % prefix), slave)
   227         if res :
   246         if res:
   228             raise Exception, res
   247             raise Exception(res)
   229         return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
   248         return [(Gen_OD_path, local_canfestival_config.getCFLAGS(CanFestivalPath))], "", False
   230 
   249 
   231     def LoadPrevious(self):
   250     def LoadPrevious(self):
   232         self.LoadCurrentPrevious()
   251         self.LoadCurrentPrevious()
   233     
   252 
   234     def LoadNext(self):
   253     def LoadNext(self):
   235         self.LoadCurrentNext()
   254         self.LoadCurrentNext()
   236     
   255 
   237     def GetBufferState(self):
   256     def GetBufferState(self):
   238         return self.GetCurrentBufferState()
   257         return self.GetCurrentBufferState()
   239 
   258 
   240 #--------------------------------------------------
   259 # --------------------------------------------------
   241 #                    MASTER
   260 #                    MASTER
   242 #--------------------------------------------------
   261 # --------------------------------------------------
       
   262 
   243 
   263 
   244 class MiniNodeManager(NodeManager):
   264 class MiniNodeManager(NodeManager):
   245     
   265 
   246     def __init__(self, parent, filepath, fullname):
   266     def __init__(self, parent, filepath, fullname):
   247         NodeManager.__init__(self)
   267         NodeManager.__init__(self)
   248         
   268 
   249         self.OpenFileInCurrent(filepath)
   269         self.OpenFileInCurrent(filepath)
   250             
   270 
   251         self.Parent = parent
   271         self.Parent = parent
   252         self.Fullname = fullname
   272         self.Fullname = fullname
   253     
   273 
   254     def GetIconName(self):
   274     def GetIconName(self):
   255         return None
   275         return None
   256     
   276 
   257     def OnCloseEditor(self, view):
   277     def OnCloseEditor(self, view):
   258         self.Parent.OnCloseEditor(view)
   278         self.Parent.OnCloseEditor(view)
   259     
   279 
   260     def CTNFullName(self):
   280     def CTNFullName(self):
   261         return self.Fullname
   281         return self.Fullname
   262     
   282 
   263     def CTNTestModified(self):
   283     def CTNTestModified(self):
   264         return False
   284         return False
   265     
   285 
   266     def GetBufferState(self):
   286     def GetBufferState(self):
   267         return self.GetCurrentBufferState()
   287         return self.GetCurrentBufferState()
   268     
   288 
   269     ConfNodeMethods = []
   289     ConfNodeMethods = []
       
   290 
   270 
   291 
   271 class _NodeManager(NodeManager):
   292 class _NodeManager(NodeManager):
   272 
   293 
   273     def __init__(self, parent, *args, **kwargs):
   294     def __init__(self, parent, *args, **kwargs):
   274         NodeManager.__init__(self, *args, **kwargs)
   295         NodeManager.__init__(self, *args, **kwargs)
   275         self.Parent = parent
   296         self.Parent = parent
   276         
   297 
   277     def __del__(self):
   298     def __del__(self):
   278         self.Parent = None
   299         self.Parent = None
   279         
   300 
   280     def GetCurrentNodeName(self):
   301     def GetCurrentNodeName(self):
   281         return self.Parent.CTNName()
   302         return self.Parent.CTNName()
   282     
   303 
   283     def GetCurrentNodeID(self):
   304     def GetCurrentNodeID(self):
   284         return self.Parent.CanFestivalNode.getNodeId()
   305         return self.Parent.CanFestivalNode.getNodeId()
   285     
   306 
       
   307 
   286 class _NodeListCTN(NodeList):
   308 class _NodeListCTN(NodeList):
   287     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   309     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   288     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   310     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   289       <xsd:element name="CanFestivalNode">
   311       <xsd:element name="CanFestivalNode">
   290         <xsd:complexType>
   312         <xsd:complexType>
   293           <xsd:attribute name="NodeId" type="xsd:integer" use="optional" default="1"/>
   315           <xsd:attribute name="NodeId" type="xsd:integer" use="optional" default="1"/>
   294           <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
   316           <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
   295         </xsd:complexType>
   317         </xsd:complexType>
   296       </xsd:element>
   318       </xsd:element>
   297     </xsd:schema>
   319     </xsd:schema>
   298     """ 
   320     """
   299     
   321 
   300     EditorType = NetworkEditor
   322     EditorType = NetworkEditor
   301     IconPath = os.path.join(CanFestivalPath, "objdictgen", "networkedit.png")
   323     IconPath = os.path.join(CanFestivalPath, "objdictgen", "networkedit.png")
   302     
   324 
   303     def __init__(self):
   325     def __init__(self):
   304         manager = _NodeManager(self)
   326         manager = _NodeManager(self)
   305         NodeList.__init__(self, manager)
   327         NodeList.__init__(self, manager)
   306         self.LoadProject(self.CTNPath())
   328         self.LoadProject(self.CTNPath())
   307         self.SetNetworkName(self.BaseParams.getName())
   329         self.SetNetworkName(self.BaseParams.getName())
   308     
   330 
   309     def GetCanDevice(self):
   331     def GetCanDevice(self):
   310         return self.CanFestivalNode.getCAN_Device()
   332         return self.CanFestivalNode.getCAN_Device()
   311     
   333 
   312     def SetParamsAttribute(self, path, value):
   334     def SetParamsAttribute(self, path, value):
   313         if path == "CanFestivalNode.NodeId":
   335         if path == "CanFestivalNode.NodeId":
   314             nodeid = self.CanFestivalNode.getNodeId()
   336             nodeid = self.CanFestivalNode.getNodeId()
   315             if value != nodeid:
   337             if value != nodeid:
   316                 slaves = self.GetSlaveIDs()
   338                 slaves = self.GetSlaveIDs()
   317                 dir = (value - nodeid) / abs(value - nodeid)
   339                 dir = (value - nodeid) / abs(value - nodeid)
   318                 while value in slaves and value >= 0:
   340                 while value in slaves and value >= 0:
   319                     value += dir
   341                     value += dir
   320                 if value < 0:
   342                 if value < 0:
   321                     value = nodeid
   343                     value = nodeid
   322         
   344 
   323         value, refresh = ConfigTreeNode.SetParamsAttribute(self, path, value)
   345         value, refresh = ConfigTreeNode.SetParamsAttribute(self, path, value)
   324         refresh_network = False
   346         refresh_network = False
   325         
   347 
   326         # Filter IEC_Channel and Name, that have specific behavior
   348         # Filter IEC_Channel and Name, that have specific behavior
   327         if path == "BaseParams.IEC_Channel" and self._View is not None:
   349         if path == "BaseParams.IEC_Channel" and self._View is not None:
   328             self._View.SetBusId(self.GetCurrentLocation())
   350             self._View.SetBusId(self.GetCurrentLocation())
   329         elif path == "BaseParams.Name":
   351         elif path == "BaseParams.Name":
   330             self.SetNetworkName(value)
   352             self.SetNetworkName(value)
   331             refresh_network = True
   353             refresh_network = True
   332         elif path == "CanFestivalNode.NodeId":
   354         elif path == "CanFestivalNode.NodeId":
   333             refresh_network = True
   355             refresh_network = True
   334             
   356 
   335         if refresh_network and self._View is not None:
   357         if refresh_network and self._View is not None:
   336             wx.CallAfter(self._View.RefreshBufferState)
   358             wx.CallAfter(self._View.RefreshBufferState)
   337         return value, refresh
   359         return value, refresh
   338     
   360 
   339     def GetVariableLocationTree(self):
   361     def GetVariableLocationTree(self):
   340         current_location = self.GetCurrentLocation()
   362         current_location = self.GetCurrentLocation()
   341         nodeindexes = self.SlaveNodes.keys()
   363         nodeindexes = self.SlaveNodes.keys()
   342         nodeindexes.sort()
   364         nodeindexes.sort()
   343         return {"name": self.BaseParams.getName(),
   365         children = []
   344                  "type": LOCATION_CONFNODE,
   366         children += [GetSlaveLocationTree(self.Manager.GetCurrentNodeCopy(),
   345                  "location": self.GetFullIEC_Channel(),
   367                                           current_location,
   346                  "children": [GetSlaveLocationTree(self.Manager.GetCurrentNodeCopy(),
   368                                           _("Local entries"))]
   347                                                    current_location,
   369         children += [GetSlaveLocationTree(self.SlaveNodes[nodeid]["Node"],
   348                                                    _("Local entries"))] + 
   370                                           current_location + (nodeid,),
   349                              [GetSlaveLocationTree(self.SlaveNodes[nodeid]["Node"], 
   371                                           self.SlaveNodes[nodeid]["Name"]) for nodeid in nodeindexes]
   350                                                    current_location + (nodeid,), 
   372 
   351                                                    self.SlaveNodes[nodeid]["Name"])
   373         return {
   352                               for nodeid in nodeindexes]
   374             "name":     self.BaseParams.getName(),
       
   375             "type":     LOCATION_CONFNODE,
       
   376             "location": self.GetFullIEC_Channel(),
       
   377             "children": children
   353         }
   378         }
   354     
   379 
   355     _GeneratedMasterView = None
   380     _GeneratedMasterView = None
       
   381 
   356     def _ShowGeneratedMaster(self):
   382     def _ShowGeneratedMaster(self):
   357         self._OpenView("Generated master")
   383         self._OpenView("Generated master")
   358         
   384 
   359     def _OpenView(self, name=None, onlyopened=False):
   385     def _OpenView(self, name=None, onlyopened=False):
   360         if name == "Generated master":
   386         if name == "Generated master":
   361             app_frame = self.GetCTRoot().AppFrame
   387             app_frame = self.GetCTRoot().AppFrame
   362             if self._GeneratedMasterView is None:
   388             if self._GeneratedMasterView is None:
   363                 buildpath = self._getBuildPath()
   389                 buildpath = self._getBuildPath()
   364                 # Eventually create build dir
   390                 # Eventually create build dir
   365                 if not os.path.exists(buildpath):
   391                 if not os.path.exists(buildpath):
   366                     self.GetCTRoot().logger.write_error(_("Error: No PLC built\n"))
   392                     self.GetCTRoot().logger.write_error(_("Error: No PLC built\n"))
   367                     return
   393                     return
   368                 
   394 
   369                 masterpath = os.path.join(buildpath, "MasterGenerated.od")
   395                 masterpath = os.path.join(buildpath, "MasterGenerated.od")
   370                 if not os.path.exists(masterpath):
   396                 if not os.path.exists(masterpath):
   371                     self.GetCTRoot().logger.write_error(_("Error: No Master generated\n"))
   397                     self.GetCTRoot().logger.write_error(_("Error: No Master generated\n"))
   372                     return
   398                     return
   373                 
   399 
   374                 manager = MiniNodeManager(self, masterpath, self.CTNFullName())
   400                 manager = MiniNodeManager(self, masterpath, self.CTNFullName())
   375                 self._GeneratedMasterView = MasterViewer(app_frame.TabsOpened, manager, app_frame, name)
   401                 self._GeneratedMasterView = MasterViewer(app_frame.TabsOpened, manager, app_frame, name)
   376                 
   402 
   377             if self._GeneratedMasterView is not None:
   403             if self._GeneratedMasterView is not None:
   378                 app_frame.EditProjectElement(self._GeneratedMasterView, self._GeneratedMasterView.GetInstancePath())
   404                 app_frame.EditProjectElement(self._GeneratedMasterView, self._GeneratedMasterView.GetInstancePath())
   379             
   405 
   380             return self._GeneratedMasterView
   406             return self._GeneratedMasterView
   381         else:
   407         else:
   382             ConfigTreeNode._OpenView(self, name, onlyopened)
   408             ConfigTreeNode._OpenView(self, name, onlyopened)
   383             if self._View is not None:
   409             if self._View is not None:
   384                 self._View.SetBusId(self.GetCurrentLocation())
   410                 self._View.SetBusId(self.GetCurrentLocation())
   385             return self._View
   411             return self._View
   386     
   412 
   387     ConfNodeMethods = [
   413     ConfNodeMethods = [
   388         {"bitmap" : "ShowMaster",
   414         {
   389          "name" : _("Show Master"), 
   415             "bitmap":    "ShowMaster",
   390          "tooltip" : _("Show Master generated by config_utils"),
   416             "name":    _("Show Master"),
   391          "method" : "_ShowGeneratedMaster"}
   417             "tooltip": _("Show Master generated by config_utils"),
       
   418             "method":   "_ShowGeneratedMaster"
       
   419         }
   392     ]
   420     ]
   393     
   421 
   394     def OnCloseEditor(self, view):
   422     def OnCloseEditor(self, view):
   395         ConfigTreeNode.OnCloseEditor(self, view)
   423         ConfigTreeNode.OnCloseEditor(self, view)
   396         if self._GeneratedMasterView == view:
   424         if self._GeneratedMasterView == view:
   397             self._GeneratedMasterView = None
   425             self._GeneratedMasterView = None
   398     
   426 
   399     def OnCTNClose(self):
   427     def OnCTNClose(self):
   400         ConfigTreeNode.OnCTNClose(self)
   428         ConfigTreeNode.OnCTNClose(self)
   401         self._CloseView(self._GeneratedMasterView)
   429         self._CloseView(self._GeneratedMasterView)
   402         return True
   430         return True
   403 
   431 
   404     def CTNTestModified(self):
   432     def CTNTestModified(self):
   405         return self.ChangesToSave or self.HasChanged()
   433         return self.ChangesToSave or self.HasChanged()
   406         
   434 
   407     def OnCTNSave(self, from_project_path=None):
   435     def OnCTNSave(self, from_project_path=None):
   408         self.SetRoot(self.CTNPath())
   436         self.SetRoot(self.CTNPath())
   409         if from_project_path is not None:
   437         if from_project_path is not None:
   410             shutil.copytree(self.GetEDSFolder(from_project_path), 
   438             shutil.copytree(self.GetEDSFolder(from_project_path),
   411                             self.GetEDSFolder())
   439                             self.GetEDSFolder())
   412         return self.SaveProject() is None
   440         return self.SaveProject() is None
   413 
   441 
   414     def CTNGenerate_C(self, buildpath, locations):
   442     def CTNGenerate_C(self, buildpath, locations):
   415         """
   443         """
   426         """
   454         """
   427         self._CloseView(self._GeneratedMasterView)
   455         self._CloseView(self._GeneratedMasterView)
   428         current_location = self.GetCurrentLocation()
   456         current_location = self.GetCurrentLocation()
   429         # define a unique name for the generated C file
   457         # define a unique name for the generated C file
   430         prefix = "_".join(map(str, current_location))
   458         prefix = "_".join(map(str, current_location))
   431         Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
   459         Gen_OD_path = os.path.join(buildpath, "OD_%s.c" % prefix)
   432         # Create a new copy of the model with DCF loaded with PDO mappings for desired location
   460         # Create a new copy of the model with DCF loaded with PDO mappings for desired location
   433         try:
   461         try:
   434             master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
   462             master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(), "OD_%s" % prefix)
   435         except config_utils.PDOmappingException, e:
   463         except config_utils.PDOmappingException, e:
   436             raise Exception, e.message
   464             raise Exception(e.message)
   437         # Do generate C file.
   465         # Do generate C file.
   438         res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
   466         res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
   439         if res :
   467         if res:
   440             raise Exception, res
   468             raise Exception(res)
   441         
   469 
   442         file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
   470         file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
   443         dump(master, file)
   471         dump(master, file)
   444         file.close()
   472         file.close()
   445         
   473 
   446         return [(Gen_OD_path,local_canfestival_config.getCFLAGS(CanFestivalPath))],"",False
   474         return [(Gen_OD_path, local_canfestival_config.getCFLAGS(CanFestivalPath))], "", False
   447     
   475 
   448     def LoadPrevious(self):
   476     def LoadPrevious(self):
   449         self.Manager.LoadCurrentPrevious()
   477         self.Manager.LoadCurrentPrevious()
   450     
   478 
   451     def LoadNext(self):
   479     def LoadNext(self):
   452         self.Manager.LoadCurrentNext()
   480         self.Manager.LoadCurrentNext()
   453     
   481 
   454     def GetBufferState(self):
   482     def GetBufferState(self):
   455         return self.Manager.GetCurrentBufferState()
   483         return self.Manager.GetCurrentBufferState()
   456     
   484 
       
   485 
   457 class RootClass:
   486 class RootClass:
   458     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   487     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   459     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   488     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   460       <xsd:element name="CanFestivalInstance">
   489       <xsd:element name="CanFestivalInstance">
   461         <xsd:complexType>
   490         <xsd:complexType>
   462           <xsd:attribute name="CAN_Driver" type="xsd:string" use="optional"/>
   491           <xsd:attribute name="CAN_Driver" type="xsd:string" use="optional"/>
   463         </xsd:complexType>
   492         </xsd:complexType>
   464       </xsd:element>
   493       </xsd:element>
   465     </xsd:schema>
   494     </xsd:schema>
   466     """
   495     """
   467     
   496 
   468     CTNChildrenTypes = [("CanOpenNode",_NodeListCTN, "CanOpen Master"),
   497     CTNChildrenTypes = [("CanOpenNode",  _NodeListCTN, "CanOpen Master"),
   469                        ("CanOpenSlave",_SlaveCTN, "CanOpen Slave")]
   498                         ("CanOpenSlave", _SlaveCTN,    "CanOpen Slave")]
   470     def GetParamsAttributes(self, path = None):
   499 
   471         infos = ConfigTreeNode.GetParamsAttributes(self, path = path)
   500     def GetParamsAttributes(self, path=None):
       
   501         infos = ConfigTreeNode.GetParamsAttributes(self, path=path)
   472         for element in infos:
   502         for element in infos:
   473             if element["name"] == "CanFestivalInstance":
   503             if element["name"] == "CanFestivalInstance":
   474                 for child in element["children"]:
   504                 for child in element["children"]:
   475                     if child["name"] == "CAN_Driver":
   505                     if child["name"] == "CAN_Driver":
   476                         child["type"] = local_canfestival_config.DLL_LIST
   506                         child["type"] = local_canfestival_config.DLL_LIST
   477         return infos
   507         return infos
   478     
   508 
   479     def GetCanDriver(self):
   509     def GetCanDriver(self):
   480         res = self.CanFestivalInstance.getCAN_Driver()
   510         res = self.CanFestivalInstance.getCAN_Driver()
   481         if not res :
   511         if not res:
   482             return ""
   512             return ""
   483         return res
   513         return res
   484         
   514 
   485     def CTNGenerate_C(self, buildpath, locations):
   515     def CTNGenerate_C(self, buildpath, locations):
   486         can_driver = self.GetCanDriver()
   516         can_driver = self.GetCanDriver()
   487         if can_driver is not None:
   517         if can_driver is not None:
   488             can_drivers = local_canfestival_config.DLL_LIST
   518             can_drivers = local_canfestival_config.DLL_LIST
   489             if can_driver not in can_drivers :
   519             if can_driver not in can_drivers:
   490                 can_driver = can_drivers[0]
   520                 can_driver = can_drivers[0]
   491             can_drv_ext = self.GetCTRoot().GetBuilder().extension
   521             can_drv_ext = self.GetCTRoot().GetBuilder().extension
   492             can_drv_prefix = self.GetCTRoot().GetBuilder().dlopen_prefix
   522             can_drv_prefix = self.GetCTRoot().GetBuilder().dlopen_prefix
   493             can_driver_name = can_drv_prefix + "libcanfestival_" + can_driver + can_drv_ext
   523             can_driver_name = can_drv_prefix + "libcanfestival_" + can_driver + can_drv_ext
   494         else:
   524         else:
   495             can_driver_name = ""
   525             can_driver_name = ""
   496 
   526 
   497         
   527         format_dict = {"locstr": "_".join(map(str, self.GetCurrentLocation())),
   498         format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())),
   528                        "candriver": can_driver_name,
   499                        "candriver" : can_driver_name,
   529                        "nodes_includes": "",
   500                        "nodes_includes" : "",
   530                        "board_decls": "",
   501                        "board_decls" : "",
   531                        "nodes_init": "",
   502                        "nodes_init" : "",
   532                        "nodes_open": "",
   503                        "nodes_open" : "",
   533                        "nodes_stop": "",
   504                        "nodes_stop" : "",
   534                        "nodes_close": "",
   505                        "nodes_close" : "",
   535                        "nodes_send_sync": "",
   506                        "nodes_send_sync" : "",
   536                        "nodes_proceed_sync": "",
   507                        "nodes_proceed_sync" : "",
   537                        "slavebootups": "",
   508                        "slavebootups" : "",
   538                        "slavebootup_register": "",
   509                        "slavebootup_register" : "",
   539                        "post_sync": "",
   510                        "post_sync" : "",
   540                        "post_sync_register": "",
   511                        "post_sync_register" : "",
   541                        "pre_op": "",
   512                        "pre_op" : "",
   542                        "pre_op_register": "",
   513                        "pre_op_register" : "",
       
   514                        }
   543                        }
   515         for child in self.IECSortedChildren():
   544         for child in self.IECSortedChildren():
   516             childlocstr = "_".join(map(str,child.GetCurrentLocation()))
   545             childlocstr = "_".join(map(str, child.GetCurrentLocation()))
   517             nodename = "OD_%s" % childlocstr
   546             nodename = "OD_%s" % childlocstr
   518             
   547 
   519             # Try to get Slave Node
   548             # Try to get Slave Node
   520             child_data = getattr(child, "CanFestivalSlaveNode", None)
   549             child_data = getattr(child, "CanFestivalSlaveNode", None)
   521             if child_data is None:
   550             if child_data is None:
   522                 # Not a slave -> master
   551                 # Not a slave -> master
   523                 child_data = getattr(child, "CanFestivalNode")
   552                 child_data = getattr(child, "CanFestivalNode")
   524                 # Apply sync setting
   553                 # Apply sync setting
   525                 format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n    '%(
   554                 format_dict["nodes_init"] += 'NODE_MASTER_INIT(%s, %s)\n    ' % (
   526                        nodename,
   555                        nodename,
   527                        child_data.getNodeId())
   556                        child_data.getNodeId())
   528                 if child_data.getSync_TPDOs():
   557                 if child_data.getSync_TPDOs():
   529                     format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n    '%(nodename)
   558                     format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n    ' % (nodename)
   530                     format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n    '%(nodename)
   559                     format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n    ' % (nodename)
   531 
   560 
   532                 # initialize and declare node boot status variables for post_SlaveBootup lookup
   561                 # initialize and declare node boot status variables for post_SlaveBootup lookup
   533                 SlaveIDs = child.GetSlaveIDs()
   562                 SlaveIDs = child.GetSlaveIDs()
   534                 if len(SlaveIDs) == 0:
   563                 if len(SlaveIDs) == 0:
   535                     # define post_SlaveBootup lookup functions
   564                     # define post_SlaveBootup lookup functions
   536                     format_dict["slavebootups"] += (
   565                     format_dict["slavebootups"] += (
   537                         "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n"%(nodename))
   566                         "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){}\n" % (nodename))
   538                 else:
   567                 else:
   539                     format_dict["slavebootups"] += (
   568                     format_dict["slavebootups"] += (
   540                         "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n"%(nodename)+
   569                         "static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){\n" % (nodename) +
   541                         "    check_and_start_node(d, nodeId);\n"+
   570                         "    check_and_start_node(d, nodeId);\n" +
   542                         "}\n")
   571                         "}\n")
   543                 # register previously declared func as post_SlaveBootup callback for that node
   572                 # register previously declared func as post_SlaveBootup callback for that node
   544                 format_dict["slavebootup_register"] += (
   573                 format_dict["slavebootup_register"] += (
   545                     "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n"%(nodename,nodename))
   574                     "%s_Data.post_SlaveBootup = %s_post_SlaveBootup;\n" % (nodename, nodename))
   546                 format_dict["pre_op"] += (
   575                 format_dict["pre_op"] += (
   547                     "static void %s_preOperational(CO_Data* d){\n    "%(nodename)+
   576                     "static void %s_preOperational(CO_Data* d){\n    " % (nodename) +
   548                     "".join(["    masterSendNMTstateChange(d, %d, NMT_Reset_Comunication);\n"%NdId for NdId in SlaveIDs])+
   577                     "".join(["    masterSendNMTstateChange(d, %d, NMT_Reset_Comunication);\n" % NdId for NdId in SlaveIDs]) +
   549                     "}\n")
   578                     "}\n")
   550                 format_dict["pre_op_register"] += (
   579                 format_dict["pre_op_register"] += (
   551                     "%s_Data.preOperational = %s_preOperational;\n"%(nodename,nodename))
   580                     "%s_Data.preOperational = %s_preOperational;\n" % (nodename, nodename))
   552             else:
   581             else:
   553                 # Slave node
   582                 # Slave node
   554                 align = child_data.getSync_Align()
   583                 align = child_data.getSync_Align()
   555                 align_ratio=child_data.getSync_Align_Ratio()
   584                 align_ratio = child_data.getSync_Align_Ratio()
   556                 if align > 0:
   585                 if align > 0:
   557                     format_dict["post_sync"] += (
   586                     format_dict["post_sync"] += (
   558                         "static int %s_CalCount = 0;\n"%(nodename)+
   587                         "static int %s_CalCount = 0;\n" % (nodename) +
   559                         "static void %s_post_sync(CO_Data* d){\n"%(nodename)+
   588                         "static void %s_post_sync(CO_Data* d){\n" % (nodename) +
   560                         "    if(%s_CalCount < %d){\n"%(nodename, align)+
   589                         "    if(%s_CalCount < %d){\n" % (nodename, align) +
   561                         "        %s_CalCount++;\n"%(nodename)+
   590                         "        %s_CalCount++;\n" % (nodename) +
   562                         "        align_tick(-1);\n"+
   591                         "        align_tick(-1);\n" +
   563                         "    }else{\n"+
   592                         "    }else{\n" +
   564                         "        align_tick(%d);\n"%(align_ratio)+
   593                         "        align_tick(%d);\n" % (align_ratio) +
   565                         "    }\n"+
   594                         "    }\n" +
   566                         "}\n")
   595                         "}\n")
   567                     format_dict["post_sync_register"] += (
   596                     format_dict["post_sync_register"] += (
   568                         "%s_Data.post_sync = %s_post_sync;\n"%(nodename,nodename))
   597                         "%s_Data.post_sync = %s_post_sync;\n" % (nodename, nodename))
   569                 format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n    '%(
   598                 format_dict["nodes_init"] += 'NODE_SLAVE_INIT(%s, %s)\n    ' % (
   570                        nodename,
   599                        nodename,
   571                        child_data.getNodeId())
   600                        child_data.getNodeId())
   572     
   601 
   573             # Include generated OD headers
   602             # Include generated OD headers
   574             format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
   603             format_dict["nodes_includes"] += '#include "%s.h"\n' % (nodename)
   575             # Declare CAN channels according user filled config
   604             # Declare CAN channels according user filled config
   576             format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
   605             format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n' % (
   577                    nodename,
   606                    nodename,
   578                    child.GetCanDevice(),
   607                    child.GetCanDevice(),
   579                    child_data.getCAN_Baudrate())
   608                    child_data.getCAN_Baudrate())
   580             format_dict["nodes_open"] += 'NODE_OPEN(%s)\n    '%(nodename)
   609             format_dict["nodes_open"] += 'NODE_OPEN(%s)\n    ' % (nodename)
   581             format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n    '%(nodename)
   610             format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n    ' % (nodename)
   582             format_dict["nodes_stop"] += 'NODE_STOP(%s)\n    '%(nodename)
   611             format_dict["nodes_stop"] += 'NODE_STOP(%s)\n    ' % (nodename)
   583         
   612 
   584         filename = paths.AbsNeighbourFile(__file__,"cf_runtime.c")
   613         filename = paths.AbsNeighbourFile(__file__, "cf_runtime.c")
   585         cf_main = open(filename).read() % format_dict
   614         cf_main = open(filename).read() % format_dict
   586         cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict)
   615         cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c" % format_dict)
   587         f = open(cf_main_path,'w')
   616         f = open(cf_main_path, 'w')
   588         f.write(cf_main)
   617         f.write(cf_main)
   589         f.close()
   618         f.close()
   590 
   619 
   591         res = [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))],local_canfestival_config.getLDFLAGS(CanFestivalPath), True
   620         res = [(cf_main_path, local_canfestival_config.getCFLAGS(CanFestivalPath))], local_canfestival_config.getLDFLAGS(CanFestivalPath), True
   592         
   621 
   593         if can_driver is not None:
   622         if can_driver is not None:
   594             can_driver_path = os.path.join(CanFestivalPath,"drivers",can_driver,can_driver_name)
   623             can_driver_path = os.path.join(CanFestivalPath, "drivers", can_driver, can_driver_name)
   595             if os.path.exists(can_driver_path):
   624             if os.path.exists(can_driver_path):
   596                 res += ((can_driver_name, file(can_driver_path,"rb")),)
   625                 res += ((can_driver_name, file(can_driver_path, "rb")),)
   597 
   626 
   598         return res
   627         return res
   599