aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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_())