]>
Commit | Line | Data |
---|---|---|
d8f6e041 | 1 | ## |
50985c20 | 2 | ## This file is part of the libsigrok project. |
d8f6e041 ML |
3 | ## |
4 | ## Copyright (C) 2013 Martin Ling <martin-sigrok@earth.li> | |
5 | ## | |
6 | ## This program is free software: you can redistribute it and/or modify | |
7 | ## it under the terms of the GNU General Public License as published by | |
8 | ## the Free Software Foundation, either version 3 of the License, or | |
9 | ## (at your option) any later version. | |
10 | ## | |
11 | ## This program is distributed in the hope that it will be useful, | |
12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | ## GNU General Public License for more details. | |
15 | ## | |
16 | ## You should have received a copy of the GNU General Public License | |
17 | ## along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | ## | |
19 | ||
20 | from functools import partial | |
21 | from fractions import Fraction | |
86573018 | 22 | from collections import OrderedDict |
1cad2115 ML |
23 | from .lowlevel import * |
24 | from . import lowlevel | |
d8f6e041 ML |
25 | import itertools |
26 | ||
9bbd6a6a | 27 | __all__ = ['Error', 'Context', 'Driver', 'Device', 'Session', 'Packet', 'Log', |
417e9f3a | 28 | 'LogLevel', 'PacketType', 'Quantity', 'Unit', 'QuantityFlag', 'ConfigKey', |
660e398f | 29 | 'ProbeType', 'Probe', 'ChannelGroup', 'InputFormat', 'OutputFormat', |
409d85b3 | 30 | 'InputFile', 'Output'] |
d8f6e041 ML |
31 | |
32 | class Error(Exception): | |
33 | ||
34 | def __str__(self): | |
35 | return sr_strerror(self.args[0]) | |
36 | ||
37 | def check(result): | |
38 | if result != SR_OK: | |
39 | raise Error(result) | |
40 | ||
d8f6e041 ML |
41 | def gvariant_to_python(value): |
42 | type_string = g_variant_get_type_string(value) | |
43 | if type_string == 't': | |
44 | return g_variant_get_uint64(value) | |
45 | if type_string == 'b': | |
46 | return g_variant_get_bool(value) | |
47 | if type_string == 'd': | |
48 | return g_variant_get_double(value) | |
49 | if type_string == 's': | |
50 | return g_variant_get_string(value, None) | |
51 | if type_string == '(tt)': | |
52 | return Fraction( | |
53 | g_variant_get_uint64(g_variant_get_child_value(value, 0)), | |
54 | g_variant_get_uint64(g_variant_get_child_value(value, 1))) | |
1cad2115 | 55 | raise NotImplementedError( |
d8f6e041 ML |
56 | "Can't convert GVariant type '%s' to a Python type." % type_string) |
57 | ||
58 | def python_to_gvariant(value): | |
59 | if isinstance(value, int): | |
60 | return g_variant_new_uint64(value) | |
61 | if isinstance(value, bool): | |
62 | return g_variant_new_boolean(value) | |
63 | if isinstance(value, float): | |
64 | return g_variant_new_double(value) | |
65 | if isinstance(value, str): | |
66 | return g_variant_new_string(value) | |
67 | if isinstance(value, Fraction): | |
68 | array = new_gvariant_ptr_array(2) | |
1e2bd8af ML |
69 | gvariant_ptr_array_setitem(array, 0, |
70 | g_variant_new_uint64(value.numerator)) | |
71 | gvariant_ptr_array_setitem(array, 1, | |
72 | g_variant_new_uint64(value.denominator)) | |
d8f6e041 ML |
73 | result = g_variant_new_tuple(array, 2) |
74 | delete_gvariant_ptr_array(array) | |
75 | return result | |
1cad2115 | 76 | raise NotImplementedError( |
d8f6e041 ML |
77 | "Can't convert Python '%s' to a GVariant." % type(value)) |
78 | ||
79 | def callback_wrapper(session, callback, device_ptr, packet_ptr): | |
80 | device = session.context._devices[int(device_ptr.this)] | |
81 | packet = Packet(session, packet_ptr) | |
82 | callback(device, packet) | |
83 | ||
84 | class Context(object): | |
85 | ||
86 | def __init__(self): | |
87 | context_ptr_ptr = new_sr_context_ptr_ptr() | |
88 | check(sr_init(context_ptr_ptr)) | |
89 | self.struct = sr_context_ptr_ptr_value(context_ptr_ptr) | |
90 | self._drivers = None | |
91 | self._devices = {} | |
a64198c8 ML |
92 | self._input_formats = None |
93 | self._output_formats = None | |
d8f6e041 ML |
94 | self.session = None |
95 | ||
96 | def __del__(self): | |
97 | sr_exit(self.struct) | |
98 | ||
99 | @property | |
100 | def drivers(self): | |
101 | if not self._drivers: | |
102 | self._drivers = {} | |
103 | driver_list = sr_driver_list() | |
104 | for i in itertools.count(): | |
105 | driver_ptr = sr_dev_driver_ptr_array_getitem(driver_list, i) | |
106 | if driver_ptr: | |
107 | self._drivers[driver_ptr.name] = Driver(self, driver_ptr) | |
108 | else: | |
109 | break | |
110 | return self._drivers | |
111 | ||
a64198c8 ML |
112 | @property |
113 | def input_formats(self): | |
114 | if not self._input_formats: | |
86573018 | 115 | self._input_formats = OrderedDict() |
a64198c8 ML |
116 | input_list = sr_input_list() |
117 | for i in itertools.count(): | |
118 | input_ptr = sr_input_format_ptr_array_getitem(input_list, i) | |
119 | if input_ptr: | |
120 | self._input_formats[input_ptr.id] = InputFormat(self, input_ptr) | |
121 | else: | |
122 | break | |
123 | return self._input_formats | |
124 | ||
125 | @property | |
126 | def output_formats(self): | |
127 | if not self._output_formats: | |
128 | self._output_formats = {} | |
129 | output_list = sr_output_list() | |
130 | for i in itertools.count(): | |
131 | output_ptr = sr_output_format_ptr_array_getitem(output_list, i) | |
132 | if output_ptr: | |
133 | self._output_formats[output_ptr.id] = OutputFormat(self, output_ptr) | |
134 | else: | |
135 | break | |
136 | return self._output_formats | |
137 | ||
d8f6e041 ML |
138 | class Driver(object): |
139 | ||
140 | def __init__(self, context, struct): | |
141 | self.context = context | |
142 | self.struct = struct | |
143 | self._initialized = False | |
144 | ||
145 | @property | |
146 | def name(self): | |
147 | return self.struct.name | |
148 | ||
3124e80b | 149 | def scan(self, **kwargs): |
d8f6e041 ML |
150 | if not self._initialized: |
151 | check(sr_driver_init(self.context.struct, self.struct)) | |
152 | self._initialized = True | |
3124e80b ML |
153 | options = [] |
154 | for name, value in kwargs.items(): | |
01e9ff61 | 155 | key = getattr(ConfigKey, name) |
3124e80b ML |
156 | src = sr_config() |
157 | src.key = key.id | |
57dd5e63 | 158 | src.data = python_to_gvariant(value) |
3124e80b ML |
159 | options.append(src.this) |
160 | option_list = python_to_gslist(options) | |
161 | device_list = sr_driver_scan(self.struct, option_list) | |
162 | g_slist_free(option_list) | |
772b21d4 | 163 | devices = [HardwareDevice(self, gpointer_to_sr_dev_inst_ptr(ptr)) |
05cfe114 | 164 | for ptr in gslist_to_python(device_list)] |
d8f6e041 ML |
165 | g_slist_free(device_list) |
166 | return devices | |
167 | ||
168 | class Device(object): | |
169 | ||
772b21d4 | 170 | def __new__(cls, struct, context): |
d8f6e041 | 171 | address = int(struct.this) |
772b21d4 ML |
172 | if address not in context._devices: |
173 | device = super(Device, cls).__new__(cls) | |
174 | device.struct = struct | |
175 | device.context = context | |
176 | device._probes = None | |
660e398f | 177 | device._channel_groups = None |
772b21d4 ML |
178 | context._devices[address] = device |
179 | return context._devices[address] | |
d8f6e041 ML |
180 | |
181 | @property | |
182 | def vendor(self): | |
183 | return self.struct.vendor | |
184 | ||
185 | @property | |
186 | def model(self): | |
187 | return self.struct.model | |
188 | ||
189 | @property | |
190 | def version(self): | |
191 | return self.struct.version | |
192 | ||
417e9f3a ML |
193 | @property |
194 | def probes(self): | |
195 | if self._probes is None: | |
196 | self._probes = {} | |
197 | probe_list = self.struct.probes | |
198 | while (probe_list): | |
91aea754 | 199 | probe_ptr = void_ptr_to_sr_channel_ptr(probe_list.data) |
417e9f3a ML |
200 | self._probes[probe_ptr.name] = Probe(self, probe_ptr) |
201 | probe_list = probe_list.next | |
202 | return self._probes | |
203 | ||
204 | @property | |
660e398f UH |
205 | def channel_groups(self): |
206 | if self._channel_groups is None: | |
207 | self._channel_groups = {} | |
208 | channel_group_list = self.struct.channel_groups | |
209 | while (channel_group_list): | |
210 | channel_group_ptr = void_ptr_to_sr_channel_group_ptr( | |
211 | channel_group_list.data) | |
212 | self._channel_groups[channel_group_ptr.name] = ChannelGroup(self, | |
213 | channel_group_ptr) | |
214 | channel_group_list = channel_group_list.next | |
215 | return self._channel_groups | |
417e9f3a | 216 | |
772b21d4 ML |
217 | class HardwareDevice(Device): |
218 | ||
219 | def __new__(cls, driver, struct): | |
220 | device = Device.__new__(cls, struct, driver.context) | |
221 | device.driver = driver | |
222 | return device | |
223 | ||
224 | def __getattr__(self, name): | |
225 | key = getattr(ConfigKey, name) | |
226 | data = new_gvariant_ptr_ptr() | |
227 | try: | |
228 | check(sr_config_get(self.driver.struct, self.struct, None, | |
229 | key.id, data)) | |
230 | except Error as error: | |
231 | if error.errno == SR_ERR_NA: | |
232 | raise NotImplementedError( | |
233 | "Device does not implement %s" % name) | |
234 | else: | |
235 | raise AttributeError | |
236 | value = gvariant_ptr_ptr_value(data) | |
237 | return gvariant_to_python(value) | |
238 | ||
239 | def __setattr__(self, name, value): | |
240 | try: | |
241 | key = getattr(ConfigKey, name) | |
242 | except AttributeError: | |
243 | super(Device, self).__setattr__(name, value) | |
244 | return | |
245 | check(sr_config_set(self.struct, None, key.id, python_to_gvariant(value))) | |
246 | ||
417e9f3a ML |
247 | class Probe(object): |
248 | ||
249 | def __init__(self, device, struct): | |
250 | self.device = device | |
251 | self.struct = struct | |
252 | ||
253 | @property | |
254 | def type(self): | |
255 | return ProbeType(self.struct.type) | |
256 | ||
257 | @property | |
258 | def enabled(self): | |
259 | return self.struct.enabled | |
260 | ||
261 | @property | |
262 | def name(self): | |
263 | return self.struct.name | |
264 | ||
660e398f | 265 | class ChannelGroup(object): |
417e9f3a ML |
266 | |
267 | def __init__(self, device, struct): | |
268 | self.device = device | |
269 | self.struct = struct | |
660e398f | 270 | self._channels = None |
417e9f3a ML |
271 | |
272 | def __iter__(self): | |
660e398f | 273 | return iter(self.channels) |
417e9f3a | 274 | |
af54bac9 ML |
275 | def __getattr__(self, name): |
276 | key = config_key(name) | |
277 | data = new_gvariant_ptr_ptr() | |
278 | try: | |
279 | check(sr_config_get(self.device.driver.struct, self.device.struct, | |
945e23a5 | 280 | self.struct, key.id, data)) |
af54bac9 ML |
281 | except Error as error: |
282 | if error.errno == SR_ERR_NA: | |
283 | raise NotImplementedError( | |
660e398f | 284 | "Channel group does not implement %s" % name) |
af54bac9 ML |
285 | else: |
286 | raise AttributeError | |
287 | value = gvariant_ptr_ptr_value(data) | |
288 | return gvariant_to_python(value) | |
289 | ||
290 | def __setattr__(self, name, value): | |
291 | try: | |
292 | key = config_key(name) | |
293 | except AttributeError: | |
660e398f | 294 | super(ChannelGroup, self).__setattr__(name, value) |
af54bac9 ML |
295 | return |
296 | check(sr_config_set(self.device.struct, self.struct, | |
945e23a5 | 297 | key.id, python_to_gvariant(value))) |
af54bac9 | 298 | |
417e9f3a ML |
299 | @property |
300 | def name(self): | |
301 | return self.struct.name | |
302 | ||
303 | @property | |
660e398f UH |
304 | def channels(self): |
305 | if self._channels is None: | |
306 | self._channels = [] | |
307 | channel_list = self.struct.channels | |
308 | while (channel_list): | |
91aea754 | 309 | channel_ptr = void_ptr_to_sr_channel_ptr(channel_list.data) |
660e398f UH |
310 | self._channels.append(Probe(self, probe_ptr)) |
311 | channel_list = channel_list.next | |
312 | return self._channels | |
417e9f3a | 313 | |
d8f6e041 ML |
314 | class Session(object): |
315 | ||
316 | def __init__(self, context): | |
317 | assert context.session is None | |
318 | self.context = context | |
319 | self.struct = sr_session_new() | |
320 | context.session = self | |
321 | ||
322 | def __del__(self): | |
323 | check(sr_session_destroy()) | |
324 | ||
325 | def add_device(self, device): | |
326 | check(sr_session_dev_add(device.struct)) | |
327 | ||
0e77b7ca UH |
328 | def open_device(self, device): |
329 | check(sr_dev_open(device.struct)) | |
330 | ||
d8f6e041 ML |
331 | def add_callback(self, callback): |
332 | wrapper = partial(callback_wrapper, self, callback) | |
333 | check(sr_session_datafeed_python_callback_add(wrapper)) | |
334 | ||
335 | def start(self): | |
336 | check(sr_session_start()) | |
337 | ||
338 | def run(self): | |
339 | check(sr_session_run()) | |
340 | ||
341 | def stop(self): | |
342 | check(sr_session_stop()) | |
343 | ||
344 | class Packet(object): | |
345 | ||
346 | def __init__(self, session, struct): | |
347 | self.session = session | |
348 | self.struct = struct | |
349 | self._payload = None | |
350 | ||
351 | @property | |
352 | def type(self): | |
9bbd6a6a | 353 | return PacketType(self.struct.type) |
d8f6e041 ML |
354 | |
355 | @property | |
356 | def payload(self): | |
357 | if self._payload is None: | |
358 | pointer = self.struct.payload | |
9bbd6a6a | 359 | if self.type == PacketType.LOGIC: |
d8f6e041 ML |
360 | self._payload = Logic(self, |
361 | void_ptr_to_sr_datafeed_logic_ptr(pointer)) | |
9bbd6a6a | 362 | elif self.type == PacketType.ANALOG: |
15574a3c ML |
363 | self._payload = Analog(self, |
364 | void_ptr_to_sr_datafeed_analog_ptr(pointer)) | |
d8f6e041 | 365 | else: |
1cad2115 | 366 | raise NotImplementedError( |
417e9f3a | 367 | "No Python mapping for packet type %s" % self.struct.type) |
d8f6e041 ML |
368 | return self._payload |
369 | ||
370 | class Logic(object): | |
371 | ||
372 | def __init__(self, packet, struct): | |
373 | self.packet = packet | |
374 | self.struct = struct | |
375 | self._data = None | |
376 | ||
377 | @property | |
378 | def data(self): | |
379 | if self._data is None: | |
380 | self._data = cdata(self.struct.data, self.struct.length) | |
381 | return self._data | |
382 | ||
15574a3c ML |
383 | class Analog(object): |
384 | ||
385 | def __init__(self, packet, struct): | |
386 | self.packet = packet | |
387 | self.struct = struct | |
388 | self._data = None | |
389 | ||
390 | @property | |
391 | def num_samples(self): | |
392 | return self.struct.num_samples | |
393 | ||
c2ec42ce UH |
394 | @property |
395 | def mq(self): | |
9bbd6a6a | 396 | return Quantity(self.struct.mq) |
c2ec42ce UH |
397 | |
398 | @property | |
399 | def unit(self): | |
9bbd6a6a | 400 | return Unit(self.struct.unit) |
c2ec42ce UH |
401 | |
402 | @property | |
403 | def mqflags(self): | |
9bbd6a6a | 404 | return QuantityFlag.set_from_mask(self.struct.mqflags) |
c2ec42ce | 405 | |
15574a3c ML |
406 | @property |
407 | def data(self): | |
408 | if self._data is None: | |
409 | self._data = float_array.frompointer(self.struct.data) | |
410 | return self._data | |
411 | ||
816aed6c UH |
412 | class Log(object): |
413 | ||
816aed6c UH |
414 | @property |
415 | def level(self): | |
9bbd6a6a | 416 | return LogLevel(sr_log_loglevel_get()) |
816aed6c UH |
417 | |
418 | @level.setter | |
419 | def level(self, l): | |
9bbd6a6a | 420 | check(sr_log_loglevel_set(l.id)) |
816aed6c UH |
421 | |
422 | @property | |
423 | def domain(self): | |
424 | return sr_log_logdomain_get() | |
425 | ||
426 | @domain.setter | |
427 | def domain(self, d): | |
428 | check(sr_log_logdomain_set(d)) | |
429 | ||
a64198c8 ML |
430 | class InputFormat(object): |
431 | ||
432 | def __init__(self, context, struct): | |
433 | self.context = context | |
434 | self.struct = struct | |
435 | ||
436 | @property | |
437 | def id(self): | |
438 | return self.struct.id | |
439 | ||
440 | @property | |
441 | def description(self): | |
442 | return self.struct.description | |
443 | ||
f0e764de ML |
444 | def format_match(self, filename): |
445 | return bool(self.struct.call_format_match(filename)) | |
446 | ||
447 | class InputFile(object): | |
448 | ||
449 | def __init__(self, format, filename, **kwargs): | |
450 | self.format = format | |
451 | self.filename = filename | |
452 | self.struct = sr_input() | |
453 | self.struct.format = self.format.struct | |
454 | self.struct.param = g_hash_table_new_full( | |
409d85b3 | 455 | g_str_hash_ptr, g_str_equal_ptr, g_free_ptr, g_free_ptr) |
f0e764de ML |
456 | for key, value in kwargs.items(): |
457 | g_hash_table_insert(self.struct.param, g_strdup(key), g_strdup(str(value))) | |
458 | check(self.format.struct.call_init(self.struct, self.filename)) | |
772b21d4 | 459 | self.device = InputFileDevice(self) |
f0e764de ML |
460 | |
461 | def load(self): | |
462 | check(self.format.struct.call_loadfile(self.struct, self.filename)) | |
463 | ||
464 | def __del__(self): | |
465 | g_hash_table_destroy(self.struct.param) | |
466 | ||
772b21d4 ML |
467 | class InputFileDevice(Device): |
468 | ||
469 | def __new__(cls, file): | |
470 | device = Device.__new__(cls, file.struct.sdi, file.format.context) | |
471 | device.file = file | |
472 | return device | |
473 | ||
a64198c8 ML |
474 | class OutputFormat(object): |
475 | ||
476 | def __init__(self, context, struct): | |
477 | self.context = context | |
478 | self.struct = struct | |
479 | ||
480 | @property | |
481 | def id(self): | |
482 | return self.struct.id | |
483 | ||
484 | @property | |
485 | def description(self): | |
486 | return self.struct.description | |
487 | ||
409d85b3 ML |
488 | class Output(object): |
489 | ||
490 | def __init__(self, format, device, param=None): | |
491 | self.format = format | |
492 | self.device = device | |
493 | self.param = param | |
494 | self.struct = sr_output() | |
495 | self.struct.format = self.format.struct | |
496 | self.struct.sdi = self.device.struct | |
497 | self.struct.param = param | |
498 | check(self.format.struct.call_init(self.struct)) | |
499 | ||
500 | def receive(self, packet): | |
501 | ||
502 | output_buf_ptr = new_uint8_ptr_ptr() | |
503 | output_len_ptr = new_uint64_ptr() | |
504 | using_obsolete_api = False | |
505 | ||
506 | if self.format.struct.event and packet.type in ( | |
507 | PacketType.TRIGGER, PacketType.FRAME_BEGIN, | |
508 | PacketType.FRAME_END, PacketType.END): | |
509 | check(self.format.struct.call_event(self.struct, packet.type.id, | |
510 | output_buf_ptr, output_len_ptr)) | |
511 | using_obsolete_api = True | |
512 | elif self.format.struct.data and packet.type.id == self.format.struct.df_type: | |
513 | check(self.format.struct.call_data(self.struct, | |
514 | packet.payload.struct.data, packet.payload.struct.length, | |
515 | output_buf_ptr, output_len_ptr)) | |
516 | using_obsolete_api = True | |
517 | ||
518 | if using_obsolete_api: | |
519 | output_buf = uint8_ptr_ptr_value(output_buf_ptr) | |
520 | output_len = uint64_ptr_value(output_len_ptr) | |
521 | result = cdata(output_buf, output_len) | |
522 | g_free(output_buf) | |
523 | return result | |
524 | ||
525 | if self.format.struct.receive: | |
526 | out_ptr = new_gstring_ptr_ptr() | |
527 | check(self.format.struct.call_receive(self.struct, self.device.struct, | |
528 | packet.struct, out_ptr)) | |
529 | out = gstring_ptr_ptr_value(out_ptr) | |
530 | if out: | |
531 | result = out.str | |
532 | g_string_free(out, True) | |
533 | return result | |
534 | ||
535 | return None | |
536 | ||
537 | def __del__(self): | |
538 | check(self.format.struct.call_cleanup(self.struct)) | |
539 | ||
8593c8e3 ML |
540 | class ConfigInfo(object): |
541 | ||
14e8eb33 ML |
542 | def __new__(cls, key): |
543 | struct = sr_config_info_get(key.id) | |
544 | if not struct: | |
545 | return None | |
546 | obj = super(ConfigInfo, cls).__new__(cls) | |
547 | obj.key = key | |
548 | obj.struct = struct | |
549 | return obj | |
8593c8e3 ML |
550 | |
551 | @property | |
552 | def datatype(self): | |
553 | return DataType(self.struct.datatype) | |
554 | ||
555 | @property | |
556 | def id(self): | |
557 | return self.struct.id | |
558 | ||
559 | @property | |
560 | def name(self): | |
561 | return self.struct.name | |
562 | ||
563 | @property | |
564 | def description(self): | |
565 | return self.struct.description | |
566 | ||
9bbd6a6a ML |
567 | class EnumValue(object): |
568 | ||
569 | _enum_values = {} | |
570 | ||
571 | def __new__(cls, id): | |
572 | if cls not in cls._enum_values: | |
573 | cls._enum_values[cls] = {} | |
574 | if id not in cls._enum_values[cls]: | |
575 | value = super(EnumValue, cls).__new__(cls) | |
576 | value.id = id | |
577 | cls._enum_values[cls][id] = value | |
578 | return cls._enum_values[cls][id] | |
579 | ||
580 | class LogLevel(EnumValue): | |
581 | pass | |
582 | ||
583 | class PacketType(EnumValue): | |
584 | pass | |
585 | ||
586 | class Quantity(EnumValue): | |
587 | pass | |
588 | ||
589 | class Unit(EnumValue): | |
590 | pass | |
591 | ||
592 | class QuantityFlag(EnumValue): | |
593 | ||
594 | @classmethod | |
595 | def set_from_mask(cls, mask): | |
596 | result = set() | |
597 | while mask: | |
598 | new_mask = mask & (mask - 1) | |
599 | result.add(cls(mask ^ new_mask)) | |
600 | mask = new_mask | |
601 | return result | |
602 | ||
f245b766 ML |
603 | class ConfigKey(EnumValue): |
604 | pass | |
605 | ||
8593c8e3 ML |
606 | class DataType(EnumValue): |
607 | pass | |
608 | ||
417e9f3a ML |
609 | class ProbeType(EnumValue): |
610 | pass | |
611 | ||
d8f6e041 | 612 | for symbol_name in dir(lowlevel): |
9bbd6a6a ML |
613 | for prefix, cls in [ |
614 | ('SR_LOG_', LogLevel), | |
615 | ('SR_DF_', PacketType), | |
616 | ('SR_MQ_', Quantity), | |
617 | ('SR_UNIT_', Unit), | |
f245b766 | 618 | ('SR_MQFLAG_', QuantityFlag), |
417e9f3a | 619 | ('SR_CONF_', ConfigKey), |
8593c8e3 | 620 | ('SR_T_', DataType), |
417e9f3a | 621 | ('SR_PROBE_', ProbeType)]: |
9bbd6a6a ML |
622 | if symbol_name.startswith(prefix): |
623 | name = symbol_name[len(prefix):] | |
624 | value = getattr(lowlevel, symbol_name) | |
cad0acef ML |
625 | obj = cls(value) |
626 | setattr(cls, name, obj) | |
627 | if cls is ConfigKey: | |
628 | obj.info = ConfigInfo(obj) | |
629 | if obj.info: | |
630 | setattr(cls, obj.info.id, obj) | |
01e9ff61 ML |
631 | else: |
632 | setattr(cls, name.lower(), obj) |