23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
24 |
24 |
25 from types import * |
25 from types import * |
26 |
26 |
27 # Translation between IEC types and Can Open types |
27 # Translation between IEC types and Can Open types |
28 IECToCOType = {"BOOL":0x01, "SINT":0x02, "INT":0x03,"DINT":0x04,"LINT":0x10, |
28 IECToCOType = { |
29 "USINT":0x05,"UINT":0x06,"UDINT":0x07,"ULINT":0x1B,"REAL":0x08, |
29 "BOOL": 0x01, |
30 "LREAL":0x11,"STRING":0x09,"BYTE":0x05,"WORD":0x06,"DWORD":0x07, |
30 "SINT": 0x02, |
31 "LWORD":0x1B,"WSTRING":0x0B} |
31 "INT": 0x03, |
32 |
32 "DINT": 0x04, |
33 # Constants for PDO types |
33 "LINT": 0x10, |
|
34 "USINT": 0x05, |
|
35 "UINT": 0x06, |
|
36 "UDINT": 0x07, |
|
37 "ULINT": 0x1B, |
|
38 "REAL": 0x08, |
|
39 "LREAL": 0x11, |
|
40 "STRING": 0x09, |
|
41 "BYTE": 0x05, |
|
42 "WORD": 0x06, |
|
43 "DWORD": 0x07, |
|
44 "LWORD": 0x1B, |
|
45 "WSTRING": 0x0B |
|
46 } |
|
47 |
|
48 # Constants for PDO types |
34 RPDO = 1 |
49 RPDO = 1 |
35 TPDO = 2 |
50 TPDO = 2 |
36 |
51 |
37 SlavePDOType = {"I" : TPDO, "Q" : RPDO} |
52 SlavePDOType = {"I": TPDO, "Q": RPDO} |
38 InvertPDOType = {RPDO : TPDO, TPDO : RPDO} |
53 InvertPDOType = {RPDO: TPDO, TPDO: RPDO} |
39 PDOTypeBaseIndex = {RPDO : 0x1400, TPDO : 0x1800} |
54 PDOTypeBaseIndex = {RPDO: 0x1400, TPDO: 0x1800} |
40 PDOTypeBaseCobId = {RPDO : 0x200, TPDO : 0x180} |
55 PDOTypeBaseCobId = {RPDO: 0x200, TPDO: 0x180} |
41 |
56 |
42 VariableIncrement = 0x100 |
57 VariableIncrement = 0x100 |
43 VariableStartIndex = {TPDO : 0x2000, RPDO : 0x4000} |
58 VariableStartIndex = {TPDO: 0x2000, RPDO: 0x4000} |
44 VariableDirText = {TPDO : "__I", RPDO : "__Q"} |
59 VariableDirText = {TPDO: "__I", RPDO: "__Q"} |
45 VariableTypeOffset = dict(zip(["","X","B","W","D","L"], range(6))) |
60 VariableTypeOffset = dict(zip(["", "X", "B", "W", "D", "L"], range(6))) |
46 |
61 |
47 TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)] |
62 TrashVariables = [(1, 0x01), (8, 0x05), (16, 0x06), (32, 0x07), (64, 0x1B)] |
48 |
63 |
49 #------------------------------------------------------------------------------- |
64 # ------------------------------------------------------------------------------- |
50 # Specific exception for PDO mapping errors |
65 # Specific exception for PDO mapping errors |
51 #------------------------------------------------------------------------------- |
66 # ------------------------------------------------------------------------------- |
|
67 |
52 |
68 |
53 class PDOmappingException(Exception): |
69 class PDOmappingException(Exception): |
54 pass |
70 pass |
55 |
71 |
56 |
72 |
150 self.ListCobIDAvailable = range(0x180, 0x580) |
167 self.ListCobIDAvailable = range(0x180, 0x580) |
151 # Dictionary of mapping value where unexpected variables are stored |
168 # Dictionary of mapping value where unexpected variables are stored |
152 self.TrashVariables = {} |
169 self.TrashVariables = {} |
153 # Dictionary of pointed variables |
170 # Dictionary of pointed variables |
154 self.PointedVariables = {} |
171 self.PointedVariables = {} |
155 |
172 |
156 self.NodeList = nodelist |
173 self.NodeList = nodelist |
157 self.Manager = self.NodeList.Manager |
174 self.Manager = self.NodeList.Manager |
158 self.MasterNode = self.Manager.GetCurrentNodeCopy() |
175 self.MasterNode = self.Manager.GetCurrentNodeCopy() |
159 self.MasterNode.SetNodeName(nodename) |
176 self.MasterNode.SetNodeName(nodename) |
160 self.PrepareMasterNode() |
177 self.PrepareMasterNode() |
161 |
178 |
162 def GetPointedVariables(self): |
179 def GetPointedVariables(self): |
163 return self.PointedVariables |
180 return self.PointedVariables |
164 |
181 |
165 def RemoveUsedNodeCobId(self, node): |
182 def RemoveUsedNodeCobId(self, node): |
166 """ |
183 """ |
167 Remove all PDO COB ID used by the given node from the list of available COB ID |
184 Remove all PDO COB ID used by the given node from the list of available COB ID |
168 @param node: node |
185 @param node: node |
169 @return: a tuple of number of RPDO and TPDO for the node |
186 @return: a tuple of number of RPDO and TPDO for the node |
170 """ |
187 """ |
171 |
188 |
172 # Get list of all node TPDO and RPDO indexes |
189 # Get list of all node TPDO and RPDO indexes |
173 nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True) |
190 nodeRpdoIndexes = GetNodePDOIndexes(node, RPDO, True) |
174 nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True) |
191 nodeTpdoIndexes = GetNodePDOIndexes(node, TPDO, True) |
175 |
192 |
176 # Mark all the COB ID of the node already mapped PDO as not available |
193 # Mark all the COB ID of the node already mapped PDO as not available |
177 for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes: |
194 for PdoIdx in nodeRpdoIndexes + nodeTpdoIndexes: |
178 pdo_cobid = node.GetEntry(PdoIdx, 0x01) |
195 pdo_cobid = node.GetEntry(PdoIdx, 0x01) |
179 # Extract COB ID, if PDO isn't active |
196 # Extract COB ID, if PDO isn't active |
180 if pdo_cobid > 0x600 : |
197 if pdo_cobid > 0x600: |
181 pdo_cobid -= 0x80000000 |
198 pdo_cobid -= 0x80000000 |
182 # Remove COB ID from the list of available COB ID |
199 # Remove COB ID from the list of available COB ID |
183 if pdo_cobid in self.ListCobIDAvailable: |
200 if pdo_cobid in self.ListCobIDAvailable: |
184 self.ListCobIDAvailable.remove(pdo_cobid) |
201 self.ListCobIDAvailable.remove(pdo_cobid) |
185 |
202 |
186 return len(nodeRpdoIndexes), len(nodeTpdoIndexes) |
203 return len(nodeRpdoIndexes), len(nodeTpdoIndexes) |
187 |
204 |
188 |
|
189 def PrepareMasterNode(self): |
205 def PrepareMasterNode(self): |
190 """ |
206 """ |
191 Add mandatory entries for DCF generation into MasterNode. |
207 Add mandatory entries for DCF generation into MasterNode. |
192 """ |
208 """ |
193 |
209 |
194 # Adding DCF entry into Master node |
210 # Adding DCF entry into Master node |
195 if not self.MasterNode.IsEntry(0x1F22): |
211 if not self.MasterNode.IsEntry(0x1F22): |
196 self.MasterNode.AddEntry(0x1F22, 1, "") |
212 self.MasterNode.AddEntry(0x1F22, 1, "") |
197 self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode) |
213 self.Manager.AddSubentriesToCurrent(0x1F22, 127, self.MasterNode) |
198 |
214 |
199 # Adding trash mappable variables for unused mapped datas |
215 # Adding trash mappable variables for unused mapped datas |
200 idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID() |
216 idxTrashVariables = 0x2000 + self.MasterNode.GetNodeID() |
201 # Add an entry for storing unexpected all variable |
217 # Add an entry for storing unexpected all variable |
202 self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode) |
218 self.Manager.AddMapVariableToCurrent(idxTrashVariables, self.MasterNode.GetNodeName()+"_trashvariables", 3, len(TrashVariables), self.MasterNode) |
203 for subidx, (size, typeidx) in enumerate(TrashVariables): |
219 for subidx, (size, typeidx) in enumerate(TrashVariables): |
204 # Add a subentry for storing unexpected variable of this size |
220 # Add a subentry for storing unexpected variable of this size |
205 self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode) |
221 self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, "TRASH%d" % size, "name", None, self.MasterNode) |
206 self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode) |
222 self.Manager.SetCurrentEntry(idxTrashVariables, subidx + 1, typeidx, "type", None, self.MasterNode) |
207 # Store the mapping value for this entry |
223 # Store the mapping value for this entry |
208 self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size |
224 self.TrashVariables[size] = (idxTrashVariables << 16) + ((subidx + 1) << 8) + size |
209 |
225 |
210 RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode) |
226 RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(self.MasterNode) |
211 |
227 |
212 # Store the indexes of the first RPDO and TPDO available for MasterNode |
228 # Store the indexes of the first RPDO and TPDO available for MasterNode |
213 self.CurrentPDOParamsIdx = {RPDO : 0x1400 + RPDOnumber, TPDO : 0x1800 + TPDOnumber} |
229 self.CurrentPDOParamsIdx = {RPDO: 0x1400 + RPDOnumber, TPDO: 0x1800 + TPDOnumber} |
214 |
230 |
215 # Prepare MasterNode with all nodelist slaves |
231 # Prepare MasterNode with all nodelist slaves |
216 for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()): |
232 for idx, (nodeid, nodeinfos) in enumerate(self.NodeList.SlaveNodes.items()): |
217 node = nodeinfos["Node"] |
233 node = nodeinfos["Node"] |
218 node.SetNodeID(nodeid) |
234 node.SetNodeID(nodeid) |
219 |
235 |
220 RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node) |
236 RPDOnumber, TPDOnumber = self.RemoveUsedNodeCobId(node) |
221 |
237 |
222 # Get Slave's default SDO server parameters |
238 # Get Slave's default SDO server parameters |
223 RSDO_cobid = node.GetEntry(0x1200,0x01) |
239 RSDO_cobid = node.GetEntry(0x1200, 0x01) |
224 if not RSDO_cobid: |
240 if not RSDO_cobid: |
225 RSDO_cobid = 0x600 + nodeid |
241 RSDO_cobid = 0x600 + nodeid |
226 TSDO_cobid = node.GetEntry(0x1200,0x02) |
242 TSDO_cobid = node.GetEntry(0x1200, 0x02) |
227 if not TSDO_cobid: |
243 if not TSDO_cobid: |
228 TSDO_cobid = 0x580 + nodeid |
244 TSDO_cobid = 0x580 + nodeid |
229 |
245 |
230 # Configure Master's SDO parameters entries |
246 # Configure Master's SDO parameters entries |
231 self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode) |
247 self.Manager.ManageEntriesOfCurrent([0x1280 + idx], [], self.MasterNode) |
232 self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid) |
248 self.MasterNode.SetEntry(0x1280 + idx, 0x01, RSDO_cobid) |
233 self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid) |
249 self.MasterNode.SetEntry(0x1280 + idx, 0x02, TSDO_cobid) |
234 self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid) |
250 self.MasterNode.SetEntry(0x1280 + idx, 0x03, nodeid) |
235 |
251 |
236 |
|
237 def GetMasterNode(self): |
252 def GetMasterNode(self): |
238 """ |
253 """ |
239 Return MasterNode. |
254 Return MasterNode. |
240 """ |
255 """ |
241 return self.MasterNode |
256 return self.MasterNode |
242 |
257 |
243 def AddParamsToDCF(self, nodeid, data, nbparams): |
258 def AddParamsToDCF(self, nodeid, data, nbparams): |
244 """ |
259 """ |
245 Add entry to DCF, for the requested nodeID |
260 Add entry to DCF, for the requested nodeID |
246 @param nodeid: id of the slave (int) |
261 @param nodeid: id of the slave (int) |
247 @param data: data to add to slave DCF (string) |
262 @param data: data to add to slave DCF (string) |
248 @param nbparams: number of params added to slave DCF (int) |
263 @param nbparams: number of params added to slave DCF (int) |
249 """ |
264 """ |
250 # Get current DCF for slave |
265 # Get current DCF for slave |
251 nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid) |
266 nodeDCF = self.MasterNode.GetEntry(0x1F22, nodeid) |
252 |
267 |
253 # Extract data and number of params in current DCF |
268 # Extract data and number of params in current DCF |
254 if nodeDCF != None and nodeDCF != '': |
269 if nodeDCF is not None and nodeDCF != '': |
255 tmpnbparams = [i for i in nodeDCF[:4]] |
270 tmpnbparams = [i for i in nodeDCF[:4]] |
256 tmpnbparams.reverse() |
271 tmpnbparams.reverse() |
257 nbparams += int(''.join(["%2.2x"%ord(i) for i in tmpnbparams]), 16) |
272 nbparams += int(''.join(["%2.2x" % ord(i) for i in tmpnbparams]), 16) |
258 data = nodeDCF[4:] + data |
273 data = nodeDCF[4:] + data |
259 |
274 |
260 # Build new DCF |
275 # Build new DCF |
261 dcf = LE_to_BE(nbparams, 0x04) + data |
276 dcf = LE_to_BE(nbparams, 0x04) + data |
262 # Set new DCF for slave |
277 # Set new DCF for slave |
263 self.MasterNode.SetEntry(0x1F22, nodeid, dcf) |
278 self.MasterNode.SetEntry(0x1F22, nodeid, dcf) |
264 |
279 |
265 def GetEmptyPDO(self, nodeid, pdotype, start_index=None): |
280 def GetEmptyPDO(self, nodeid, pdotype, start_index=None): |
266 """ |
281 """ |
267 Search a not configured PDO for a slave |
282 Search a not configured PDO for a slave |
268 @param node: the slave node object |
283 @param node: the slave node object |
269 @param pdotype: type of PDO to generated (RPDO or TPDO) |
284 @param pdotype: type of PDO to generated (RPDO or TPDO) |
294 if cobid not in self.ListCobIDAvailable: |
309 if cobid not in self.ListCobIDAvailable: |
295 cobid = self.ListCobIDAvailable.pop(0) |
310 cobid = self.ListCobIDAvailable.pop(0) |
296 return index, cobid, values[0] |
311 return index, cobid, values[0] |
297 index += 1 |
312 index += 1 |
298 return None |
313 return None |
299 |
314 |
300 def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs): |
315 def AddPDOMapping(self, nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs): |
301 """ |
316 """ |
302 Record a new mapping request for a slave, and add related slave config to the DCF |
317 Record a new mapping request for a slave, and add related slave config to the DCF |
303 @param nodeid: id of the slave (int) |
318 @param nodeid: id of the slave (int) |
304 @param pdotype: type of PDO to generated (RPDO or TPDO) |
319 @param pdotype: type of PDO to generated (RPDO or TPDO) |
305 @param pdomapping: list od variables to map with PDO |
320 @param pdomapping: list od variables to map with PDO |
306 """ |
321 """ |
307 # Add an entry to MasterMapping |
322 # Add an entry to MasterMapping |
308 self.MasterMapping[pdocobid] = {"type" : InvertPDOType[pdotype], |
323 self.MasterMapping[pdocobid] = { |
309 "mapping" : [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping]} |
324 "type": InvertPDOType[pdotype], |
310 |
325 "mapping": [None] + [(loc_infos["type"], name) for name, loc_infos in pdomapping] |
|
326 } |
|
327 |
311 # Return the data to add to DCF |
328 # Return the data to add to DCF |
312 if sync_TPDOs: |
329 if sync_TPDOs: |
313 return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping) |
330 return GeneratePDOMappingDCF(pdoindex, pdocobid, 0x01, pdomapping) |
314 else: |
331 else: |
315 return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping) |
332 return GeneratePDOMappingDCF(pdoindex, pdocobid, 0xFF, pdomapping) |
316 return 0, "" |
333 return 0, "" |
317 |
334 |
318 def GenerateDCF(self, locations, current_location, sync_TPDOs): |
335 def GenerateDCF(self, locations, current_location, sync_TPDOs): |
319 """ |
336 """ |
320 Generate Concise DCF of MasterNode for the locations list given |
337 Generate Concise DCF of MasterNode for the locations list given |
321 @param locations: list of locations to be mapped |
338 @param locations: list of locations to be mapped |
322 @param current_location: tuple of the located prefixes not to be considered |
339 @param current_location: tuple of the located prefixes not to be considered |
323 @param sync_TPDOs: indicate if TPDO must be synchronous |
340 @param sync_TPDOs: indicate if TPDO must be synchronous |
324 """ |
341 """ |
325 |
342 |
326 #------------------------------------------------------------------------------- |
343 # ------------------------------------------------------------------------------- |
327 # Verify that locations correspond to real slave variables |
344 # Verify that locations correspond to real slave variables |
328 #------------------------------------------------------------------------------- |
345 # ------------------------------------------------------------------------------- |
329 |
346 |
330 # Get list of locations check if exists and mappables -> put them in IECLocations |
347 # Get list of locations check if exists and mappables -> put them in IECLocations |
331 for location in locations: |
348 for location in locations: |
332 COlocationtype = IECToCOType[location["IEC_TYPE"]] |
349 COlocationtype = IECToCOType[location["IEC_TYPE"]] |
333 name = location["NAME"] |
350 name = location["NAME"] |
334 if name in self.IECLocations: |
351 if name in self.IECLocations: |
335 if self.IECLocations[name]["type"] != COlocationtype: |
352 if self.IECLocations[name]["type"] != COlocationtype: |
336 raise PDOmappingException, _("Type conflict for location \"%s\"") % name |
353 raise PDOmappingException(_("Type conflict for location \"%s\"") % name) |
337 else: |
354 else: |
338 # Get only the part of the location that concern this node |
355 # Get only the part of the location that concern this node |
339 loc = location["LOC"][len(current_location):] |
356 loc = location["LOC"][len(current_location):] |
340 # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) |
357 # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) |
341 if len(loc) not in (2, 3, 4): |
358 if len(loc) not in (2, 3, 4): |
342 raise PDOmappingException, _("Bad location size : %s") % str(loc) |
359 raise PDOmappingException(_("Bad location size : %s") % str(loc)) |
343 elif len(loc) == 2: |
360 elif len(loc) == 2: |
344 continue |
361 continue |
345 |
362 |
346 direction = location["DIR"] |
363 direction = location["DIR"] |
347 |
364 |
348 sizelocation = location["SIZE"] |
365 sizelocation = location["SIZE"] |
349 |
366 |
350 # Extract and check nodeid |
367 # Extract and check nodeid |
351 nodeid, index, subindex = loc[:3] |
368 nodeid, index, subindex = loc[:3] |
352 |
369 |
353 # Check Id is in slave node list |
370 # Check Id is in slave node list |
354 if nodeid not in self.NodeList.SlaveNodes.keys(): |
371 if nodeid not in self.NodeList.SlaveNodes.keys(): |
355 raise PDOmappingException, _("Non existing node ID : {a1} (variable {a2})").format(a1 = nodeid, a2 = name) |
372 raise PDOmappingException( |
356 |
373 _("Non existing node ID : {a1} (variable {a2})"). |
|
374 format(a1=nodeid, a2=name)) |
|
375 |
357 # Get the model for this node (made from EDS) |
376 # Get the model for this node (made from EDS) |
358 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
377 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
359 |
378 |
360 # Extract and check index and subindex |
379 # Extract and check index and subindex |
361 if not node.IsEntry(index, subindex): |
380 if not node.IsEntry(index, subindex): |
362 msg = _("No such index/subindex ({a1},{a2}) in ID : {a3} (variable {a4})").\ |
381 msg = _("No such index/subindex ({a1},{a2}) in ID : {a3} (variable {a4})").\ |
363 format(a1 = "%x" % index, a2 ="%x" % subindex, a3 = nodeid, a4 = name) |
382 format(a1="%x" % index, a2="%x" % subindex, a3=nodeid, a4=name) |
364 raise PDOmappingException, msg |
383 raise PDOmappingException(msg) |
365 |
384 |
366 # Get the entry info |
385 # Get the entry info |
367 subentry_infos = node.GetSubentryInfos(index, subindex) |
386 subentry_infos = node.GetSubentryInfos(index, subindex) |
368 |
387 |
369 # If a PDO mappable |
388 # If a PDO mappable |
370 if subentry_infos and subentry_infos["pdo"]: |
389 if subentry_infos and subentry_infos["pdo"]: |
371 if sizelocation == "X" and len(loc) > 3: |
390 if sizelocation == "X" and len(loc) > 3: |
372 numbit = loc[3] |
391 numbit = loc[3] |
373 elif sizelocation != "X" and len(loc) > 3: |
392 elif sizelocation != "X" and len(loc) > 3: |
374 msg = _("Cannot set bit offset for non bool '{a1}' variable (ID:{a2},Idx:{a3},sIdx:{a4}))").\ |
393 raise PDOmappingException( |
375 format(a1 = name, a2 = nodeid, a3 = "%x" % index, a4 = "%x" % subindex) |
394 _("Cannot set bit offset for non bool '{a1}' variable (ID:{a2},Idx:{a3},sIdx:{a4}))"). |
376 raise PDOmappingException, msg |
395 format(a1=name, a2=nodeid, a3="%x" % index, a4="%x" % subindex)) |
377 else: |
396 else: |
378 numbit = None |
397 numbit = None |
379 |
398 |
380 if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype: |
399 if location["IEC_TYPE"] != "BOOL" and subentry_infos["type"] != COlocationtype: |
381 raise PDOmappingException, _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\"").\ |
400 raise PDOmappingException( |
382 format(a1 = location["IEC_TYPE"], a2 = COlocationtype, a3 = subentry_infos["type"] , a4 = name) |
401 _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\""). |
383 |
402 format(a1=location["IEC_TYPE"], |
|
403 a2=COlocationtype, |
|
404 a3=subentry_infos["type"], |
|
405 a4=name)) |
|
406 |
384 typeinfos = node.GetEntryInfos(COlocationtype) |
407 typeinfos = node.GetEntryInfos(COlocationtype) |
385 self.IECLocations[name] = {"type":COlocationtype, "pdotype":SlavePDOType[direction], |
408 self.IECLocations[name] = { |
386 "nodeid": nodeid, "index": index,"subindex": subindex, |
409 "type": COlocationtype, |
387 "bit": numbit, "size": typeinfos["size"], "sizelocation": sizelocation} |
410 "pdotype": SlavePDOType[direction], |
|
411 "nodeid": nodeid, |
|
412 "index": index, |
|
413 "subindex": subindex, |
|
414 "bit": numbit, |
|
415 "size": typeinfos["size"], |
|
416 "sizelocation": sizelocation |
|
417 } |
388 else: |
418 else: |
389 raise PDOmappingException, _("Not PDO mappable variable : '{a1}' (ID:{a2},Idx:{a3},sIdx:{a4}))").\ |
419 raise PDOmappingException( |
390 format(a1 = name, a2 = nodeid, a3 = "%x" % index, a4 = "%x" % subindex) |
420 _("Not PDO mappable variable : '{a1}' (ID:{a2},Idx:{a3},sIdx:{a4}))"). |
391 |
421 format(a1=name, a2=nodeid, a3="%x" % index, a4="%x" % subindex)) |
392 #------------------------------------------------------------------------------- |
422 |
|
423 # ------------------------------------------------------------------------------- |
393 # Search for locations already mapped |
424 # Search for locations already mapped |
394 #------------------------------------------------------------------------------- |
425 # ------------------------------------------------------------------------------- |
395 |
426 |
396 for name, locationinfos in self.IECLocations.items(): |
427 for name, locationinfos in self.IECLocations.items(): |
397 node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"] |
428 node = self.NodeList.SlaveNodes[locationinfos["nodeid"]]["Node"] |
398 |
429 |
399 # Search if slave has a PDO mapping this locations |
430 # Search if slave has a PDO mapping this locations |
400 result = SearchNodePDOMapping(locationinfos, node) |
431 result = SearchNodePDOMapping(locationinfos, node) |
401 if result != None: |
432 if result is not None: |
402 index, subindex = result |
433 index, subindex = result |
403 # Get COB ID of the PDO |
434 # Get COB ID of the PDO |
404 cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1) |
435 cobid = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 1) |
405 |
436 |
406 # Add PDO to MasterMapping |
437 # Add PDO to MasterMapping |
407 if cobid not in self.MasterMapping.keys(): |
438 if cobid not in self.MasterMapping.keys(): |
408 # Verify that PDO transmit type is conform to sync_TPDOs |
439 # Verify that PDO transmit type is conform to sync_TPDOs |
409 transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2) |
440 transmittype = self.NodeList.GetSlaveNodeEntry(locationinfos["nodeid"], index - 0x200, 2) |
410 if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF: |
441 if sync_TPDOs and transmittype != 0x01 or transmittype != 0xFF: |
412 # Change TransmitType to SYNCHRONE |
443 # Change TransmitType to SYNCHRONE |
413 data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, []) |
444 data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0x01, []) |
414 else: |
445 else: |
415 # Change TransmitType to ASYCHRONE |
446 # Change TransmitType to ASYCHRONE |
416 data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, []) |
447 data, nbparams = GeneratePDOMappingDCF(index - 0x200, cobid, 0xFF, []) |
417 |
448 |
418 # Add entry to slave dcf to change transmit type of |
449 # Add entry to slave dcf to change transmit type of |
419 self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams) |
450 self.AddParamsToDCF(locationinfos["nodeid"], data, nbparams) |
420 |
451 |
421 mapping = [None] |
452 mapping = [None] |
422 values = node.GetEntry(index) |
453 values = node.GetEntry(index) |
423 # Store the size of each entry mapped in PDO |
454 # Store the size of each entry mapped in PDO |
424 for value in values[1:]: |
455 for value in values[1:]: |
425 if value != 0: |
456 if value != 0: |
426 mapping.append(value % 0x100) |
457 mapping.append(value % 0x100) |
427 self.MasterMapping[cobid] = {"type" : InvertPDOType[locationinfos["pdotype"]], "mapping" : mapping} |
458 self.MasterMapping[cobid] = {"type": InvertPDOType[locationinfos["pdotype"]], "mapping": mapping} |
428 |
459 |
429 # Indicate that this PDO entry must be saved |
460 # Indicate that this PDO entry must be saved |
430 if locationinfos["bit"] is not None: |
461 if locationinfos["bit"] is not None: |
431 if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType): |
462 if not isinstance(self.MasterMapping[cobid]["mapping"][subindex], ListType): |
432 self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex] |
463 self.MasterMapping[cobid]["mapping"][subindex] = [1] * self.MasterMapping[cobid]["mapping"][subindex] |
433 if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]): |
464 if locationinfos["bit"] < len(self.MasterMapping[cobid]["mapping"][subindex]): |
434 self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name) |
465 self.MasterMapping[cobid]["mapping"][subindex][locationinfos["bit"]] = (locationinfos["type"], name) |
435 else: |
466 else: |
436 self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name) |
467 self.MasterMapping[cobid]["mapping"][subindex] = (locationinfos["type"], name) |
437 |
468 |
438 else: |
469 else: |
439 # Add location to those that haven't been mapped yet |
470 # Add location to those that haven't been mapped yet |
440 if locationinfos["nodeid"] not in self.LocationsNotMapped.keys(): |
471 if locationinfos["nodeid"] not in self.LocationsNotMapped.keys(): |
441 self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO : [], RPDO : []} |
472 self.LocationsNotMapped[locationinfos["nodeid"]] = {TPDO: [], RPDO: []} |
442 self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos)) |
473 self.LocationsNotMapped[locationinfos["nodeid"]][locationinfos["pdotype"]].append((name, locationinfos)) |
443 |
474 |
444 #------------------------------------------------------------------------------- |
475 # ------------------------------------------------------------------------------- |
445 # Build concise DCF for the others locations |
476 # Build concise DCF for the others locations |
446 #------------------------------------------------------------------------------- |
477 # ------------------------------------------------------------------------------- |
447 |
478 |
448 for nodeid, locations in self.LocationsNotMapped.items(): |
479 for nodeid, locations in self.LocationsNotMapped.items(): |
449 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
480 node = self.NodeList.SlaveNodes[nodeid]["Node"] |
450 |
481 |
451 # Initialize number of params and data to add to node DCF |
482 # Initialize number of params and data to add to node DCF |
452 nbparams = 0 |
483 nbparams = 0 |
453 dataparams = "" |
484 dataparams = "" |
454 |
485 |
455 # Generate the best PDO mapping for each type of PDO |
486 # Generate the best PDO mapping for each type of PDO |
456 for pdotype in (TPDO, RPDO): |
487 for pdotype in (TPDO, RPDO): |
457 if len(locations[pdotype]) > 0: |
488 if len(locations[pdotype]) > 0: |
458 pdosize = 0 |
489 pdosize = 0 |
459 pdomapping = [] |
490 pdomapping = [] |
460 result = self.GetEmptyPDO(nodeid, pdotype) |
491 result = self.GetEmptyPDO(nodeid, pdotype) |
461 if result is None: |
492 if result is None: |
462 raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid |
493 raise PDOmappingException( |
|
494 _("Unable to define PDO mapping for node %02x") % nodeid) |
463 pdoindex, pdocobid, pdonbparams = result |
495 pdoindex, pdocobid, pdonbparams = result |
464 for name, loc_infos in locations[pdotype]: |
496 for name, loc_infos in locations[pdotype]: |
465 pdosize += loc_infos["size"] |
497 pdosize += loc_infos["size"] |
466 # If pdo's size > 64 bits |
498 # If pdo's size > 64 bits |
467 if pdosize > 64 or len(pdomapping) >= pdonbparams: |
499 if pdosize > 64 or len(pdomapping) >= pdonbparams: |
471 nbparams += nbaddedparams |
503 nbparams += nbaddedparams |
472 pdosize = loc_infos["size"] |
504 pdosize = loc_infos["size"] |
473 pdomapping = [(name, loc_infos)] |
505 pdomapping = [(name, loc_infos)] |
474 result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1) |
506 result = self.GetEmptyPDO(nodeid, pdotype, pdoindex + 1) |
475 if result is None: |
507 if result is None: |
476 raise PDOmappingException, _("Unable to define PDO mapping for node %02x") % nodeid |
508 raise PDOmappingException( |
|
509 _("Unable to define PDO mapping for node %02x") % nodeid) |
477 pdoindex, pdocobid, pdonbparams = result |
510 pdoindex, pdocobid, pdonbparams = result |
478 else: |
511 else: |
479 pdomapping.append((name, loc_infos)) |
512 pdomapping.append((name, loc_infos)) |
480 # If there isn't locations yet but there is still a PDO to generate |
513 # If there isn't locations yet but there is still a PDO to generate |
481 if len(pdomapping) > 0: |
514 if len(pdomapping) > 0: |
482 # Generate a new PDO Mapping |
515 # Generate a new PDO Mapping |
483 data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs) |
516 data, nbaddedparams = self.AddPDOMapping(nodeid, pdotype, pdoindex, pdocobid, pdomapping, sync_TPDOs) |
484 dataparams += data |
517 dataparams += data |
485 nbparams += nbaddedparams |
518 nbparams += nbaddedparams |
486 |
519 |
487 # Add number of params and data to node DCF |
520 # Add number of params and data to node DCF |
488 self.AddParamsToDCF(nodeid, dataparams, nbparams) |
521 self.AddParamsToDCF(nodeid, dataparams, nbparams) |
489 |
522 |
490 #------------------------------------------------------------------------------- |
523 # ------------------------------------------------------------------------------- |
491 # Master Node Configuration |
524 # Master Node Configuration |
492 #------------------------------------------------------------------------------- |
525 # ------------------------------------------------------------------------------- |
493 |
526 |
494 # Generate Master's Configuration from informations stored in MasterMapping |
527 # Generate Master's Configuration from informations stored in MasterMapping |
495 for cobid, pdo_infos in self.MasterMapping.items(): |
528 for cobid, pdo_infos in self.MasterMapping.items(): |
496 # Get next PDO index in MasterNode for this PDO type |
529 # Get next PDO index in MasterNode for this PDO type |
497 current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]] |
530 current_idx = self.CurrentPDOParamsIdx[pdo_infos["type"]] |
498 |
531 |
499 # Search if there is already a PDO in MasterNode with this cob id |
532 # Search if there is already a PDO in MasterNode with this cob id |
500 for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True): |
533 for idx in GetNodePDOIndexes(self.MasterNode, pdo_infos["type"], True): |
501 if self.MasterNode.GetEntry(idx, 1) == cobid: |
534 if self.MasterNode.GetEntry(idx, 1) == cobid: |
502 current_idx = idx |
535 current_idx = idx |
503 |
536 |
504 # Add a PDO to MasterNode if not PDO have been found |
537 # Add a PDO to MasterNode if not PDO have been found |
505 if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]: |
538 if current_idx == self.CurrentPDOParamsIdx[pdo_infos["type"]]: |
506 addinglist = [current_idx, current_idx + 0x200] |
539 addinglist = [current_idx, current_idx + 0x200] |
507 self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode) |
540 self.Manager.ManageEntriesOfCurrent(addinglist, [], self.MasterNode) |
508 self.MasterNode.SetEntry(current_idx, 0x01, cobid) |
541 self.MasterNode.SetEntry(current_idx, 0x01, cobid) |
509 |
542 |
510 # Increment the number of PDO for this PDO type |
543 # Increment the number of PDO for this PDO type |
511 self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1 |
544 self.CurrentPDOParamsIdx[pdo_infos["type"]] += 1 |
512 |
545 |
513 # Change the transmit type of the PDO |
546 # Change the transmit type of the PDO |
514 if sync_TPDOs: |
547 if sync_TPDOs: |
515 self.MasterNode.SetEntry(current_idx, 0x02, 0x01) |
548 self.MasterNode.SetEntry(current_idx, 0x02, 0x01) |
516 else: |
549 else: |
517 self.MasterNode.SetEntry(current_idx, 0x02, 0xFF) |
550 self.MasterNode.SetEntry(current_idx, 0x02, 0xFF) |
518 |
551 |
519 mapping = [] |
552 mapping = [] |
520 for item in pdo_infos["mapping"]: |
553 for item in pdo_infos["mapping"]: |
521 if isinstance(item, ListType): |
554 if isinstance(item, ListType): |
522 mapping.extend(item) |
555 mapping.extend(item) |
523 else: |
556 else: |
524 mapping.append(item) |
557 mapping.append(item) |
525 |
558 |
526 # Add some subentries to PDO mapping if there is not enough |
559 # Add some subentries to PDO mapping if there is not enough |
527 if len(mapping) > 1: |
560 if len(mapping) > 1: |
528 self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode) |
561 self.Manager.AddSubentriesToCurrent(current_idx + 0x200, len(mapping) - 1, self.MasterNode) |
529 |
562 |
530 # Generate MasterNode's PDO mapping |
563 # Generate MasterNode's PDO mapping |
531 for subindex, variable in enumerate(mapping): |
564 for subindex, variable in enumerate(mapping): |
532 if subindex == 0: |
565 if subindex == 0: |
533 continue |
566 continue |
534 new_index = False |
567 new_index = False |
535 |
568 |
536 if isinstance(variable, (IntType, LongType)): |
569 if isinstance(variable, (IntType, LongType)): |
537 # If variable is an integer then variable is unexpected |
570 # If variable is an integer then variable is unexpected |
538 self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable]) |
571 self.MasterNode.SetEntry(current_idx + 0x200, subindex, self.TrashVariables[variable]) |
539 else: |
572 else: |
540 typeidx, varname = variable |
573 typeidx, varname = variable |
541 variable_infos = self.IECLocations[varname] |
574 variable_infos = self.IECLocations[varname] |
542 |
575 |
543 # Calculate base index for storing variable |
576 # Calculate base index for storing variable |
544 mapvariableidx = VariableStartIndex[variable_infos["pdotype"]] + \ |
577 mapvariableidx = \ |
545 VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \ |
578 VariableStartIndex[variable_infos["pdotype"]] + \ |
546 variable_infos["nodeid"] |
579 VariableTypeOffset[variable_infos["sizelocation"]] * VariableIncrement + \ |
547 |
580 variable_infos["nodeid"] |
|
581 |
548 # Generate entry name |
582 # Generate entry name |
549 indexname = "%s%s%s_%d"%(VariableDirText[variable_infos["pdotype"]], |
583 indexname = "%s%s%s_%d" % (VariableDirText[variable_infos["pdotype"]], |
550 variable_infos["sizelocation"], |
584 variable_infos["sizelocation"], |
551 '_'.join(map(str,current_location)), |
585 '_'.join(map(str, current_location)), |
552 variable_infos["nodeid"]) |
586 variable_infos["nodeid"]) |
553 |
587 |
554 # Search for an entry that has an empty subindex |
588 # Search for an entry that has an empty subindex |
555 while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000: |
589 while mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000: |
556 # Entry doesn't exist |
590 # Entry doesn't exist |
557 if not self.MasterNode.IsEntry(mapvariableidx): |
591 if not self.MasterNode.IsEntry(mapvariableidx): |
558 # Add entry to MasterNode |
592 # Add entry to MasterNode |
559 self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode) |
593 self.Manager.AddMapVariableToCurrent(mapvariableidx, "beremiz"+indexname, 3, 1, self.MasterNode) |
560 new_index = True |
594 new_index = True |
561 nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00) |
595 nbsubentries = self.MasterNode.GetEntry(mapvariableidx, 0x00) |
562 else: |
596 else: |
565 # if entry is full, go to next entry possible or stop now |
599 # if entry is full, go to next entry possible or stop now |
566 if nbsubentries == 0xFF: |
600 if nbsubentries == 0xFF: |
567 mapvariableidx += 8 * VariableIncrement |
601 mapvariableidx += 8 * VariableIncrement |
568 else: |
602 else: |
569 break |
603 break |
570 |
604 |
571 # Verify that a not full entry has been found |
605 # Verify that a not full entry has been found |
572 if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000: |
606 if mapvariableidx < VariableStartIndex[variable_infos["pdotype"]] + 0x2000: |
573 # Generate subentry name |
607 # Generate subentry name |
574 if variable_infos["bit"] != None: |
608 if variable_infos["bit"] is not None: |
575 subindexname = "%(index)d_%(subindex)d_%(bit)d"%variable_infos |
609 subindexname = "%(index)d_%(subindex)d_%(bit)d" % variable_infos |
576 else: |
610 else: |
577 subindexname = "%(index)d_%(subindex)d"%variable_infos |
611 subindexname = "%(index)d_%(subindex)d" % variable_infos |
578 # If entry have just been created, no subentry have to be added |
612 # If entry have just been created, no subentry have to be added |
579 if not new_index: |
613 if not new_index: |
580 self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode) |
614 self.Manager.AddSubentriesToCurrent(mapvariableidx, 1, self.MasterNode) |
581 nbsubentries += 1 |
615 nbsubentries += 1 |
582 # Add informations to the new subentry created |
616 # Add informations to the new subentry created |
583 self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"name" : subindexname}) |
617 self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values={"name": subindexname}) |
584 self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values = {"type" : typeidx}) |
618 self.MasterNode.SetMappingEntry(mapvariableidx, nbsubentries, values={"type": typeidx}) |
585 |
619 |
586 # Set value of the PDO mapping |
620 # Set value of the PDO mapping |
587 typeinfos = self.Manager.GetEntryInfos(typeidx) |
621 typeinfos = self.Manager.GetEntryInfos(typeidx) |
588 if typeinfos != None: |
622 if typeinfos is not None: |
589 value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"] |
623 value = (mapvariableidx << 16) + ((nbsubentries) << 8) + typeinfos["size"] |
590 self.MasterNode.SetEntry(current_idx + 0x200, subindex, value) |
624 self.MasterNode.SetEntry(current_idx + 0x200, subindex, value) |
591 |
625 |
592 # Add variable to pointed variables |
626 # Add variable to pointed variables |
593 self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s"%(indexname, subindexname) |
627 self.PointedVariables[(mapvariableidx, nbsubentries)] = "%s_%s" % (indexname, subindexname) |
|
628 |
594 |
629 |
595 def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename): |
630 def GenerateConciseDCF(locations, current_location, nodelist, sync_TPDOs, nodename): |
596 """ |
631 """ |
597 Fills a CanFestival network editor model, with DCF with requested PDO mappings. |
632 Fills a CanFestival network editor model, with DCF with requested PDO mappings. |
598 @param locations: List of complete variables locations \ |
633 @param locations: List of complete variables locations \ |
603 "LOC" : tuple of interger for IEC location (0,1,2,...) |
638 "LOC" : tuple of interger for IEC location (0,1,2,...) |
604 }, ...] |
639 }, ...] |
605 @param nodelist: CanFestival network editor model |
640 @param nodelist: CanFestival network editor model |
606 @return: a modified copy of the given CanFestival network editor model |
641 @return: a modified copy of the given CanFestival network editor model |
607 """ |
642 """ |
608 |
643 |
609 dcfgenerator = ConciseDCFGenerator(nodelist, nodename) |
644 dcfgenerator = ConciseDCFGenerator(nodelist, nodename) |
610 dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs) |
645 dcfgenerator.GenerateDCF(locations, current_location, sync_TPDOs) |
611 masternode,pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables() |
646 masternode, pointers = dcfgenerator.GetMasterNode(), dcfgenerator.GetPointedVariables() |
612 # allow access to local OD from Master PLC |
647 # allow access to local OD from Master PLC |
613 pointers.update(LocalODPointers(locations, current_location, masternode)) |
648 pointers.update(LocalODPointers(locations, current_location, masternode)) |
614 return masternode,pointers |
649 return masternode, pointers |
|
650 |
615 |
651 |
616 def LocalODPointers(locations, current_location, slave): |
652 def LocalODPointers(locations, current_location, slave): |
617 IECLocations = {} |
653 IECLocations = {} |
618 pointers = {} |
654 pointers = {} |
619 for location in locations: |
655 for location in locations: |
620 COlocationtype = IECToCOType[location["IEC_TYPE"]] |
656 COlocationtype = IECToCOType[location["IEC_TYPE"]] |
621 name = location["NAME"] |
657 name = location["NAME"] |
622 if name in IECLocations: |
658 if name in IECLocations: |
623 if IECLocations[name] != COlocationtype: |
659 if IECLocations[name] != COlocationtype: |
624 raise PDOmappingException, _("Type conflict for location \"%s\"") % name |
660 raise PDOmappingException(_("Type conflict for location \"%s\"") % name) |
625 else: |
661 else: |
626 # Get only the part of the location that concern this node |
662 # Get only the part of the location that concern this node |
627 loc = location["LOC"][len(current_location):] |
663 loc = location["LOC"][len(current_location):] |
628 # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) |
664 # loc correspond to (ID, INDEX, SUBINDEX [,BIT]) |
629 if len(loc) not in (2, 3, 4): |
665 if len(loc) not in (2, 3, 4): |
630 raise PDOmappingException, _("Bad location size : %s") % str(loc) |
666 raise PDOmappingException(_("Bad location size : %s") % str(loc)) |
631 elif len(loc) != 2: |
667 elif len(loc) != 2: |
632 continue |
668 continue |
633 |
669 |
634 # Extract and check nodeid |
670 # Extract and check nodeid |
635 index, subindex = loc[:2] |
671 index, subindex = loc[:2] |
636 |
672 |
637 # Extract and check index and subindex |
673 # Extract and check index and subindex |
638 if not slave.IsEntry(index, subindex): |
674 if not slave.IsEntry(index, subindex): |
639 raise PDOmappingException, _("No such index/subindex ({a1},{a2}) (variable {a3})").\ |
675 raise PDOmappingException( |
640 format(a1 = "%x" % index, a2 = "%x" % subindex, a3 = name) |
676 _("No such index/subindex ({a1},{a2}) (variable {a3})"). |
641 |
677 format(a1="%x" % index, a2="%x" % subindex, a3=name)) |
|
678 |
642 # Get the entry info |
679 # Get the entry info |
643 subentry_infos = slave.GetSubentryInfos(index, subindex) |
680 subentry_infos = slave.GetSubentryInfos(index, subindex) |
644 if subentry_infos["type"] != COlocationtype: |
681 if subentry_infos["type"] != COlocationtype: |
645 raise PDOmappingException, _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\"").\ |
682 raise PDOmappingException( |
646 format( a1 = location["IEC_TYPE"], a2 = COlocationtype, a3 = subentry_infos["type"] , a4 = name) |
683 _("Invalid type \"{a1}\"-> {a2} != {a3} for location \"{a4}\""). |
647 |
684 format(a1=location["IEC_TYPE"], |
|
685 a2=COlocationtype, |
|
686 a3=subentry_infos["type"], |
|
687 a4=name)) |
|
688 |
648 IECLocations[name] = COlocationtype |
689 IECLocations[name] = COlocationtype |
649 pointers[(index, subindex)] = name |
690 pointers[(index, subindex)] = name |
650 return pointers |
691 return pointers |
651 |
692 |
|
693 |
652 if __name__ == "__main__": |
694 if __name__ == "__main__": |
653 import os, sys, getopt |
695 import os |
|
696 import sys |
|
697 import getopt |
654 |
698 |
655 def usage(): |
699 def usage(): |
656 print """ |
700 print """ |
657 Usage of config_utils.py test : |
701 Usage of config_utils.py test : |
658 |
702 |
691 base_folder = sys.path[0] |
735 base_folder = sys.path[0] |
692 for i in xrange(3): |
736 for i in xrange(3): |
693 base_folder = os.path.split(base_folder)[0] |
737 base_folder = os.path.split(base_folder)[0] |
694 # Add CanFestival folder to search pathes |
738 # Add CanFestival folder to search pathes |
695 sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen")) |
739 sys.path.append(os.path.join(base_folder, "CanFestival-3", "objdictgen")) |
696 |
740 |
697 from nodemanager import * |
741 from nodemanager import * |
698 from nodelist import * |
742 from nodelist import * |
699 |
743 |
700 # Open the test nodelist contained into test_config folder |
744 # Open the test nodelist contained into test_config folder |
701 manager = NodeManager() |
745 manager = NodeManager() |
702 nodelist = NodeList(manager) |
746 nodelist = NodeList(manager) |
703 result = nodelist.LoadProject("test_config") |
747 result = nodelist.LoadProject("test_config") |
704 |
748 |
705 # List of locations, we try to map for test |
749 # List of locations, we try to map for test |
706 locations = [{"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24576_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24576,1)}, |
750 locations = [ |
707 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_2","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,2)}, |
751 {"IEC_TYPE": "BYTE", "NAME": "__IB0_1_64_24576_1", "DIR": "I", "SIZE": "B", "LOC": (0, 1, 64, 24576, 1)}, |
708 {"IEC_TYPE":"INT","NAME":"__IW0_1_64_25601_3","DIR":"I","SIZE":"W","LOC":(0,1,64,25601,3)}, |
752 {"IEC_TYPE": "INT", "NAME": "__IW0_1_64_25601_2", "DIR": "I", "SIZE": "W", "LOC": (0, 1, 64, 25601, 2)}, |
709 {"IEC_TYPE":"INT","NAME":"__QW0_1_64_25617_2","DIR":"Q","SIZE":"W","LOC":(0,1,64,25617,1)}, |
753 {"IEC_TYPE": "INT", "NAME": "__IW0_1_64_25601_3", "DIR": "I", "SIZE": "W", "LOC": (0, 1, 64, 25601, 3)}, |
710 {"IEC_TYPE":"BYTE","NAME":"__IB0_1_64_24578_1","DIR":"I","SIZE":"B","LOC":(0,1,64,24578,1)}, |
754 {"IEC_TYPE": "INT", "NAME": "__QW0_1_64_25617_2", "DIR": "Q", "SIZE": "W", "LOC": (0, 1, 64, 25617, 1)}, |
711 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_1","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,1)}, |
755 {"IEC_TYPE": "BYTE", "NAME": "__IB0_1_64_24578_1", "DIR": "I", "SIZE": "B", "LOC": (0, 1, 64, 24578, 1)}, |
712 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_2","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,2)}, |
756 {"IEC_TYPE": "UDINT", "NAME": "__ID0_1_64_25638_1", "DIR": "I", "SIZE": "D", "LOC": (0, 1, 64, 25638, 1)}, |
713 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_3","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,3)}, |
757 {"IEC_TYPE": "UDINT", "NAME": "__ID0_1_64_25638_2", "DIR": "I", "SIZE": "D", "LOC": (0, 1, 64, 25638, 2)}, |
714 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_64_25638_4","DIR":"I","SIZE":"D","LOC":(0,1,64,25638,4)}, |
758 {"IEC_TYPE": "UDINT", "NAME": "__ID0_1_64_25638_3", "DIR": "I", "SIZE": "D", "LOC": (0, 1, 64, 25638, 3)}, |
715 {"IEC_TYPE":"UDINT","NAME":"__ID0_1_4096_0","DIR":"I","SIZE":"D","LOC":(0,1,4096,0)}] |
759 {"IEC_TYPE": "UDINT", "NAME": "__ID0_1_64_25638_4", "DIR": "I", "SIZE": "D", "LOC": (0, 1, 64, 25638, 4)}, |
716 |
760 {"IEC_TYPE": "UDINT", "NAME": "__ID0_1_4096_0", "DIR": "I", "SIZE": "D", "LOC": (0, 1, 4096, 0)} |
|
761 ] |
|
762 |
717 # Generate MasterNode configuration |
763 # Generate MasterNode configuration |
718 try: |
764 try: |
719 masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode") |
765 masternode, pointedvariables = GenerateConciseDCF(locations, (0, 1), nodelist, True, "TestNode") |
720 except ValueError, message: |
766 except ValueError, message: |
721 print "%s\nTest Failed!"%message |
767 print "%s\nTest Failed!" % message |
722 sys.exit() |
768 sys.exit() |
723 |
769 |
724 import pprint |
770 import pprint |
725 # Get Text corresponding to MasterNode |
771 # Get Text corresponding to MasterNode |
726 result_node = masternode.PrintString() |
772 result_node = masternode.PrintString() |
727 result_vars = pprint.pformat(pointedvariables) |
773 result_vars = pprint.pformat(pointedvariables) |
728 result = result_node + "\n********POINTERS*********\n" + result_vars + "\n" |
774 result = result_node + "\n********POINTERS*********\n" + result_vars + "\n" |
729 |
775 |
730 # If reset has been choosen |
776 # If reset has been choosen |
731 if reset: |
777 if reset: |
732 # Write Text into reference result file |
778 # Write Text into reference result file |
733 testfile = open("test_config/result.txt", "w") |
779 testfile = open("test_config/result.txt", "w") |
734 testfile.write(result) |
780 testfile.write(result) |
735 testfile.close() |
781 testfile.close() |
736 |
782 |
737 print "Reset Successful!" |
783 print "Reset Successful!" |
738 else: |
784 else: |
739 import os |
785 import os |
740 |
786 |
741 testfile = open("test_config/result_tmp.txt", "w") |
787 testfile = open("test_config/result_tmp.txt", "w") |
742 testfile.write(result) |
788 testfile.write(result) |
743 testfile.close() |
789 testfile.close() |
744 |
790 |
745 os.system("diff test_config/result.txt test_config/result_tmp.txt") |
791 os.system("diff test_config/result.txt test_config/result_tmp.txt") |
746 os.remove("test_config/result_tmp.txt") |
792 os.remove("test_config/result_tmp.txt") |