--- a/plugins/canfestival/canfestival.py Mon Jun 23 18:22:40 2008 +0200
+++ b/plugins/canfestival/canfestival.py Tue Jun 24 19:02:11 2008 +0200
@@ -19,17 +19,10 @@
# 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 _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">
+ <xsd:element name="CanFestivalSlaveNode">
<xsd:complexType>
<xsd:attribute name="CAN_Device" type="xsd:string" use="required"/>
<xsd:attribute name="CAN_Baudrate" type="xsd:string" use="required"/>
@@ -40,7 +33,7 @@
"""
def GetSlaveODPath(self):
- os.path.join(self.PlugPath(), 'slave.od')
+ return os.path.join(self.PlugPath(), 'slave.od')
def __init__(self):
# TODO change netname when name change
@@ -65,36 +58,18 @@
self._View = None
def _onsave():
self.GetPlugRoot().SaveProject()
- self._View = _NodeEdit(self.GetPlugRoot().AppFrame, self)
+ self._View = objdictedit(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",
+ "name" : "Edit slave",
+ "tooltip" : "Edit CanOpen slave with ObjdictEdit",
"method" : "_OpenView"},
- {"name" : "Show Master",
- "tooltip" : "Show Master generated by config_utils",
- "method" : "_ShowMasterGenerated"}
]
def OnPlugClose(self):
@@ -102,12 +77,10 @@
self._View.Close()
def PlugTestModified(self):
- return self.ChangesToSave or self.HasChanged()
+ return self.ChangesToSave or self.OneFileHasChanged()
def OnPlugSave(self):
- self.SetRoot(self.PlugPath())
- self.SaveProject()
- return True
+ return self.SaveCurrentInFile(self.GetSlaveODPath())
def PlugGenerate_C(self, buildpath, locations, logger):
"""
@@ -124,31 +97,23 @@
"""
current_location = self.GetCurrentLocation()
# define a unique name for the generated C file
- prefix = "_".join(map(lambda x:str(x), current_location))
+ prefix = "_".join(map(str, 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 = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
- res = gen_cfile.GenerateFile(Gen_OD_path, master)
+ # Create a new copy of the model
+ slave = self.GetCurrentNodeCopy()
+ slave.SetNodeName("OD_%s"%prefix)
+ # allow access to local OD from Slave PLC
+ pointers = config_utils.LocalODPointers(locations, current_location, slave)
+ res = gen_cfile.GenerateFile(Gen_OD_path, slave, pointers)
if res :
raise Exception, res
-
- file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
- dump(master, file)
- file.close()
-
+ self.ExportCurrentToEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix))
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">
@@ -176,7 +141,7 @@
self._View = None
def _onsave():
self.GetPlugRoot().SaveProject()
- self._View = _NetworkEdit(self.GetPlugRoot().AppFrame, self)
+ self._View = networkedit(self.GetPlugRoot().AppFrame, self)
# TODO redefine BusId when IEC channel change
self._View.SetBusId(self.GetCurrentLocation())
self._View._onclose = _onclose
@@ -217,8 +182,7 @@
def OnPlugSave(self):
self.SetRoot(self.PlugPath())
- self.SaveProject()
- return True
+ return self.SaveProject() is not None
def PlugGenerate_C(self, buildpath, locations, logger):
"""
@@ -235,10 +199,13 @@
"""
current_location = self.GetCurrentLocation()
# define a unique name for the generated C file
- prefix = "_".join(map(lambda x:str(x), current_location))
+ prefix = "_".join(map(str, 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)
+ # allow access to local OD from Master PLC
+ pointers.update(config_utils.LocalODPointers(locations, current_location, master))
+ # Do generate C file.
res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
if res :
raise Exception, res
@@ -288,22 +255,29 @@
for child in self.IECSortedChilds():
childlocstr = "_".join(map(str,child.GetCurrentLocation()))
nodename = "OD_%s" % childlocstr
+
+ # Try to get Slave Node
+ child_data = getattr(child, "CanFestivalSlaveNode", None)
+ if child_data is None:
+ # Not a slave -> master
+ child_data = getattr(child, "CanFestivalNode")
+ if child_data.getSync_TPDOs():
+ format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n '%(nodename)
+ format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n '%(nodename)
format_dict["nodes_includes"] += '#include "%s.h"\n'%(nodename)
format_dict["board_decls"] += 'BOARD_DECL(%s, "%s", "%s")\n'%(
nodename,
- child.CanFestivalNode.getCAN_Device(),
- child.CanFestivalNode.getCAN_Baudrate())
+ child_data.getCAN_Device(),
+ child_data.getCAN_Baudrate())
format_dict["nodes_declare"] += 'NODE_DECLARE(%s, %s)\n '%(
nodename,
- child.CanFestivalNode.getNodeId())
+ child_data.getNodeId())
format_dict["nodes_init"] += 'NODE_INIT(%s, %s)\n '%(
nodename,
- child.CanFestivalNode.getNodeId())
+ child_data.getNodeId())
format_dict["nodes_open"] += 'NODE_OPEN(%s)\n '%(nodename)
format_dict["nodes_close"] += 'NODE_CLOSE(%s)\n '%(nodename)
- format_dict["nodes_send_sync"] += 'NODE_SEND_SYNC(%s)\n '%(nodename)
- format_dict["nodes_proceed_sync"] += 'NODE_PROCEED_SYNC(%s)\n '%(nodename)
if sys.platform == 'win32':
if self.CanFestivalInstance.getDebug_mode() and os.path.isfile(os.path.join("%s"%(format_dict["candriver"] + '_DEBUG.dll'))):
--- a/plugins/canfestival/config_utils.py Mon Jun 23 18:22:40 2008 +0200
+++ b/plugins/canfestival/config_utils.py Tue Jun 24 19:02:11 2008 +0200
@@ -341,8 +341,10 @@
# Get only the part of the location that concern this node
loc = location["LOC"][len(current_location):]
# loc correspond to (ID, INDEX, SUBINDEX [,BIT])
- if len(loc) not in (3, 4):
+ if len(loc) not in (2, 3, 4):
raise ValueError, "Bad location size : %s"%str(loc)
+ elif len(loc) == 2:
+ continue
direction = location["DIR"]
@@ -374,9 +376,8 @@
else:
numbit = None
- entryinfos = node.GetSubentryInfos(index, subindex)
- if location["IEC_TYPE"] != "BOOL" and entryinfos["type"] != COlocationtype:
- raise ValueError, "Invalid type \"%s\"-> %d != %d for location\"%s\"" % (location["IEC_TYPE"], COlocationtype, entryinfos["type"] , name)
+ if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype:
+ raise ValueError, "Invalid type \"%s\"-> %d != %d for location\"%s\"" % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
typeinfos = node.GetEntryInfos(COlocationtype)
self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction],
@@ -584,6 +585,40 @@
dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs)
return dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables()
+def LocalODPointers(locations, current_location, slave):
+ IECLocations = {}
+ pointers = {}
+ for location in locations:
+ COlocationtype = IECToCOType[location["IEC_TYPE"]]
+ name = location["NAME"]
+ if name in IECLocations:
+ if IECLocations[name] != COlocationtype:
+ raise ValueError, "Conflict type for location \"%s\"" % name
+ else:
+ # Get only the part of the location that concern this node
+ loc = location["LOC"][len(current_location):]
+ # loc correspond to (ID, INDEX, SUBINDEX [,BIT])
+ if len(loc) not in (2, 3, 4):
+ raise ValueError, "Bad location size : %s"%str(loc)
+ elif len(loc) != 2:
+ continue
+
+ # Extract and check nodeid
+ index, subindex = loc[:2]
+
+ # Extract and check index and subindex
+ if not slave.IsEntry(index, subindex):
+ raise ValueError, "No such index/subindex (%x,%x) (variable %s)" % (index, subindex, name)
+
+ # Get the entry info
+ subentry_infos = slave.GetSubentryInfos(index, subindex)
+ if subentry_infos["type"] != COlocationtype:
+ raise ValueError, "Invalid type \"%s\"-> %d != %d for location\"%s\"" % (location["IEC_TYPE"], COlocationtype, subentry_infos["type"] , name)
+
+ IECLocations[name] = COlocationtype
+ pointers[(index, subindex)] = name
+ return pointers
+
if __name__ == "__main__":
import os, sys, getopt