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.IsStringType(values["type"]) and not self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
757 self.SetEntry(index, subIndex, "")
758 elif not self.IsStringType(values["type"]) and self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
759 self.SetEntry(index, subIndex, 0)
760 self.UserMapping[index]["values"][subIndex].update(values)
765 Removes an existing entry in the User Mapping Dictionary. If a subIndex is specified
766 it will remove this subIndex only if it's the last of the index. If no subIndex
767 is specified it removes the whole index and subIndexes from the User Mapping Dictionary.
769 def RemoveMappingEntry(self, index, subIndex = None):
770 if index in self.UserMapping:
772 self.UserMapping.pop(index)
774 elif subIndex == len(self.UserMapping[index]["values"]) - 1:
775 self.UserMapping[index]["values"].pop(subIndex)
779 def RemoveMapVariable(self, index, subIndex = None):
783 model += subIndex << 8
785 for i in self.Dictionary.iterkeys():
786 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
787 for j,value in enumerate(self.Dictionary[i]):
788 if (value & mask) == model:
789 self.Dictionary[i][j] = 0
791 def UpdateMapVariable(self, index, subIndex, size):
795 model += subIndex << 8
797 for i in self.Dictionary.iterkeys():
798 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
799 for j,value in enumerate(self.Dictionary[i]):
800 if (value & mask) == model:
801 self.Dictionary[i][j] = model + size
803 def RemoveLine(self, index, max, incr = 1):
805 while i < max and self.IsEntry(i + incr):
806 self.Dictionary[i] = self.Dictionary[i + incr]
808 self.Dictionary.pop(i)
810 def RemoveUserType(self, index):
811 type = self.GetEntry(index, 1)
812 for i in self.UserMapping:
813 for value in self.UserMapping[i]["values"]:
814 if value["type"] == index:
816 self.RemoveMappingEntry(index)
817 self.RemoveEntry(index)
820 Return a copy of the node
823 return cPickle.loads(cPickle.dumps(self))
826 Return a sorted list of indexes in Object Dictionary
828 def GetIndexes(self):
829 listindex = self.Dictionary.keys()
834 Print the Dictionary values
837 print self.PrintString()
839 def PrintString(self):
841 listindex = self.Dictionary.keys()
843 for index in listindex:
844 name = self.GetEntryName(index)
845 values = self.Dictionary[index]
846 if isinstance(values, ListType):
847 result += "%04X (%s):\n"%(index, name)
848 for subidx, value in enumerate(values):
849 subentry_infos = self.GetSubentryInfos(index, subidx + 1)
850 if index == 0x1F22 and value:
851 nb_params = BE_to_LE(value[:4])
853 value = "%d arg defined"%nb_params
857 value += "\n%04X %02X, arg %d: "%(index, subidx+1, count)
858 value += "%04X"%BE_to_LE(data[i:i+2])
859 value += " %02X"%BE_to_LE(data[i+2:i+3])
860 size = BE_to_LE(data[i+3:i+7])
861 value += " %08X"%size
862 value += (" %0"+"%d"%(size * 2)+"X")%BE_to_LE(data[i+7:i+7+size])
865 elif isinstance(value, IntType):
867 result += "%04X %02X (%s): %s\n"%(index, subidx+1, subentry_infos["name"], value)
869 if isinstance(values, IntType):
871 result += "%04X (%s): %s\n"%(index, name, values)
874 def CompileValue(self, value, index, compute = True):
875 if type(value) == StringType and value.find("$NODEID") != -1:
876 base = self.GetBaseIndex(index)
880 return eval(raw.replace("$NODEID","self.ID"))
887 #-------------------------------------------------------------------------------
888 # Node Informations Functions
889 #-------------------------------------------------------------------------------
891 def GetBaseIndex(self, index):
892 for mapping in self.GetMappings():
893 result = FindIndex(index, mapping)
895 return (index - result) / mapping[result].get("incr", 1)
896 result = FindIndex(index, MappingDictionary)
898 return (index - result) / MappingDictionary[result].get("incr", 1)
901 def GetCustomisedTypeValues(self, index):
902 values = self.GetEntry(index)
903 customisabletypes = self.GetCustomisableTypes()
904 return values, customisabletypes[values[1]][1]
906 def GetEntryName(self, index):
908 mappings = self.GetMappings()
910 while not result and i < len(mappings):
911 result = FindEntryName(index, mappings[i])
914 result = FindEntryName(index, MappingDictionary)
917 def GetEntryInfos(self, index):
919 mappings = self.GetMappings()
921 while not result and i < len(mappings):
922 result = FindEntryInfos(index, mappings[i])
925 result = FindEntryInfos(index, MappingDictionary)
928 def GetSubentryInfos(self, index, subIndex):
930 mappings = self.GetMappings()
932 while not result and i < len(mappings):
933 result = FindSubentryInfos(index, subIndex, mappings[i])
935 result["user_defined"] = i == len(mappings) - 1 and index >= 0x1000
938 result = FindSubentryInfos(index, subIndex, MappingDictionary)
940 result["user_defined"] = False
943 def GetTypeIndex(self, typename):
945 mappings = self.GetMappings()
947 while not result and i < len(mappings):
948 result = FindTypeIndex(typename, mappings[i])
951 result = FindTypeIndex(typename, MappingDictionary)
954 def GetTypeName(self, typeindex):
956 mappings = self.GetMappings()
958 while not result and i < len(mappings):
959 result = FindTypeName(typeindex, mappings[i])
962 result = FindTypeName(typeindex, MappingDictionary)
965 def GetTypeDefaultValue(self, typeindex):
967 mappings = self.GetMappings()
969 while not result and i < len(mappings):
970 result = FindTypeDefaultValue(typeindex, mappings[i])
973 result = FindTypeDefaultValue(typeindex, MappingDictionary)
976 def GetMapVariableList(self):
977 list = FindMapVariableList(MappingDictionary, self)
978 for mapping in self.GetMappings():
979 list.extend(FindMapVariableList(mapping, self))
983 def GetMandatoryIndexes(self, node = None):
984 list = FindMandatoryIndexes(MappingDictionary)
985 for mapping in self.GetMappings():
986 list.extend(FindMandatoryIndexes(mapping))
989 def GetCustomisableTypes(self):
991 for index, valuetype in CustomisableTypes:
992 name = self.GetTypeName(index)
993 dic[index] = [name, valuetype]
996 #-------------------------------------------------------------------------------
997 # Type helper functions
998 #-------------------------------------------------------------------------------
1000 def IsStringType(self, index):
1001 if index in (0x9, 0xA, 0xB):
1003 elif 0xA0 <= index < 0x100:
1004 result = self.GetEntry(index, 1)
1005 if result is not None and result in (0x9, 0xA, 0xB):
1009 #-------------------------------------------------------------------------------
1010 # Type and Map Variable Lists
1011 #-------------------------------------------------------------------------------
1013 def GetTypeList(self):
1014 list = FindTypeList(MappingDictionary)
1015 for mapping in self.GetMappings():
1016 list.extend(FindTypeList(mapping))
1018 return ",".join(list)
1021 Generate the list of variables that can be mapped for the current node
1023 def GenerateMapList(self):
1024 self.MapList = "None"
1025 self.NameTranslation = {"None" : "00000000"}
1026 self.MapTranslation = {"00000000" : "None"}
1027 list = self.GetMapVariableList()
1028 for index, subIndex, size, name in list:
1029 self.MapList += ",%s"%name
1030 map = "%04X%02X%02X"%(index,subIndex,size)
1031 self.NameTranslation[name] = map
1032 self.MapTranslation[map] = name
1034 def GetMapValue(self, mapname):
1035 if mapname == "None":
1038 list = self.GetMapVariableList()
1039 for index, subIndex, size, name in list:
1041 return (index << 16) + (subIndex << 8) + size
1044 def GetMapName(self, value):
1047 subindex = (value >> 8) % (1 << 8)
1048 result = self.GetSubentryInfos(index, subindex)
1050 return result["name"]
1054 Return the list of variables that can be mapped for the current node
1056 def GetMapList(self):
1057 list = ["None"] + [name for index, subIndex, size, name in self.GetMapVariableList()]
1058 return ",".join(list)
1060 def BE_to_LE(value):
1062 Convert Big Endian to Little Endian
1063 @param value: value expressed in Big Endian
1064 @param size: number of bytes generated
1065 @return: a string containing the value converted
1068 data = [char for char in value]
1070 return int("".join(["%2.2X"%ord(char) for char in data]), 16)
1072 def LE_to_BE(value, size):
1074 Convert Little Endian to Big Endian
1075 @param value: value expressed in integer
1076 @param size: number of bytes generated
1077 @return: a string containing the value converted
1080 data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
1081 list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
1083 return "".join([chr(int(car, 16)) for car in list_car])