X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=sigrok-meter;h=c991fad0e5fdf3dfddac710d0e557ead8b641a4b;hb=a6fe45e1c6c5bc2659f670768bcdcf5f6f483966;hp=769b36c6a43441e05ffe709bd34b98198617ab74;hpb=fdb40b430b1a9a5fa0c4e74760273def05a670bb;p=sigrok-meter.git diff --git a/sigrok-meter b/sigrok-meter index 769b36c..c991fad 100755 --- a/sigrok-meter +++ b/sigrok-meter @@ -1,9 +1,9 @@ #!/usr/bin/env python - ## ## This file is part of the sigrok-meter project. ## ## Copyright (C) 2013 Uwe Hermann +## Copyright (C) 2014 Jens Steinhauser ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -21,178 +21,100 @@ ## import argparse -from multiprocessing import Process, Queue -from gi.repository import Gtk, GObject -import re import sigrok.core as sr import sys import textwrap +import signal -default_drivers = [('demo', {'analog_channels': 1})] -default_loglevel = sr.LogLevel.WARN - -def format_unit(u): - units = { - sr.Unit.VOLT: 'V', - sr.Unit.AMPERE: 'A', - sr.Unit.OHM: u'\u03A9', - sr.Unit.FARAD: 'F', - sr.Unit.KELVIN: 'K', - sr.Unit.CELSIUS: u'\u00B0C', - sr.Unit.FAHRENHEIT: u'\u00B0F', - sr.Unit.HERTZ: 'Hz', - sr.Unit.PERCENTAGE: '%', - # sr.Unit.BOOLEAN - sr.Unit.SECOND: 's', - sr.Unit.SIEMENS: 'S', - sr.Unit.DECIBEL_MW: 'dBu', - sr.Unit.DECIBEL_VOLT: 'dBV', - # sr.Unit.UNITLESS - sr.Unit.DECIBEL_SPL: 'dB', - # sr.Unit.CONCENTRATION - sr.Unit.REVOLUTIONS_PER_MINUTE: 'rpm', - sr.Unit.VOLT_AMPERE: 'VA', - sr.Unit.WATT: 'W', - sr.Unit.WATT_HOUR: 'Wh', - sr.Unit.METER_SECOND: 'm/s', - sr.Unit.HECTOPASCAL: 'hPa', - sr.Unit.HUMIDITY_293K: '%rF', - sr.Unit.DEGREE: u'\u00B0', - sr.Unit.HENRY: 'H' - } - - return units.get(u, '') - -def init_and_run(queue, drivers, loglevel): - def datafeed_in(device, packet): - if packet.type == sr.PacketType.ANALOG: - data = packet.payload.data - unit_str = format_unit(packet.payload.unit) - mqflags, mqflags_str = packet.payload.mq_flags, "" - - if sr.QuantityFlag.AC in mqflags: - mqflags_str = "AC" - elif sr.QuantityFlag.DC in mqflags: - mqflags_str = "DC" - - for i in range(packet.payload.num_samples): - dev = "%s %s" % (device.vendor, device.model) - mag_str = "%f" % data[0][i] - val = ' '.join([mag_str, unit_str, mqflags_str]) - queue.put((dev, val)) - - context = sr.Context_create() - context.log_level = loglevel - - devices = [] - for name, options in drivers: - try: - dr = context.drivers[name] - devices.append(dr.scan(**options)[0]) - except: - print('error getting device for driver "{}", skipping'.format(name)) - - if not devices: - print('no devices found') - return - - session = context.create_session() - for dev in devices: - session.add_device(dev) - dev.open() - session.add_datafeed_callback(datafeed_in) - session.start() - session.run() - session.stop() - -class SigrokMeter: - def __init__(self): - self.builder = Gtk.Builder() - self.builder.add_from_file("sigrok-meter.glade") - self.builder.connect_signals(self) - self.value_label = self.builder.get_object("value_label") - self.value_label2 = self.builder.get_object("value_label2") - self.win = self.builder.get_object("mainwindow") - self.win.show_all() - self.queue = Queue() - GObject.timeout_add(100, self.update_label_if_needed) - - def update_label_if_needed(self): - try: - t = self.queue.get_nowait() - l = self.value_label if t[0] != "Victor" else self.value_label2 - l.set_text("%s: %s" % (t[0], t[1])) - except: - pass - GObject.timeout_add(100, self.update_label_if_needed) - - def on_quit(self, *args): - Gtk.main_quit(*args) - - def on_about(self, action): - about = self.builder.get_object("aboutdialog") - context = sr.Context_create() - sr_pkg = context.package_version - sr_lib = context.lib_version - s = "Using libsigrok %s (lib version %s)." % (sr_pkg, sr_lib) - about.set_comments(s) - about.run() - about.hide() +default_drivers = [('demo:analog_channels=4', 'samplerate=4')] def parse_cli(): parser = argparse.ArgumentParser( description='Simple sigrok GUI for multimeters and dataloggers.', epilog=textwrap.dedent('''\ - The DRIVER string is the same as for sigrok-cli(1). + The DRIVER string is the same as for sigrok-cli(1). Multiple + DRIVER and CONFIG items can be supplied. The nth CONFIG is applied + to the nth DRIVER. If there are more drivers than configs, the + remaining drivers use the default configuration. - examples: + Examples: %(prog)s --driver tecpel-dmm-8061-ser:conn=/dev/ttyUSB0 %(prog)s --driver uni-t-ut61e:conn=1a86.e008 + + %(prog)s --driver demo:analog_channels=1 \\ + --config samplerate=10 + + %(prog)s --driver voltcraft-k204:conn=/dev/ttyUSB0 \\ + --driver uni-t-ut61d:conn=1a86.e008 \\ + --driver uni-t-ut61e-ser:conn=/dev/ttyUSB1 '''), formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('-d', '--driver', action='append', + default=[], help='The driver to use') + parser.add_argument('-c', '--config', + action='append', + default=[], + help='Specify device configuration options') parser.add_argument('-l', '--loglevel', type=int, + default=None, help='Set loglevel (5 is most verbose)') + parser.add_argument('--pyside', + action='store_true', + default=False, + help='Force use of PySide (default is to use PyQt4)') args = parser.parse_args() - result = { - 'drivers': default_drivers, - 'loglevel': default_loglevel - } + if len(args.config) > len(args.driver): + sys.exit('Error: More configurations than drivers given.') + # Merge drivers and configurations into a list of tuples. + setattr(args, 'drivers', []) + if not args.driver: + args.drivers = default_drivers + sys.stderr.write('No driver given, using demo driver.\n') if args.driver: - result['drivers'] = [] - for d in args.driver: - m = re.match('(?P[^:]+)(?P(:[^:=]+=[^:=]+)*)', d) - if not m: - sys.exit('error parsing option "{}"'.format(d)) + args.config.extend([''] * (len(args.driver) - len(args.config))) + args.drivers = zip(args.driver, args.config) + del args.driver + del args.config - opts = m.group('opts').split(':')[1:] - opts = [tuple(kv.split('=')) for kv in opts] - opts = dict(opts) + return args - result['drivers'].append((m.group('name'), opts)) +if __name__ == '__main__': + signal.signal(signal.SIGINT, signal.SIG_DFL) + + args = parse_cli() + + import qtcompat + qtcompat.load_modules(args.pyside) + QtCore = qtcompat.QtCore + QtGui = qtcompat.QtGui + import mainwindow + + app = QtGui.QApplication([]) + + # Initialize modules that need a QApplication to exist. + import settings + settings.init() + import icons + icons.load_icons() + + context = sr.Context_create() if args.loglevel != None: try: - result['loglevel'] = sr.LogLevel.get(args.loglevel) + loglevel = sr.LogLevel.get(args.loglevel) + settings.logging.level.setValue(loglevel) except: - sys.exit('error: invalid log level') - - return result + sys.exit('Error: invalid log level.') -if __name__ == '__main__': - args = parse_cli() - s = SigrokMeter() - process = Process(target=init_and_run, - args=(s.queue, args['drivers'], args['loglevel'])) - process.start() - Gtk.main() - process.terminate() + s = mainwindow.MainWindow(context, args.drivers) + s.show() + sys.exit(app.exec_())