I search for a Solution for Power Consumption Fallback

Hi,

i search for a Solution to restore the Power Consumption if my Shelly get a powerloss and the Total Power Consumption falls back to 0

So far I've made it this far:

I have a MQTT IN with the actually results of the Shelly (optional for testing a Inject Node)
One goes into a Function Query for Influx DB to Read the latest Power Consumption stored in the Influx DB
Other goes after Rename the Payload into a Join Node
Both goes to this function Node:

var totalstarttime = msg.payload.TotalStartTime;
var totalkwh = msg.payload.Total;
var yesterdaykwh = msg.payload.Yesterday;
var todaykwh = msg.payload.Today;
var period = msg.payload.Period;
var watt = msg.payload.Power;
var voltage = msg.payload.Voltage;
var ampere = msg.payload.Current;
var factor = msg.payload.Factor;
var scheinleistung = msg.payload.ApparentPower;
var blindleistung = msg.payload.ReactivePower;

var totalDB = msg.payload.totalkwh;

if (ampere === 0 && watt === 0) {

    return [null, msg];

} else {

    if (totalDB > totalkwh) {

        msg.payload = {
            totalstarttime: totalstarttime,
            totalkwh: (totalDB + totalkwh).toFixed(3),
            yesterdaykwh: yesterdaykwh,
            todaykwh: todaykwh,
            period: period,
            watt: watt,
            voltage: voltage,
            ampere: ampere,
            factor: factor,
            scheinleistung: scheinleistung,
            blindleistung: blindleistung,

        }

        return msg;

    } else {


        msg.payload = {
            totalstarttime: totalstarttime,
            totalkwh: totalkwh,
            yesterdaykwh: yesterdaykwh,
            todaykwh: todaykwh,
            period: period,
            watt: watt,
            voltage: voltage,
            ampere: ampere,
            factor: factor,
            scheinleistung: scheinleistung,
            blindleistung: blindleistung,

        }

        return msg;


    }

}

The If Power and Current = 0 is for stopping Input to the Influx Database if Power and Current = 0

The other one is my problem:
if (totalDB > totalkwh)
If the actually Value from Shelly (totalkwh) smaller than the Database Value (totalDB)
Add the actually Value to the Database Value

But there is the Problem:
eg.: Database have 6.500 kwh
actuall Value is 0.100 kwh

i gettin 6.600kwh thats correct, but after that add this value is added to InfluxDB

Now i have 6.600kwh in Influx DB and a actually value from Shelly of 0.150kwh

After the Second pass i have then not 6.650kwh but the wrong 6.750kwh because it asks the InfluxDB a second Time for the latest value.

I hope I explained that a bit understandable

I am still having problems with my routine for doing this - the overall maths is wrong.

However, here is the relevant part. I check the reading coming in from the consumption monitor (PZEM-004 in my case) and compare it with it's last reading AND the overall reading for today. This is a dirty routine, but I am still working on it...

//let elecPowerToday = msg.pzem.ENERGY.Today;  //Today Power from PZEM

let elecLastPowerToday = global.get("elec.LastPowerToday", 'storeInFile') || 0;  //Context PowerToday
let elecNewPower = msg.pzem.ENERGY.Today;  //Today Power from pzem
let elecOldPower = msg.payload[0].today;  //Today Power from last db pzem

//let negPower = elecOldPower - elecNewPower
//if PZEM has been reset recalc NewPower XCPT when @midnight!!
if ((elecNewPower < elecOldPower) && resetTimeFlag === 0 ) {
    elecNewPower = elecNewPower + elecOldPower;
}


let elecNewPowerToday = elecNewPower; //in case of pzem reset

It may help just a bit...

Hi,

thanks @mudwalker i try your code.

I have found another thread here in Nodered Forum with this code:

// Given current total energy from Shelly in msg.payload
let runningTotalEnergy = global.get("runningTotalEnergy", "storeInFile") || 0
let previousShellyValue = global.get("previousShellyValue", "storeInFile") || 0
// test whether the Shelly has reset since last input
if (msg.payload < previousShellyValue) {
    // yes it has, just add new value to the total
    runningTotalEnergy += msg.payload
} else {
    // no so add the difference between this and last to the running total
    runningTotalEnergy += msg.payload - previousShellyValue
}
global.set("previousShellyValue", msg.payload, "storeInFile")
global.set("runningTotalEnergy",runningTotalEnergy, "storeInFile")
msg.payload = runningTotalEnergy
return msg;

I'll try to combine the codes to get it running.

Thank you. I will be able to spend some time on it tomorrow.

My maths works, but I get the occasional 'glitch' which gives completely 'out of whack' results. I shall report back.

I have modified the Script from @Colin down here, that works for me.

Only i have a Question: Where do this Script store the Data ? and where is the File stored ? (I have Debian on Raspberry Pi)

// Given current total energy from Shelly in msg.payload
let runningTotalEnergy = global.get("runningTotalEnergy", "storeInFile") || 0
let previousShellyValue = global.get("previousShellyValue", "storeInFile") || 0
// test whether the Shelly has reset since last input
if (msg.payload < previousShellyValue) {
    // yes it has, just add new value to the total
    runningTotalEnergy += msg.payload
} else {
    // no so add the difference between this and last to the running total
    runningTotalEnergy += msg.payload - previousShellyValue
}
global.set("previousShellyValue", msg.payload, "storeInFile")
global.set("runningTotalEnergy",runningTotalEnergy, "storeInFile")
msg.payload = runningTotalEnergy
return msg;

EDIT: @Starfoxfs - wrote this as you replied.

I have modified the routine and think (hope) it will not give me the glitches the previous one gave...

//New routine************************************************************ */
//if PZEM has been reset or -ve anomalous reading recalc newPower XCPT when @midnight!!

//Fetch current and last stored readings  New should always be >> old (Don't check during daily reading reset)
if ((elecNewPower < elecOldPower) && resetTimeFlag === 0 ) {
    //Modify new reading if == 0 or < OldPower
    if (elecNewPower == 0){
        elecNewPower = elecOldPower;
    }
    
    //be careful- don't want to skew readings, so might be best to ignore
    /*
    //mitigate anomalous reading to ripple through routine
    else{
        elecNewPower = elecOldPower + elecNewPower;
    }
    */
}
//*********************************************************************** */

You will then be able to calculate the difference between the New Power and Old Power and get the power used between two valid readings.

HTH

The variables are stored as Context Data. 'storeInFile' is probably in memory and lost during reset.

See this thread here for more details.

1 Like

I have configured it out in Settings.json

Now it´s stored in

~/.node-red/context/global/global.json

Now modified my code to the less confusing version presented by @Colin. Thank you.

I have learnt some more about Javascript and dumped my routine where I was needlessly trying to trap completely unnecessary possibilities I had probably imagined! (Confused? So was I! :lol)

It is often a tricky balance to get the right amount of defensive code to guard against incorrect data.