Shelly Power Consumption trouble with Number:Energy

Hello!
i have these items:

Number:Energy               Shelly_EM3_accTotal     "Shelly em3 Gesamtverbrauch"                (gShelly)   {channel="shelly:shellyem3:84cca8ad12a6:device#accumulatedWTotal"}

Number:Energy               Shelly_EM3_consumption    "Shelly em3 Verbrauch"                    (gShelly)
Number:Energy               Shelly_EM3_today                                                    (gShelly)

but only Shelly_EM3_accTotal is displays with kWh. and openhab doesn’t calculate consumption as i had hoped:

2021-11-30 20:52:02.358 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly_EM3_accTotal' changed from 2272.385 kWh to 2272.386 kWh
2021-11-30 20:52:02.370 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly_EM3_consumption' changed from 0 to 3600.0

everytime Shelly_EM3_accTotal increases 0.001 kWh Shelly_EM3_consumption in 3600 steps (and the values have not the kWh unit)…

this is my rule:

rule "Power Consumption em3"
when
    Item Shelly_EM3_accTotal changed
then
    Shelly_EM3_consumption.postUpdate((Shelly_EM3_accTotal.state as Number) - (previousState as Number))
end

i think the problem is the Numer:Energy in the item definition and that’s where something goes wrong in the rule? should i change the items to “Number only”?

Number:Energy is a Quantity type, and demands you that you use a unit. Otherwise “10” means ten what - kWh, Ws, ergs, apples? The unit is part of thestate, the number is meaningless without the unit.

That’s okay, the Shelley binding provides you with updates with units. You can see that in your log

But in your rule, you throw the units away

and do maths with the meaningless numbers.
(In truth, getting quantity state as Number gives you some weird hybrid value, but you can’t do maths with it)

Try working with the Quantities -
(Shelly_EM3_accTotal.state as QuantityType<Energy>) - (previousState as QuantityType<Energy>)
and the result will itself be a quantity suitable for updating your Item.

1 Like

great, thank you!
this works fine now, but i’m still struggling with my persistence sum:
rule “Power Consumption em3 today”

when    
    Item Shelly_EM3_consumption received update
then
    var today = Shelly_EM3_consumption.sumSince(now().with(LocalTime.MIDNIGHT))  as QuantityType<Energy>
    Shelly_EM3_today.postUpdate(today)
end

gives me

Cannot cast from DecimalType to QuantityType<Energy>(org.eclipse.xtext.xbase.validation.IssueCodes.invalid_cast)

i tried it also without quantityType but that doesn’t work either…

Find out what you get. (log it out)
Persistence of quantities gets complicated; persistence service stores only the numeric part and uses the Item default unit to reconstruct a quantity on retrieval.
I’ve no idea what yours will do here - your Shelly_EM3_consumption Item has no default unit defined, so maybe it all breaks down.

Default unit gets defined by hijacking state presentation parameters.

Number:Energy Shelly_EM3_consumption "Shelly em3 Verbrauch [%.2f kWh]"  ...

Which persistence service are you using? rrd4j may not give the results you expect, due to compression algorithms.

alright, i defined the unit for Shelly_EM3_consumpion and for Shelly_EM3_today (and added another item):

Number:Energy               Shelly_EM3_consumption    "Shelly em3 Verbrauch [%.2f kWh]"                    (gShellyConsumption)
Number:Energy               Shelly_EM3_today          "Shelly em3 Verbrauch Heute [%.2f kWh]"              (gShellyConsumption)
Number:Energy               Shelly_EM3_todayDelta          "Shelly em3 Verbrauch Heute als Delta [%.2f kWh]"              (gShellyConsumption)

and it works with this rules:

rule "Power Consumption em3"
when
    Item Shelly_EM3_accTotal changed
then
    Shelly_EM3_consumption.postUpdate((Shelly_EM3_accTotal.state as QuantityType<Energy>) - (previousState as QuantityType<Energy>))
end

rule "Power Consumption em3 today"
when    
    Item Shelly_EM3_consumption received update
then
    var today = Shelly_EM3_consumption.sumSince(now().with(LocalTime.MIDNIGHT))
    Shelly_EM3_today.postUpdate(today)
    var todaydelta = Shelly_EM3_accTotal.deltaSince(now().with(LocalTime.MIDNIGHT))
    Shelly_EM3_todayDelta.postUpdate(todaydelta)
end

visual code gives me this error on the 3 postUpdates:

Ambiguous feature call.
The extension methods
	postUpdate(Item, State) in BusEvent and
	postUpdate(Item, Number) in BusEvent
both match.(org.eclipse.xtext.xbase.validation.IssueCodes.ambiguous_feature_call)

i tried to add “as Number” on the first postUpdate but then i’m back with wrong calculations (0,01 kWh becomes 3600) so i guess i should stick with the error?

