mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-18 02:20:47 -04:00
rmanager
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
// rover Manager math utils
|
||||
// Purpose: Centralizes numeric clamping and battery display calculations used by rover-manager orchestration.
|
||||
// Scope: Keeps runtime behavior unchanged by extracting pure utility functions from the main service module.
|
||||
const { DEFAULT_PRIVATE_SAFETY } = require('./constants');
|
||||
|
||||
function clampInt(value, min, max, fallback) {
|
||||
const num = Number.parseInt(value, 10);
|
||||
if (!Number.isFinite(num)) return fallback;
|
||||
return Math.max(min, Math.min(max, num));
|
||||
}
|
||||
|
||||
function normalizePrivateSafety(raw = {}) {
|
||||
const source = raw && typeof raw === 'object' ? raw : {};
|
||||
return {
|
||||
speedLimitEnabled: Boolean(source.speedLimitEnabled),
|
||||
speedLimitMaxWheelSpeed: clampInt(
|
||||
source.speedLimitMaxWheelSpeed,
|
||||
1,
|
||||
500,
|
||||
DEFAULT_PRIVATE_SAFETY.speedLimitMaxWheelSpeed,
|
||||
),
|
||||
hardOvercurrentEnabled: Boolean(source.hardOvercurrentEnabled),
|
||||
overcurrentStopMs: clampInt(
|
||||
source.overcurrentStopMs,
|
||||
100,
|
||||
5000,
|
||||
DEFAULT_PRIVATE_SAFETY.overcurrentStopMs,
|
||||
),
|
||||
hardBumpEnabled: Boolean(source.hardBumpEnabled),
|
||||
bumpBackoffSpeed: clampInt(
|
||||
source.bumpBackoffSpeed,
|
||||
1,
|
||||
500,
|
||||
DEFAULT_PRIVATE_SAFETY.bumpBackoffSpeed,
|
||||
),
|
||||
bumpBackoffMs: clampInt(
|
||||
source.bumpBackoffMs,
|
||||
100,
|
||||
5000,
|
||||
DEFAULT_PRIVATE_SAFETY.bumpBackoffMs,
|
||||
),
|
||||
cliffEnabled: Boolean(source.cliffEnabled),
|
||||
cliffBackoffSpeed: clampInt(
|
||||
source.cliffBackoffSpeed,
|
||||
1,
|
||||
500,
|
||||
DEFAULT_PRIVATE_SAFETY.cliffBackoffSpeed,
|
||||
),
|
||||
cliffBackoffMs: clampInt(
|
||||
source.cliffBackoffMs,
|
||||
100,
|
||||
5000,
|
||||
DEFAULT_PRIVATE_SAFETY.cliffBackoffMs,
|
||||
),
|
||||
triggerCooldownMs: clampInt(
|
||||
source.triggerCooldownMs,
|
||||
100,
|
||||
10000,
|
||||
DEFAULT_PRIVATE_SAFETY.triggerCooldownMs,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function computeBatteryDisplayPercent({ charge, full, warn, urgent, percent, capacity }) {
|
||||
if (
|
||||
charge != null &&
|
||||
full != null &&
|
||||
warn != null &&
|
||||
urgent != null &&
|
||||
full > warn &&
|
||||
warn > urgent
|
||||
) {
|
||||
if (charge <= urgent) return 0;
|
||||
if (charge <= warn) {
|
||||
const t = (charge - urgent) / (warn - urgent);
|
||||
return Math.round(Math.max(0, Math.min(1, t)) * 10);
|
||||
}
|
||||
if (charge >= full) return 100;
|
||||
const t = (charge - warn) / (full - warn);
|
||||
return Math.round((0.1 + Math.max(0, Math.min(1, t)) * 0.9) * 100);
|
||||
}
|
||||
if (percent != null && Number.isFinite(percent)) {
|
||||
return Math.round(Math.max(0, Math.min(1, percent)) * 100);
|
||||
}
|
||||
if (charge != null && capacity != null && capacity > 0) {
|
||||
const fallback = charge / capacity;
|
||||
return Math.round(Math.max(0, Math.min(1, fallback)) * 100);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function computeBatteryState(record, sensors) {
|
||||
if (!record) return null;
|
||||
if (!sensors) return record.batteryState;
|
||||
const config = record.meta?.battery || null;
|
||||
const charge = sensors?.batteryChargeMah ?? null;
|
||||
const capacity = sensors?.batteryCapacityMah ?? null;
|
||||
const full = typeof config?.Full === 'number' ? config.Full : null;
|
||||
const warn = typeof config?.Warn === 'number' ? config.Warn : null;
|
||||
const urgent = typeof config?.Urgent === 'number' ? config.Urgent : null;
|
||||
let percent = null;
|
||||
if (charge != null && warn != null && full != null && full > warn) {
|
||||
const span = full - warn;
|
||||
percent = (charge - warn) / span;
|
||||
} else if (charge != null && capacity != null && capacity > 0) {
|
||||
percent = charge / capacity;
|
||||
}
|
||||
if (percent != null) {
|
||||
percent = Math.max(0, Math.min(1, percent));
|
||||
}
|
||||
const percentDisplay = computeBatteryDisplayPercent({
|
||||
charge,
|
||||
full,
|
||||
warn,
|
||||
urgent,
|
||||
percent,
|
||||
capacity,
|
||||
});
|
||||
return {
|
||||
charge,
|
||||
capacity,
|
||||
full,
|
||||
warn,
|
||||
urgent,
|
||||
percent,
|
||||
percentDisplay,
|
||||
warnActive: Boolean(warn != null && charge != null && charge <= warn),
|
||||
urgentActive: Boolean(urgent != null && charge != null && charge <= urgent),
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
clampInt,
|
||||
normalizePrivateSafety,
|
||||
computeBatteryDisplayPercent,
|
||||
computeBatteryState,
|
||||
};
|
||||
Reference in New Issue
Block a user