]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - objdictgen/node.py
Fixed some comments in sdo.c
[CanFestival-3.git] / objdictgen / node.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 #This file is part of CanFestival, a library implementing CanOpen Stack. 
5 #
6 #Copyright (C): Edouard TISSERANT, Francis DUPIN and Laurent BESSARD
7 #
8 #See COPYING file for copyrights details.
9 #
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.
14 #
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.
19 #
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
23
24 import cPickle
25 from types import *
26 import re
27
28 """
29 Dictionary of translation between access symbol and their signification
30 """
31 AccessType = {"ro" : "Read Only", "wo" : "Write Only", "rw" : "Read/Write"}
32
33 BoolType = {True : "True", False : "False"} 
34 OptionType = {True : "Yes", False : "No"}
35
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),
39     (0x1B, 0)]
40
41 DefaultParams = {"comment" : "", "save" : False}
42
43 #-------------------------------------------------------------------------------
44 #                      Dictionary Mapping and Organisation
45 #-------------------------------------------------------------------------------
46
47 """
48 Properties of entry structure in the Object Dictionary
49 """
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
54
55 """
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
58 """
59 nosub = 0 # Entry without subindex (only for type declaration)
60 var = OD_Subindex
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
67
68 """
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.
73 """
74
75 MappingDictionary = {
76     0x0001 : {"name" : "BOOLEAN", "struct" : nosub, "size" : 1, "default" : False, "values" : []},
77     0x0002 : {"name" : "INTEGER8", "struct" : nosub, "size" : 8, "default" : 0, "values" : []},
78     0x0003 : {"name" : "INTEGER16", "struct" : nosub, "size" : 16, "default" : 0, "values" : []},
79     0x0004 : {"name" : "INTEGER32", "struct" : nosub, "size" : 32, "default" : 0, "values" : []},
80     0x0005 : {"name" : "UNSIGNED8", "struct" : nosub, "size" : 8, "default" : 0, "values" : []},
81     0x0006 : {"name" : "UNSIGNED16", "struct" : nosub, "size" : 16, "default" : 0, "values" : []},
82     0x0007 : {"name" : "UNSIGNED32", "struct" : nosub, "size" : 32, "default" : 0, "values" : []},
83     0x0008 : {"name" : "REAL32", "struct" : nosub, "size" : 32, "default" : 0.0, "values" : []},
84     0x0009 : {"name" : "VISIBLE_STRING", "struct" : nosub, "size" : 8, "default" : "", "values" : []},
85     0x000A : {"name" : "OCTET_STRING", "struct" : nosub, "size" : 8, "default" : "", "values" : []},
86     0x000B : {"name" : "UNICODE_STRING", "struct" : nosub, "size" : 16, "default" : "", "values" : []},
87 #    0x000C : {"name" : "TIME_OF_DAY", "struct" : nosub, "size" : 48, "default" : 0, "values" : []},
88 #    0x000D : {"name" : "TIME_DIFFERENCE", "struct" : nosub, "size" : 48, "default" : 0, "values" : []},
89     0x000F : {"name" : "DOMAIN", "struct" : nosub, "size" : 0, "default" : "", "values" : []},
90     0x0010 : {"name" : "INTEGER24", "struct" : nosub, "size" : 24, "default" : 0, "values" : []},
91     0x0011 : {"name" : "REAL64", "struct" : nosub, "size" : 64, "default" : 0.0, "values" : []},
92     0x0012 : {"name" : "INTEGER40", "struct" : nosub, "size" : 40, "default" : 0, "values" : []},
93     0x0013 : {"name" : "INTEGER48", "struct" : nosub, "size" : 48, "default" : 0, "values" : []},
94     0x0014 : {"name" : "INTEGER56", "struct" : nosub, "size" : 56, "default" : 0, "values" : []},
95     0x0015 : {"name" : "INTEGER64", "struct" : nosub, "size" : 64, "default" : 0, "values" : []},
96     0x0016 : {"name" : "UNSIGNED24", "struct" : nosub, "size" : 24, "default" : 0, "values" : []},
97     0x0018 : {"name" : "UNSIGNED40", "struct" : nosub, "size" : 40, "default" : 0, "values" : []},
98     0x0019 : {"name" : "UNSIGNED48", "struct" : nosub, "size" : 48, "default" : 0, "values" : []},
99     0x001A : {"name" : "UNSIGNED56", "struct" : nosub, "size" : 56, "default" : 0, "values" : []},
100     0x001B : {"name" : "UNSIGNED64", "struct" : nosub, "size" : 64, "default" : 0, "values" : []},
101     0x1000 : {"name" : "Device Type", "struct" : var, "need" : True, "values" : 
102                 [{"name" : "Device Type", "type" : 0x07, "access" : 'ro', "pdo" : False}]},
103     0x1001 : {"name" : "Error Register", "struct" : var,  "need" : True, "values" : 
104                 [{"name" : "Error Register", "type" : 0x05, "access": 'ro', "pdo" : True}]},
105     0x1002 : {"name" : "Manufacturer Status Register", "struct" : var, "need" : False,  "values" :
106                 [{"name" : "Manufacturer Status Register", "type" : 0x07, "access" : 'ro', "pdo" : True}]},
107     0x1003 : {"name" : "Pre-defined Error Field", "struct" : rec, "need" : False, "callback" : True,  "values" :
108                 [{"name" : "Number of Errors", "type" : 0x05, "access" : 'rw', "pdo" : False},
109                  {"name" : "Standard Error Field", "type" : 0x07, "access" : 'ro', "pdo" : False, "nbmax" : 0xFE}]},
110     0x1005 : {"name" : "SYNC COB ID", "struct" : var, "need" : False, "callback" : True, "values" :
111                 [{"name" : "SYNC COB ID", "type" : 0x07, "access" : 'rw', "pdo" : False}]},
112     0x1006 : {"name" : "Communication / Cycle Period", "struct" : var, "need" : False, "callback" : True, "values" :
113                 [{"name" : "Communication Cycle Period", "type" : 0x07, "access" : 'rw', "pdo" : False}]},
114     0x1007 : {"name" : "Synchronous Window Length", "struct" : var, "need" : False, "values" :
115                 [{"name" : "Synchronous Window Length", "type" : 0x07, "access" : 'rw', "pdo" : False}]},
116     0x1008 : {"name" : "Manufacturer Device Name", "struct" : var, "need" : False, "values" :
117                 [{"name" : "Manufacturer Device Name", "type" : 0x09, "access" : 'ro', "pdo" : False}]},
118     0x1009 : {"name" : "Manufacturer Hardware Version", "struct" : var, "need" : False, "values" :
119                 [{"name" : "Manufacturer Hardware Version", "type" : 0x09, "access" : 'ro', "pdo" : False}]},
120     0x100A : {"name" : "Manufacturer Software Version", "struct" : var, "need" : False, "values" :
121                 [{"name" : "Manufacturer Software Version", "type" : 0x09, "access" : 'ro', "pdo" : False}]},
122     0x100C : {"name" : "Guard Time", "struct" : var, "need" : False, "values" :
123                 [{"name" : "Guard Time", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
124     0x100D : {"name" : "Life Time Factor", "struct" : var, "need" : False, "values" :
125                 [{"name" : "Life Time Factor", "type" : 0x05, "access" : 'rw', "pdo" : False}]},
126     0x1010 : {"name" : "Store parameters", "struct" : array, "need" : False, "values" :
127                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
128                  {"name" : "Save All Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
129                  {"name" : "Save Communication Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
130                  {"name" : "Save Application Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
131                  {"name" : "Save Manufacturer Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmax" : 0x7C}]},
132     0x1011 : {"name" : "Restore Default Parameters", "struct" : array, "need" : False, "values" :
133                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
134                  {"name" : "Restore All Default Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
135                  {"name" : "Restore Communication Default Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
136                  {"name" : "Restore Application Default Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False},
137                  {"name" : "Restore Manufacturer Default Parameters", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmax" : 0x7C}]},
138     0x1012 : {"name" : "TIME COB ID", "struct" : var, "need" : False, "values" :
139                 [{"name" : "TIME COB ID", "type" : 0x07, "access" : 'rw', "pdo" : False}]},
140     0x1013 : {"name" : "High Resolution Timestamp", "struct" : var, "need" : False, "values" :
141                 [{"name" : "High Resolution Time Stamp", "type" : 0x07, "access" : 'rw', "pdo" : True}]},
142     0x1014 : {"name" : "Emergency COB ID", "struct" : var, "need" : False, "values" :
143                 [{"name" : "Emergency COB ID", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "\"$NODEID+0x80\""}]},
144     0x1015 : {"name" : "Inhibit Time Emergency", "struct" : var, "need" : False, "values" :
145                 [{"name" : "Inhibit Time Emergency", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
146     0x1016 : {"name" : "Consumer Heartbeat Time", "struct" : rec, "need" : False, "values" :
147                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
148                  {"name" : "Consumer Heartbeat Time", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 1, "nbmax" : 0x7F}]},
149     0x1017 : {"name" : "Producer Heartbeat Time", "struct" : var, "need" : False, "callback" : True, "values" :
150                 [{"name" : "Producer Heartbeat Time", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
151     0x1018 : {"name" : "Identity", "struct" : array, "need" : True, "values" :
152                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
153                  {"name" : "Vendor ID", "type" : 0x07, "access" : 'ro', "pdo" : False},
154                  {"name" : "Product Code", "type" : 0x07, "access" : 'ro', "pdo" : False},
155                  {"name" : "Revision Number", "type" : 0x07, "access" : 'ro', "pdo" : False},
156                  {"name" : "Serial Number", "type" : 0x07, "access" : 'ro', "pdo" : False}]},
157     0x1020 : {"name" : "Verify Configuration", "struct" : array, "need" : False, "values" :
158                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
159                  {"name" : "Configuration Date", "type" : 0x07, "access" : 'ro', "pdo" : False},
160                  {"name" : "Configuration Time", "type" : 0x07, "access" : 'ro', "pdo" : False}]},
161 #    0x1021 : {"name" : "Store EDS", "struct" : var, "need" : False, "values" :
162 #                [{"name" : "Store EDS", "type" : 0x0F, "access" : 'rw', "pdo" : False}]},
163 #    0x1022 : {"name" : "Storage Format", "struct" : var, "need" : False, "values" :
164 #                [{"name" : "Storage Format", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
165     0x1023 : {"name" : "OS Command", "struct" : array, "need" : False, "values" :
166                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
167                  {"name" : "Command", "type" : 0x0A, "access" : 'rw', "pdo" : False},
168                  {"name" : "Status", "type" : 0x05, "access" : 'ro', "pdo" : False},
169                  {"name" : "Reply", "type" : 0x0A, "access" : 'ro', "pdo" : False}]},
170     0x1024 : {"name" : "OS Command Mode", "struct" : var, "need" : False, "values" :
171                 [{"name" : "OS Command Mode", "type" : 0x05, "access" : 'wo', "pdo" : False}]},
172     0x1025 : {"name" : "OS Debugger Interface", "struct" : array, "need" : False, "values" :
173                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
174                  {"name" : "Command", "type" : 0x0A, "access" : 'rw', "pdo" : False},
175                  {"name" : "Status", "type" : 0x07, "access" : 'ro', "pdo" : False},
176                  {"name" : "Reply", "type" : 0x0A, "access" : 'ro', "pdo" : False}]},
177     0x1026 : {"name" : "OS Prompt", "struct" : array, "need" : False, "values" :
178                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
179                  {"name" : "StdIn", "type" : 0x05, "access" : 'wo', "pdo" : True},
180                  {"name" : "StdOut", "type" : 0x05, "access" : 'ro', "pdo" : True},
181                  {"name" : "StdErr", "type" : 0x05, "access" : 'ro', "pdo" : True}]},
182     0x1027 : {"name" : "Module List", "struct" : rec, "need" : False, "values" :
183                 [{"name" : "Number of Connected Modules", "type" : 0x05, "access" : 'ro', "pdo" : False},
184                  {"name" : "Module %d[(sub)]", "type" : 0x06, "access" : 'ro', "pdo" : False, "nbmin" : 1, "nbmax" : 0xFE}]},
185     0x1028 : {"name" : "Emergency Consumer", "struct" : rec, "need" : False, "values" :
186                 [{"name" : "Number of Consumed Emergency Objects", "type" : 0x05, "access" : 'ro', "pdo" : False},
187                  {"name" : "Emergency Consumer", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 1, "nbmax" : 0x7E}]},
188     0x1029 : {"name" : "Error Behavior", "struct" : array, "need" : False, "values" :
189                 [{"name" : "Number of Error Classes", "type" : 0x05, "access" : 'ro', "pdo" : False},
190                  {"name" : "Communication Error", "type" : 0x05, "access" : 'rw', "pdo" : False},
191                  {"name" : "Device Profile", "type" : 0x05, "access" : 'rw', "pdo" : False, "nbmax" : 0xFE}]},
192     0x1200 : {"name" : "Server SDO Parameter", "struct" : array, "need" : False, "values" :
193                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
194                  {"name" : "COB ID Client to Server (Receive SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False, "default" : "\"$NODEID+0x600\""},
195                  {"name" : "COB ID Server to Client (Transmit SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False, "default" : "\"$NODEID+0x580\""}]},
196     0x1201 : {"name" : "Additional Server SDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x7F, "need" : False, "values" :
197                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
198                  {"name" : "COB ID Client to Server (Receive SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False},
199                  {"name" : "COB ID Server to Client (Transmit SDO)", "type" : 0x07, "access" : 'ro', "pdo" : False},
200                  {"name" : "Node ID of the SDO Client", "type" : 0x05, "access" : 'ro', "pdo" : False}]},
201     0x1280 : {"name" : "Client SDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x100, "need" : False, "values" :
202                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'ro', "pdo" : False},
203                  {"name" : "COB ID Client to Server (Transmit SDO)", "type" : 0x07, "access" : 'rw', "pdo" : False},
204                  {"name" : "COB ID Server to Client (Receive SDO)", "type" : 0x07, "access" : 'rw', "pdo" : False},
205                  {"name" : "Node ID of the SDO Server", "type" : 0x05, "access" : 'rw', "pdo" : False}]},
206     0x1400 : {"name" : "Receive PDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
207                 [{"name" : "Highest SubIndex Supported", "type" : 0x05, "access" : 'ro', "pdo" : False},
208                  {"name" : "COB ID used by PDO", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "{True:\"$NODEID+0x%X00\"%(base+2),False:0x80000000}[base<4]"},
209                  {"name" : "Transmission Type", "type" : 0x05, "access" : 'rw', "pdo" : False},
210                  {"name" : "Inhibit Time", "type" : 0x06, "access" : 'rw', "pdo" : False},
211                  {"name" : "Compatibility Entry", "type" : 0x05, "access" : 'rw', "pdo" : False},
212                  {"name" : "Event Timer", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
213     0x1600 : {"name" : "Receive PDO %d Mapping[(idx)]", "struct" : plurirec, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
214                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'rw', "pdo" : False},
215                  {"name" : "PDO %d Mapping for an application object %d[(idx,sub)]", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 0, "nbmax" : 0x40}]},
216     0x1800 : {"name" : "Transmit PDO %d Parameter[(idx)]", "struct" : pluriarray, "incr" : 1, "nbmax" : 0x200, "need" : False, "callback" : True, "values" :
217                 [{"name" : "Highest SubIndex Supported", "type" : 0x05, "access" : 'ro', "pdo" : False},
218                  {"name" : "COB ID used by PDO", "type" : 0x07, "access" : 'rw', "pdo" : False, "default" : "{True:\"$NODEID+0x%X80\"%(base+1),False:0x80000000}[base<4]"},
219                  {"name" : "Transmission Type", "type" : 0x05, "access" : 'rw', "pdo" : False},
220                  {"name" : "Inhibit Time", "type" : 0x06, "access" : 'rw', "pdo" : False},
221                  {"name" : "Compatibility Entry", "type" : 0x05, "access" : 'rw', "pdo" : False},
222                  {"name" : "Event Timer", "type" : 0x06, "access" : 'rw', "pdo" : False}]},
223     0x1A00 : {"name" : "Transmit PDO %d Mapping[(idx)]", "struct" : plurirec, "incr" : 1, "nbmax" : 0x200, "need" : False, "values" :
224                 [{"name" : "Number of Entries", "type" : 0x05, "access" : 'rw', "pdo" : False},
225                  {"name" : "PDO %d Mapping for a process data variable %d[(idx,sub)]", "type" : 0x07, "access" : 'rw', "pdo" : False, "nbmin" : 0, "nbmax" : 0x40}]},
226 }
227
228 #-------------------------------------------------------------------------------
229 #                         Search in a Mapping Dictionary
230 #-------------------------------------------------------------------------------
231
232 """
233 Return the index of the typename given by searching in mappingdictionary 
234 """
235 def FindTypeIndex(typename, mappingdictionary):
236     testdic = {}
237     for index, values in mappingdictionary.iteritems():
238         if index < 0x1000:
239             testdic[values["name"]] = index
240     if typename in testdic:
241         return testdic[typename]
242     return None
243
244 """
245 Return the name of the type by searching in mappingdictionary 
246 """
247 def FindTypeName(typeindex, mappingdictionary):
248     if typeindex < 0x1000 and typeindex in mappingdictionary:
249         return mappingdictionary[typeindex]["name"]
250     return None
251
252 """
253 Return the default value of the type by searching in mappingdictionary 
254 """
255 def FindTypeDefaultValue(typeindex, mappingdictionary):
256     if typeindex < 0x1000 and typeindex in mappingdictionary:
257         return mappingdictionary[typeindex]["default"]
258     return None
259
260 """
261 Return the list of types defined in mappingdictionary 
262 """
263 def FindTypeList(mappingdictionary):
264     list = []
265     for index in mappingdictionary.keys():
266         if index < 0x1000:
267             list.append(mappingdictionary[index]["name"])
268     return list
269
270 """
271 Return the name of an entry by searching in mappingdictionary 
272 """
273 def FindEntryName(index, mappingdictionary):
274     base_index = FindIndex(index, mappingdictionary)
275     if base_index:
276         infos = mappingdictionary[base_index]
277         if infos["struct"] & OD_IdenticalIndexes:
278             return StringFormat(infos["name"], (index - base_index) / infos["incr"] + 1, 0)
279         else:
280             return infos["name"]
281     return None
282
283 """
284 Return the informations of one entry by searching in mappingdictionary 
285 """
286 def FindEntryInfos(index, mappingdictionary):
287     base_index = FindIndex(index, mappingdictionary)
288     if base_index:
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)
292         copy.pop("values")
293         return copy
294     return None
295
296 """
297 Return the informations of one subentry of an entry by searching in mappingdictionary 
298 """
299 def FindSubentryInfos(index, subIndex, mappingdictionary):
300     base_index = FindIndex(index, mappingdictionary)
301     if base_index:
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"]
307                 else:
308                     incr = 1
309                 if subIndex == 0:
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)
314                     return copy
315             elif struct & OD_MultipleSubindexes and 0 <= subIndex < len(mappingdictionary[base_index]["values"]):
316                 return mappingdictionary[base_index]["values"][subIndex].copy()
317             elif subIndex == 0:
318                 return mappingdictionary[base_index]["values"][0].copy()
319     return None
320
321 """
322 Return the list of variables that can be mapped defined in mappingdictionary 
323 """
324 def FindMapVariableList(mappingdictionary, Node):
325     list = []
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)))
335                     else:
336                         list.append((index, subIndex, infos["size"], mappingdictionary[index]["values"][subIndex]["name"]))
337     return list
338
339 """
340 Return the list of mandatory indexes defined in mappingdictionary 
341 """
342 def FindMandatoryIndexes(mappingdictionary):
343     list = []
344     for index in mappingdictionary.iterkeys():
345         if index >= 0x1000 and mappingdictionary[index]["need"]:
346             list.append(index)
347     return list
348
349 """
350 Return the index of the informations in the Object Dictionary in case of identical
351 indexes
352 """
353 def FindIndex(index, mappingdictionary):
354     if index in mappingdictionary:
355         return index
356     else:
357         listpluri = [idx for idx in mappingdictionary.keys() if mappingdictionary[idx]["struct"] & OD_IdenticalIndexes]
358         listpluri.sort()
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:
363                 return idx
364     return None
365
366 #-------------------------------------------------------------------------------
367 #                           Formating Name of an Entry
368 #-------------------------------------------------------------------------------
369
370 name_model = re.compile('(.*)\[(.*)\]')
371
372 """
373 Format the text given with the index and subindex defined
374 """
375 def StringFormat(text, idx, sub):
376     result = name_model.match(text)
377     if result:
378         format = result.groups()
379         return format[0]%eval(format[1])
380     else:
381         return text
382
383 #-------------------------------------------------------------------------------
384 #                          Definition of Node Object
385 #-------------------------------------------------------------------------------
386
387 """
388 Class recording the Object Dictionary entries. It checks at each modification
389 that the structure of the Object Dictionary stay coherent
390 """
391
392 class Node:
393     
394     DefaultStringSize = 10
395     
396     def __init__(self, name = "", type = "slave", id = 0, description = "", profilename = "DS-301", profile = {}, specificmenu = []):
397         self.Name = name
398         self.Type = type
399         self.ID = id
400         self.Description = description
401         self.ProfileName = profilename
402         self.Profile = profile
403         self.SpecificMenu = specificmenu
404         self.Dictionary = {}
405         self.ParamsDictionary = {}
406         self.DS302 = {}
407         self.UserMapping = {}
408     
409     """
410     Return the node name
411     """
412     def GetNodeName(self):
413         return self.Name
414     
415     """
416     Define the node name
417     """
418     def SetNodeName(self, name):
419         self.Name = name
420
421     """
422     Return the node type ("master" or "slave")
423     """
424     def GetNodeType(self):
425         return self.Type
426     
427     """
428     Define the node type ("master" or "slave")
429     """
430     def SetNodeType(self, type):
431         self.Type = type
432
433     """
434     Return the node ID
435     """
436     def GetNodeID(self):
437         return self.ID
438     
439     """
440     Define the node ID
441     """
442     def SetNodeID(self, id):
443         self.ID = id
444
445     """
446     Return the node description
447     """
448     def GetNodeDescription(self):
449         if getattr(self, "Description", False):
450             return self.Description
451         else:
452             return ""
453     
454     """
455     Define the node description
456     """
457     def SetNodeDescription(self, description):
458         self.Description = description
459
460     """
461     Return the Specific Profile Name
462     """
463     def GetProfileName(self):
464         return self.ProfileName
465     
466     """
467     Define the Specific Profile Name
468     """
469     def SetProfileName(self, profilename):
470         self.ProfileName = profilename
471
472     """
473     Return the Specific Profile
474     """
475     def GetProfile(self):
476         return self.Profile
477     
478     """
479     Define the Specific Profile
480     """
481     def SetProfile(self, profile):
482         self.Profile = profile
483     
484     """
485     Return the default string size
486     """
487     def GetDefaultStringSize(self):
488         return self.DefaultStringSize
489     
490     """
491     Define the default string size
492     """
493     def SetDefaultStringSize(self, size):
494         self.DefaultStringSize = size
495     
496     """
497     Define the DS-302 Profile
498     """
499     def SetDS302Profile(self, profile):
500         self.DS302 = profile
501     
502     """
503     Define the DS-302 Profile
504     """
505     def GetDS302Profile(self):
506         return self.DS302
507     
508     """
509     Return the Specific Menu Entries
510     """
511     def GetSpecificMenu(self):
512         return self.SpecificMenu
513     
514     """
515     Define the Specific Menu Entries
516     """
517     def SetSpecificMenu(self, specificmenu):
518         self.SpecificMenu = specificmenu
519     
520     """
521     Extend the Specific Menu Entries
522     """
523     
524     def ExtendSpecificMenu(self, specificmenu):
525         self.SpecificMenu.extend(specificmenu)
526     
527     """
528     Function which return the different Mappings available for this node
529     """
530     def GetMappings(self, userdefinedtoo = True):
531         if userdefinedtoo:
532             return [self.Profile, self.DS302, self.UserMapping]
533         else:
534             return [self.Profile, self.DS302]
535     
536     """
537     Add a new entry in the Object Dictionary
538     """
539     def AddEntry(self, index, subIndex = None, value = None):
540         if index not in self.Dictionary:
541             if not subIndex:
542                 self.Dictionary[index] = value
543                 return True
544             elif subIndex == 1:
545                 self.Dictionary[index] = [value]
546                 return True
547         elif subIndex > 0 and type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]) + 1:
548             self.Dictionary[index].append(value)
549             return True
550         return False
551
552     """
553     Warning ! Modifies an existing entry in the Object Dictionary. Can't add a new one.
554     """
555     def SetEntry(self, index, subIndex = None, value = None):
556         if index in self.Dictionary:
557             if not subIndex:
558                 if value != None:
559                     self.Dictionary[index] = value
560                 return True
561             elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
562                 if value != None:
563                     self.Dictionary[index][subIndex - 1] = value
564                 return True
565         return False
566     
567     def SetParamsEntry(self, index, subIndex = None, comment = None, save = None, callback = None):
568         if not getattr(self, "ParamsDictionary", False):
569             self.ParamsDictionary = {}
570         if index in self.Dictionary:
571             if (comment != None or save != None or callback != None) and index not in self.ParamsDictionary:
572                 self.ParamsDictionary[index] = {}
573             if subIndex == None or type(self.Dictionary[index]) != ListType and subIndex == 0:
574                 if comment != None:
575                     self.ParamsDictionary[index]["comment"] = comment
576                 if save != None:
577                     self.ParamsDictionary[index]["save"] = save
578                 if callback != None:
579                     self.ParamsDictionary[index]["callback"] = callback
580                 return True
581             elif type(self.Dictionary[index]) == ListType and 0 <= subIndex <= len(self.Dictionary[index]):
582                 if (comment != None or save != None or callback != None) and subIndex not in self.ParamsDictionary[index]:
583                     self.ParamsDictionary[index][subIndex] = {}
584                 if comment != None:
585                     self.ParamsDictionary[index][subIndex]["comment"] = comment
586                 if save != None:
587                     self.ParamsDictionary[index][subIndex]["save"] = save
588                 return True
589         return False
590     
591     """
592     Removes an existing entry in the Object Dictionary. If a subIndex is specified
593     it will remove this subIndex only if it's the last of the index. If no subIndex
594     is specified it removes the whole index and subIndexes from the Object Dictionary.
595     """
596     def RemoveEntry(self, index, subIndex = None):
597         if not getattr(self, "ParamsDictionary", False):
598             self.ParamsDictionary = {}
599         if index in self.Dictionary:
600             if not subIndex:
601                 self.Dictionary.pop(index)
602                 if index in self.ParamsDictionary:
603                     self.ParamsDictionary.pop(index)
604                 return True
605             elif type(self.Dictionary[index]) == ListType and subIndex == len(self.Dictionary[index]):
606                 self.Dictionary[index].pop(subIndex - 1)
607                 if index in self.ParamsDictionary:
608                     if subIndex in self.ParamsDictionary[index]:
609                         self.ParamsDictionary[index].pop(subIndex)
610                     if len(self.ParamsDictionary[index]) == 0:
611                         self.ParamsDictionary.pop(index)
612                 if len(self.Dictionary[index]) == 0:
613                     self.Dictionary.pop(index)
614                     if index in self.ParamsDictionary:
615                         self.ParamsDictionary.pop(index)
616                 return True
617         return False
618     
619     """
620     Check if an entry exists in the Object Dictionary and returns the answer.
621     """
622     def IsEntry(self, index, subIndex = None):
623         if index in self.Dictionary:
624             if not subIndex:
625                 return True
626             return subIndex <= len(self.Dictionary[index])
627         return False
628     
629     """
630     Returns the value of the entry asked. If the entry has the value "count", it
631     returns the number of subIndex in the entry except the first.
632     """
633     def GetEntry(self, index, subIndex = None, compute = True):
634         if index in self.Dictionary:
635             if subIndex == None:
636                 if type(self.Dictionary[index]) == ListType:
637                     values = [len(self.Dictionary[index])]
638                     for value in self.Dictionary[index]:
639                         values.append(self.CompileValue(value, index, compute))
640                     return values
641                 else:
642                     return self.CompileValue(self.Dictionary[index], index, compute)
643             elif subIndex == 0:
644                 if type(self.Dictionary[index]) == ListType:
645                     return len(self.Dictionary[index])
646                 else:
647                     return self.CompileValue(self.Dictionary[index], index, compute)
648             elif type(self.Dictionary[index]) == ListType and 0 < subIndex <= len(self.Dictionary[index]):
649                 return self.CompileValue(self.Dictionary[index][subIndex - 1], index, compute)
650         return None
651
652     """
653     Returns the value of the entry asked. If the entry has the value "count", it
654     returns the number of subIndex in the entry except the first.
655     """
656     def GetParamsEntry(self, index, subIndex = None):
657         if not getattr(self, "ParamsDictionary", False):
658             self.ParamsDictionary = {}
659         if index in self.Dictionary:
660             if subIndex == None:
661                 if type(self.Dictionary[index]) == ListType:
662                     if index in self.ParamsDictionary:
663                         result = []
664                         for i in xrange(len(self.Dictionary[index]) + 1):
665                             line = DefaultParams.copy()
666                             if i in self.ParamsDictionary[index]:
667                                 line.update(self.ParamsDictionary[index][i])
668                             result.append(line)
669                         return result
670                     else:
671                         return [DefaultParams.copy() for i in xrange(len(self.Dictionary[index]) + 1)]
672                 else:
673                     result = DefaultParams.copy()
674                     if index in self.ParamsDictionary:
675                         result.update(self.ParamsDictionary[index])
676                     return result
677             elif subIndex == 0 and type(self.Dictionary[index]) != ListType:
678                 result = DefaultParams.copy()
679                 if index in self.ParamsDictionary:
680                     result.update(self.ParamsDictionary[index])
681                 return result
682             elif type(self.Dictionary[index]) == ListType and 0 <= subIndex <= len(self.Dictionary[index]):
683                 result = DefaultParams.copy()
684                 if index in self.ParamsDictionary and subIndex in self.ParamsDictionary[index]:
685                     result.update(self.ParamsDictionary[index][subIndex])
686                 return result
687         return None
688
689     def HasEntryCallbacks(self, index):
690         entry_infos = self.GetEntryInfos(index)
691         if entry_infos and "callback" in entry_infos:
692             return entry_infos["callback"]
693         else:
694             if not getattr(self, "ParamsDictionary", False):
695                 self.ParamsDictionary = {}
696             if index in self.Dictionary and index in self.ParamsDictionary and "callback" in self.ParamsDictionary[index]:
697                 return self.ParamsDictionary[index]["callback"]
698         return False
699
700     """
701     Check if an entry exists in the User Mapping Dictionary and returns the answer.
702     """
703     def IsMappingEntry(self, index):
704         if index in self.UserMapping:
705             return True
706         return False
707
708     """
709     Add a new entry in the User Mapping Dictionary
710     """
711     def AddMappingEntry(self, index, subIndex = None, name = "Undefined", struct = 0, size = None, nbmax = None, default = None, values = None):
712         if index not in self.UserMapping:
713             if values == None:
714                 values = []
715             if subIndex == None:
716                 self.UserMapping[index] = {"name" : name, "struct" : struct, "need" : False, "values" : values}
717                 if size != None:
718                     self.UserMapping[index]["size"] = size
719                 if nbmax != None:
720                     self.UserMapping[index]["nbmax"] = nbmax
721                 if default != None:
722                     self.UserMapping[index]["default"] = default
723                 return True
724         elif subIndex != None and subIndex == len(self.UserMapping[index]["values"]):
725             if values == None:
726                 values = {}
727             self.UserMapping[index]["values"].append(values)
728             return True
729         return False
730
731     """
732     Warning ! Modifies an existing entry in the User Mapping Dictionary. Can't add a new one.
733     """
734     def SetMappingEntry(self, index, subIndex = None, name = None, struct = None, size = None, nbmax = None, default = None, values = None):
735         if index in self.UserMapping:
736             if subIndex == None:
737                 if name != None:
738                     self.UserMapping[index]["name"] = name
739                     if self.UserMapping[index]["struct"] & OD_IdenticalSubindexes:
740                         self.UserMapping[index]["values"][1]["name"] = name + " %d[(sub)]"
741                     elif not self.UserMapping[index]["struct"] & OD_MultipleSubindexes:
742                         self.UserMapping[index]["values"][0]["name"] = name
743                 if struct != None:
744                     self.UserMapping[index]["struct"] = struct
745                 if size != None:
746                     self.UserMapping[index]["size"] = size
747                 if nbmax != None:
748                     self.UserMapping[index]["nbmax"] = nbmax
749                 if default != None:
750                     self.UserMapping[index]["default"] = default
751                 if values != None:
752                     self.UserMapping[index]["values"] = values
753                 return True
754             elif 0 <= subIndex < len(self.UserMapping[index]["values"]) and values != None:
755                 if "type" in values:
756                     if self.UserMapping[index]["struct"] & OD_IdenticalSubindexes:
757                         if self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
758                             if self.IsRealType(values["type"]):
759                                 for i in xrange(len(self.Dictionary[index])):
760                                     self.SetEntry(index, i + 1, 0.)
761                             elif not self.IsStringType(values["type"]):
762                                 for i in xrange(len(self.Dictionary[index])):
763                                     self.SetEntry(index, i + 1, 0)
764                         elif self.IsRealType(self.UserMapping[index]["values"][subIndex]["type"]):
765                             if self.IsStringType(values["type"]):
766                                 for i in xrange(len(self.Dictionary[index])):
767                                     self.SetEntry(index, i + 1, "")
768                             elif not self.IsRealType(values["type"]):
769                                 for i in xrange(len(self.Dictionary[index])):
770                                     self.SetEntry(index, i + 1, 0)
771                         elif self.IsStringType(values["type"]):
772                             for i in xrange(len(self.Dictionary[index])):
773                                 self.SetEntry(index, i + 1, "")
774                         elif self.IsRealType(values["type"]):
775                             for i in xrange(len(self.Dictionary[index])):
776                                 self.SetEntry(index, i + 1, 0.)                        
777                     else:
778                         if self.IsStringType(self.UserMapping[index]["values"][subIndex]["type"]):
779                             if self.IsRealType(values["type"]):
780                                 self.SetEntry(index, subIndex, 0.)
781                             elif not self.IsStringType(values["type"]):
782                                 self.SetEntry(index, subIndex, 0)
783                         elif self.IsRealType(self.UserMapping[index]["values"][subIndex]["type"]):
784                             if self.IsStringType(values["type"]):
785                                 self.SetEntry(index, subIndex, "")
786                             elif not self.IsRealType(values["type"]):
787                                 self.SetEntry(index, subIndex, 0)
788                         elif self.IsStringType(values["type"]):
789                             self.SetEntry(index, subIndex, "")
790                         elif self.IsRealType(values["type"]):
791                             self.SetEntry(index, subIndex, 0.)
792                 self.UserMapping[index]["values"][subIndex].update(values)
793                 return True
794         return False
795     
796     """
797     Removes an existing entry in the User Mapping Dictionary. If a subIndex is specified
798     it will remove this subIndex only if it's the last of the index. If no subIndex
799     is specified it removes the whole index and subIndexes from the User Mapping Dictionary.
800     """
801     def RemoveMappingEntry(self, index, subIndex = None):
802         if index in self.UserMapping:
803             if subIndex == None:
804                 self.UserMapping.pop(index)
805                 return True
806             elif subIndex == len(self.UserMapping[index]["values"]) - 1:
807                 self.UserMapping[index]["values"].pop(subIndex)
808                 return True
809         return False
810
811     def RemoveMapVariable(self, index, subIndex = None):
812         model = index << 16
813         mask = 0xFFFF << 16
814         if subIndex:
815             model += subIndex << 8
816             mask += 0xFF << 8
817         for i in self.Dictionary.iterkeys():
818             if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
819                 for j,value in enumerate(self.Dictionary[i]):
820                     if (value & mask) == model:
821                         self.Dictionary[i][j] = 0
822     
823     def UpdateMapVariable(self, index, subIndex, size):
824         model = index << 16
825         mask = 0xFFFF << 16
826         if subIndex:
827             model += subIndex << 8
828             mask = 0xFF << 8
829         for i in self.Dictionary.iterkeys():
830             if 0x1600 <= i <= 0x17FF or 0x1A00 <= i <= 0x1BFF:
831                 for j,value in enumerate(self.Dictionary[i]):
832                     if (value & mask) == model:
833                         self.Dictionary[i][j] = model + size
834     
835     def RemoveLine(self, index, max, incr = 1):
836         i = index
837         while i < max and self.IsEntry(i + incr):
838             self.Dictionary[i] = self.Dictionary[i + incr]
839             i += incr
840         self.Dictionary.pop(i)
841
842     def RemoveUserType(self, index):
843         type = self.GetEntry(index, 1)
844         for i in self.UserMapping:
845             for value in self.UserMapping[i]["values"]:
846                 if value["type"] == index:
847                     value["type"] = type
848         self.RemoveMappingEntry(index)
849         self.RemoveEntry(index)
850
851     """
852     Return a copy of the node
853     """
854     def Copy(self):
855         return cPickle.loads(cPickle.dumps(self))
856
857     """
858     Return a sorted list of indexes in Object Dictionary
859     """
860     def GetIndexes(self):
861         listindex = self.Dictionary.keys()
862         listindex.sort()
863         return listindex
864
865     """
866     Print the Dictionary values
867     """
868     def Print(self):
869         print self.PrintString()
870     
871     def PrintString(self):
872         result = ""
873         listindex = self.Dictionary.keys()
874         listindex.sort()
875         for index in listindex:
876             name = self.GetEntryName(index)
877             values = self.Dictionary[index]
878             if isinstance(values, ListType):
879                 result += "%04X (%s):\n"%(index, name)
880                 for subidx, value in enumerate(values):
881                     subentry_infos = self.GetSubentryInfos(index, subidx + 1)
882                     if index == 0x1F22 and value:
883                         nb_params = BE_to_LE(value[:4])
884                         data = value[4:]
885                         value = "%d arg defined"%nb_params
886                         i = 0
887                         count = 1
888                         while i < len(data):
889                             value += "\n%04X %02X, arg %d: "%(index, subidx+1, count)
890                             value += "%04X"%BE_to_LE(data[i:i+2])
891                             value += " %02X"%BE_to_LE(data[i+2:i+3])
892                             size = BE_to_LE(data[i+3:i+7])
893                             value += " %08X"%size
894                             value += (" %0"+"%d"%(size * 2)+"X")%BE_to_LE(data[i+7:i+7+size])
895                             i += 7 + size
896                             count += 1
897                     elif isinstance(value, IntType):
898                         value = "%X"%value
899                     result += "%04X %02X (%s): %s\n"%(index, subidx+1, subentry_infos["name"], value)
900             else:
901                 if isinstance(values, IntType):
902                     values = "%X"%values
903                 result += "%04X (%s): %s\n"%(index, name, values)
904         return result
905             
906     def CompileValue(self, value, index, compute = True):
907         if type(value) == StringType and value.find("$NODEID") != -1:
908             base = self.GetBaseIndex(index)
909             try:
910                 raw = eval(value)
911                 if compute:
912                     return eval(raw.replace("$NODEID","self.ID"))
913                 return raw
914             except:
915                 return 0
916         else:
917             return value
918
919 #-------------------------------------------------------------------------------
920 #                         Node Informations Functions
921 #-------------------------------------------------------------------------------
922
923     def GetBaseIndex(self, index):
924         for mapping in self.GetMappings():
925             result = FindIndex(index, mapping)
926             if result != None:
927                 return (index - result) / mapping[result].get("incr", 1)
928         result = FindIndex(index, MappingDictionary)
929         if result != None:
930             return (index - result) / MappingDictionary[result].get("incr", 1)
931         return 0
932
933     def GetCustomisedTypeValues(self, index):
934         values = self.GetEntry(index)
935         customisabletypes = self.GetCustomisableTypes()
936         return values, customisabletypes[values[1]][1]
937
938     def GetEntryName(self, index):
939         result = None
940         mappings = self.GetMappings()
941         i = 0
942         while not result and i < len(mappings):
943             result = FindEntryName(index, mappings[i])
944             i += 1
945         if result == None:
946             result = FindEntryName(index, MappingDictionary)
947         return result
948     
949     def GetEntryInfos(self, index):
950         result = None
951         mappings = self.GetMappings()
952         i = 0
953         while not result and i < len(mappings):
954             result = FindEntryInfos(index, mappings[i])
955             i += 1
956         if result == None:
957             result = FindEntryInfos(index, MappingDictionary)
958         return result
959     
960     def GetSubentryInfos(self, index, subIndex):
961         result = None
962         mappings = self.GetMappings()
963         i = 0
964         while not result and i < len(mappings):
965             result = FindSubentryInfos(index, subIndex, mappings[i])
966             if result:
967                 result["user_defined"] = i == len(mappings) - 1 and index >= 0x1000
968             i += 1
969         if result == None:
970             result = FindSubentryInfos(index, subIndex, MappingDictionary)
971             if result:
972                 result["user_defined"] = False
973         return result
974     
975     def GetTypeIndex(self, typename):
976         result = None
977         mappings = self.GetMappings()
978         i = 0
979         while not result and i < len(mappings):
980             result = FindTypeIndex(typename, mappings[i])
981             i += 1
982         if result == None:
983             result = FindTypeIndex(typename, MappingDictionary)
984         return result
985     
986     def GetTypeName(self, typeindex):
987         result = None
988         mappings = self.GetMappings()
989         i = 0
990         while not result and i < len(mappings):
991             result = FindTypeName(typeindex, mappings[i])
992             i += 1
993         if result == None:
994             result = FindTypeName(typeindex, MappingDictionary)
995         return result
996     
997     def GetTypeDefaultValue(self, typeindex):
998         result = None
999         mappings = self.GetMappings()
1000         i = 0
1001         while not result and i < len(mappings):
1002             result = FindTypeDefaultValue(typeindex, mappings[i])
1003             i += 1
1004         if result == None:
1005             result = FindTypeDefaultValue(typeindex, MappingDictionary)
1006         return result
1007     
1008     def GetMapVariableList(self):
1009         list = FindMapVariableList(MappingDictionary, self)
1010         for mapping in self.GetMappings():
1011             list.extend(FindMapVariableList(mapping, self))
1012         list.sort()
1013         return list
1014     
1015     def GetMandatoryIndexes(self, node = None):
1016         list = FindMandatoryIndexes(MappingDictionary)
1017         for mapping in self.GetMappings():
1018             list.extend(FindMandatoryIndexes(mapping))
1019         return list
1020     
1021     def GetCustomisableTypes(self):
1022         dic = {}
1023         for index, valuetype in CustomisableTypes:
1024             name = self.GetTypeName(index)
1025             dic[index] = [name, valuetype]
1026         return dic
1027
1028 #-------------------------------------------------------------------------------
1029 #                            Type helper functions
1030 #-------------------------------------------------------------------------------
1031
1032     def IsStringType(self, index):
1033         if index in (0x9, 0xA, 0xB):
1034             return True
1035         elif 0xA0 <= index < 0x100:
1036             result = self.GetEntry(index, 1)
1037             if result is not None and result in (0x9, 0xA, 0xB):
1038                 return True
1039         return False
1040
1041     def IsRealType(self, index):
1042         if index in (0x8, 0x11):
1043             return True
1044         elif 0xA0 <= index < 0x100:
1045             result = self.GetEntry(index, 1)
1046             if result is not None and result in (0x8, 0x11):
1047                 return True
1048         return False
1049
1050 #-------------------------------------------------------------------------------
1051 #                            Type and Map Variable Lists
1052 #-------------------------------------------------------------------------------
1053     
1054     def GetTypeList(self):
1055         list = FindTypeList(MappingDictionary)
1056         for mapping in self.GetMappings():
1057             list.extend(FindTypeList(mapping))
1058         list.sort()
1059         return ",".join(list)
1060
1061     """
1062     Generate the list of variables that can be mapped for the current node
1063     """
1064     def GenerateMapList(self):
1065         self.MapList = "None"
1066         self.NameTranslation = {"None" : "00000000"}
1067         self.MapTranslation = {"00000000" : "None"}
1068         list = self.GetMapVariableList()
1069         for index, subIndex, size, name in list:
1070             self.MapList += ",%s"%name
1071             map = "%04X%02X%02X"%(index,subIndex,size)
1072             self.NameTranslation[name] = map
1073             self.MapTranslation[map] = name
1074
1075     def GetMapValue(self, mapname):
1076         if mapname == "None":
1077             return 0
1078         else:
1079             list = self.GetMapVariableList()
1080             for index, subIndex, size, name in list:
1081                 if mapname == name:
1082                     return (index << 16) + (subIndex << 8) + size
1083             return None
1084     
1085     def GetMapName(self, value):
1086         if value != 0:
1087             index = value >> 16
1088             subindex = (value >> 8) % (1 << 8)
1089             result = self.GetSubentryInfos(index, subindex)
1090             if result:
1091                 return result["name"]
1092         return "None"
1093     
1094     """
1095     Return the list of variables that can be mapped for the current node
1096     """
1097     def GetMapList(self):
1098         list = ["None"] + [name for index, subIndex, size, name in self.GetMapVariableList()]
1099         return ",".join(list)
1100
1101 def BE_to_LE(value):
1102     """
1103     Convert Big Endian to Little Endian 
1104     @param value: value expressed in Big Endian
1105     @param size: number of bytes generated
1106     @return: a string containing the value converted
1107     """
1108     
1109     data = [char for char in value]
1110     data.reverse()
1111     return int("".join(["%2.2X"%ord(char) for char in data]), 16)
1112
1113 def LE_to_BE(value, size):
1114     """
1115     Convert Little Endian to Big Endian
1116     @param value: value expressed in integer
1117     @param size: number of bytes generated
1118     @return: a string containing the value converted
1119     """
1120     
1121     data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value
1122     list_car = [data[i:i+2] for i in xrange(0, len(data), 2)]
1123     list_car.reverse()
1124     return "".join([chr(int(car, 16)) for car in list_car])
1125