requet fix and ui change

This commit is contained in:
legop3
2026-05-01 19:48:04 -04:00
parent 6280724f6e
commit 9c287f068a
7 changed files with 35 additions and 58 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -11,8 +11,8 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" /> <meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
<title>Multi Roomba Rover</title> <title>Multi Roomba Rover</title>
<script type="module" crossorigin src="/assets/index-BT4tyIib.js"></script> <script type="module" crossorigin src="/assets/index-BpIdNRSY.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DYarsG-0.css"> <link rel="stylesheet" crossorigin href="/assets/index-CGvUXLso.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
-10
View File
@@ -275,13 +275,6 @@ function broadcastLidarScan(payload) {
} }
} }
function broadcastLidarLine(payload) {
for (const socket of io.sockets.sockets.values()) {
if (!isVerified(socket)) continue;
socket.emit('neato:lidarLine', payload);
}
}
lidarRuntime = lidarRuntime =
brainslugHost && brainslugKey brainslugHost && brainslugKey
? createLidarRuntime({ ? createLidarRuntime({
@@ -299,9 +292,6 @@ if (lidarRuntime) {
lidarRuntime.on('scan', (payload) => { lidarRuntime.on('scan', (payload) => {
broadcastLidarScan(payload); broadcastLidarScan(payload);
}); });
lidarRuntime.on('line', (payload) => {
broadcastLidarLine(payload);
});
lidarRuntime.on('status', () => { lidarRuntime.on('status', () => {
emitUpdate(); emitUpdate();
}); });
@@ -163,6 +163,7 @@ function createLidarRuntime({ logger, host, port = 6053, key, logFile = '', shou
state.stats.rotationsWithoutScan += 1; state.stats.rotationsWithoutScan += 1;
emitFrame({ status: 'error', reason: 'rotation_without_scan', scan: null }); emitFrame({ status: 'error', reason: 'rotation_without_scan', scan: null });
resetScanState(); resetScanState();
triggerPollSoon();
return; return;
} }
state.stats.scansOk += 1; state.stats.scansOk += 1;
+22 -36
View File
@@ -2,7 +2,6 @@
// Purpose: Defines the Vip Neato Card module and the local helpers/components used in this file. // Purpose: Defines the Vip Neato Card module and the local helpers/components used in this file.
// Scope: Keeps behavior unchanged while isolating this concern into a clear, single-responsibility unit. // Scope: Keeps behavior unchanged while isolating this concern into a clear, single-responsibility unit.
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useSocket } from '../../context/SocketContext.jsx';
function normalizeState(value) { function normalizeState(value) {
return String(value || '').trim(); return String(value || '').trim();
@@ -66,11 +65,9 @@ export default function VipNeatoCard({
onPowerCycle, onPowerCycle,
fullWidth = false, fullWidth = false,
}) { }) {
const socket = useSocket();
const [working, setWorking] = useState(''); const [working, setWorking] = useState('');
const [lidarFlash, setLidarFlash] = useState(false); const [lidarFlash, setLidarFlash] = useState(false);
const [showLidarDebug, setShowLidarDebug] = useState(false); const [showLidarDebug, setShowLidarDebug] = useState(false);
const [recentLidarLines, setRecentLidarLines] = useState([]);
const wrapClass = fullWidth ? 'w-full' : 'w-full max-w-xl'; const wrapClass = fullWidth ? 'w-full' : 'w-full max-w-xl';
const configured = Boolean(neato?.configured); const configured = Boolean(neato?.configured);
@@ -135,19 +132,6 @@ export default function VipNeatoCard({
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [lidar]); }, [lidar]);
useEffect(() => {
function handleLidarLine(payload = null) {
const next = payload && typeof payload === 'object' ? payload : null;
if (!next?.line) return;
setRecentLidarLines((prev) => [...prev.slice(-199), next]);
}
socket.on('neato:lidarLine', handleLidarLine);
return () => {
socket.off('neato:lidarLine', handleLidarLine);
};
}, [socket]);
return ( return (
<section className={`surface text-sm text-slate-200 ${wrapClass}`}> <section className={`surface text-sm text-slate-200 ${wrapClass}`}>
<div className="grid gap-0.5"> <div className="grid gap-0.5">
@@ -267,23 +251,37 @@ export default function VipNeatoCard({
<div className="mt-0.25 aspect-square rounded-md bg-slate-900 p-0.25"> <div className="mt-0.25 aspect-square rounded-md bg-slate-900 p-0.25">
{lidarDots ? ( {lidarDots ? (
<svg viewBox="0 0 220 220" className="h-full w-full"> <svg viewBox="0 0 220 220" className="h-full w-full">
<circle cx="110" cy="110" r="92" fill="none" stroke="#475569" strokeWidth="1" /> <rect x="0" y="0" width="220" height="220" fill="#020617" />
<circle cx="110" cy="110" r="61" fill="none" stroke="#334155" strokeWidth="1" /> <circle cx="110" cy="110" r="92" fill="none" stroke="#166534" strokeWidth="1" />
<circle cx="110" cy="110" r="31" fill="none" stroke="#1e293b" strokeWidth="1" /> <circle cx="110" cy="110" r="61" fill="none" stroke="#15803d" strokeWidth="1" />
<line x1="110" y1="18" x2="110" y2="202" stroke="#334155" strokeWidth="1" /> <circle cx="110" cy="110" r="31" fill="none" stroke="#22c55e" strokeWidth="1" />
<line x1="18" y1="110" x2="202" y2="110" stroke="#334155" strokeWidth="1" /> <line x1="110" y1="18" x2="110" y2="202" stroke="#166534" strokeWidth="1" />
<circle cx="110" cy="110" r="4" fill="#e2e8f0" /> <line x1="18" y1="110" x2="202" y2="110" stroke="#166534" strokeWidth="1" />
<circle cx="110" cy="110" r="4" fill="#4ade80" />
<polyline <polyline
points={lidarDots} points={lidarDots}
fill="none" fill="none"
stroke="#38bdf8" stroke="#4ade80"
strokeWidth="1.5" strokeWidth="1.5"
strokeLinejoin="round" strokeLinejoin="round"
strokeLinecap="round" strokeLinecap="round"
/> />
{lidarPoints
.filter(
(point) =>
point && point.valid && Number.isFinite(point.angleDeg) && Number.isFinite(point.distanceMm),
)
.map((point) => {
const angleRad = ((Number(point.angleDeg) - 90) * Math.PI) / 180;
const normalized = Math.max(0, Math.min(1, Number(point.distanceMm) / 4000));
const scaledRadius = normalized * 92;
const x = 110 + Math.cos(angleRad) * scaledRadius;
const y = 110 + Math.sin(angleRad) * scaledRadius;
return <circle key={`${point.angleDeg}-${point.distanceMm}-${point.intensity}`} cx={x} cy={y} r="1.6" fill="#86efac" />;
})}
</svg> </svg>
) : ( ) : (
<div className="flex h-full items-center justify-center text-center text-xs text-slate-400"> <div className="flex h-full items-center justify-center text-center text-xs text-emerald-300">
Waiting for scan Waiting for scan
</div> </div>
)} )}
@@ -304,18 +302,6 @@ export default function VipNeatoCard({
<div>Rotation no scan: {lidarStats?.rotationsWithoutScan ?? '--'}</div> <div>Rotation no scan: {lidarStats?.rotationsWithoutScan ?? '--'}</div>
<div>Parseable payloads: {lidarStats?.parseablePayloads ?? '--'}</div> <div>Parseable payloads: {lidarStats?.parseablePayloads ?? '--'}</div>
<div>Point payloads: {lidarStats?.pointPayloads ?? '--'}</div> <div>Point payloads: {lidarStats?.pointPayloads ?? '--'}</div>
<div className="mt-0.5 border-t border-slate-700 pt-0.5 text-slate-400">Raw ESP lines</div>
<div className="mt-0.25 max-h-40 overflow-y-auto rounded bg-black/30 px-0.5 py-0.5 text-[0.62rem] leading-tight text-slate-300">
{recentLidarLines.length ? (
recentLidarLines.map((entry, index) => (
<div key={`${index}-${entry.source || 'line'}`} className="break-all">
<span className="text-slate-500">[{entry.source || 'line'}]</span> {entry.line}
</div>
))
) : (
<div className="text-slate-500">No raw lines yet</div>
)}
</div>
</div> </div>
) : null} ) : null}
</div> </div>