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)
63 # Entries identical on multiple indexes
65 pluriarray = 11 # Example : PDO Parameters
66 plurirec = 15 # 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" : True, "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" : 0x04, "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 if not getattr(self, "ParamsDictionary", False):
677 self.ParamsDictionary = {}
678 if index in self.Dictionary and index in self.ParamsDictionary and "callback" in self.ParamsDictionary[index]:
679 return self.ParamsDictionary[index]["callback"]
683 Check if an entry exists in the User Mapping Dictionary and returns the answer.
685 def IsMappingEntry(self, index):
686 if index in self.UserMapping:
691 Add a new entry in the User Mapping Dictionary
693 def AddMappingEntry(self, index, subIndex = None, name = "Undefined", struct = 0, size = None, nbmax = None, default = None, values = None):
694 if index not in self.UserMapping:
698 self.UserMapping[index] = {"name" : name, "struct" : struct, "need" : False, "values" : values}
700 self.UserMapping[index]["size"] = size
702 self.UserMapping[index]["nbmax"] = nbmax
704 self.UserMapping[index]["default"] = default
706 elif subIndex != None and subIndex == len(self.UserMapping[index]["values"]):
709 self.UserMapping[index]["values"].append(values)
714 Warning ! Modifies an existing entry in the User Mapping Dictionary. Can't add a new one.
716 def SetMappingEntry(self, index, subIndex = None, name = None, struct = None, size = None, nbmax = None, default = None, values = None):
717 if index in self.UserMapping:
720 self.UserMapping[index]["name"] = name
721 if self.UserMapping[index]["struct"] & OD_IdenticalSubindexes:
722 self.UserMapping[index]["values"][1]["name"] = name + " %d[(sub)]"
723 elif not self.UserMapping[index]["struct"] & OD_MultipleSubindexes:
724 self.UserMapping[index]["values"][0]["name"] = name
726 self.UserMapping[index]["struct"] = struct
728 self.UserMapping[index]["size"] = size
730 self.UserMapping[index]["nbmax"] = nbmax
732 self.UserMapping[index]["default"] = default
734 self.UserMapping[index]["values"] = values
736 elif 0 <= subIndex < len(self.UserMapping[index]["values"]) and values != None:
737 self.UserMapping[index]["values"][subIndex].update(values)
742 Removes an existing entry in the User Mapping Dictionary. If a subIndex is specified
743 it will remove this subIndex only if it's the last of the index. If no subIndex
744 is specified it removes the whole index and subIndexes from the User Mapping Dictionary.
746 def RemoveMappingEntry(self, index, subIndex = None):
747 if index in self.UserMapping:
749 self.UserMapping.pop(index)
751 elif subIndex == len(self.UserMapping[index]["values"]) - 1:
752 self.UserMapping[index]["values"].pop(subIndex)
756 def RemoveMapVariable(self, index, subIndex = None):
760 model += subIndex << 8
762 for i in self.Dictionary.iterkeys():
763 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
764 for j,value in enumerate(self.Dictionary[i]):
765 if (value & mask) == model:
766 self.Dictionary[i][j] = 0
768 def UpdateMapVariable(self, index, subIndex, size):
772 model += subIndex << 8
774 for i in self.Dictionary.iterkeys():
775 if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
776 for j,value in enumerate(self.Dictionary[i]):
777 if (value & mask) == model:
778 self.Dictionary[i][j] = model + size
780 def RemoveLine(self, index, max, incr = 1):
782 while i < max and self.IsEntry(i + incr):
783 self.Dictionary[i] = self.Dictionary[i + incr]
785 self.Dictionary.pop(i)
787 def RemoveUserType(self, index):
788 type = self.GetEntry(index, 1)
789 for i in self.UserMapping:
790 for value in self.UserMapping[i]["values"]:
791 if value["type"] == index:
793 self.RemoveMappingEntry(index)
794 self.RemoveEntry(index)
797 Return a copy of the node
800 return cPickle.loads(cPickle.dumps(self))
803 Return a sorted list of indexes in Object Dictionary
805 def GetIndexes(self):
806 listindex = self.Dictionary.keys()
811 Print the Dictionary values
814 listindex = self.Dictionary.keys()
816 for index in listindex:
817 values = self.Dictionary[index]
818 if index != 0x1F22 and type(values) != IntType:
819 values = [i for i in values]
820 for i, value in enumerate(values):
821 if type(value) == IntType:
822 values[i] = "%X"%value
823 values = "[" + ",".join(values) + "]"
824 print "%04X : %s"%(index, values)
826 def CompileValue(self, value, index):
827 if type(value) == StringType and value.find("self.ID") != -1:
828 base = self.GetBaseIndex(index)
836 #-------------------------------------------------------------------------------
837 # Node Informations Functions
838 #-------------------------------------------------------------------------------
840 def GetBaseIndex(self, index):
841 for mapping in self.GetMappings():
842 result = FindIndex(index, mapping)
844 return (index - result) / mapping[result].get("incr", 1)
845 result = FindIndex(index, MappingDictionary)
847 return (index - result) / MappingDictionary[result].get("incr", 1)
850 def GetCustomisedTypeValues(self, index):
851 values = self.GetEntry(index)
852 customisabletypes = self.GetCustomisableTypes()
853 return values, customisabletypes[values[1]][1]
855 def GetEntryName(self, index):
857 mappings = self.GetMappings()
859 while not result and i < len(mappings):
860 result = FindEntryName(index, mappings[i])
863 result = FindEntryName(index, MappingDictionary)
866 def GetEntryInfos(self, index):
868 mappings = self.GetMappings()
870 while not result and i < len(mappings):
871 result = FindEntryInfos(index, mappings[i])
874 result = FindEntryInfos(index, MappingDictionary)
877 def GetSubentryInfos(self, index, subIndex):
879 mappings = self.GetMappings()
881 while not result and i < len(mappings):
882 result = FindSubentryInfos(index, subIndex, mappings[i])
884 result["user_defined"] = i == len(mappings) - 1 and index >= 0x1000
887 result = FindSubentryInfos(index, subIndex, MappingDictionary)
889 result["user_defined"] = False
892 def GetTypeIndex(self, typename):
894 mappings = self.GetMappings()
896 while not result and i < len(mappings):
897 result = FindTypeIndex(typename, mappings[i])
900 result = FindTypeIndex(typename, MappingDictionary)
903 def GetTypeName(self, typeindex):
905 mappings = self.GetMappings()
907 while not result and i < len(mappings):
908 result = FindTypeName(typeindex, mappings[i])
911 result = FindTypeName(typeindex, MappingDictionary)
914 def GetTypeDefaultValue(self, typeindex):
916 mappings = self.GetMappings()
918 while not result and i < len(mappings):
919 result = FindTypeDefaultValue(typeindex, mappings[i])
922 result = FindTypeDefaultValue(typeindex, MappingDictionary)
925 def GetMapVariableList(self):
926 list = FindMapVariableList(MappingDictionary, self)
927 for mapping in self.GetMappings():
928 list.extend(FindMapVariableList(mapping, self))
932 def GetMandatoryIndexes(self, node = None):
933 list = FindMandatoryIndexes(MappingDictionary)
934 for mapping in self.GetMappings():
935 list.extend(FindMandatoryIndexes(mapping))
938 def GetCustomisableTypes(self):
940 for index, valuetype in CustomisableTypes:
941 name = self.GetTypeName(index)
942 dic[index] = [name, valuetype]
945 #-------------------------------------------------------------------------------
946 # Type and Map Variable Lists
947 #-------------------------------------------------------------------------------
949 def GetTypeList(self):
950 list = FindTypeList(MappingDictionary)
951 for mapping in self.GetMappings():
952 list.extend(FindTypeList(mapping))
954 return ",".join(list)
957 Generate the list of variables that can be mapped for the current node
959 def GenerateMapList(self):
960 self.MapList = "None"
961 self.NameTranslation = {"None" : "00000000"}
962 self.MapTranslation = {"00000000" : "None"}
963 list = self.GetMapVariableList()
964 for index, subIndex, size, name in list:
965 self.MapList += ",%s"%name
966 map = "%04X%02X%02X"%(index,subIndex,size)
967 self.NameTranslation[name] = map
968 self.MapTranslation[map] = name
970 def GetMapValue(self, mapname):
971 if mapname == "None":
974 list = self.GetMapVariableList()
975 for index, subIndex, size, name in list:
977 return (index << 16) + (subIndex << 8) + size
980 def GetMapName(self, value):
983 subindex = (value >> 8) % (1 << 8)
984 result = self.GetSubentryInfos(index, subindex)
986 return result["name"]
990 Return the list of variables that can be mapped for the current node
992 def GetMapList(self):
993 list = ["None"] + [name for index, subIndex, size, name in self.GetMapVariableList()]
994 return ",".join(list)