import { useMemo, useState } from 'react';
import { useSession } from '../context/SessionContext.jsx';
import { useTelemetryFrame } from '../context/TelemetryContext.jsx';
function formatMetric(value, fallback = '--') {
if (value == null || value === '') return fallback;
return value;
}
export default function TelemetryPanel() {
const { connected, session, requestControl } = useSession();
const roverId = session?.assignment?.roverId;
const frame = useTelemetryFrame(roverId);
const sensors = frame?.sensors || {};
const voltage = sensors.voltageMv != null ? `${(sensors.voltageMv / 1000).toFixed(2)} V` : null;
const current = sensors.currentMa != null ? `${sensors.currentMa} mA` : null;
const charge = sensors.batteryChargeMah;
const capacity = sensors.batteryCapacityMah;
const updated = frame?.receivedAt ? new Date(frame.receivedAt).toLocaleTimeString() : null;
const rawSnippet = frame?.raw ? (frame.raw.length > 80 ? `${frame.raw.slice(0, 80)}…` : frame.raw) : null;
const roster = session?.roster ?? [];
const isAdmin = useMemo(
() => session?.role === 'admin' || session?.role === 'lockdown' || session?.role === 'lockdown-admin',
[session?.role],
);
const [pending, setPending] = useState({});
async function handleRequest(roverId) {
if (!roverId) return;
setPending((prev) => ({ ...prev, [roverId]: true }));
try {
await requestControl(roverId);
} catch (err) {
alert(err.message);
} finally {
setPending((prev) => ({ ...prev, [roverId]: false }));
}
}
return (
Assign a rover to view sensors. Waiting for sensor frames… Rovers No roster data. {rover.name}
{rover.locked ? 'locked' : 'free'} · {rover.lastSeen ? 'seen' : 'unknown'}
{rawSnippet}
)}
{roster.map((rover) => (
)}