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 %d[(sub - 3)]", "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 Defined Default Parameters %d[(sub - 3)]", "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_IdenticalIndexes:
304 incr = mappingdictionary[base_index]["incr"]
307 if struct & OD_Subindex:
309 if struct & OD_IdenticalSubindexes:
311 infos = mappingdictionary[base_index]["values"][0].copy()
312 elif 0 < subIndex <= mappingdictionary[base_index]["values"][1]["nbmax"]:
313 infos = mappingdictionary[base_index]["values"][1].copy()
314 elif struct & OD_MultipleSubindexes:
316 for subindex_infos in mappingdictionary[base_index]["values"]:
317 if "nbmax" in subindex_infos:
318 if idx <= subIndex < idx + subindex_infos["nbmax"]:
319 infos = subindex_infos.copy()
321 idx += subindex_infos["nbmax"]
324 infos = subindex_infos.copy()
328 infos = mappingdictionary[base_index]["values"][0].copy()
329 if infos is not None:
330 infos["name"] = StringFormat(infos["name"], (index - base_index) / incr + 1, subIndex)
335 Return the list of variables that can be mapped defined in mappingdictionary
337 def FindMapVariableList(mappingdictionary, Node):
339 for index in mappingdictionary.iterkeys():
340 if Node.IsEntry(index):
341 for subIndex, values in enumerate(mappingdictionary[index]["values"]):
342 if mappingdictionary[index]["values"][subIndex]["pdo"]:
343 infos = Node.GetEntryInfos(mappingdictionary[index]["values"][subIndex]["type"])
344 if mappingdictionary[index]["struct"] & OD_IdenticalSubindexes:
345 values = Node.GetEntry(index)
346 for i in xrange(len(values) - 1):
347 list.append((index, i + 1, infos["size"], StringFormat(mappingdictionary[index]["values"][subIndex]["name"],1,i+1)))
349 list.append((index, subIndex, infos["size"], mappingdictionary[index]["values"][subIndex]["name"]))
353 Return the list of mandatory indexes defined in mappingdictionary
355 def FindMandatoryIndexes(mappingdictionary):
357 for index in mappingdictionary.iterkeys():
358 if index >= 0x1000 and mappingdictionary[index]["need"]:
363 Return the index of the informations in the Object Dictionary in case of identical
366 def FindIndex(index, mappingdictionary):
367 if index in mappingdictionary:
370 listpluri = [idx for idx in mappingdictionary.keys() if mappingdictionary[idx]["struct"] & OD_IdenticalIndexes]
372 for idx in listpluri:
373 nb_max = mappingdictionary[idx]["nbmax"]
374 incr = mappingdictionary[idx]["incr"]
375 if idx < index < idx + incr * nb_max and (index - idx)%incr == 0:
379 #-------------------------------------------------------------------------------
380 # Formating Name of an Entry
381 #-------------------------------------------------------------------------------
383 name_model = re.compile('(.*)\[(.*)\]')
386 Format the text given with the index and subindex defined
388 def StringFormat(text, idx, sub):
389 result = name_model.match(text)
391 format = result.groups()
392 return format[0]%eval(format[1])
396 #-------------------------------------------------------------------------------
397 # Definition of Node Object
398 #-------------------------------------------------------------------------------
401 Class recording the Object Dictionary entries. It checks at each modification
402 that the structure of the Object Dictionary stay coherent
407 DefaultStringSize = 10
409 def __init__(self, name = "", type = "slave", id = 0, description = "", profilename = "DS-301", profile = {}, specificmenu = []):
413 self.Description = description
414 self.ProfileName = profilename
415 self.Profile = profile
416 self.SpecificMenu = specificmenu
418 self.ParamsDictionary = {}
420 self.UserMapping = {}
425 def GetNodeName(self):
431 def SetNodeName(self, name):
435 Return the node type ("master" or "slave")
437 def GetNodeType(self):
441 Define the node type ("master" or "slave")
443 def SetNodeType(self, type):
455 def SetNodeID(self, id):
459 Return the node description
461 def GetNodeDescription(self):
462 if getattr(self, "Description", False):
463 return self.Description
468 Define the node description
470 def SetNodeDescription(self, description):
471 self.Description = description
474 Return the Specific Profile Name
476 def GetProfileName(self):
477 return self.ProfileName
480 Define the Specific Profile Name
482 def SetProfileName(self, profilename):
483 self.ProfileName = profilename
486 Return the Specific Profile
488 def GetProfile(self):
492 Define the Specific Profile
494 def SetProfile(self, profile):
495 self.Profile = profile
498 Return the default string size
500 def GetDefaultStringSize(self):
501 return self.DefaultStringSize
504 Define the default string size
506 def SetDefaultStringSize(self, size):
507 self.DefaultStringSize = size
510 Define the DS-302 Profile
512 def SetDS302Profile(self, profile):
516 Define the DS-302 Profile
518 def GetDS302Profile(self):
522 Return the Specific Menu Entries
524 def GetSpecificMenu(self):
525 return self.SpecificMenu
528 Define the Specific Menu Entries
530 def SetSpecificMenu(self, specificmenu):
531 self.SpecificMenu = specificmenu
534 Extend the Specific Menu Entries
537 def ExtendSpecificMenu(self, specificmenu):
538 self.SpecificMenu.extend(specificmenu)
541 Function which return the different Mappings available for this node
543 def GetMappings(self, userdefinedtoo = True):
545 return [self.Profile, self.DS302, self.UserMapping]
547 return [self.Profile, self.DS302]
550 Add a new entry in the Object Dictionary
552 def AddEntry(self, index, subIndex = None, value = None):
553 if index not in self.Dictionary:
555 self.Dictionary[index] = value
558 self.Dictionary[index] = [value]
560 elif subIndex > 0 and type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]) + 1:
561 self.Dictionary[index].append(value)
566 Warning ! Modifies an existing entry in the Object Dictionary. Can't add a new one.
568 def SetEntry(self, index, subIndex = None, value = None):
569 if index in self.Dictionary:
572 self.Dictionary[index] = value
574 elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
576 self.Dictionary[index][subIndex - 1] = value
580 def SetParamsEntry(self, index, subIndex = None, comment = None, save = None, callback = None):
581 if not getattr(self, "ParamsDictionary", False):
582 self.ParamsDictionary = {}
583 if index in self.Dictionary:
584 if (comment != None or save != None or callback != None) and index not in self.ParamsDictionary:
585 self.ParamsDictionary[index] = {}
586 if subIndex == None or type(self.Dictionary[index]) != ListType and subIndex == 0:
588 self.ParamsDictionary[index]["comment"] = comment
590 self.ParamsDictionary[index]["save"] = save
592 self.ParamsDictionary[index]["callback"] = callback
594 elif type(self.Dictionary[index]) == ListType and 0 <= subIndex <= len(self.Dictionary[index]):
595 if (comment != None or save != None or callback != None) and subIndex not in self.ParamsDictionary[index]:
596 self.ParamsDictionary[index][subIndex] = {}
598 self.ParamsDictionary[index][subIndex]["comment"] = comment
600 self.ParamsDictionary[index][subIndex]["save"] = save
605 Removes an existing entry in the Object Dictionary. If a subIndex is specified
606 it will remove this subIndex only if it's the last of the index. If no subIndex
607 is specified it removes the whole index and subIndexes from the Object Dictionary.
609 def RemoveEntry(self, index, subIndex = None):
610 if not getattr(self, "ParamsDictionary", False):
611 self.ParamsDictionary = {}
612 if index in self.Dictionary:
614 self.Dictionary.pop(index)
615 if index in self.ParamsDictionary:
616 self.ParamsDictionary.pop(index)
618 elif type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]):
619 self.Dictionary[index].pop(subIndex - 1)
620 if index in self.ParamsDictionary:
621 if subIndex in self.ParamsDictionary[index]:
622 self.ParamsDictionary[index].pop(subIndex)
623 if len(self.ParamsDictionary[index]) == 0:
624 self.ParamsDictionary.pop(index)
625 if len(self.Dictionary[index]) == 0:
626 self.Dictionary.pop(index)
627 if index in self.ParamsDictionary:
628 self.ParamsDictionary.pop(index)
633 Check if an entry exists in the Object Dictionary and returns the answer.
635 def IsEntry(self, index, subIndex = None):
636 if index in self.Dictionary:
639 return subIndex <= len(self.Dictionary[index])
643 Returns the value of the entry asked. If the entry has the value "count", it
644 returns the number of subIndex in the entry except the first.
646 def GetEntry(self, index, subIndex = None, compute = True):
647 if index in self.Dictionary:
649 if type(self.Dictionary[index]) == ListType:
650 values = [len(self.Dictionary[index])]
651 for value in self.Dictionary[index]:
652 values.append(self.CompileValue(value, index, compute))
655 return self.CompileValue(self.Dictionary[index], index, compute)
657 if type(self.Dictionary[index]) == ListType:
658 return len(self.Dictionary[index])
660 return self.CompileValue(self.Dictionary[index], index, compute)
661 elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
662 return self.CompileValue(self.Dictionary[index][subIndex - 1], index, compute)
666 Returns the value of the entry asked. If the entry has the value "count", it
667 returns the number of subIndex in the entry except the first.
669 def GetParamsEntry(self, index, subIndex = None):
670 if not getattr(self, "ParamsDictionary", False):
671 self.ParamsDictionary = {}
672 if index in self.Dictionary:
674 if type(self.Dictionary[index]) == ListType:
675 if index in self.ParamsDictionary:
677 for i in xrange(len(self.Dictionary[index]) + 1):
678 line = DefaultParams.copy()
679 if i in self.ParamsDictionary[index]:
680 line.update(self.ParamsDictionary[index][i])
684 return [DefaultParams.copy() for i in xrange(len(self.Dictionary[index]) + 1)]
686 result = DefaultParams.copy()
687 if index in self.ParamsDictionary:
688 result.update(self.ParamsDictionary[index])
690 elif subIndex == 0 and type(self.Dictionary[index]) != ListType:
691 result = DefaultParams.copy()
692 if index in self.ParamsDictionary:
693 result.update(self.ParamsDictionary[index])
695 elif type(self.Dictionary[index]) == ListType and 0 <= subIndex <= len(self.Dictionary[index]):
696 result = DefaultParams.copy()
697 if index in self.ParamsDictionary and subIndex in self.ParamsDictionary[index]:
698 result.update(self.ParamsDictionary[index][subIndex])
702 def HasEntryCallbacks(self, index):
703 entry_infos = self.GetEntryInfos(index)
704 if entry_infos and "callback" in entry_infos:
705 return entry_infos["callback"]
707 if not getattr(self, "ParamsDictionary", False):
708 self.ParamsDictionary = {}
709 if index in self.Dictionary and index in self.ParamsDictionary and "callback" in self.ParamsDictionary[index]:
710 return self.ParamsDictionary[index]["callback"]
714 Check if an entry exists in the User Mapping Dictionary and returns the answer.
716 def IsMappingEntry(self, index):
717 if index in self.UserMapping:
722 Add a new entry in the User Mapping Dictionary
724 def AddMappingEntry(self, index, subIndex = None, name = "Undefined", struct = 0, size = None, nbmax = None, default = None, values = None):
725 if index not in self.UserMapping:
729 self.UserMapping[index] = {"name" : name, "struct" : struct, "need" : False, "values" : values}
731 self.UserMapping[index]["size"] = size
733 self.UserMapping[index]["nbmax"] = nbmax
735 self.UserMapping[index]["default"] = default
737 elif subIndex != None and subIndex == len(self.UserMapping[index]["values"]):
740 self.UserMapping[index]["values"].append(values)
745 Warning ! Modifies an existing entry in the User Mapping Dictionary. Can't add a new one.
747 def SetMappingEntry(self, index, subIndex = None, name = None, struct = None, size = None, nbmax = None, default = None, values = None):
748 if index in self.UserMapping:
751 self.UserMapping[index]["name"] = name
752 if self.UserMapping[index]["struct"] & OD_IdenticalSubindexes:
753 self.UserMapping[index]["values"][1]["name"] = name + " %d[(sub)]"
754 elif not self.UserMapping[index]["struct"] & OD_MultipleSubindexes:
755 self.UserMapping[index]["values"][0]["name"] = name
757 self.UserMapping[index]["struct"] = struct
759 self.UserMapping[index]["size"] = size
761 self.UserMapping[index]["nbmax"] = nbmax
763 self.UserMapping[index]["default"] = default
765 self.UserMapping[index]["values"] = values
767 elif 0 <= subIndex < len(self.UserMapping[index]["values"]) and values != None:
769 if self.UserMapping[index]["struct"] & OD_IdenticalSubindexes:
770 if self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
771 if self.IsRealType(values["type"]):
772 for i in xrange(len(self.Dictionary[index])):
773 self.SetEntry(index, i + 1, 0.)
774 elif not self.IsStringType(values["type"]):
775 for i in xrange(len(self.Dictionary[index])):
776 self.SetEntry(index, i + 1, 0)
777 elif self.IsRealType(self.UserMapping[index]["values"][subIndex]["type"]):
778 if self.IsStringType(values["type"]):
779 for i in xrange(len(self.Dictionary[index])):
780 self.SetEntry(index, i + 1, "")
781 elif not self.IsRealType(values["type"]):
782 for i in xrange(len(self.Dictionary[index])):
783 self.SetEntry(index, i + 1, 0)
784 elif self.IsStringType(values["type"]):
785 for i in xrange(len(self.Dictionary[index])):
786 self.SetEntry(index, i + 1, "")
787 elif self.IsRealType(values["type"]):
788 for i in xrange(len(self.Dictionary[index])):
789 self.SetEntry(index, i + 1, 0.)
791 if self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
792 if self.IsRealType(values["type"]):
793 self.SetEntry(index, subIndex, 0.)
794 elif not self.IsStringType(values["type"]):
795 self.SetEntry(index, subIndex, 0)
796 elif self.IsRealType(self.UserMapping[index]["values"][subIndex]["type"]):
797 if self.IsStringType(values["type"]):
798 self.SetEntry(index, subIndex, "")
799 elif not self.IsRealType(values["type"]):
800 self.SetEntry(index, subIndex, 0)
801 elif self.IsStringType(values["type"]):
802 self.SetEntry(index, subIndex, "")
803 elif self.IsRealType(values["type"]):
804 self.SetEntry(index, subIndex, 0.)
805 self.UserMapping[index]["values"][subIndex].update(values)
810 Removes an existing entry in the User Mapping Dictionary. If a subIndex is specified
811 it will remove this subIndex only if it's the last of the index. If no subIndex
812 is specified it removes the whole index and subIndexes from the User Mapping Dictionary.
814 def RemoveMappingEntry(self, index, subIndex = None):
815 if index in self.UserMapping:
817 self.UserMapping.pop(index)
819 elif subIndex == len(self.UserMapping[index]["values"]) - 1:
820 self.UserMapping[index]["values"].pop(subIndex)
824 def RemoveMapVariable(self, index, subIndex = None):
828 model += subIndex << 8
830 for i in self.Dictionary.iterkeys():
831 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
832 for j,value in enumerate(self.Dictionary[i]):
833 if (value & mask) == model:
834 self.Dictionary[i][j] = 0
836 def UpdateMapVariable(self, index, subIndex, size):
840 model += subIndex << 8
842 for i in self.Dictionary.iterkeys():
843 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
844 for j,value in enumerate(self.Dictionary[i]):
845 if (value & mask) == model:
846 self.Dictionary[i][j] = model + size
848 def RemoveLine(self, index, max, incr = 1):
850 while i < max and self.IsEntry(i + incr):
851 self.Dictionary[i] = self.Dictionary[i + incr]
853 self.Dictionary.pop(i)
855 def RemoveUserType(self, index):
856 type = self.GetEntry(index, 1)
857 for i in self.UserMapping:
858 for value in self.UserMapping[i]["values"]:
859 if value["type"] == index:
861 self.RemoveMappingEntry(index)
862 self.RemoveEntry(index)
865 Return a copy of the node
868 return cPickle.loads(cPickle.dumps(self))
871 Return a sorted list of indexes in Object Dictionary
873 def GetIndexes(self):
874 listindex = self.Dictionary.keys()
879 Print the Dictionary values
882 print self.PrintString()
884 def PrintString(self):
886 listindex = self.Dictionary.keys()
888 for index in listindex:
889 name = self.GetEntryName(index)
890 values = self.Dictionary[index]
891 if isinstance(values, ListType):
892 result += "%04X (%s):\n"%(index, name)
893 for subidx, value in enumerate(values):
894 subentry_infos = self.GetSubentryInfos(index, subidx + 1)
895 if index == 0x1F22 and value:
896 nb_params = BE_to_LE(value[:4])
898 value = "%d arg defined"%nb_params
902 value += "\n%04X %02X, arg %d: "%(index, subidx+1, count)
903 value += "%04X"%BE_to_LE(data[i:i+2])
904 value += " %02X"%BE_to_LE(data[i+2:i+3])
905 size = BE_to_LE(data[i+3:i+7])
906 value += " %08X"%size
907 value += (" %0"+"%d"%(size * 2)+"X")%BE_to_LE(data[i+7:i+7+size])
910 elif isinstance(value, IntType):
912 result += "%04X %02X (%s): %s\n"%(index, subidx+1, subentry_infos["name"], value)
914 if isinstance(values, IntType):
916 result += "%04X (%s): %s\n"%(index, name, values)
919 def CompileValue(self, value, index, compute = True):
920 if isinstance(value, (StringType, UnicodeType)) and value.find("$NODEID") != -1:
921 base = self.GetBaseIndex(index)
925 return eval(raw.upper().replace("$NODEID","self.ID"))
932 #-------------------------------------------------------------------------------
933 # Node Informations Functions
934 #-------------------------------------------------------------------------------
936 def GetBaseIndex(self, index):
937 for mapping in self.GetMappings():
938 result = FindIndex(index, mapping)
940 return (index - result) / mapping[result].get("incr", 1)
941 result = FindIndex(index, MappingDictionary)
943 return (index - result) / MappingDictionary[result].get("incr", 1)
946 def GetCustomisedTypeValues(self, index):
947 values = self.GetEntry(index)
948 customisabletypes = self.GetCustomisableTypes()
949 return values, customisabletypes[values[1]][1]
951 def GetEntryName(self, index):
953 mappings = self.GetMappings()
955 while not result and i < len(mappings):
956 result = FindEntryName(index, mappings[i])
959 result = FindEntryName(index, MappingDictionary)
962 def GetEntryInfos(self, index):
964 mappings = self.GetMappings()
966 while not result and i < len(mappings):
967 result = FindEntryInfos(index, mappings[i])
970 result = FindEntryInfos(index, MappingDictionary)
973 def GetSubentryInfos(self, index, subIndex):
975 mappings = self.GetMappings()
977 while not result and i < len(mappings):
978 result = FindSubentryInfos(index, subIndex, mappings[i])
980 result["user_defined"] = i == len(mappings) - 1 and index >= 0x1000
983 result = FindSubentryInfos(index, subIndex, MappingDictionary)
985 result["user_defined"] = False
988 def GetTypeIndex(self, typename):
990 mappings = self.GetMappings()
992 while not result and i < len(mappings):
993 result = FindTypeIndex(typename, mappings[i])
996 result = FindTypeIndex(typename, MappingDictionary)
999 def GetTypeName(self, typeindex):
1001 mappings = self.GetMappings()
1003 while not result and i < len(mappings):
1004 result = FindTypeName(typeindex, mappings[i])
1007 result = FindTypeName(typeindex, MappingDictionary)
1010 def GetTypeDefaultValue(self, typeindex):
1012 mappings = self.GetMappings()
1014 while not result and i < len(mappings):
1015 result = FindTypeDefaultValue(typeindex, mappings[i])
1018 result = FindTypeDefaultValue(typeindex, MappingDictionary)
1021 def GetMapVariableList(self):
1022 list = FindMapVariableList(MappingDictionary, self)
1023 for mapping in self.GetMappings():
1024 list.extend(FindMapVariableList(mapping, self))
1028 def GetMandatoryIndexes(self, node = None):
1029 list = FindMandatoryIndexes(MappingDictionary)
1030 for mapping in self.GetMappings():
1031 list.extend(FindMandatoryIndexes(mapping))
1034 def GetCustomisableTypes(self):
1036 for index, valuetype in CustomisableTypes:
1037 name = self.GetTypeName(index)
1038 dic[index] = [name, valuetype]
1041 #-------------------------------------------------------------------------------
1042 # Type helper functions
1043 #-------------------------------------------------------------------------------
1045 def IsStringType(self, index):
1046 if index in (0x9, 0xA, 0xB, 0xF):
1048 elif 0xA0 <= index < 0x100:
1049 result = self.GetEntry(index, 1)
1050 if result is not None and result in (0x9, 0xA, 0xB):
1054 def IsRealType(self, index):
1055 if index in (0x8, 0x11):
1057 elif 0xA0 <= index < 0x100:
1058 result = self.GetEntry(index, 1)
1059 if result is not None and result in (0x8, 0x11):
1063 #-------------------------------------------------------------------------------
1064 # Type and Map Variable Lists
1065 #-------------------------------------------------------------------------------
1067 def GetTypeList(self):
1068 list = FindTypeList(MappingDictionary)
1069 for mapping in self.GetMappings():
1070 list.extend(FindTypeList(mapping))
1072 return ",".join(list)
1075 Generate the list of variables that can be mapped for the current node
1077 def GenerateMapList(self):
1078 self.MapList = "None"
1079 self.NameTranslation = {"None" : "00000000"}
1080 self.MapTranslation = {"00000000" : "None"}
1081 list = self.GetMapVariableList()
1082 for index, subIndex, size, name in list:
1083 self.MapList += ",%s"%name
1084 map = "%04X%02X%02X"%(index,subIndex,size)
1085 self.NameTranslation[name] = map
1086 self.MapTranslation[map] = name
1088 def GetMapValue(self, mapname):
1089 if mapname == "None":
1092 list = self.GetMapVariableList()
1093 for index, subIndex, size, name in list:
1095 return (index << 16) + (subIndex << 8) + size
1098 def GetMapName(self, value):
1101 subindex = (value >> 8) % (1 << 8)
1102 result = self.GetSubentryInfos(index, subindex)
1104 return result["name"]
1108 Return the list of variables that can be mapped for the current node
1110 def GetMapList(self):
1111 list = ["None"] + [name for index, subIndex, size, name in self.GetMapVariableList()]
1112 return ",".join(list)
1114 def BE_to_LE(value):
1116 Convert Big Endian to Little Endian
1117 @param value: value expressed in Big Endian
1118 @param size: number of bytes generated
1119 @return: a string containing the value converted
1122 data = [char for char in value]
1124 return int("".join(["%2.2X"%ord(char) for char in data]), 16)
1126 def LE_to_BE(value, size):
1128 Convert Little Endian to Big Endian
1129 @param value: value expressed in integer
1130 @param size: number of bytes generated
1131 @return: a string containing the value converted
1134 data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
1135 list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
1137 return "".join([chr(int(car, 16)) for car in list_car])