112 lines
3.4 KiB
JavaScript
112 lines
3.4 KiB
JavaScript
import { PowerState } from "../db/models/index.js";
|
|
|
|
function numOrNull(v) {
|
|
if (v == null || v === "") return null;
|
|
const n = Number(v);
|
|
return Number.isFinite(n) ? n : null;
|
|
}
|
|
|
|
export async function getOrCreatePowerState() {
|
|
let doc = await PowerState.findOne();
|
|
if (!doc) {
|
|
doc = await PowerState.create({});
|
|
}
|
|
return doc;
|
|
}
|
|
|
|
/**
|
|
* Client + history sample shape aligned with PowerState.schema nested fields.
|
|
* Merges legacy flat keys still present on some documents (`batteryPercent`, `chargingVoltage`).
|
|
*
|
|
* @param {import("mongoose").Document | Record<string, unknown>} power
|
|
*/
|
|
export function formatPowerStateForClient(power) {
|
|
const o = power?.toObject ? power.toObject() : { ...(power || {}) };
|
|
const bat = o.battery && typeof o.battery === "object" ? o.battery : {};
|
|
const sol = o.solar && typeof o.solar === "object" ? o.solar : {};
|
|
const load = o.load && typeof o.load === "object" ? o.load : {};
|
|
return {
|
|
battery: {
|
|
voltage: numOrNull(bat.voltage ?? o.chargingVoltage),
|
|
current: numOrNull(bat.current),
|
|
percent: numOrNull(bat.percent ?? o.batteryPercent),
|
|
},
|
|
solar: {
|
|
voltage: numOrNull(sol.voltage),
|
|
current: numOrNull(sol.current),
|
|
},
|
|
load: {
|
|
voltage: numOrNull(load.voltage),
|
|
current: numOrNull(load.current),
|
|
},
|
|
updatedAt: o.updatedAt ?? null,
|
|
};
|
|
}
|
|
|
|
/** @returns {Promise<boolean>} whether power doc was updated */
|
|
export async function applyPowerFromPayload(payload) {
|
|
if (!payload || typeof payload !== "object") return false;
|
|
|
|
const bat = payload.battery;
|
|
const hasNestedBat =
|
|
bat &&
|
|
typeof bat === "object" &&
|
|
(bat.percent != null || bat.voltage != null || bat.current != null);
|
|
const hasFlat =
|
|
payload.batteryPercent != null ||
|
|
payload.chargingVoltage != null ||
|
|
payload.chargingCurrent != null ||
|
|
payload.current != null;
|
|
const sol = payload.solar;
|
|
const hasSolar =
|
|
sol &&
|
|
typeof sol === "object" &&
|
|
(sol.voltage != null || sol.current != null);
|
|
const ld = payload.load;
|
|
const hasLoad =
|
|
ld &&
|
|
typeof ld === "object" &&
|
|
(ld.voltage != null || ld.current != null);
|
|
|
|
if (!hasNestedBat && !hasFlat && !hasSolar && !hasLoad) {
|
|
return false;
|
|
}
|
|
|
|
const pow = await getOrCreatePowerState();
|
|
|
|
if (hasFlat) {
|
|
if (!pow.battery) pow.battery = {};
|
|
if (payload.batteryPercent != null) {
|
|
pow.battery.percent = Number(payload.batteryPercent);
|
|
}
|
|
if (payload.chargingVoltage != null) {
|
|
pow.battery.voltage = Number(payload.chargingVoltage);
|
|
}
|
|
if (payload.chargingCurrent != null || payload.current != null) {
|
|
pow.battery.current = Number(payload.chargingCurrent ?? payload.current);
|
|
}
|
|
}
|
|
|
|
if (hasNestedBat) {
|
|
if (!pow.battery) pow.battery = {};
|
|
if (bat.percent != null) pow.battery.percent = Number(bat.percent);
|
|
if (bat.voltage != null) pow.battery.voltage = Number(bat.voltage);
|
|
if (bat.current != null) pow.battery.current = Number(bat.current);
|
|
}
|
|
|
|
if (hasSolar) {
|
|
if (!pow.solar) pow.solar = {};
|
|
if (sol.voltage != null) pow.solar.voltage = Number(sol.voltage);
|
|
if (sol.current != null) pow.solar.current = Number(sol.current);
|
|
}
|
|
|
|
if (hasLoad) {
|
|
if (!pow.load) pow.load = {};
|
|
if (ld.voltage != null) pow.load.voltage = Number(ld.voltage);
|
|
if (ld.current != null) pow.load.current = Number(ld.current);
|
|
}
|
|
|
|
await pow.save();
|
|
return true;
|
|
}
|