5 import wx |
5 import wx |
6 |
6 |
7 from xmlclass import * |
7 from xmlclass import * |
8 from plugger import PlugTemplate |
8 from plugger import PlugTemplate |
9 from PLCControler import UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY |
9 from PLCControler import UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY |
10 from ConfigEditor import ConfigEditor, DS402NodeEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE |
10 from ConfigEditor import NodeEditor, DS402NodeEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE |
|
11 |
|
12 try: |
|
13 from plugins.motion import Headers, AxisXSD |
|
14 HAS_MCL = True |
|
15 except: |
|
16 HAS_MCL = False |
|
17 |
|
18 |
|
19 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L", |
|
20 "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", |
|
21 "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L"} |
|
22 |
|
23 DATATYPECONVERSION = {"BOOL" : "BIT", "SINT" : "S8", "INT" : "S16", "DINT" : "S32", "LINT" : "S64", |
|
24 "USINT" : "U8", "UINT" : "U16", "UDINT" : "U32", "ULINT" : "U64", |
|
25 "BYTE" : "U8", "WORD" : "U16", "DWORD" : "U32", "LWORD" : "U64"} |
|
26 |
|
27 VARCLASSCONVERSION = {"T": LOCATION_VAR_INPUT, "R": LOCATION_VAR_OUTPUT, "RT": LOCATION_VAR_MEMORY} |
11 |
28 |
12 #-------------------------------------------------- |
29 #-------------------------------------------------- |
13 # Ethercat DS402 Node |
30 # Remote Exec Etherlab Commands |
14 #-------------------------------------------------- |
31 #-------------------------------------------------- |
15 |
32 |
16 NODE_VARIABLES = [ |
33 SCAN_COMMAND = """ |
17 ("ControlWord", 0x6040, 0x00, "UINT", "Q"), |
34 import commands |
18 ("TargetPosition", 0x607a, 0x00, "DINT", "Q"), |
35 result = commands.getoutput("ethercat slaves") |
19 ("StatusWord", 0x6041, 0x00, "UINT", "I"), |
36 slaves = [] |
20 ("ModesOfOperationDisplay", 0x06061, 0x00, "SINT", "I"), |
37 for slave_line in result.splitlines(): |
21 ("ActualPosition", 0x6064, 0x00, "DINT", "I"), |
38 chunks = slave_line.split() |
22 ("ErrorCode", 0x603f, 0x00, "UINT", "I"), |
39 idx, pos, state, flag = chunks[:4] |
23 ] |
40 name = " ".join(chunks[4:]) |
24 |
41 alias, position = pos.split(":") |
25 class _EthercatDS402SlavePlug: |
42 slave = {"idx": int(idx), |
26 XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> |
43 "alias": int(alias), |
27 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
44 "position": int(position), |
28 <xsd:element name="EtherlabDS402Slave"> |
45 "name": name} |
29 <xsd:complexType> |
46 details = commands.getoutput("ethercat slaves -p %d -v" % slave["idx"]) |
30 <xsd:attribute name="Node_Type" type="xsd:string" use="optional"/> |
47 for details_line in details.splitlines(): |
31 </xsd:complexType> |
48 details_line = details_line.strip() |
32 </xsd:element> |
49 for header, param in [("Vendor Id:", "vendor_id"), |
33 </xsd:schema> |
50 ("Product code:", "product_code"), |
34 """ |
51 ("Revision number:", "revision_number")]: |
35 EditorType = DS402NodeEditor |
52 if details_line.startswith(header): |
|
53 slave[param] = int(details_line.split()[-1], 16) |
|
54 break |
|
55 slaves.append(slave) |
|
56 returnVal = slaves |
|
57 """ |
|
58 |
|
59 #-------------------------------------------------- |
|
60 # Ethercat Node |
|
61 #-------------------------------------------------- |
|
62 |
|
63 class _EthercatSlavePlug: |
|
64 |
|
65 NODE_PROFILE = None |
|
66 EditorType = NodeEditor |
36 |
67 |
37 def ExtractHexDecValue(self, value): |
68 def ExtractHexDecValue(self, value): |
38 return ExtractHexDecValue(value) |
69 return ExtractHexDecValue(value) |
39 |
70 |
40 def GetSizeOfType(self, type): |
71 def GetSizeOfType(self, type): |
41 return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None) |
72 return TYPECONVERSION.get(self.GetPlugRoot().GetBaseType(type), None) |
42 |
73 |
43 def _GetChildBySomething(self, something, toks): |
74 def GetSlavePos(self): |
44 return self |
75 return self.BaseParams.getIEC_Channel() |
45 |
76 |
46 def GetParamsAttributes(self, path = None): |
77 def GetParamsAttributes(self, path = None): |
47 infos = PlugTemplate.GetParamsAttributes(self, path = None) |
78 if path: |
48 for element in infos: |
79 parts = path.split(".", 1) |
49 if element["name"] == "EtherlabDS402Slave": |
80 if self.MandatoryParams and parts[0] == self.MandatoryParams[0]: |
50 for child in element["children"]: |
81 return self.MandatoryParams[1].getElementInfos(parts[0], parts[1]) |
51 if child["name"] == "Node_Type": |
82 elif self.PlugParams and parts[0] == self.PlugParams[0]: |
52 child["type"] = [module[0] for module in self.PlugParent.GetModulesByProfile(402)] |
83 return self.PlugParams[1].getElementInfos(parts[0], parts[1]) |
53 return infos |
84 else: |
54 |
85 params = [] |
55 def GetAllChannels(self): |
86 if wx.VERSION < (2, 8, 0) and self.MandatoryParams: |
56 AllChannels = PlugTemplate.GetAllChannels(self) |
87 params.append(self.MandatoryParams[1].getElementInfos(self.MandatoryParams[0])) |
57 for slave_pos in self.PlugParent.GetSlaves(): |
88 slave_type = self.PlugParent.GetSlaveType(self.GetSlavePos()) |
58 if slave_pos[0] not in AllChannels: |
89 params.append({ |
59 AllChannels.append(slave_pos[0]) |
90 'use': 'required', |
60 AllChannels.sort() |
91 'type': 'element', |
61 return AllChannels |
92 'name': 'SlaveParams', |
62 |
93 'value': None, |
63 def GetCurrentLocation(self): |
94 'children': [{ |
64 """ |
95 'use': 'optional', |
65 @return: Tupple containing plugin IEC location of current plugin : %I0.0.4.5 => (0,0,4,5) |
96 'type': self.PlugParent.GetSlaveTypesLibrary(self.NODE_PROFILE), |
66 """ |
97 'name': 'Type', |
67 return self.PlugParent.GetCurrentLocation() + self.GetSlavePos() |
98 'value': (slave_type["device_type"], slave_type)}, |
68 |
99 {'use': 'optional', |
69 def GetSlavePos(self): |
100 'type': 'unsignedLong', |
70 return self.BaseParams.getIEC_Channel(), 0 |
101 'name': 'Alias', |
71 |
102 'value': self.PlugParent.GetSlaveAlias(self.GetSlavePos())}] |
72 def GetSlaveTypeInfos(self): |
103 }) |
73 slave_type = self.EtherlabDS402Slave.getNode_Type() |
104 if self.PlugParams: |
74 |
105 params.append(self.PlugParams[1].getElementInfos(self.PlugParams[0])) |
75 for module_type, vendor_id, product_code, revision_number in self.PlugParent.GetModulesByProfile(402): |
106 return params |
76 if module_type == slave_type: |
107 |
77 return {"device_type": module_type, |
108 def SetParamsAttribute(self, path, value): |
78 "vendor": GenerateHexDecValue(vendor_id), |
109 position = self.BaseParams.getIEC_Channel() |
79 "product_code": GenerateHexDecValue(product_code, 16), |
110 value, changed = PlugTemplate.SetParamsAttribute(self, path, value) |
80 "revision_number": GenerateHexDecValue(revision_number, 16)} |
111 # Filter IEC_Channel, Slave_Type and Alias that have specific behavior |
81 |
112 if path == "BaseParams.IEC_Channel": |
82 return None |
113 self.PlugParent.SetSlavePosition(position, value) |
|
114 elif path == "SlaveParams.Type": |
|
115 self.PlugParent.SetSlaveType(position, value) |
|
116 slave_type = self.PlugParent.GetSlaveType(self.GetSlavePos()) |
|
117 value = (slave_type["device_type"], slave_type) |
|
118 changed = True |
|
119 elif path == "SlaveParams.Alias": |
|
120 self.PlugParent.SetSlaveAlias(position, value) |
|
121 changed = True |
|
122 return value, changed |
83 |
123 |
84 def GetSlaveInfos(self): |
124 def GetSlaveInfos(self): |
85 slave_typeinfos = self.GetSlaveTypeInfos() |
125 return self.PlugParent.GetSlaveInfos(self.GetSlavePos()) |
86 if slave_typeinfos is not None: |
126 |
87 device = self.PlugParent.GetModuleInfos(slave_typeinfos) |
|
88 if device is not None: |
|
89 infos = slave_typeinfos.copy() |
|
90 entries = device.GetEntriesList() |
|
91 entries_list = entries.items() |
|
92 entries_list.sort() |
|
93 entries = [] |
|
94 current_index = None |
|
95 current_entry = None |
|
96 for (index, subindex), entry in entries_list: |
|
97 entry["children"] = [] |
|
98 if index != current_index: |
|
99 current_index = index |
|
100 current_entry = entry |
|
101 entries.append(entry) |
|
102 elif current_entry is not None: |
|
103 current_entry["children"].append(entry) |
|
104 else: |
|
105 entries.append(entry) |
|
106 infos.update({"physics": device.getPhysics(), |
|
107 "sync_managers": device.GetSyncManagers(), |
|
108 "entries": entries}) |
|
109 return infos |
|
110 return None |
|
111 |
|
112 def GetVariableLocationTree(self): |
127 def GetVariableLocationTree(self): |
113 slave_typeinfos = self.GetSlaveTypeInfos() |
|
114 vars = [] |
|
115 if slave_typeinfos is not None: |
|
116 vars = self.PlugParent.GetDeviceLocationTree(self.GetCurrentLocation(), slave_typeinfos) |
|
117 |
|
118 return {"name": self.BaseParams.getName(), |
128 return {"name": self.BaseParams.getName(), |
119 "type": LOCATION_PLUGIN, |
129 "type": LOCATION_PLUGIN, |
120 "location": self.GetFullIEC_Channel(), |
130 "location": self.GetFullIEC_Channel(), |
121 "children": vars} |
131 "children": self.PlugParent.GetDeviceLocationTree(self.GetSlavePos(), self.GetCurrentLocation(), self.BaseParams.getName()) |
|
132 } |
122 |
133 |
123 PluginMethods = [ |
134 PluginMethods = [ |
124 {"bitmap" : os.path.join("images", "EditCfile"), |
135 {"bitmap" : os.path.join("images", "EditCfile"), |
125 "name" : _("Edit Node"), |
136 "name" : _("Edit Node"), |
126 "tooltip" : _("Edit Node"), |
137 "tooltip" : _("Edit Node"), |
127 "method" : "_OpenView"}, |
138 "method" : "_OpenView"}, |
128 ] |
139 ] |
129 |
|
130 |
140 |
131 def PlugGenerate_C(self, buildpath, locations): |
141 def PlugGenerate_C(self, buildpath, locations): |
132 """ |
142 """ |
133 Generate C code |
143 Generate C code |
134 @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) |
144 @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) |
139 "SIZE" : size "X", "B", "W", "D", "L" |
149 "SIZE" : size "X", "B", "W", "D", "L" |
140 "LOC" : tuple of interger for IEC location (0,1,2,...) |
150 "LOC" : tuple of interger for IEC location (0,1,2,...) |
141 }, ...] |
151 }, ...] |
142 @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND |
152 @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND |
143 """ |
153 """ |
144 current_location = self.GetCurrentLocation() |
154 return [],"",False |
145 |
155 |
146 location_str = "_".join(map(lambda x:str(x), current_location)) |
156 #-------------------------------------------------- |
147 |
157 # Ethercat DS402 Node |
148 slave_pos = current_location[-2:] |
158 #-------------------------------------------------- |
149 |
159 |
150 slave_typeinfos = self.GetSlaveTypeInfos() |
160 if HAS_MCL: |
151 device = None |
161 |
152 if slave_typeinfos is not None: |
162 NODE_VARIABLES = [ |
153 device = self.PlugParent.GetModuleInfos(slave_typeinfos) |
163 ("ControlWord", 0x6040, 0x00, "UINT", "Q"), |
154 |
164 ("TargetPosition", 0x607a, 0x00, "DINT", "Q"), |
155 if device is None: |
165 ("StatusWord", 0x6041, 0x00, "UINT", "I"), |
156 raise (ValueError, |
166 ("ModesOfOperationDisplay", 0x06061, 0x00, "SINT", "I"), |
157 _("No information found for DS402 node \"%s\" at location %s!") % ( |
167 ("ActualPosition", 0x6064, 0x00, "DINT", "I"), |
158 slave_typeinfos["device_type"], ".".join(current_location))) |
168 ("ErrorCode", 0x603f, 0x00, "UINT", "I"), |
159 |
169 ] |
160 self.PlugParent.FileGenerator.DeclareSlave(slave_pos, slave_typeinfos) |
170 |
161 |
171 class _EthercatDS402SlavePlug(_EthercatSlavePlug): |
162 plc_ds402node_filepath = os.path.join(os.path.split(__file__)[0], "plc_ds402node.c") |
172 XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?> |
163 plc_ds402node_file = open(plc_ds402node_filepath, 'r') |
173 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
164 plc_ds402node_code = plc_ds402node_file.read() |
174 <xsd:element name="DS402SlaveParams"> |
165 plc_ds402node_file.close() |
175 <xsd:complexType> |
166 |
176 %s |
167 from plugins.motion import Headers |
177 </xsd:complexType> |
168 |
178 </xsd:element> |
169 str_completion = { |
179 </xsd:schema> |
170 "location": location_str, |
180 """ % AxisXSD |
171 "MCL_headers": Headers, |
181 |
172 "extern_located_variables_declaration": [], |
182 NODE_PROFILE = 402 |
173 "entry_variables": [], |
183 EditorType = DS402NodeEditor |
174 "init_entry_variables": [], |
184 |
175 } |
185 def PlugGenerate_C(self, buildpath, locations): |
176 |
186 """ |
177 for variable in NODE_VARIABLES: |
187 Generate C code |
178 var_infos = dict(zip(["name", "index", "subindex", "var_type", "dir"], variable)) |
188 @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) |
179 var_infos["location"] = location_str |
189 @param locations: List of complete variables locations \ |
180 var_infos["var_size"] = self.PlugParent.GetSizeOfType(var_infos["var_type"]) |
190 [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) |
181 var_infos["var_name"] = "__%(dir)s%(var_size)s%(location)s_%(index)d_%(subindex)d" % var_infos |
191 "NAME" : name of the variable (generally "__IW0_1_2" style) |
182 |
192 "DIR" : direction "Q","I" or "M" |
183 str_completion["extern_located_variables_declaration"].append( |
193 "SIZE" : size "X", "B", "W", "D", "L" |
184 "IEC_%(var_type)s *%(var_name)s;" % var_infos) |
194 "LOC" : tuple of interger for IEC location (0,1,2,...) |
185 str_completion["entry_variables"].append( |
195 }, ...] |
186 " IEC_%(var_type)s *%(name)s;" % var_infos) |
196 @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND |
187 str_completion["init_entry_variables"].append( |
197 """ |
188 " __DS402Node_%(location)s.%(name)s = %(var_name)s;" % var_infos) |
198 current_location = self.GetCurrentLocation() |
189 |
199 |
190 self.PlugParent.FileGenerator.DeclareVariable( |
200 location_str = "_".join(map(lambda x:str(x), current_location)) |
191 slave_pos, var_infos["index"], var_infos["subindex"], |
201 |
192 var_infos["var_type"], var_infos["dir"], var_infos["var_name"]) |
202 plc_ds402node_filepath = os.path.join(os.path.split(__file__)[0], "plc_ds402node.c") |
193 |
203 plc_ds402node_file = open(plc_ds402node_filepath, 'r') |
194 for element in ["extern_located_variables_declaration", |
204 plc_ds402node_code = plc_ds402node_file.read() |
195 "entry_variables", |
205 plc_ds402node_file.close() |
196 "init_entry_variables"]: |
206 |
197 str_completion[element] = "\n".join(str_completion[element]) |
207 str_completion = { |
198 |
208 "location": location_str, |
199 Gen_DS402Nodefile_path = os.path.join(buildpath, "ds402node_%s.c"%location_str) |
209 "MCL_headers": Headers, |
200 ds402nodefile = open(Gen_DS402Nodefile_path, 'w') |
210 "extern_located_variables_declaration": [], |
201 ds402nodefile.write(plc_ds402node_code % str_completion) |
211 "entry_variables": [], |
202 ds402nodefile.close() |
212 "init_axis_params": [], |
203 |
213 "init_entry_variables": [], |
204 return [(Gen_DS402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath()))],"",True |
214 } |
205 |
215 |
206 |
216 for variable in NODE_VARIABLES: |
207 |
217 var_infos = dict(zip(["name", "index", "subindex", "var_type", "dir"], variable)) |
208 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L", |
218 var_infos["location"] = location_str |
209 "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", |
219 var_infos["var_size"] = self.GetSizeOfType(var_infos["var_type"]) |
210 "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L"} |
220 var_infos["var_name"] = "__%(dir)s%(var_size)s%(location)s_%(index)d_%(subindex)d" % var_infos |
211 |
221 |
212 DATATYPECONVERSION = {"BOOL" : "BIT", "SINT" : "S8", "INT" : "S16", "DINT" : "S32", "LINT" : "S64", |
222 str_completion["extern_located_variables_declaration"].append( |
213 "USINT" : "U8", "UINT" : "U16", "UDINT" : "U32", "ULINT" : "U64", |
223 "IEC_%(var_type)s *%(var_name)s;" % var_infos) |
214 "BYTE" : "U8", "WORD" : "U16", "DWORD" : "U32", "LWORD" : "U64"} |
224 str_completion["entry_variables"].append( |
215 |
225 " IEC_%(var_type)s *%(name)s;" % var_infos) |
216 VARCLASSCONVERSION = {"T": LOCATION_VAR_INPUT, "R": LOCATION_VAR_OUTPUT, "RT": LOCATION_VAR_MEMORY} |
226 str_completion["init_entry_variables"].append( |
|
227 " __DS402Node_%(location)s.%(name)s = %(var_name)s;" % var_infos) |
|
228 |
|
229 self.PlugParent.FileGenerator.DeclareVariable( |
|
230 self.GetSlavePos(), var_infos["index"], var_infos["subindex"], |
|
231 var_infos["var_type"], var_infos["dir"], var_infos["var_name"]) |
|
232 |
|
233 params = self.PlugParams[1].getElementInfos(self.PlugParams[0]) |
|
234 for param in params["children"]: |
|
235 if param["value"] is not None: |
|
236 param_infos = { |
|
237 "location": location_str, |
|
238 "param_name": param["name"], |
|
239 } |
|
240 if param["type"] == "boolean": |
|
241 param_infos["param_value"] = {True: "true", False: "false"}[param["value"]] |
|
242 else: |
|
243 param_infos["param_value"] = str(param["value"]) |
|
244 str_completion["init_axis_params"].append( |
|
245 " __DS402Node_%(location)s.axis->%(param_name)s = %(param_value)s;" % param_infos) |
|
246 |
|
247 for element in ["extern_located_variables_declaration", |
|
248 "entry_variables", |
|
249 "init_axis_params", |
|
250 "init_entry_variables"]: |
|
251 str_completion[element] = "\n".join(str_completion[element]) |
|
252 |
|
253 Gen_DS402Nodefile_path = os.path.join(buildpath, "ds402node_%s.c"%location_str) |
|
254 ds402nodefile = open(Gen_DS402Nodefile_path, 'w') |
|
255 ds402nodefile.write(plc_ds402node_code % str_completion) |
|
256 ds402nodefile.close() |
|
257 |
|
258 return [(Gen_DS402Nodefile_path, '"-I%s"'%os.path.abspath(self.GetPlugRoot().GetIECLibPath()))],"",True |
217 |
259 |
218 #-------------------------------------------------- |
260 #-------------------------------------------------- |
219 # Ethercat MASTER |
261 # Ethercat MASTER |
220 #-------------------------------------------------- |
262 #-------------------------------------------------- |
221 |
263 |
312 return os.path.join(self.PlugPath(), "config.xml") |
343 return os.path.join(self.PlugPath(), "config.xml") |
313 |
344 |
314 def GetSlaves(self): |
345 def GetSlaves(self): |
315 slaves = [] |
346 slaves = [] |
316 for slave in self.Config.getConfig().getSlave(): |
347 for slave in self.Config.getConfig().getSlave(): |
317 slaves.append(slave.getInfo().getSlavePosition()) |
348 slaves.append(slave.getInfo().getPhysAddr()) |
318 slaves.sort() |
349 slaves.sort() |
319 return slaves |
350 return slaves |
320 |
351 |
321 def GetSlave(self, slave_pos): |
352 def GetSlave(self, slave_pos): |
322 for slave in self.Config.getConfig().getSlave(): |
353 for slave in self.Config.getConfig().getSlave(): |
323 slave_info = slave.getInfo() |
354 slave_info = slave.getInfo() |
324 if slave_info.getSlavePosition() == slave_pos: |
355 if slave_info.getPhysAddr() == slave_pos: |
325 return slave |
356 return slave |
326 return None |
357 return None |
327 |
358 |
328 def AddSlave(self): |
359 def PlugAddChild(self, PlugName, PlugType, IEC_Channel=0): |
329 slaves = self.GetSlaves() |
360 """ |
330 for PlugInstance in self.IterChilds(): |
361 Create the plugins that may be added as child to this node self |
331 slaves.append(PlugInstance.GetSlavePos()) |
362 @param PlugType: string desining the plugin class name (get name from PlugChildsTypes) |
332 slaves.sort() |
363 @param PlugName: string for the name of the plugin instance |
333 if len(slaves) > 0: |
364 """ |
334 new_pos = (slaves[-1][0] + 1, 0) |
365 newPluginOpj = PlugTemplate.PlugAddChild(self, PlugName, PlugType, IEC_Channel) |
335 else: |
366 |
336 new_pos = (0, 0) |
367 slave = self.GetSlave(newPluginOpj.BaseParams.getIEC_Channel()) |
337 slave = EtherCATConfigClasses["Config_Slave"]() |
368 if slave is None: |
338 slave_infos = slave.getInfo() |
369 slave = EtherCATConfigClasses["Config_Slave"]() |
339 slave_infos.setName("undefined") |
370 slave_infos = slave.getInfo() |
340 slave_infos.setSlavePosition(new_pos[0], new_pos[1]) |
371 slave_infos.setName("undefined") |
341 self.Config.getConfig().appendSlave(slave) |
372 slave_infos.setPhysAddr(newPluginOpj.BaseParams.getIEC_Channel()) |
342 self.BufferConfig() |
373 slave_infos.setAutoIncAddr(0) |
343 return new_pos |
374 self.Config.getConfig().appendSlave(slave) |
344 |
375 self.BufferConfig() |
345 def RemoveSlave(self, slave_pos): |
376 self.OnPlugSave() |
|
377 |
|
378 return newPluginOpj |
|
379 |
|
380 def _doRemoveChild(self, PlugInstance): |
|
381 slave_pos = PlugInstance.GetSlavePos() |
346 config = self.Config.getConfig() |
382 config = self.Config.getConfig() |
347 for idx, slave in enumerate(config.getSlave()): |
383 for idx, slave in enumerate(config.getSlave()): |
348 slave_infos = slave.getInfo() |
384 slave_infos = slave.getInfo() |
349 if slave_infos.getSlavePosition() == slave_pos: |
385 if slave_infos.getPhysAddr() == slave_pos: |
350 config.removeSlave(idx) |
386 config.removeSlave(idx) |
351 self.BufferConfig() |
387 self.BufferConfig() |
352 return True |
388 self.OnPlugSave() |
353 return False |
389 PlugTemplate._doRemoveChild(self, PlugInstance) |
354 |
390 |
355 def SetSlavePos(self, slave_pos, alias=None, position=None): |
391 def SetSlavePosition(self, slave_pos, new_pos): |
356 for PlugInstance in self.IterChilds(): |
|
357 if PlugInstance.BaseParams.getIEC_Channel() == alias: |
|
358 return _("Slave with alias \"%d\" already exists!" % alias) |
|
359 slave = self.GetSlave(slave_pos) |
392 slave = self.GetSlave(slave_pos) |
360 if slave is not None: |
393 if slave is not None: |
361 slave_info = slave.getInfo() |
394 slave_info = slave.getInfo() |
362 new_pos = slave_pos |
395 slave_info.setPhysAddr(new_pos) |
363 if alias is not None: |
|
364 new_pos = (alias, new_pos[1]) |
|
365 if position is not None: |
|
366 new_pos = (new_pos[0], position) |
|
367 if self.GetSlave(new_pos) is not None: |
|
368 return _("Slave with position \"%d:%d\" already exists!" % new_pos) |
|
369 slave_info.setSlavePosition(*new_pos) |
|
370 self.BufferConfig() |
396 self.BufferConfig() |
|
397 |
|
398 def GetSlaveAlias(self, slave_pos): |
|
399 slave = self.GetSlave(slave_pos) |
|
400 if slave is not None: |
|
401 slave_info = slave.getInfo() |
|
402 return slave_info.getAutoIncAddr() |
371 return None |
403 return None |
|
404 |
|
405 def SetSlaveAlias(self, slave_pos, alias): |
|
406 slave = self.GetSlave(slave_pos) |
|
407 if slave is not None: |
|
408 slave_info = slave.getInfo() |
|
409 slave_info.setAutoIncAddr(alias) |
|
410 self.BufferConfig() |
372 |
411 |
373 def GetSlaveType(self, slave_pos): |
412 def GetSlaveType(self, slave_pos): |
374 slave = self.GetSlave(slave_pos) |
413 slave = self.GetSlave(slave_pos) |
375 if slave is not None: |
414 if slave is not None: |
376 return slave.getType() |
415 return slave.getType() |
413 return None |
451 return None |
414 |
452 |
415 def GetModuleInfos(self, type_infos): |
453 def GetModuleInfos(self, type_infos): |
416 return self.PlugParent.GetModuleInfos(type_infos) |
454 return self.PlugParent.GetModuleInfos(type_infos) |
417 |
455 |
418 def GetModulesByProfile(self, profile_type): |
456 def GetSlaveTypesLibrary(self, profile_filter=None): |
419 return self.PlugParent.GetModulesByProfile(profile_type) |
457 return self.PlugParent.GetModulesLibrary(profile_filter) |
420 |
458 |
421 def GetSlaveTypesLibrary(self): |
459 def GetDeviceLocationTree(self, slave_pos, current_location, device_name): |
422 return self.PlugParent.GetModulesLibrary() |
460 slave = self.GetSlave(slave_pos) |
423 |
461 if slave is not None: |
424 def GetDeviceLocationTree(self, current_location, type_infos): |
462 type_infos = slave.getType() |
425 vars = [] |
463 |
426 |
464 vars = [] |
427 device = self.GetModuleInfos(type_infos) |
465 |
428 if device is not None: |
466 device = self.GetModuleInfos(type_infos) |
429 sync_managers = [] |
467 if device is not None: |
430 for sync_manager in device.getSm(): |
468 sync_managers = [] |
431 sync_manager_control_byte = ExtractHexDecValue(sync_manager.getControlByte()) |
469 for sync_manager in device.getSm(): |
432 sync_manager_direction = sync_manager_control_byte & 0x0c |
470 sync_manager_control_byte = ExtractHexDecValue(sync_manager.getControlByte()) |
433 if sync_manager_direction: |
471 sync_manager_direction = sync_manager_control_byte & 0x0c |
434 sync_managers.append(LOCATION_VAR_OUTPUT) |
472 if sync_manager_direction: |
435 else: |
473 sync_managers.append(LOCATION_VAR_OUTPUT) |
436 sync_managers.append(LOCATION_VAR_INPUT) |
474 else: |
437 |
475 sync_managers.append(LOCATION_VAR_INPUT) |
438 entries = device.GetEntriesList().items() |
476 |
439 entries.sort() |
477 entries = device.GetEntriesList().items() |
440 for (index, subindex), entry in entries: |
478 entries.sort() |
441 var_size = self.GetSizeOfType(entry["Type"]) |
479 for (index, subindex), entry in entries: |
442 if var_size is not None: |
480 var_size = self.GetSizeOfType(entry["Type"]) |
443 var_class = VARCLASSCONVERSION.get(entry["PDOMapping"], None) |
481 if var_size is not None: |
444 if var_class is not None: |
482 var_class = VARCLASSCONVERSION.get(entry["PDOMapping"], None) |
445 if var_class == LOCATION_VAR_INPUT: |
483 if var_class is not None: |
446 var_dir = "%I" |
484 if var_class == LOCATION_VAR_INPUT: |
447 else: |
485 var_dir = "%I" |
448 var_dir = "%Q" |
486 else: |
449 |
487 var_dir = "%Q" |
450 vars.append({"name": "0x%4.4x-0x%2.2x: %s" % (index, subindex, entry["Name"]), |
488 |
451 "type": var_class, |
489 vars.append({"name": "0x%4.4x-0x%2.2x: %s" % (index, subindex, entry["Name"]), |
452 "size": var_size, |
490 "type": var_class, |
453 "IEC_type": entry["Type"], |
491 "size": var_size, |
454 "var_name": "%s_%4.4x_%2.2x" % ("_".join(type_infos["device_type"].split()), index, subindex), |
492 "IEC_type": entry["Type"], |
455 "location": "%s%s%s"%(var_dir, var_size, ".".join(map(str, current_location + |
493 "var_name": "%s_%4.4x_%2.2x" % ("_".join(device_name.split()), index, subindex), |
456 (index, subindex)))), |
494 "location": "%s%s%s"%(var_dir, var_size, ".".join(map(str, current_location + |
457 "description": "", |
495 (index, subindex)))), |
458 "children": []}) |
496 "description": "", |
|
497 "children": []}) |
459 |
498 |
460 return vars |
499 return vars |
461 |
500 |
462 def GetVariableLocationTree(self): |
|
463 '''See PlugTemplate.GetVariableLocationTree() for a description.''' |
|
464 |
|
465 current_location = self.GetCurrentLocation() |
|
466 |
|
467 groups = [] |
|
468 for slave_pos in self.GetSlaves(): |
|
469 |
|
470 slave = self.GetSlave(slave_pos) |
|
471 if slave is not None: |
|
472 type_infos = slave.getType() |
|
473 |
|
474 vars = self.GetDeviceLocationTree(current_location + slave_pos, type_infos) |
|
475 if len(vars) > 0: |
|
476 groups.append({"name": "%s (%d,%d)" % ((type_infos["device_type"],) + slave_pos), |
|
477 "type": LOCATION_GROUP, |
|
478 "location": ".".join(map(str, current_location + slave_pos)) + ".x", |
|
479 "children": vars}) |
|
480 |
|
481 return {"name": self.BaseParams.getName(), |
|
482 "type": LOCATION_PLUGIN, |
|
483 "location": self.GetFullIEC_Channel(), |
|
484 "children": groups} |
|
485 |
|
486 PluginMethods = [ |
|
487 {"bitmap" : os.path.join("images", "EditCfile"), |
|
488 "name" : _("Edit Config"), |
|
489 "tooltip" : _("Edit Config"), |
|
490 "method" : "_OpenView"}, |
|
491 ] |
|
492 |
|
493 def PlugTestModified(self): |
501 def PlugTestModified(self): |
494 return self.ChangesToSave or not self.ConfigIsSaved() |
502 return self.ChangesToSave or not self.ConfigIsSaved() |
495 |
503 |
496 def OnPlugSave(self): |
504 def OnPlugSave(self): |
497 filepath = self.ConfigFileName() |
505 filepath = self.ConfigFileName() |
1304 device_group = device.getGroupType() |
1317 device_group = device.getGroupType() |
1305 if not vendor_category["groups"].has_key(device_group): |
1318 if not vendor_category["groups"].has_key(device_group): |
1306 raise ValueError, "Not such group \"%\"" % device_group |
1319 raise ValueError, "Not such group \"%\"" % device_group |
1307 vendor_category["groups"][device_group]["devices"].append((device.getType().getcontent(), device)) |
1320 vendor_category["groups"][device_group]["devices"].append((device.getType().getcontent(), device)) |
1308 |
1321 |
1309 def GetModulesLibrary(self): |
1322 def GetModulesLibrary(self, profile_filter=None): |
1310 library = [] |
1323 library = [] |
1311 children_dict = {} |
1324 children_dict = {} |
1312 for vendor_id, vendor in self.ModulesLibrary.iteritems(): |
1325 for vendor_id, vendor in self.ModulesLibrary.iteritems(): |
1313 groups = [] |
1326 groups = [] |
1314 library.append({"name": vendor["name"], |
|
1315 "type": ETHERCAT_VENDOR, |
|
1316 "children": groups}) |
|
1317 for group_type, group in vendor["groups"].iteritems(): |
1327 for group_type, group in vendor["groups"].iteritems(): |
1318 group_infos = {"name": group["name"], |
1328 group_infos = {"name": group["name"], |
1319 "order": group["order"], |
1329 "order": group["order"], |
1320 "type": ETHERCAT_GROUP, |
1330 "type": ETHERCAT_GROUP, |
|
1331 "infos": None, |
1321 "children": children_dict.setdefault(group_type, [])} |
1332 "children": children_dict.setdefault(group_type, [])} |
1322 if group["parent"] is not None: |
|
1323 parent_children = children_dict.setdefault(group["parent"], []) |
|
1324 parent_children.append(group_infos) |
|
1325 else: |
|
1326 groups.append(group_infos) |
|
1327 device_dict = {} |
1333 device_dict = {} |
1328 for device_type, device in group["devices"]: |
1334 for device_type, device in group["devices"]: |
1329 device_infos = {"name": ExtractName(device.getName()), |
1335 if profile_filter is None or profile_filter in device.GetProfileNumbers(): |
1330 "type": ETHERCAT_DEVICE, |
1336 device_infos = {"name": ExtractName(device.getName()), |
1331 "infos": {"device_type": device_type, |
1337 "type": ETHERCAT_DEVICE, |
1332 "vendor": vendor_id, |
1338 "infos": {"device_type": device_type, |
1333 "product_code": device.getType().getProductCode(), |
1339 "vendor": vendor_id, |
1334 "revision_number": device.getType().getRevisionNo()}} |
1340 "product_code": device.getType().getProductCode(), |
1335 group_infos["children"].append(device_infos) |
1341 "revision_number": device.getType().getRevisionNo()}, |
1336 device_type_occurrences = device_dict.setdefault(device_type, []) |
1342 "children": []} |
1337 device_type_occurrences.append(device_infos) |
1343 group_infos["children"].append(device_infos) |
|
1344 device_type_occurrences = device_dict.setdefault(device_type, []) |
|
1345 device_type_occurrences.append(device_infos) |
1338 for device_type_occurrences in device_dict.itervalues(): |
1346 for device_type_occurrences in device_dict.itervalues(): |
1339 if len(device_type_occurrences) > 1: |
1347 if len(device_type_occurrences) > 1: |
1340 for occurrence in device_type_occurrences: |
1348 for occurrence in device_type_occurrences: |
1341 occurrence["name"] += _(" (rev. %s)") % occurrence["infos"]["revision_number"] |
1349 occurrence["name"] += _(" (rev. %s)") % occurrence["infos"]["revision_number"] |
|
1350 if len(group_infos["children"]) > 0: |
|
1351 if group["parent"] is not None: |
|
1352 parent_children = children_dict.setdefault(group["parent"], []) |
|
1353 parent_children.append(group_infos) |
|
1354 else: |
|
1355 groups.append(group_infos) |
|
1356 if len(groups) > 0: |
|
1357 library.append({"name": vendor["name"], |
|
1358 "type": ETHERCAT_VENDOR, |
|
1359 "infos": None, |
|
1360 "children": groups}) |
1342 library.sort(lambda x, y: cmp(x["name"], y["name"])) |
1361 library.sort(lambda x, y: cmp(x["name"], y["name"])) |
1343 return library |
1362 return library |
1344 |
1363 |
1345 def GetModuleInfos(self, type_infos): |
1364 def GetModuleInfos(self, type_infos): |
1346 vendor = self.ModulesLibrary.get(ExtractHexDecValue(type_infos["vendor"]), None) |
1365 vendor = self.ModulesLibrary.get(ExtractHexDecValue(type_infos["vendor"]), None) |