Hello!
I wanted to make some more use of my Shelly EM devices and tried to calculate last months energy consume. I wanted to accomplish this by detracting the last days, but the value i get from historichState() and what was written in eventlog is (slightly) different.
Yes. Older data is ‘aggregated’, or compressed. By default, that generally means it is averaged over ever larger periods as you go back in time. Keyword “archives” for rrd4j.
ok thanks!
if i understood rrd4j correctly the values get more and more aggregater/compressed, right?
would it make sense to use a proxy item ( Shelly_EM3_accTotal_beforeMidnight ) and persist that one with a different service?
That’s up to your choice.
It is also possible to configure rrd4j to aggregate in a different way i.e. record the max, not the average, for a given time slot in the archives.
Unless you are billing someone else, does that level of accuracy actually matter?
Fiddling with rrd4j settings is deeply technical, and starting another persistence service is rather overkill just for this.
There are alternate means. Calculate an end-of-day reading at 23:59 or whatever, and put that in an Item, that represents “Yesterdays reading”. That Item retains that value all day until the next midnight. Persist that Item in the usual rrd4j way. It’ll persist the same value all day, that’s fine, it’s free, and the whole point of rrd4j is that the database does not grow over time.
When you want the historic reading for a given day, ask for the next day at noon, which will give “yesterdays” end-of-day reading. This will never get affected by averaging unless you have a century or so of records.
but i’m not able to update this item with this rule:
var accTotal1 = (Shelly_EM3_accTotal.historicState(firstDayPrevMonth).state as QuantityType<Energy>).doubleValue
var accTotal2 = (Shelly_EM3_accTotal.historicState(lastDayPrevMonth).state as QuantityType<Energy>).doubleValue
Shelly_EM3_consumeP1.postUpdate(accTotal2 - accTotal1)
the first line is responsible for this error:
[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'shelly-5' failed: Could not cast 3883.4413 to org.openhab.core.library.types.QuantityType; line 45, column 22, length 82 in shelly
am i reading the historicState in a wrong way (don’t get the value as QuantityType Energy)?
if i change Shelly_EM3_consumeP1 to Number and read the historic States as Number this rule works:
var accTotal1 = (Shelly_EM3_accTotal.historicState(firstDayPrevMonth).state as Number).doubleValue
var accTotal2 = (Shelly_EM3_accTotal.historicState(lastDayPrevMonth).state as Number).doubleValue
Shelly_EM3_consumeP1.postUpdate(accTotal2 - accTotal1)
okay, figured it out myself! Shelly_EM3_consumeP1 as Number:Energy and this rule:
var accTotal1 = (Shelly_EM3_accTotal.historicState(firstDayPrevMonth).state as Number).doubleValue
var accTotal2 = (Shelly_EM3_accTotal.historicState(lastDayPrevMonth).state as Number).doubleValue
Shelly_EM3_consumeP1.postUpdate((accTotal2 - accTotal1).toString)
i don’t really understand why it has to be this way but i works
You’ve thrown away the Quantity property, effectively discarding the units.
So your result has no units either when you try to update an Item that demands units.
Work with the units, not against them. If you log out the values of your intermediate variables you will get a better idea of what’s going on.
var accTotal1 = Shelly_EM3_accTotal.historicState(firstDayPrevMonth).state as QuantityType<Energy>
That will give you accTotal1 as a Quantity type with units.
It might be in joules or kWh or Wh, who cares - so long as you sum it with another Quantity, openHAB will take care of matching/scaling the units. So you can add kWh to Wh without thinking about it.
The result will be a Quantity as well.
rule "Power Consumption Range"
when
Item Test_Test0815 changed
then
val ZonedDateTime firstDayThisMonth = now.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0)
val ZonedDateTime firstDayPrevMonth = now.minusMonths(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0)
val ZonedDateTime lastDayPrevMonth = firstDayThisMonth.minusSeconds(1)
var accTotal1 = Shelly_EM3_accTotal.historicState(firstDayPrevMonth).state as QuantityType<Energy>
var accTotal2 = Shelly_EM3_accTotal.historicState(lastDayPrevMonth).state as QuantityType<Energy>
end
and i get this error for the line with var accTotal1 [...]:
Script execution of rule with UID 'shelly-5' failed: Could not cast 3883.4413 to org.openhab.core.library.types.QuantityType;
We’d better check what version of OH is being used here.
Persistence strips off units and stores numbers only. In OH3, it should restore the units when retrieving data. (In OH2 it doesn’t, you have to do that yourself).
So if it should but doesn’t for you - why is that? Persistence can’t guess the units of stored numeric-only data. So it looks to the particular Item’s default unit. If there isn’t an Item-level default, it looks to the locale dependent system default units. But not all quantity types have a system default - Energy type does not. You need an Item default unit…
You haven’t got an Item default unit in this Item. It’s not the source Item for persistence, but you’d better check those.
When using xxx.items files, the label [state presentation] does double duty as default units too.
Something like Number:Energy Shelly_EM3_accTotal "Shelly em3 Gesamtverbrauch [%.1f kWh]"
A caution when messing with default units and persistence - if you change the unit it won’t go back and edit stored old data. So when you introduce a default, be sure it matches what was being used before (looks like kWh for you)