--- 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 @@
#--------------------------------------------------
-class _NodeEdit(objdictedit):
- " Overload some of CanFestival Node Editor methods "
- def OnCloseFrame(self, event):
- " Do reset _NodeListPlug.View when closed"
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: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') # TODO change netname when name change
@@ -65,7 +58,90 @@
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 + {"bitmap" : os.path.join("images", "NetworkEdit"), + "tooltip" : "Edit CanOpen slave with ObjdictEdit", + "method" : "_OpenView"}, + def PlugTestModified(self): + return self.ChangesToSave or self.OneFileHasChanged() + return self.SaveCurrentInFile(self.GetSlaveODPath()) + def PlugGenerate_C(self, buildpath, locations, logger): + @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(str, current_location)) + Gen_OD_path = os.path.join(buildpath, "OD_%s.c"%prefix ) + # 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) + self.ExportCurrentToEDSFile(os.path.join(buildpath, "Slave_%s.eds"%prefix)) + return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False +#-------------------------------------------------- +#-------------------------------------------------- +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: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"/> + manager = NodeManager() + # TODO change netname when name change + NodeList.__init__(self, manager, self.BaseParams.getName()) + self.LoadProject(self.PlugPath()) + def _OpenView(self, logger): + 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
@@ -106,8 +182,7 @@
self.SetRoot(self.PlugPath())
+ return self.SaveProject() is not None def PlugGenerate_C(self, buildpath, locations, logger):
@@ -124,121 +199,13 @@
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 = config_utils.GenerateConciseDCF(locations, current_location, self, self.CanFestivalNode.getSync_TPDOs(),"OD_%s"%prefix)
- res = gen_cfile.GenerateFile(Gen_OD_path, master)
- file = open(os.path.join(buildpath, "MasterGenerated.od"), "w")
- return [(Gen_OD_path,canfestival_config.getCFLAGS(CanFestivalPath))],"",False
-#--------------------------------------------------
-#--------------------------------------------------
-class _NetworkEdit(networkedit):
- " Overload some of CanFestival Network Editor methods "
- def OnCloseFrame(self, event):
- " Do reset _NodeListPlug.View when closed"
-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: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"/>
- manager = NodeManager()
- # TODO change netname when name change
- NodeList.__init__(self, manager, self.BaseParams.getName())
- self.LoadProject(self.PlugPath())
- def _OpenView(self, logger):
- 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
- 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")
- masterpath = os.path.join(buildpath, "MasterGenerated.od")
- if not os.path.exists(masterpath):
- logger.write_error("Error: No Master generated\n")
- new_dialog = objdictedit(None, [masterpath])
- {"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 PlugTestModified(self):
- return self.ChangesToSave or self.HasChanged()
- self.SetRoot(self.PlugPath())
- def PlugGenerate_C(self, buildpath, locations, logger):
- @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))
+ 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)) res = gen_cfile.GenerateFile(Gen_OD_path, master, pointers)
@@ -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) + # 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'%(
- 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 '%(
- child.CanFestivalNode.getNodeId())
+ child_data.getNodeId()) format_dict["nodes_init"] += 'NODE_INIT(%s, %s)\n '%(
- 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)
direction = location["DIR"]
@@ -374,9 +376,8 @@
- 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): + 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 + # 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) + # 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) + 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 if __name__ == "__main__":