From cc58b11aef870b7cbe7cfb6333515775ebff54b4 Mon Sep 17 00:00:00 2001 From: JayPiKay Date: Fri, 24 Jan 2020 10:29:45 +0100 Subject: [PATCH 1/2] Displaying first real data from the meter --- .python-version | 1 - requirements.txt | 1 - src/UM24CUI.py | 957 +++++++++++++++++++++++++++++++++++++++++++++ src/meter/um24c.py | 104 ++++- src/um24clab.py | 82 ++-- 5 files changed, 1116 insertions(+), 29 deletions(-) delete mode 100644 .python-version create mode 100644 src/UM24CUI.py diff --git a/.python-version b/.python-version deleted file mode 100644 index de84bc6..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -py3 diff --git a/requirements.txt b/requirements.txt index c075bf2..6d656f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,5 @@ PyBluez==0.23 PyOpenGL==3.1.5 PyQt5==5.14.1 PyQt5-sip==12.7.0 -pyqtgraph==0.10.0 PySide2==5.14.0 shiboken2==5.14.0 diff --git a/src/UM24CUI.py b/src/UM24CUI.py new file mode 100644 index 0000000..efea25a --- /dev/null +++ b/src/UM24CUI.py @@ -0,0 +1,957 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'MainWindow.ui' +## +## Created by: Qt User Interface Compiler version 5.14.0 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint, + QRect, QSize, QUrl, Qt) +from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QFont, + QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap, + QRadialGradient) +from PySide2.QtCharts import (QtCharts) +from PySide2.QtWidgets import * + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + if MainWindow.objectName(): + MainWindow.setObjectName(u"MainWindow") + MainWindow.resize(1280, 940) + MainWindow.setMinimumSize(QSize(1280, 940)) + self.centralwidget = QWidget(MainWindow) + self.centralwidget.setObjectName(u"centralwidget") + self.horizontalLayout = QHBoxLayout(self.centralwidget) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.widget = QWidget(self.centralwidget) + self.widget.setObjectName(u"widget") + sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth()) + self.widget.setSizePolicy(sizePolicy) + self.verticalLayout = QVBoxLayout(self.widget) + self.verticalLayout.setObjectName(u"verticalLayout") + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.frame = QFrame(self.widget) + self.frame.setObjectName(u"frame") + sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy1) + self.frame.setFrameShape(QFrame.StyledPanel) + self.frame.setFrameShadow(QFrame.Raised) + self.horizontalLayout_2 = QHBoxLayout(self.frame) + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.comboDevices = QComboBox(self.frame) + self.comboDevices.setObjectName(u"comboDevices") + + self.horizontalLayout_2.addWidget(self.comboDevices) + + self.buttonConnection = QPushButton(self.frame) + self.buttonConnection.setObjectName(u"buttonConnection") + self.buttonConnection.setFlat(False) + + self.horizontalLayout_2.addWidget(self.buttonConnection) + + + self.verticalLayout.addWidget(self.frame) + + self.frame_2 = QFrame(self.widget) + self.frame_2.setObjectName(u"frame_2") + sizePolicy1.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth()) + self.frame_2.setSizePolicy(sizePolicy1) + self.frame_2.setFrameShape(QFrame.StyledPanel) + self.frame_2.setFrameShadow(QFrame.Raised) + self.frame_2.setLineWidth(1) + self.verticalLayout_2 = QVBoxLayout(self.frame_2) + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.verticalLayout_2.setContentsMargins(0, 0, 0, 9) + self.widget_2 = QWidget(self.frame_2) + self.widget_2.setObjectName(u"widget_2") + sizePolicy1.setHeightForWidth(self.widget_2.sizePolicy().hasHeightForWidth()) + self.widget_2.setSizePolicy(sizePolicy1) + self.horizontalLayout_3 = QHBoxLayout(self.widget_2) + self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") + self.horizontalLayout_3.setContentsMargins(-1, 9, -1, 0) + self.radioButton = QRadioButton(self.widget_2) + self.buttonGroup = QButtonGroup(MainWindow) + self.buttonGroup.setObjectName(u"buttonGroup") + self.buttonGroup.addButton(self.radioButton) + self.radioButton.setObjectName(u"radioButton") + sizePolicy2 = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.radioButton.sizePolicy().hasHeightForWidth()) + self.radioButton.setSizePolicy(sizePolicy2) + self.radioButton.setCheckable(False) + self.radioButton.setChecked(False) + + self.horizontalLayout_3.addWidget(self.radioButton) + + self.radioButton_3 = QRadioButton(self.widget_2) + self.buttonGroup.addButton(self.radioButton_3) + self.radioButton_3.setObjectName(u"radioButton_3") + sizePolicy2.setHeightForWidth(self.radioButton_3.sizePolicy().hasHeightForWidth()) + self.radioButton_3.setSizePolicy(sizePolicy2) + self.radioButton_3.setCheckable(False) + self.radioButton_3.setChecked(False) + + self.horizontalLayout_3.addWidget(self.radioButton_3) + + self.radioButton_5 = QRadioButton(self.widget_2) + self.buttonGroup.addButton(self.radioButton_5) + self.radioButton_5.setObjectName(u"radioButton_5") + sizePolicy2.setHeightForWidth(self.radioButton_5.sizePolicy().hasHeightForWidth()) + self.radioButton_5.setSizePolicy(sizePolicy2) + self.radioButton_5.setCheckable(False) + self.radioButton_5.setChecked(False) + + self.horizontalLayout_3.addWidget(self.radioButton_5) + + self.radioButton_4 = QRadioButton(self.widget_2) + self.buttonGroup.addButton(self.radioButton_4) + self.radioButton_4.setObjectName(u"radioButton_4") + sizePolicy2.setHeightForWidth(self.radioButton_4.sizePolicy().hasHeightForWidth()) + self.radioButton_4.setSizePolicy(sizePolicy2) + self.radioButton_4.setCheckable(False) + self.radioButton_4.setChecked(False) + + self.horizontalLayout_3.addWidget(self.radioButton_4) + + self.radioButton_2 = QRadioButton(self.widget_2) + self.buttonGroup.addButton(self.radioButton_2) + self.radioButton_2.setObjectName(u"radioButton_2") + sizePolicy2.setHeightForWidth(self.radioButton_2.sizePolicy().hasHeightForWidth()) + self.radioButton_2.setSizePolicy(sizePolicy2) + self.radioButton_2.setCheckable(False) + self.radioButton_2.setChecked(False) + + self.horizontalLayout_3.addWidget(self.radioButton_2) + + self.radioButton_6 = QRadioButton(self.widget_2) + self.buttonGroup.addButton(self.radioButton_6) + self.radioButton_6.setObjectName(u"radioButton_6") + sizePolicy2.setHeightForWidth(self.radioButton_6.sizePolicy().hasHeightForWidth()) + self.radioButton_6.setSizePolicy(sizePolicy2) + self.radioButton_6.setCheckable(False) + self.radioButton_6.setChecked(False) + + self.horizontalLayout_3.addWidget(self.radioButton_6) + + self.radioButton_7 = QRadioButton(self.widget_2) + self.buttonGroup.addButton(self.radioButton_7) + self.radioButton_7.setObjectName(u"radioButton_7") + sizePolicy2.setHeightForWidth(self.radioButton_7.sizePolicy().hasHeightForWidth()) + self.radioButton_7.setSizePolicy(sizePolicy2) + self.radioButton_7.setCheckable(False) + self.radioButton_7.setChecked(False) + + self.horizontalLayout_3.addWidget(self.radioButton_7) + + + self.verticalLayout_2.addWidget(self.widget_2) + + self.widget_3 = QWidget(self.frame_2) + self.widget_3.setObjectName(u"widget_3") + sizePolicy1.setHeightForWidth(self.widget_3.sizePolicy().hasHeightForWidth()) + self.widget_3.setSizePolicy(sizePolicy1) + self.horizontalLayout_4 = QHBoxLayout(self.widget_3) + self.horizontalLayout_4.setObjectName(u"horizontalLayout_4") + self.horizontalLayout_4.setContentsMargins(-1, 0, 9, 0) + self.buttonRotateScreen = QPushButton(self.widget_3) + self.buttonRotateScreen.setObjectName(u"buttonRotateScreen") + sizePolicy3 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) + sizePolicy3.setHorizontalStretch(0) + sizePolicy3.setVerticalStretch(0) + sizePolicy3.setHeightForWidth(self.buttonRotateScreen.sizePolicy().hasHeightForWidth()) + self.buttonRotateScreen.setSizePolicy(sizePolicy3) + + self.horizontalLayout_4.addWidget(self.buttonRotateScreen) + + self.buttonNextScreen = QPushButton(self.widget_3) + self.buttonNextScreen.setObjectName(u"buttonNextScreen") + + self.horizontalLayout_4.addWidget(self.buttonNextScreen) + + + self.verticalLayout_2.addWidget(self.widget_3) + + + self.verticalLayout.addWidget(self.frame_2) + + self.frame_3 = QFrame(self.widget) + self.frame_3.setObjectName(u"frame_3") + self.frame_3.setFrameShape(QFrame.StyledPanel) + self.frame_3.setFrameShadow(QFrame.Raised) + self.verticalLayout_3 = QVBoxLayout(self.frame_3) + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.widget_4 = QWidget(self.frame_3) + self.widget_4.setObjectName(u"widget_4") + sizePolicy1.setHeightForWidth(self.widget_4.sizePolicy().hasHeightForWidth()) + self.widget_4.setSizePolicy(sizePolicy1) + self.horizontalLayout_5 = QHBoxLayout(self.widget_4) + self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") + self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) + self.buttonSwitchGroup = QPushButton(self.widget_4) + self.buttonSwitchGroup.setObjectName(u"buttonSwitchGroup") + + self.horizontalLayout_5.addWidget(self.buttonSwitchGroup) + + self.buttonClearData = QPushButton(self.widget_4) + self.buttonClearData.setObjectName(u"buttonClearData") + + self.horizontalLayout_5.addWidget(self.buttonClearData) + + + self.verticalLayout_3.addWidget(self.widget_4) + + self.tableView = QTableView(self.frame_3) + self.tableView.setObjectName(u"tableView") + self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers) + + self.verticalLayout_3.addWidget(self.tableView) + + + self.verticalLayout.addWidget(self.frame_3) + + + self.horizontalLayout.addWidget(self.widget) + + self.widget_5 = QWidget(self.centralwidget) + self.widget_5.setObjectName(u"widget_5") + self.verticalLayout_4 = QVBoxLayout(self.widget_5) + self.verticalLayout_4.setSpacing(6) + self.verticalLayout_4.setObjectName(u"verticalLayout_4") + self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) + self.framePlots = QFrame(self.widget_5) + self.framePlots.setObjectName(u"framePlots") + sizePolicy4 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) + sizePolicy4.setHorizontalStretch(0) + sizePolicy4.setVerticalStretch(0) + sizePolicy4.setHeightForWidth(self.framePlots.sizePolicy().hasHeightForWidth()) + self.framePlots.setSizePolicy(sizePolicy4) + self.framePlots.setFrameShape(QFrame.StyledPanel) + self.framePlots.setFrameShadow(QFrame.Raised) + self.horizontalLayout_7 = QHBoxLayout(self.framePlots) + self.horizontalLayout_7.setObjectName(u"horizontalLayout_7") + self.widgetVoltage = QtCharts.QChartView() + self.widgetVoltage.setObjectName(u"widgetVoltage") + + self.horizontalLayout_7.addWidget(self.widgetVoltage) + + self.widgetCurrent = QtCharts.QChartView() + self.widgetCurrent.setObjectName(u"widgetCurrent") + + self.horizontalLayout_7.addWidget(self.widgetCurrent) + + + self.verticalLayout_4.addWidget(self.framePlots) + + self.widget_6 = QWidget(self.widget_5) + self.widget_6.setObjectName(u"widget_6") + self.horizontalLayout_6 = QHBoxLayout(self.widget_6) + self.horizontalLayout_6.setObjectName(u"horizontalLayout_6") + self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) + self.frame_5 = QFrame(self.widget_6) + self.frame_5.setObjectName(u"frame_5") + self.frame_5.setFrameShape(QFrame.StyledPanel) + self.frame_5.setFrameShadow(QFrame.Raised) + self.verticalLayout_14 = QVBoxLayout(self.frame_5) + self.verticalLayout_14.setObjectName(u"verticalLayout_14") + self.widget_8 = QWidget(self.frame_5) + self.widget_8.setObjectName(u"widget_8") + self.verticalLayout_6 = QVBoxLayout(self.widget_8) + self.verticalLayout_6.setObjectName(u"verticalLayout_6") + self.verticalLayout_6.setContentsMargins(-1, 0, -1, 0) + self.widget_9 = QWidget(self.widget_8) + self.widget_9.setObjectName(u"widget_9") + self.verticalLayout_7 = QVBoxLayout(self.widget_9) + self.verticalLayout_7.setObjectName(u"verticalLayout_7") + self.label_2 = QLabel(self.widget_9) + self.label_2.setObjectName(u"label_2") + font = QFont() + font.setPointSize(14) + self.label_2.setFont(font) + + self.verticalLayout_7.addWidget(self.label_2) + + + self.verticalLayout_6.addWidget(self.widget_9) + + self.widget_10 = QWidget(self.widget_8) + self.widget_10.setObjectName(u"widget_10") + self.horizontalLayout_8 = QHBoxLayout(self.widget_10) + self.horizontalLayout_8.setObjectName(u"horizontalLayout_8") + self.horizontalLayout_8.setContentsMargins(9, 0, -1, -1) + self.lcdVoltage = QLCDNumber(self.widget_10) + self.lcdVoltage.setObjectName(u"lcdVoltage") + font1 = QFont() + font1.setPointSize(10) + self.lcdVoltage.setFont(font1) + self.lcdVoltage.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_8.addWidget(self.lcdVoltage) + + self.label = QLabel(self.widget_10) + self.label.setObjectName(u"label") + self.label.setFont(font) + + self.horizontalLayout_8.addWidget(self.label) + + + self.verticalLayout_6.addWidget(self.widget_10) + + + self.verticalLayout_14.addWidget(self.widget_8) + + self.widget_17 = QWidget(self.frame_5) + self.widget_17.setObjectName(u"widget_17") + self.verticalLayout_12 = QVBoxLayout(self.widget_17) + self.verticalLayout_12.setObjectName(u"verticalLayout_12") + self.verticalLayout_12.setContentsMargins(-1, 0, -1, 0) + self.widget_18 = QWidget(self.widget_17) + self.widget_18.setObjectName(u"widget_18") + self.verticalLayout_13 = QVBoxLayout(self.widget_18) + self.verticalLayout_13.setObjectName(u"verticalLayout_13") + self.label_7 = QLabel(self.widget_18) + self.label_7.setObjectName(u"label_7") + self.label_7.setFont(font) + + self.verticalLayout_13.addWidget(self.label_7) + + + self.verticalLayout_12.addWidget(self.widget_18) + + self.widget_19 = QWidget(self.widget_17) + self.widget_19.setObjectName(u"widget_19") + self.horizontalLayout_11 = QHBoxLayout(self.widget_19) + self.horizontalLayout_11.setObjectName(u"horizontalLayout_11") + self.horizontalLayout_11.setContentsMargins(9, 0, -1, -1) + self.lcdCurrent = QLCDNumber(self.widget_19) + self.lcdCurrent.setObjectName(u"lcdCurrent") + self.lcdCurrent.setFont(font1) + self.lcdCurrent.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_11.addWidget(self.lcdCurrent) + + self.label_8 = QLabel(self.widget_19) + self.label_8.setObjectName(u"label_8") + self.label_8.setFont(font) + + self.horizontalLayout_11.addWidget(self.label_8) + + + self.verticalLayout_12.addWidget(self.widget_19) + + + self.verticalLayout_14.addWidget(self.widget_17) + + self.widget_11 = QWidget(self.frame_5) + self.widget_11.setObjectName(u"widget_11") + self.verticalLayout_8 = QVBoxLayout(self.widget_11) + self.verticalLayout_8.setObjectName(u"verticalLayout_8") + self.verticalLayout_8.setContentsMargins(-1, 0, -1, 0) + self.widget_12 = QWidget(self.widget_11) + self.widget_12.setObjectName(u"widget_12") + self.verticalLayout_9 = QVBoxLayout(self.widget_12) + self.verticalLayout_9.setObjectName(u"verticalLayout_9") + self.label_3 = QLabel(self.widget_12) + self.label_3.setObjectName(u"label_3") + self.label_3.setFont(font) + + self.verticalLayout_9.addWidget(self.label_3) + + + self.verticalLayout_8.addWidget(self.widget_12) + + self.widget_13 = QWidget(self.widget_11) + self.widget_13.setObjectName(u"widget_13") + self.horizontalLayout_9 = QHBoxLayout(self.widget_13) + self.horizontalLayout_9.setObjectName(u"horizontalLayout_9") + self.horizontalLayout_9.setContentsMargins(9, 0, -1, -1) + self.lcdPower = QLCDNumber(self.widget_13) + self.lcdPower.setObjectName(u"lcdPower") + self.lcdPower.setFont(font1) + self.lcdPower.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_9.addWidget(self.lcdPower) + + self.label_4 = QLabel(self.widget_13) + self.label_4.setObjectName(u"label_4") + self.label_4.setFont(font) + + self.horizontalLayout_9.addWidget(self.label_4) + + + self.verticalLayout_8.addWidget(self.widget_13) + + + self.verticalLayout_14.addWidget(self.widget_11) + + self.widget_14 = QWidget(self.frame_5) + self.widget_14.setObjectName(u"widget_14") + self.verticalLayout_10 = QVBoxLayout(self.widget_14) + self.verticalLayout_10.setObjectName(u"verticalLayout_10") + self.verticalLayout_10.setContentsMargins(-1, 0, -1, 0) + self.widget_15 = QWidget(self.widget_14) + self.widget_15.setObjectName(u"widget_15") + self.verticalLayout_11 = QVBoxLayout(self.widget_15) + self.verticalLayout_11.setObjectName(u"verticalLayout_11") + self.label_5 = QLabel(self.widget_15) + self.label_5.setObjectName(u"label_5") + self.label_5.setFont(font) + + self.verticalLayout_11.addWidget(self.label_5) + + + self.verticalLayout_10.addWidget(self.widget_15) + + self.widget_16 = QWidget(self.widget_14) + self.widget_16.setObjectName(u"widget_16") + self.horizontalLayout_10 = QHBoxLayout(self.widget_16) + self.horizontalLayout_10.setObjectName(u"horizontalLayout_10") + self.horizontalLayout_10.setContentsMargins(9, 0, -1, -1) + self.lcdImpedance = QLCDNumber(self.widget_16) + self.lcdImpedance.setObjectName(u"lcdImpedance") + self.lcdImpedance.setFont(font1) + self.lcdImpedance.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_10.addWidget(self.lcdImpedance) + + self.label_6 = QLabel(self.widget_16) + self.label_6.setObjectName(u"label_6") + self.label_6.setFont(font) + + self.horizontalLayout_10.addWidget(self.label_6) + + + self.verticalLayout_10.addWidget(self.widget_16) + + + self.verticalLayout_14.addWidget(self.widget_14) + + + self.horizontalLayout_6.addWidget(self.frame_5) + + self.frame_6 = QFrame(self.widget_6) + self.frame_6.setObjectName(u"frame_6") + self.frame_6.setFrameShape(QFrame.StyledPanel) + self.frame_6.setFrameShadow(QFrame.Raised) + self.verticalLayout_23 = QVBoxLayout(self.frame_6) + self.verticalLayout_23.setObjectName(u"verticalLayout_23") + self.widget_20 = QWidget(self.frame_6) + self.widget_20.setObjectName(u"widget_20") + self.verticalLayout_15 = QVBoxLayout(self.widget_20) + self.verticalLayout_15.setObjectName(u"verticalLayout_15") + self.verticalLayout_15.setContentsMargins(-1, 0, -1, 0) + self.widget_21 = QWidget(self.widget_20) + self.widget_21.setObjectName(u"widget_21") + self.verticalLayout_16 = QVBoxLayout(self.widget_21) + self.verticalLayout_16.setObjectName(u"verticalLayout_16") + self.verticalLayout_16.setContentsMargins(-1, -1, -1, 0) + self.label_9 = QLabel(self.widget_21) + self.label_9.setObjectName(u"label_9") + self.label_9.setFont(font) + + self.verticalLayout_16.addWidget(self.label_9) + + + self.verticalLayout_15.addWidget(self.widget_21) + + self.widget_22 = QWidget(self.widget_20) + self.widget_22.setObjectName(u"widget_22") + self.horizontalLayout_12 = QHBoxLayout(self.widget_22) + self.horizontalLayout_12.setObjectName(u"horizontalLayout_12") + self.horizontalLayout_12.setContentsMargins(-1, 0, -1, 0) + self.lcdCapacityRecorded = QLCDNumber(self.widget_22) + self.lcdCapacityRecorded.setObjectName(u"lcdCapacityRecorded") + self.lcdCapacityRecorded.setFont(font1) + self.lcdCapacityRecorded.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_12.addWidget(self.lcdCapacityRecorded) + + self.label_10 = QLabel(self.widget_22) + self.label_10.setObjectName(u"label_10") + self.label_10.setFont(font) + + self.horizontalLayout_12.addWidget(self.label_10) + + + self.verticalLayout_15.addWidget(self.widget_22) + + + self.verticalLayout_23.addWidget(self.widget_20) + + self.widget_29 = QWidget(self.frame_6) + self.widget_29.setObjectName(u"widget_29") + self.verticalLayout_21 = QVBoxLayout(self.widget_29) + self.verticalLayout_21.setObjectName(u"verticalLayout_21") + self.verticalLayout_21.setContentsMargins(-1, 0, -1, 0) + self.widget_30 = QWidget(self.widget_29) + self.widget_30.setObjectName(u"widget_30") + self.verticalLayout_22 = QVBoxLayout(self.widget_30) + self.verticalLayout_22.setObjectName(u"verticalLayout_22") + self.verticalLayout_22.setContentsMargins(-1, -1, -1, 0) + self.label_15 = QLabel(self.widget_30) + self.label_15.setObjectName(u"label_15") + self.label_15.setFont(font) + + self.verticalLayout_22.addWidget(self.label_15) + + + self.verticalLayout_21.addWidget(self.widget_30) + + self.widget_31 = QWidget(self.widget_29) + self.widget_31.setObjectName(u"widget_31") + self.horizontalLayout_15 = QHBoxLayout(self.widget_31) + self.horizontalLayout_15.setObjectName(u"horizontalLayout_15") + self.horizontalLayout_15.setContentsMargins(-1, 0, -1, 0) + self.lcdEnergyRecorded = QLCDNumber(self.widget_31) + self.lcdEnergyRecorded.setObjectName(u"lcdEnergyRecorded") + self.lcdEnergyRecorded.setFont(font1) + self.lcdEnergyRecorded.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_15.addWidget(self.lcdEnergyRecorded) + + self.label_16 = QLabel(self.widget_31) + self.label_16.setObjectName(u"label_16") + self.label_16.setFont(font) + + self.horizontalLayout_15.addWidget(self.label_16) + + + self.verticalLayout_21.addWidget(self.widget_31) + + + self.verticalLayout_23.addWidget(self.widget_29) + + self.widget_23 = QWidget(self.frame_6) + self.widget_23.setObjectName(u"widget_23") + self.verticalLayout_17 = QVBoxLayout(self.widget_23) + self.verticalLayout_17.setObjectName(u"verticalLayout_17") + self.verticalLayout_17.setContentsMargins(-1, 0, -1, 0) + self.widget_24 = QWidget(self.widget_23) + self.widget_24.setObjectName(u"widget_24") + self.verticalLayout_18 = QVBoxLayout(self.widget_24) + self.verticalLayout_18.setObjectName(u"verticalLayout_18") + self.verticalLayout_18.setContentsMargins(-1, -1, -1, 0) + self.label_11 = QLabel(self.widget_24) + self.label_11.setObjectName(u"label_11") + self.label_11.setFont(font) + + self.verticalLayout_18.addWidget(self.label_11) + + + self.verticalLayout_17.addWidget(self.widget_24) + + self.widget_25 = QWidget(self.widget_23) + self.widget_25.setObjectName(u"widget_25") + self.horizontalLayout_13 = QHBoxLayout(self.widget_25) + self.horizontalLayout_13.setObjectName(u"horizontalLayout_13") + self.spinStopCurrent = QDoubleSpinBox(self.widget_25) + self.spinStopCurrent.setObjectName(u"spinStopCurrent") + self.spinStopCurrent.setFont(font) + self.spinStopCurrent.setReadOnly(True) + self.spinStopCurrent.setButtonSymbols(QAbstractSpinBox.PlusMinus) + self.spinStopCurrent.setMaximum(0.300000000000000) + self.spinStopCurrent.setSingleStep(0.010000000000000) + self.spinStopCurrent.setValue(0.120000000000000) + + self.horizontalLayout_13.addWidget(self.spinStopCurrent) + + self.label_12 = QLabel(self.widget_25) + self.label_12.setObjectName(u"label_12") + sizePolicy5 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) + sizePolicy5.setHorizontalStretch(0) + sizePolicy5.setVerticalStretch(0) + sizePolicy5.setHeightForWidth(self.label_12.sizePolicy().hasHeightForWidth()) + self.label_12.setSizePolicy(sizePolicy5) + self.label_12.setFont(font) + + self.horizontalLayout_13.addWidget(self.label_12) + + + self.verticalLayout_17.addWidget(self.widget_25) + + + self.verticalLayout_23.addWidget(self.widget_23) + + self.widget_26 = QWidget(self.frame_6) + self.widget_26.setObjectName(u"widget_26") + self.verticalLayout_19 = QVBoxLayout(self.widget_26) + self.verticalLayout_19.setObjectName(u"verticalLayout_19") + self.verticalLayout_19.setContentsMargins(-1, 0, -1, 0) + self.widget_27 = QWidget(self.widget_26) + self.widget_27.setObjectName(u"widget_27") + self.verticalLayout_20 = QVBoxLayout(self.widget_27) + self.verticalLayout_20.setObjectName(u"verticalLayout_20") + self.verticalLayout_20.setContentsMargins(-1, -1, -1, 0) + self.label_13 = QLabel(self.widget_27) + self.label_13.setObjectName(u"label_13") + self.label_13.setFont(font) + + self.verticalLayout_20.addWidget(self.label_13) + + + self.verticalLayout_19.addWidget(self.widget_27) + + self.widget_28 = QWidget(self.widget_26) + self.widget_28.setObjectName(u"widget_28") + self.horizontalLayout_14 = QHBoxLayout(self.widget_28) + self.horizontalLayout_14.setObjectName(u"horizontalLayout_14") + self.horizontalLayout_14.setContentsMargins(0, 0, 0, 0) + self.frame_4 = QFrame(self.widget_28) + self.frame_4.setObjectName(u"frame_4") + self.frame_4.setFrameShape(QFrame.StyledPanel) + self.frame_4.setFrameShadow(QFrame.Raised) + self.horizontalLayout_22 = QHBoxLayout(self.frame_4) + self.horizontalLayout_22.setObjectName(u"horizontalLayout_22") + self.labelTimeRecorded = QLabel(self.frame_4) + self.labelTimeRecorded.setObjectName(u"labelTimeRecorded") + font2 = QFont() + font2.setPointSize(16) + self.labelTimeRecorded.setFont(font2) + self.labelTimeRecorded.setAlignment(Qt.AlignCenter) + + self.horizontalLayout_22.addWidget(self.labelTimeRecorded) + + + self.horizontalLayout_14.addWidget(self.frame_4) + + + self.verticalLayout_19.addWidget(self.widget_28) + + + self.verticalLayout_23.addWidget(self.widget_26) + + + self.horizontalLayout_6.addWidget(self.frame_6) + + self.widget_7 = QWidget(self.widget_6) + self.widget_7.setObjectName(u"widget_7") + self.verticalLayout_5 = QVBoxLayout(self.widget_7) + self.verticalLayout_5.setSpacing(6) + self.verticalLayout_5.setObjectName(u"verticalLayout_5") + self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) + self.frame_8 = QFrame(self.widget_7) + self.frame_8.setObjectName(u"frame_8") + self.frame_8.setFrameShape(QFrame.StyledPanel) + self.frame_8.setFrameShadow(QFrame.Raised) + self.verticalLayout_26 = QVBoxLayout(self.frame_8) + self.verticalLayout_26.setObjectName(u"verticalLayout_26") + self.widget_32 = QWidget(self.frame_8) + self.widget_32.setObjectName(u"widget_32") + self.verticalLayout_24 = QVBoxLayout(self.widget_32) + self.verticalLayout_24.setObjectName(u"verticalLayout_24") + self.label_17 = QLabel(self.widget_32) + self.label_17.setObjectName(u"label_17") + self.label_17.setFont(font) + self.label_17.setAlignment(Qt.AlignCenter) + + self.verticalLayout_24.addWidget(self.label_17) + + self.sliderBrightness = QSlider(self.widget_32) + self.sliderBrightness.setObjectName(u"sliderBrightness") + sizePolicy5.setHeightForWidth(self.sliderBrightness.sizePolicy().hasHeightForWidth()) + self.sliderBrightness.setSizePolicy(sizePolicy5) + self.sliderBrightness.setFont(font) + self.sliderBrightness.setMinimum(0) + self.sliderBrightness.setMaximum(5) + self.sliderBrightness.setValue(4) + self.sliderBrightness.setOrientation(Qt.Horizontal) + self.sliderBrightness.setInvertedAppearance(False) + self.sliderBrightness.setInvertedControls(False) + self.sliderBrightness.setTickPosition(QSlider.TicksBelow) + self.sliderBrightness.setTickInterval(1) + + self.verticalLayout_24.addWidget(self.sliderBrightness) + + + self.verticalLayout_26.addWidget(self.widget_32) + + self.widget_33 = QWidget(self.frame_8) + self.widget_33.setObjectName(u"widget_33") + self.verticalLayout_25 = QVBoxLayout(self.widget_33) + self.verticalLayout_25.setObjectName(u"verticalLayout_25") + self.label_18 = QLabel(self.widget_33) + self.label_18.setObjectName(u"label_18") + self.label_18.setFont(font) + self.label_18.setAlignment(Qt.AlignCenter) + + self.verticalLayout_25.addWidget(self.label_18) + + self.sliderScreenOff = QSlider(self.widget_33) + self.sliderScreenOff.setObjectName(u"sliderScreenOff") + sizePolicy5.setHeightForWidth(self.sliderScreenOff.sizePolicy().hasHeightForWidth()) + self.sliderScreenOff.setSizePolicy(sizePolicy5) + self.sliderScreenOff.setFont(font) + self.sliderScreenOff.setMaximum(9) + self.sliderScreenOff.setOrientation(Qt.Horizontal) + self.sliderScreenOff.setTickPosition(QSlider.TicksBelow) + self.sliderScreenOff.setTickInterval(1) + + self.verticalLayout_25.addWidget(self.sliderScreenOff) + + + self.verticalLayout_26.addWidget(self.widget_33) + + + self.verticalLayout_5.addWidget(self.frame_8) + + self.frame_9 = QFrame(self.widget_7) + self.frame_9.setObjectName(u"frame_9") + self.frame_9.setFrameShape(QFrame.StyledPanel) + self.frame_9.setFrameShadow(QFrame.Raised) + self.verticalLayout_27 = QVBoxLayout(self.frame_9) + self.verticalLayout_27.setObjectName(u"verticalLayout_27") + self.horizontalFrame = QFrame(self.frame_9) + self.horizontalFrame.setObjectName(u"horizontalFrame") + self.horizontalLayout_23 = QHBoxLayout(self.horizontalFrame) + self.horizontalLayout_23.setObjectName(u"horizontalLayout_23") + self.horizontalLayout_23.setContentsMargins(9, 9, 9, 9) + self.label_14 = QLabel(self.horizontalFrame) + self.label_14.setObjectName(u"label_14") + self.label_14.setFont(font) + + self.horizontalLayout_23.addWidget(self.label_14) + + self.lcdDataPlus = QLCDNumber(self.horizontalFrame) + self.lcdDataPlus.setObjectName(u"lcdDataPlus") + self.lcdDataPlus.setFont(font1) + self.lcdDataPlus.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_23.addWidget(self.lcdDataPlus) + + self.label_19 = QLabel(self.horizontalFrame) + self.label_19.setObjectName(u"label_19") + sizePolicy.setHeightForWidth(self.label_19.sizePolicy().hasHeightForWidth()) + self.label_19.setSizePolicy(sizePolicy) + self.label_19.setFont(font) + + self.horizontalLayout_23.addWidget(self.label_19) + + + self.verticalLayout_27.addWidget(self.horizontalFrame) + + self.widget_35 = QWidget(self.frame_9) + self.widget_35.setObjectName(u"widget_35") + self.horizontalLayout_17 = QHBoxLayout(self.widget_35) + self.horizontalLayout_17.setObjectName(u"horizontalLayout_17") + self.label_21 = QLabel(self.widget_35) + self.label_21.setObjectName(u"label_21") + self.label_21.setFont(font) + + self.horizontalLayout_17.addWidget(self.label_21) + + self.lcdDataMinus = QLCDNumber(self.widget_35) + self.lcdDataMinus.setObjectName(u"lcdDataMinus") + self.lcdDataMinus.setFont(font1) + self.lcdDataMinus.setFrameShadow(QFrame.Raised) + self.lcdDataMinus.setSegmentStyle(QLCDNumber.Flat) + self.lcdDataMinus.setProperty("value", 2.020000000000000) + + self.horizontalLayout_17.addWidget(self.lcdDataMinus) + + self.label_22 = QLabel(self.widget_35) + self.label_22.setObjectName(u"label_22") + sizePolicy.setHeightForWidth(self.label_22.sizePolicy().hasHeightForWidth()) + self.label_22.setSizePolicy(sizePolicy) + self.label_22.setFont(font) + + self.horizontalLayout_17.addWidget(self.label_22) + + + self.verticalLayout_27.addWidget(self.widget_35) + + self.frame_36 = QFrame(self.frame_9) + self.frame_36.setObjectName(u"frame_36") + self.frame_36.setFrameShape(QFrame.Box) + self.frame_36.setFrameShadow(QFrame.Raised) + self.horizontalLayout_18 = QHBoxLayout(self.frame_36) + self.horizontalLayout_18.setObjectName(u"horizontalLayout_18") + self.labelUSBMode = QLabel(self.frame_36) + self.labelUSBMode.setObjectName(u"labelUSBMode") + self.labelUSBMode.setFont(font) + self.labelUSBMode.setAlignment(Qt.AlignCenter) + + self.horizontalLayout_18.addWidget(self.labelUSBMode) + + + self.verticalLayout_27.addWidget(self.frame_36) + + + self.verticalLayout_5.addWidget(self.frame_9) + + + self.horizontalLayout_6.addWidget(self.widget_7) + + self.frame_7 = QFrame(self.widget_6) + self.frame_7.setObjectName(u"frame_7") + self.frame_7.setFrameShape(QFrame.StyledPanel) + self.frame_7.setFrameShadow(QFrame.Raised) + self.horizontalLayout_21 = QHBoxLayout(self.frame_7) + self.horizontalLayout_21.setObjectName(u"horizontalLayout_21") + self.widget_36 = QWidget(self.frame_7) + self.widget_36.setObjectName(u"widget_36") + self.verticalLayout_28 = QVBoxLayout(self.widget_36) + self.verticalLayout_28.setObjectName(u"verticalLayout_28") + self.widget_37 = QWidget(self.widget_36) + self.widget_37.setObjectName(u"widget_37") + sizePolicy1.setHeightForWidth(self.widget_37.sizePolicy().hasHeightForWidth()) + self.widget_37.setSizePolicy(sizePolicy1) + self.horizontalLayout_19 = QHBoxLayout(self.widget_37) + self.horizontalLayout_19.setObjectName(u"horizontalLayout_19") + self.lcdTempC = QLCDNumber(self.widget_37) + self.lcdTempC.setObjectName(u"lcdTempC") + sizePolicy6 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) + sizePolicy6.setHorizontalStretch(0) + sizePolicy6.setVerticalStretch(0) + sizePolicy6.setHeightForWidth(self.lcdTempC.sizePolicy().hasHeightForWidth()) + self.lcdTempC.setSizePolicy(sizePolicy6) + self.lcdTempC.setFont(font1) + self.lcdTempC.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_19.addWidget(self.lcdTempC) + + self.label_23 = QLabel(self.widget_37) + self.label_23.setObjectName(u"label_23") + sizePolicy1.setHeightForWidth(self.label_23.sizePolicy().hasHeightForWidth()) + self.label_23.setSizePolicy(sizePolicy1) + self.label_23.setFont(font) + + self.horizontalLayout_19.addWidget(self.label_23) + + + self.verticalLayout_28.addWidget(self.widget_37) + + self.progressTempC = QProgressBar(self.widget_36) + self.progressTempC.setObjectName(u"progressTempC") + sizePolicy7 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) + sizePolicy7.setHorizontalStretch(0) + sizePolicy7.setVerticalStretch(0) + sizePolicy7.setHeightForWidth(self.progressTempC.sizePolicy().hasHeightForWidth()) + self.progressTempC.setSizePolicy(sizePolicy7) + self.progressTempC.setValue(26) + self.progressTempC.setOrientation(Qt.Vertical) + + self.verticalLayout_28.addWidget(self.progressTempC) + + + self.horizontalLayout_21.addWidget(self.widget_36) + + self.widget_38 = QWidget(self.frame_7) + self.widget_38.setObjectName(u"widget_38") + self.verticalLayout_29 = QVBoxLayout(self.widget_38) + self.verticalLayout_29.setObjectName(u"verticalLayout_29") + self.widget_39 = QWidget(self.widget_38) + self.widget_39.setObjectName(u"widget_39") + sizePolicy1.setHeightForWidth(self.widget_39.sizePolicy().hasHeightForWidth()) + self.widget_39.setSizePolicy(sizePolicy1) + self.horizontalLayout_20 = QHBoxLayout(self.widget_39) + self.horizontalLayout_20.setObjectName(u"horizontalLayout_20") + self.lcdTempF = QLCDNumber(self.widget_39) + self.lcdTempF.setObjectName(u"lcdTempF") + sizePolicy6.setHeightForWidth(self.lcdTempF.sizePolicy().hasHeightForWidth()) + self.lcdTempF.setSizePolicy(sizePolicy6) + self.lcdTempF.setFont(font1) + self.lcdTempF.setSegmentStyle(QLCDNumber.Flat) + + self.horizontalLayout_20.addWidget(self.lcdTempF) + + self.label_25 = QLabel(self.widget_39) + self.label_25.setObjectName(u"label_25") + sizePolicy1.setHeightForWidth(self.label_25.sizePolicy().hasHeightForWidth()) + self.label_25.setSizePolicy(sizePolicy1) + self.label_25.setFont(font) + + self.horizontalLayout_20.addWidget(self.label_25) + + + self.verticalLayout_29.addWidget(self.widget_39) + + self.progressTempF = QProgressBar(self.widget_38) + self.progressTempF.setObjectName(u"progressTempF") + sizePolicy7.setHeightForWidth(self.progressTempF.sizePolicy().hasHeightForWidth()) + self.progressTempF.setSizePolicy(sizePolicy7) + self.progressTempF.setMaximum(200) + self.progressTempF.setValue(79) + self.progressTempF.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter) + self.progressTempF.setOrientation(Qt.Vertical) + + self.verticalLayout_29.addWidget(self.progressTempF) + + + self.horizontalLayout_21.addWidget(self.widget_38) + + + self.horizontalLayout_6.addWidget(self.frame_7) + + + self.verticalLayout_4.addWidget(self.widget_6) + + + self.horizontalLayout.addWidget(self.widget_5) + + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QMenuBar(MainWindow) + self.menubar.setObjectName(u"menubar") + self.menubar.setGeometry(QRect(0, 0, 1280, 20)) + MainWindow.setMenuBar(self.menubar) + self.statusbar = QStatusBar(MainWindow) + self.statusbar.setObjectName(u"statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + + QMetaObject.connectSlotsByName(MainWindow) + # setupUi + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) + self.buttonConnection.setText(QCoreApplication.translate("MainWindow", u"Connect", None)) + self.radioButton.setText("") + self.radioButton_3.setText("") + self.radioButton_5.setText("") + self.radioButton_4.setText("") + self.radioButton_2.setText("") + self.radioButton_6.setText("") + self.radioButton_7.setText("") + self.buttonRotateScreen.setText(QCoreApplication.translate("MainWindow", u"Rotate Screen", None)) + self.buttonNextScreen.setText(QCoreApplication.translate("MainWindow", u"Next Screen", None)) + self.buttonSwitchGroup.setText(QCoreApplication.translate("MainWindow", u"Switch Group", None)) + self.buttonClearData.setText(QCoreApplication.translate("MainWindow", u"Clear Data", None)) + self.label_2.setText(QCoreApplication.translate("MainWindow", u"Voltage", None)) + self.label.setText(QCoreApplication.translate("MainWindow", u"V", None)) + self.label_7.setText(QCoreApplication.translate("MainWindow", u"Current", None)) + self.label_8.setText(QCoreApplication.translate("MainWindow", u"A", None)) + self.label_3.setText(QCoreApplication.translate("MainWindow", u"Power", None)) + self.label_4.setText(QCoreApplication.translate("MainWindow", u"W", None)) + self.label_5.setText(QCoreApplication.translate("MainWindow", u"Impedance", None)) + self.label_6.setText(QCoreApplication.translate("MainWindow", u"\u2126", None)) + self.label_9.setText(QCoreApplication.translate("MainWindow", u"Capacity recorded", None)) + self.label_10.setText(QCoreApplication.translate("MainWindow", u"mAh", None)) + self.label_15.setText(QCoreApplication.translate("MainWindow", u"Energy recorded", None)) + self.label_16.setText(QCoreApplication.translate("MainWindow", u"mWh", None)) + self.label_11.setText(QCoreApplication.translate("MainWindow", u"Stop current", None)) + self.spinStopCurrent.setSuffix("") + self.label_12.setText(QCoreApplication.translate("MainWindow", u"A", None)) + self.label_13.setText(QCoreApplication.translate("MainWindow", u"Time recorded", None)) + self.labelTimeRecorded.setText(QCoreApplication.translate("MainWindow", u"03:07:35", None)) + self.label_17.setText(QCoreApplication.translate("MainWindow", u"Brightness level", None)) + self.label_18.setText(QCoreApplication.translate("MainWindow", u"Auto screen off", None)) + self.label_14.setText(QCoreApplication.translate("MainWindow", u"USB D+", None)) + self.label_19.setText(QCoreApplication.translate("MainWindow", u"V", None)) + self.label_21.setText(QCoreApplication.translate("MainWindow", u"USB D-", None)) + self.label_22.setText(QCoreApplication.translate("MainWindow", u"V", None)) + self.labelUSBMode.setText(QCoreApplication.translate("MainWindow", u"Unkown mode", None)) + self.label_23.setText(QCoreApplication.translate("MainWindow", u"\u00b0C", None)) + self.progressTempC.setFormat(QCoreApplication.translate("MainWindow", u"%p", None)) + self.label_25.setText(QCoreApplication.translate("MainWindow", u"\u00b0F", None)) + self.progressTempF.setFormat(QCoreApplication.translate("MainWindow", u"%p", None)) + # retranslateUi + diff --git a/src/meter/um24c.py b/src/meter/um24c.py index 7598ed7..e4c35ec 100644 --- a/src/meter/um24c.py +++ b/src/meter/um24c.py @@ -1,10 +1,13 @@ -import struct +from time import sleep +from struct import unpack from collections import namedtuple +import bluetooth + PACKET_MAGIC = (b'\x09\x63', b'\xff\xf1') DATA_FORMAT = ">2x2HI2HxB20I2HBx2IHI2x2HIxB2x" - +rfcomm = None UMeterStatus = namedtuple('UMeterStatus', [ 'Voltage', @@ -33,8 +36,8 @@ UMeterStatus = namedtuple('UMeterStatus', [ 'Accumulated_Energy8', 'Accumulated_Capacity9', 'Accumulated_Energy9', - 'D+', - 'D-', + 'DPlus', + 'DMinus', 'Mode', 'Recorded_Capacity', 'Recorded_Energy', @@ -45,3 +48,96 @@ UMeterStatus = namedtuple('UMeterStatus', [ 'Load_equivalent_impedance', 'Current_screen'] ) + + +UM24C_GET_STATUS = b'\xf0' + + +def discover_devices(): + """Discover UM24C Bluetooth USB Power Meters. + + Scan nearby bluetooth devices and check for *UM24C* named devices. + + Returns: + Returns a list of a bluetooth address and device name pair (`str`, + `str`). + + Raises: + Exception if bluetooth controller cannot be accessed. + """ + try: + nearby_devices = bluetooth.discover_devices(lookup_names=True) + except OSError as oserr: + raise Exception('Cannot access bluetooth controller.') + + um24_meters = [] + for bt_device in nearby_devices: + if 'UM24C' in bt_device: + um24_meters.append(bt_device) + return um24_meters + + +def connect(dev, port=1): + """Connect to nearby bluetooth `dev`. + + Open a RFCOMM socket connection to the bluetooth device. The argument `dev` + is the bluetooth address. The `port` defines the communication endpoint of + the bluetooth device to connect. + + Args: + dev (str): Bluetooth device address + port (int, Default=1): Communication endpoint + """ + global rfcomm + if is_connected(): + peername, peerport = rfcomm.getpeername() + raise Exception(f'Already connected to {peername}.') + + rfcomm = bluetooth.BluetoothSocket(bluetooth.RFCOMM) + rfcomm.connect((dev, port)) + + +def disconnect(): + """Close connection to UM24C Bluetooth USB Power Meter. + + Closes the `rfcomm` socket connection. + """ + global rfcomm + if is_connected(): + rfcomm.close() + + +def is_connected(): + """Check the RFCOMM connection state. + + Check if the socket is opened. + + Returns: + boolean: Return `True` if connected otherwise return `False`. + """ + global rfcomm + if not rfcomm: + return False + elif rfcomm.fileno() < 0: + return False + else: + try: + rfcomm.getpeername() + return True + except bluetooth.btcommon.BluetoothError: + return False + + +def get_meter_stats(): + global rfcomm + rfcomm.send(UM24C_GET_STATUS) + sleep(0.25) + data = rfcomm.recv(0x8f) + assert len(data) == 130 + assert data[0:2] == PACKET_MAGIC[0] and data[-2:] == PACKET_MAGIC[1] + values = list(unpack(DATA_FORMAT, data)) + for i, value in enumerate(values): + if type(value) is bytes: + values[i] = int.from_bytes(value.strip(b'\x00'), 'big', + signed=False) + return UMeterStatus(*values) diff --git a/src/um24clab.py b/src/um24clab.py index 9b17e6d..a9c93a4 100644 --- a/src/um24clab.py +++ b/src/um24clab.py @@ -14,6 +14,8 @@ from PySide2.QtCharts import ( from UM24CUI import Ui_MainWindow +from meter import um24c + class UM24Lab(QMainWindow): @@ -22,6 +24,21 @@ class UM24Lab(QMainWindow): self.ui = Ui_MainWindow() self.ui.setupUi(self) + # TODO: Add splash screen, discover in background + self.connected = False + supported_devices = um24c.discover_devices() + for device in supported_devices: + self.ui.comboDevices.addItem(device[0]) + self.ui.buttonConnection.clicked.connect(self.connect_device) + + # --- Plot setup --- + self._setup_plots() + self.timer_step = 0 + timer = QTimer(self) + timer.timeout.connect(self.update_graphs) + timer.start(200) + + def _setup_plots(self): self.ui.plotVoltage = QtCharts.QChart() self.ui.widgetVoltage.setChart(self.ui.plotVoltage) @@ -72,23 +89,50 @@ class UM24Lab(QMainWindow): self.current.addAxis(axis_y, Qt.AlignLeft) self.current_series.attachAxis(axis_y) - self.timer_step = 0 - - timer = QTimer(self) - timer.timeout.connect(self.update_graphs) - timer.start(10) + def connect_device(self): + if not self.connected: + um24c.connect(self.ui.comboDevices.currentText()) + if um24c.is_connected(): + self.ui.buttonConnection.setText('Disconnect') + self.ui.comboDevices.setEnabled(False) + self.connected = True + else: + um24c.disconnect() + if not um24c.is_connected(): + self.ui.buttonConnection.setText('Connect') + self.ui.comboDevices.setEnabled(True) + self.connected = False def update_graphs(self): - 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) - pass + if um24c.is_connected(): + self.meter_stats = um24c.get_meter_stats() + print(self.meter_stats) + + self.ui.lcdVoltage.display(self.meter_stats.Voltage / 100) + self.ui.lcdCurrent.display(self.meter_stats.Current / 100) + self.ui.lcdImpedance.display(self.meter_stats.Load_equivalent_impedance + / 10) + self.ui.lcdPower.display(self.meter_stats.Power / 100) + self.ui.lcdTempC.display(self.meter_stats.Temperature_Celcius) + self.ui.lcdTempF.display(self.meter_stats.Temperature_Fahrenheit) + # self.ui.progressTempC.setValue(self.meter_stats.Temperature_Celcius) + # self.ui.progressTempF.setValue(self.meter_stats.Temperature_Fahrenheit) + self.ui.lcdDataMinus.display(self.meter_stats.DMinus / 100) + self.ui.lcdDataPlus.display(self.meter_stats.DPlus / 100) + self.ui.lcdCapacityRecorded.display(self.meter_stats.Recorded_Capacity) + self.ui.lcdEnergyRecorded.display(self.meter_stats.Recorded_Energy) + self.ui.spinStopCurrent.setValue(self.meter_stats.Current_Trigger / + 100) + + # 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__': @@ -97,12 +141,4 @@ if __name__ == '__main__': labview = UM24Lab() labview.show() - # def idle_processor(): - # labview.update_graphs() - # app.processEvents() - - # mainTimer = QTimer() - # mainTimer.timeout.connect(idle_processor) - # mainTimer.start(0) - sys.exit(app.exec_()) From e26291be050a3a398edacc72b5639ce7b4931eaf Mon Sep 17 00:00:00 2001 From: JayPiKay Date: Fri, 24 Jan 2020 16:45:24 +0100 Subject: [PATCH 2/2] Filling most of the UI elements with data --- src/UM24CUI.py | 3 +- src/meter/um24c.py | 23 ++--- src/um24clab.py | 210 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 195 insertions(+), 41 deletions(-) diff --git a/src/UM24CUI.py b/src/UM24CUI.py index efea25a..90754d6 100644 --- a/src/UM24CUI.py +++ b/src/UM24CUI.py @@ -48,13 +48,14 @@ class Ui_MainWindow(object): self.horizontalLayout_2 = QHBoxLayout(self.frame) self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.comboDevices = QComboBox(self.frame) + self.comboDevices.setEnabled(False) self.comboDevices.setObjectName(u"comboDevices") self.horizontalLayout_2.addWidget(self.comboDevices) self.buttonConnection = QPushButton(self.frame) self.buttonConnection.setObjectName(u"buttonConnection") - self.buttonConnection.setFlat(False) + self.buttonConnection.setEnabled(False) self.horizontalLayout_2.addWidget(self.buttonConnection) diff --git a/src/meter/um24c.py b/src/meter/um24c.py index e4c35ec..de574c9 100644 --- a/src/meter/um24c.py +++ b/src/meter/um24c.py @@ -128,16 +128,19 @@ def is_connected(): return False -def get_meter_stats(): +def get_meter_stats(timeout=50): global rfcomm rfcomm.send(UM24C_GET_STATUS) - sleep(0.25) + sleep(timeout) data = rfcomm.recv(0x8f) - assert len(data) == 130 - assert data[0:2] == PACKET_MAGIC[0] and data[-2:] == PACKET_MAGIC[1] - values = list(unpack(DATA_FORMAT, data)) - for i, value in enumerate(values): - if type(value) is bytes: - values[i] = int.from_bytes(value.strip(b'\x00'), 'big', - signed=False) - return UMeterStatus(*values) + # assert len(data) == 130 + # assert data[0:2] == PACKET_MAGIC[0] and data[-2:] == PACKET_MAGIC[1] + try: + values = list(unpack(DATA_FORMAT, data)) + for i, value in enumerate(values): + if type(value) is bytes: + values[i] = int.from_bytes(value.strip(b'\x00'), 'big', + signed=False) + return UMeterStatus(*values) + except: + return None diff --git a/src/um24clab.py b/src/um24clab.py index a9c93a4..644ccb0 100644 --- a/src/um24clab.py +++ b/src/um24clab.py @@ -1,9 +1,10 @@ #!/usr/bin/env python import sys +import traceback import random from PySide2.QtCore import ( - Qt, QTimer + Qt, QTimer, QObject, Signal, Slot, QRunnable, QThreadPool ) from PySide2.QtWidgets import ( QApplication, QMainWindow @@ -17,6 +18,89 @@ 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: + 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) + except: + 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 UM24Lab(QMainWindow): def __init__(self): @@ -24,19 +108,37 @@ class UM24Lab(QMainWindow): 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.connected = False - supported_devices = um24c.discover_devices() - for device in supported_devices: - self.ui.comboDevices.addItem(device[0]) - self.ui.buttonConnection.clicked.connect(self.connect_device) + self.action_discover_devices() # --- Plot setup --- self._setup_plots() self.timer_step = 0 timer = QTimer(self) timer.timeout.connect(self.update_graphs) - timer.start(200) + timer.start(50) def _setup_plots(self): self.ui.plotVoltage = QtCharts.QChart() @@ -89,40 +191,88 @@ class UM24Lab(QMainWindow): self.current.addAxis(axis_y, Qt.AlignLeft) self.current_series.attachAxis(axis_y) - def connect_device(self): - if not self.connected: + 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) - self.connected = True + return True else: um24c.disconnect() if not um24c.is_connected(): self.ui.buttonConnection.setText('Connect') self.ui.comboDevices.setEnabled(True) - self.connected = False + 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) + # worker.signals.finished.connect(...) + # worker.signals.progress.connect(...) + self.threadpool.start(worker) + + def do_update_stats(self, progress_callback): + while um24c.is_connected: + current = um24c.get_meter_stats() + progress_callback.emit(current) + + def update_stats_progress(self, current): + self.meter_stats = current + + def action_update_stats(self): + worker = UM24LabWorker(self.do_update_stats) + worker.signals.progress.connect(self.update_stats_progress) + self.threadpool.start(worker) def update_graphs(self): - if um24c.is_connected(): - self.meter_stats = um24c.get_meter_stats() - print(self.meter_stats) - - self.ui.lcdVoltage.display(self.meter_stats.Voltage / 100) - self.ui.lcdCurrent.display(self.meter_stats.Current / 100) - self.ui.lcdImpedance.display(self.meter_stats.Load_equivalent_impedance - / 10) - self.ui.lcdPower.display(self.meter_stats.Power / 100) - self.ui.lcdTempC.display(self.meter_stats.Temperature_Celcius) - self.ui.lcdTempF.display(self.meter_stats.Temperature_Fahrenheit) - # self.ui.progressTempC.setValue(self.meter_stats.Temperature_Celcius) - # self.ui.progressTempF.setValue(self.meter_stats.Temperature_Fahrenheit) - self.ui.lcdDataMinus.display(self.meter_stats.DMinus / 100) - self.ui.lcdDataPlus.display(self.meter_stats.DPlus / 100) - self.ui.lcdCapacityRecorded.display(self.meter_stats.Recorded_Capacity) - self.ui.lcdEnergyRecorded.display(self.meter_stats.Recorded_Energy) - self.ui.spinStopCurrent.setValue(self.meter_stats.Current_Trigger / - 100) + 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 / 100) + ui.lcdImpedance.display(self.meter_stats.Load_equivalent_impedance + / 10) + ui.lcdPower.display(self.meter_stats.Power / 100) + 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))