248 lines
11 KiB
Python
248 lines
11 KiB
Python
# --- REPLACE the entire content of ui/widgets.py with this ---
|
|
|
|
from PyQt6.QtWidgets import (
|
|
QGroupBox, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QFrame, QPushButton, QFormLayout, QSizePolicy
|
|
)
|
|
from PyQt6.QtCore import Qt, pyqtSignal
|
|
from PyQt6.QtGui import QFont
|
|
|
|
class ChamberWidget(QGroupBox):
|
|
# Signals for button presses
|
|
open_door_requested = pyqtSignal()
|
|
chg_on_requested = pyqtSignal()
|
|
chg_off_requested = pyqtSignal()
|
|
|
|
def __init__(self, title="CHAMBER - X", scale=1.0):
|
|
super().__init__(title)
|
|
self.setObjectName("ChamberWidget")
|
|
self.setFont(QFont("Arial", max(8, int(9 * scale)), QFont.Weight.Bold))
|
|
|
|
main_layout = QVBoxLayout(self)
|
|
main_layout.setSpacing(max(2, int(4 * scale)))
|
|
|
|
# --- Battery ID ---
|
|
id_layout = QHBoxLayout()
|
|
id_layout.addWidget(QLabel("BAT ID: "))
|
|
self.id_field = self._create_data_field(scale)
|
|
self.id_field.setObjectName("BatIdField")
|
|
id_layout.addWidget(self.id_field)
|
|
main_layout.addLayout(id_layout)
|
|
|
|
# --- Main Data Columns ---
|
|
columns_layout = QHBoxLayout()
|
|
|
|
# == Left Column: Battery Info ==
|
|
battery_form_layout = QFormLayout()
|
|
battery_form_layout.setVerticalSpacing(max(2, int(4 * scale)))
|
|
|
|
self.battery_status_label = self._create_status_label("ABSENT", scale)
|
|
self.battery_status_label.setProperty("status", "absent")
|
|
|
|
self.soc_field = self._create_data_field(scale)
|
|
self.soc_field.setObjectName("DataField")
|
|
|
|
self.voltage_field = self._create_data_field(scale)
|
|
self.voltage_field.setObjectName("DataField")
|
|
|
|
self.temp_field = self._create_data_field(scale)
|
|
self.temp_field.setObjectName("DataField")
|
|
|
|
self.battery_fault_field = self._create_data_field(scale)
|
|
self.battery_fault_field.setObjectName("DataField")
|
|
|
|
battery_form_layout.addRow("Status:", self.battery_status_label)
|
|
battery_form_layout.addRow("SOC:", self.soc_field)
|
|
battery_form_layout.addRow("Voltage:", self.voltage_field)
|
|
battery_form_layout.addRow("Temp:", self.temp_field)
|
|
battery_form_layout.addRow("Fault:", self.battery_fault_field)
|
|
|
|
# == Separator ==
|
|
separator_line = QFrame()
|
|
separator_line.setFrameShape(QFrame.Shape.VLine)
|
|
separator_line.setFrameShadow(QFrame.Shadow.Sunken)
|
|
|
|
# == Right Column: Charger Info ==
|
|
charger_form_layout = QFormLayout()
|
|
charger_form_layout.setVerticalSpacing(max(2, int(4 * scale)))
|
|
|
|
self.charger_status_label = self._create_status_label("OFF", scale)
|
|
self.charger_status_label.setProperty("status", "absent")
|
|
|
|
self.chg_temp_field = self._create_data_field(scale)
|
|
self.chg_temp_field.setObjectName("DataField")
|
|
|
|
self.charger_fault_field = self._create_data_field(scale)
|
|
self.charger_fault_field.setObjectName("DataField")
|
|
|
|
self.current_field = self._create_data_field(scale)
|
|
self.current_field.setObjectName("DataField")
|
|
|
|
self.slot_temp_field = self._create_data_field(scale)
|
|
self.slot_temp_field.setObjectName("DataField")
|
|
|
|
charger_form_layout.addRow("Chg Status:", self.charger_status_label)
|
|
charger_form_layout.addRow("Chg Temp:", self.chg_temp_field)
|
|
charger_form_layout.addRow("Fault:", self.charger_fault_field)
|
|
charger_form_layout.addRow("Current:", self.current_field)
|
|
charger_form_layout.addRow("Slot Temp:", self.slot_temp_field)
|
|
|
|
columns_layout.addLayout(battery_form_layout)
|
|
columns_layout.addWidget(separator_line)
|
|
columns_layout.addLayout(charger_form_layout)
|
|
main_layout.addLayout(columns_layout)
|
|
|
|
main_layout.addStretch()
|
|
|
|
# --- Door status and buttons are on one line ---
|
|
button_layout = QHBoxLayout()
|
|
|
|
# Part 1: Door Status (fixed size on the left)
|
|
button_layout.addWidget(QLabel("Door Status:"))
|
|
self.door_status_field = self._create_data_field(scale)
|
|
self.door_status_field.setObjectName("DoorStatusField")
|
|
self.door_status_field.setMaximumWidth(int(140 * scale))
|
|
button_layout.addWidget(self.door_status_field)
|
|
|
|
# Part 2: Buttons
|
|
self.open_door_btn = QPushButton("OPEN DOOR")
|
|
self.chg_on_btn = QPushButton("CHG ON")
|
|
self.chg_off_btn = QPushButton("CHG OFF")
|
|
|
|
self.open_door_btn.setObjectName("ChamberOpenDoorButton")
|
|
self.chg_on_btn.setObjectName("ChamberChgOnButton")
|
|
self.chg_off_btn.setObjectName("ChamberChgOffButton")
|
|
|
|
self.open_door_btn.clicked.connect(self.open_door_requested.emit)
|
|
self.chg_on_btn.clicked.connect(self.chg_on_requested.emit)
|
|
self.chg_off_btn.clicked.connect(self.chg_off_requested.emit)
|
|
|
|
button_layout.addWidget(self.open_door_btn)
|
|
button_layout.addWidget(self.chg_on_btn)
|
|
button_layout.addWidget(self.chg_off_btn)
|
|
|
|
main_layout.addLayout(button_layout)
|
|
|
|
def _create_status_label(self, text, scale):
|
|
label = QLabel(text)
|
|
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
label.setFont(QFont("Arial", max(7, int(8 * scale)), QFont.Weight.Bold))
|
|
return label
|
|
|
|
def _create_data_field(self, scale):
|
|
field = QLineEdit(" ")
|
|
field.setReadOnly(True)
|
|
field.setFont(QFont("Arial", max(7, int(8 * scale))))
|
|
return field
|
|
|
|
def update_data(self, data):
|
|
# Retrieve battery and charger presence with fallback keys
|
|
battery_present_status = data.get("batteryPresent")
|
|
# <-- MODIFIED: Now checks for 'chargerPresent' key from your payload
|
|
charger_on_status = data.get("chargerPresent", data.get("chargerOn", data.get("chgStatus", 0)))
|
|
|
|
if battery_present_status == 1:
|
|
self.battery_status_label.setText("PRESENT")
|
|
self.battery_status_label.setProperty("status", "present")
|
|
else:
|
|
self.battery_status_label.setText("ABSENT")
|
|
self.battery_status_label.setProperty("status", "absent")
|
|
|
|
if charger_on_status == 1:
|
|
self.charger_status_label.setText("CHARGER ON")
|
|
self.charger_status_label.setProperty("status", "present")
|
|
else:
|
|
self.charger_status_label.setText("CHARGER OFF")
|
|
self.charger_status_label.setProperty("status", "absent")
|
|
|
|
for widget in [self.battery_status_label, self.charger_status_label]:
|
|
widget.style().unpolish(widget)
|
|
widget.style().polish(widget)
|
|
|
|
self.id_field.setText(data.get("batteryIdentification", " "))
|
|
self.soc_field.setText(f'{data.get("soc", 0)}%')
|
|
self.voltage_field.setText(f'{data.get("voltage", 0) / 1000.0:.2f} V')
|
|
self.temp_field.setText(f'{data.get("batteryMaxTemp", 0) / 10.0:.1f} °C')
|
|
self.battery_fault_field.setText(str(data.get("batteryFaultCode", 0)))
|
|
|
|
# <-- MODIFIED: Now checks for 'chargerMaxTemp' key from your payload
|
|
charger_temp = data.get("chargerMaxTemp", data.get("chargerTemp", data.get("chgTemp", 0)))
|
|
self.chg_temp_field.setText(f'{charger_temp / 10.0:.1f} °C')
|
|
self.charger_fault_field.setText(str(data.get("chargerFaultCode", 0)))
|
|
self.current_field.setText(f'{data.get("current", 0) / 1000.0:.2f} A')
|
|
|
|
slot_temp = data.get("slotTemperature", data.get("slotTemp", 0))
|
|
self.slot_temp_field.setText(f'{slot_temp / 10.0:.1f} °C')
|
|
|
|
door_status = "OPEN" if data.get("doorStatus") == 1 else "CLOSED"
|
|
self.door_status_field.setText(door_status)
|
|
|
|
if door_status == "OPEN":
|
|
self.door_status_field.setStyleSheet("background-color: #2E7D32; color: white; border-radius: 3px;")
|
|
else:
|
|
self.door_status_field.setStyleSheet("background-color: #C62828; color: white; border-radius: 3px;")
|
|
|
|
|
|
|
|
# def update_data(self, data):
|
|
# if data.get("batteryPresent") == 1:
|
|
# self.battery_status_label.setText("PRESENT")
|
|
# self.battery_status_label.setProperty("status", "present")
|
|
# else:
|
|
# self.battery_status_label.setText("ABSENT")
|
|
# self.battery_status_label.setProperty("status", "absent")
|
|
|
|
# if data.get("chargerOn") == 1:
|
|
# self.charger_status_label.setText("CHARGER ON")
|
|
# self.charger_status_label.setProperty("status", "present")
|
|
# else:
|
|
# self.charger_status_label.setText("CHARGER OFF")
|
|
# self.charger_status_label.setProperty("status", "absent")
|
|
|
|
# for widget in [self.battery_status_label, self.charger_status_label]:
|
|
# widget.style().unpolish(widget)
|
|
# widget.style().polish(widget)
|
|
|
|
# self.id_field.setText(data.get("batteryIdentification", " "))
|
|
# self.soc_field.setText(f'{data.get("soc", 0)}%')
|
|
# self.voltage_field.setText(f'{data.get("voltage", 0) / 1000.0:.2f} V')
|
|
# self.temp_field.setText(f'{data.get("batteryMaxTemp", 0) / 10.0:.1f} °C')
|
|
# self.battery_fault_field.setText(str(data.get("batteryFaultCode", 0)))
|
|
|
|
# self.chg_temp_field.setText(f'{data.get("chargerTemp", 0) / 10.0:.1f} °C')
|
|
# self.charger_fault_field.setText(str(data.get("chargerFaultCode", 0)))
|
|
# self.current_field.setText(f'{data.get("current", 0) / 1000.0:.2f} A')
|
|
# self.slot_temp_field.setText(f'{data.get("slotTemperature", 0) / 10.0:.1f} °C')
|
|
|
|
# door_status = "OPEN" if data.get("doorStatus") == 1 else "CLOSED"
|
|
# self.door_status_field.setText(door_status)
|
|
|
|
# # --- ADDED: Set color based on door status ---
|
|
# if door_status == "OPEN":
|
|
# self.door_status_field.setStyleSheet("background-color: #2E7D32; color: white; border-radius: 3px;")
|
|
# else: # CLOSED
|
|
# self.door_status_field.setStyleSheet("background-color: #C62828; color: white; border-radius: 3px;")
|
|
|
|
def reset_to_default(self):
|
|
"""Resets all fields in this chamber widget to their default state."""
|
|
self.battery_status_label.setText("ABSENT")
|
|
self.battery_status_label.setProperty("status", "absent")
|
|
self.charger_status_label.setText("CHARGER OFF")
|
|
self.charger_status_label.setProperty("status", "absent")
|
|
|
|
for widget in [self.battery_status_label, self.charger_status_label]:
|
|
widget.style().unpolish(widget)
|
|
widget.style().polish(widget)
|
|
|
|
self.id_field.setText(" ")
|
|
self.soc_field.setText(" ")
|
|
self.voltage_field.setText(" ")
|
|
self.temp_field.setText(" ")
|
|
self.battery_fault_field.setText(" ")
|
|
self.chg_temp_field.setText(" ")
|
|
self.charger_fault_field.setText(" ")
|
|
self.current_field.setText(" ")
|
|
self.slot_temp_field.setText(" ")
|
|
self.door_status_field.setText(" ")
|
|
|
|
# --- ADDED: Reset the color ---
|
|
self.door_status_field.setStyleSheet("") |