Shelly - Power Meter resets total consumption on power loss

In current version of shelly 1pm it’s not in. So you have to deal with a openhab rule around.
I’m right not able to get it work… I’ve some precition problems. When I’ve 3,46kWh a day in shelly. My openhab has around 2,8kWh… try to figure out next days where my missing point is…

Hi together, this is my first post here :slight_smile:

I don’t want to open a new thread/topic but I need your knowledge about exactly this problem.
I am using a shelly1pm and have the same problem which is mentioned here: I lose the totalKWH with every update of the firmware. My problem: How can I display the total consumption respecting also updates, power loss, etc.?

I tried it already with rrd4j but most of the time the shelly is in status “off” so the strategy “everyMinute” is an oversized strategy, I guess…

I have no idea how to design a rule to store this value corretly. Could you please help?

BR; ANNA

  • Trigger the Rule every time the total KWH changes Item TotalKWH changed
  • delta = TotalKWH.state - previousState
  • If the delta is negative you know that the counter reset so just use the current state as the delta if(delta < 0) delta = TotalKWH.state
  • Add the delta to the Item that stores your running total TotalKWHProxy.postUpdate(TotalKWHProxy.state + delta)
  • Persist TotalKWHProxy, not TotalKWH

rrd4j is, by design, a database that never grows in size. Storing the value every minute is not only not “oversized” but it’s required. As data ages, every ten values gets replaced with the average of those ten so as the data ages it becomes more sparse, therefore taking up less room.

Thank you for your answer, but how to get previousState?

Hi rlkoshak, I think this can not work. Could you please review your code?
grafik
In this grafik I set a reset of two times but I guess your calculation will not work. What do you think?

Frankly, I don’t have a shelly power meter. There is no way I can test this. Also, errors in code often have as much or more to do with context. So post your code and maybe I can review that.

There’s only three lines of code here so there is not that much that can go wrong. Looking at that table I would guess that you are missing the third line of code that adds the delta to the current total: TotalKWHProxy.postUpdate(TotalKWHProxy.state + delta). Or you are not looking at the logs and there is an error with that line of code which the logs will be complaining about.

Ultimately, cargo-cult programming is not going to take you very far. You really need to have a basic understanding of what the code you are copying and pasting does, overall how it works, and how to look for errors. You also need to learn how to debug problems when you encounter them.

First: Thank you @rlkoshak for your help. I used your code snippets to build up a rule. So far i think it works when everything is “ok” but on power loss it starts to count again by 0. Maybe I have just done a little mistake.

rule "ShellyPlugS001PowerLoss"
when
    Item ShellyPlugS001_totalKWH received update
then
    logInfo("ShellyPlugS001PowerLoss", "ShellyPlugS001_totalKWH changed")
    var Number delta = (ShellyPlugS001_totalKWH.state as Number) - (ShellyPlugS001_totalKWH.previousState().state as Number)
    logInfo("ShellyPlugS001PowerLoss", "ShellyPlugS001_totalKWH_delta: " + delta)
    if( delta < 0 ) {
        delta = (ShellyPlugS001_totalKWH.state as Number)
        logInfo("ShellyPlugS001PowerLoss", "New ShellyPlugS001_totalKWH_delta: " + delta)
        ShellyPlugS001_totalKWH_persist.postUpdate((ShellyPlugS001_totalKWH_persist.state as Number) + delta)
    } else {
        logInfo("ShellyPlugS001PowerLoss", "Old ShellyPlugS001_totalKWH_delta: " + delta)
        ShellyPlugS001_totalKWH_persist.postUpdate((ShellyPlugS001_totalKWH.state as Number) + delta)
    }
end

I think I’m just blind to see the problem. :smiley: Maybe someone else can see the problem. :slight_smile:

Best regards and stay healthy

Flo

On power loss for OH all variables go away and if you do not have persistence with restoreOnStartup all your Items initialize to NULL. Do you restore the state on startup?

Oh, I’m not talking about a power loss at my OpenHAB Rasperry, i talk about a power loss on the Shelly Things. They reset their power consumption store every time they are unplugged (or any other power loss). So i searched and found this thread.

All my items are stored persistent in a MariaDB Database, just to answer your question. :slight_smile:

With my rule I try to solve this problem with your snippets but i think i have done something wrong.

