diff options
author | suchinton2001 <suchinton.2001@gmail.com> | 2023-10-09 16:00:58 +0530 |
---|---|---|
committer | suchinton2001 <suchinton.2001@gmail.com> | 2023-10-09 16:00:58 +0530 |
commit | db862e32df7f31e6453d7f05a6f011091b96ffab (patch) | |
tree | 6abcc3a2eceb79a43b7836d1d23a8594da375826 | |
parent | 260bbf89836ff9ce98054e5166699a163a0d7c11 (diff) |
agl-demo-control-panel: Add grpc support for databroker
- Add grpc support for databroker (set default protocol)
- Add virtual car for script mode in IC app
- Refine UI elements
- Use specific grpc/ws jwt tokens
- Simplify settings menu
Bug-AGL: SPEC-4905
Signed-off-by: suchinton2001 <suchinton.2001@gmail.com>
Change-Id: I59c4b1de80e280fe22993b2d2f7c92d6b41a89c7
-rw-r--r-- | Widgets/ICPage.py | 373 | ||||
-rw-r--r-- | Widgets/SteeringCtrlPage.py | 206 | ||||
-rw-r--r-- | Widgets/settings.py | 137 | ||||
-rw-r--r-- | extras/FeedCAN.py | 10 | ||||
-rw-r--r-- | extras/FeedKuksa.py | 6 | ||||
-rw-r--r-- | extras/Kuksa_Instance.py | 41 | ||||
-rw-r--r-- | extras/config.py | 12 | ||||
-rw-r--r-- | ui/Dashboard.ui | 35 | ||||
-rw-r--r-- | ui/Settings_Window.ui | 586 |
9 files changed, 813 insertions, 593 deletions
diff --git a/Widgets/ICPage.py b/Widgets/ICPage.py index 64fa2d3..2d11cdf 100644 --- a/Widgets/ICPage.py +++ b/Widgets/ICPage.py @@ -18,10 +18,12 @@ import os import sys from PyQt5 import uic, QtCore, QtWidgets from PyQt5.QtWidgets import QApplication -from PyQt5.QtWidgets import QSlider, QLCDNumber, QPushButton from PyQt5.QtGui import QIcon, QPixmap, QPainter +from PyQt5.QtCore import QObject, pyqtSignal import time -from PyQt5.QtCore import QThread +from PyQt5.QtWidgets import QWidget +from qtwidgets import AnimatedToggle +import threading current_dir = os.path.dirname(os.path.abspath(__file__)) @@ -49,35 +51,40 @@ class IC_Paths(): class ICWidget(Base, Form): + """ + This class represents the ICWidget which is a widget for the AGL Demo Control Panel. + It inherits from the Base and Form classes. + """ + def __init__(self, parent=None): + """ + Initializes the ICWidget object. + + Args: + - parent: The parent widget. Defaults to None. + """ super(self.__class__, self).__init__(parent) self.setupUi(self) self.IC = IC_Paths() + #self.vehicle_simulator = VehicleSimulator(self) self.feed_kuksa = FeedKuksa() self.feed_kuksa.start() + self.vehicle_simulator = VehicleSimulator() - # # load the stylesheet - # theme = open(os.path.join(current_dir, "../ui/styles/Tron/ICPage.qss"), 'r') - # self.setStyleSheet(theme.read()) - # theme.close() - - self.scriptBtn = self.findChild(QPushButton, "scriptBtn") + header_frame = self.findChild(QWidget, "header_frame") + layout = header_frame.layout() - self.Speed_slider = self.findChild(QSlider, "Speed_slider") - self.Speed_monitor = self.findChild(QLCDNumber, "Speed_monitor") - self.RPM_slider = self.findChild(QSlider, "RPM_slider") - self.RPM_monitor = self.findChild(QLCDNumber, "RPM_monitor") + self.IC_Frame = self.findChild(QWidget, "frame_1") - self.coolantTemp_slider = self.findChild(QSlider, "coolantTemp_slider") - self.fuelLevel_slider = self.findChild(QSlider, "fuelLevel_slider") + self.Script_toggle = AnimatedToggle( + checked_color="#4BD7D6", + pulse_checked_color="#00ffff" + ) - self.accelerationBtn = self.findChild(QPushButton, "accelerationBtn") - - self.leftIndicatorBtn = self.findChild(QPushButton, "leftIndicatorBtn") - self.rightIndicatorBtn = self.findChild(QPushButton, "rightIndicatorBtn") - self.hazardBtn = self.findChild(QPushButton, "hazardBtn") + layout.replaceWidget(self.demoToggle, self.Script_toggle) + self.demoToggle.deleteLater() buttons = [self.parkBtn, self.reverseBtn, @@ -85,6 +92,10 @@ class ICWidget(Base, Form): self.driveBtn] # group for the buttons for mutual exclusion + + self.vehicle_simulator.speed_changed.connect(self.set_Vehicle_Speed) + self.vehicle_simulator.rpm_changed.connect(self.set_Vehicle_RPM) + self.driveGroupBtns = QtWidgets.QButtonGroup(self) self.driveGroupBtns.setExclusive(True) @@ -93,8 +104,6 @@ class ICWidget(Base, Form): self.driveGroupBtns.buttonClicked.connect(self.driveBtnClicked) - self.scriptBtn.clicked.connect(self.scriptBtnClicked) - self.Speed_slider.valueChanged.connect(self.update_Speed_monitor) self.Speed_slider.setMinimum(0) self.Speed_slider.setMaximum(240) @@ -112,107 +121,136 @@ class ICWidget(Base, Form): self.accelerationBtn.released.connect(self.accelerationBtnReleased) # make both buttons checkable + self.Script_toggle.clicked.connect(self.handle_Script_toggle) self.leftIndicatorBtn.setCheckable(True) self.rightIndicatorBtn.setCheckable(True) self.hazardBtn.setCheckable(True) - self.leftIndicatorBtn.clicked.connect(self.leftIndicatorBtnClicked) - self.rightIndicatorBtn.clicked.connect(self.rightIndicatorBtnClicked) - self.hazardBtn.clicked.connect(self.hazardBtnClicked) + self.leftIndicatorBtn.toggled.connect(self.leftIndicatorBtnClicked) + self.rightIndicatorBtn.toggled.connect(self.rightIndicatorBtnClicked) + self.hazardBtn.toggled.connect(self.hazardBtnClicked) - def scriptBtnClicked(self): - if self.scriptBtn.isChecked(): - ICScript.start_script() + def set_Vehicle_Speed(self, speed): + self.Speed_slider.setValue(speed) - if not self.ScriptBtn.isChecked(): - ICScript.stop_script() + def set_Vehicle_RPM(self, rpm): + self.RPM_slider.setValue(rpm) def update_Speed_monitor(self): + """ + Updates the speed monitor with the current speed value. + """ speed = int(self.Speed_slider.value()) self.Speed_monitor.display(speed) - self.feed_kuksa.send_values(self.IC.speed, str(speed), 'value') + try: self.feed_kuksa.send_values(self.IC.speed, str(speed), 'value') + except Exception as e: print(e) def update_RPM_monitor(self): + """ + Updates the RPM monitor with the current RPM value. + """ rpm = int(self.RPM_slider.value()) self.RPM_monitor.display(rpm) - self.feed_kuksa.send_values(self.IC.engineRPM, str(rpm), 'value') + try: self.feed_kuksa.send_values(self.IC.engineRPM, str(rpm), 'value') + except Exception as e: print(e) def update_coolantTemp_monitor(self): + """ + Updates the coolant temperature monitor with the current coolant temperature value. + """ coolantTemp = int(self.coolantTemp_slider.value()) - self.feed_kuksa.send_values(self.IC.coolantTemp, str(coolantTemp), 'value') + try: self.feed_kuksa.send_values(self.IC.coolantTemp, str(coolantTemp), 'value') + except Exception as e: print(e) def update_fuelLevel_monitor(self): + """ + Updates the fuel level monitor with the current fuel level value. + """ fuelLevel = int(self.fuelLevel_slider.value()) - self.feed_kuksa.send_values(self.IC.fuelLevel, str(fuelLevel)) + try: self.feed_kuksa.send_values(self.IC.fuelLevel, str(fuelLevel)) + except Exception as e: print(e) def hazardBtnClicked(self): + """ + Handles the hazard button click event. + """ hazardIcon = QPixmap(":/Images/Images/hazard.png") + painter = QPainter(hazardIcon) + painter.setCompositionMode(QPainter.CompositionMode_SourceIn) + if self.hazardBtn.isChecked(): - painter = QPainter(hazardIcon) - painter.setCompositionMode(QPainter.CompositionMode_SourceIn) - painter.fillRect(hazardIcon.rect(), QtCore.Qt.yellow) - painter.end() - self.hazardBtn.setIcon(QIcon(hazardIcon)) - - self.leftIndicatorBtn.setChecked(True) - self.rightIndicatorBtn.setChecked(True) - self.feed_kuksa.send_values(self.IC.leftIndicator, "true") - self.feed_kuksa.send_values(self.IC.rightIndicator, "true") - self.feed_kuksa.send_values(self.IC.hazard, "true") + color = QtCore.Qt.yellow + value = "true" else: - painter = QPainter(hazardIcon) - painter.setCompositionMode(QPainter.CompositionMode_SourceIn) - painter.fillRect(hazardIcon.rect(), QtCore.Qt.black) - painter.end() - self.hazardBtn.setIcon(QIcon(hazardIcon)) - - self.leftIndicatorBtn.setChecked(False) - self.rightIndicatorBtn.setChecked(False) - self.feed_kuksa.send_values(self.IC.leftIndicator, "false") - self.feed_kuksa.send_values(self.IC.rightIndicator, "false") - self.feed_kuksa.send_values(self.IC.hazard, "false") + color = QtCore.Qt.black + value = "false" + + painter.fillRect(hazardIcon.rect(), color) + painter.end() + self.hazardBtn.setIcon(QIcon(hazardIcon)) + + self.leftIndicatorBtn.setChecked(self.hazardBtn.isChecked()) + self.rightIndicatorBtn.setChecked(self.hazardBtn.isChecked()) + + try: + self.feed_kuksa.send_values(self.IC.leftIndicator, value) + self.feed_kuksa.send_values(self.IC.rightIndicator, value) + self.feed_kuksa.send_values(self.IC.hazard, value) + except Exception as e: + print(e) + def leftIndicatorBtnClicked(self): + """ + Handles the left indicator button click event. + """ leftIndicatorIcon = QPixmap(":/Images/Images/left.png") - if self.leftIndicatorBtn.isChecked(): + painter = QPainter(leftIndicatorIcon) + painter.setCompositionMode(QPainter.CompositionMode_SourceIn) - painter = QPainter(leftIndicatorIcon) - painter.setCompositionMode(QPainter.CompositionMode_SourceIn) - painter.fillRect(leftIndicatorIcon.rect(), QtCore.Qt.green) - painter.end() - - self.leftIndicatorBtn.setIcon(QIcon(leftIndicatorIcon)) - self.feed_kuksa.send_values(self.IC.leftIndicator, "true") + if self.leftIndicatorBtn.isChecked(): + color = QtCore.Qt.green + value = "true" else: + color = QtCore.Qt.black + value = "false" - painter = QPainter(leftIndicatorIcon) - painter.setCompositionMode(QPainter.CompositionMode_SourceIn) - painter.fillRect(leftIndicatorIcon.rect(), QtCore.Qt.black) - painter.end() + painter.fillRect(leftIndicatorIcon.rect(), color) + painter.end() + self.leftIndicatorBtn.setIcon(QIcon(leftIndicatorIcon)) - self.leftIndicatorBtn.setIcon(QIcon(leftIndicatorIcon)) - self.feed_kuksa.send_values(self.IC.leftIndicator, "false") + try: self.feed_kuksa.send_values(self.IC.leftIndicator, value) + except Exception as e: print(e) def rightIndicatorBtnClicked(self): + """ + Handles the right indicator button click event. + """ rightIndicatorIcon = QPixmap(":/Images/Images/right.png") - if self.rightIndicatorBtn.isChecked(): + painter = QPainter(rightIndicatorIcon) + painter.setCompositionMode(QPainter.CompositionMode_SourceIn) - painter = QPainter(rightIndicatorIcon) - painter.setCompositionMode(QPainter.CompositionMode_SourceIn) - painter.fillRect(rightIndicatorIcon.rect(), QtCore.Qt.green) - painter.end() - self.rightIndicatorBtn.setIcon(QIcon(rightIndicatorIcon)) - self.feed_kuksa.send_values(self.IC.rightIndicator, "true") + if self.rightIndicatorBtn.isChecked(): + color = QtCore.Qt.green + value = "true" else: + color = QtCore.Qt.black + value = "false" + + painter.fillRect(rightIndicatorIcon.rect(), color) + painter.end() + self.rightIndicatorBtn.setIcon(QIcon(rightIndicatorIcon)) + + try: + self.feed_kuksa.send_values(self.IC.rightIndicator, value) + except Exception as e: + print(e) - painter = QPainter(rightIndicatorIcon) - painter.setCompositionMode(QPainter.CompositionMode_SourceIn) - painter.fillRect(rightIndicatorIcon.rect(), QtCore.Qt.black) - painter.end() - self.rightIndicatorBtn.setIcon(QIcon(rightIndicatorIcon)) - self.feed_kuksa.send_values(self.IC.rightIndicator, "false") def accelerationBtnPressed(self): + """ + Handles the acceleration button press event. + """ self.startTime = QtCore.QTime.currentTime() self.acceleration_timer = QtCore.QTimer() self.acceleration_timer.timeout.connect( @@ -227,6 +265,14 @@ class ICWidget(Base, Form): lambda: self.updateSpeedAndEngineRpm("Decelerate")) self.acceleration_timer.start(100) + def handle_Script_toggle(self): + if self.Script_toggle.isChecked(): + self.set_Vehicle_RPM(1000) + self.set_Vehicle_Speed(0) + self.vehicle_simulator.start() + else: + self.vehicle_simulator.stop() + def updateSpeedAndEngineRpm(self, action, acceleration=(60/5)): if action == "Accelerate": pass @@ -257,33 +303,26 @@ class ICWidget(Base, Form): self.update_RPM_monitor() def driveBtnClicked(self): - # // Selected Gear output = > 0 = Neutral, 1/2/.. = Forward, -1/.. = Reverse, 126 = Park, 127 = Drive - # #859287 ; /* light green */ - - if self.driveGroupBtns.checkedButton() == self.driveBtn: + gear_mapping = { + self.driveBtn: "127", + self.parkBtn: "126", + self.reverseBtn: "-1", + self.neutralBtn: "0" + } + + checked_button = self.driveGroupBtns.checkedButton() + + if checked_button in gear_mapping: + gear_value = gear_mapping[checked_button] self.accelerationBtn.setEnabled(True) - self.Speed_slider.setEnabled(True) - self.RPM_slider.setEnabled(True) - self.feed_kuksa.send_values(self.IC.selectedGear, "127") - - if self.driveGroupBtns.checkedButton() == self.parkBtn: - self.accelerationBtn.setEnabled(False) - self.Speed_slider.setEnabled(False) - self.RPM_slider.setEnabled(False) - self.feed_kuksa.send_values(self.IC.selectedGear, "126") - - if self.driveGroupBtns.checkedButton() == self.reverseBtn: - self.accelerationBtn.setEnabled(True) - self.Speed_slider.setEnabled(True) - self.RPM_slider.setEnabled(True) - self.feed_kuksa.send_values(self.IC.selectedGear, "-1") - - if self.driveGroupBtns.checkedButton() == self.neutralBtn: - self.accelerationBtn.setEnabled(False) - self.Speed_slider.setEnabled(False) + self.Speed_slider.setEnabled(checked_button != self.neutralBtn) self.RPM_slider.setEnabled(True) - self.feed_kuksa.send_values(self.IC.selectedGear, "0") - + try: + self.feed_kuksa.send_values(self.IC.selectedGear, gear_value) + except Exception as e: + print(e) + else: + print("Unknown button checked!") class AccelerationFns(): def calculate_speed(time, acceleration) -> int: @@ -314,37 +353,105 @@ class AccelerationFns(): engine_rpm = wheel_rps * gear_ratios[current_gear - 1] * 60 return int(engine_rpm) + +class VehicleSimulator(QObject): + # Define signals for updating speed and rpm + speed_changed = pyqtSignal(int) + rpm_changed = pyqtSignal(int) + DEFAULT_IDLE_RPM = 1000 -class ICScript(ICWidget): - def start_script(self): - ICWidget.reset() - - # disable all widgets in the scroll area - for widget in ICWidget.scrollAreaWidgetContents.children(): - widget.setEnabled(False) - - rates = [(60/5), (60/4), (60/3)] + def __init__(self): + super().__init__() + self.freq = 10 + self.vehicle_speed = 0 + self.engine_speed = self.DEFAULT_IDLE_RPM + self.running = False + self.lock = threading.Lock() + self.thread = threading.Thread(target=self.run, daemon=True) + + def start(self): + if not self.running: + self.reset() + self.running = True + self.thread.start() + + def stop(self): + self.running = False + + def reset(self): + with self.lock: + self.vehicle_speed = 0 + self.engine_speed = self.DEFAULT_IDLE_RPM + + def run(self): + while self.running: + if not self.running: + break - # start assigning values to the speed and rpm sliders and send them to the IC do this in a loop for each rate - for rate in rates: - ICWidget.accelerationBtnPressed() - ICWidget.acceleration_timer.timeout.connect( - lambda: ICWidget.updateSpeedAndEngineRpm("Accelerate"), rate) - ICWidget.acceleration_timer.start(100) - time.sleep(5) - ICWidget.accelerationBtnReleased() - ICWidget.acceleration_timer.timeout.connect( - lambda: ICWidget.updateSpeedAndEngineRpm("Decelerate"), rate) - ICWidget.acceleration_timer.start(100) + # Simulate acceleration and update speed and rpm + self.accelerate(60, 1800, 3) + self.accelerate(65, 1700, 1) + self.accelerate(80, 2500, 6) + self.accelerate(100, 3000, 4) + self.brake(80, 3000, 3) + self.accelerate(104, 4000, 6) + self.brake(40, 2000, 4) + self.accelerate(90, 3000, 5) + self.brake(1, 650, 5) + + # Ensure reset is called when not in cruise mode + if not self.running: + self.reset() + time.sleep(5) - def stop_script(self): - ICWidget.reset() - - # enable all widgets in the scroll area - for widget in ICWidget.scrollAreaWidgetContents.children(): - widget.setEnabled(True) + def accelerate(self, target_speed, target_rpm, duration): + if target_speed <= self.vehicle_speed: + return + v = (target_speed - self.vehicle_speed) / (duration * self.freq) + r = (target_rpm - self.engine_speed) / (duration * self.freq) + while self.vehicle_speed < target_speed and self.running: + with self.lock: + self.vehicle_speed += v + self.engine_speed += r + self.speed_changed.emit(int(self.vehicle_speed)) + self.rpm_changed.emit(int(self.engine_speed)) + time.sleep(1 / self.freq) + + def brake(self, target_speed, target_rpm, duration): + if target_speed >= self.vehicle_speed: + return + v = (self.vehicle_speed - target_speed) / (duration * self.freq) + r = (self.engine_speed - target_rpm) / (duration * self.freq) + while self.vehicle_speed > target_speed and self.running: + with self.lock: + self.vehicle_speed -= v + self.engine_speed -= r + self.speed_changed.emit(int(self.vehicle_speed)) + self.rpm_changed.emit(int(self.engine_speed)) + time.sleep(1 / self.freq) + + def increase(self, bycruise = True): + if self.CRUISEACTIVE: + target_speed = self.vehicle_speed + 5 + target_rpm = self.engine_speed * 1.1 + self.accelerate(target_speed, target_rpm, 2, bycruise) + + def decrease(self, bycruise = True): + if self.CRUISEACTIVE: + target_speed = self.vehicle_speed - 5 + target_rpm = self.engine_speed * 0.9 + self.brake(target_speed, target_rpm, 2, bycruise) + + def resume(self, bycruise = True): + target_speed = self.CRUISESPEED + target_rpm = self.CRUISERPM + current_speed = self.get_vehicle_speed() + if target_speed > current_speed: + self.accelerate(target_speed, target_rpm, 2, bycruise) + else: + self.brake(target_speed, target_rpm, 2, bycruise) if __name__ == '__main__': app = QApplication(sys.argv) diff --git a/Widgets/SteeringCtrlPage.py b/Widgets/SteeringCtrlPage.py index 61271c2..696c6c9 100644 --- a/Widgets/SteeringCtrlPage.py +++ b/Widgets/SteeringCtrlPage.py @@ -28,7 +28,9 @@ current_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.append(os.path.dirname(current_dir)) -import extras.Kuksa_Instance as kuksa_instance +from extras.FeedKuksa import FeedKuksa +import extras.FeedCAN as feed_can +from . import settings Form, Base = uic.loadUiType(os.path.join(current_dir, "../ui/SteeringControls.ui")) @@ -36,31 +38,62 @@ Form, Base = uic.loadUiType(os.path.join(current_dir, "../ui/SteeringControls.ui class Steering_Paths(): def __init__(self): - self.VolumeUp = "Vehicle.Cabin.SteeringWheel.Switches.VolumeUp" - self.VolumeDown = "Vehicle.Cabin.SteeringWheel.Switches.VolumeDown" - self.VolumeMute = "Vehicle.Cabin.SteeringWheel.Switches.VolumeMute" - - self.Mode = "Vehicle.Cabin.SteeringWheel.Switches.Mode" - - self.NextTrack = "Vehicle.Cabin.SteeringWheel.Switches.Next" - self.PreviousTrack = "Vehicle.Cabin.SteeringWheel.Switches.Previous" - - self.Info = "Vehicle.Cabin.SteeringWheel.Switches.Info" - - self.PhoneCall = "Vehicle.Cabin.SteeringWheel.Switches.PhoneCall" - self.PhoneHangup = "Vehicle.Cabin.SteeringWheel.Switches.PhoneHangup" - self.Voice = "Vehicle.Cabin.SteeringWheel.Switches.Voice" - self.LaneDeparture = "Vehicle.Cabin.SteeringWheel.Switches.LaneDepartureWarning" - - self.Horn = "Vehicle.Cabin.SteeringWheel.Switches.Horn" - - self.CruiseEnable = "Vehicle.Cabin.SteeringWheel.Switches.CruiseEnable" - self.CruseSet = "Vehicle.Cabin.SteeringWheel.Switches.CruiseSet" - self.CruiseResume = "Vehicle.Cabin.SteeringWheel.Switches.CruiseResume" - self.CruiseCancel = "Vehicle.Cabin.SteeringWheel.Switches.CruiseCancel" - - self.CruiseLimit = "Vehicle.Cabin.SteeringWheel.Switches.CruiseLimit" - self.CruiseDistance = "Vehicle.Cabin.SteeringWheel.Switches.CruiseDistance" + self.switches = { + "VolumeUp": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.VolumeUp", + "CAN": "021#FFFFFFFF40000000"}, + "VolumeDown": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.VolumeDown", + "CAN": "021#FFFFFFFF10000000"}, + "VolumeMute": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.VolumeMute", + "CAN": "021#FFFFFFFF01000000"}, + "Mode": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Mode", + "CAN": "021#FFFFFFFF20000000"}, + "NextTrack": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Next", + "CAN": "021#FFFFFFFF08000000"}, + "PreviousTrack": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Previous", + "CAN": "021#FFFFFFFF80000000"}, + "Info": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Info", + "CAN": "021#FFFFFFFF02000000"}, + "PhoneCall": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.PhoneCall", + "CAN": "021#FFFFFFFF00010000"}, + "PhoneHangup": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.PhoneHangup", + "CAN": "021#FFFFFFFF00020000"}, + "Voice": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Voice", + "CAN": "021#FFFFFFFF00040000"}, + "LaneDeparture": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.LaneDepartureWarning", + "CAN": "021#FFFFFFFF00000001"}, + "Horn": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Horn", + "CAN": "021#FFFFFFFF00000080"}, + "CruiseEnable": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseEnable", + "CAN": "021#FFFFFFFF00008000"}, + "CruiseSet": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseSet", + "CAN": "021#FFFFFFFF00001000"}, + "CruiseResume": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseResume", + "CAN": "021#FFFFFFFF00004000"}, + "CruiseCancel": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseCancel", + "CAN": "021#FFFFFFFF00000800"}, + "CruiseLimit": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseLimit", + "CAN": "021#FFFFFFFF00000200"}, + "CruiseDistance": { + "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseDistance", + "CAN": "021#FFFFFFFF00000100"} + } class SteeringCtrlWidget(Base, Form): def __init__(self, parent=None): @@ -69,94 +102,49 @@ class SteeringCtrlWidget(Base, Form): self.Steering = Steering_Paths() self.feed_kuksa = FeedKuksa() + self.settings = settings + self.add_buttons() def add_buttons(self): # Define button groups and actions - LeftControlsBtns = [self.VolUpBtn, - self.VolDownBtn, - self.ModeBtn, - self.VolMuteBtn, - self.NextTrackBtn, - self.PrevTrackBtn, - self.InfoBtn] - - - PhoneBtns = [self.PhoneCallBtn, self.PhoneHangupBtn] - ExtraContolsBtns = [self.VoiceBtn, self.LaneDepartureBtn] - - RightControlsBtns = [self.CruiseEnableBtn, - self.CruiseSetBtn, - self.CruiseResumeBtn, - self.CruiseCancelBtn, - self.CruiseLimitBtn, - self.CruiseDistanceBtn] - - self.LeftControlsBtnsGroup = QButtonGroup() - self.PhoneBtnsGroup = QButtonGroup() - self.ExtraContolsBtnsGroup = QButtonGroup() - self.RiqhtControlsBtnsGroup = QButtonGroup() - - for btn in LeftControlsBtns: - self.LeftControlsBtnsGroup.addButton(btn) - - for btn in PhoneBtns: - self.PhoneBtnsGroup.addButton(btn) - - - for btn in RightControlsBtns: - self.RiqhtControlsBtnsGroup.addButton(btn) - - self.LeftControlsBtnsGroup.buttonClicked.connect(self.left_controls_clicked) - self.RiqhtControlsBtnsGroup.buttonClicked.connect(self.right_controls_clicked) - - self.HornBtn.clicked.connect(self.horn_clicked) - - def left_controls_clicked(self): - print("Left controls clicked") - - def right_controls_clicked(self): - print("Right controls clicked") - - def horn_clicked(self): - print("Horn clicked") - -class FeedKuksa(QThread): - def __init__(self, parent=None): - QThread.__init__(self,parent) - self.stop_flag = False - self.set_instance() - - def run(self): - print("Starting thread") - self.set_instance() - while not self.stop_flag: - self.send_values() - - def stop(self): - self.stop_flag = True - print("Stopping thread") - - def set_instance(self): - self.kuksa = kuksa_instance.KuksaClientSingleton.get_instance() - self.client = self.kuksa.get_client() - - def send_values(self, Path=None, Value=None, Attribute=None): - if self.client is not None: - if self.client.checkConnection() is True: - - if Attribute is not None: - self.client.setValue(Path, Value, Attribute) - else: - self.client.setValue(Path, Value) - else: - print("Could not connect to Kuksa") - self.set_instance() - else: - print("Kuksa client is None, try reconnecting") - time.sleep(2) - self.set_instance() + ControlsBtns = [self.VolumeUp, + self.VolumeDown, + self.Mode, + self.VolumeMute, + self.NextTrack, + self.PreviousTrack, + self.Info, + self.PhoneCall, + self.PhoneHangup, + self.Voice, + self.LaneDeparture, + self.CruiseEnable, + self.CruiseSet, + self.CruiseResume, + self.CruiseCancel, + self.CruiseLimit, + self.CruiseDistance] + + self.ControlsBtnsGroup = QButtonGroup() + + for btn in ControlsBtns: + self.ControlsBtnsGroup.addButton(btn) + + self.ControlsBtnsGroup.buttonClicked.connect(self.controls_clicked) + + def controls_clicked(self, button): + button_clicked = button.objectName() + signal_type = settings.Steering_Signal_Type + if signal_type == "Kuksa": + self.feed_kuksa.send_values(self.Steering.switches[button_clicked]["Kuksa"], 1) + self.feed_kuksa.send_values(self.Steering.switches[button_clicked]["Kuksa"], 0) + elif signal_type == "CAN": + feed_can.send_can_signal(self.Steering.switches[button_clicked]["CAN"]) + # Making sure button state goes back to off + feed_can.send_can_signal("021#FFFFFFFF00000000") + print(button_clicked + " button clicked") if __name__ == '__main__': import sys diff --git a/Widgets/settings.py b/Widgets/settings.py index 11800a2..17ea7f6 100644 --- a/Widgets/settings.py +++ b/Widgets/settings.py @@ -12,12 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -import extras.Kuksa_Instance as kuksa_instance + import os import sys import time from PyQt5 import uic -from PyQt5.QtWidgets import QApplication, QLineEdit, QPushButton, QLabel, QCheckBox +from PyQt5.QtWidgets import QApplication, QLineEdit, QPushButton, QLabel +from qtwidgets import AnimatedToggle +from PyQt5.QtWidgets import QWidget +from PyQt5.QtCore import QThread +from PyQt5 import QtGui +import logging current_dir = os.path.dirname(os.path.abspath(__file__)) @@ -25,47 +30,115 @@ current_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.append(os.path.dirname(current_dir)) +import extras.Kuksa_Instance as kuksa_instance Form, Base = uic.loadUiType(os.path.join( current_dir, "../ui/Settings_Window.ui")) # ======================================== +Steering_Signal_Type = "Kuksa" class settings(Base, Form): + """ + A class representing the settings widget of the AGL Demo Control Panel. + + Attributes: + - SSL_toggle: An AnimatedToggle object representing the SSL toggle button. + - CAN_Kuksa_toggle: An AnimatedToggle object representing the CAN/Kuksa toggle button. + - connectionStatus: A QLabel object representing the connection status label. + - connectionLogo: A QLabel object representing the connection logo label. + - IPAddrInput: A QLineEdit object representing the IP address input field. + - reconnectBtn: A QPushButton object representing the reconnect button. + - refreshBtn: A QPushButton object representing the refresh button. + - startClientBtn: A QPushButton object representing the start client button. + """ + def __init__(self, parent=None): + """ + Initializes the settings widget of the AGL Demo Control Panel. + """ super(self.__class__, self).__init__(parent) self.setupUi(self) - self.SSLToggle = self.findChild(QCheckBox, "SSLToggle") + self.SSL_toggle = AnimatedToggle( + checked_color="#4BD7D6", + pulse_checked_color="#00ffff", + ) + + self.Protocol_toggle = AnimatedToggle( + checked_color="#4BD7D6", + pulse_checked_color="#00ffff" + ) + + self.CAN_Kuksa_toggle = AnimatedToggle( + checked_color="#4BD7D6", + pulse_checked_color="#00ffff" + ) self.connectionStatus = self.findChild(QLabel, "connectionStatus") self.connectionLogo = self.findChild(QLabel, "connectionLogo") self.IPAddrInput = self.findChild(QLineEdit, "IPAddrInput") - self.tokenPathInput = self.findChild(QLineEdit, "tokenPathInput") self.reconnectBtn = self.findChild(QPushButton, "reconnectBtn") - self.refreshBtn = self.findChild(QPushButton, "refreshBtn") self.startClientBtn = self.findChild(QPushButton, "startClientBtn") self.startClientBtn.clicked.connect(self.set_instance) self.reconnectBtn.clicked.connect(self.reconnectClient) - self.refreshBtn.clicked.connect(self.refreshStatus) + self.SSL_toggle.clicked.connect(self.toggleSSL) + self.CAN_Kuksa_toggle.clicked.connect(self.toggle_CAN_Kuksa) + + Frame_GS = self.findChild(QWidget, "frame_general_settings") + Frame_PS = self.findChild(QWidget, "frame_page_settings") + GS_layout = Frame_GS.layout() + PS_layout = Frame_PS.layout() + + GS_layout.replaceWidget(self.place_holder_toggle_1, self.SSL_toggle) + GS_layout.replaceWidget(self.place_holder_toggle_2, self.Protocol_toggle) + PS_layout.replaceWidget(self.place_holder_toggle_3, self.CAN_Kuksa_toggle) + + self.place_holder_toggle_1.deleteLater() + self.place_holder_toggle_2.deleteLater() + self.place_holder_toggle_3.deleteLater() self.refreshStatus() - self.show() + + def toggleSSL(self): + """ + Toggles the SSL connection. + """ + self.kuksa_config["insecure"] = not self.SSL_toggle.isChecked() + print(self.kuksa_config) + + def toggle_CAN_Kuksa(self): + """ + Toggles the CAN/Kuksa connection. + """ + global Steering_Signal_Type + if (self.CAN_Kuksa_toggle.isChecked()): + Steering_Signal_Type = "CAN" + else: + Steering_Signal_Type = "Kuksa" + + def get_protocol(self): + if (not self.Protocol_toggle.isChecked()): + return "ws" + else: + return "grpc" def set_instance(self): - self.kuksa = kuksa_instance.KuksaClientSingleton.get_instance() + """ + Sets the instance of the Kuksa client. + """ + self.kuksa = kuksa_instance.KuksaClientSingleton.instance() self.client = self.kuksa.get_client() - self.config = self.kuksa.get_config() - self.token = self.kuksa.get_token() + self.kuksa_config = self.kuksa.get_config() - self.IPAddrInput.setText(self.config["ip"]) - self.SSLToggle.setChecked(self.config["insecure"]) - self.tokenPathInput.setText(self.token) + self.IPAddrInput.setText(self.kuksa_config["ip"]) + self.SSL_toggle.setChecked(not self.kuksa_config["insecure"]) + self.Protocol_toggle.setChecked(self.kuksa_config["protocol"] == 'grpc') time.sleep(2) @@ -76,16 +149,21 @@ class settings(Base, Form): self.refreshStatus() def refreshStatus(self): + """ + Refreshes the connection status. + """ try: if (self.client is None): self.connectionStatus.setText('Not Connected') self.connectionLogo.setStyleSheet("background-color: red") + self.connectionLogo.setPixmap(QtGui.QPixmap(":/Carbon_Icons/carbon_icons/connection-signal--off.svg")) return None if (self.client.checkConnection() == True): self.connectionStatus.setText('Connected') - self.connectionLogo.setPixmap(":/icons/feather/check-circle.svg") self.connectionLogo.setStyleSheet("background-color: green") + # change cnnection logo pixmap to connected.svf from resources + self.connectionLogo.setPixmap(QtGui.QPixmap(":/Carbon_Icons/carbon_icons/connection-signal.svg")) self.client.start() return True @@ -93,20 +171,41 @@ class settings(Base, Form): self.client.stop() self.connectionStatus.setText('Disconnected') self.connectionLogo.setStyleSheet("background-color: yellow") + self.connectionLogo.setPixmap(QtGui.QPixmap(":/Carbon_Icons/carbon_icons/connection-signal--off.svg")) return False except: pass def reconnectClient(self): + """ + Reconnects the client. + """ try: - self.config["ip"] = self.IPAddrInput.text() - self.config["insecure"] = self.SSLToggle.isChecked() - self.token = self.tokenPathInput.text() - self.client = self.kuksa.reconnect_client(self.config, self.token) + self.kuksa_config["ip"] = self.IPAddrInput.text() + self.kuksa_config["insecure"] = not self.SSL_toggle.isChecked() + self.kuksa_config["protocol"] = self.get_protocol() + if self.kuksa_config["protocol"] == 'ws': + self.kuksa_config["port"] = "8090" + if self.kuksa_config["protocol"] == 'grpc': + self.kuksa_config["port"] = "55555" + self.client = self.kuksa.reconnect(self.kuksa_config) self.client.start() self.refreshStatus() + + self.refreshThread = RefreshThread(self) + self.refreshThread.start() + except Exception as e: - print(e) + logging.error(e) + +class RefreshThread(QThread): + def __init__(self, settings): + QThread.__init__(self) + self.settings = settings + + def run(self): + time.sleep(2) + self.settings.refreshStatus() if __name__ == '__main__': import sys diff --git a/extras/FeedCAN.py b/extras/FeedCAN.py index 92649f4..9cd01d5 100644 --- a/extras/FeedCAN.py +++ b/extras/FeedCAN.py @@ -15,6 +15,7 @@ """ import can +import logging def send_can_signal(frame): """ @@ -25,8 +26,13 @@ def send_can_signal(frame): None """ msg = separate_can_frame(frame) - bus = can.interface.Bus(channel='can0', bustype='socketcan') - #msg = can.Message(arbitration_id=can_id, data=data, is_extended_id=False) + + try: + bus = can.interface.Bus(channel='can0', bustype='socketcan') + except Exception as e: + logging.error(f"Failed to initialize bus with channel 'can0': {e}") + return + try: bus.send(msg) print("CAN signal sent successfully:") diff --git a/extras/FeedKuksa.py b/extras/FeedKuksa.py index 903b442..56e902e 100644 --- a/extras/FeedKuksa.py +++ b/extras/FeedKuksa.py @@ -57,6 +57,7 @@ class FeedKuksa(QThread): Stops the thread. """ self.stop_flag = True + logging.info("Stopping thread") def set_instance(self): @@ -64,7 +65,7 @@ class FeedKuksa(QThread): Sets the instance of the Kuksa client. """ self.kuksa = kuksa_instance.KuksaClientSingleton.instance() - self.client = self.kuksa.client + self.client = self.kuksa.get_client() def send_values(self, path=None, value=None, attribute=None): """ @@ -94,6 +95,9 @@ class FeedKuksa(QThread): except Exception as e: logging.error(f"Error sending values to kuksa {e}") self.set_instance() + else: + logging.error("Kuksa client is not connected, try reconnecting") + self.set_instance() else: logging.error("Kuksa client is None, try reconnecting") time.sleep(2) diff --git a/extras/Kuksa_Instance.py b/extras/Kuksa_Instance.py index 49662bd..500e039 100644 --- a/extras/Kuksa_Instance.py +++ b/extras/Kuksa_Instance.py @@ -30,7 +30,7 @@ class KuksaClientSingleton: Attributes: _instance (Optional[KuksaClientSingleton]): The instance of the class. _lock (threading.Lock): A lock to ensure thread-safety. - config (dict): The configuration for KuksaClientThread. + kuksa_config (dict): The configuration for KuksaClientThread. token (str): The path to the token file. client (KuksaClientThread): The instance of KuksaClientThread. @@ -73,12 +73,19 @@ class KuksaClientSingleton: if KuksaClientSingleton._instance is not None: raise Exception("This class is a singleton!") - self.config = config.KUKSA_CONFIG - self.token = config.TOKEN_PATH + self.kuksa_config = config.KUKSA_CONFIG + self.ws_token = config.WS_TOKEN + self.grpc_token = config.GRPC_TOKEN + + if self.kuksa_config["protocol"] == 'ws': + self.token = self.ws_token + if self.kuksa_config["protocol"] == 'grpc': + self.token = self.grpc_token try: - self.client = kuksa.KuksaClientThread(self.config) + self.client = kuksa.KuksaClientThread(self.kuksa_config) self.client.authorize(self.token) + self.client.start() time.sleep(2) if not self.client.checkConnection(): self.client = None @@ -87,7 +94,7 @@ class KuksaClientSingleton: KuksaClientSingleton._instance = self - def reconnect(self, config, token): + def reconnect(self, config): """ Reconnects the client with the given configuration and token. @@ -100,8 +107,17 @@ class KuksaClientSingleton: """ if self.client: self.client.stop() - self.client = kuksa.KuksaClientThread(config) - self.client.authorize(token) + + if self.kuksa_config["protocol"] == 'ws': + self.token = self.ws_token + self.kuksa_config["port"] = "8090" + if self.kuksa_config["protocol"] == 'grpc': + self.token = self.grpc_token + self.kuksa_config["port"] = "55555" + + self.client = kuksa.KuksaClientThread(self.kuksa_config) + self.client.authorize(self.token) + self.client.start() return self.client def get_client(self): @@ -123,16 +139,7 @@ class KuksaClientSingleton: Returns: dict: The configuration for KuksaClientThread. """ - return self.config - - def get_token(self): - """ - Returns the path to the token file. - - Returns: - str: The path to the token file. - """ - return self.token + return self.kuksa_config def status(self): """ diff --git a/extras/config.py b/extras/config.py index cc61c57..2ea749c 100644 --- a/extras/config.py +++ b/extras/config.py @@ -19,16 +19,16 @@ import platform python_version = f"python{'.'.join(platform.python_version_tuple()[:2])}" -CA = os.path.abspath(os.path.join(os.path.dirname(__file__), "../assets/CA.pem")) +CA = os.path.abspath(os.path.join(os.path.dirname(__file__), "../assets/cert/CA.pem")) KUKSA_CONFIG = { - "ip": 'localhost', - "port": "8090", - 'protocol': 'ws', + "ip": '10.42.0.95', + "port": "55555", + 'protocol': 'grpc', 'insecure': False, 'cacertificate': CA, 'tls_server_name': "Server", } -TOKEN_PATH = os.path.join(os.path.expanduser("~"), - f".local/lib/{python_version}/site-packages/kuksa_certificates/jwt/super-admin.json.token") +WS_TOKEN = os.path.join(os.path.expanduser("~"), f".local/lib/{python_version}/site-packages/kuksa_certificates/jwt/super-admin.json.token") +GRPC_TOKEN = os.path.abspath(os.path.join(os.path.dirname(__file__), "../assets/token/grpc/actuate-provide-all.token"))
\ No newline at end of file diff --git a/ui/Dashboard.ui b/ui/Dashboard.ui index 51f913a..ef30cf6 100644 --- a/ui/Dashboard.ui +++ b/ui/Dashboard.ui @@ -84,8 +84,8 @@ QPushButton:pressed { </rect> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QPushButton" name="DB_IC_Tile"> + <item row="0" column="1"> + <widget class="QPushButton" name="DB_HVAC_Tile"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> @@ -96,11 +96,11 @@ QPushButton:pressed { <enum>Qt::LeftToRight</enum> </property> <property name="text"> - <string>Instrument Cluster</string> + <string>HVAC</string> </property> <property name="icon"> <iconset resource="../assets/res.qrc"> - <normaloff>:/Carbon_Icons/carbon_icons/meter.svg</normaloff>:/Carbon_Icons/carbon_icons/meter.svg</iconset> + <normaloff>:/Carbon_Icons/carbon_icons/windy--strong.svg</normaloff>:/Carbon_Icons/carbon_icons/windy--strong.svg</iconset> </property> <property name="iconSize"> <size> @@ -113,8 +113,8 @@ QPushButton:pressed { </property> </widget> </item> - <item row="0" column="1"> - <widget class="QPushButton" name="DB_HVAC_Tile"> + <item row="1" column="0"> + <widget class="QPushButton" name="DB_Steering_Tile"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> @@ -125,11 +125,11 @@ QPushButton:pressed { <enum>Qt::LeftToRight</enum> </property> <property name="text"> - <string>HVAC</string> + <string>Steering Controls</string> </property> <property name="icon"> <iconset resource="../assets/res.qrc"> - <normaloff>:/Carbon_Icons/carbon_icons/windy--strong.svg</normaloff>:/Carbon_Icons/carbon_icons/windy--strong.svg</iconset> + <normaloff>:/Images/Images/steering-wheel.svg</normaloff>:/Images/Images/steering-wheel.svg</iconset> </property> <property name="iconSize"> <size> @@ -142,8 +142,8 @@ QPushButton:pressed { </property> </widget> </item> - <item row="1" column="0"> - <widget class="QPushButton" name="DB_Steering_Tile"> + <item row="1" column="1"> + <widget class="QPushButton" name="DB_Settings_Tile"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> @@ -154,11 +154,11 @@ QPushButton:pressed { <enum>Qt::LeftToRight</enum> </property> <property name="text"> - <string>Steering Controls</string> + <string>Configure</string> </property> <property name="icon"> <iconset resource="../assets/res.qrc"> - <normaloff>:/Images/Images/steering-wheel.svg</normaloff>:/Images/Images/steering-wheel.svg</iconset> + <normaloff>:/Carbon_Icons/carbon_icons/settings.svg</normaloff>:/Carbon_Icons/carbon_icons/settings.svg</iconset> </property> <property name="iconSize"> <size> @@ -171,8 +171,8 @@ QPushButton:pressed { </property> </widget> </item> - <item row="1" column="1"> - <widget class="QPushButton" name="DB_Settings_Tile"> + <item row="0" column="0"> + <widget class="QPushButton" name="DB_IC_Tile"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> @@ -183,11 +183,11 @@ QPushButton:pressed { <enum>Qt::LeftToRight</enum> </property> <property name="text"> - <string>Configure</string> + <string>Instrument Cluster</string> </property> <property name="icon"> <iconset resource="../assets/res.qrc"> - <normaloff>:/Carbon_Icons/carbon_icons/settings.svg</normaloff>:/Carbon_Icons/carbon_icons/settings.svg</iconset> + <normaloff>:/Carbon_Icons/carbon_icons/meter.svg</normaloff>:/Carbon_Icons/carbon_icons/meter.svg</iconset> </property> <property name="iconSize"> <size> @@ -195,9 +195,6 @@ QPushButton:pressed { <height>50</height> </size> </property> - <property name="flat"> - <bool>false</bool> - </property> </widget> </item> </layout> diff --git a/ui/Settings_Window.ui b/ui/Settings_Window.ui index ff73614..477fa40 100644 --- a/ui/Settings_Window.ui +++ b/ui/Settings_Window.ui @@ -71,8 +71,21 @@ QCheckBox:indicator:disabled { </property> <widget class="QWidget" name="centralwidget"> <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="3" rowspan="4"> - <spacer name="horizontalSpacer"> + <item row="0" column="0" colspan="4"> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" rowspan="5"> + <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -84,6 +97,215 @@ QCheckBox:indicator:disabled { </property> </spacer> </item> + <item row="3" column="1" colspan="2"> + <widget class="QFrame" name="frame_general_settings"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="5" colspan="2" alignment="Qt::AlignLeft"> + <widget class="QLabel" name="connectionLogo"> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../assets/res.qrc">:/Carbon_Icons/carbon_icons/connection-signal--off.svg</pixmap> + </property> + </widget> + </item> + <item row="2" column="0" colspan="4"> + <widget class="QLabel" name="IPAddr"> + <property name="text"> + <string>IP Address *</string> + </property> + </widget> + </item> + <item row="4" column="7" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="place_holder_toggle_2"> + <property name="toolTip"> + <string>Default: WS</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="4" column="0" colspan="3"> + <widget class="QLabel" name="label_11"> + <property name="toolTip"> + <string>Default: WS</string> + </property> + <property name="text"> + <string>Protocol</string> + </property> + </widget> + </item> + <item row="4" column="10" alignment="Qt::AlignLeft"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string>grpc</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="4"> + <widget class="QLabel" name="status"> + <property name="text"> + <string>Status</string> + </property> + </widget> + </item> + <item row="1" column="7"> + <widget class="QLabel" name="connectionStatus"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Disconnected</string> + </property> + </widget> + </item> + <item row="5" column="1" rowspan="2"> + <widget class="QFrame" name="PageIcons"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + </layout> + </widget> + </item> + <item row="3" column="5"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../assets/res.qrc">:/Carbon_Icons/carbon_icons/security-services.svg</pixmap> + </property> + </widget> + </item> + <item row="1" column="4" rowspan="4"> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="3" column="0" colspan="4"> + <widget class="QLabel" name="label"> + <property name="toolTip"> + <string>Default: Secure</string> + </property> + <property name="text"> + <string>Secure Mode</string> + </property> + </widget> + </item> + <item row="5" column="2" rowspan="2"> + <widget class="QFrame" name="PageLabels"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + </layout> + </widget> + </item> + <item row="4" column="5" alignment="Qt::AlignRight"> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>ws</string> + </property> + </widget> + </item> + <item row="2" column="5" colspan="7"> + <widget class="QLineEdit" name="IPAddrInput"> + <property name="placeholderText"> + <string>Default: localhost</string> + </property> + </widget> + </item> + <item row="3" column="6" colspan="3" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="place_holder_toggle_1"> + <property name="toolTip"> + <string>Default: Secure</string> + </property> + <property name="text"> + <string/> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="0" colspan="11"> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Maximum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> <item row="1" column="1" colspan="2"> <widget class="QFrame" name="frame_2"> <property name="sizePolicy"> @@ -133,32 +355,10 @@ QCheckBox:indicator:disabled { </property> </widget> </item> - <item> - <widget class="QPushButton" name="refreshBtn"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="text"> - <string>Refresh Status</string> - </property> - <property name="iconSize"> - <size> - <width>30</width> - <height>30</height> - </size> - </property> - </widget> - </item> </layout> </widget> </item> - <item row="4" column="1" colspan="2"> + <item row="5" column="1" colspan="2"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -174,8 +374,8 @@ QCheckBox:indicator:disabled { </property> </spacer> </item> - <item row="1" column="0" rowspan="4"> - <spacer name="horizontalSpacer_2"> + <item row="1" column="3" rowspan="5"> + <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -187,143 +387,57 @@ QCheckBox:indicator:disabled { </property> </spacer> </item> - <item row="3" column="1" colspan="2"> - <widget class="QFrame" name="frame_3"> + <item row="4" column="1" colspan="2"> + <widget class="QFrame" name="frame_page_settings"> + <property name="minimumSize"> + <size> + <width>300</width> + <height>300</height> + </size> + </property> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="4" column="6" colspan="2"> - <widget class="QCheckBox" name="place_holder_toggle_1"> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="7" column="4"> + <widget class="QPushButton" name="pushButton_3"> <property name="text"> <string/> </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="0" column="1" colspan="8"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Maximum</enum> + <property name="icon"> + <iconset resource="../assets/res.qrc"> + <normaloff>:/Carbon_Icons/carbon_icons/view.svg</normaloff>:/Carbon_Icons/carbon_icons/view.svg</iconset> </property> - <property name="sizeHint" stdset="0"> + <property name="iconSize"> <size> - <width>20</width> - <height>40</height> + <width>30</width> + <height>30</height> </size> </property> - </spacer> - </item> - <item row="1" column="7" colspan="4"> - <widget class="QLabel" name="connectionStatus"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Disconnected</string> - </property> - </widget> - </item> - <item row="8" column="2" rowspan="3"> - <widget class="QFrame" name="PageLabels"> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Instrument Cluster</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>HVAC</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Steering Controls</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="2" column="0" colspan="4"> - <widget class="QLabel" name="IPAddr"> - <property name="text"> - <string>IP Address *</string> - </property> </widget> </item> - <item row="10" column="9"> - <widget class="QCheckBox" name="place_holder_toggle_2"> + <item row="5" column="4"> + <widget class="QPushButton" name="pushButton"> <property name="text"> <string/> </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="label_6"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Ignored"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <property name="icon"> + <iconset resource="../assets/res.qrc"> + <normaloff>:/Carbon_Icons/carbon_icons/view.svg</normaloff>:/Carbon_Icons/carbon_icons/view.svg</iconset> </property> - <property name="maximumSize"> + <property name="iconSize"> <size> - <width>25</width> - <height>25</height> + <width>30</width> + <height>30</height> </size> </property> - <property name="text"> - <string/> - </property> - <property name="pixmap"> - <pixmap resource="../assets/res.qrc">:/Carbon_Icons/carbon_icons/meter.svg</pixmap> - </property> - <property name="scaledContents"> - <bool>true</bool> - </property> </widget> </item> - <item row="10" column="6" colspan="2" alignment="Qt::AlignLeft"> - <widget class="QPushButton" name="pushButton_3"> + <item row="6" column="4"> + <widget class="QPushButton" name="pushButton_2"> <property name="text"> <string/> </property> @@ -339,15 +453,15 @@ QCheckBox:indicator:disabled { </property> </widget> </item> - <item row="3" column="0" colspan="4"> - <widget class="QLabel" name="tokenPath"> + <item row="7" column="1" colspan="3"> + <widget class="QLabel" name="label_5"> <property name="text"> - <string>JWT token Path *</string> + <string>Steering Controls</string> </property> </widget> </item> - <item row="10" column="0"> - <widget class="QLabel" name="label_8"> + <item row="6" column="0"> + <widget class="QLabel" name="label_7"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -364,109 +478,61 @@ QCheckBox:indicator:disabled { <string/> </property> <property name="pixmap"> - <pixmap resource="../assets/res.qrc">:/Images/Images/steering-wheel.svg</pixmap> + <pixmap resource="../assets/res.qrc">:/Carbon_Icons/carbon_icons/windy--strong.svg</pixmap> </property> <property name="scaledContents"> <bool>true</bool> </property> </widget> </item> - <item row="5" column="0" colspan="3"> - <widget class="QLabel" name="label_11"> - <property name="text"> - <string>CA</string> - </property> - </widget> - </item> - <item row="4" column="0" colspan="4"> - <widget class="QLabel" name="label"> + <item row="0" column="0" colspan="5" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="label_2"> <property name="text"> - <string>Insecure Mode</string> + <string>Page Settings</string> </property> </widget> </item> - <item row="4" column="5"> - <widget class="QLabel" name="label_9"> + <item row="6" column="1" colspan="3"> + <widget class="QLabel" name="label_4"> <property name="text"> - <string/> - </property> - <property name="pixmap"> - <pixmap resource="../assets/res.qrc">:/Carbon_Icons/carbon_icons/security-services.svg</pixmap> + <string>HVAC</string> </property> </widget> </item> - <item row="6" column="1" colspan="7"> - <spacer name="verticalSpacer_4"> - <property name="orientation"> - <enum>Qt::Vertical</enum> + <item row="5" column="0"> + <widget class="QLabel" name="label_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Ignored"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="sizeHint" stdset="0"> + <property name="maximumSize"> <size> - <width>20</width> - <height>40</height> + <width>25</width> + <height>25</height> </size> </property> - </spacer> - </item> - <item row="5" column="9" colspan="2"> - <widget class="QToolButton" name="toolButton"> <property name="text"> - <string>...</string> - </property> - </widget> - </item> - <item row="7" column="0" colspan="11"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Page Settings</string> + <string/> </property> - </widget> - </item> - <item row="8" column="1" rowspan="3"> - <widget class="QFrame" name="PageIcons"> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> + <property name="pixmap"> + <pixmap resource="../assets/res.qrc">:/Carbon_Icons/carbon_icons/meter.svg</pixmap> </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> + <property name="scaledContents"> + <bool>true</bool> </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - </layout> </widget> </item> - <item row="1" column="4" rowspan="4"> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> + <item row="5" column="1" colspan="3"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Instrument Cluster</string> </property> - </spacer> + </widget> </item> - <item row="9" column="0"> - <widget class="QLabel" name="label_7"> + <item row="7" column="0"> + <widget class="QLabel" name="label_8"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -483,101 +549,47 @@ QCheckBox:indicator:disabled { <string/> </property> <property name="pixmap"> - <pixmap resource="../assets/res.qrc">:/Carbon_Icons/carbon_icons/windy--strong.svg</pixmap> + <pixmap resource="../assets/res.qrc">:/Images/Images/steering-wheel.svg</pixmap> </property> <property name="scaledContents"> <bool>true</bool> </property> </widget> </item> - <item row="10" column="8"> + <item row="8" column="4" alignment="Qt::AlignLeft"> <widget class="QLabel" name="label_10"> <property name="text"> <string>CAN</string> </property> </widget> </item> - <item row="2" column="5" colspan="6"> - <widget class="QLineEdit" name="IPAddrInput"> - <property name="placeholderText"> - <string>Default: localhost</string> - </property> - </widget> - </item> - <item row="9" column="6" colspan="2" alignment="Qt::AlignLeft"> - <widget class="QPushButton" name="pushButton_2"> + <item row="8" column="3" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="place_holder_toggle_3"> <property name="text"> <string/> </property> - <property name="icon"> - <iconset resource="../assets/res.qrc"> - <normaloff>:/Carbon_Icons/carbon_icons/view.svg</normaloff>:/Carbon_Icons/carbon_icons/view.svg</iconset> - </property> - <property name="iconSize"> - <size> - <width>30</width> - <height>30</height> - </size> - </property> </widget> </item> - <item row="1" column="5" colspan="2"> - <widget class="QLabel" name="connectionLogo"> + <item row="8" column="2" alignment="Qt::AlignRight|Qt::AlignVCenter"> + <widget class="QLabel" name="label_14"> <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="3" column="5" colspan="6"> - <widget class="QLineEdit" name="tokenPathInput"> - <property name="placeholderText"> - <string>/Path/To/Token</string> + <string>Kuksa</string> </property> </widget> </item> - <item row="1" column="0" colspan="4"> - <widget class="QLabel" name="status"> - <property name="text"> - <string>Status</string> - </property> - </widget> - </item> - <item row="5" column="5" colspan="4"> - <widget class="QLineEdit" name="lineEdit"/> - </item> - <item row="8" column="6" colspan="2" alignment="Qt::AlignLeft"> - <widget class="QPushButton" name="pushButton"> + <item row="8" column="1" alignment="Qt::AlignHCenter|Qt::AlignVCenter"> + <widget class="QLabel" name="label_15"> <property name="text"> <string/> </property> - <property name="icon"> - <iconset resource="../assets/res.qrc"> - <normaloff>:/Carbon_Icons/carbon_icons/view.svg</normaloff>:/Carbon_Icons/carbon_icons/view.svg</iconset> - </property> - <property name="iconSize"> - <size> - <width>30</width> - <height>30</height> - </size> + <property name="pixmap"> + <pixmap resource="../assets/res.qrc">:/Carbon_Icons/carbon_icons/x-axis.svg</pixmap> </property> </widget> </item> </layout> </widget> </item> - <item row="0" column="0" colspan="4"> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> </layout> </widget> </widget> |