mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
neato updates
This commit is contained in:
@@ -31,6 +31,10 @@ function normalizeDeviceName(value) {
|
||||
|
||||
const device = normalizeDeviceName(neatoConfig.device);
|
||||
const RESUME_DELAY_MS = 3000;
|
||||
// BrainSlug exposes these exact select values for Gen 3 robots. Keeping the
|
||||
// allowlist on the server prevents arbitrary Home Assistant select options from
|
||||
// being submitted by a modified browser while preserving BrainSlug's casing.
|
||||
const NAVIGATION_MODES = Object.freeze(['Normal', 'Gentle', 'Deep', 'Quick']);
|
||||
|
||||
function entityId(domain, suffix) {
|
||||
if (!device) return '';
|
||||
@@ -61,6 +65,9 @@ const ENTITY_IDS = {
|
||||
robotError: entityId('sensor', 'robot_error'),
|
||||
robotAlert: entityId('sensor', 'robot_alert'),
|
||||
},
|
||||
selects: {
|
||||
navigationMode: entityId('select', 'navigation_mode'),
|
||||
},
|
||||
};
|
||||
|
||||
function readRaw(entityIdValue) {
|
||||
@@ -146,6 +153,14 @@ function buildState() {
|
||||
entityId: ENTITY_IDS.buttons.powerCycle,
|
||||
available: hasEntity(ENTITY_IDS.buttons.powerCycle),
|
||||
},
|
||||
navigationMode: {
|
||||
entityId: ENTITY_IDS.selects.navigationMode,
|
||||
available: isEntityAvailable(ENTITY_IDS.selects.navigationMode),
|
||||
value: readState(ENTITY_IDS.selects.navigationMode),
|
||||
// The browser receives the supported choices through the session contract
|
||||
// instead of duplicating BrainSlug-specific values in the presentation layer.
|
||||
options: NAVIGATION_MODES,
|
||||
},
|
||||
};
|
||||
|
||||
const batteryPercentValue = parseNumber(readState(ENTITY_IDS.sensors.batteryPercent));
|
||||
@@ -255,6 +270,29 @@ async function powerCycle() {
|
||||
await pressButton(ENTITY_IDS.buttons.powerCycle, 'powercucle');
|
||||
}
|
||||
|
||||
async function setNavigationMode(mode) {
|
||||
assertConfiguredAndConnected();
|
||||
const normalizedMode = String(mode || '').trim();
|
||||
if (!NAVIGATION_MODES.includes(normalizedMode)) {
|
||||
throw new Error('Invalid Neato navigation mode');
|
||||
}
|
||||
if (!isEntityAvailable(ENTITY_IDS.selects.navigationMode)) {
|
||||
throw new Error('Neato action unavailable: navigation_mode');
|
||||
}
|
||||
|
||||
// ESPHome implements Navigation Mode as a Home Assistant select entity, so
|
||||
// select_option is the native service call and avoids sending raw UART commands.
|
||||
await callHomeAssistantService('select', 'select_option', {
|
||||
entity_id: ENTITY_IDS.selects.navigationMode,
|
||||
option: normalizedMode,
|
||||
});
|
||||
logger.info('Issued Neato action', {
|
||||
action: 'set_navigation_mode',
|
||||
entityId: ENTITY_IDS.selects.navigationMode,
|
||||
option: normalizedMode,
|
||||
});
|
||||
}
|
||||
|
||||
function getState() {
|
||||
cachedState = buildState();
|
||||
return cachedState;
|
||||
@@ -328,6 +366,16 @@ if (featureEnabled) {
|
||||
cb({ error: err.message });
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('neato:setNavigationMode', async ({ mode } = {}, cb = () => {}) => {
|
||||
try {
|
||||
assertFeatureAccess();
|
||||
await setNavigationMode(mode);
|
||||
cb({ success: true });
|
||||
} catch (err) {
|
||||
cb({ error: err.message });
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
logger.info('Neato disabled by config');
|
||||
@@ -342,5 +390,6 @@ module.exports = {
|
||||
locateRobot,
|
||||
clearErrors,
|
||||
powerCycle,
|
||||
setNavigationMode,
|
||||
neatoEvents: events,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user