]>
Commit | Line | Data |
---|---|---|
5add80f6 JS |
1 | #!/usr/bin/env python |
2 | ||
c09ca11b UH |
3 | ## |
4 | ## This file is part of the sigrok-meter project. | |
5 | ## | |
6 | ## Copyright (C) 2013 Uwe Hermann <uwe@hermann-uwe.de> | |
7 | ## | |
8 | ## This program is free software; you can redistribute it and/or modify | |
9 | ## it under the terms of the GNU General Public License as published by | |
10 | ## the Free Software Foundation; either version 2 of the License, or | |
11 | ## (at your option) any later version. | |
12 | ## | |
13 | ## This program is distributed in the hope that it will be useful, | |
14 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | ## GNU General Public License for more details. | |
17 | ## | |
18 | ## You should have received a copy of the GNU General Public License | |
19 | ## along with this program; if not, write to the Free Software | |
20 | ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
21 | ## | |
22 | ||
782f5926 | 23 | import argparse |
13e332b7 UH |
24 | from multiprocessing import Process, Queue |
25 | from gi.repository import Gtk, GObject | |
f94bb73f | 26 | import re |
efdef4fa | 27 | import sigrok.core as sr |
782f5926 | 28 | import sys |
f94bb73f | 29 | import textwrap |
13e332b7 | 30 | |
f94bb73f | 31 | default_drivers = [('demo', {'analog_channels': 1})] |
782f5926 JS |
32 | default_loglevel = sr.LogLevel.WARN |
33 | ||
fdb40b43 JS |
34 | def format_unit(u): |
35 | units = { | |
36 | sr.Unit.VOLT: 'V', | |
37 | sr.Unit.AMPERE: 'A', | |
38 | sr.Unit.OHM: u'\u03A9', | |
39 | sr.Unit.FARAD: 'F', | |
40 | sr.Unit.KELVIN: 'K', | |
41 | sr.Unit.CELSIUS: u'\u00B0C', | |
42 | sr.Unit.FAHRENHEIT: u'\u00B0F', | |
43 | sr.Unit.HERTZ: 'Hz', | |
44 | sr.Unit.PERCENTAGE: '%', | |
45 | # sr.Unit.BOOLEAN | |
46 | sr.Unit.SECOND: 's', | |
47 | sr.Unit.SIEMENS: 'S', | |
48 | sr.Unit.DECIBEL_MW: 'dBu', | |
49 | sr.Unit.DECIBEL_VOLT: 'dBV', | |
50 | # sr.Unit.UNITLESS | |
51 | sr.Unit.DECIBEL_SPL: 'dB', | |
52 | # sr.Unit.CONCENTRATION | |
53 | sr.Unit.REVOLUTIONS_PER_MINUTE: 'rpm', | |
54 | sr.Unit.VOLT_AMPERE: 'VA', | |
55 | sr.Unit.WATT: 'W', | |
56 | sr.Unit.WATT_HOUR: 'Wh', | |
57 | sr.Unit.METER_SECOND: 'm/s', | |
58 | sr.Unit.HECTOPASCAL: 'hPa', | |
59 | sr.Unit.HUMIDITY_293K: '%rF', | |
60 | sr.Unit.DEGREE: u'\u00B0', | |
61 | sr.Unit.HENRY: 'H' | |
62 | } | |
63 | ||
64 | return units.get(u, '') | |
65 | ||
f94bb73f | 66 | def init_and_run(queue, drivers, loglevel): |
13e332b7 | 67 | def datafeed_in(device, packet): |
efdef4fa | 68 | if packet.type == sr.PacketType.ANALOG: |
13e332b7 | 69 | data = packet.payload.data |
fdb40b43 | 70 | unit_str = format_unit(packet.payload.unit) |
92ba651c | 71 | mqflags, mqflags_str = packet.payload.mq_flags, "" |
fdb40b43 | 72 | |
efdef4fa | 73 | if sr.QuantityFlag.AC in mqflags: |
fdb40b43 | 74 | mqflags_str = "AC" |
efdef4fa | 75 | elif sr.QuantityFlag.DC in mqflags: |
fdb40b43 JS |
76 | mqflags_str = "DC" |
77 | ||
13e332b7 | 78 | for i in range(packet.payload.num_samples): |
53fed2c3 | 79 | dev = "%s %s" % (device.vendor, device.model) |
fdb40b43 JS |
80 | mag_str = "%f" % data[0][i] |
81 | val = ' '.join([mag_str, unit_str, mqflags_str]) | |
49e0ee28 | 82 | queue.put((dev, val)) |
13e332b7 | 83 | |
efdef4fa | 84 | context = sr.Context_create() |
782f5926 | 85 | context.log_level = loglevel |
f94bb73f JS |
86 | |
87 | devices = [] | |
88 | for name, options in drivers: | |
89 | try: | |
90 | dr = context.drivers[name] | |
91 | devices.append(dr.scan(**options)[0]) | |
92 | except: | |
93 | print('error getting device for driver "{}", skipping'.format(name)) | |
94 | ||
95 | if not devices: | |
96 | print('no devices found') | |
97 | return | |
98 | ||
92ba651c | 99 | session = context.create_session() |
49e0ee28 UH |
100 | for dev in devices: |
101 | session.add_device(dev) | |
92ba651c JS |
102 | dev.open() |
103 | session.add_datafeed_callback(datafeed_in) | |
13e332b7 UH |
104 | session.start() |
105 | session.run() | |
106 | session.stop() | |
c09ca11b | 107 | |
730cbd1f UH |
108 | class SigrokMeter: |
109 | def __init__(self): | |
110 | self.builder = Gtk.Builder() | |
111 | self.builder.add_from_file("sigrok-meter.glade") | |
112 | self.builder.connect_signals(self) | |
13e332b7 | 113 | self.value_label = self.builder.get_object("value_label") |
49e0ee28 | 114 | self.value_label2 = self.builder.get_object("value_label2") |
fd029d02 | 115 | self.win = self.builder.get_object("mainwindow") |
730cbd1f | 116 | self.win.show_all() |
13e332b7 UH |
117 | self.queue = Queue() |
118 | GObject.timeout_add(100, self.update_label_if_needed) | |
119 | ||
120 | def update_label_if_needed(self): | |
121 | try: | |
122 | t = self.queue.get_nowait() | |
49e0ee28 UH |
123 | l = self.value_label if t[0] != "Victor" else self.value_label2 |
124 | l.set_text("%s: %s" % (t[0], t[1])) | |
13e332b7 UH |
125 | except: |
126 | pass | |
127 | GObject.timeout_add(100, self.update_label_if_needed) | |
730cbd1f | 128 | |
fd029d02 | 129 | def on_quit(self, *args): |
2f5ef701 | 130 | Gtk.main_quit(*args) |
730cbd1f | 131 | |
fd029d02 | 132 | def on_about(self, action): |
730cbd1f | 133 | about = self.builder.get_object("aboutdialog") |
efdef4fa | 134 | context = sr.Context_create() |
92ba651c JS |
135 | sr_pkg = context.package_version |
136 | sr_lib = context.lib_version | |
a683a5e2 UH |
137 | s = "Using libsigrok %s (lib version %s)." % (sr_pkg, sr_lib) |
138 | about.set_comments(s) | |
dd73092b UH |
139 | about.run() |
140 | about.hide() | |
2f5ef701 | 141 | |
f94bb73f | 142 | def parse_cli(): |
782f5926 | 143 | parser = argparse.ArgumentParser( |
f94bb73f JS |
144 | description='Simple sigrok GUI for multimeters and dataloggers.', |
145 | epilog=textwrap.dedent('''\ | |
146 | The DRIVER string is the same as for sigrok-cli(1). | |
147 | ||
148 | examples: | |
149 | ||
150 | %(prog)s --driver tecpel-dmm-8061-ser:conn=/dev/ttyUSB0 | |
151 | ||
152 | %(prog)s --driver uni-t-ut61e:conn=1a86.e008 | |
153 | '''), | |
154 | formatter_class=argparse.RawDescriptionHelpFormatter) | |
155 | ||
156 | parser.add_argument('-d', '--driver', | |
157 | action='append', | |
158 | help='The driver to use') | |
782f5926 JS |
159 | parser.add_argument('-l', '--loglevel', |
160 | type=int, | |
161 | help='Set loglevel (5 is most verbose)') | |
162 | args = parser.parse_args() | |
163 | ||
f94bb73f JS |
164 | result = { |
165 | 'drivers': default_drivers, | |
166 | 'loglevel': default_loglevel | |
167 | } | |
168 | ||
169 | if args.driver: | |
170 | result['drivers'] = [] | |
171 | for d in args.driver: | |
172 | m = re.match('(?P<name>[^:]+)(?P<opts>(:[^:=]+=[^:=]+)*)', d) | |
173 | if not m: | |
174 | sys.exit('error parsing option "{}"'.format(d)) | |
175 | ||
176 | opts = m.group('opts').split(':')[1:] | |
177 | opts = [tuple(kv.split('=')) for kv in opts] | |
178 | opts = dict(opts) | |
179 | ||
180 | result['drivers'].append((m.group('name'), opts)) | |
181 | ||
782f5926 JS |
182 | if args.loglevel != None: |
183 | try: | |
f94bb73f | 184 | result['loglevel'] = sr.LogLevel.get(args.loglevel) |
782f5926 JS |
185 | except: |
186 | sys.exit('error: invalid log level') | |
187 | ||
f94bb73f JS |
188 | return result |
189 | ||
190 | if __name__ == '__main__': | |
191 | args = parse_cli() | |
9e7bd3d2 | 192 | s = SigrokMeter() |
f94bb73f JS |
193 | process = Process(target=init_and_run, |
194 | args=(s.queue, args['drivers'], args['loglevel'])) | |
9e7bd3d2 UH |
195 | process.start() |
196 | Gtk.main() | |
197 | process.terminate() | |
c09ca11b | 198 |