330 lines
12 KiB
Python
330 lines
12 KiB
Python
#!/usr/bin/env python
|
|
import sys
|
|
import traceback
|
|
|
|
from PySide2.QtCore import (
|
|
Qt, QObject, Signal, Slot, QRunnable, QThreadPool
|
|
)
|
|
from PySide2.QtWidgets import (
|
|
QApplication, QMainWindow
|
|
)
|
|
from PySide2.QtCharts import (
|
|
QtCharts
|
|
)
|
|
|
|
from UM24CUI import Ui_MainWindow
|
|
|
|
from meter import um24c
|
|
|
|
|
|
class WorkerSignals(QObject):
|
|
"""
|
|
Defines the signals available from a running worker thread.
|
|
|
|
Supported signals are:
|
|
|
|
finished
|
|
No data
|
|
|
|
error
|
|
`tuple` (exctype, value, traceback.format_exc() )
|
|
|
|
result
|
|
`object` data returned from processing, anything
|
|
|
|
progress
|
|
`int` indicating % progress
|
|
"""
|
|
finished = Signal()
|
|
error = Signal(tuple)
|
|
result = Signal(object)
|
|
progress = Signal(int)
|
|
|
|
|
|
class MeterSignals(WorkerSignals):
|
|
|
|
progress = Signal(object)
|
|
|
|
|
|
class UM24LabUIWorker(QRunnable):
|
|
|
|
def __init__(self, fn, *args, **kwargs):
|
|
super(UM24LabUIWorker, self).__init__()
|
|
|
|
self.fn = fn
|
|
self.args = args
|
|
self.kwargs = kwargs
|
|
self.signals = WorkerSignals()
|
|
|
|
self.kwargs['progress_callback'] = self.signals.progress
|
|
|
|
@Slot()
|
|
def run(self):
|
|
try:
|
|
result = self.fn(*self.args, **self.kwargs)
|
|
except Exception:
|
|
traceback.print_exc()
|
|
exctype, value = sys.exc_info()[:2]
|
|
self.signals.error.emit((exctype, value, traceback.format_exc()))
|
|
else:
|
|
self.signals.result.emit(result)
|
|
finally:
|
|
self.signals.finished.emit()
|
|
|
|
|
|
class UM24LabWorker(UM24LabUIWorker):
|
|
|
|
def __init__(self, fn, *args, **kwargs):
|
|
super(UM24LabUIWorker, self).__init__()
|
|
|
|
self.fn = fn
|
|
self.args = args
|
|
self.kwargs = kwargs
|
|
self.signals = MeterSignals()
|
|
|
|
self.kwargs['progress_callback'] = self.signals.progress
|
|
|
|
@Slot()
|
|
def run(self):
|
|
while um24c.is_connected():
|
|
try:
|
|
result = self.fn(*self.args, **self.kwargs)
|
|
self.signals.progress.emit(result)
|
|
except Exception:
|
|
traceback.print_exc()
|
|
exctype, value = sys.exc_info()[:2]
|
|
self.signals.error.emit((exctype, value,
|
|
traceback.format_exc()))
|
|
else:
|
|
self.signals.result.emit(result)
|
|
|
|
|
|
class UM24Lab(QMainWindow):
|
|
|
|
def __init__(self):
|
|
super(UM24Lab, self).__init__()
|
|
self.ui = Ui_MainWindow()
|
|
self.ui.setupUi(self)
|
|
|
|
self.threadpool = QThreadPool()
|
|
|
|
self.meter_stats = None
|
|
|
|
self.ui.labelTimeRecorded.setText('00:00:00')
|
|
self.ui.sliderBrightness.setValue(0)
|
|
self.ui.sliderScreenOff.setValue(0)
|
|
self.ui.lcdVoltage.display(0.00)
|
|
self.ui.lcdCurrent.display(0.00)
|
|
self.ui.lcdImpedance.display(0.00)
|
|
self.ui.lcdPower.display(0.00)
|
|
self.ui.lcdTempC.display(0)
|
|
self.ui.lcdTempF.display(0)
|
|
self.ui.progressTempC.setValue(0)
|
|
self.ui.progressTempF.setValue(0)
|
|
self.ui.lcdDataMinus.display(0.00)
|
|
self.ui.lcdDataPlus.display(0.00)
|
|
self.ui.lcdCapacityRecorded.display(0)
|
|
self.ui.lcdEnergyRecorded.display(0)
|
|
self.ui.spinStopCurrent.setValue(0.00)
|
|
self.ui.buttonGroup.buttons()[0].setChecked(True)
|
|
|
|
# TODO: Add splash screen, discover in background
|
|
self.action_discover_devices()
|
|
|
|
self.ui.buttonNextScreen.clicked.connect(self.action_next_screen)
|
|
self.ui.buttonSwitchGroup.clicked.connect(self.action_next_group)
|
|
self.ui.buttonClearData.clicked.connect(self.action_clear_group)
|
|
self.ui.buttonRotateScreen.clicked.connect(self.action_rotate_screen)
|
|
|
|
# --- Plot setup ---
|
|
self._setup_plots()
|
|
self.timer_step = 0
|
|
# timer = QTimer(self)
|
|
# timer.timeout.connect(self.update_graphs)
|
|
# timer.start(50)
|
|
|
|
def _setup_plots(self):
|
|
self.ui.plotVoltage = QtCharts.QChart()
|
|
self.ui.widgetVoltage.setChart(self.ui.plotVoltage)
|
|
|
|
self.ui.plotCurrent = QtCharts.QChart()
|
|
self.ui.widgetCurrent.setChart(self.ui.plotCurrent)
|
|
|
|
# --- Voltage ---
|
|
self.voltage = self.ui.plotVoltage
|
|
self.voltage_series = QtCharts.QLineSeries(self)
|
|
self.voltage_series.setName('Voltage over time')
|
|
self.voltage_series.setUseOpenGL(True)
|
|
self.voltage.addSeries(self.voltage_series)
|
|
|
|
axis_x = QtCharts.QValueAxis()
|
|
axis_x.setRange(0, 0)
|
|
# axis_x.setTickCount(1)
|
|
axis_x.setTickInterval(0.001)
|
|
axis_x.setTitleText('Seconds')
|
|
self.voltage.addAxis(axis_x, Qt.AlignBottom)
|
|
self.voltage_series.attachAxis(axis_x)
|
|
|
|
axis_y = QtCharts.QValueAxis()
|
|
# axis_y.setTickCount(1)
|
|
axis_y.setRange(0, 10)
|
|
axis_y.setTitleText('Voltage (V)')
|
|
self.voltage.addAxis(axis_y, Qt.AlignLeft)
|
|
self.voltage_series.attachAxis(axis_y)
|
|
|
|
# --- Current ---
|
|
self.current = self.ui.plotCurrent
|
|
self.current_series = QtCharts.QLineSeries(self)
|
|
self.current_series.setName('Current over time')
|
|
self.current_series.setUseOpenGL(True)
|
|
self.current.addSeries(self.current_series)
|
|
|
|
axis_x = QtCharts.QValueAxis()
|
|
axis_x.setRange(0, 60000)
|
|
# axis_x.setTickCount(1)
|
|
# axis_x.setTickInterval(1)
|
|
axis_x.setTitleText('Seconds')
|
|
self.current.addAxis(axis_x, Qt.AlignBottom)
|
|
self.current_series.attachAxis(axis_x)
|
|
|
|
axis_y = QtCharts.QValueAxis()
|
|
# axis_y.setTickCount(1)
|
|
axis_y.setRange(0, 10)
|
|
axis_y.setTitleText('Current (A)')
|
|
self.current.addAxis(axis_y, Qt.AlignLeft)
|
|
self.current_series.attachAxis(axis_y)
|
|
|
|
def action_next_screen(self):
|
|
um24c.send_command(um24c.Command.NEXT_SCREEN)
|
|
|
|
def action_next_group(self):
|
|
um24c.send_command(um24c.Command.NEXT_GROUP)
|
|
|
|
def action_rotate_screen(self):
|
|
um24c.send_command(um24c.Command.ROTATE_SCREEN)
|
|
|
|
def action_clear_group(self):
|
|
um24c.send_command(um24c.Command.CLEAR_GROUP)
|
|
|
|
def do_discover_devices(self, progress_callback):
|
|
return um24c.discover_devices()
|
|
|
|
def discover_devices_finished(self):
|
|
if self.ui.comboDevices.count() > 0:
|
|
self.ui.comboDevices.setEnabled(True)
|
|
self.ui.buttonConnection.setEnabled(True)
|
|
|
|
def discover_devices_result(self, devices):
|
|
for device in devices:
|
|
self.ui.comboDevices.addItem(device[0])
|
|
self.ui.buttonConnection.clicked.connect(self.action_connect_device)
|
|
|
|
def action_discover_devices(self):
|
|
worker = UM24LabUIWorker(self.do_discover_devices)
|
|
worker.signals.result.connect(self.discover_devices_result)
|
|
worker.signals.finished.connect(self.discover_devices_finished)
|
|
# worker.signals.progress.connect(...)
|
|
self.threadpool.start(worker)
|
|
|
|
def do_connect_device(self, progress_callback):
|
|
if not um24c.is_connected():
|
|
um24c.connect(self.ui.comboDevices.currentText())
|
|
if um24c.is_connected():
|
|
self.ui.buttonConnection.setText('Disconnect')
|
|
self.ui.comboDevices.setEnabled(False)
|
|
return True
|
|
else:
|
|
um24c.disconnect()
|
|
if not um24c.is_connected():
|
|
self.ui.buttonConnection.setText('Connect')
|
|
self.ui.comboDevices.setEnabled(True)
|
|
return False
|
|
|
|
def connect_device_result(self, status):
|
|
self.ui.comboDevices.setEnabled(not status)
|
|
if status:
|
|
self.ui.buttonConnection.setText('Disconnect')
|
|
self.action_update_stats()
|
|
else:
|
|
self.ui.buttonConnection.setText('Connect')
|
|
|
|
def action_connect_device(self):
|
|
worker = UM24LabUIWorker(self.do_connect_device)
|
|
worker.signals.result.connect(self.connect_device_result)
|
|
self.threadpool.start(worker)
|
|
|
|
def do_update_stats(self, progress_callback):
|
|
return um24c.get_meter_stats()
|
|
|
|
def update_stats_progress(self, current):
|
|
self.meter_stats = current
|
|
self.update_graphs()
|
|
|
|
def update_stats_finished(self):
|
|
ui = self.ui
|
|
ui.lcdVoltage.display(self.meter_stats.Voltage / 100)
|
|
ui.lcdCurrent.display(self.meter_stats.Current / 1000)
|
|
ui.lcdImpedance.display(self.meter_stats.Load_equivalent_impedance
|
|
/ 10)
|
|
ui.lcdPower.display(self.meter_stats.Power / 1000)
|
|
ui.lcdTempC.display(self.meter_stats.Temperature_Celcius)
|
|
ui.lcdTempF.display(self.meter_stats.Temperature_Fahrenheit)
|
|
ui.progressTempC.setValue(self.meter_stats.Temperature_Celcius)
|
|
ui.progressTempF.setValue(self.meter_stats.Temperature_Fahrenheit)
|
|
ui.lcdDataMinus.display(self.meter_stats.DMinus / 100)
|
|
ui.lcdDataPlus.display(self.meter_stats.DPlus / 100)
|
|
ui.lcdCapacityRecorded.display(self.meter_stats.Recorded_Capacity)
|
|
ui.lcdEnergyRecorded.display(self.meter_stats.Recorded_Energy)
|
|
ui.spinStopCurrent.setValue(self.meter_stats.Current_Trigger / 100)
|
|
ui.sliderBrightness.setValue(self.meter_stats.Display_brightness)
|
|
ui.sliderScreenOff.setValue(self.meter_stats.Display_timeout)
|
|
ui.buttonGroup.buttons()[self.meter_stats.Current_screen] \
|
|
.setChecked(True)
|
|
|
|
def action_update_stats(self):
|
|
worker = UM24LabWorker(self.do_update_stats)
|
|
worker.signals.progress.connect(self.update_stats_progress)
|
|
worker.signals.finished.connect(self.update_stats_finished)
|
|
self.threadpool.start(worker)
|
|
|
|
def update_graphs(self):
|
|
if um24c.is_connected() and self.meter_stats:
|
|
ui = self.ui
|
|
ui.lcdVoltage.display(self.meter_stats.Voltage / 100)
|
|
ui.lcdCurrent.display(self.meter_stats.Current / 1000)
|
|
ui.lcdImpedance.display(self.meter_stats.Load_equivalent_impedance
|
|
/ 10)
|
|
ui.lcdPower.display(self.meter_stats.Power / 1000)
|
|
ui.lcdTempC.display(self.meter_stats.Temperature_Celcius)
|
|
ui.lcdTempF.display(self.meter_stats.Temperature_Fahrenheit)
|
|
ui.progressTempC.setValue(self.meter_stats.Temperature_Celcius)
|
|
ui.progressTempF.setValue(self.meter_stats.Temperature_Fahrenheit)
|
|
ui.lcdDataMinus.display(self.meter_stats.DMinus / 100)
|
|
ui.lcdDataPlus.display(self.meter_stats.DPlus / 100)
|
|
ui.lcdCapacityRecorded.display(self.meter_stats.Recorded_Capacity)
|
|
ui.lcdEnergyRecorded.display(self.meter_stats.Recorded_Energy)
|
|
ui.spinStopCurrent.setValue(self.meter_stats.Current_Trigger / 100)
|
|
ui.sliderBrightness.setValue(self.meter_stats.Display_brightness)
|
|
ui.sliderScreenOff.setValue(self.meter_stats.Display_timeout)
|
|
ui.buttonGroup.buttons()[self.meter_stats.Current_screen] \
|
|
.setChecked(True)
|
|
|
|
# self.voltage_series.append(self.timer_step, random.randint(0, 10))
|
|
# self.current_series.append(self.timer_step, random.randint(0, 10))
|
|
# self.timer_step += 1
|
|
# for axis in self.voltage_series.attachedAxes():
|
|
# if axis.orientation() == Qt.Orientation.Horizontal:
|
|
# axis.setRange(0, self.timer_step)
|
|
# for axis in self.current_series.attachedAxes():
|
|
# if axis.orientation() == Qt.Orientation.Horizontal:
|
|
# axis.setRange(0, self.timer_step)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app = QApplication(sys.argv)
|
|
|
|
labview = UM24Lab()
|
|
labview.show()
|
|
|
|
sys.exit(app.exec_())
|