Add Pico detail screen view models
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
from .dashboard_view_model import format_value, format_bool
|
||||
|
||||
|
||||
class BatteryViewModel:
|
||||
def __init__(self, state):
|
||||
self.state = state
|
||||
|
||||
def as_dict(self):
|
||||
battery = self.state.battery
|
||||
|
||||
return {
|
||||
"soc": format_value(battery.get("soc"), "%", decimals=0),
|
||||
"voltage": format_value(battery.get("voltage"), "V", decimals=1),
|
||||
"current": format_value(battery.get("current"), "A", decimals=1),
|
||||
"remaining_ah": format_value(battery.get("remaining_ah"), "Ah", decimals=1),
|
||||
"runtime_hours": format_value(battery.get("runtime_hours"), " hr", decimals=1),
|
||||
"temperature_f": format_value(battery.get("temperature_f"), "°F", decimals=1),
|
||||
}
|
||||
|
||||
|
||||
class TempsViewModel:
|
||||
SENSOR_LABELS = {
|
||||
"fridge_zone_1": "Fridge Zone 1",
|
||||
"fridge_zone_2": "Fridge Zone 2",
|
||||
"rear_seat": "Rear Seat",
|
||||
"outside": "Outside Air",
|
||||
}
|
||||
|
||||
def __init__(self, state):
|
||||
self.state = state
|
||||
|
||||
def as_list(self):
|
||||
rows = []
|
||||
|
||||
for key, label in self.SENSOR_LABELS.items():
|
||||
online = self.state.sensor_health.get(key, False)
|
||||
temp = self.state.temps.get(key)
|
||||
|
||||
rows.append({
|
||||
"key": key,
|
||||
"label": label,
|
||||
"temperature": format_value(temp, "°F", decimals=1),
|
||||
"status": "OK" if online else "FAULT",
|
||||
})
|
||||
|
||||
return rows
|
||||
|
||||
|
||||
class PowerViewModel:
|
||||
def __init__(self, state):
|
||||
self.state = state
|
||||
|
||||
def as_dict(self):
|
||||
return {
|
||||
"starlink": format_bool(self.state.relays.get("starlink")),
|
||||
"fridge": format_bool(self.state.relays.get("fridge")),
|
||||
}
|
||||
|
||||
|
||||
class SystemViewModel:
|
||||
def __init__(self, state):
|
||||
self.state = state
|
||||
|
||||
def as_dict(self):
|
||||
sensor_count = sum(1 for online in self.state.sensor_health.values() if online)
|
||||
total_sensors = len(self.state.sensor_health)
|
||||
|
||||
return {
|
||||
"esp32": "Online" if self.state.network.get("uart_connected") else "Unknown",
|
||||
"uart": "Connected" if self.state.network.get("uart_connected") else "Disconnected",
|
||||
"wifi_api": "Available" if self.state.network.get("wifi_enabled") else "Unavailable",
|
||||
"sensors": f"{sensor_count} / {total_sensors} OK",
|
||||
"ignition": "On" if self.state.vehicle.get("ignition_on") else "Off",
|
||||
}
|
||||
@@ -482,3 +482,104 @@ def test_dashboard_view_model_handles_missing_values():
|
||||
|
||||
assert vm["battery"]["voltage"] == "--"
|
||||
assert vm["fridge"]["zone_1"] == "--"
|
||||
|
||||
|
||||
def test_battery_view_model():
|
||||
from ui.detail_view_models import BatteryViewModel
|
||||
|
||||
state = AppState()
|
||||
state.update_from_status({
|
||||
"battery": {
|
||||
"soc": 82,
|
||||
"voltage": 13.2,
|
||||
"current": -6.4,
|
||||
"remaining_ah": 82.0,
|
||||
"runtime_hours": 12.0,
|
||||
"temperature_f": 76.0,
|
||||
}
|
||||
})
|
||||
|
||||
vm = BatteryViewModel(state).as_dict()
|
||||
|
||||
assert vm["soc"] == "82%"
|
||||
assert vm["voltage"] == "13.2V"
|
||||
assert vm["current"] == "-6.4A"
|
||||
assert vm["remaining_ah"] == "82.0Ah"
|
||||
assert vm["runtime_hours"] == "12.0 hr"
|
||||
assert vm["temperature_f"] == "76.0°F"
|
||||
|
||||
|
||||
def test_temps_view_model():
|
||||
from ui.detail_view_models import TempsViewModel
|
||||
|
||||
state = AppState()
|
||||
state.update_from_status({
|
||||
"temps": {
|
||||
"fridge_zone_1": 34.5,
|
||||
"fridge_zone_2": 36.0,
|
||||
"rear_seat": 71.2,
|
||||
"outside": None,
|
||||
},
|
||||
"sensor_health": {
|
||||
"fridge_zone_1": True,
|
||||
"fridge_zone_2": True,
|
||||
"rear_seat": True,
|
||||
"outside": False,
|
||||
}
|
||||
})
|
||||
|
||||
rows = TempsViewModel(state).as_list()
|
||||
|
||||
assert rows[0]["label"] == "Fridge Zone 1"
|
||||
assert rows[0]["temperature"] == "34.5°F"
|
||||
assert rows[0]["status"] == "OK"
|
||||
|
||||
assert rows[3]["label"] == "Outside Air"
|
||||
assert rows[3]["temperature"] == "--"
|
||||
assert rows[3]["status"] == "FAULT"
|
||||
|
||||
|
||||
def test_power_view_model():
|
||||
from ui.detail_view_models import PowerViewModel
|
||||
|
||||
state = AppState()
|
||||
state.update_from_status({
|
||||
"relays": {
|
||||
"starlink": False,
|
||||
"fridge": True,
|
||||
}
|
||||
})
|
||||
|
||||
vm = PowerViewModel(state).as_dict()
|
||||
|
||||
assert vm["starlink"] == "OFF"
|
||||
assert vm["fridge"] == "ON"
|
||||
|
||||
|
||||
def test_system_view_model():
|
||||
from ui.detail_view_models import SystemViewModel
|
||||
|
||||
state = AppState()
|
||||
state.update_from_status({
|
||||
"sensor_health": {
|
||||
"fridge_zone_1": True,
|
||||
"fridge_zone_2": True,
|
||||
"rear_seat": False,
|
||||
"outside": True,
|
||||
},
|
||||
"vehicle": {
|
||||
"ignition_on": False,
|
||||
},
|
||||
"network": {
|
||||
"uart_connected": True,
|
||||
"wifi_enabled": True,
|
||||
}
|
||||
})
|
||||
|
||||
vm = SystemViewModel(state).as_dict()
|
||||
|
||||
assert vm["esp32"] == "Online"
|
||||
assert vm["uart"] == "Connected"
|
||||
assert vm["wifi_api"] == "Available"
|
||||
assert vm["sensors"] == "3 / 4 OK"
|
||||
assert vm["ignition"] == "Off"
|
||||
|
||||
Reference in New Issue
Block a user