mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 17:40:46 -04:00
awaa
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
// Idle Service Actions
|
||||
// Purpose: Implements the expandable action pipeline executed when the system remains idle.
|
||||
// Scope: Provides isolated action handlers and shared execution helpers for idle automation.
|
||||
const logger = require('../../globals/logger').child('idleService');
|
||||
const roverManager = require('../roverManager');
|
||||
const { issueCommand } = require('../commandService');
|
||||
const homeAssistantService = require('../homeAssistantService');
|
||||
const neatoService = require('../neatoService');
|
||||
const {
|
||||
NIGHT_VISION_DISABLE_ACTION,
|
||||
DOCK_COMMAND_BASE64,
|
||||
} = require('./constants');
|
||||
|
||||
async function turnOffRoomControls() {
|
||||
await homeAssistantService.setAllControllableEntitiesState('off');
|
||||
return { action: 'roomControlsOff' };
|
||||
}
|
||||
|
||||
async function dockAllRovers() {
|
||||
const attempted = [];
|
||||
const failed = [];
|
||||
roverManager.rovers.forEach((record) => {
|
||||
if (!record?.ws) return;
|
||||
const roverId = String(record.id);
|
||||
try {
|
||||
issueCommand(roverId, { type: 'raw', raw: DOCK_COMMAND_BASE64 });
|
||||
attempted.push(roverId);
|
||||
} catch (err) {
|
||||
failed.push({ roverId, error: err.message });
|
||||
}
|
||||
});
|
||||
return { action: 'dockAllRovers', attempted, failed };
|
||||
}
|
||||
|
||||
async function disableAllRoverNightVision() {
|
||||
const attempted = [];
|
||||
const failed = [];
|
||||
roverManager.rovers.forEach((record) => {
|
||||
if (!record?.ws) return;
|
||||
const roverId = String(record.id);
|
||||
try {
|
||||
issueCommand(roverId, {
|
||||
type: 'nightVision',
|
||||
nightVision: { action: NIGHT_VISION_DISABLE_ACTION },
|
||||
});
|
||||
attempted.push(roverId);
|
||||
} catch (err) {
|
||||
failed.push({ roverId, error: err.message });
|
||||
}
|
||||
});
|
||||
return { action: 'disableRoverNightVision', attempted, failed };
|
||||
}
|
||||
|
||||
async function sendNeatoHome() {
|
||||
try {
|
||||
await neatoService.sendHome();
|
||||
return { action: 'neatoSendHome', success: true };
|
||||
} catch (err) {
|
||||
return { action: 'neatoSendHome', success: false, error: err.message };
|
||||
}
|
||||
}
|
||||
|
||||
const idleActions = [
|
||||
turnOffRoomControls,
|
||||
dockAllRovers,
|
||||
disableAllRoverNightVision,
|
||||
sendNeatoHome,
|
||||
];
|
||||
|
||||
async function runIdleActions() {
|
||||
const results = [];
|
||||
for (const action of idleActions) {
|
||||
try {
|
||||
const result = await action();
|
||||
results.push({ ok: true, result });
|
||||
} catch (err) {
|
||||
logger.warn('Idle action failed', { action: action.name, error: err.message });
|
||||
results.push({ ok: false, action: action.name, error: err.message });
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
runIdleActions,
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
// Idle Service Constants
|
||||
// Purpose: Defines idle timing and command constants used by idle automation workflows.
|
||||
// Scope: Centralizes immutable configuration for trigger windows and rover command payloads.
|
||||
const IDLE_TIMEOUT_MS = 2 * 60 * 1000;
|
||||
const NIGHT_VISION_DISABLE_ACTION = 'on';
|
||||
const DOCK_COMMAND_BASE64 = Buffer.from([143]).toString('base64');
|
||||
|
||||
module.exports = {
|
||||
IDLE_TIMEOUT_MS,
|
||||
NIGHT_VISION_DISABLE_ACTION,
|
||||
DOCK_COMMAND_BASE64,
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
// Idle Service
|
||||
// Purpose: Triggers a modular idle action pipeline after a sustained no-driver period.
|
||||
// Scope: Observes driver activity events and coordinates timer-based idle automation execution.
|
||||
const logger = require('../../globals/logger').child('idleService');
|
||||
const { getActiveDrivers, turnEvents } = require('../turnService');
|
||||
const roverManager = require('../roverManager');
|
||||
const { IDLE_TIMEOUT_MS } = require('./constants');
|
||||
const { runtime } = require('./state');
|
||||
const { runIdleActions } = require('./actions');
|
||||
|
||||
function getActiveDriverCount() {
|
||||
const active = getActiveDrivers();
|
||||
const turnCount = active && typeof active === 'object' ? Object.keys(active).length : 0;
|
||||
if (turnCount > 0) return turnCount;
|
||||
let liveCount = 0;
|
||||
roverManager.rovers.forEach((record) => {
|
||||
if (record?.drivers?.size > 0) liveCount += 1;
|
||||
});
|
||||
return liveCount;
|
||||
}
|
||||
|
||||
function clearIdleTimer() {
|
||||
if (runtime.timer) {
|
||||
clearTimeout(runtime.timer);
|
||||
runtime.timer = null;
|
||||
}
|
||||
runtime.deadlineAt = null;
|
||||
}
|
||||
|
||||
function scheduleIdleTimer() {
|
||||
if (runtime.timer) return;
|
||||
runtime.deadlineAt = Date.now() + IDLE_TIMEOUT_MS;
|
||||
runtime.timer = setTimeout(async () => {
|
||||
runtime.timer = null;
|
||||
runtime.deadlineAt = null;
|
||||
if (getActiveDriverCount() > 0) {
|
||||
return;
|
||||
}
|
||||
runtime.lastTriggeredAt = Date.now();
|
||||
const results = await runIdleActions();
|
||||
logger.info('Idle automation executed', {
|
||||
idleMs: IDLE_TIMEOUT_MS,
|
||||
resultCount: results.length,
|
||||
failures: results.filter((entry) => !entry.ok).length,
|
||||
});
|
||||
refreshIdleState();
|
||||
}, IDLE_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
function refreshIdleState() {
|
||||
if (getActiveDriverCount() > 0) {
|
||||
clearIdleTimer();
|
||||
return;
|
||||
}
|
||||
scheduleIdleTimer();
|
||||
}
|
||||
|
||||
turnEvents.on('activeDriver', refreshIdleState);
|
||||
turnEvents.on('queue', refreshIdleState);
|
||||
|
||||
refreshIdleState();
|
||||
|
||||
module.exports = {
|
||||
refreshIdleState,
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
// Idle Service State
|
||||
// Purpose: Stores runtime timer and bookkeeping state for idle automation scheduling.
|
||||
// Scope: Encapsulates mutable idle-tracking data shared by idle service modules.
|
||||
const runtime = {
|
||||
timer: null,
|
||||
deadlineAt: null,
|
||||
lastTriggeredAt: null,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
runtime,
|
||||
};
|
||||
Reference in New Issue
Block a user