diff --git a/firmware/config/device.json b/firmware/config/device.json
index b303545..6136790 100644
--- a/firmware/config/device.json
+++ b/firmware/config/device.json
@@ -3,5 +3,5 @@
"mode": "DEV",
"active_slot": "A",
"status": "OFFLINE",
- "name": "Unnamed Device"
+ "name": "Unnamed Device0"
}
\ No newline at end of file
diff --git a/firmware/simulator.py b/firmware/simulator.py
index b38c108..a8af0c5 100644
--- a/firmware/simulator.py
+++ b/firmware/simulator.py
@@ -143,12 +143,13 @@ if __name__ == "__main__":
print(" 4. Switch to PROD Mode")
print(" 5. Swap Active Slot (A/B)")
print(" 6. Start Automated Loop")
+ print(" 7. Request Re-enlistment")
print(" 0. Exit Orchestrator")
print("-" * 45)
while True:
print_menu()
- choice = input("Select operation [0-6] >> ").strip()
+ choice = input("Select operation [0-7] >> ").strip()
if choice == "1":
hu.register()
@@ -177,6 +178,9 @@ if __name__ == "__main__":
break
except KeyboardInterrupt:
print("\n[!] Loop interrupted by user.")
+ elif choice == "7":
+ hu.status = "PENDING"
+ hu.register()
elif choice == "0":
print("[*] Powering down head unit...")
break
diff --git a/prisma/dev.db b/prisma/dev.db
index 58b8b6f..19709b5 100644
Binary files a/prisma/dev.db and b/prisma/dev.db differ
diff --git a/src/app/admin/devices/[id]/page.tsx b/src/app/admin/devices/[id]/page.tsx
index 41ffa6e..903affc 100644
--- a/src/app/admin/devices/[id]/page.tsx
+++ b/src/app/admin/devices/[id]/page.tsx
@@ -155,20 +155,42 @@ export default function DeviceConfigPage({ params }: { params: Promise<{ id: str
-
-
+ {device.status === "OFFLINE" ? (
+
+ ) : (
+ <>
+
+
+ >
+ )}
diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx
index b8c2cab..163e051 100644
--- a/src/app/admin/page.tsx
+++ b/src/app/admin/page.tsx
@@ -1,7 +1,7 @@
"use client";
import { useState, useEffect } from "react";
-import { Shield, ArrowRight, Settings2, PlusCircle, CheckCircle2, XCircle, Clock, ChevronRight } from "lucide-react";
+import { Shield, ArrowRight, Settings2, PlusCircle, CheckCircle2, XCircle, Clock, ChevronRight, RefreshCw } from "lucide-react";
import Link from "next/link";
interface Device {
@@ -27,7 +27,8 @@ export default function AdminPage() {
});
}, []);
- const handleEnroll = async (id: string) => {
+ const handleEnroll = async (id: string, currentStatus: string) => {
+ const nextStatus = currentStatus === "OFFLINE" ? "ENROLLED" : "ENROLLED";
const res = await fetch(`/api/devices/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
@@ -38,6 +39,19 @@ export default function AdminPage() {
}
};
+ const handleDecommission = async (id: string) => {
+ if (!confirm("Are you sure you want to decommission this hardware node? It will be disconnected from the active mesh.")) return;
+
+ const res = await fetch(`/api/devices/${id}`, {
+ method: "PATCH",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ status: "OFFLINE" }),
+ });
+ if (res.ok) {
+ setDevices(devices.map(d => d.id === id ? { ...d, status: "OFFLINE" } : d));
+ }
+ };
+
const handleUpdateName = async (id: string, name: string) => {
await fetch(`/api/devices/${id}`, {
method: "PATCH",
@@ -145,14 +159,22 @@ export default function AdminPage() {
{device.status === "PENDING" ? (
+ ) : device.status === "OFFLINE" ? (
+
) : (
|