--- a/plugins/canfestival/canfestival.py Mon Jun 23 16:06:20 2008 +0200
+++ b/plugins/canfestival/canfestival.py Mon Jun 23 17:52:21 2008 +0200
@@ -1,4 +1,4 @@
-import os, sys, wx
+import os, sys
base_folder = os.path.split(sys.path[0])[0]
CanFestivalPath = os.path.join(base_folder, "CanFestival-3")
sys.path.append(os.path.join(CanFestivalPath, "objdictgen"))
@@ -15,14 +15,18 @@
from gnosis.xml.pickle.util import setParanoia
setParanoia(0)
-class _NetworkEdit(networkedit):
- " Overload some of CanFestival Network Editor methods "
+#--------------------------------------------------
+# SLAVE
+#--------------------------------------------------
+
+class _NodeEdit(objdictedit):
+ " Overload some of CanFestival Node Editor methods "
def OnCloseFrame(self, event):
" Do reset _NodeListPlug.View when closed"
self._onclose()
event.Skip()
-class _NodeListPlug(NodeList):
+class _SlavePlug(NodeManager):
XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="CanFestivalNode">
@@ -30,18 +34,30 @@
<xsd:attribute name="CAN_Device" type="xsd:string" use="required"/>
<xsd:attribute name="CAN_Baudrate" type="xsd:string" use="required"/>
<xsd:attribute name="NodeId" type="xsd:string" use="required"/>
- <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
"""
+ def GetSlaveODPath(self):
+ os.path.join(self.PlugPath(), 'slave.od')
+
def __init__(self):
- manager = NodeManager()
# TODO change netname when name change
- NodeList.__init__(self, manager, self.BaseParams.getName())
- self.LoadProject(self.PlugPath())
-
+ NodeManager.__init__(self)
+ odfilepath = self.GetSlaveODPath()
+ if(os.path.isfile(odfilepath)):
+ self.OpenFileInCurrent(odfilepath)
+ else:
+ self.CreateNewNode("SlaveNode", # Name - will be changed at build time
+ 0x00, # NodeID - will be changed at build time
+ "slave", # Type
+ "", # description
+ "None", # profile
+ "", # prfile filepath
+ "heartbeat", # NMT
+ []) # options
+
_View = None
def _OpenView(self, logger):
if not self._View:
@@ -49,7 +65,7 @@
self._View = None
def _onsave():
self.GetPlugRoot().SaveProject()
- self._View = _NetworkEdit(self.GetPlugRoot().AppFrame, self)
+ self._View = _NodeEdit(self.GetPlugRoot().AppFrame, self)
# TODO redefine BusId when IEC channel change
self._View.SetBusId(self.GetCurrentLocation())
self._View._onclose = _onclose
@@ -121,6 +137,117 @@
file.close()
return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False
+
+#--------------------------------------------------
+# MASTER
+#--------------------------------------------------
+
+class _NetworkEdit(networkedit):
+ " Overload some of CanFestival Network Editor methods "
+ def OnCloseFrame(self, event):
+ " Do reset _NodeListPlug.View when closed"
+ self._onclose()
+ event.Skip()
+
+class _NodeListPlug(NodeList):
+ XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:element name="CanFestivalNode">
+ <xsd:complexType>
+ <xsd:attribute name="CAN_Device" type="xsd:string" use="required"/>
+ <xsd:attribute name="CAN_Baudrate" type="xsd:string" use="required"/>
+ <xsd:attribute name="NodeId" type="xsd:string" use="required"/>
+ <xsd:attribute name="Sync_TPDOs" type="xsd:boolean" use="optional" default="true"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ """
+
+ def __init__(self):
+ manager = NodeManager()
+ # TODO change netname when name change
+ NodeList.__init__(self, manager, self.BaseParams.getName())
+ self.LoadProject(self.PlugPath())
+
+ _View = None
+ def _OpenView(self, logger):
+ if not self._View:
+ def _onclose():
+ self._View = None
+ def _onsave():
+ self.GetPlugRoot().SaveProject()
+ self._View = _NetworkEdit(self.GetPlugRoot().AppFrame, self)
+ # TODO redefine BusId when IEC channel change
+ self._View.SetBusId(self.GetCurrentLocation())
+ self._View._onclose = _onclose
+ self._View._onsave = _onsave
+ self._View.Show()
+
+ def _ShowMasterGenerated(self, logger):
+ buildpath = self._getBuildPath()
+ # Eventually create build dir
+ if not os.path.exists(buildpath):
+ logger.write_error("Error: No PLC built\n")
+ return
+
+ masterpath = os.path.join(buildpath, "MasterGenerated.od")
+ if not os.path.exists(masterpath):
+ logger.write_error("Error: No Master generated\n")
+ return
+
+ new_dialog = objdictedit(None, [masterpath])
+ new_dialog.Show()
+
+ PluginMethods = [
+ {"bitmap" : os.path.join("images", "NetworkEdit"),
+ "name" : "Edit network",
+ "tooltip" : "Edit CanOpen Network with NetworkEdit",
+ "method" : "_OpenView"},
+ {"name" : "Show Master",
+ "tooltip" : "Show Master generated by config_utils",
+ "method" : "_ShowMasterGenerated"}
+ ]
+
+ def OnPlugClose(self):
+ if self._View:
+ self._View.Close()
+
+ def PlugTestModified(self):
+ return self.ChangesToSave or self.HasChanged()
+
+ def OnPlugSave(self):
+ self.SetRoot(self.PlugPath())
+ self.SaveProject()
+ return True
+
+ def PlugGenerate_C(self, buildpath, locations, logger):
+ """
+ Generate C code
+ @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
+ @param locations: List of complete variables locations \
+ [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
+ "NAME" : name of the variable (generally "__IW0_1_2" style)
+ "DIR" : direction "Q","I" or "M"
+ "SIZE" : size "X", "B", "W", "D", "L"
+ "LOC" : tuple of interger for IEC location (0,1,2,...)
+ }, ...]
+ @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
+ """
+ current_location = self.GetCurrentLocation()
+ # define a unique name for the generated C file
+ prefix = "_".join(map(lambda x:str(x), current_location))
+ Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix )
+ # Create a new copy of the model with DCF loaded with PDO mappings for desired location
+ master, pointers = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
+ res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
+ if res :
+ raise Exception, res
+
+ file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
+ dump(master, file)
+ file.close()
+
+ return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False
class RootClass:
XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
@@ -133,11 +260,11 @@
</xsd:element>
</xsd:schema>
"""
- PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen node")]
+ PlugChildsTypes = [("CanOpenNode",_NodeListPlug, "CanOpen Master"),("CanOpenSlave",_SlavePlug, "CanOpen Slave")]
def GetParamsAttributes(self, path = None):
infos = PlugTemplate.GetParamsAttributes(self, path = None)
for element in infos:
- if element["name"] == "CanFestivalInstance":
+ if element["name"] == "CanFestivalInstance":
for child in element["children"]:
if child["name"] == "CAN_Driver":
DLL_LIST= getattr(canfestival_config,"DLL_LIST",None)
@@ -178,7 +305,7 @@
format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n '%(nodename)
format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n '%(nodename)
- if wx.Platform == '__WXMSW__':
+ if sys.platform == 'win32':
if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(format_dict["candriver"] + '_DEBUG.dll'))):
format_dict["candriver"] += '_DEBUG.dll'
else:
--- a/plugins/canfestival/config_utils.py Mon Jun 23 16:06:20 2008 +0200
+++ b/plugins/canfestival/config_utils.py Mon Jun 23 17:52:21 2008 +0200
@@ -138,6 +138,8 @@
self.SlavesPdoNumber = {}
# Dictionary of mapping value where unexpected variables are stored
self.TrashVariables = {}
+ # Dictionary of pointed variables
+ self.PointedVariables = {}
self.NodeList = nodelist
self.Manager = self.NodeList.Manager
@@ -145,6 +147,8 @@
self.MasterNode.SetNodeName(nodename)
self.PrepareMasterNode()
+ def GetPointedVariables(self):
+ return self.PointedVariables
def RemoveUsedNodeCobId(self, node):
"""
@@ -515,17 +519,18 @@
VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \
variable_infos["nodeid"]
+ # Generate entry name
+ indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
+ variable_infos["sizelocation"],
+ '_'.join(map(str,current_location)),
+ variable_infos["nodeid"])
+
# Search for an entry that has an empty subindex
while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000:
# Entry doesn't exist
if not self.MasterNode.IsEntry(mapvariableidx):
- # Generate entry name
- indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]],
- variable_infos["sizelocation"],
- '_'.join(map(str,current_location)),
- variable_infos["nodeid"])
# Add entry to MasterNode
- self.Manager.AddMapVariableToCurrent(mapvariableidx, indexname, 3, 1, self.MasterNode)
+ self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode)
new_index = True
nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00)
else:
@@ -557,6 +562,9 @@
if typeinfos != None:
value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"]
self.MasterNode.SetEntry(current_idx + 0x200, subindex, value)
+
+ # Add variable to pointed variables
+ self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname)
def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename):
"""
@@ -574,7 +582,7 @@
dcfgenerator = ConciseDCFGenerator(nodelist, nodename)
dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
- return dcfgenerator.GetMasterNode()
+ return dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
if __name__ == "__main__":
import os, sys, getopt