import json import random import time from pathlib import Path class ESP32Simulator: def __init__(self): self.relays = { "starlink": False, "fridge": True } self.wifi_override_until = 0 self.ignition_on = True self.soc = 82.0 self.last_update = time.time() def load_config(self): config_path = Path(__file__).parent / "config.json" with config_path.open() as f: return json.load(f) def update_battery(self): now = time.time() elapsed_hours = (now - self.last_update) / 3600 self.last_update = now load_amps = 6.0 if self.relays["starlink"]: load_amps += 4.5 if self.relays["fridge"]: load_amps += 2.0 capacity_ah = 100 self.soc -= (load_amps * elapsed_hours / capacity_ah) * 100 self.soc = max(self.soc, 0) return -load_amps def get_status(self): current = self.update_battery() starlink_on = self.relays["starlink"] wifi_override_active = time.time() < self.wifi_override_until temps = { "fridge_zone_1": self.sensor(36, 2), "fridge_zone_2": self.sensor(12, 3), "rear_seat": self.sensor(78, 8), "outside": self.sensor(88, 8) } sensor_health = { "fridge_zone_1": True, "fridge_zone_2": True, "rear_seat": True, "outside": True } remaining_ah = round(self.soc, 1) runtime_hours = round(remaining_ah / abs(current), 1) if current else 0 return { "timestamp": int(time.time()), "vehicle": { "ignition_on": self.ignition_on }, "battery": { "soc": round(self.soc), "voltage": round(13.0 + (self.soc / 100) * 0.4, 2), "current": round(current, 1), "remaining_ah": remaining_ah, "runtime_hours": runtime_hours, "temperature_f": self.sensor(76, 4) }, "temps": temps, "sensor_health": sensor_health, "relays": self.relays, "network": { "wifi_enabled": starlink_on or wifi_override_active, "wifi_override_active": wifi_override_active, "rs485_connected": True, "starlink_enabled": starlink_on }, "config": self.load_config() } def sensor(self, base, spread): return round(random.uniform(base - spread, base + spread), 1) def set_relay(self, name, state): if name not in self.relays: return False self.relays[name] = bool(state) return True def enable_wifi(self, minutes): self.wifi_override_until = time.time() + minutes * 60 def toggle_ignition(self): self.ignition_on = not self.ignition_on return self.ignition_on esp32 = ESP32Simulator()