Updates
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
147
main.py
147
main.py
@@ -5,16 +5,18 @@ AUTOMOTIVE POWER SIMULATOR APP - MAIN.PY
|
|||||||
|
|
||||||
VERSION: 1.0
|
VERSION: 1.0
|
||||||
|
|
||||||
AUTHOR: D. RICE 14/11/2025
|
AUTHOR: D. RICE 06/01/2026
|
||||||
© 2025 ARRIVE
|
© 2026 ARRIVE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Imports
|
# Imports
|
||||||
import sys
|
import sys
|
||||||
from PySide6.QtWidgets import (QApplication, QDialog, QMainWindow)
|
from PySide6.QtWidgets import (QApplication, QDialog, QMainWindow)
|
||||||
from PySide6.QtCore import (QThread, QObject, Signal, Slot)
|
from PySide6.QtCore import (QThread, QObject, Signal, Slot)
|
||||||
|
from PySide6.QtSerialPort import (QserialPort, QSerialPortInfo)
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import struct
|
||||||
|
|
||||||
from ui_mainwindow import Ui_MainWindow
|
from ui_mainwindow import Ui_MainWindow
|
||||||
from ui_scanning import Ui_scanningDialog
|
from ui_scanning import Ui_scanningDialog
|
||||||
@@ -73,16 +75,16 @@ class MainWindow(QMainWindow):
|
|||||||
self.ui.connButton.clicked.connect(self.conn_button_press)
|
self.ui.connButton.clicked.connect(self.conn_button_press)
|
||||||
|
|
||||||
# Set initial size
|
# Set initial size
|
||||||
initial_width = 1024
|
initial_width = 1000
|
||||||
initial_height = 768
|
initial_height = 600
|
||||||
|
|
||||||
# Lock the window size by setting min/max to the same values
|
# Lock the window size by setting min/max to the same values
|
||||||
self.setMinimumSize(initial_width, initial_height)
|
self.setMinimumSize(initial_width, initial_height)
|
||||||
self.setMaximumSize(initial_width, initial_height)
|
self.setMaximumSize(initial_width, initial_height)
|
||||||
|
|
||||||
self.setGeometry(0, 0, 1024, 768)
|
self.setGeometry(0, 0, 1000, 600)
|
||||||
|
|
||||||
self.setFixedSize(1024, 768)
|
self.setFixedSize(1000, 600)
|
||||||
|
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
@@ -100,8 +102,16 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
|
|
||||||
# Run Connection actions here
|
# Setup serial port
|
||||||
#self.start_worker()
|
|
||||||
|
ser = self.serial.Serial(port="/dev/ttyACM0", baudrate=921600)
|
||||||
|
|
||||||
|
|
||||||
|
command = 73 #0x49 'I' ASCII
|
||||||
|
state = 0
|
||||||
|
data = (command, state)
|
||||||
|
byte_data = self.pack_integers_to_bytes(*data)
|
||||||
|
|
||||||
|
|
||||||
while ((IDN_Response_flag == False) and (Error_flag == False)):
|
while ((IDN_Response_flag == False) and (Error_flag == False)):
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
@@ -138,100 +148,39 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
|
|
||||||
|
def pack_integers_to_bytes(self, *integers: int) -> bytes:
|
||||||
|
# Setup header
|
||||||
|
sync_bytes = [0x41, 0x52]
|
||||||
|
|
||||||
|
# Process data
|
||||||
|
# Mask each input to 8-bits to prevent packing errors
|
||||||
|
data_bytes = [i & 0xFF for i in integers]
|
||||||
|
|
||||||
|
# Get length
|
||||||
|
data_length = [len(data_bytes) & 0xFF]
|
||||||
|
|
||||||
|
# Calculate checksum
|
||||||
|
# Summingall data bytes, then applying bitwise NOT
|
||||||
|
total_sum = sum(data_bytes)
|
||||||
|
rx_checksum = ~total_sum
|
||||||
|
|
||||||
|
rx_checksum_h = (rx_checksum >> 8) & 0xFF
|
||||||
|
rx_checksum_l = rx_checksum & 0xFF
|
||||||
|
checksum_bytes = [rx_checksum_h,rx_checksum_l]
|
||||||
|
|
||||||
|
# Combine all components
|
||||||
|
full_packet = sync_bytes + data_length + data_bytes + checksum_bytes
|
||||||
|
|
||||||
|
# Dymanically create format string
|
||||||
|
# '!' = Network order, 'B' = unsigned char
|
||||||
|
# We need as many 'B's as there are elements in the full packet
|
||||||
|
format_string = f"!{len(full_packet)}B"
|
||||||
|
|
||||||
|
return struct.pack(format_string, *full_packet)
|
||||||
|
|
||||||
def run_scope_setup (self):
|
def run_scope_setup (self):
|
||||||
self.worker.run_setup()
|
self.worker.run_setup()
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def start_worker(self):
|
|
||||||
# Create a QThread
|
|
||||||
self.worker_thread = QThread()
|
|
||||||
|
|
||||||
#nCreate the worker QObject (Now created directly, no import needed)
|
|
||||||
self.worker = ScopeWorker()
|
|
||||||
|
|
||||||
# Move the worker object to the thread
|
|
||||||
self.worker.moveToThread(self.worker_thread)
|
|
||||||
|
|
||||||
# Connect Signals
|
|
||||||
self.worker_thread.started.connect(self.worker.run)
|
|
||||||
|
|
||||||
self.worker.idn_signal.connect(self.handle_idn)
|
|
||||||
self.worker.data_ready_signal.connect(self.handle_data_ready)
|
|
||||||
self.worker.error_signal.connect(self.handle_error)
|
|
||||||
|
|
||||||
# Clean-up connections
|
|
||||||
self.worker.finished_signal.connect(self.worker_thread.quit)
|
|
||||||
self.worker.finished_signal.connect(self.worker.deleteLater)
|
|
||||||
self.worker_thread.finished.connect(self.worker_thread.deleteLater)
|
|
||||||
|
|
||||||
# Start the QThread, which triggers worker.run
|
|
||||||
self.worker_thread.start()
|
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def signal_acquisition(self):
|
|
||||||
"""Sends the signal to the worker to start pulling data."""
|
|
||||||
if self.worker:
|
|
||||||
self.log_text.append("Main: Sending START_ACQUISITION signal.")
|
|
||||||
self.status_label.setText("Status: Acquiring data...")
|
|
||||||
# This is safe because start_acquisition only sets a flag
|
|
||||||
self.worker.start_acquisition()
|
|
||||||
|
|
||||||
# --- SLOTS: Receive data safely from the worker thread ---
|
|
||||||
|
|
||||||
@Slot(str)
|
|
||||||
def handle_idn(self, idn_string):
|
|
||||||
global IDN_Response_flag
|
|
||||||
global Error_flag
|
|
||||||
|
|
||||||
# Received the initial IDN from the worker
|
|
||||||
IDN_Response_flag = True
|
|
||||||
|
|
||||||
# Split the string by the comma delimiter
|
|
||||||
components = idn_string.strip().split(',')
|
|
||||||
|
|
||||||
# Split the string by the comma delimiter
|
|
||||||
components = idn_string.strip().split(',')
|
|
||||||
|
|
||||||
if len(components) == 4:
|
|
||||||
# Assign the components to meaningful keys in a dictionary
|
|
||||||
parsed_data = {
|
|
||||||
"manufacturer": components[0],
|
|
||||||
"model": components[1],
|
|
||||||
"serial_number": components[2],
|
|
||||||
"firmware_version": components[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ui.manu.setText(parsed_data.get("manufacturer"))
|
|
||||||
self.ui.model.setText(parsed_data.get("model"))
|
|
||||||
self.ui.sn.setText(parsed_data.get("serial_number"))
|
|
||||||
self.ui.fw.setText(parsed_data.get("firmware_version"))
|
|
||||||
|
|
||||||
else:
|
|
||||||
Error_flag = True
|
|
||||||
|
|
||||||
self.ui.manu.setText("---")
|
|
||||||
self.ui.model.setText("---")
|
|
||||||
self.ui.sn.setText("---")
|
|
||||||
self.ui.fw.setText("---")
|
|
||||||
|
|
||||||
@Slot(str)
|
|
||||||
def handle_data_ready(self, data_snippet):
|
|
||||||
"""Received the acquired data from the worker."""
|
|
||||||
self.status_label.setText("Status: Data Ready. Waiting for next command.")
|
|
||||||
self.log_text.append(f"Main: Received Waveform Data Snippet:\n{data_snippet}")
|
|
||||||
|
|
||||||
@Slot(str)
|
|
||||||
def handle_error(self, message):
|
|
||||||
global Error_flag
|
|
||||||
|
|
||||||
Error_flag = True
|
|
||||||
|
|
||||||
def closeEvent(self):
|
|
||||||
"""Handle application close to stop the thread gracefully."""
|
|
||||||
if self.worker_thread and self.worker_thread.isRunning():
|
|
||||||
self.worker.stop()
|
|
||||||
# Wait a moment for the thread to clean up
|
|
||||||
self.worker_thread.wait(500)
|
|
||||||
|
|
||||||
# Run main
|
# Run main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
106
ui_mainwindow.py
106
ui_mainwindow.py
@@ -13,7 +13,7 @@ class Ui_MainWindow(object):
|
|||||||
MainWindow.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
MainWindow.setToolButtonStyle(Qt.ToolButtonIconOnly)
|
||||||
MainWindow.setAnimated(True)
|
MainWindow.setAnimated(True)
|
||||||
MainWindow.setDocumentMode(False)
|
MainWindow.setDocumentMode(False)
|
||||||
MainWindow.setWindowIcon(QIcon('/home/davidrice/Python/Automotive-Power-Simulator-App/arriveico.png'))
|
MainWindow.setWindowIcon(QIcon('/home/david-rice/Python/Automotive-Power-Simulator-App/arriveico.png'))
|
||||||
fontmain = QFont()
|
fontmain = QFont()
|
||||||
fontmain.setFamilies([u"Optimism Sans"])
|
fontmain.setFamilies([u"Optimism Sans"])
|
||||||
fontmain.setPointSize(8)
|
fontmain.setPointSize(8)
|
||||||
@@ -21,7 +21,7 @@ class Ui_MainWindow(object):
|
|||||||
|
|
||||||
MainWindow.setFont(fontmain)
|
MainWindow.setFont(fontmain)
|
||||||
# Ensure the path is correct for your system!
|
# Ensure the path is correct for your system!
|
||||||
image_path = "/home/davidrice/Python/Automotive-Power-Simulator-App/appbackground.jpg" # Example Path
|
image_path = "/home/david-rice/Python/Automotive-Power-Simulator-App/appbackground.jpg" # Example Path
|
||||||
|
|
||||||
# --- Define and Apply the Style Sheet ---
|
# --- Define and Apply the Style Sheet ---
|
||||||
bg_style_sheet = f"""
|
bg_style_sheet = f"""
|
||||||
@@ -37,7 +37,7 @@ class Ui_MainWindow(object):
|
|||||||
self.centralwidget.setStyleSheet(bg_style_sheet)
|
self.centralwidget.setStyleSheet(bg_style_sheet)
|
||||||
self.header = QLabel(self.centralwidget)
|
self.header = QLabel(self.centralwidget)
|
||||||
self.header.setObjectName(u"header")
|
self.header.setObjectName(u"header")
|
||||||
self.header.setGeometry(QRect(50, 35, 650, 50))
|
self.header.setGeometry(QRect(50, 35, 750, 50))
|
||||||
font = QFont()
|
font = QFont()
|
||||||
font.setFamilies([u"Optimism Sans"])
|
font.setFamilies([u"Optimism Sans"])
|
||||||
font.setPointSize(24)
|
font.setPointSize(24)
|
||||||
@@ -49,7 +49,7 @@ class Ui_MainWindow(object):
|
|||||||
|
|
||||||
self.test_area = QFrame(self.centralwidget)
|
self.test_area = QFrame(self.centralwidget)
|
||||||
self.test_area.setObjectName(u"test_area")
|
self.test_area.setObjectName(u"test_area")
|
||||||
self.test_area.setGeometry(QRect(50, 115, 924, 618))
|
self.test_area.setGeometry(QRect(50, 115, 900, 440))
|
||||||
self.test_area.setFrameShape(QFrame.StyledPanel)
|
self.test_area.setFrameShape(QFrame.StyledPanel)
|
||||||
self.test_area.setFrameShadow(QFrame.Raised)
|
self.test_area.setFrameShadow(QFrame.Raised)
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ class Ui_MainWindow(object):
|
|||||||
|
|
||||||
self.connButton = QPushButton(self.test_area)
|
self.connButton = QPushButton(self.test_area)
|
||||||
self.connButton.setObjectName(u"connButton")
|
self.connButton.setObjectName(u"connButton")
|
||||||
self.connButton.setGeometry(QRect(25, 25, 125, 25))
|
self.connButton.setGeometry(QRect(350, 25, 200, 25))
|
||||||
self.connButton.setStyleSheet(button_style)
|
self.connButton.setStyleSheet(button_style)
|
||||||
|
|
||||||
text_label_style = """
|
text_label_style = """
|
||||||
@@ -75,11 +75,11 @@ class Ui_MainWindow(object):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.manuLabel = QLabel(self.test_area)
|
#self.manuLabel = QLabel(self.test_area)
|
||||||
self.manuLabel.setObjectName(u"manuLabel")
|
#self.manuLabel.setObjectName(u"manuLabel")
|
||||||
self.manuLabel.setGeometry(QRect(200, 5, 250, 15))
|
#self.manuLabel.setGeometry(QRect(200, 5, 250, 15))
|
||||||
self.manuLabel.setAlignment(Qt.AlignCenter)
|
#self.manuLabel.setAlignment(Qt.AlignCenter)
|
||||||
self.manuLabel.setStyleSheet(text_label_style)
|
#self.manuLabel.setStyleSheet(text_label_style)
|
||||||
|
|
||||||
label_style = """
|
label_style = """
|
||||||
QLabel {
|
QLabel {
|
||||||
@@ -90,47 +90,47 @@ class Ui_MainWindow(object):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.manu = QLabel(self.test_area)
|
#self.manu = QLabel(self.test_area)
|
||||||
self.manu.setObjectName(u"manu")
|
#self.manu.setObjectName(u"manu")
|
||||||
self.manu.setGeometry(QRect(200, 25, 250, 25))
|
#self.manu.setGeometry(QRect(200, 25, 250, 25))
|
||||||
self.manu.setAlignment(Qt.AlignCenter)
|
#self.manu.setAlignment(Qt.AlignCenter)
|
||||||
self.manu.setStyleSheet(label_style)
|
#self.manu.setStyleSheet(label_style)
|
||||||
|
|
||||||
self.modelLabel = QLabel(self.test_area)
|
#self.modelLabel = QLabel(self.test_area)
|
||||||
self.modelLabel.setObjectName(u"modelLabel")
|
#self.modelLabel.setObjectName(u"modelLabel")
|
||||||
self.modelLabel.setGeometry(QRect(475, 5, 125, 15))
|
#self.modelLabel.setGeometry(QRect(475, 5, 125, 15))
|
||||||
self.modelLabel.setAlignment(Qt.AlignCenter)
|
#self.modelLabel.setAlignment(Qt.AlignCenter)
|
||||||
self.modelLabel.setStyleSheet(text_label_style)
|
#self.modelLabel.setStyleSheet(text_label_style)
|
||||||
|
|
||||||
self.model = QLabel(self.test_area)
|
#self.model = QLabel(self.test_area)
|
||||||
self.model.setObjectName(u"model")
|
#self.model.setObjectName(u"model")
|
||||||
self.model.setGeometry(QRect(475, 25, 125, 25))
|
#self.model.setGeometry(QRect(475, 25, 125, 25))
|
||||||
self.model.setAlignment(Qt.AlignCenter)
|
#self.model.setAlignment(Qt.AlignCenter)
|
||||||
self.model.setStyleSheet(label_style)
|
#self.model.setStyleSheet(label_style)
|
||||||
|
|
||||||
self.snLabel = QLabel(self.test_area)
|
#self.snLabel = QLabel(self.test_area)
|
||||||
self.snLabel.setObjectName(u"snlabel")
|
#self.snLabel.setObjectName(u"snlabel")
|
||||||
self.snLabel.setGeometry(QRect(625, 5, 125, 15))
|
#self.snLabel.setGeometry(QRect(625, 5, 125, 15))
|
||||||
self.snLabel.setAlignment(Qt.AlignCenter)
|
#self.snLabel.setAlignment(Qt.AlignCenter)
|
||||||
self.snLabel.setStyleSheet(text_label_style)
|
#self.snLabel.setStyleSheet(text_label_style)
|
||||||
|
|
||||||
self.sn = QLabel(self.test_area)
|
#self.sn = QLabel(self.test_area)
|
||||||
self.sn.setObjectName(u"sn")
|
#self.sn.setObjectName(u"sn")
|
||||||
self.sn.setGeometry(QRect(625, 25, 125, 25))
|
#self.sn.setGeometry(QRect(625, 25, 125, 25))
|
||||||
self.sn.setAlignment(Qt.AlignCenter)
|
#self.sn.setAlignment(Qt.AlignCenter)
|
||||||
self.sn.setStyleSheet(label_style)
|
#self.sn.setStyleSheet(label_style)
|
||||||
|
|
||||||
self.fwLabel = QLabel(self.test_area)
|
#self.fwLabel = QLabel(self.test_area)
|
||||||
self.fwLabel.setObjectName(u"fwLabel")
|
#self.fwLabel.setObjectName(u"fwLabel")
|
||||||
self.fwLabel.setGeometry(QRect(775, 5, 125, 15))
|
#self.fwLabel.setGeometry(QRect(775, 5, 125, 15))
|
||||||
self.fwLabel.setAlignment(Qt.AlignCenter)
|
#self.fwLabel.setAlignment(Qt.AlignCenter)
|
||||||
self.fwLabel.setStyleSheet(text_label_style)
|
#self.fwLabel.setStyleSheet(text_label_style)
|
||||||
|
|
||||||
self.fw = QLabel(self.test_area)
|
#self.fw = QLabel(self.test_area)
|
||||||
self.fw.setObjectName(u"fw")
|
#self.fw.setObjectName(u"fw")
|
||||||
self.fw.setGeometry(QRect(775, 25, 125, 25))
|
#self.fw.setGeometry(QRect(775, 25, 125, 25))
|
||||||
self.fw.setAlignment(Qt.AlignCenter)
|
#self.fw.setAlignment(Qt.AlignCenter)
|
||||||
self.fw.setStyleSheet(label_style)
|
#self.fw.setStyleSheet(label_style)
|
||||||
|
|
||||||
|
|
||||||
frame_style = """
|
frame_style = """
|
||||||
@@ -157,14 +157,14 @@ class Ui_MainWindow(object):
|
|||||||
None))
|
None))
|
||||||
self.header.setText(QCoreApplication.translate("MainWindow", u"AUTOMOTIVE POWER SIMULATOR", None))
|
self.header.setText(QCoreApplication.translate("MainWindow", u"AUTOMOTIVE POWER SIMULATOR", None))
|
||||||
self.connButton.setText(QCoreApplication.translate("MainWindow", u"CONNECT", None))
|
self.connButton.setText(QCoreApplication.translate("MainWindow", u"CONNECT", None))
|
||||||
self.manuLabel.setText(QCoreApplication.translate("MainWindow", u"MANUFACTURER", None))
|
#self.manuLabel.setText(QCoreApplication.translate("MainWindow", u"MANUFACTURER", None))
|
||||||
self.manu.setText(QCoreApplication.translate("MainWindow", u"---", None))
|
#self.manu.setText(QCoreApplication.translate("MainWindow", u"---", None))
|
||||||
self.modelLabel.setText(QCoreApplication.translate("MainWindow", u"MODEL", None))
|
#self.modelLabel.setText(QCoreApplication.translate("MainWindow", u"MODEL", None))
|
||||||
self.model.setText(QCoreApplication.translate("MainWindow", u"---", None))
|
#self.model.setText(QCoreApplication.translate("MainWindow", u"---", None))
|
||||||
self.snLabel.setText(QCoreApplication.translate("MainWindow", u"SERIAL NO", None))
|
#self.snLabel.setText(QCoreApplication.translate("MainWindow", u"SERIAL NO", None))
|
||||||
self.sn.setText(QCoreApplication.translate("MainWindow", u"---", None))
|
#self.sn.setText(QCoreApplication.translate("MainWindow", u"---", None))
|
||||||
self.fwLabel.setText(QCoreApplication.translate("MainWindow", u"F/W REV", None))
|
#self.fwLabel.setText(QCoreApplication.translate("MainWindow", u"F/W REV", None))
|
||||||
self.fw.setText(QCoreApplication.translate("MainWindow", u"---", None))
|
#self.fw.setText(QCoreApplication.translate("MainWindow", u"---", None))
|
||||||
# retranslateUi
|
# retranslateUi
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class Ui_scanningDialog(object):
|
|||||||
def setupUi(self, Dialog):
|
def setupUi(self, Dialog):
|
||||||
if not Dialog.objectName():
|
if not Dialog.objectName():
|
||||||
Dialog.setObjectName(u"Dialog")
|
Dialog.setObjectName(u"Dialog")
|
||||||
Dialog.resize(320, 160)
|
Dialog.resize(300, 150)
|
||||||
# Set the window flags to remove the title bar
|
# Set the window flags to remove the title bar
|
||||||
Dialog.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
Dialog.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ class Ui_scanningDialog(object):
|
|||||||
self.label = QLabel(Dialog)
|
self.label = QLabel(Dialog)
|
||||||
self.label.setObjectName(u"label")
|
self.label.setObjectName(u"label")
|
||||||
self.label.setFont(font)
|
self.label.setFont(font)
|
||||||
self.label.setGeometry(QRect(10, 10, 300, 140))
|
self.label.setGeometry(QRect(10, 10, 280, 130))
|
||||||
self.label.setAlignment(Qt.AlignCenter)
|
self.label.setAlignment(Qt.AlignCenter)
|
||||||
self.label.setWordWrap(True)
|
self.label.setWordWrap(True)
|
||||||
|
|
||||||
@@ -37,5 +37,5 @@ class Ui_scanningDialog(object):
|
|||||||
# setupUi
|
# setupUi
|
||||||
|
|
||||||
def retranslateUi(self, Dialog):
|
def retranslateUi(self, Dialog):
|
||||||
self.label.setText(QCoreApplication.translate("Dialog", u"SCANNING FOR DSO80204B", None))
|
self.label.setText(QCoreApplication.translate("Dialog", u"SCANNING FOR ARRIVE POWERSIM", None))
|
||||||
# retranslateUi
|
# retranslateUi
|
||||||
Reference in New Issue
Block a user