diff options
-rw-r--r-- | Widgets/Dashboard.py | 54 | ||||
-rw-r--r-- | Widgets/HVACPage.py | 39 | ||||
-rw-r--r-- | Widgets/ICPage.py | 74 | ||||
-rw-r--r-- | Widgets/SteeringCtrlPage.py | 67 | ||||
-rw-r--r-- | assets/Images/steering-wheel-disabled.svg | 78 | ||||
-rw-r--r-- | assets/carbon_icons/meter-disabled.svg | 85 | ||||
-rw-r--r-- | assets/carbon_icons/windy--strong-disabled.svg | 1 | ||||
-rw-r--r-- | assets/res.qrc | 3 | ||||
-rw-r--r-- | extras/KuksaClient.py (renamed from extras/FeedKuksa.py) | 70 | ||||
-rw-r--r-- | extras/config.ini | 2 | ||||
-rw-r--r-- | main.py | 19 |
11 files changed, 345 insertions, 147 deletions
diff --git a/Widgets/Dashboard.py b/Widgets/Dashboard.py index 370405c..1992b14 100644 --- a/Widgets/Dashboard.py +++ b/Widgets/Dashboard.py @@ -1,18 +1,7 @@ -""" - Copyright 2023 Suchinton Chakravarty - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" +# Copyright (C) 2023 Suchinton Chakravarty +# Copyright (C) 2024 Konsulko Group +# +# SPDX-License-Identifier: Apache-2.0 from PyQt5 import QtCore, QtWidgets import os @@ -26,6 +15,8 @@ from PyQt5.QtGui import QIcon from PyQt5 import QtCore from PyQt5 import QtSvg +from extras import config + current_dir = os.path.dirname(os.path.abspath(__file__)) # ======================================== @@ -72,7 +63,17 @@ class Dashboard(Base, Form): DashboardTiles.buttonClicked.connect(self.tile_clicked) - for i, tile in enumerate(Dashboard_tiles): + for tile in Dashboard_tiles: + enabled = True + if tile == self.DB_HVAC_Tile and not config.hvac_enabled(): + self.DB_HVAC_Tile.setEnabled(False) + self.DB_HVAC_Tile.setStyleSheet("background-color : darkGray; color : gray") + enabled = False + if tile == self.DB_Steering_Tile and not config.steering_wheel_enabled(): + self.DB_Steering_Tile.setEnabled(False) + self.DB_Steering_Tile.setStyleSheet("background-color : darkGray; color: gray") + enabled = False + self.set_icon(tile, 90) DashboardTiles.addButton(tile) @@ -83,6 +84,13 @@ class Dashboard(Base, Form): self.DB_Steering_Tile: ":/Images/Images/steering-wheel.svg", self.DB_Settings_Tile: ":/Carbon_Icons/carbon_icons/settings.svg" } + icon_mapping_disabled = { + self.DB_IC_Tile: ":/Carbon_Icons/carbon_icons/meter-disabled.svg", + self.DB_HVAC_Tile: ":/Carbon_Icons/carbon_icons/windy--strong-disabled.svg", + self.DB_Steering_Tile: ":/Images/Images/steering-wheel-disabled.svg", + self.DB_Settings_Tile: ":/Carbon_Icons/carbon_icons/settings.svg" + } + file = icon_mapping.get(tile) if file is None: @@ -92,7 +100,19 @@ class Dashboard(Base, Form): svg_widget = QtSvg.QSvgWidget(file) svg_widget.setFixedSize(getsize.defaultSize()*2) svg_widget.setStyleSheet("background-color: transparent;") - tile.setIcon(QIcon(svg_widget.grab())) + icon = QIcon(svg_widget.grab()) + + file = icon_mapping_disabled.get(tile) + if file is None: + return + + getsize = QtSvg.QSvgRenderer(file) + svg_widget = QtSvg.QSvgWidget(file) + svg_widget.setFixedSize(getsize.defaultSize()*2) + svg_widget.setStyleSheet("background-color: transparent;") + icon.addPixmap(svg_widget.grab(), QIcon.Disabled, QIcon.Off) + + tile.setIcon(icon) tile.setIconSize(QtCore.QSize(icon_size, icon_size)) def tile_clicked(self, tile): diff --git a/Widgets/HVACPage.py b/Widgets/HVACPage.py index b41d263..0c25c58 100644 --- a/Widgets/HVACPage.py +++ b/Widgets/HVACPage.py @@ -1,20 +1,9 @@ -""" - Copyright 2023 Suchinton Chakravarty - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" - -from extras.FeedKuksa import FeedKuksa +# Copyright (C) 2023 Suchinton Chakravarty +# Copyright (C) 2024 Konsulko Group +# +# SPDX-License-Identifier: Apache-2.0 + +from extras.KuksaClient import KuksaClient import os import sys from PyQt5 import uic @@ -63,7 +52,7 @@ class HVACWidget(Base, Form): self.HVAC = HVAC_Paths() - self.feed_kuksa = FeedKuksa() + self.kuksa_client = KuksaClient() self.leftTempList = self.findChild(QListWidget, "leftTempList") self.leftTempList.addItems(self.HVAC.temperatureList) @@ -110,7 +99,7 @@ class HVACWidget(Base, Form): def leftTempListClicked(self): """ Handles the event when an item in the left temperature list is clicked. - Sends the selected temperature value to the feed_kuksa object. + Sets the corresponding VSS signal to the selected temperature value. """ self.setTemperature(self.leftTempList, self.HVAC.leftTemp) @@ -118,7 +107,7 @@ class HVACWidget(Base, Form): def rightTempListClicked(self): """ Handles the event when an item in the right temperature list is clicked. - Sends the selected temperature value to the feed_kuksa object. + Sets the corresponding VSS signal to the selected temperature value. """ self.setTemperature(self.rightTempList, self.HVAC.rightTemp) @@ -127,27 +116,27 @@ class HVACWidget(Base, Form): item = list_widget.currentItem() if item is not None: list_widget.scrollToItem(item, 1) - self.feed_kuksa.send_values(path, item.text()[:-2], "targetValue") + self.kuksa_client.set(path, item.text()[:-2], "targetValue") print(item.text()) def leftFanSpeed_sliderChanged(self): """ Handles the event when the left fan speed slider is changed. - Sends the selected fan speed value to the feed_kuksa object. + Sets the corresponding VSS signal to the fan speed value. """ value = self.leftFanSpeed_slider.value() - self.feed_kuksa.send_values(self.HVAC.leftFanSpeed, str(value), "targetValue") + self.kuksa_client.set(self.HVAC.leftFanSpeed, str(value), "targetValue") print(value) def rightFanSpeed_sliderChanged(self): """ Handles the event when the right fan speed slider is changed. - Sends the selected fan speed value to the feed_kuksa object. + Sets the corresponding VSS signal to the fan speed value. """ value = self.rightFanSpeed_slider.value() - self.feed_kuksa.send_values(self.HVAC.rightFanSpeed, str(value), "targetValue") + self.kuksa_client.set(self.HVAC.rightFanSpeed, str(value), "targetValue") print(value) diff --git a/Widgets/ICPage.py b/Widgets/ICPage.py index 859f3e7..33a1401 100644 --- a/Widgets/ICPage.py +++ b/Widgets/ICPage.py @@ -1,31 +1,20 @@ -""" - Copyright 2023 Suchinton Chakravarty - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" - -from extras.FeedKuksa import FeedKuksa +# Copyright (C) 2023 Suchinton Chakravarty +# Copyright (C) 2024 Konsulko Group +# +# SPDX-License-Identifier: Apache-2.0 + import os import sys +import logging +import threading +import time from PyQt5 import uic, QtCore, QtWidgets from PyQt5.QtWidgets import QApplication from PyQt5.QtGui import QIcon, QPixmap, QPainter from PyQt5.QtCore import QObject, pyqtSignal -import time from PyQt5.QtWidgets import QWidget from qtwidgets import AnimatedToggle -import threading -import logging +from extras.KuksaClient import KuksaClient current_dir = os.path.dirname(os.path.abspath(__file__)) @@ -69,8 +58,9 @@ class ICWidget(Base, Form): self.IC = IC_Paths() - self.feed_kuksa = FeedKuksa() - self.vehicle_simulator = VehicleSimulator() + self.kuksa_client = KuksaClient() + self.simulator = VehicleSimulator() + self.simulator_running = False header_frame = self.findChild(QWidget, "header_frame") layout = header_frame.layout() @@ -92,8 +82,8 @@ class ICWidget(Base, Form): # 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.simulator.speed_changed.connect(self.set_Vehicle_Speed) + self.simulator.rpm_changed.connect(self.set_Vehicle_RPM) self.driveGroupBtns = QtWidgets.QButtonGroup(self) self.driveGroupBtns.setExclusive(True) @@ -142,7 +132,7 @@ class ICWidget(Base, Form): speed = int(self.Speed_slider.value()) self.Speed_monitor.display(speed) try: - self.feed_kuksa.send_values(self.IC.speed, str(speed), 'value') + self.kuksa_client.set(self.IC.speed, str(speed), 'value') except Exception as e: logging.error(f"Error sending values to kuksa {e}") @@ -153,7 +143,7 @@ class ICWidget(Base, Form): rpm = int(self.RPM_slider.value()) self.RPM_monitor.display(rpm) try: - self.feed_kuksa.send_values(self.IC.engineRPM, str(rpm), 'value') + self.kuksa_client.set(self.IC.engineRPM, str(rpm), 'value') except Exception as e: logging.error(f"Error sending values to kuksa {e}") @@ -163,7 +153,7 @@ class ICWidget(Base, Form): """ coolantTemp = int(self.coolantTemp_slider.value()) try: - self.feed_kuksa.send_values( + self.kuksa_client.set( self.IC.coolantTemp, str(coolantTemp), 'value') except Exception as e: logging.error(f"Error sending values to kuksa {e}") @@ -174,7 +164,7 @@ class ICWidget(Base, Form): """ fuelLevel = int(self.fuelLevel_slider.value()) try: - self.feed_kuksa.send_values(self.IC.fuelLevel, str(fuelLevel)) + self.kuksa_client.set(self.IC.fuelLevel, str(fuelLevel)) except Exception as e: logging.error(f"Error sending values to kuksa {e}") @@ -201,9 +191,9 @@ class ICWidget(Base, Form): 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) + self.kuksa_client.set(self.IC.leftIndicator, value, "targetValue") + self.kuksa_client.set(self.IC.rightIndicator, value, "targetValue") + self.kuksa_client.set(self.IC.hazard, value, "targetValue") except Exception as e: logging.error(f"Error sending values to kuksa {e}") @@ -227,7 +217,7 @@ class ICWidget(Base, Form): self.leftIndicatorBtn.setIcon(QIcon(leftIndicatorIcon)) try: - self.feed_kuksa.send_values(self.IC.leftIndicator, value) + self.kuksa_client.set(self.IC.leftIndicator, value) except Exception as e: logging.error(f"Error sending values to kuksa {e}") @@ -251,7 +241,7 @@ class ICWidget(Base, Form): self.rightIndicatorBtn.setIcon(QIcon(rightIndicatorIcon)) try: - self.feed_kuksa.send_values(self.IC.rightIndicator, value) + self.kuksa_client.set(self.IC.rightIndicator, value) except Exception as e: logging.error(f"Error sending values to kuksa {e}") @@ -275,11 +265,23 @@ class ICWidget(Base, Form): def handle_Script_toggle(self): if self.Script_toggle.isChecked(): + self.Speed_slider.setEnabled(False) + self.RPM_slider.setEnabled(False) + self.accelerationBtn.setEnabled(False) + for button in self.driveGroupBtns.buttons(): + button.setEnabled(False) self.set_Vehicle_RPM(1000) self.set_Vehicle_Speed(0) - self.vehicle_simulator.start() + self.simulator_running = True + self.simulator.start() else: - self.vehicle_simulator.stop() + self.simulator.stop() + self.simulator_running = False + self.Speed_slider.setEnabled(True) + self.RPM_slider.setEnabled(True) + self.accelerationBtn.setEnabled(True) + for button in self.driveGroupBtns.buttons(): + button.setEnabled(True) def updateSpeedAndEngineRpm(self, action, acceleration=(60/5)): if action == "Accelerate": @@ -326,7 +328,7 @@ class ICWidget(Base, Form): self.Speed_slider.setEnabled(checked_button != self.neutralBtn) self.RPM_slider.setEnabled(True) try: - self.feed_kuksa.send_values(self.IC.selectedGear, gear_value) + self.kuksa_client.set(self.IC.selectedGear, gear_value) except Exception as e: logging.error(f"Error sending values to kuksa {e}") else: diff --git a/Widgets/SteeringCtrlPage.py b/Widgets/SteeringCtrlPage.py index a610f9b..7e0a131 100644 --- a/Widgets/SteeringCtrlPage.py +++ b/Widgets/SteeringCtrlPage.py @@ -1,22 +1,11 @@ -""" - Copyright 2023 Suchinton Chakravarty - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" +# Copyright (C) 2023 Suchinton Chakravarty +# Copyright (C) 2024 Konsulko Group +# +# SPDX-License-Identifier: Apache-2.0 from . import settings import extras.FeedCAN as feed_can -from extras.FeedKuksa import FeedKuksa +from extras.KuksaClient import KuksaClient import os import sys from PyQt5 import uic @@ -39,58 +28,58 @@ class Steering_Paths(): def __init__(self): self.switches = { "VolumeUp": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.VolumeUp", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.VolumeUp", "CAN": "021#FFFFFFFF40000000"}, "VolumeDown": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.VolumeDown", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.VolumeDown", "CAN": "021#FFFFFFFF10000000"}, "VolumeMute": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.VolumeMute", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.VolumeMute", "CAN": "021#FFFFFFFF01000000"}, "Mode": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Mode", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.Mode", "CAN": "021#FFFFFFFF20000000"}, "NextTrack": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Next", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.Next", "CAN": "021#FFFFFFFF08000000"}, "PreviousTrack": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Previous", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.Previous", "CAN": "021#FFFFFFFF80000000"}, "Info": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Info", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.Info", "CAN": "021#FFFFFFFF02000000"}, "PhoneCall": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.PhoneCall", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.PhoneCall", "CAN": "021#FFFFFFFF00010000"}, "PhoneHangup": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.PhoneHangup", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.PhoneHangup", "CAN": "021#FFFFFFFF00020000"}, "Voice": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Voice", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.Voice", "CAN": "021#FFFFFFFF00040000"}, "LaneDeparture": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.LaneDepartureWarning", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.LaneDepartureWarning", "CAN": "021#FFFFFFFF00000001"}, "Horn": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.Horn", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.Horn", "CAN": "021#FFFFFFFF00000080"}, "CruiseEnable": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseEnable", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.CruiseEnable", "CAN": "021#FFFFFFFF00008000"}, "CruiseSet": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseSet", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.CruiseSet", "CAN": "021#FFFFFFFF00001000"}, "CruiseResume": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseResume", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.CruiseResume", "CAN": "021#FFFFFFFF00004000"}, "CruiseCancel": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseCancel", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.CruiseCancel", "CAN": "021#FFFFFFFF00000800"}, "CruiseLimit": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseLimit", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.CruiseLimit", "CAN": "021#FFFFFFFF00000200"}, "CruiseDistance": { - "Kuksa": "Vehicle.Cabin.SteeringWheel.Switches.CruiseDistance", + "VSS": "Vehicle.Cabin.SteeringWheel.Switches.CruiseDistance", "CAN": "021#FFFFFFFF00000100"} } @@ -101,7 +90,7 @@ class SteeringCtrlWidget(Base, Form): self.setupUi(self) self.Steering = Steering_Paths() - self.feed_kuksa = FeedKuksa() + self.kuksa_client = KuksaClient() self.settings = settings self.add_buttons() @@ -138,11 +127,9 @@ class SteeringCtrlWidget(Base, Form): 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") + if signal_type == "VSS": + self.kuksa_client.set(self.Steering.switches[button_clicked]["VSS"], "1") + self.kuksa_client.set(self.Steering.switches[button_clicked]["VSS"], "0") elif signal_type == "CAN": feed_can.send_can_signal( self.Steering.switches[button_clicked]["CAN"]) diff --git a/assets/Images/steering-wheel-disabled.svg b/assets/Images/steering-wheel-disabled.svg new file mode 100644 index 0000000..b90b222 --- /dev/null +++ b/assets/Images/steering-wheel-disabled.svg @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools --> + +<svg + width="32px" + height="32px" + viewBox="-1.6 -1.6 19.20 19.20" + version="1.1" + class="si-glyph si-glyph-wheel-steel" + fill="#ffffff" + stroke="#ffffff" + id="svg3" + sodipodi:docname="steering-wheel-disabled.svg" + inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <defs + id="defs3" /> + <sodipodi:namedview + id="namedview3" + pagecolor="#505050" + bordercolor="#eeeeee" + borderopacity="1" + inkscape:showpageshadow="0" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#505050" + inkscape:zoom="25.78125" + inkscape:cx="16" + inkscape:cy="15.961212" + inkscape:window-width="1920" + inkscape:window-height="1029" + inkscape:window-x="1080" + inkscape:window-y="422" + inkscape:window-maximized="1" + inkscape:current-layer="svg3" /> + <g + id="SVGRepo_bgCarrier" + stroke-width="0" /> + <g + id="SVGRepo_tracerCarrier" + stroke-linecap="round" + stroke-linejoin="round" + stroke="#CCCCCC" + stroke-width="0.032" /> + <g + id="SVGRepo_iconCarrier" + style="fill:#868482;fill-opacity:1"> + <title + id="title1">Wheel-steel</title> + <defs + id="defs1" /> + <g + stroke-width="0.00016" + fill="none" + fill-rule="evenodd" + id="g3" + style="fill:#868482;fill-opacity:1"> + <g + fill="#ffffff" + id="g2" + style="fill:#868482;fill-opacity:1"> + <path + d="M7.99899041,16 C3.58808682,16 0,12.4108272 0,8 C0,3.58917278 3.58808682,0 7.99899041,0 C12.4109036,0 16,3.58917278 16,8 C16,12.4108272 12.4109036,16 7.99899041,16 L7.99899041,16 Z M8,2 C4.69083225,2 2,4.69151671 2,8 C2,11.3084833 4.69180754,14 8,14 C11.3081925,14 14,11.3084833 14,8 C14,4.69151671 11.3091678,2 8,2 L8,2 Z" + class="si-glyph-fill" + id="path1" + style="fill:#868482;fill-opacity:1" /> + <path + d="M7.992,6 C5.676,6 3.894,6.797 3.031,8.346 C3.068,8.819 3.185,9.274 3.367,9.698 C4.588,9.046 6.918,11.528 6.185,12.633 C6.765,12.837 7.326,12.988 7.982,12.988 C8.627,12.988 9.299,12.87 9.869,12.673 C9.135,11.568 11.394,9.138 12.623,9.804 C12.811,9.366 12.932,8.898 12.967,8.408 C12.095,6.875 10.293,6 7.992,6 L7.992,6 Z M8.002,9.156 C7.377,9.156 6.875,8.646 6.875,8.015 C6.875,7.384 7.377,6.874 8.002,6.874 C8.621,6.874 9.125,7.384 9.125,8.015 C9.125,8.646 8.621,9.156 8.002,9.156 L8.002,9.156 Z" + class="si-glyph-fill" + id="path2" + style="fill:#868482;fill-opacity:1" /> + </g> + </g> + </g> +</svg> diff --git a/assets/carbon_icons/meter-disabled.svg b/assets/carbon_icons/meter-disabled.svg new file mode 100644 index 0000000..2b12684 --- /dev/null +++ b/assets/carbon_icons/meter-disabled.svg @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + id="icon" + width="32" + height="32" + viewBox="0 0 32 32" + version="1.1" + sodipodi:docname="meter-disabled.svg" + inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <sodipodi:namedview + id="namedview4" + pagecolor="#505050" + bordercolor="#eeeeee" + borderopacity="1" + inkscape:showpageshadow="0" + inkscape:pageopacity="0" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#505050" + inkscape:zoom="25.78125" + inkscape:cx="16" + inkscape:cy="15.961212" + inkscape:window-width="1920" + inkscape:window-height="1029" + inkscape:window-x="1080" + inkscape:window-y="422" + inkscape:window-maximized="1" + inkscape:current-layer="icon" /> + <defs + id="defs1"> + <linearGradient + id="swatch9" + inkscape:swatch="solid"> + <stop + style="stop-color:#828282;stop-opacity:1;" + offset="0" + id="stop9" /> + </linearGradient> + <style + id="style1">.cls-1{fill:none;}</style> + </defs> + <title + id="title1">meter</title> + <path + d="M26,16a9.9283,9.9283,0,0,0-1.1392-4.6182l-1.4961,1.4961A7.9483,7.9483,0,0,1,24,16Z" + fill="white" + id="path1" + style="fill:#868482;fill-opacity:1" /> + <path + d="M23.4141,10,22,8.5859l-4.7147,4.7147A2.9659,2.9659,0,0,0,16,13a3,3,0,1,0,3,3,2.9659,2.9659,0,0,0-.3006-1.2853ZM16,17a1,1,0,1,1,1-1A1.0013,1.0013,0,0,1,16,17Z" + fill="white" + id="path2" + style="fill:#868482;fill-opacity:1" /> + <path + d="M16,8a7.9515,7.9515,0,0,1,3.1223.6353l1.4961-1.4961A9.9864,9.9864,0,0,0,6,16H8A8.0092,8.0092,0,0,1,16,8Z" + fill="white" + id="path3" + style="fill:#868482;fill-opacity:1" /> + <path + d="M16,30A14,14,0,1,1,30,16,14.0158,14.0158,0,0,1,16,30ZM16,4A12,12,0,1,0,28,16,12.0137,12.0137,0,0,0,16,4Z" + fill="white" + id="path4" + style="fill:#868482;fill-opacity:1" /> + <rect + id="_Transparent_Rectangle_" + data-name="<Transparent Rectangle>" + class="cls-1" + width="32" + height="32" /> + <metadata + id="metadata19"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:title>meter</dc:title> + </cc:Work> + </rdf:RDF> + </metadata> +</svg> diff --git a/assets/carbon_icons/windy--strong-disabled.svg b/assets/carbon_icons/windy--strong-disabled.svg new file mode 100644 index 0000000..168a048 --- /dev/null +++ b/assets/carbon_icons/windy--strong-disabled.svg @@ -0,0 +1 @@ +<svg id="icon" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><defs><style>.cls-1{fill:none;}</style></defs><title>windy--strong</title><path d="M13,30a5.0057,5.0057,0,0,1-5-5h2a3,3,0,1,0,3-3H4V20h9a5,5,0,0,1,0,10Z" fill="gray"/><path d="M25,25a5.0057,5.0057,0,0,1-5-5h2a3,3,0,1,0,3-3H2V15H25a5,5,0,0,1,0,10Z" fill="gray"/><path d="M21,12H6V10H21a3,3,0,1,0-3-3H16a5,5,0,1,1,5,5Z" fill="gray"/><rect id="_Transparent_Rectangle_" data-name="<Transparent Rectangle>" class="cls-1" width="32" height="32"/></svg> diff --git a/assets/res.qrc b/assets/res.qrc index a662c76..58ac6ec 100644 --- a/assets/res.qrc +++ b/assets/res.qrc @@ -11,6 +11,7 @@ <file>carbon_icons/information.svg</file> <file>carbon_icons/add--alt.svg</file> <file>carbon_icons/meter.svg</file> + <file>carbon_icons/meter-disabled.svg</file> <file>carbon_icons/misuse--outline.svg</file> <file>carbon_icons/phone--filled.svg</file> <file>carbon_icons/phone--off--filled.svg</file> @@ -36,6 +37,7 @@ <file>carbon_icons/temperature--water.svg</file> <file>carbon_icons/security-services.svg</file> <file>carbon_icons/windy--strong.svg</file> + <file>carbon_icons/windy--strong-disabled.svg</file> </qresource> <qresource prefix="Images"> <file>Images/HMI_HVAC_Fan_Icon.svg</file> @@ -43,6 +45,7 @@ <file>Images/AGL_Icons_CruiseControl_white.svg</file> <file>Images/cruise-distance.svg</file> <file>Images/steering-wheel.svg</file> + <file>Images/steering-wheel-disabled.svg</file> <file>Images/low-beam.png</file> <file>Images/high-beam.png</file> <file>Images/fuel-icon.png</file> diff --git a/extras/FeedKuksa.py b/extras/KuksaClient.py index 955361d..504e21c 100644 --- a/extras/FeedKuksa.py +++ b/extras/KuksaClient.py @@ -1,18 +1,7 @@ -""" - Copyright 2023 Suchinton Chakravarty - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" +# Copyright (C) 2023 Suchinton Chakravarty +# Copyright (C) 2024 Konsulko Group +# +# SPDX-License-Identifier: Apache-2.0 import logging from PyQt5.QtCore import QThread @@ -20,7 +9,7 @@ from PyQt5.QtCore import pyqtSignal from . import Kuksa_Instance as kuksa_instance import threading -class FeedKuksa(QThread): +class KuksaClient(QThread): """ A class to handle sending values to Kuksa. @@ -48,6 +37,8 @@ class FeedKuksa(QThread): """ QThread.__init__(self, parent) self.stop_flag = False + self.kuksa = None + self.client = None def run(self): """ @@ -71,31 +62,31 @@ class FeedKuksa(QThread): self.kuksa = kuksa_instance.KuksaClientSingleton.instance() self.client = self.kuksa.get_client() - def send_values(self, path=None, value=None, attribute=None): + def set(self, path=None, value=None, attribute=None): """ - Sends values to Kuksa. + Sets VSS value. Parameters: ----------- path : str - The path to the value in Kuksa. + The VSS signal path. value : str - The value to be sent to Kuksa. + The value to be set. attribute : str - The attribute of the value in Kuksa. + The value attribute ("value" or "targetValue" (for actuators)). Raises: ------- Exception - If there is an error sending values to Kuksa. + If there is an error setting the value. """ if self.client is None: - logging.error("Kuksa client is None, try reconnecting") + #logging.error("Kuksa client is None, try reconnecting") return if not self.client.checkConnection(): - logging.error("Kuksa client is not connected, try reconnecting") + logging.error("Client is not connected, try reconnecting") threading.Thread(target=self.set_instance).start() return @@ -111,3 +102,34 @@ class FeedKuksa(QThread): except Exception as e: logging.error(f"Error sending values to kuksa {e}") threading.Thread(target=self.set_instance).start() + + def setValues(self, values : dict[str, any] = None): + """ + Sets VSS values. + + Parameters: + ----------- + values : Dict[str, Any] + The values to be set. + + Raises: + ------- + Exception + If there is an error setting the values. + """ + + if self.client is None: + #logging.error("Kuksa client is None, try reconnecting") + return + + if not self.client.checkConnection(): + logging.error("Client is not connected, try reconnecting") + threading.Thread(target=self.set_instance).start() + return + + try: + self.sending_values.emit() + self.client.setValues(values) + except Exception as e: + logging.error(f"Error sending values to kuksa {e}") + threading.Thread(target=self.set_instance).start() diff --git a/extras/config.ini b/extras/config.ini index 6619900..36306cc 100644 --- a/extras/config.ini +++ b/extras/config.ini @@ -1,5 +1,7 @@ [default] fullscreen-mode = true +hvac-enabled = true +steering-wheel-enabled = true [vss-server] ip = localhost @@ -78,8 +78,8 @@ class MainWindow(Base, Form): self.dashboardButton = self.findChild(QPushButton, 'dashboardButton') UI_Handeler.Hide_Navbar(self, bool_arg=True) - self.stackedWidget.currentChanged.connect(lambda: UI_Handeler.subscribe_VSS_Signals( - self) if UI_Handeler.set_instance(self) else None) + #self.stackedWidget.currentChanged.connect(lambda: UI_Handeler.subscribe_VSS_Signals( + # self) if UI_Handeler.set_instance(self) else None) self.notificationContent = self.findChild( QWidget, 'notificationContent') @@ -109,10 +109,19 @@ class MainWindow(Base, Form): svg_widget.setStyleSheet("background-color: transparent;") self.steeringCtrlButton.setIcon(QIcon(svg_widget.grab())) + if not config.hvac_enabled(): + self.hvacButton.hide() + if not config.steering_wheel_enabled(): + self.steeringCtrlButton.hide() + NavigationButtons = QtWidgets.QButtonGroup(self) NavigationButtons.setExclusive(True) for i, button in enumerate(Navigation_buttons): + if button == self.hvacButton and not config.hvac_enabled(): + continue + if button == self.steeringCtrlButton and not config.steering_wheel_enabled(): + continue button.setCheckable(True) NavigationButtons.addButton(button) button.clicked.connect(partial(UI_Handeler.animateSwitch, self, i)) @@ -164,12 +173,12 @@ class MainWindow(Base, Form): if self.current_page is not None: if self.current_page != 0 and self.current_page != 4: - self.stackedWidget.widget(self.current_page).feed_kuksa.stop() + self.stackedWidget.widget(self.current_page).kuksa_client.stop() self.current_page = page_index if self.current_page != 0 and self.current_page != 4: - self.stackedWidget.widget(self.current_page).feed_kuksa.start() + self.stackedWidget.widget(self.current_page).kuksa_client.start() if __name__ == '__main__': @@ -179,4 +188,4 @@ if __name__ == '__main__': ':/Images/Images/Automotive_Grade_Linux_logo.svg')) window = MainWindow() window.show() - sys.exit(app.exec_())
\ No newline at end of file + sys.exit(app.exec_()) |