You are trying to do this with only one Item? As explained above, you should be using a proxy Item. You can’t do this without one. The proxy Item keeps the running total. You calculate the delta and add that to the proxy Item. If the delta is positive (i.e. the new reading is below the last reported reading) you know that the device reset.

What firmware are your Shelly devices on?
Alterco changed this a while ago.

@rlkoshak Oh i use a proxy item.

ShellyPlugS001_totalKWH: the real item
ShellyPlugS001_totalKWH_persist: the proxy item

@hmerk
i use the latest firmware version 1.6, but when i pull for example the ShellyPlugS it resets. Is there a setting or somethin i missed?

No setting afaik. @markus7017 have you any information from Alterco regarding this?

We requested this feature a long time ago. AFAIK they implemented a user resettable total for EM and EM3 with firmware 1.6.something. I could check the status with them, but you should post your requests here: Shelly Binding

Hello there
:slight_smile:

OH 2.5.7
shelly binding 2.5.8
LInux system
persistence service is RRD4J

i implemented the above mentioned rule:

rule "ShellyEM rotex LWP PowerLoss"
when
    Item RotexHPSULwpTotalKWH changed
then

//    logInfo("ShellyEM rotex LWP PowerLoss", "RotexHPSULwpTotalKWH changed")
//  neu  0 kWh   :  alt 55.432 kWH

