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