def __init__(self, parent):
self._init_ctrls(parent)
+ self.staticText2.Hide()
+ self.NodeID.Hide()
+
self.Type.Append("master")
self.Type.Append("slave")
def __init__(self, parent):
self._init_ctrls(parent)
+ self.staticText3.Hide()
+ self.NodeID.Hide()
+
self.NodeID.SetValue("0x00")
self.Type.Append("master")
self.Type.Append("slave")
if value.startswith("$NODEID"):
try:
test = int(value.replace("$NODEID+", ""), 16)
- computed_value = value.replace("$NODEID", "self.ID")
+ computed_value = "\"%s\""%value
except:
raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
# Second case, value starts with "0x", then it's an hexadecimal value
elif values["DATATYPE"] == 0x01:
values["DEFAULTVALUE"] = {0 : True, 1 : False}[values["DEFAULTVALUE"]]
else:
- if type(values["DEFAULTVALUE"]) != IntType and values["DEFAULTVALUE"].find("self.ID") == -1:
+ if type(values["DEFAULTVALUE"]) != IntType and values["DEFAULTVALUE"].find("$NODEID") == -1:
raise
except:
raise SyntaxError, "Error on section \"[%s]\":\nDefaultValue incompatible with DataType"%section_name
for entry in entries:
# Extract infos and values for the entry
entry_infos = Manager.GetEntryInfos(entry)
- values = Manager.GetCurrentEntry(entry)
+ values = Manager.GetCurrentEntry(entry, compute = False)
# Define section name
text = "\n[%X]\n"%entry
# If there is only one value, it's a VAR entry
max_subindex = values["subindexes"][0]["DEFAULTVALUE"]
except:
raise SyntaxError, "Error on entry 0x%4.4X:\nSubindex 0 must be defined for an ARRAY or a RECORD entry"%entry
+ Node.AddEntry(entry, value = [])
# Define value for all subindexes except the first
for subindex in xrange(1, int(max_subindex) + 1):
# Take default value if it is defined and entry is defined
from types import *
import os, re, platform, sys, time, traceback, getopt
-__version__ = "$Revision: 1.11 $"
+__version__ = "$Revision: 1.12 $"
from nodelist import *
from nodemanager import *
self._onsave()
event.Skip()
- def GetNoteBook(self):
- return self.NetworkNodes
-
def OnQuitMenu(self, event):
self.Close()
event.Skip()
values = dialog.GetValues()
result = self.NodeList.AddSlaveNode(values["slaveName"], values["slaveNodeID"], values["edsFile"])
if not result:
- new_editingpanel = EditingPanel(self, self.NodeList, False)
+ new_editingpanel = EditingPanel(self.NetworkNodes, self, self.NodeList, False)
new_editingpanel.SetIndex(values["slaveNodeID"])
idx = self.NodeList.GetOrderNumber(values["slaveNodeID"])
self.NetworkNodes.InsertPage(idx, new_editingpanel, "")
if self.NetworkNodes.GetPageCount() > 0:
self.NetworkNodes.DeleteAllPages()
if self.NodeList:
- new_editingpanel = EditingPanel(self, self.Manager)
+ new_editingpanel = EditingPanel(self.NetworkNodes, self, self.Manager)
new_editingpanel.SetIndex(0)
self.NetworkNodes.AddPage(new_editingpanel, "")
for idx in self.NodeList.GetSlaveIDs():
- new_editingpanel = EditingPanel(self, self.NodeList, False)
+ new_editingpanel = EditingPanel(self.NetworkNodes, self, self.NodeList, False)
new_editingpanel.SetIndex(idx)
self.NetworkNodes.AddPage(new_editingpanel, "")
[{"name" : "Inhibit Time Emergency", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
0x1016 : {"name" : "Consumer Heartbeat Time", "struct" : rec, "need" : False, "values" :
[{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
- {"name" : "Consumer Heartbeat Time", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmax" : 0x7F}]},
+ {"name" : "Consumer Heartbeat Time", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 1, "nbmax" : 0x7F}]},
0x1017 : {"name" : "Producer Heartbeat Time", "struct" : var, "need" : False, "callback" : True, "values" :
[{"name" : "Producer Heartbeat Time", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
0x1018 : {"name" : "Identity", "struct" : array, "need" : True, "values" :
{"name" : "StdErr", "type" : 0x05, "access" : 'ro', "pdo" : True}]},
0x1027 : {"name" : "Module List", "struct" : rec, "need" : False, "values" :
[{"name" : "Number of Connected Modules", "type" : 0x05, "access" : 'ro', "pdo" : False},
- {"name" : "Module %d[(sub)]", "type" : 0x06, "access" : 'ro', "pdo" : False, "nbmax" : 0xFE}]},
+ {"name" : "Module %d[(sub)]", "type" : 0x06, "access" : 'ro', "pdo" : False, "nbmin" : 1, "nbmax" : 0xFE}]},
0x1028 : {"name" : "Emergency Consumer", "struct" : rec, "need" : False, "values" :
[{"name" : "Number of Consumed Emergency Objects", "type" : 0x05, "access" : 'ro', "pdo" : False},
- {"name" : "Emergency Consumer", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmax" : 0x7E}]},
+ {"name" : "Emergency Consumer", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 1, "nbmax" : 0x7E}]},
0x1029 : {"name" : "Error Behavior", "struct" : array, "need" : False, "values" :
[{"name" : "Number of Error Classes", "type" : 0x05, "access" : 'ro', "pdo" : False},
{"name" : "Communication Error", "type" : 0x05, "access" : 'rw', "pdo" : False},
{"name" : "Device Profile", "type" : 0x05, "access" : 'rw', "pdo" : False, "nbmax" : 0xFE}]},
0x1200 : {"name" : "Server SDO Parameter", "struct" : array, "need" : False, "values" :
[{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
- {"name" : "COB ID Client to Server (Receive SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False},
- {"name" : "COB ID Server to Client (Transmit SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False}]},
+ {"name" : "COB ID Client to Server (Receive SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False, "default" : "\"$NODEID+0x600\""},
+ {"name" : "COB ID Server to Client (Transmit SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False, "default" : "\"$NODEID+0x580\""}]},
0x1201 : {"name" : "Additional Server SDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x7F, "need" : False, "values" :
[{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
{"name" : "COB ID Client to Server (Receive SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False},
{"name" : "Node ID of the SDO Server", "type" : 0x05, "access" : 'rw', "pdo" : False}]},
0x1400 : {"name" : "Receive PDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
[{"name" : "Highest SubIndex Supported", "type" : 0x05, "access" : 'ro', "pdo" : False},
- {"name" : "COB ID used by PDO", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "{True:self.ID+(base+2)*0x100,False:0}[base<4]"},
+ {"name" : "COB ID used by PDO", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "{True:\"$NODEID+0x%X00\"%(base+2),False:0}[base<4]"},
{"name" : "Transmission Type", "type" : 0x05, "access" : 'rw', "pdo" : False},
{"name" : "Inhibit Time", "type" : 0x06, "access" : 'rw', "pdo" : False},
{"name" : "Compatibility Entry", "type" : 0x05, "access" : 'rw', "pdo" : False},
{"name" : "Event Timer", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
0x1600 : {"name" : "Receive PDO %d Mapping[(idx)]", "struct" : plurirec, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
[{"name" : "Number of Entries", "type" : 0x05, "access" : 'rw', "pdo" : False},
- {"name" : "PDO %d Mapping for an application object %d[(idx,sub)]", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmax" : 0x40}]},
+ {"name" : "PDO %d Mapping for an application object %d[(idx,sub)]", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 0, "nbmax" : 0x40}]},
0x1800 : {"name" : "Transmit PDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x200, "need" : False, "callback" : True, "values" :
[{"name" : "Highest SubIndex Supported", "type" : 0x05, "access" : 'ro', "pdo" : False},
- {"name" : "COB ID used by PDO", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "{True:self.ID+(base+1)*0x100+0x80,False:0}[base<4]"},
+ {"name" : "COB ID used by PDO", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "{True:\"$NODEID+0x%X80\"%(base+1),False:0}[base<4]"},
{"name" : "Transmission Type", "type" : 0x05, "access" : 'rw', "pdo" : False},
{"name" : "Inhibit Time", "type" : 0x06, "access" : 'rw', "pdo" : False},
{"name" : "Compatibility Entry", "type" : 0x05, "access" : 'rw', "pdo" : False},
{"name" : "Event Timer", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
0x1A00 : {"name" : "Transmit PDO %d Mapping[(idx)]", "struct" : plurirec, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
[{"name" : "Number of Entries", "type" : 0x05, "access" : 'rw', "pdo" : False},
- {"name" : "PDO %d Mapping for a process data variable %d[(idx,sub)]", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmax" : 0x40}]},
+ {"name" : "PDO %d Mapping for a process data variable %d[(idx,sub)]", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 0, "nbmax" : 0x40}]},
}
#-------------------------------------------------------------------------------
elif subIndex == 1:
self.Dictionary[index] = [value]
return True
- elif subIndex > 1 and type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]) + 1:
+ elif subIndex > 0 and type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]) + 1:
self.Dictionary[index].append(value)
return True
return False
Returns the value of the entry asked. If the entry has the value "count", it
returns the number of subIndex in the entry except the first.
"""
- def GetEntry(self, index, subIndex = None):
+ def GetEntry(self, index, subIndex = None, compute = True):
if index in self.Dictionary:
if subIndex == None:
if type(self.Dictionary[index]) == ListType:
values = [len(self.Dictionary[index])]
for value in self.Dictionary[index]:
- values.append(self.CompileValue(value, index))
+ values.append(self.CompileValue(value, index, compute))
return values
else:
- return self.CompileValue(self.Dictionary[index], index)
+ return self.CompileValue(self.Dictionary[index], index, compute)
elif subIndex == 0:
if type(self.Dictionary[index]) == ListType:
return len(self.Dictionary[index])
else:
- return self.CompileValue(self.Dictionary[index], index)
+ return self.CompileValue(self.Dictionary[index], index, compute)
elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
- return self.CompileValue(self.Dictionary[index][subIndex - 1], index)
+ return self.CompileValue(self.Dictionary[index][subIndex - 1], index, compute)
return None
"""
mask = 0xFFFF << 16
if subIndex:
model += subIndex << 8
- mask = 0xFF << 8
+ mask += 0xFF << 8
for i in self.Dictionary.iterkeys():
if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
for j,value in enumerate(self.Dictionary[i]):
result += "%04X (%s): %s\n"%(index, name, values)
return result
- def CompileValue(self, value, index):
- if type(value) == StringType and value.find("self.ID") != -1:
+ def CompileValue(self, value, index, compute = True):
+ if type(value) == StringType:
base = self.GetBaseIndex(index)
try:
- return eval(value)
+ raw = eval(value)
+ if compute:
+ return eval(raw.replace("$NODEID","self.ID"))
+ return raw
except:
return 0
else:
node = load(file)
file.close()
self.CurrentNode = node
+ self.CurrentNode.SetNodeID(0)
# Add a new buffer and defining current state
index = self.AddNodeBuffer(self.CurrentNode.Copy(), True)
self.SetCurrentFilePath(filepath)
# Verify if it's not forced that the current node is saved before closing it
if self.UndoBuffers[self.NodeIndex].IsCurrentSaved() or ignore:
self.RemoveNodeBuffer(self.NodeIndex)
+ if len(self.UndoBuffers) > 0:
+ previousindexes = [idx for idx in self.UndoBuffers.keys() if idx < self.NodeIndex]
+ nextindexes = [idx for idx in self.UndoBuffers.keys() if idx > self.NodeIndex]
+ if len(previousindexes) > 0:
+ previousindexes.sort()
+ self.NodeIndex = previousindexes[-1]
+ elif len(nextindexes) > 0:
+ nextindexes.sort()
+ self.NodeIndex = nextindexes[0]
+ else:
+ self.NodeIndex = None
+ else:
+ self.NodeIndex = None
return True
return False
# Informations about entry
infos = self.GetEntryInfos(index)
length = self.CurrentNode.GetEntry(index, 0)
+ if "nbmin" in infos:
+ nbmin = infos["nbmin"]
+ else:
+ nbmin = 1
# Entry is a record, or is an array of manufacturer specific
if infos["struct"] & OD_IdenticalSubindexes or 0x2000 <= index <= 0x5FFF and infos["struct"] & OD_IdenticalSubindexes:
- for i in xrange(min(number, length - 1)):
+ for i in xrange(min(number, length - nbmin)):
self.RemoveCurrentVariable(index, length - i)
self.BufferCurrentNode()
default = subentry_infos["default"]
else:
default = self.GetTypeDefaultValue(subentry_infos["type"])
- node.AddEntry(index, 1, default)
+ node.AddEntry(index, value = [])
+ if "nbmin" in subentry_infos:
+ for i in xrange(subentry_infos["nbmin"]):
+ node.AddEntry(index, i + 1, default)
+ else:
+ node.AddEntry(index, 1, default)
# Second case entry is a record
else:
i = 1
return None
+ """
+ Reset an subentry from current node to its default value
+ """
+ def SetCurrentEntryToDefault(self, index, subindex, node = None):
+ disable_buffer = node != None
+ if node == None:
+ node = self.CurrentNode
+ if node.IsEntry(index, subindex):
+ subentry_infos = self.GetSubentryInfos(index, subindex)
+ if "default" in subentry_infos:
+ default = subentry_infos["default"]
+ else:
+ default = self.GetTypeDefaultValue(subentry_infos["type"])
+ node.SetEntry(index, subindex, default)
+ if not disable_buffer:
+ self.BufferCurrentNode()
+
"""
Remove an entry from current node. Analize the index to perform the correct
method
type = node.GetEntry(type)[1]
if dic[type] == 0:
try:
- if value.startswith("0x"):
+ if value.startswith("$NODEID"):
+ value = "\"%s\""%value
+ elif value.startswith("0x"):
value = int(value, 16)
else:
value = int(value)
return self.CurrentNode.IsEntry(index)
return False
- def GetCurrentEntry(self, index, subIndex = None):
+ def GetCurrentEntry(self, index, subIndex = None, compute = True):
if self.CurrentNode:
- return self.CurrentNode.GetEntry(index, subIndex)
+ return self.CurrentNode.GetEntry(index, subIndex, compute)
return None
def GetCurrentParamsEntry(self, index, subIndex = None):
entry_infos = node.GetEntryInfos(index)
data = []
editors = []
- values = node.GetEntry(index)
+ values = node.GetEntry(index, compute = False)
params = node.GetParamsEntry(index)
if type(values) == ListType:
for i, value in enumerate(values):
if result:
values = result.groups()
if values[0] == "UNSIGNED":
- format = "0x%0" + str(int(values[1])/4) + "X"
- dic["value"] = format%dic["value"]
+ try:
+ format = "0x%0" + str(int(values[1])/4) + "X"
+ dic["value"] = format%dic["value"]
+ except:
+ pass
editor["value"] = "string"
if values[0] == "INTEGER":
editor["value"] = "number"
from types import *
import os, re, platform, sys, time, traceback, getopt
-__version__ = "$Revision: 1.30 $"
+__version__ = "$Revision: 1.31 $"
from node import OD_Subindex, OD_MultipleSubindexes, OD_IdenticalSubindexes, OD_IdenticalIndexes
for filepath in filesOpen:
result = self.Manager.OpenFileInCurrent(filepath)
if type(result) == IntType:
- new_editingpanel = EditingPanel(self, self.Manager)
+ new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
new_editingpanel.SetIndex(result)
self.FileOpened.AddPage(new_editingpanel, "")
window = self.FileOpened.GetPage(0)
self.RefreshTitle()
self.RefreshMainMenu()
- def GetNoteBook(self):
- return self.FileOpened
-
def OnAddSDOServerMenu(self, event):
self.Manager.AddSDOServerToCurrent()
self.RefreshBufferState()
options = dialog.GetOptions()
result = self.Manager.CreateNewNode(name, id, nodetype, description, profile, filepath, NMT, options)
if type(result) == IntType:
- new_editingpanel = EditingPanel(self, self.Manager)
+ new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
new_editingpanel.SetIndex(result)
self.FileOpened.AddPage(new_editingpanel, "")
self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
message.ShowModal()
message.Destroy()
+ dialog.Destroy()
event.Skip()
def OnOpenMenu(self, event):
if os.path.isfile(filepath):
result = self.Manager.OpenFileInCurrent(filepath)
if type(result) == IntType:
- new_editingpanel = EditingPanel(self, self.Manager)
+ new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
new_editingpanel.SetIndex(result)
self.FileOpened.AddPage(new_editingpanel, "")
self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
if os.path.isfile(filepath):
result = self.Manager.ImportCurrentFromEDSFile(filepath)
if type(result) == IntType:
- new_editingpanel = EditingPanel(self, self.Manager)
+ new_editingpanel = EditingPanel(self.FileOpened, self, self.Manager)
new_editingpanel.SetIndex(result)
self.FileOpened.AddPage(new_editingpanel, "")
self.FileOpened.SetSelection(self.FileOpened.GetPageCount() - 1)
] = [wx.NewId() for _init_coll_IndexListMenu_Items in range(3)]
[ID_EDITINGPANELMENU1ITEMS0, ID_EDITINGPANELMENU1ITEMS1,
-] = [wx.NewId() for _init_coll_SubindexGridMenu_Items in range(2)]
+ ID_EDITINGPANELMENU1ITEMS3,
+] = [wx.NewId() for _init_coll_SubindexGridMenu_Items in range(3)]
class EditingPanel(wx.SplitterWindow):
def _init_coll_AddToListSizer_Items(self, parent):
def _init_coll_SubindexGridMenu_Items(self, parent):
parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS0,
- kind=wx.ITEM_NORMAL, text='Add')
+ kind=wx.ITEM_NORMAL, text='Add subindexes')
parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS1,
- kind=wx.ITEM_NORMAL, text='Delete')
+ kind=wx.ITEM_NORMAL, text='Delete subindexes')
+ parent.AppendSeparator()
+ parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS3,
+ kind=wx.ITEM_NORMAL, text='Default value')
self.Bind(wx.EVT_MENU, self.OnAddSubindexMenu,
id=ID_EDITINGPANELMENU1ITEMS0)
self.Bind(wx.EVT_MENU, self.OnDeleteSubindexMenu,
id=ID_EDITINGPANELMENU1ITEMS1)
+ self.Bind(wx.EVT_MENU, self.OnDefaultValueSubindexMenu,
+ id=ID_EDITINGPANELMENU1ITEMS3)
def _init_coll_IndexListMenu_Items(self, parent):
parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS0,
self._init_sizers()
- def __init__(self, parent, manager, editable = True):
- self._init_ctrls(parent.GetNoteBook())
- self.ParentWindow = parent
+ def __init__(self, parent, window, manager, editable = True):
+ self._init_ctrls(parent)
+ self.ParentWindow = window
self.Manager = manager
self.ListIndex = []
self.ChoiceIndex = []
self.Index = None
for values in DictionaryOrganisation:
- text = " 0x%04X-0x%04X %s"%(values["minIndex"],values["maxIndex"],values["name"])
+ text = " 0x%04X-0x%04X %s"%(values["minIndex"], values["maxIndex"], values["name"])
self.PartList.Append(text)
self.Table = SubindexTable(self, [], [], ["subindex", "name", "type", "value", "access", "save", "comment"])
self.SubindexGrid.SetTable(self.Table)
event.Skip()
def OnSubindexGridRightClick(self, event):
+ self.SubindexGrid.SetGridCursor(event.GetRow(), event.GetCol())
if self.Editable:
selected = self.IndexList.GetSelection()
if selected != wx.NOT_FOUND:
index = self.ListIndex[selected]
if self.Manager.IsCurrentEntry(index):
+ showpopup = False
infos = self.Manager.GetEntryInfos(index)
if index >= 0x2000 and infos["struct"] & OD_MultipleSubindexes or infos["struct"] & OD_IdenticalSubindexes:
+ showpopup = True
+ self.SubindexGridMenu.FindItemByPosition(0).Enable(True)
+ self.SubindexGridMenu.FindItemByPosition(1).Enable(True)
+ else:
+ self.SubindexGridMenu.FindItemByPosition(0).Enable(False)
+ self.SubindexGridMenu.FindItemByPosition(1).Enable(False)
+ if self.Table.GetColLabelValue(event.GetCol()) == "value":
+ showpopup = True
+ self.SubindexGridMenu.FindItemByPosition(3).Enable(True)
+ else:
+ self.SubindexGridMenu.FindItemByPosition(3).Enable(False)
+ if showpopup:
self.PopupMenu(self.SubindexGridMenu)
event.Skip()
dialog.Destroy()
event.Skip()
+ def OnDefaultValueSubindexMenu(self, event):
+ if self.Editable:
+ selected = self.IndexList.GetSelection()
+ if selected != wx.NOT_FOUND:
+ index = self.ListIndex[selected]
+ if self.Manager.IsCurrentEntry(index):
+ row = self.SubindexGrid.GetGridCursorRow()
+ self.Manager.SetCurrentEntryToDefault(index, row)
+ self.ParentWindow.RefreshBufferState()
+ self.RefreshIndexList()
+ event.Skip()
\ No newline at end of file