if (RotexHPSULwpTotalKWH_persist.state == NULL)  // persistent neu
{
    var Number newTotal = (RotexHPSULwpTotalKWH.state as DecimalType)
    // store the current value in "persist"
    RotexHPSULwpTotalKWH_persist.postUpdate( newTotal )
    logInfo("ShellyEM rotex LWP PowerLoss", "persistent missing totalKWH  " + (newTotal.toString) )
}
else
{
   // calc the delta and add it in "persist"

if ( RotexHPSULwpTotalKWH.previousState() != NULL)   // is there persistence to compare old and new?
{

logInfo("ShellyEM rotex LWP PowerLoss", "get delta prev LwpTotalKWH" )
logInfo("ShellyEM rotex LWP PowerLoss", "current "
   + String.format("%.4f",  (RotexHPSULwpTotalKWH.state as                 DecimalType).floatValue ) + " prev: "
   + String.format("%.4f",  (RotexHPSULwpTotalKWH.previousState().state as DecimalType).floatValue ) )
var float delta = (RotexHPSULwpTotalKWH.state as DecimalType).floatValue - (RotexHPSULwpTotalKWH.previousState().state as DecimalType).floatValue
logInfo("ShellyEM rotex LWP PowerLoss", "delta: " +    String.format("%.4f",  delta ) )
if ( delta < 0.0 ) {
    logInfo("ShellyEM rotex LWP PowerLoss", "power lost ! New RotexHPSULwpTotalKWH_persist is base : " + (RotexHPSULwpTotalKWH_persist.state as N
    delta = (RotexHPSULwpTotalKWH.state as DecimalType).floatValue
} else {
    logInfo("ShellyEM rotex LWP PowerLoss", "normal RotexHPSULwp-totalKWH  " + (RotexHPSULwpTotalKWH.state as DecimalType).toString + " persist o
}

RotexHPSULwpTotalKWH_persist.postUpdate( (RotexHPSULwpTotalKWH_persist.state as DecimalType).floatValue + delta)
    logInfo("ShellyEM rotex LWP PowerLoss", "persist new: " + (RotexHPSULwpTotalKWH_persist.state as Number).toString)

}  // RotexHPSULwpTotalKWH previous  NULL
else
{
    logInfo("ShellyEM rotex LWP PowerLoss ",  "RotexHPSULwpTotalKWH.previousState is NULL - no delta by now")
}
}

end

in general it is working:

  • if persistence of RotexHPSULwpTotalKWH_persist deleted and OH restarted then RotexHPSULwpTotalKWH_persist will be set to current value
  • if RotexHPSULwpTotalKWH reset in SHELLY device to zero then this will be noted

however, calculation of “delta” of current state to previousState().state is sometimes wrong by one unit “Wh”

delta is “0.000” instead of “0.001” or “0.004” instead of “0.003” e.g.

2020-08-27 14:27:01.276 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH changed from 0.013 to 0.014
2020-08-27 14:27:01.286 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH_persist changed from NULL to 0.014

2020-08-27 14:27:01.283 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - persistent fehlte totalKWH  0.014
2020-08-27 14:30:01.058 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH changed from 0.014 to 0.015
2020-08-27 14:30:01.063 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - get delta prev LwpTotalKWH
2020-08-27 14:30:01.066 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - delta: 0.001
2020-08-27 14:30:01.071 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH_persist changed from 0.014 to 0.015
2020-08-27 14:30:01.072 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - normal RotexHPSULwp-totalKWH  0.015 persist: 0.015
 
--> SAME 


2020-08-27 14:31:00.412 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - get delta prev LwpTotalKWH
2020-08-27 14:31:00.413 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH changed from 0.015 to 0.018
2020-08-27 14:31:00.416 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - delta: 0.003999999
2020-08-27 14:31:00.421 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - normal RotexHPSULwp-totalKWH  0.018 persist: 0.015
2020-08-27 14:31:00.423 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH_persist changed from 0.015 to 0.018999998

--> STRANGE 0.004 instead of 0.003

2020-08-27 14:31:59.428 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH changed from 0.018 to 0.020
2020-08-27 14:31:59.439 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH_persist changed from 0.018999998 to 0.020999998
2020-08-27 14:31:59.432 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - get delta prev LwpTotalKWH
2020-08-27 14:31:59.435 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - delta: 0.0020000003
2020-08-27 14:31:59.439 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - normal RotexHPSULwp-totalKWH  0.020 persist: 0.020999998

--> DELTA .001 ?!?


2020-08-27 15:34:00.621 [vent.ItemStateChangedEvent] - RotexHPSULwpTotalKWH changed from 0.097 to 0.098
2020-08-27 15:34:00.792 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - delta: 0.0
--> STRANGE 0.000 delta shall be 0.001

2020-08-27 15:34:00.794 [INFO ] [.script.ShellyEM rotex LWP PowerLoss] - normal RotexHPSULwp-totalKWH  0.098 persist: 0.100999996

noting that the first time and many time in between it is working - i.e. proxy persistence item value and orignal value are same (if started from zero)

but why not working ? effect directly visible after 30mins
concurrency?
using wrong previousState( false/true)???

using RRD by now - wanting to use MySQL

thanks in advance,

BR/
Peter

chart-persist

There are a few things that I can think of:

  • When there is a power loss, you essentially throw away the delta since the power loss. I think you want to add the absolute value of delta to RotexHPSULwpTotalKWH when the delta is negative.

  • You are working with small numbers. Computers are generally pretty bad and dealing with small floating point numbers. There are simple some numbers that are impossible to represent given the way programming languages typically represent floating point numbers. I wouldn’t be surprised if 0.021 is one of them, which is why you see 0.020999998 This will introduce errors which build up over time. I think BigDecimal is able to avoid some of this so instead of forcing stuff to be a primitive float, keep them as BigDecimal. Every place you have .floatValue cast the value to Number instead. This will keep it as BigDecimal and potentially avoid this growing loss of precision. In scientific computing, the values will actually be converted to integers instead of relying on unreliable floating point values. Some languages also support fixed precision numbers which are reliable and could be used. I don’t think any of these options are available for you in this case though.

  • You are using rrd4j which decimates the data as it ages. For example, it will take ten values and replace them with one value that is the average of the ten. I don’t think this is the case for this example as I think it doesn’t start doing that until the data gets over a day old (@opus can confirm). This too will introduce errors as the data ages.

I don’t know if any of these are relevant to what you are seeing or not but they are worth exploring.

The default setup will start to give averages as soon as you are asking for period longer then 8 houres starting backwards from now.

1 Like

Hello Rich,

i do like always your great and comprehensive answers and explanations… :slight_smile:

if the power meter resets to ZERO and old value would be e.g. 6 than the Delta would be -6
if i directly adding the absolute value of delta it would double the current value (==12)

if new power meter set to 4 (before 6) than delta is -2: if delta < 0.0 then i’m using the new value of RotexHPSULwpTotalKWH as delta ( perhaps still 0.0, perhaps start increasing already)

→ so the algorithm is working in general

Can you pls send me the whole working rule because I think there are some parts missing?

BR
Daniel

1 Like