diff --git a/simulator/app.py b/simulator/app.py index a4c0067..2cf4154 100644 --- a/simulator/app.py +++ b/simulator/app.py @@ -19,17 +19,17 @@ def status(): @app.route("/battery") def battery(): - return jsonify(pico.get_status()["battery"]) + return jsonify(pico.get_status().get("battery", {})) @app.route("/temps") def temps(): - return jsonify(pico.get_status()["temps"]) + return jsonify(pico.get_status().get("temps", {})) @app.route("/relays") def relays(): - return jsonify(pico.get_status()["relays"]) + return jsonify(pico.get_status().get("relays", {})) @app.route("/relay/", methods=["POST"]) @@ -37,38 +37,65 @@ def set_relay(name): data = request.get_json(force=True) response = pico.set_relay(name, data.get("state", False)) - if not response["success"]: - return jsonify(response), 404 + if not response.get("success"): + return jsonify(response), 503 return jsonify(response) @app.route("/network") def network(): - return jsonify(pico.get_status()["network"]) + return jsonify(pico.get_status().get("network", {})) @app.route("/network/wifi", methods=["POST"]) def enable_wifi(): data = request.get_json(force=True) minutes = int(data.get("minutes", 10)) - return jsonify(pico.enable_wifi(minutes)) + response = pico.enable_wifi(minutes) + + if not response.get("success"): + return jsonify(response), 503 + + return jsonify(response) @app.route("/vehicle/ignition", methods=["POST"]) def toggle_ignition(): - return jsonify(pico.toggle_ignition()) + response = pico.toggle_ignition() + + if not response.get("success"): + return jsonify(response), 503 + + return jsonify(response) @app.route("/sensor//fault", methods=["POST"]) def toggle_sensor_fault(name): response = pico.toggle_sensor_fault(name) - if not response["success"]: - return jsonify(response), 404 + if not response.get("success"): + return jsonify(response), 503 return jsonify(response) +@app.route("/comms") +def comms(): + return jsonify(pico.get_comms()) + + +@app.route("/comms/rs485/disconnect", methods=["POST"]) +def disconnect_rs485(): + pico.disconnect_rs485() + return jsonify({"success": True, "rs485_connected": False}) + + +@app.route("/comms/rs485/restore", methods=["POST"]) +def restore_rs485(): + pico.restore_rs485() + return jsonify({"success": True, "rs485_connected": True}) + + if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True) diff --git a/simulator/pico_sim.py b/simulator/pico_sim.py index 70d1821..0456889 100644 --- a/simulator/pico_sim.py +++ b/simulator/pico_sim.py @@ -1,5 +1,6 @@ +import time + from protocol import ( - MessageType, status_request, set_relay_request, enable_wifi_request, @@ -13,20 +14,65 @@ class PicoSimulator: self.controller = controller self.last_status = None self.primary_link = "rs485" + self.rs485_connected = True self.backup_link_available = True + self.messages_sent = 0 + self.messages_received = 0 + self.last_message_time = None def send_message(self, message): - """ - This simulates the Pico sending a protocol message to the ESP32. + self.messages_sent += 1 - Later, this is where RS-485 serial communication will replace - the direct Python method call. - """ - return self.controller.handle_message(message) + if not self.rs485_connected: + return { + "type": "error", + "success": False, + "error": "RS-485 disconnected" + } + + response = self.controller.handle_message(message) + self.messages_received += 1 + self.last_message_time = int(time.time()) + return response def get_status(self): response = self.send_message(status_request()) + + if response.get("type") == "error": + if self.last_status: + self.last_status["network"]["rs485_connected"] = False + self.last_status["network"]["communication_lost"] = True + self.last_status["network"]["messages_sent"] = self.messages_sent + self.last_status["network"]["messages_received"] = self.messages_received + self.last_status["network"]["last_message_time"] = self.last_message_time + return self.last_status + + return { + "timestamp": int(time.time()), + "vehicle": {"ignition_on": True}, + "battery": {}, + "temps": {}, + "sensor_health": {}, + "relays": {}, + "network": { + "rs485_connected": False, + "communication_lost": True, + "wifi_enabled": False, + "wifi_override_active": False, + "starlink_enabled": False, + "messages_sent": self.messages_sent, + "messages_received": self.messages_received, + "last_message_time": self.last_message_time + }, + "config": {} + } + self.last_status = response["data"] + self.last_status["network"]["rs485_connected"] = self.rs485_connected + self.last_status["network"]["communication_lost"] = False + self.last_status["network"]["messages_sent"] = self.messages_sent + self.last_status["network"]["messages_received"] = self.messages_received + self.last_status["network"]["last_message_time"] = self.last_message_time return self.last_status def set_relay(self, relay, state): @@ -40,3 +86,19 @@ class PicoSimulator: def toggle_sensor_fault(self, sensor): return self.send_message(toggle_sensor_fault_request(sensor)) + + def disconnect_rs485(self): + self.rs485_connected = False + + def restore_rs485(self): + self.rs485_connected = True + + def get_comms(self): + return { + "primary": self.primary_link, + "backup_available": self.backup_link_available, + "rs485_connected": self.rs485_connected, + "messages_sent": self.messages_sent, + "messages_received": self.messages_received, + "last_message_time": self.last_message_time + } diff --git a/simulator/static/style.css b/simulator/static/style.css index 60eb5bc..9dda027 100644 --- a/simulator/static/style.css +++ b/simulator/static/style.css @@ -308,3 +308,19 @@ nav button { color: #ffaaaa; font-weight: bold; } + +.comms-lost header { + border: 2px solid #b00020; + border-radius: 12px; + padding: 10px; + background: #260808; +} + +.settings-list input[type="checkbox"] { + width: 28px; + height: 28px; +} + +#config .settings-list { + margin-bottom: 18px; +} diff --git a/simulator/templates/index.html b/simulator/templates/index.html index aaa9cee..5c52656 100644 --- a/simulator/templates/index.html +++ b/simulator/templates/index.html @@ -90,6 +90,18 @@ +

Communication

+
+
Primary Link --
+
Backup Available --
+
Messages Sent --
+
Messages Received --
+
Last Message --
+
+ + + +

Sensor Fault Simulation

@@ -98,35 +110,6 @@
-

Alarm Settings

-
- - - - - - - - - - - -
@@ -136,6 +119,7 @@ +