Yes, the rules validator is trying to check that you are passing sensible variable types around. But until the rule runs, it cannot guess what type some things are going to be.
You can cheat here and pass a string, and let postUpdate() parse the string as whatever type it is looking for
Shelly_EM3_today.postUpdate(today.toString)

perfect! thank you very much!

hi ,i installed a shelly3em yesterday,and i used the above rule example to calculate a daily energy consumption .I have the 3 phases kwh items in a SUM group named gEnergy and this is showing me the total energy consumption of my home.I just need a rule to calculate me the daily Kwh used so…

Number:Energy  Energy_today          "Energy_today [%.2f kWh]"  ( Group_HabPanel_Dashboard )
rule "Power Consumption em3 today"
when    
    Item gEnergy changed
then
    var today = gEnergy.sumSince(now().with(LocalTime.MIDNIGHT))
    Energy_today.postUpdate(today)
end

is this the right way to calculate?
also how can i calculate the monthly consumption?

no idea about the calculation (as you see other people are the experts here) but there are general channels for shelly 3em that already give you the total (sum) values:

accumulatedWatts	Number	yes	Accumulated power in W of the device (including all meters)
accumulatedTotal	Number	yes	Accumulated total power in kwh of the device (including all meters)
accumulatedReturned	Number	yes	Accumulated returned power in kwh of the device (including all meters)

The accumulated channels are only available for devices with more than 1 meter. accumulatedReturned only for the EM and 3EM.

thnx mate i didnt know that,i had to set “advanced” at channels page! to see them.I really strangle now with the calculations…as i have no coding skills whatsoever :slight_smile: .But iam learning something new every day…thnx
@rossko57
edit :so i found a little time to check narf27 's example and i thought that i get it but cant make it work for real.
I take my acumulatedenergytotal item and at every change i find the difference between the now and the previous value and postupdate with that my Shelly_EM3_consumption item.

rule "Power Consumption em3"
when
    Item GreenHousePowerMeter_AccumulatedTotal changed
then
    Shelly_EM3_consumption.postUpdate((GreenHousePowerMeter_AccumulatedTotal.state as QuantityType<Energy>) - (previousState as QuantityType<Energy>))
end

so now we take the Shelly_EM3_consumption value and sum it every time its updated and postupdate the result to a new item Energy_today .

rule "Power Consumption em3 today"
when    
    Item Shelly_EM3_consumption received update
then
    var today = Shelly_EM3_consumption.sumSince(now().with(LocalTime.MIDNIGHT))
    Energy_today.postUpdate(today)
end

the value i get for the Energy_today item is

2021-12-03 20:27:02.963 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'GreenHousePowerMeter_AccumulatedTotal' changed from 26.976 kWh to 26.991 kWh
2021-12-03 20:27:02.976 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Energy_today' changed from 0.016 kWh to 0.015 kWh

it keeps giving me the previous difference ,what iam i doing wrong?I use MAP as default service and i also persist these values with rrd4j.

1 Like

I’m not quite sure what you’re trying to do with these rules.
You’re keeping your interim value Shelly_EM3_consumption a secret, that might shed some light on what is going on.

MAP persistence has a depth of exactly one; whether your data was recorded a year or a millisecond ago, only one value is ever stored.
itemxxx.sumSince( any time you like)
operates on the default service. In your case, MAP. Summing up all the entries since whenever, when there is only one record, gives you either none or that lonely one record, depending of the time falls before or after the sole record.

Isn’t the daily-so-far consumption - (psuedocode)
GreenHousePowerMeter_AccumulatedTotal - GreenHousePowerMeter_AccumulatedTotal(at last midnight)
which you’re going to need to get from rrd4j

thnx,i got it working this way

Number:Energy GreenHousePowerMeter_AccumulatedTotal  "shelly_total"  ( Group_HabPanel_Dashboard,gEnergy )
Number:Energy  Energy_today          "Energy_today"  ( Group_HabPanel_Dashboard,gEnergy )
Number:Energy  Energy_counter   "Energy_counter"  ( Group_HabPanel_Dashboard,gEnergy )
Number:Energy  Energy_unit      "Energy_unit"  ( Group_HabPanel_Dashboard,gEnergy )

gEnergy members are persisted with rrd4j.

rule "energy counter unit"
when
    Item GreenHousePowerMeter_AccumulatedTotal changed
then 
    Energy_unit.postUpdate((GreenHousePowerMeter_AccumulatedTotal.state as QuantityType<Energy>) - (previousState as QuantityType<Energy>))
end
rule "energy counter"
when
    Item Energy_unit changed
then
    var counter = (Energy_unit.state as QuantityType<Energy>) + (Energy_counter.state as QuantityType<Energy>)
	Energy_counter.postUpdate(counter)
end
rule "Daily Power Consumption total"
when
    Time is midnight
then
    var today_total = Energy_counter.state
    Energy_today.postUpdate(today_total)
	Thread::sleep(2000)
	Energy_counter.postUpdate("0kWh")
end

Its working so far ,i dont know if there is an easier way…

1 Like

That’s the important thing

1 Like