Files
volvodisplay/main.py

181 lines
6.1 KiB
Python
Raw Normal View History

import sys
import os
import json
import math
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
from PySide6.QtCore import QObject, Property, Signal, Slot, QTimer
# Try importing w1thermsensor, handle failure for dev environments
try:
from w1thermsensor import W1ThermSensor, Sensor
HAS_W1 = True
except ImportError:
HAS_W1 = False
print("Warning: w1thermsensor not found. Running in simulation mode.")
class Backend(QObject):
leftTempChanged = Signal()
rightTempChanged = Signal()
def __init__(self, demo_mode=False):
super().__init__()
self.demo_mode = demo_mode
self._left_temp = 0.0
self._right_temp = 0.0
self.left_sensor = None
self.right_sensor = None
# Load Config
self.config = self.load_config()
# Initialize Sensors
self.init_sensors()
# Timer for polling
self.timer = QTimer()
self.timer.timeout.connect(self.update_temps)
self.timer.start(2000) # Poll every 2 seconds
def load_config(self):
2026-01-14 14:58:30 +01:00
# Determine path based on run mode (Script vs Frozen/Compiled)
if getattr(sys, 'frozen', False):
# If run as a compiled exe, look in the same directory as the executable
application_path = os.path.dirname(sys.executable)
else:
# If run as a script, look in the directory of the script
application_path = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(application_path, "config.json")
if os.path.exists(config_path):
try:
with open(config_path, 'r') as f:
return json.load(f)
except Exception as e:
print(f"Error loading config: {e}")
return {}
def init_sensors(self):
if not HAS_W1:
print("W1ThermSensor not installed.")
return
print(f"Loading sensors using config: {self.config}")
try:
available_sensors = W1ThermSensor.get_available_sensors()
print(f"Available W1 sensors: {[s.id for s in available_sensors]}")
# Map Left Sensor
left_id = self.config.get("left_sensor_id")
if left_id:
try:
# Check if ID exists in available to be sure
found = next((s for s in available_sensors if s.id == left_id), None)
if found:
self.left_sensor = found
print(f"✅ Successfully bound Left Sensor to {left_id}")
else:
print(f"❌ Configured Left Sensor {left_id} not found in available list!")
# Try direct init anyway just in case
self.left_sensor = W1ThermSensor(sensor_id=left_id)
except Exception as e:
print(f"❌ Failed to bind Left Sensor {left_id}: {e}")
# Auto-assign fallback
if not self.left_sensor and len(available_sensors) > 0:
self.left_sensor = available_sensors[0]
print(f"⚠️ Auto-assigned Left Sensor to {self.left_sensor.id}")
# Map Right Sensor
right_id = self.config.get("right_sensor_id")
if right_id:
try:
self.right_sensor = W1ThermSensor(sensor_id=right_id)
print(f"Bound Right Sensor to {right_id}")
except Exception as e:
print(f"Failed to bind Right Sensor {right_id}: {e}")
except Exception as e:
print(f"Error initializing sensors: {e}")
def update_temps(self):
# Simulation counter
if not hasattr(self, '_sim_step'):
self._sim_step = 0
self._sim_step += 0.1
# Left
if self.left_sensor:
try:
t = self.left_sensor.get_temperature()
print(f"Left Sensor ({self.left_sensor.id}) Read: {t}°C")
self._set_left_temp(t)
except Exception as e:
print(f"Error reading left sensor: {e}")
elif self.demo_mode:
# Simulation
print("Left Sensor Missing - Simulating...")
sim_val = 5 + 10 * math.sin(self._sim_step)
self._set_left_temp(sim_val)
# Right
if self.right_sensor:
try:
t = self.right_sensor.get_temperature()
self._set_right_temp(t)
except Exception as e:
print(f"Error reading right sensor: {e}")
elif self.demo_mode:
# Simulation
sim_val = 10 + 10 * math.cos(self._sim_step)
self._set_right_temp(sim_val)
@Property(float, notify=leftTempChanged)
def leftTemp(self):
return self._left_temp
def _set_left_temp(self, val):
if abs(self._left_temp - val) > 0.1:
self._left_temp = val
self.leftTempChanged.emit()
@Property(float, notify=rightTempChanged)
def rightTemp(self):
return self._right_temp
def _set_right_temp(self, val):
if abs(self._right_temp - val) > 0.1:
self._right_temp = val
self.rightTempChanged.emit()
def main():
# Redirect output to log.txt
sys.stdout = open("log.txt", "w", buffering=1)
sys.stderr = sys.stdout
print("--- Volvo Display Log ---")
# Check for demo mode
demo_mode = "--demo" in sys.argv
if demo_mode:
print("Starting in DEMO MODE (Simulation Enabled)")
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
backend = Backend(demo_mode=demo_mode)
engine.rootContext().setContextProperty("backend", backend)
# Get absolute path to main.qml
current_dir = os.path.dirname(os.path.abspath(__file__))
qml_file = os.path.join(current_dir, "main.qml")
engine.load(qml_file)
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec())
if __name__ == "__main__":
main()