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, "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}]},
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, "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, "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, "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},
195 {"name" : "COB ID Server to Client (Transmit SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False}]},
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:self.ID+(base+2)*0x100,False:0}[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, "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:self.ID+(base+1)*0x100+0x80,False:0}[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, "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 def __init__(self, name = "", type = "slave", id = 0, description = "", profilename = "DS-301", profile = {}, specificmenu = []):
398 self.Description = description
399 self.ProfileName = profilename
400 self.Profile = profile
401 self.SpecificMenu = specificmenu
403 self.ParamsDictionary = {}
405 self.UserMapping = {}
410 def GetNodeName(self):
416 def SetNodeName(self, name):
420 Return the node type ("master" or "slave")
422 def GetNodeType(self):
426 Define the node type ("master" or "slave")
428 def SetNodeType(self, type):
440 def SetNodeID(self, id):
444 Return the node description
446 def GetNodeDescription(self):
447 if getattr(self, "Description", False):
448 return self.Description
453 Define the node description
455 def SetNodeDescription(self, description):
456 self.Description = description
459 Return the Specific Profile Name
461 def GetProfileName(self):
462 return self.ProfileName
465 Define the Specific Profile Name
467 def SetProfileName(self, profilename):
468 self.ProfileName = profilename
471 Return the Specific Profile
473 def GetProfile(self):
477 Define the Specific Profile
479 def SetProfile(self, profile):
480 self.Profile = profile
483 Define the DS-302 Profile
485 def SetDS302Profile(self, profile):
489 Define the DS-302 Profile
491 def GetDS302Profile(self):
495 Return the Specific Menu Entries
497 def GetSpecificMenu(self):
498 return self.SpecificMenu
501 Define the Specific Menu Entries
503 def SetSpecificMenu(self, specificmenu):
504 self.SpecificMenu = specificmenu
507 Extend the Specific Menu Entries
510 def ExtendSpecificMenu(self, specificmenu):
511 self.SpecificMenu.extend(specificmenu)
514 Function which return the different Mappings available for this node
516 def GetMappings(self, userdefinedtoo = True):
518 return [self.Profile, self.DS302, self.UserMapping]
520 return [self.Profile, self.DS302]
523 Add a new entry in the Object Dictionary
525 def AddEntry(self, index, subIndex = None, value = None):
526 if index not in self.Dictionary:
528 self.Dictionary[index] = value
531 self.Dictionary[index] = [value]
533 elif subIndex > 1 and type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]) + 1:
534 self.Dictionary[index].append(value)
539 Warning ! Modifies an existing entry in the Object Dictionary. Can't add a new one.
541 def SetEntry(self, index, subIndex = None, value = None):
542 if index in self.Dictionary:
545 self.Dictionary[index] = value
547 elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
549 self.Dictionary[index][subIndex - 1] = value
553 def SetParamsEntry(self, index, subIndex = None, comment = None, save = None, callback = None):
554 if not getattr(self, "ParamsDictionary", False):
555 self.ParamsDictionary = {}
556 if index in self.Dictionary:
557 if (comment != None or save != None or callback != None) and index not in self.ParamsDictionary:
558 self.ParamsDictionary[index] = {}
559 if subIndex == None or type(self.Dictionary[index]) != ListType and subIndex == 0:
561 self.ParamsDictionary[index]["comment"] = comment
563 self.ParamsDictionary[index]["save"] = save
565 self.ParamsDictionary[index]["callback"] = callback
567 elif type(self.Dictionary[index]) == ListType and 0 <= subIndex <= len(self.Dictionary[index]):
568 if (comment != None or save != None or callback != None) and subIndex not in self.ParamsDictionary[index]:
569 self.ParamsDictionary[index][subIndex] = {}
571 self.ParamsDictionary[index][subIndex]["comment"] = comment
573 self.ParamsDictionary[index][subIndex]["save"] = save
578 Removes an existing entry in the Object Dictionary. If a subIndex is specified
579 it will remove this subIndex only if it's the last of the index. If no subIndex
580 is specified it removes the whole index and subIndexes from the Object Dictionary.
582 def RemoveEntry(self, index, subIndex = None):
583 if not getattr(self, "ParamsDictionary", False):
584 self.ParamsDictionary = {}
585 if index in self.Dictionary:
587 self.Dictionary.pop(index)
588 if index in self.ParamsDictionary:
589 self.ParamsDictionary.pop(index)
591 elif type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]):
592 self.Dictionary[index].pop(subIndex - 1)
593 if index in self.ParamsDictionary:
594 if subIndex in self.ParamsDictionary[index]:
595 self.ParamsDictionary[index].pop(subIndex)
596 if len(self.ParamsDictionary[index]) == 0:
597 self.ParamsDictionary.pop(index)
598 if len(self.Dictionary[index]) == 0:
599 self.Dictionary.pop(index)
600 if index in self.ParamsDictionary:
601 self.ParamsDictionary.pop(index)
606 Check if an entry exists in the Object Dictionary and returns the answer.
608 def IsEntry(self, index, subIndex = None):
609 if index in self.Dictionary:
612 return subIndex <= len(self.Dictionary[index])
616 Returns the value of the entry asked. If the entry has the value "count", it
617 returns the number of subIndex in the entry except the first.
619 def GetEntry(self, index, subIndex = None):
620 if index in self.Dictionary:
622 if type(self.Dictionary[index]) == ListType:
623 values = [len(self.Dictionary[index])]
624 for value in self.Dictionary[index]:
625 values.append(self.CompileValue(value, index))
628 return self.CompileValue(self.Dictionary[index], index)
630 if type(self.Dictionary[index]) == ListType:
631 return len(self.Dictionary[index])
633 return self.CompileValue(self.Dictionary[index], index)
634 elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
635 return self.CompileValue(self.Dictionary[index][subIndex - 1], index)
639 Returns the value of the entry asked. If the entry has the value "count", it
640 returns the number of subIndex in the entry except the first.
642 def GetParamsEntry(self, index, subIndex = None):
643 if not getattr(self, "ParamsDictionary", False):
644 self.ParamsDictionary = {}
645 if index in self.Dictionary:
647 if type(self.Dictionary[index]) == ListType:
648 if index in self.ParamsDictionary:
650 for i in xrange(len(self.Dictionary[index]) + 1):
651 line = DefaultParams.copy()
652 if i in self.ParamsDictionary[index]:
653 line.update(self.ParamsDictionary[index][i])
657 return [DefaultParams.copy() for i in xrange(len(self.Dictionary[index]) + 1)]
659 result = DefaultParams.copy()
660 if index in self.ParamsDictionary:
661 result.update(self.ParamsDictionary[index])
663 elif subIndex == 0 and type(self.Dictionary[index]) != ListType:
664 result = DefaultParams.copy()
665 if index in self.ParamsDictionary:
666 result.update(self.ParamsDictionary[index])
668 elif type(self.Dictionary[index]) == ListType and 0 <= subIndex <= len(self.Dictionary[index]):
669 result = DefaultParams.copy()
670 if index in self.ParamsDictionary and subIndex in self.ParamsDictionary[index]:
671 result.update(self.ParamsDictionary[index][subIndex])
675 def HasEntryCallbacks(self, index):
676 entry_infos = self.GetEntryInfos(index)
677 if entry_infos and "callback" in entry_infos:
678 return entry_infos["callback"]
680 if not getattr(self, "ParamsDictionary", False):
681 self.ParamsDictionary = {}
682 if index in self.Dictionary and index in self.ParamsDictionary and "callback" in self.ParamsDictionary[index]:
683 return self.ParamsDictionary[index]["callback"]
687 Check if an entry exists in the User Mapping Dictionary and returns the answer.
689 def IsMappingEntry(self, index):
690 if index in self.UserMapping:
695 Add a new entry in the User Mapping Dictionary
697 def AddMappingEntry(self, index, subIndex = None, name = "Undefined", struct = 0, size = None, nbmax = None, default = None, values = None):
698 if index not in self.UserMapping:
702 self.UserMapping[index] = {"name" : name, "struct" : struct, "need" : False, "values" : values}
704 self.UserMapping[index]["size"] = size
706 self.UserMapping[index]["nbmax"] = nbmax
708 self.UserMapping[index]["default"] = default
710 elif subIndex != None and subIndex == len(self.UserMapping[index]["values"]):
713 self.UserMapping[index]["values"].append(values)
718 Warning ! Modifies an existing entry in the User Mapping Dictionary. Can't add a new one.
720 def SetMappingEntry(self, index, subIndex = None, name = None, struct = None, size = None, nbmax = None, default = None, values = None):
721 if index in self.UserMapping:
724 self.UserMapping[index]["name"] = name
725 if self.UserMapping[index]["struct"] & OD_IdenticalSubindexes:
726 self.UserMapping[index]["values"][1]["name"] = name + " %d[(sub)]"
727 elif not self.UserMapping[index]["struct"] & OD_MultipleSubindexes:
728 self.UserMapping[index]["values"][0]["name"] = name
730 self.UserMapping[index]["struct"] = struct
732 self.UserMapping[index]["size"] = size
734 self.UserMapping[index]["nbmax"] = nbmax
736 self.UserMapping[index]["default"] = default
738 self.UserMapping[index]["values"] = values
740 elif 0 <= subIndex < len(self.UserMapping[index]["values"]) and values != None:
742 if self.IsStringType(values["type"]) and not self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
743 self.SetEntry(index, subIndex, "")
744 elif not self.IsStringType(values["type"]) and self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
745 self.SetEntry(index, subIndex, 0)
746 self.UserMapping[index]["values"][subIndex].update(values)
751 Removes an existing entry in the User Mapping Dictionary. If a subIndex is specified
752 it will remove this subIndex only if it's the last of the index. If no subIndex
753 is specified it removes the whole index and subIndexes from the User Mapping Dictionary.
755 def RemoveMappingEntry(self, index, subIndex = None):
756 if index in self.UserMapping:
758 self.UserMapping.pop(index)
760 elif subIndex == len(self.UserMapping[index]["values"]) - 1:
761 self.UserMapping[index]["values"].pop(subIndex)
765 def RemoveMapVariable(self, index, subIndex = None):
769 model += subIndex << 8
771 for i in self.Dictionary.iterkeys():
772 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
773 for j,value in enumerate(self.Dictionary[i]):
774 if (value & mask) == model:
775 self.Dictionary[i][j] = 0
777 def UpdateMapVariable(self, index, subIndex, size):
781 model += subIndex << 8
783 for i in self.Dictionary.iterkeys():
784 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
785 for j,value in enumerate(self.Dictionary[i]):
786 if (value & mask) == model:
787 self.Dictionary[i][j] = model + size
789 def RemoveLine(self, index, max, incr = 1):
791 while i < max and self.IsEntry(i + incr):
792 self.Dictionary[i] = self.Dictionary[i + incr]
794 self.Dictionary.pop(i)
796 def RemoveUserType(self, index):
797 type = self.GetEntry(index, 1)
798 for i in self.UserMapping:
799 for value in self.UserMapping[i]["values"]:
800 if value["type"] == index:
802 self.RemoveMappingEntry(index)
803 self.RemoveEntry(index)
806 Return a copy of the node
809 return cPickle.loads(cPickle.dumps(self))
812 Return a sorted list of indexes in Object Dictionary
814 def GetIndexes(self):
815 listindex = self.Dictionary.keys()
820 Print the Dictionary values
823 print self.PrintString()
825 def PrintString(self):
827 listindex = self.Dictionary.keys()
829 for index in listindex:
830 name = self.GetEntryName(index)
831 values = self.Dictionary[index]
832 if isinstance(values, ListType):
833 result += "%04X (%s):\n"%(index, name)
834 for subidx, value in enumerate(values):
835 subentry_infos = self.GetSubentryInfos(index, subidx + 1)
836 if index == 0x1F22 and value:
837 nb_params = BE_to_LE(value[:4])
839 value = "%d arg defined"%nb_params
843 value += "\n%04X %02X, arg %d: "%(index, subidx+1, count)
844 value += "%04X"%BE_to_LE(data[i:i+2])
845 value += " %02X"%BE_to_LE(data[i+2:i+3])
846 size = BE_to_LE(data[i+3:i+7])
847 value += " %08X"%size
848 value += (" %0"+"%d"%(size * 2)+"X")%BE_to_LE(data[i+7:i+7+size])
851 elif isinstance(value, IntType):
853 result += "%04X %02X (%s): %s\n"%(index, subidx+1, subentry_infos["name"], value)
855 if isinstance(values, IntType):
857 result += "%04X (%s): %s\n"%(index, name, values)
860 def CompileValue(self, value, index):
861 if type(value) == StringType and value.find("self.ID") != -1:
862 base = self.GetBaseIndex(index)
870 #-------------------------------------------------------------------------------
871 # Node Informations Functions
872 #-------------------------------------------------------------------------------
874 def GetBaseIndex(self, index):
875 for mapping in self.GetMappings():
876 result = FindIndex(index, mapping)
878 return (index - result) / mapping[result].get("incr", 1)
879 result = FindIndex(index, MappingDictionary)
881 return (index - result) / MappingDictionary[result].get("incr", 1)
884 def GetCustomisedTypeValues(self, index):
885 values = self.GetEntry(index)
886 customisabletypes = self.GetCustomisableTypes()
887 return values, customisabletypes[values[1]][1]
889 def GetEntryName(self, index):
891 mappings = self.GetMappings()
893 while not result and i < len(mappings):
894 result = FindEntryName(index, mappings[i])
897 result = FindEntryName(index, MappingDictionary)
900 def GetEntryInfos(self, index):
902 mappings = self.GetMappings()
904 while not result and i < len(mappings):
905 result = FindEntryInfos(index, mappings[i])
908 result = FindEntryInfos(index, MappingDictionary)
911 def GetSubentryInfos(self, index, subIndex):
913 mappings = self.GetMappings()
915 while not result and i < len(mappings):
916 result = FindSubentryInfos(index, subIndex, mappings[i])
918 result["user_defined"] = i == len(mappings) - 1 and index >= 0x1000
921 result = FindSubentryInfos(index, subIndex, MappingDictionary)
923 result["user_defined"] = False
926 def GetTypeIndex(self, typename):
928 mappings = self.GetMappings()
930 while not result and i < len(mappings):
931 result = FindTypeIndex(typename, mappings[i])
934 result = FindTypeIndex(typename, MappingDictionary)
937 def GetTypeName(self, typeindex):
939 mappings = self.GetMappings()
941 while not result and i < len(mappings):
942 result = FindTypeName(typeindex, mappings[i])
945 result = FindTypeName(typeindex, MappingDictionary)
948 def GetTypeDefaultValue(self, typeindex):
950 mappings = self.GetMappings()
952 while not result and i < len(mappings):
953 result = FindTypeDefaultValue(typeindex, mappings[i])
956 result = FindTypeDefaultValue(typeindex, MappingDictionary)
959 def GetMapVariableList(self):
960 list = FindMapVariableList(MappingDictionary, self)
961 for mapping in self.GetMappings():
962 list.extend(FindMapVariableList(mapping, self))
966 def GetMandatoryIndexes(self, node = None):
967 list = FindMandatoryIndexes(MappingDictionary)
968 for mapping in self.GetMappings():
969 list.extend(FindMandatoryIndexes(mapping))
972 def GetCustomisableTypes(self):
974 for index, valuetype in CustomisableTypes:
975 name = self.GetTypeName(index)
976 dic[index] = [name, valuetype]
979 #-------------------------------------------------------------------------------
980 # Type helper functions
981 #-------------------------------------------------------------------------------
983 def IsStringType(self, index):
984 if index in (0x9, 0xA, 0xB):
986 elif 0xA0 <= index < 0x100:
987 result = self.GetEntry(index, 1)
988 if result is not None and result in (0x9, 0xA, 0xB):
992 #-------------------------------------------------------------------------------
993 # Type and Map Variable Lists
994 #-------------------------------------------------------------------------------
996 def GetTypeList(self):
997 list = FindTypeList(MappingDictionary)
998 for mapping in self.GetMappings():
999 list.extend(FindTypeList(mapping))
1001 return ",".join(list)
1004 Generate the list of variables that can be mapped for the current node
1006 def GenerateMapList(self):
1007 self.MapList = "None"
1008 self.NameTranslation = {"None" : "00000000"}
1009 self.MapTranslation = {"00000000" : "None"}
1010 list = self.GetMapVariableList()
1011 for index, subIndex, size, name in list:
1012 self.MapList += ",%s"%name
1013 map = "%04X%02X%02X"%(index,subIndex,size)
1014 self.NameTranslation[name] = map
1015 self.MapTranslation[map] = name
1017 def GetMapValue(self, mapname):
1018 if mapname == "None":
1021 list = self.GetMapVariableList()
1022 for index, subIndex, size, name in list:
1024 return (index << 16) + (subIndex << 8) + size
1027 def GetMapName(self, value):
1030 subindex = (value >> 8) % (1 << 8)
1031 result = self.GetSubentryInfos(index, subindex)
1033 return result["name"]
1037 Return the list of variables that can be mapped for the current node
1039 def GetMapList(self):
1040 list = ["None"] + [name for index, subIndex, size, name in self.GetMapVariableList()]
1041 return ",".join(list)
1043 def BE_to_LE(value):
1045 Convert Big Endian to Little Endian
1046 @param value: value expressed in Big Endian
1047 @param size: number of bytes generated
1048 @return: a string containing the value converted
1051 data = [char for char in value]
1053 return int("".join(["%2.2X"%ord(char) for char in data]), 16)