Files
evse-backend/src/mqtt/handlers/meter.handler.js
2026-01-10 18:39:55 +00:00

95 lines
2.9 KiB
JavaScript
Executable File

// src/mqtt/handlers/meter.handler.js
async function handleStateMeter(ctx, mqttTopic, payload, meterKind /* 'evse'|'grid' */) {
const charger = await ctx.getChargerByMqttTopic(mqttTopic);
if (!charger) {
console.warn(`[MQTT] Charger não encontrado para topic: ${mqttTopic}`);
return;
}
const chargerId = charger.id;
const now = new Date();
const vrms = ctx.toArr3(payload?.vrms); // 2 casas
const irms = ctx.toArr3(payload?.irms); // 2 casas
// watt em W -> kW com 2 casas
const wattKw = ctx.toArr3Kw2(payload?.watt);
const totalEnergy = ctx.round2(payload?.totalEnergy); // kWh acumulado (2 casas)
const source = String(payload?.source || meterKind || '').toUpperCase();
if (Number.isFinite(totalEnergy) && totalEnergy >= 0) {
ctx.lastTotalEnergyByChargerId.set(chargerId, totalEnergy);
}
if (meterKind === 'evse' || source === 'EVSE') {
const dbUpdate = {
consumption: totalEnergy,
charging_current: ctx.round2(irms[0]),
power_l1: wattKw[0],
power_l2: wattKw[1],
power_l3: wattKw[2],
voltage_l1: vrms[0],
voltage_l2: vrms[1],
voltage_l3: vrms[2],
current_l1: irms[0],
current_l2: irms[1],
current_l3: irms[2],
updated_at: now.toISOString(),
};
await ctx.updateChargerDbIfChanged(chargerId, dbUpdate);
// atualiza sessão ativa com delta (sem fechar)
const currentlyEnabled = ctx.lastEnabled[chargerId] || false;
if (currentlyEnabled) {
const session = await ctx.db('charger_sessions')
.where({ charger_id: chargerId })
.whereNull('ended_at')
.first();
if (session) {
const startEnergy = ctx.sessionStartEnergyByChargerId.get(chargerId) ?? 0;
const delta = Math.max(
0,
ctx.round2((ctx.lastTotalEnergyByChargerId.get(chargerId) ?? 0) - startEnergy)
);
await ctx.db('charger_sessions').where({ id: session.id }).update({ kwh: delta });
}
}
const meta = ctx.lastMetaByChargerId.get(chargerId) || { status: '—', stateCode: undefined };
ctx.emitter.emit('charging-status', {
charger_id: chargerId,
mqtt_topic: mqttTopic,
status: meta.status,
stateCode: meta.stateCode,
consumption: totalEnergy,
chargingTime: 0,
power: wattKw,
voltage: vrms,
current: irms,
raw: payload,
});
}
ctx.emitter.emit('meter-live', {
charger_id: chargerId,
mqtt_topic: mqttTopic,
meter: meterKind,
vrms,
irms,
watt: wattKw,
totalEnergy,
raw: payload,
updated_at: now.toISOString(),
});
}
module.exports = { handleStateMeter };