etisserant@163: import os, sys etisserant@20: base_folder = os.path.split(sys.path[0])[0] etisserant@49: CanFestivalPath = os.path.join(base_folder, "CanFestival-3") etisserant@49: sys.path.append(os.path.join(CanFestivalPath, "objdictgen")) etisserant@20: lbessard@11: from nodelist import NodeList lbessard@11: from nodemanager import NodeManager lbessard@11: import config_utils, gen_cfile etisserant@12: from networkedit import networkedit lbessard@77: from objdictedit import objdictedit etisserant@49: import canfestival_config greg@95: from plugger import PlugTemplate etisserant@169: from commondialogs import CreateNodeDialog etisserant@169: import wx lbessard@11: lbessard@77: from gnosis.xml.pickle import * lbessard@77: from gnosis.xml.pickle.util import setParanoia lbessard@77: setParanoia(0) lbessard@77: etisserant@163: #-------------------------------------------------- etisserant@163: # SLAVE etisserant@163: #-------------------------------------------------- etisserant@163: etisserant@163: class _SlavePlug(NodeManager): etisserant@12: XSD = """ etisserant@12: etisserant@166: etisserant@12: lbessard@86: lbessard@86: lbessard@86: etisserant@12: etisserant@12: etisserant@12: etisserant@12: """ etisserant@12: etisserant@163: def GetSlaveODPath(self): etisserant@166: return os.path.join(self.PlugPath(), 'slave.od') etisserant@163: lbessard@17: def __init__(self): etisserant@23: # TODO change netname when name change etisserant@163: NodeManager.__init__(self) etisserant@163: odfilepath = self.GetSlaveODPath() etisserant@163: if(os.path.isfile(odfilepath)): etisserant@163: self.OpenFileInCurrent(odfilepath) etisserant@163: else: etisserant@169: self.FilePath = "" etisserant@169: dialog = CreateNodeDialog(None, wx.OK) etisserant@169: dialog.Type.Enable(False) etisserant@169: dialog.GenSYNC.Enable(False) etisserant@169: if dialog.ShowModal() == wx.ID_OK: etisserant@169: name, id, nodetype, description = dialog.GetValues() etisserant@169: profile, filepath = dialog.GetProfile() etisserant@169: NMT = dialog.GetNMTManagement() etisserant@169: options = dialog.GetOptions() etisserant@169: self.CreateNewNode(name, # Name - will be changed at build time etisserant@169: id, # NodeID - will be changed at build time etisserant@169: "slave", # Type etisserant@169: description,# description etisserant@169: profile, # profile etisserant@169: filepath, # prfile filepath etisserant@169: NMT, # NMT etisserant@169: options) # options etisserant@169: else: etisserant@169: self.CreateNewNode("SlaveNode", # Name - will be changed at build time etisserant@169: 0x00, # NodeID - will be changed at build time etisserant@169: "slave", # Type etisserant@169: "", # description etisserant@169: "None", # profile etisserant@169: "", # prfile filepath etisserant@169: "heartbeat", # NMT etisserant@169: []) # options etisserant@169: dialog.Destroy() etisserant@13: _View = None etisserant@18: def _OpenView(self, logger): etisserant@13: if not self._View: etisserant@13: def _onclose(): etisserant@30: self._View = None lbessard@25: def _onsave(): lbessard@25: self.GetPlugRoot().SaveProject() etisserant@166: self._View = objdictedit(self.GetPlugRoot().AppFrame, self) etisserant@23: # TODO redefine BusId when IEC channel change etisserant@23: self._View.SetBusId(self.GetCurrentLocation()) etisserant@13: self._View._onclose = _onclose lbessard@25: self._View._onsave = _onsave etisserant@23: self._View.Show() etisserant@23: lbessard@65: PluginMethods = [ lbessard@82: {"bitmap" : os.path.join("images", "NetworkEdit"), etisserant@166: "name" : "Edit slave", etisserant@166: "tooltip" : "Edit CanOpen slave with ObjdictEdit", etisserant@105: "method" : "_OpenView"}, lbessard@65: ] etisserant@13: etisserant@13: def OnPlugClose(self): etisserant@13: if self._View: etisserant@13: self._View.Close() etisserant@13: etisserant@13: def PlugTestModified(self): etisserant@166: return self.ChangesToSave or self.OneFileHasChanged() etisserant@12: lbessard@17: def OnPlugSave(self): etisserant@166: return self.SaveCurrentInFile(self.GetSlaveODPath()) etisserant@12: etisserant@24: def PlugGenerate_C(self, buildpath, locations, logger): etisserant@12: """ etisserant@15: Generate C code etisserant@15: @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) etisserant@15: @param locations: List of complete variables locations \ etisserant@22: [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) etisserant@22: "NAME" : name of the variable (generally "__IW0_1_2" style) etisserant@22: "DIR" : direction "Q","I" or "M" etisserant@22: "SIZE" : size "X", "B", "W", "D", "L" etisserant@22: "LOC" : tuple of interger for IEC location (0,1,2,...) etisserant@22: }, ...] etisserant@22: @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND etisserant@12: """ etisserant@24: current_location = self.GetCurrentLocation() etisserant@22: # define a unique name for the generated C file etisserant@166: prefix = "_".join(map(str, current_location)) etisserant@49: Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix ) etisserant@166: # Create a new copy of the model etisserant@166: slave = self.GetCurrentNodeCopy() etisserant@166: slave.SetNodeName("OD_%s"%prefix) etisserant@166: # allow access to local OD from Slave PLC etisserant@166: pointers = config_utils.LocalODPointers(locations, current_location, slave) etisserant@166: res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers) etisserant@15: if res : etisserant@15: raise Exception, res lbessard@172: res = eds_utils.GenerateEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix), slave) lbessard@172: if res : lbessard@172: raise Exception, res etisserant@52: return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False etisserant@163: etisserant@163: #-------------------------------------------------- etisserant@163: # MASTER etisserant@163: #-------------------------------------------------- etisserant@163: etisserant@163: class _NodeListPlug(NodeList): etisserant@163: XSD = """ etisserant@163: etisserant@163: etisserant@163: etisserant@163: etisserant@163: etisserant@163: etisserant@163: etisserant@163: etisserant@163: etisserant@163: etisserant@163: """ etisserant@163: etisserant@163: def __init__(self): etisserant@163: manager = NodeManager() etisserant@163: # TODO change netname when name change etisserant@163: NodeList.__init__(self, manager, self.BaseParams.getName()) etisserant@163: self.LoadProject(self.PlugPath()) etisserant@163: etisserant@163: _View = None etisserant@163: def _OpenView(self, logger): etisserant@163: if not self._View: etisserant@163: def _onclose(): etisserant@163: self._View = None etisserant@163: def _onsave(): etisserant@163: self.GetPlugRoot().SaveProject() etisserant@166: self._View = networkedit(self.GetPlugRoot().AppFrame, self) etisserant@163: # TODO redefine BusId when IEC channel change etisserant@163: self._View.SetBusId(self.GetCurrentLocation()) etisserant@163: self._View._onclose = _onclose etisserant@163: self._View._onsave = _onsave etisserant@163: self._View.Show() etisserant@163: etisserant@163: def _ShowMasterGenerated(self, logger): etisserant@163: buildpath = self._getBuildPath() etisserant@163: # Eventually create build dir etisserant@163: if not os.path.exists(buildpath): etisserant@163: logger.write_error("Error: No PLC built\n") etisserant@163: return etisserant@163: etisserant@163: masterpath = os.path.join(buildpath, "MasterGenerated.od") etisserant@163: if not os.path.exists(masterpath): etisserant@163: logger.write_error("Error: No Master generated\n") etisserant@163: return etisserant@163: etisserant@169: new_dialog = objdictedit(None, filesOpen=[masterpath]) etisserant@163: new_dialog.Show() etisserant@163: etisserant@163: PluginMethods = [ etisserant@163: {"bitmap" : os.path.join("images", "NetworkEdit"), etisserant@163: "name" : "Edit network", etisserant@163: "tooltip" : "Edit CanOpen Network with NetworkEdit", etisserant@163: "method" : "_OpenView"}, etisserant@163: {"name" : "Show Master", etisserant@163: "tooltip" : "Show Master generated by config_utils", etisserant@163: "method" : "_ShowMasterGenerated"} etisserant@163: ] etisserant@163: etisserant@163: def OnPlugClose(self): etisserant@163: if self._View: etisserant@163: self._View.Close() etisserant@163: etisserant@163: def PlugTestModified(self): etisserant@163: return self.ChangesToSave or self.HasChanged() etisserant@163: etisserant@163: def OnPlugSave(self): etisserant@163: self.SetRoot(self.PlugPath()) etisserant@166: return self.SaveProject() is not None etisserant@163: etisserant@163: def PlugGenerate_C(self, buildpath, locations, logger): etisserant@163: """ etisserant@163: Generate C code etisserant@163: @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) etisserant@163: @param locations: List of complete variables locations \ etisserant@163: [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) etisserant@163: "NAME" : name of the variable (generally "__IW0_1_2" style) etisserant@163: "DIR" : direction "Q","I" or "M" etisserant@163: "SIZE" : size "X", "B", "W", "D", "L" etisserant@163: "LOC" : tuple of interger for IEC location (0,1,2,...) etisserant@163: }, ...] etisserant@163: @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND etisserant@163: """ etisserant@163: current_location = self.GetCurrentLocation() etisserant@163: # define a unique name for the generated C file etisserant@166: prefix = "_".join(map(str, current_location)) etisserant@163: Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix ) etisserant@163: # Create a new copy of the model with DCF loaded with PDO mappings for desired location etisserant@163: master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix) etisserant@166: # allow access to local OD from Master PLC etisserant@166: pointers.update(config_utils.LocalODPointers(locations, current_location, master)) etisserant@166: # Do generate C file. etisserant@163: res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers) etisserant@163: if res : etisserant@163: raise Exception, res etisserant@163: etisserant@163: file = open(os.path.join(buildpath, "MasterGenerated.od"), "w") etisserant@163: dump(master, file) etisserant@163: file.close() etisserant@163: etisserant@163: return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False etisserant@12: etisserant@13: class RootClass: etisserant@12: XSD = """ etisserant@12: etisserant@12: etisserant@12: lbessard@86: greg@157: etisserant@12: etisserant@12: etisserant@12: etisserant@12: """ etisserant@169: PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen Master"), etisserant@169: ("CanOpenSlave",_SlavePlug, "CanOpen Slave")] greg@95: def GetParamsAttributes(self, path = None): greg@95: infos = PlugTemplate.GetParamsAttributes(self, path = None) greg@95: for element in infos: etisserant@163: if element["name"] == "CanFestivalInstance": greg@95: for child in element["children"]: greg@95: if child["name"] == "CAN_Driver": greg@95: DLL_LIST= getattr(canfestival_config,"DLL_LIST",None) greg@95: if DLL_LIST is not None: greg@95: child["type"] = DLL_LIST greg@95: return infos greg@95: return infos lbessard@11: etisserant@24: def PlugGenerate_C(self, buildpath, locations, logger): etisserant@52: etisserant@52: format_dict = {"locstr" : "_".join(map(str,self.GetCurrentLocation())), etisserant@52: "candriver" : self.CanFestivalInstance.getCAN_Driver(), etisserant@52: "nodes_includes" : "", etisserant@52: "board_decls" : "", etisserant@59: "nodes_declare" : "", etisserant@52: "nodes_init" : "", etisserant@52: "nodes_open" : "", etisserant@57: "nodes_close" : "", etisserant@57: "nodes_send_sync" : "", etisserant@169: "nodes_proceed_sync" : "", etisserant@174: "slavebootups" : "", etisserant@174: "slavebootup_register" : ""} etisserant@52: for child in self.IECSortedChilds(): etisserant@52: childlocstr = "_".join(map(str,child.GetCurrentLocation())) etisserant@52: nodename = "OD_%s" % childlocstr etisserant@166: etisserant@166: # Try to get Slave Node etisserant@166: child_data = getattr(child, "CanFestivalSlaveNode", None) etisserant@166: if child_data is None: etisserant@166: # Not a slave -> master etisserant@166: child_data = getattr(child, "CanFestivalNode") etisserant@169: # Apply sync setting etisserant@166: if child_data.getSync_TPDOs(): etisserant@166: format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n '%(nodename) etisserant@166: format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n '%(nodename) etisserant@169: # initialize and declare node table for post_SlaveBootup lookup etisserant@169: etisserant@169: SlaveIDs = child.GetSlaveIDs() etisserant@169: for id in SlaveIDs: etisserant@169: format_dict["slavebootups"] += """ etisserant@169: int %s_slave_%d_booted = 0; etisserant@169: """%(nodename, id) etisserant@169: format_dict["slavebootups"] += """ etisserant@169: static void %s_post_SlaveBootup(CO_Data* d, UNS8 nodeId){ etisserant@169: switch(nodeId){ etisserant@169: """%(nodename) etisserant@169: for id in SlaveIDs: etisserant@169: format_dict["slavebootups"] += """ etisserant@169: case %d: etisserant@169: %s_slave_%d_booted = 1; etisserant@169: break; etisserant@169: """%(id, nodename, id) etisserant@169: format_dict["slavebootups"] += """ etisserant@169: default: etisserant@169: break; etisserant@169: } etisserant@169: if( """ etisserant@169: format_dict["slavebootups"] += " && ".join(["%s_slave_%d_booted"%(nodename, id) for id in SlaveIDs]) etisserant@169: etisserant@169: format_dict["slavebootups"] += """ ) etisserant@169: Master_post_SlaveBootup(d,nodeId); etisserant@169: } etisserant@174: """ etisserant@174: format_dict["slavebootup_register"] += """ etisserant@169: %s_Data.post_SlaveBootup = %s_post_SlaveBootup; etisserant@169: """%(nodename,nodename) etisserant@169: etisserant@52: format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename) etisserant@52: format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%( etisserant@52: nodename, etisserant@166: child_data.getCAN_Device(), etisserant@166: child_data.getCAN_Baudrate()) etisserant@59: format_dict["nodes_declare"] += 'NODE_DECLARE(%s, %s)\n '%( etisserant@59: nodename, etisserant@166: child_data.getNodeId()) etisserant@57: format_dict["nodes_init"] += 'NODE_INIT(%s, %s)\n '%( etisserant@52: nodename, etisserant@166: child_data.getNodeId()) etisserant@57: format_dict["nodes_open"] += 'NODE_OPEN(%s)\n '%(nodename) etisserant@57: format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n '%(nodename) greg@157: etisserant@163: if sys.platform == 'win32': greg@157: if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(format_dict["candriver"] + '_DEBUG.dll'))): greg@157: format_dict["candriver"] += '_DEBUG.dll' greg@157: else: greg@157: format_dict["candriver"] += '.dll' greg@157: etisserant@52: filename = os.path.join(os.path.split(__file__)[0],"cf_runtime.c") etisserant@52: cf_main = open(filename).read() % format_dict etisserant@52: cf_main_path = os.path.join(buildpath, "CF_%(locstr)s.c"%format_dict) etisserant@52: f = open(cf_main_path,'w') etisserant@52: f.write(cf_main) etisserant@52: f.close() etisserant@52: etisserant@52: return [(cf_main_path, canfestival_config.getCFLAGS(CanFestivalPath))],canfestival_config.getLDFLAGS(CanFestivalPath), True lbessard@11: etisserant@15: