plugins/canfestival/canfestival.py
changeset 166 121b18748de0
parent 163 482ca562d414
child 169 8e87b69286c0
equal deleted inserted replaced
165:f9c6c9e36725 166:121b18748de0
    17 
    17 
    18 #--------------------------------------------------
    18 #--------------------------------------------------
    19 #                    SLAVE
    19 #                    SLAVE
    20 #--------------------------------------------------
    20 #--------------------------------------------------
    21 
    21 
    22 class _NodeEdit(objdictedit):
       
    23     " Overload some of CanFestival Node Editor methods "
       
    24     def OnCloseFrame(self, event):
       
    25         " Do reset _NodeListPlug.View when closed"
       
    26         self._onclose()
       
    27         event.Skip()
       
    28 
       
    29 class _SlavePlug(NodeManager):
    22 class _SlavePlug(NodeManager):
    30     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    23     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    31     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    24     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    32       <xsd:element name="CanFestivalNode">
    25       <xsd:element name="CanFestivalSlaveNode">
    33         <xsd:complexType>
    26         <xsd:complexType>
    34           <xsd:attribute name="CAN_Device" type="xsd:string" use="required"/>
    27           <xsd:attribute name="CAN_Device" type="xsd:string" use="required"/>
    35           <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="required"/>
    28           <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="required"/>
    36           <xsd:attribute name="NodeId" type="xsd:string" use="required"/>
    29           <xsd:attribute name="NodeId" type="xsd:string" use="required"/>
    37         </xsd:complexType>
    30         </xsd:complexType>
    38       </xsd:element>
    31       </xsd:element>
    39     </xsd:schema>
    32     </xsd:schema>
    40     """
    33     """
    41 
    34 
    42     def GetSlaveODPath(self):
    35     def GetSlaveODPath(self):
    43         os.path.join(self.PlugPath(), 'slave.od')
    36         return os.path.join(self.PlugPath(), 'slave.od')
    44 
    37 
    45     def __init__(self):
    38     def __init__(self):
    46         # TODO change netname when name change
    39         # TODO change netname when name change
    47         NodeManager.__init__(self)
    40         NodeManager.__init__(self)
    48         odfilepath = self.GetSlaveODPath()
    41         odfilepath = self.GetSlaveODPath()
    63         if not self._View:
    56         if not self._View:
    64             def _onclose():
    57             def _onclose():
    65                 self._View = None
    58                 self._View = None
    66             def _onsave():
    59             def _onsave():
    67                 self.GetPlugRoot().SaveProject()
    60                 self.GetPlugRoot().SaveProject()
    68             self._View = _NodeEdit(self.GetPlugRoot().AppFrame, self)
    61             self._View = objdictedit(self.GetPlugRoot().AppFrame, self)
    69             # TODO redefine BusId when IEC channel change
    62             # TODO redefine BusId when IEC channel change
    70             self._View.SetBusId(self.GetCurrentLocation())
    63             self._View.SetBusId(self.GetCurrentLocation())
    71             self._View._onclose = _onclose
    64             self._View._onclose = _onclose
    72             self._View._onsave = _onsave
    65             self._View._onsave = _onsave
    73             self._View.Show()
    66             self._View.Show()
    74 
    67 
    75     def _ShowMasterGenerated(self, logger):
       
    76         buildpath = self._getBuildPath()
       
    77         # Eventually create build dir
       
    78         if not os.path.exists(buildpath):
       
    79             logger.write_error("Error: No PLC built\n")
       
    80             return
       
    81         
       
    82         masterpath = os.path.join(buildpath, "MasterGenerated.od")
       
    83         if not os.path.exists(masterpath):
       
    84             logger.write_error("Error: No Master generated\n")
       
    85             return
       
    86         
       
    87         new_dialog = objdictedit(None, [masterpath])
       
    88         new_dialog.Show()
       
    89 
       
    90     PluginMethods = [
    68     PluginMethods = [
    91         {"bitmap" : os.path.join("images", "NetworkEdit"),
    69         {"bitmap" : os.path.join("images", "NetworkEdit"),
    92          "name" : "Edit network", 
    70          "name" : "Edit slave", 
    93          "tooltip" : "Edit CanOpen Network with NetworkEdit",
    71          "tooltip" : "Edit CanOpen slave with ObjdictEdit",
    94          "method" : "_OpenView"},
    72          "method" : "_OpenView"},
    95         {"name" : "Show Master", 
       
    96          "tooltip" : "Show Master generated by config_utils",
       
    97          "method" : "_ShowMasterGenerated"}
       
    98     ]
    73     ]
    99 
    74 
   100     def OnPlugClose(self):
    75     def OnPlugClose(self):
   101         if self._View:
    76         if self._View:
   102             self._View.Close()
    77             self._View.Close()
   103 
    78 
   104     def PlugTestModified(self):
    79     def PlugTestModified(self):
   105         return self.ChangesToSave or self.HasChanged()
    80         return self.ChangesToSave or self.OneFileHasChanged()
   106         
    81         
   107     def OnPlugSave(self):
    82     def OnPlugSave(self):
   108         self.SetRoot(self.PlugPath())
    83         return self.SaveCurrentInFile(self.GetSlaveODPath())
   109         self.SaveProject()
       
   110         return True
       
   111 
    84 
   112     def PlugGenerate_C(self, buildpath, locations, logger):
    85     def PlugGenerate_C(self, buildpath, locations, logger):
   113         """
    86         """
   114         Generate C code
    87         Generate C code
   115         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
    88         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   122             }, ...]
    95             }, ...]
   123         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
    96         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   124         """
    97         """
   125         current_location = self.GetCurrentLocation()
    98         current_location = self.GetCurrentLocation()
   126         # define a unique name for the generated C file
    99         # define a unique name for the generated C file
   127         prefix = "_".join(map(lambda x:str(x), current_location))
   100         prefix = "_".join(map(str, current_location))
   128         Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
   101         Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
   129         # Create a new copy of the model with DCF loaded with PDO mappings for desired location
   102         # Create a new copy of the model
   130         master = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
   103         slave = self.GetCurrentNodeCopy()
   131         res = gen_cfile.GenerateFile(Gen_OD_path, master)
   104         slave.SetNodeName("OD_%s"%prefix)
       
   105         # allow access to local OD from Slave PLC
       
   106         pointers = config_utils.LocalODPointers(locations, current_location, slave)
       
   107         res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
   132         if res :
   108         if res :
   133             raise Exception, res
   109             raise Exception, res
   134         
   110         self.ExportCurrentToEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix))
   135         file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
       
   136         dump(master, file)
       
   137         file.close()
       
   138         
       
   139         return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False
   111         return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False
   140 
   112 
   141 #--------------------------------------------------
   113 #--------------------------------------------------
   142 #                    MASTER
   114 #                    MASTER
   143 #--------------------------------------------------
   115 #--------------------------------------------------
   144 
       
   145 class _NetworkEdit(networkedit):
       
   146     " Overload some of CanFestival Network Editor methods "
       
   147     def OnCloseFrame(self, event):
       
   148         " Do reset _NodeListPlug.View when closed"
       
   149         self._onclose()
       
   150         event.Skip()
       
   151 
   116 
   152 class _NodeListPlug(NodeList):
   117 class _NodeListPlug(NodeList):
   153     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   118     XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
   154     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   119     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   155       <xsd:element name="CanFestivalNode">
   120       <xsd:element name="CanFestivalNode">
   174         if not self._View:
   139         if not self._View:
   175             def _onclose():
   140             def _onclose():
   176                 self._View = None
   141                 self._View = None
   177             def _onsave():
   142             def _onsave():
   178                 self.GetPlugRoot().SaveProject()
   143                 self.GetPlugRoot().SaveProject()
   179             self._View = _NetworkEdit(self.GetPlugRoot().AppFrame, self)
   144             self._View = networkedit(self.GetPlugRoot().AppFrame, self)
   180             # TODO redefine BusId when IEC channel change
   145             # TODO redefine BusId when IEC channel change
   181             self._View.SetBusId(self.GetCurrentLocation())
   146             self._View.SetBusId(self.GetCurrentLocation())
   182             self._View._onclose = _onclose
   147             self._View._onclose = _onclose
   183             self._View._onsave = _onsave
   148             self._View._onsave = _onsave
   184             self._View.Show()
   149             self._View.Show()
   215     def PlugTestModified(self):
   180     def PlugTestModified(self):
   216         return self.ChangesToSave or self.HasChanged()
   181         return self.ChangesToSave or self.HasChanged()
   217         
   182         
   218     def OnPlugSave(self):
   183     def OnPlugSave(self):
   219         self.SetRoot(self.PlugPath())
   184         self.SetRoot(self.PlugPath())
   220         self.SaveProject()
   185         return self.SaveProject() is not None
   221         return True
       
   222 
   186 
   223     def PlugGenerate_C(self, buildpath, locations, logger):
   187     def PlugGenerate_C(self, buildpath, locations, logger):
   224         """
   188         """
   225         Generate C code
   189         Generate C code
   226         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   190         @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
   233             }, ...]
   197             }, ...]
   234         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   198         @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
   235         """
   199         """
   236         current_location = self.GetCurrentLocation()
   200         current_location = self.GetCurrentLocation()
   237         # define a unique name for the generated C file
   201         # define a unique name for the generated C file
   238         prefix = "_".join(map(lambda x:str(x), current_location))
   202         prefix = "_".join(map(str, current_location))
   239         Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
   203         Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
   240         # Create a new copy of the model with DCF loaded with PDO mappings for desired location
   204         # Create a new copy of the model with DCF loaded with PDO mappings for desired location
   241         master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
   205         master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
       
   206         # allow access to local OD from Master PLC
       
   207         pointers.update(config_utils.LocalODPointers(locations, current_location, master))
       
   208         # Do generate C file.
   242         res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
   209         res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
   243         if res :
   210         if res :
   244             raise Exception, res
   211             raise Exception, res
   245         
   212         
   246         file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
   213         file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
   286                        "nodes_send_sync" : "",
   253                        "nodes_send_sync" : "",
   287                        "nodes_proceed_sync" : ""}
   254                        "nodes_proceed_sync" : ""}
   288         for child in self.IECSortedChilds():
   255         for child in self.IECSortedChilds():
   289             childlocstr = "_".join(map(str,child.GetCurrentLocation()))
   256             childlocstr = "_".join(map(str,child.GetCurrentLocation()))
   290             nodename = "OD_%s" % childlocstr
   257             nodename = "OD_%s" % childlocstr
       
   258             
       
   259             # Try to get Slave Node
       
   260             child_data = getattr(child, "CanFestivalSlaveNode", None)
       
   261             if child_data is None:
       
   262                 # Not a slave -> master
       
   263                 child_data = getattr(child, "CanFestivalNode")
       
   264                 if child_data.getSync_TPDOs():
       
   265                     format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n    '%(nodename)
       
   266                     format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n    '%(nodename)
   291 
   267 
   292             format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
   268             format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
   293             format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
   269             format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
   294                    nodename,
   270                    nodename,
   295                    child.CanFestivalNode.getCAN_Device(),
   271                    child_data.getCAN_Device(),
   296                    child.CanFestivalNode.getCAN_Baudrate())
   272                    child_data.getCAN_Baudrate())
   297             format_dict["nodes_declare"] += 'NODE_DECLARE(%s, %s)\n    '%(
   273             format_dict["nodes_declare"] += 'NODE_DECLARE(%s, %s)\n    '%(
   298                    nodename,
   274                    nodename,
   299                    child.CanFestivalNode.getNodeId())
   275                    child_data.getNodeId())
   300             format_dict["nodes_init"] += 'NODE_INIT(%s, %s)\n    '%(
   276             format_dict["nodes_init"] += 'NODE_INIT(%s, %s)\n    '%(
   301                    nodename,
   277                    nodename,
   302                    child.CanFestivalNode.getNodeId())
   278                    child_data.getNodeId())
   303             format_dict["nodes_open"] += 'NODE_OPEN(%s)\n    '%(nodename)
   279             format_dict["nodes_open"] += 'NODE_OPEN(%s)\n    '%(nodename)
   304             format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n    '%(nodename)
   280             format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n    '%(nodename)
   305             format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n    '%(nodename)
       
   306             format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n    '%(nodename)
       
   307         
   281         
   308         if sys.platform == 'win32':
   282         if sys.platform == 'win32':
   309             if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(format_dict["candriver"] + '_DEBUG.dll'))):
   283             if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(format_dict["candriver"] + '_DEBUG.dll'))):
   310                     format_dict["candriver"] += '_DEBUG.dll'
   284                     format_dict["candriver"] += '_DEBUG.dll'
   311             else:
   285             else: