mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
battery manager progress
This commit is contained in:
@@ -20,4 +20,5 @@ require('./src/services/videoAuthService');
|
|||||||
require('./src/services/videoSocketService');
|
require('./src/services/videoSocketService');
|
||||||
require('./src/services/logStreamService');
|
require('./src/services/logStreamService');
|
||||||
require('./src/services/sessionService');
|
require('./src/services/sessionService');
|
||||||
|
require('./src/services/batteryManager');
|
||||||
require('./src/services/httpServer');
|
require('./src/services/httpServer');
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>webui</title>
|
<title>webui</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DN5ZA6hs.js"></script>
|
<script type="module" crossorigin src="/assets/index-DBNvZqXA.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-DP0zs3Oi.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DP0zs3Oi.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
const logger = require('../globals/logger').child('batteryManager');
|
||||||
|
const { publishEvent } = require('./eventBus');
|
||||||
|
const { managerEvents, lockRover, rovers } = require('./roverManager');
|
||||||
|
|
||||||
|
const STATES = {
|
||||||
|
NORMAL: 'normal',
|
||||||
|
WARN: 'warn',
|
||||||
|
URGENT: 'urgent',
|
||||||
|
DOCKED: 'docked',
|
||||||
|
CHARGING: 'charging',
|
||||||
|
FULL: 'full',
|
||||||
|
LOCKED: 'locked',
|
||||||
|
};
|
||||||
|
|
||||||
|
const roverState = new Map(); // roverId -> state snapshot
|
||||||
|
|
||||||
|
function getState(roverId) {
|
||||||
|
if (!roverState.has(roverId)) {
|
||||||
|
roverState.set(roverId, {
|
||||||
|
lastPercent: null,
|
||||||
|
warned: false,
|
||||||
|
urgent: false,
|
||||||
|
docked: false,
|
||||||
|
batteryLocked: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return roverState.get(roverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldLock(record) {
|
||||||
|
return record.lockReason == null || record.lockReason === 'battery';
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSensorEvent({ roverId, sensors, batteryState }) {
|
||||||
|
if (!roverId) return;
|
||||||
|
const record = rovers.get(roverId);
|
||||||
|
if (!record) return;
|
||||||
|
const state = getState(roverId);
|
||||||
|
const config = record.meta?.battery || {};
|
||||||
|
const lockable = shouldLock(record);
|
||||||
|
|
||||||
|
if (batteryState?.percent != null) {
|
||||||
|
state.lastPercent = batteryState.percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.warned && batteryState?.warnActive) {
|
||||||
|
state.warned = true;
|
||||||
|
publishEvent({
|
||||||
|
source: 'batteryManager',
|
||||||
|
type: 'battery.warn',
|
||||||
|
payload: { roverId, batteryState },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!state.urgent && batteryState?.urgentActive) {
|
||||||
|
state.urgent = true;
|
||||||
|
publishEvent({
|
||||||
|
source: 'batteryManager',
|
||||||
|
type: 'battery.urgent',
|
||||||
|
payload: { roverId, batteryState },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const chargingState = sensors?.chargingState?.code;
|
||||||
|
const chargingSources = sensors?.chargingSources;
|
||||||
|
const docked =
|
||||||
|
Boolean(chargingSources?.homeBase) ||
|
||||||
|
chargingState === 2 ||
|
||||||
|
chargingState === 3 ||
|
||||||
|
chargingState === 4;
|
||||||
|
if (docked && !state.docked) {
|
||||||
|
state.docked = true;
|
||||||
|
publishEvent({
|
||||||
|
source: 'batteryManager',
|
||||||
|
type: 'battery.docked',
|
||||||
|
payload: { roverId, batteryState },
|
||||||
|
});
|
||||||
|
} else if (!docked && state.docked) {
|
||||||
|
state.docked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (docked && lockable && !record.locked) {
|
||||||
|
logger.info('Auto-locking rover for charging', { roverId });
|
||||||
|
lockRover(roverId, true, { reason: 'battery' });
|
||||||
|
state.batteryLocked = true;
|
||||||
|
publishEvent({
|
||||||
|
source: 'batteryManager',
|
||||||
|
type: 'battery.locked',
|
||||||
|
payload: { roverId, batteryState },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullThreshold =
|
||||||
|
typeof config?.Full === 'number' ? config.Full : batteryState?.full ?? null;
|
||||||
|
const isFull =
|
||||||
|
(batteryState?.charge != null && fullThreshold != null && batteryState.charge >= fullThreshold) ||
|
||||||
|
(batteryState?.percent != null && batteryState.percent >= 0.99);
|
||||||
|
|
||||||
|
if (record.locked && record.lockReason === 'battery') {
|
||||||
|
if (isFull || !docked) {
|
||||||
|
logger.info('Unlocking rover after charge', { roverId, isFull, docked });
|
||||||
|
lockRover(roverId, false, { reason: 'battery' });
|
||||||
|
state.batteryLocked = false;
|
||||||
|
publishEvent({
|
||||||
|
source: 'batteryManager',
|
||||||
|
type: 'battery.unlocked',
|
||||||
|
payload: { roverId, batteryState },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
managerEvents.on('sensor', handleSensorEvent);
|
||||||
@@ -223,9 +223,14 @@ export default function KeyboardInputManager() {
|
|||||||
};
|
};
|
||||||
}, [actionTokens, driveFromKeys, ensureServoLoop, keymap.dockMacro, keymap.driveMacro, resetAll, runMacro, setMode]);
|
}, [actionTokens, driveFromKeys, ensureServoLoop, keymap.dockMacro, keymap.driveMacro, resetAll, runMacro, setMode]);
|
||||||
|
|
||||||
|
const latestResetAllRef = useRef(resetAll);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
resetAll();
|
latestResetAllRef.current = resetAll;
|
||||||
}, [state.roverId, resetAll]);
|
}, [resetAll]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
latestResetAllRef.current();
|
||||||
|
}, [state.roverId]);
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() => () => {
|
() => () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user