aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2024-05-22 15:02:15 -0400
committerScott Murray <scott.murray@konsulko.com>2024-05-27 13:03:41 +0000
commit6b21032fc91b679353a53073f5570a25a4fd0991 (patch)
tree818dc7c5fd97db7750ab1001014f36db7a8dfa4a
parentf2c7811d3c6331f264f3505147d590c315e16d02 (diff)
Add ability to disable HVAC and steering wheel pages
Add configuration file options to disable the HVAC and steering wheel pages. Also includes a bit of refactoring around the KUKSA.val databroker client mostly focused on cleaning up naming for now. If significant development continues on this application the KuksaClient class should be used as the place where more refactoring occurs. Bug-AGL: SPEC-5142 Change-Id: I986c7cac4e6543e2a1ad40ebf436fd40e2ae2300 Signed-off-by: Scott Murray <scott.murray@konsulko.com>
-rw-r--r--Widgets/Dashboard.py54
-rw-r--r--Widgets/HVACPage.py39
-rw-r--r--Widgets/ICPage.py74
-rw-r--r--Widgets/SteeringCtrlPage.py67
-rw-r--r--assets/Images/steering-wheel-disabled.svg78
-rw-r--r--assets/carbon_icons/meter-disabled.svg85
-rw-r--r--assets/carbon_icons/windy--strong-disabled.svg1
-rw-r--r--assets/res.qrc3
-rw-r--r--extras/KuksaClient.py (renamed from extras/FeedKuksa.py)70
-rw-r--r--extras/config.ini2
-rw-r--r--main.py19
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="&lt;Transparent Rectangle&gt;"
+ 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="&lt;Transparent Rectangle&gt;" 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
diff --git a/main.py b/main.py
index b6b0b2f..18cc49b 100644
--- a/main.py
+++ b/main.py
@@ -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_())