This repository has been archived on 2026-10-08. You can view files and clone it, but cannot push or open issues or pull requests.

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;
}