2 # -*- coding: utf-8 -*-
4 #This file is part of CanFestival, a library implementing CanOpen Stack.
6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
8 #See COPYING file for copyrights details.
10 #This library is free software; you can redistribute it and/or
11 #modify it under the terms of the GNU Lesser General Public
12 #License as published by the Free Software Foundation; either
13 #version 2.1 of the License, or (at your option) any later version.
15 #This library is distributed in the hope that it will be useful,
16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 #Lesser General Public License for more details.
20 #You should have received a copy of the GNU Lesser General Public
21 #License along with this library; if not, write to the Free Software
22 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 Dictionary of translation between access symbol and their signification
31 AccessType = {"ro" : "Read Only", "wo" : "Write Only", "rw" : "Read/Write"}
33 BoolType = {True : "True", False : "False"}
34 OptionType = {True : "Yes", False : "No"}
36 CustomisableTypes = [(0x02, 0), (0x03, 0), (0x04, 0), (0x05, 0), (0x06, 0), (0x07, 0),
37 (0x08, 0), (0x09, 1), (0x0A, 1), (0x0B, 1), (0x10, 0), (0x11, 0), (0x12, 0),
38 (0x13, 0), (0x14, 0), (0x15, 0), (0x16, 0), (0x18, 0), (0x19, 0), (0x1A, 0),
41 DefaultParams = {"comment" : "", "save" : False}
43 #-------------------------------------------------------------------------------
44 # Dictionary Mapping and Organisation
45 #-------------------------------------------------------------------------------
48 Properties of entry structure in the Object Dictionary
50 OD_Subindex = 1 # Entry has at least one subindex
51 OD_MultipleSubindexes = 2 # Entry has more than one subindex
52 OD_IdenticalSubindexes = 4 # Subindexes of entry have the same description
53 OD_IdenticalIndexes = 8 # Entry has the same description on multiple indexes
56 Structures of entry in the Object Dictionary, sum of the properties described above
57 for all sorts of entries use in CAN Open specification
59 nosub = 0 # Entry without subindex (only for type declaration)
61 array = OD_Subindex | OD_MultipleSubindexes
62 rec = OD_Subindex | OD_MultipleSubindexes | OD_IdenticalSubindexes
63 # Entries identical on multiple indexes
64 plurivar = OD_Subindex | OD_IdenticalIndexes
65 pluriarray = OD_Subindex | OD_MultipleSubindexes | OD_IdenticalIndexes # Example : PDO Parameters
66 plurirec = OD_Subindex | OD_MultipleSubindexes | OD_IdenticalSubindexes |OD_IdenticalIndexes # Example : PDO Mapping
69 MappingDictionary is the structure used for writing a good organised Object
70 Dictionary. It follows the specifications of the CANOpen standard.
71 Change the informations within it if there is a mistake. But don't modify the
72 organisation of this object, it will involve in a malfunction of the application.
76 0x0001 : {"name" : "BOOLEAN", "struct" : nosub, "size" : 1, "default" : False, "values" : []},
77 0x0002 : {"name" : "INTEGER8", "struct" : nosub, "size" : 8, "default" : 0, "values" : []},
78 0x0003 : {"name" : "INTEGER16", "struct" : nosub, "size" : 16, "default" : 0, "values" : []},
79 0x0004 : {"name" : "INTEGER32", "struct" : nosub, "size" : 32, "default" : 0, "values" : []},
80 0x0005 : {"name" : "UNSIGNED8", "struct" : nosub, "size" : 8, "default" : 0, "values" : []},
81 0x0006 : {"name" : "UNSIGNED16", "struct" : nosub, "size" : 16, "default" : 0, "values" : []},
82 0x0007 : {"name" : "UNSIGNED32", "struct" : nosub, "size" : 32, "default" : 0, "values" : []},
83 0x0008 : {"name" : "REAL32", "struct" : nosub, "size" : 32, "default" : 0.0, "values" : []},
84 0x0009 : {"name" : "VISIBLE_STRING", "struct" : nosub, "size" : 8, "default" : "", "values" : []},
85 0x000A : {"name" : "OCTET_STRING", "struct" : nosub, "size" : 8, "default" : "", "values" : []},
86 0x000B : {"name" : "UNICODE_STRING", "struct" : nosub, "size" : 16, "default" : "", "values" : []},
87 # 0x000C : {"name" : "TIME_OF_DAY", "struct" : nosub, "size" : 48, "default" : 0, "values" : []},
88 # 0x000D : {"name" : "TIME_DIFFERENCE", "struct" : nosub, "size" : 48, "default" : 0, "values" : []},
89 0x000F : {"name" : "DOMAIN", "struct" : nosub, "size" : 0, "default" : "", "values" : []},
90 0x0010 : {"name" : "INTEGER24", "struct" : nosub, "size" : 24, "default" : 0, "values" : []},
91 0x0011 : {"name" : "REAL64", "struct" : nosub, "size" : 64, "default" : 0.0, "values" : []},
92 0x0012 : {"name" : "INTEGER40", "struct" : nosub, "size" : 40, "default" : 0, "values" : []},
93 0x0013 : {"name" : "INTEGER48", "struct" : nosub, "size" : 48, "default" : 0, "values" : []},
94 0x0014 : {"name" : "INTEGER56", "struct" : nosub, "size" : 56, "default" : 0, "values" : []},
95 0x0015 : {"name" : "INTEGER64", "struct" : nosub, "size" : 64, "default" : 0, "values" : []},
96 0x0016 : {"name" : "UNSIGNED24", "struct" : nosub, "size" : 24, "default" : 0, "values" : []},
97 0x0018 : {"name" : "UNSIGNED40", "struct" : nosub, "size" : 40, "default" : 0, "values" : []},
98 0x0019 : {"name" : "UNSIGNED48", "struct" : nosub, "size" : 48, "default" : 0, "values" : []},
99 0x001A : {"name" : "UNSIGNED56", "struct" : nosub, "size" : 56, "default" : 0, "values" : []},
100 0x001B : {"name" : "UNSIGNED64", "struct" : nosub, "size" : 64, "default" : 0, "values" : []},
101 0x1000 : {"name" : "Device Type", "struct" : var, "need" : True, "values" :
102 [{"name" : "Device Type", "type" : 0x07, "access" : 'ro', "pdo" : False}]},
103 0x1001 : {"name" : "Error Register", "struct" : var, "need" : True, "values" :
104 [{"name" : "Error Register", "type" : 0x05, "access": 'ro', "pdo" : True}]},
105 0x1002 : {"name" : "Manufacturer Status Register", "struct" : var, "need" : False, "values" :
106 [{"name" : "Manufacturer Status Register", "type" : 0x07, "access" : 'ro', "pdo" : True}]},
107 0x1003 : {"name" : "Pre-defined Error Field", "struct" : rec, "need" : False, "callback" : True, "values" :
108 [{"name" : "Number of Errors", "type" : 0x05, "access" : 'rw', "pdo" : False},
109 {"name" : "Standard Error Field", "type" : 0x07, "access" : 'ro', "pdo" : False, "nbmax" : 0xFE}]},
110 0x1005 : {"name" : "SYNC COB ID", "struct" : var, "need" : False, "callback" : True, "values" :
111 [{"name" : "SYNC COB ID", "type" : 0x07, "access" : 'rw', "pdo" : False}]},
112 0x1006 : {"name" : "Communication / Cycle Period", "struct" : var, "need" : False, "callback" : True, "values" :
113 [{"name" : "Communication Cycle Period", "type" : 0x07, "access" : 'rw', "pdo" : False}]},
114 0x1007 : {"name" : "Synchronous Window Length", "struct" : var, "need" : False, "values" :
115 [{"name" : "Synchronous Window Length", "type" : 0x07, "access" : 'rw', "pdo" : False}]},
116 0x1008 : {"name" : "Manufacturer Device Name", "struct" : var, "need" : False, "values" :
117 [{"name" : "Manufacturer Device Name", "type" : 0x09, "access" : 'ro', "pdo" : False}]},
118 0x1009 : {"name" : "Manufacturer Hardware Version", "struct" : var, "need" : False, "values" :
119 [{"name" : "Manufacturer Hardware Version", "type" : 0x09, "access" : 'ro', "pdo" : False}]},
120 0x100A : {"name" : "Manufacturer Software Version", "struct" : var, "need" : False, "values" :
121 [{"name" : "Manufacturer Software Version", "type" : 0x09, "access" : 'ro', "pdo" : False}]},
122 0x100C : {"name" : "Guard Time", "struct" : var, "need" : False, "values" :
123 [{"name" : "Guard Time", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
124 0x100D : {"name" : "Life Time Factor", "struct" : var, "need" : False, "values" :
125 [{"name" : "Life Time Factor", "type" : 0x05, "access" : 'rw', "pdo" : False}]},
126 0x1010 : {"name" : "Store parameters", "struct" : array, "need" : False, "values" :
127 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
128 {"name" : "Save All Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
129 {"name" : "Save Communication Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
130 {"name" : "Save Application Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
131 {"name" : "Save Manufacturer Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmax" : 0x7C}]},
132 0x1011 : {"name" : "Restore Default Parameters", "struct" : array, "need" : False, "values" :
133 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
134 {"name" : "Restore All Default Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
135 {"name" : "Restore Communication Default Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
136 {"name" : "Restore Application Default Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
137 {"name" : "Restore Manufacturer Default Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmax" : 0x7C}]},
138 0x1012 : {"name" : "TIME COB ID", "struct" : var, "need" : False, "values" :
139 [{"name" : "TIME COB ID", "type" : 0x07, "access" : 'rw', "pdo" : False}]},
140 0x1013 : {"name" : "High Resolution Timestamp", "struct" : var, "need" : False, "values" :
141 [{"name" : "High Resolution Time Stamp", "type" : 0x07, "access" : 'rw', "pdo" : True}]},
142 0x1014 : {"name" : "Emergency COB ID", "struct" : var, "need" : False, "values" :
143 [{"name" : "Emergency COB ID", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "\"$NODEID+0x80\""}]},
144 0x1015 : {"name" : "Inhibit Time Emergency", "struct" : var, "need" : False, "values" :
145 [{"name" : "Inhibit Time Emergency", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
146 0x1016 : {"name" : "Consumer Heartbeat Time", "struct" : rec, "need" : False, "values" :
147 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
148 {"name" : "Consumer Heartbeat Time", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 1, "nbmax" : 0x7F}]},
149 0x1017 : {"name" : "Producer Heartbeat Time", "struct" : var, "need" : False, "callback" : True, "values" :
150 [{"name" : "Producer Heartbeat Time", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
151 0x1018 : {"name" : "Identity", "struct" : array, "need" : True, "values" :
152 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
153 {"name" : "Vendor ID", "type" : 0x07, "access" : 'ro', "pdo" : False},
154 {"name" : "Product Code", "type" : 0x07, "access" : 'ro', "pdo" : False},
155 {"name" : "Revision Number", "type" : 0x07, "access" : 'ro', "pdo" : False},
156 {"name" : "Serial Number", "type" : 0x07, "access" : 'ro', "pdo" : False}]},
157 0x1020 : {"name" : "Verify Configuration", "struct" : array, "need" : False, "values" :
158 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
159 {"name" : "Configuration Date", "type" : 0x07, "access" : 'ro', "pdo" : False},
160 {"name" : "Configuration Time", "type" : 0x07, "access" : 'ro', "pdo" : False}]},
161 # 0x1021 : {"name" : "Store EDS", "struct" : var, "need" : False, "values" :
162 # [{"name" : "Store EDS", "type" : 0x0F, "access" : 'rw', "pdo" : False}]},
163 # 0x1022 : {"name" : "Storage Format", "struct" : var, "need" : False, "values" :
164 # [{"name" : "Storage Format", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
165 0x1023 : {"name" : "OS Command", "struct" : array, "need" : False, "values" :
166 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
167 {"name" : "Command", "type" : 0x0A, "access" : 'rw', "pdo" : False},
168 {"name" : "Status", "type" : 0x05, "access" : 'ro', "pdo" : False},
169 {"name" : "Reply", "type" : 0x0A, "access" : 'ro', "pdo" : False}]},
170 0x1024 : {"name" : "OS Command Mode", "struct" : var, "need" : False, "values" :
171 [{"name" : "OS Command Mode", "type" : 0x05, "access" : 'wo', "pdo" : False}]},
172 0x1025 : {"name" : "OS Debugger Interface", "struct" : array, "need" : False, "values" :
173 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
174 {"name" : "Command", "type" : 0x0A, "access" : 'rw', "pdo" : False},
175 {"name" : "Status", "type" : 0x07, "access" : 'ro', "pdo" : False},
176 {"name" : "Reply", "type" : 0x0A, "access" : 'ro', "pdo" : False}]},
177 0x1026 : {"name" : "OS Prompt", "struct" : array, "need" : False, "values" :
178 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
179 {"name" : "StdIn", "type" : 0x05, "access" : 'wo', "pdo" : True},
180 {"name" : "StdOut", "type" : 0x05, "access" : 'ro', "pdo" : True},
181 {"name" : "StdErr", "type" : 0x05, "access" : 'ro', "pdo" : True}]},
182 0x1027 : {"name" : "Module List", "struct" : rec, "need" : False, "values" :
183 [{"name" : "Number of Connected Modules", "type" : 0x05, "access" : 'ro', "pdo" : False},
184 {"name" : "Module %d[(sub)]", "type" : 0x06, "access" : 'ro', "pdo" : False, "nbmin" : 1, "nbmax" : 0xFE}]},
185 0x1028 : {"name" : "Emergency Consumer", "struct" : rec, "need" : False, "values" :
186 [{"name" : "Number of Consumed Emergency Objects", "type" : 0x05, "access" : 'ro', "pdo" : False},
187 {"name" : "Emergency Consumer", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 1, "nbmax" : 0x7E}]},
188 0x1029 : {"name" : "Error Behavior", "struct" : array, "need" : False, "values" :
189 [{"name" : "Number of Error Classes", "type" : 0x05, "access" : 'ro', "pdo" : False},
190 {"name" : "Communication Error", "type" : 0x05, "access" : 'rw', "pdo" : False},
191 {"name" : "Device Profile", "type" : 0x05, "access" : 'rw', "pdo" : False, "nbmax" : 0xFE}]},
192 0x1200 : {"name" : "Server SDO Parameter", "struct" : array, "need" : False, "values" :
193 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
194 {"name" : "COB ID Client to Server (Receive SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False, "default" : "\"$NODEID+0x600\""},
195 {"name" : "COB ID Server to Client (Transmit SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False, "default" : "\"$NODEID+0x580\""}]},
196 0x1201 : {"name" : "Additional Server SDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x7F, "need" : False, "values" :
197 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
198 {"name" : "COB ID Client to Server (Receive SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False},
199 {"name" : "COB ID Server to Client (Transmit SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False},
200 {"name" : "Node ID of the SDO Client", "type" : 0x05, "access" : 'ro', "pdo" : False}]},
201 0x1280 : {"name" : "Client SDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x100, "need" : False, "values" :
202 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
203 {"name" : "COB ID Client to Server (Transmit SDO)", "type" : 0x07, "access" : 'rw', "pdo" : False},
204 {"name" : "COB ID Server to Client (Receive SDO)", "type" : 0x07, "access" : 'rw', "pdo" : False},
205 {"name" : "Node ID of the SDO Server", "type" : 0x05, "access" : 'rw', "pdo" : False}]},
206 0x1400 : {"name" : "Receive PDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
207 [{"name" : "Highest SubIndex Supported", "type" : 0x05, "access" : 'ro', "pdo" : False},
208 {"name" : "COB ID used by PDO", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "{True:\"$NODEID+0x%X00\"%(base+2),False:0x80000000}[base<4]"},
209 {"name" : "Transmission Type", "type" : 0x05, "access" : 'rw', "pdo" : False},
210 {"name" : "Inhibit Time", "type" : 0x06, "access" : 'rw', "pdo" : False},
211 {"name" : "Compatibility Entry", "type" : 0x05, "access" : 'rw', "pdo" : False},
212 {"name" : "Event Timer", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
213 0x1600 : {"name" : "Receive PDO %d Mapping[(idx)]", "struct" : plurirec, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
214 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'rw', "pdo" : False},
215 {"name" : "PDO %d Mapping for an application object %d[(idx,sub)]", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 0, "nbmax" : 0x40}]},
216 0x1800 : {"name" : "Transmit PDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x200, "need" : False, "callback" : True, "values" :
217 [{"name" : "Highest SubIndex Supported", "type" : 0x05, "access" : 'ro', "pdo" : False},
218 {"name" : "COB ID used by PDO", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "{True:\"$NODEID+0x%X80\"%(base+1),False:0x80000000}[base<4]"},
219 {"name" : "Transmission Type", "type" : 0x05, "access" : 'rw', "pdo" : False},
220 {"name" : "Inhibit Time", "type" : 0x06, "access" : 'rw', "pdo" : False},
221 {"name" : "Compatibility Entry", "type" : 0x05, "access" : 'rw', "pdo" : False},
222 {"name" : "Event Timer", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
223 0x1A00 : {"name" : "Transmit PDO %d Mapping[(idx)]", "struct" : plurirec, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
224 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'rw', "pdo" : False},
225 {"name" : "PDO %d Mapping for a process data variable %d[(idx,sub)]", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 0, "nbmax" : 0x40}]},
228 #-------------------------------------------------------------------------------
229 # Search in a Mapping Dictionary
230 #-------------------------------------------------------------------------------
233 Return the index of the typename given by searching in mappingdictionary
235 def FindTypeIndex(typename, mappingdictionary):
237 for index, values in mappingdictionary.iteritems():
239 testdic[values["name"]] = index
240 if typename in testdic:
241 return testdic[typename]
245 Return the name of the type by searching in mappingdictionary
247 def FindTypeName(typeindex, mappingdictionary):
248 if typeindex < 0x1000 and typeindex in mappingdictionary:
249 return mappingdictionary[typeindex]["name"]
253 Return the default value of the type by searching in mappingdictionary
255 def FindTypeDefaultValue(typeindex, mappingdictionary):
256 if typeindex < 0x1000 and typeindex in mappingdictionary:
257 return mappingdictionary[typeindex]["default"]
261 Return the list of types defined in mappingdictionary
263 def FindTypeList(mappingdictionary):
265 for index in mappingdictionary.keys():
267 list.append(mappingdictionary[index]["name"])
271 Return the name of an entry by searching in mappingdictionary
273 def FindEntryName(index, mappingdictionary):
274 base_index = FindIndex(index, mappingdictionary)
276 infos = mappingdictionary[base_index]
277 if infos["struct"] & OD_IdenticalIndexes:
278 return StringFormat(infos["name"], (index - base_index) / infos["incr"] + 1, 0)
284 Return the informations of one entry by searching in mappingdictionary
286 def FindEntryInfos(index, mappingdictionary):
287 base_index = FindIndex(index, mappingdictionary)
289 copy = mappingdictionary[base_index].copy()
290 if copy["struct"] & OD_IdenticalIndexes:
291 copy["name"] = StringFormat(copy["name"], (index - base_index) / copy["incr"] + 1, 0)
297 Return the informations of one subentry of an entry by searching in mappingdictionary
299 def FindSubentryInfos(index, subIndex, mappingdictionary):
300 base_index = FindIndex(index, mappingdictionary)
302 struct = mappingdictionary[base_index]["struct"]
303 if struct & OD_Subindex:
304 if struct & OD_IdenticalSubindexes:
305 if struct & OD_IdenticalIndexes:
306 incr = mappingdictionary[base_index]["incr"]
310 return mappingdictionary[base_index]["values"][0].copy()
311 elif 0 < subIndex <= mappingdictionary[base_index]["values"][1]["nbmax"]:
312 copy = mappingdictionary[base_index]["values"][1].copy()
313 copy["name"] = StringFormat(copy["name"], (index - base_index) / incr + 1, subIndex)
315 elif struct & OD_MultipleSubindexes and 0 <= subIndex < len(mappingdictionary[base_index]["values"]):
316 return mappingdictionary[base_index]["values"][subIndex].copy()
318 return mappingdictionary[base_index]["values"][0].copy()
322 Return the list of variables that can be mapped defined in mappingdictionary
324 def FindMapVariableList(mappingdictionary, Node):
326 for index in mappingdictionary.iterkeys():
327 if Node.IsEntry(index):
328 for subIndex, values in enumerate(mappingdictionary[index]["values"]):
329 if mappingdictionary[index]["values"][subIndex]["pdo"]:
330 infos = Node.GetEntryInfos(mappingdictionary[index]["values"][subIndex]["type"])
331 if mappingdictionary[index]["struct"] & OD_IdenticalSubindexes:
332 values = Node.GetEntry(index)
333 for i in xrange(len(values) - 1):
334 list.append((index, i + 1, infos["size"], StringFormat(mappingdictionary[index]["values"][subIndex]["name"],1,i+1)))
336 list.append((index, subIndex, infos["size"], mappingdictionary[index]["values"][subIndex]["name"]))
340 Return the list of mandatory indexes defined in mappingdictionary
342 def FindMandatoryIndexes(mappingdictionary):
344 for index in mappingdictionary.iterkeys():
345 if index >= 0x1000 and mappingdictionary[index]["need"]:
350 Return the index of the informations in the Object Dictionary in case of identical
353 def FindIndex(index, mappingdictionary):
354 if index in mappingdictionary:
357 listpluri = [idx for idx in mappingdictionary.keys() if mappingdictionary[idx]["struct"] & OD_IdenticalIndexes]
359 for idx in listpluri:
360 nb_max = mappingdictionary[idx]["nbmax"]
361 incr = mappingdictionary[idx]["incr"]
362 if idx < index < idx + incr * nb_max and (index - idx)%incr == 0:
366 #-------------------------------------------------------------------------------
367 # Formating Name of an Entry
368 #-------------------------------------------------------------------------------
370 name_model = re.compile('(.*)\[(.*)\]')
373 Format the text given with the index and subindex defined
375 def StringFormat(text, idx, sub):
376 result = name_model.match(text)
378 format = result.groups()
379 return format[0]%eval(format[1])
383 #-------------------------------------------------------------------------------
384 # Definition of Node Object
385 #-------------------------------------------------------------------------------
388 Class recording the Object Dictionary entries. It checks at each modification
389 that the structure of the Object Dictionary stay coherent
394 DefaultStringSize = 10
396 def __init__(self, name = "", type = "slave", id = 0, description = "", profilename = "DS-301", profile = {}, specificmenu = []):
400 self.Description = description
401 self.ProfileName = profilename
402 self.Profile = profile
403 self.SpecificMenu = specificmenu
405 self.ParamsDictionary = {}
407 self.UserMapping = {}
412 def GetNodeName(self):
418 def SetNodeName(self, name):
422 Return the node type ("master" or "slave")
424 def GetNodeType(self):
428 Define the node type ("master" or "slave")
430 def SetNodeType(self, type):
442 def SetNodeID(self, id):
446 Return the node description
448 def GetNodeDescription(self):
449 if getattr(self, "Description", False):
450 return self.Description
455 Define the node description
457 def SetNodeDescription(self, description):
458 self.Description = description
461 Return the Specific Profile Name
463 def GetProfileName(self):
464 return self.ProfileName
467 Define the Specific Profile Name
469 def SetProfileName(self, profilename):
470 self.ProfileName = profilename
473 Return the Specific Profile
475 def GetProfile(self):
479 Define the Specific Profile
481 def SetProfile(self, profile):
482 self.Profile = profile
485 Return the default string size
487 def GetDefaultStringSize(self):
488 return self.DefaultStringSize
491 Define the default string size
493 def SetDefaultStringSize(self, size):
494 self.DefaultStringSize = size
497 Define the DS-302 Profile
499 def SetDS302Profile(self, profile):
503 Define the DS-302 Profile
505 def GetDS302Profile(self):
509 Return the Specific Menu Entries
511 def GetSpecificMenu(self):
512 return self.SpecificMenu
515 Define the Specific Menu Entries
517 def SetSpecificMenu(self, specificmenu):
518 self.SpecificMenu = specificmenu
521 Extend the Specific Menu Entries
524 def ExtendSpecificMenu(self, specificmenu):
525 self.SpecificMenu.extend(specificmenu)
528 Function which return the different Mappings available for this node
530 def GetMappings(self, userdefinedtoo = True):
532 return [self.Profile, self.DS302, self.UserMapping]
534 return [self.Profile, self.DS302]
537 Add a new entry in the Object Dictionary
539 def AddEntry(self, index, subIndex = None, value = None):
540 if index not in self.Dictionary:
542 self.Dictionary[index] = value
545 self.Dictionary[index] = [value]
547 elif subIndex > 0 and type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]) + 1:
548 self.Dictionary[index].append(value)
553 Warning ! Modifies an existing entry in the Object Dictionary. Can't add a new one.
555 def SetEntry(self, index, subIndex = None, value = None):
556 if index in self.Dictionary:
559 self.Dictionary[index] = value
561 elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
563 self.Dictionary[index][subIndex - 1] = value
567 def SetParamsEntry(self, index, subIndex = None, comment = None, save = None, callback = None):
568 if not getattr(self, "ParamsDictionary", False):
569 self.ParamsDictionary = {}
570 if index in self.Dictionary:
571 if (comment != None or save != None or callback != None) and index not in self.ParamsDictionary:
572 self.ParamsDictionary[index] = {}
573 if subIndex == None or type(self.Dictionary[index]) != ListType and subIndex == 0:
575 self.ParamsDictionary[index]["comment"] = comment
577 self.ParamsDictionary[index]["save"] = save
579 self.ParamsDictionary[index]["callback"] = callback
581 elif type(self.Dictionary[index]) == ListType and 0 <= subIndex <= len(self.Dictionary[index]):
582 if (comment != None or save != None or callback != None) and subIndex not in self.ParamsDictionary[index]:
583 self.ParamsDictionary[index][subIndex] = {}
585 self.ParamsDictionary[index][subIndex]["comment"] = comment
587 self.ParamsDictionary[index][subIndex]["save"] = save
592 Removes an existing entry in the Object Dictionary. If a subIndex is specified
593 it will remove this subIndex only if it's the last of the index. If no subIndex
594 is specified it removes the whole index and subIndexes from the Object Dictionary.
596 def RemoveEntry(self, index, subIndex = None):
597 if not getattr(self, "ParamsDictionary", False):
598 self.ParamsDictionary = {}
599 if index in self.Dictionary:
601 self.Dictionary.pop(index)
602 if index in self.ParamsDictionary:
603 self.ParamsDictionary.pop(index)
605 elif type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]):
606 self.Dictionary[index].pop(subIndex - 1)
607 if index in self.ParamsDictionary:
608 if subIndex in self.ParamsDictionary[index]:
609 self.ParamsDictionary[index].pop(subIndex)
610 if len(self.ParamsDictionary[index]) == 0:
611 self.ParamsDictionary.pop(index)
612 if len(self.Dictionary[index]) == 0:
613 self.Dictionary.pop(index)
614 if index in self.ParamsDictionary:
615 self.ParamsDictionary.pop(index)
620 Check if an entry exists in the Object Dictionary and returns the answer.
622 def IsEntry(self, index, subIndex = None):
623 if index in self.Dictionary:
626 return subIndex <= len(self.Dictionary[index])
630 Returns the value of the entry asked. If the entry has the value "count", it
631 returns the number of subIndex in the entry except the first.
633 def GetEntry(self, index, subIndex = None, compute = True):
634 if index in self.Dictionary:
636 if type(self.Dictionary[index]) == ListType:
637 values = [len(self.Dictionary[index])]
638 for value in self.Dictionary[index]:
639 values.append(self.CompileValue(value, index, compute))
642 return self.CompileValue(self.Dictionary[index], index, compute)
644 if type(self.Dictionary[index]) == ListType:
645 return len(self.Dictionary[index])
647 return self.CompileValue(self.Dictionary[index], index, compute)
648 elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
649 return self.CompileValue(self.Dictionary[index][subIndex - 1], index, compute)
653 Returns the value of the entry asked. If the entry has the value "count", it
654 returns the number of subIndex in the entry except the first.
656 def GetParamsEntry(self, index, subIndex = None):
657 if not getattr(self, "ParamsDictionary", False):
658 self.ParamsDictionary = {}
659 if index in self.Dictionary:
661 if type(self.Dictionary[index]) == ListType:
662 if index in self.ParamsDictionary:
664 for i in xrange(len(self.Dictionary[index]) + 1):
665 line = DefaultParams.copy()
666 if i in self.ParamsDictionary[index]:
667 line.update(self.ParamsDictionary[index][i])
671 return [DefaultParams.copy() for i in xrange(len(self.Dictionary[index]) + 1)]
673 result = DefaultParams.copy()
674 if index in self.ParamsDictionary:
675 result.update(self.ParamsDictionary[index])
677 elif subIndex == 0 and type(self.Dictionary[index]) != ListType:
678 result = DefaultParams.copy()
679 if index in self.ParamsDictionary:
680 result.update(self.ParamsDictionary[index])
682 elif type(self.Dictionary[index]) == ListType and 0 <= subIndex <= len(self.Dictionary[index]):
683 result = DefaultParams.copy()
684 if index in self.ParamsDictionary and subIndex in self.ParamsDictionary[index]:
685 result.update(self.ParamsDictionary[index][subIndex])
689 def HasEntryCallbacks(self, index):
690 entry_infos = self.GetEntryInfos(index)
691 if entry_infos and "callback" in entry_infos:
692 return entry_infos["callback"]
694 if not getattr(self, "ParamsDictionary", False):
695 self.ParamsDictionary = {}
696 if index in self.Dictionary and index in self.ParamsDictionary and "callback" in self.ParamsDictionary[index]:
697 return self.ParamsDictionary[index]["callback"]
701 Check if an entry exists in the User Mapping Dictionary and returns the answer.
703 def IsMappingEntry(self, index):
704 if index in self.UserMapping:
709 Add a new entry in the User Mapping Dictionary
711 def AddMappingEntry(self, index, subIndex = None, name = "Undefined", struct = 0, size = None, nbmax = None, default = None, values = None):
712 if index not in self.UserMapping:
716 self.UserMapping[index] = {"name" : name, "struct" : struct, "need" : False, "values" : values}
718 self.UserMapping[index]["size"] = size
720 self.UserMapping[index]["nbmax"] = nbmax
722 self.UserMapping[index]["default"] = default
724 elif subIndex != None and subIndex == len(self.UserMapping[index]["values"]):
727 self.UserMapping[index]["values"].append(values)
732 Warning ! Modifies an existing entry in the User Mapping Dictionary. Can't add a new one.
734 def SetMappingEntry(self, index, subIndex = None, name = None, struct = None, size = None, nbmax = None, default = None, values = None):
735 if index in self.UserMapping:
738 self.UserMapping[index]["name"] = name
739 if self.UserMapping[index]["struct"] & OD_IdenticalSubindexes:
740 self.UserMapping[index]["values"][1]["name"] = name + " %d[(sub)]"
741 elif not self.UserMapping[index]["struct"] & OD_MultipleSubindexes:
742 self.UserMapping[index]["values"][0]["name"] = name
744 self.UserMapping[index]["struct"] = struct
746 self.UserMapping[index]["size"] = size
748 self.UserMapping[index]["nbmax"] = nbmax
750 self.UserMapping[index]["default"] = default
752 self.UserMapping[index]["values"] = values
754 elif 0 <= subIndex < len(self.UserMapping[index]["values"]) and values != None:
756 if self.UserMapping[index]["struct"] & OD_IdenticalSubindexes:
757 if self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
758 if self.IsRealType(values["type"]):
759 for i in xrange(len(self.Dictionary[index])):
760 self.SetEntry(index, i + 1, 0.)
761 elif not self.IsStringType(values["type"]):
762 for i in xrange(len(self.Dictionary[index])):
763 self.SetEntry(index, i + 1, 0)
764 elif self.IsRealType(self.UserMapping[index]["values"][subIndex]["type"]):
765 if self.IsStringType(values["type"]):
766 for i in xrange(len(self.Dictionary[index])):
767 self.SetEntry(index, i + 1, "")
768 elif not self.IsRealType(values["type"]):
769 for i in xrange(len(self.Dictionary[index])):
770 self.SetEntry(index, i + 1, 0)
771 elif self.IsStringType(values["type"]):
772 for i in xrange(len(self.Dictionary[index])):
773 self.SetEntry(index, i + 1, "")
774 elif self.IsRealType(values["type"]):
775 for i in xrange(len(self.Dictionary[index])):
776 self.SetEntry(index, i + 1, 0.)
778 if self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
779 if self.IsRealType(values["type"]):
780 self.SetEntry(index, subIndex, 0.)
781 elif not self.IsStringType(values["type"]):
782 self.SetEntry(index, subIndex, 0)
783 elif self.IsRealType(self.UserMapping[index]["values"][subIndex]["type"]):
784 if self.IsStringType(values["type"]):
785 self.SetEntry(index, subIndex, "")
786 elif not self.IsRealType(values["type"]):
787 self.SetEntry(index, subIndex, 0)
788 elif self.IsStringType(values["type"]):
789 self.SetEntry(index, subIndex, "")
790 elif self.IsRealType(values["type"]):
791 self.SetEntry(index, subIndex, 0.)
792 self.UserMapping[index]["values"][subIndex].update(values)
797 Removes an existing entry in the User Mapping Dictionary. If a subIndex is specified
798 it will remove this subIndex only if it's the last of the index. If no subIndex
799 is specified it removes the whole index and subIndexes from the User Mapping Dictionary.
801 def RemoveMappingEntry(self, index, subIndex = None):
802 if index in self.UserMapping:
804 self.UserMapping.pop(index)
806 elif subIndex == len(self.UserMapping[index]["values"]) - 1:
807 self.UserMapping[index]["values"].pop(subIndex)
811 def RemoveMapVariable(self, index, subIndex = None):
815 model += subIndex << 8
817 for i in self.Dictionary.iterkeys():
818 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
819 for j,value in enumerate(self.Dictionary[i]):
820 if (value & mask) == model:
821 self.Dictionary[i][j] = 0
823 def UpdateMapVariable(self, index, subIndex, size):
827 model += subIndex << 8
829 for i in self.Dictionary.iterkeys():
830 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
831 for j,value in enumerate(self.Dictionary[i]):
832 if (value & mask) == model:
833 self.Dictionary[i][j] = model + size
835 def RemoveLine(self, index, max, incr = 1):
837 while i < max and self.IsEntry(i + incr):
838 self.Dictionary[i] = self.Dictionary[i + incr]
840 self.Dictionary.pop(i)
842 def RemoveUserType(self, index):
843 type = self.GetEntry(index, 1)
844 for i in self.UserMapping:
845 for value in self.UserMapping[i]["values"]:
846 if value["type"] == index:
848 self.RemoveMappingEntry(index)
849 self.RemoveEntry(index)
852 Return a copy of the node
855 return cPickle.loads(cPickle.dumps(self))
858 Return a sorted list of indexes in Object Dictionary
860 def GetIndexes(self):
861 listindex = self.Dictionary.keys()
866 Print the Dictionary values
869 print self.PrintString()
871 def PrintString(self):
873 listindex = self.Dictionary.keys()
875 for index in listindex:
876 name = self.GetEntryName(index)
877 values = self.Dictionary[index]
878 if isinstance(values, ListType):
879 result += "%04X (%s):\n"%(index, name)
880 for subidx, value in enumerate(values):
881 subentry_infos = self.GetSubentryInfos(index, subidx + 1)
882 if index == 0x1F22 and value:
883 nb_params = BE_to_LE(value[:4])
885 value = "%d arg defined"%nb_params
889 value += "\n%04X %02X, arg %d: "%(index, subidx+1, count)
890 value += "%04X"%BE_to_LE(data[i:i+2])
891 value += " %02X"%BE_to_LE(data[i+2:i+3])
892 size = BE_to_LE(data[i+3:i+7])
893 value += " %08X"%size
894 value += (" %0"+"%d"%(size * 2)+"X")%BE_to_LE(data[i+7:i+7+size])
897 elif isinstance(value, IntType):
899 result += "%04X %02X (%s): %s\n"%(index, subidx+1, subentry_infos["name"], value)
901 if isinstance(values, IntType):
903 result += "%04X (%s): %s\n"%(index, name, values)
906 def CompileValue(self, value, index, compute = True):
907 if type(value) == StringType and value.find("$NODEID") != -1:
908 base = self.GetBaseIndex(index)
912 return eval(raw.replace("$NODEID","self.ID"))
919 #-------------------------------------------------------------------------------
920 # Node Informations Functions
921 #-------------------------------------------------------------------------------
923 def GetBaseIndex(self, index):
924 for mapping in self.GetMappings():
925 result = FindIndex(index, mapping)
927 return (index - result) / mapping[result].get("incr", 1)
928 result = FindIndex(index, MappingDictionary)
930 return (index - result) / MappingDictionary[result].get("incr", 1)
933 def GetCustomisedTypeValues(self, index):
934 values = self.GetEntry(index)
935 customisabletypes = self.GetCustomisableTypes()
936 return values, customisabletypes[values[1]][1]
938 def GetEntryName(self, index):
940 mappings = self.GetMappings()
942 while not result and i < len(mappings):
943 result = FindEntryName(index, mappings[i])
946 result = FindEntryName(index, MappingDictionary)
949 def GetEntryInfos(self, index):
951 mappings = self.GetMappings()
953 while not result and i < len(mappings):
954 result = FindEntryInfos(index, mappings[i])
957 result = FindEntryInfos(index, MappingDictionary)
960 def GetSubentryInfos(self, index, subIndex):
962 mappings = self.GetMappings()
964 while not result and i < len(mappings):
965 result = FindSubentryInfos(index, subIndex, mappings[i])
967 result["user_defined"] = i == len(mappings) - 1 and index >= 0x1000
970 result = FindSubentryInfos(index, subIndex, MappingDictionary)
972 result["user_defined"] = False
975 def GetTypeIndex(self, typename):
977 mappings = self.GetMappings()
979 while not result and i < len(mappings):
980 result = FindTypeIndex(typename, mappings[i])
983 result = FindTypeIndex(typename, MappingDictionary)
986 def GetTypeName(self, typeindex):
988 mappings = self.GetMappings()
990 while not result and i < len(mappings):
991 result = FindTypeName(typeindex, mappings[i])
994 result = FindTypeName(typeindex, MappingDictionary)
997 def GetTypeDefaultValue(self, typeindex):
999 mappings = self.GetMappings()
1001 while not result and i < len(mappings):
1002 result = FindTypeDefaultValue(typeindex, mappings[i])
1005 result = FindTypeDefaultValue(typeindex, MappingDictionary)
1008 def GetMapVariableList(self):
1009 list = FindMapVariableList(MappingDictionary, self)
1010 for mapping in self.GetMappings():
1011 list.extend(FindMapVariableList(mapping, self))
1015 def GetMandatoryIndexes(self, node = None):
1016 list = FindMandatoryIndexes(MappingDictionary)
1017 for mapping in self.GetMappings():
1018 list.extend(FindMandatoryIndexes(mapping))
1021 def GetCustomisableTypes(self):
1023 for index, valuetype in CustomisableTypes:
1024 name = self.GetTypeName(index)
1025 dic[index] = [name, valuetype]
1028 #-------------------------------------------------------------------------------
1029 # Type helper functions
1030 #-------------------------------------------------------------------------------
1032 def IsStringType(self, index):
1033 if index in (0x9, 0xA, 0xB):
1035 elif 0xA0 <= index < 0x100:
1036 result = self.GetEntry(index, 1)
1037 if result is not None and result in (0x9, 0xA, 0xB):
1041 def IsRealType(self, index):
1042 if index in (0x8, 0x11):
1044 elif 0xA0 <= index < 0x100:
1045 result = self.GetEntry(index, 1)
1046 if result is not None and result in (0x8, 0x11):
1050 #-------------------------------------------------------------------------------
1051 # Type and Map Variable Lists
1052 #-------------------------------------------------------------------------------
1054 def GetTypeList(self):
1055 list = FindTypeList(MappingDictionary)
1056 for mapping in self.GetMappings():
1057 list.extend(FindTypeList(mapping))
1059 return ",".join(list)
1062 Generate the list of variables that can be mapped for the current node
1064 def GenerateMapList(self):
1065 self.MapList = "None"
1066 self.NameTranslation = {"None" : "00000000"}
1067 self.MapTranslation = {"00000000" : "None"}
1068 list = self.GetMapVariableList()
1069 for index, subIndex, size, name in list:
1070 self.MapList += ",%s"%name
1071 map = "%04X%02X%02X"%(index,subIndex,size)
1072 self.NameTranslation[name] = map
1073 self.MapTranslation[map] = name
1075 def GetMapValue(self, mapname):
1076 if mapname == "None":
1079 list = self.GetMapVariableList()
1080 for index, subIndex, size, name in list:
1082 return (index << 16) + (subIndex << 8) + size
1085 def GetMapName(self, value):
1088 subindex = (value >> 8) % (1 << 8)
1089 result = self.GetSubentryInfos(index, subindex)
1091 return result["name"]
1095 Return the list of variables that can be mapped for the current node
1097 def GetMapList(self):
1098 list = ["None"] + [name for index, subIndex, size, name in self.GetMapVariableList()]
1099 return ",".join(list)
1101 def BE_to_LE(value):
1103 Convert Big Endian to Little Endian
1104 @param value: value expressed in Big Endian
1105 @param size: number of bytes generated
1106 @return: a string containing the value converted
1109 data = [char for char in value]
1111 return int("".join(["%2.2X"%ord(char) for char in data]), 16)
1113 def LE_to_BE(value, size):
1115 Convert Little Endian to Big Endian
1116 @param value: value expressed in integer
1117 @param size: number of bytes generated
1118 @return: a string containing the value converted
1121 data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
1122 list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
1124 return "".join([chr(int(car, 16)) for car in list_car])