--- a/etherlab/ConfigEditor.py Tue Mar 05 00:59:34 2013 +0100
+++ b/etherlab/ConfigEditor.py Tue Mar 05 23:04:59 2013 +0100
@@ -331,14 +331,25 @@
master_location = self.ParentWindow.GetMasterLocation()
if (master_location == tuple(location[:len(master_location)]) and
len(location) - len(master_location) == 3):
+ values = tuple(location[len(master_location):]) + var_type = self.ParentWindow.Controler.GetSlaveVariableDataType(*values) - self.ParentWindow.ProcessVariablesTable.SetValueByName(
- row, "ReadFrom", tuple(location[len(master_location):]))
+ other_values = self.ParentWindow.ProcessVariablesTable.GetValueByName(row, "WriteTo") + other_values = self.ParentWindow.ProcessVariablesTable.GetValueByName(row, "ReadFrom") + other_type = self.ParentWindow.Controler.GetSlaveVariableDataType(*other_values) - self.ParentWindow.ProcessVariablesTable.SetValueByName(
- row, "WriteTo", tuple(location[len(master_location):]))
- self.ParentWindow.SaveProcessVariables()
- self.ParentWindow.RefreshProcessVariables()
+ if other_type is None or var_type == other_type: + self.ParentWindow.ProcessVariablesTable.SetValueByName(row, "ReadFrom", values) + self.ParentWindow.ProcessVariablesTable.SetValueByName(row, "WriteTo", values) + self.ParentWindow.SaveProcessVariables() + self.ParentWindow.RefreshProcessVariables() + message = _("'Read from' and 'Write to' variables types are not compatible") message = _("Invalid value \"%s\" for process variable")%data
@@ -375,7 +386,7 @@
if values[1] == "location":
result = LOCATION_MODEL.match(values[0])
+ if result is not None and len(values) > 5: location = map(int, result.group(1).split('.'))
elif values[1] == "variable":
@@ -531,6 +542,7 @@
self.OnProcessVariablesGridCellChange)
self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK,
self.OnProcessVariablesGridCellLeftClick)
+ self.ProcessVariablesGrid.Bind(wx.EVT_KEY_DOWN, self.OnProcessVariablesGridKeyDown) startup_commands_header = wx.BoxSizer(wx.HORIZONTAL)
@@ -586,7 +598,10 @@
def __init__(self, parent, controler, window):
ConfTreeNodeEditor.__init__(self, parent, controler, window)
+ self.ProcessVariables = [] + self.LastCommandInfos = None self.ProcessVariablesDefaultValue = {"Name": "", "ReadFrom": "", "WriteTo": "", "Description": ""}
self.ProcessVariablesTable = ProcessVariablesTable(self, [], GetProcessVariablesTableColnames())
self.ProcessVariablesColSizes = [40, 100, 150, 150, 200]
@@ -619,6 +634,17 @@
setattr(self.ProcessVariablesGrid, "_MoveRow", _MoveVariablesElement)
+ _refresh_buttons = getattr(self.ProcessVariablesGrid, "RefreshButtons") + if self.NodesFilter.GetSelection() == 0: + self.AddVariableButton.Enable(False) + self.DeleteVariableButton.Enable(False) + self.UpVariableButton.Enable(False) + self.DownVariableButton.Enable(False) + setattr(self.ProcessVariablesGrid, "RefreshButtons", _RefreshButtons) self.ProcessVariablesGrid.SetRowLabelSize(0)
for col in range(self.ProcessVariablesTable.GetNumberCols()):
attr = wx.grid.GridCellAttr()
@@ -651,7 +677,7 @@
self.RefreshStartupCommands()
setattr(self.StartupCommandsGrid, "_DeleteRow", _DeleteCommandsElement)
self.StartupCommandsGrid.SetRowLabelSize(0)
for col in range(self.StartupCommandsTable.GetNumberCols()):
attr = wx.grid.GridCellAttr()
@@ -667,6 +693,17 @@
self.ParentWindow.RefreshEditMenu()
self.ParentWindow.RefreshPageTitles()
+ def GetBufferState(self): + return self.Controler.GetBufferState() + self.Controler.LoadPrevious() + self.Controler.LoadNext() ConfTreeNodeEditor.RefreshView(self)
@@ -707,20 +744,31 @@
self.NodesVariables.SetCurrentNodesFilter(self.CurrentNodesFilter)
def RefreshProcessVariables(self):
- self.ProcessVariablesTable.SetData(
- self.Controler.GetProcessVariables())
- self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
+ if self.CurrentNodesFilter is not None: + self.ProcessVariables = self.Controler.GetProcessVariables() + slaves = self.Controler.GetSlaves(**self.CurrentNodesFilter) + for variable in self.ProcessVariables: + if (variable["ReadFrom"] == "" or variable["ReadFrom"][0] in slaves or + variable["WriteTo"] == "" or variable["WriteTo"][0] in slaves): + self.ProcessVariablesTable.SetData(data) + self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid) + self.ProcessVariablesGrid.RefreshButtons() def SaveProcessVariables(self):
self.Controler.SetProcessVariables(
self.ProcessVariablesTable.GetData())
- def RefreshStartupCommands(self):
+ def RefreshStartupCommands(self, position=None, command_idx=None): if self.CurrentNodesFilter is not None:
+ self.StartupCommandsGrid.CloseEditControl() self.StartupCommandsTable.SetData(
self.Controler.GetStartupCommands(**self.CurrentNodesFilter))
self.StartupCommandsTable.ResetView(self.StartupCommandsGrid)
+ if position is not None and command_idx is not None: + self.SelectStartupCommand(position, command_idx) def SelectStartupCommand(self, position, command_idx):
self.StartupCommandsGrid.SetSelectedRow(
@@ -768,15 +816,43 @@
def OnProcessVariablesGridCellLeftClick(self, event):
+ if event.GetCol() == 0: + var_name = self.ProcessVariablesTable.GetValueByName(row, "Name") + var_type = self.Controler.GetSlaveVariableDataType( + *self.ProcessVariablesTable.GetValueByName(row, "ReadFrom")) + data_size = self.Controler.GetSizeOfType(var_type) + number = self.ProcessVariablesTable.GetValueByName(row, "Number") + location = "%%M%s" % data_size + \ + ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation() + (number,))) + data = wx.TextDataObject(str((location, "location", var_type, var_name, ""))) + dragSource = wx.DropSource(self.ProcessVariablesGrid) + dragSource.SetData(data) + dragSource.DoDragDrop() + def OnProcessVariablesGridKeyDown(self, event): + keycode = event.GetKeyCode() + col = self.ProcessVariablesGrid.GetGridCursorCol() + row = self.ProcessVariablesGrid.GetGridCursorRow() + colname = self.ProcessVariablesTable.GetColLabelValue(col, False) + if (keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and + (colname.startswith("Read from") or colname.startswith("Write to"))): + self.ProcessVariablesTable.SetValue(row, col, "") + self.SaveProcessVariables() + wx.CallAfter(self.ProcessVariablesTable.ResetView, self.ProcessVariablesGrid) def OnStartupCommandsGridCellChange(self, event):
row, col = event.GetRow(), event.GetCol()
colname = self.StartupCommandsTable.GetColLabelValue(col, False)
value = self.StartupCommandsTable.GetValue(row, col)
if colname == "Position":
if value not in self.Controler.GetSlaves():
message = _("No slave defined at position %d!") % value
@@ -786,13 +862,22 @@
self.StartupCommandsTable.GetValueByName(row, "command_idx"))
command = self.StartupCommandsTable.GetRow(row)
command_idx = self.Controler.AppendStartupCommand(command)
- wx.CallAfter(self.RefreshStartupCommands)
- wx.CallAfter(self.SelectStartupCommand, command["Position"], command_idx)
+ wx.CallAfter(self.RefreshStartupCommands, command["Position"], command_idx) - self.Controler.SetStartupCommandInfos(self.StartupCommandsTable.GetRow(row))
+ command = self.StartupCommandsTable.GetRow(row) + if self.LastCommandInfos != command: + self.LastCommandInfos = command.copy() + self.Controler.SetStartupCommandInfos(command) + if colname in ["Index", "SubIndex"]: + wx.CallAfter(self.RefreshStartupCommands, command["Position"], command["command_idx"])
dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
--- a/etherlab/etherlab.py Tue Mar 05 00:59:34 2013 +0100
+++ b/etherlab/etherlab.py Tue Mar 05 23:04:59 2013 +0100
@@ -650,20 +650,6 @@
def ProcessVariablesFileName(self):
return os.path.join(self.CTNPath(), "process_variables.xml")
- for slave in self.Config.getConfig().getSlave():
- slaves.append(slave.getInfo().getPhysAddr())
- def GetSlave(self, slave_pos):
- for slave in self.Config.getConfig().getSlave():
- slave_info = slave.getInfo()
- if slave_info.getPhysAddr() == slave_pos:
def FilterSlave(self, slave, vendor=None, slave_pos=None, slave_profile=None):
if slave_pos is not None and slave.getInfo().getPhysAddr() != slave_pos:
@@ -675,6 +661,21 @@
+ def GetSlaves(self, vendor=None, slave_pos=None, slave_profile=None): + for slave in self.Config.getConfig().getSlave(): + if self.FilterSlave(slave, vendor, slave_pos, slave_profile): + slaves.append(slave.getInfo().getPhysAddr()) + def GetSlave(self, slave_pos): + for slave in self.Config.getConfig().getSlave(): + slave_info = slave.getInfo() + if slave_info.getPhysAddr() == slave_pos: def GetStartupCommands(self, vendor=None, slave_pos=None, slave_profile=None):
for slave in self.Config.getConfig().getSlave():
@@ -735,8 +736,10 @@
def GetProcessVariables(self):
for variable in self.ProcessVariables.getvariable():
var = {"Name": variable.getName(),
"Description": variable.getComment()}
read_from = variable.getReadFrom()
if read_from is not None:
@@ -753,6 +756,7 @@
@@ -831,7 +835,18 @@
slave_info = slave.getInfo()
slave_info.setPhysAddr(new_pos)
+ for variable in self.ProcessVariables.getvariable(): + read_from = variable.getReadFrom() + if read_from is not None and read_from.getPosition() == slave_pos: + read_from.setPosition(new_pos) + write_to = variable.getWriteTo() + if write_to is not None and write_to.getPosition() == slave_pos: + write_to.setPosition(new_pos) + self.CreateBuffer(True) + if self._View is not None: + self._View.RefreshView() + self._View.RefreshBuffer() def GetSlaveAlias(self, slave_pos):
slave = self.GetSlave(slave_pos)
@@ -901,6 +916,17 @@
+ def GetSlaveVariableDataType(self, slave_pos, index, subindex): + slave = self.GetSlave(slave_pos) + device, alignment = self.GetModuleInfos(slave.getType()) + entries = device.GetEntriesList() + entry_infos = entries.get((index, subindex)) + if entry_infos is not None: + return entry_infos["Type"] def GetNodesVariables(self, vendor=None, slave_pos=None, slave_profile=None, limits=None):
for slave_position in self.GetSlaves():
@@ -1005,7 +1031,7 @@
LocationCFilesAndCFLAGS, LDFLAGS, extra_files = ConfigTreeNode._Generate_C(self, buildpath, locations)
- self.FileGenerator.GenerateCFile(Gen_Ethercatfile_path, location_str, self.EtherlabNode)
+ self.FileGenerator.GenerateCFile(Gen_Ethercatfile_path, location_str, self.BaseParams.getIEC_Channel()) LocationCFilesAndCFLAGS.append(
@@ -1041,7 +1067,7 @@
slave = self.GetSlave(slave_pos)
- self.FileGenerator.DeclareSlave(slave_pos, slave.getInfo().getAutoIncAddr(), slave.getType())
+ self.FileGenerator.DeclareSlave(slave_pos, slave) for location in locations:
loc = location["LOC"][len(current_location):]
@@ -1210,8 +1236,8 @@
- def DeclareSlave(self, slave_index, slave_alias, slave):
- self.Slaves.append((slave_index, slave_alias, slave))
+ def DeclareSlave(self, slave_index, slave): + self.Slaves.append((slave_index, slave.getInfo().getAutoIncAddr(), slave)) def DeclareVariable(self, slave_index, index, subindex, iec_type, dir, name):
slave_variables = self.UsedVariables.setdefault(slave_index, {})
@@ -1224,7 +1250,7 @@
elif entry_infos["infos"] != (iec_type, dir, name):
raise ValueError, _("Definition conflict for location \"%s\"") % name
- def GenerateCFile(self, filepath, location_str, etherlab_node_infos):
+ def GenerateCFile(self, filepath, location_str, master_number): # Extract etherlab master code template
plc_etherlab_filepath = os.path.join(os.path.split(__file__)[0], "plc_etherlab.c")
@@ -1235,7 +1261,7 @@
# Initialize strings for formatting master code template
"location": location_str,
- "master_number": self.BaseParams.getIEC_Channel(),
+ "master_number": master_number, "located_variables_declaration": [],
"used_pdo_entry_offset_variables_declaration": [],
"used_pdo_entry_configuration": [],
@@ -1259,7 +1285,8 @@
# Generating code for each slave
- for (slave_idx, slave_alias, type_infos) in self.Slaves:
+ for (slave_idx, slave_alias, slave) in self.Slaves: + type_infos = slave.getType() # Defining slave alias and auto-increment position
if alias.get(slave_alias) is not None:
@@ -1289,13 +1316,20 @@
# If device support CanOpen over Ethernet, adding code for calling
# init commands when initializing slave in master code template strings
for initCmd in device_coe.getInitCmd():
- index = ExtractHexDecValue(initCmd.getIndex())
- subindex = ExtractHexDecValue(initCmd.getSubIndex())
+ "Index": ExtractHexDecValue(initCmd.getIndex()), + "Subindex": ExtractHexDecValue(initCmd.getSubIndex()), + "Value": initCmd.getData().getcontent()}) + initCmds.extend(slave.getStartupCommands()) + for initCmd in initCmds: + index = initCmd["Index"] + subindex = initCmd["Subindex"] entry = device_entries.get((index, subindex), None)
data_size = entry["BitSize"] / 8
- data_str = ("0x%%.%dx" % (data_size * 2)) % initCmd.getData().getcontent()
+ data_str = ("0x%%.%dx" % (data_size * 2)) % initCmd["Value"] @@ -1554,6 +1588,8 @@
dynamic_pdos[pdo_type]["pdos"].append(pdo)
pdo["entries"].append(" {0x%(index).4x, 0x%(subindex).2x, %(bitlen)d}, /* %(name)s */" % entry_infos)
+ if entry_infos["bitlen"] < alignment: + pdo["entries"].append(" {0x0000, 0x00, %d}, /* None */" % (alignment - entry_infos["bitlen"])) pdo["entries_number"] += 1
if pdo["entries_number"] == 255: