I’m trying to setup a Year-to-date calculation of my electrical energy consumption. The consumption is reported in Watthours in the item vpmEFAT ( persisted in rrd4j every minute). Next to the fact, that I’m absolutely not sure if the code below is correct, I have started persisting only in may this year. But if the rule could serve as general example for YTD-calculation as dela between a current value and the value at the beginning of the year, it wouldbe great if it could also handle such an issue.
rule "YTD energy values"
when
Item vpmEFAT received update or Time cron "0 */5 * * * ?"
then
val onTheFirstDayOfTheFirstWeek = dateTime.withWeekyear(dateTime.getYear()).withWeekOfWeekyear(1).withDayOfWeek(1)
var Number YTDBezug = vpmEFATKWH.deltaSince(now.minus(onTheFirstDayOfTheFirstWeek))
postUpdfate(vpmEFATYTD,YTDBezug)
logInfo("Rules", "YTD Bezug updated to: "+vpmEFATYTD.state)
end
Current error in the logs:
2017-10-24 23:51:28.521 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘YTD energy values’: An error occurred during the script execution: The name ‘dateTime’ cannot be resolved to an item or type.
Ok after some further testing something general about the error.
From my understanding you are trying to get the first day of the first week of the year.
(I think you want to get this from the current date.)
You are doing this with DateTime Methods and trying it with static methods and without a DateTime instance
I have searched a bit in the Documentation of joda time and cant find that much static methods.
My simple suggestion would be: Create a DateTime instance first:
var DateTime myDate = new DateTime()
val onTheFirstDayOfTheFirstWeek = myDate.withWeekyear(myDate.getYear()).withWeekOfWeekyear(1).withDayOfWeek(1)
@Confectrician: I thought the import is not necessary anymore in OH2
As output there should have been 1.1.2017 (00:00 hrs) --> beginning of the year. As it should automatically change every year, I thought I try the joda.time stuff.
So using the first day of the first week was a wrong approach by myself.
So I got it working, that I dynamically receive the first day of the first year - but still get an error:
ule "YTD energy values"
when
Item vpmEFAT changed or Time cron "0 */5 * * * ?"
then
val CurrentDate = new DateTime()
val Yearbeginn = new DateTime(CurrentDate.getYear(),1, 1, 0, 0, 0)
logInfo("Rules", "Datum: "+Yearbeginn)
var Number YTDBezug = vpmEFATKWH.deltaSince(now.minus(Yearbeginn))
postUpdate(vpmEFATYTD,YTDBezug)
logInfo("Rules", "YTD Bezug updated to: "+vpmEFATYTD.state)
end
Log:
2017-10-26 22:37:54.469 [INFO ] [eclipse.smarthome.model.script.Rules] - Datum: 2017-01-01T00:00:00.000+01:00
2017-10-26 22:37:54.496 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘YTD energy values’: An error occurred during the script execution: Could not invoke method: org.joda.time.DateTime.minus(long) on instance: 2017-10-26T22:37:54.493+02
Is my delta-calculation wrong or is it due to a missing value in the rrd4j database on the 1.1.2017 00:00:00 ?
It seems like you are going about the date stuff the hard way.
// you don't need CurrentDate because now IS the current date
val Yearbeginn = now.withTimeAtStartOfDay.withDayOfYear(1)
And since Yearbeginn is the beginning of the year it makes no sense to subtract it from now. That will result in a timestamp that is completely wrong. Just use Yearbeginn.
var Number YTDBezug = vmpEFATKWH.deltaSince(Yearbeginn)
deltaSince literally expects a timestamp to start the query from, not a number of milliseconds from now.
However, this still might throw an error if you don’t have data that goes back that far. I think I remember that rrd4j tends to just trow an error when you try to go back before your first piece of data in the DB. You may have to gradually work with this rule until you have enough data for a full year.
It seems like you are going about the date stuff the hard way.
Why going the easy way? My way or the highway
You were right → result was a NULL value for this year. That’s why i put a check in it:
rule "YTD energy values"
when
Item vpmEFAT changed or Time cron "0 */5 * * * ?"
then
val Yearbeginn = now.withTimeAtStartOfDay.withDayOfYear(1)
logInfo("Rules", "Datum: "+Yearbeginn)
var Number YTDBezug = vpmEFATKWH.deltaSince(Yearbeginn)
logInfo("Rules", "YTD Bezug updated to: "+YTDBezug)
if (YTDBezug == null) {
vpmEFATYTD.postUpdate(vpmEFATKWH.state)
}
else {
postUpdate(vpmEFATYTD,YTDBezug)
}
logInfo("Rules", "EFATYTD updated to: "+vpmEFATYTD.state)
end
I’m trying to achieve about the same function, but can’t get it to work.
I got my meter value in kWh from the item P_BP8_ElMaalervisningKwh, and I have used it to trigger the rule instead of your item vpmEFAT
On my sitemap, I would like to have a YTD value next to my P_BP8_ElMaalervisningKwh which I imagine could be done by using the YTDBezug. However, I’m in doubt what your vpmEFATKWH item contain, and thereby what I should replace it with?
Sorry, I’m still on a steep learing curve, but of course I will try to help.
If you receive your values already in kWh the items vpmEFAT and vpmEFATKWH are the same. In fact I could change that to the same name, as another rule triggers the conversion from watthours to kilowatthours.
I try to put your rule here (you’ve to try and see the logs):
rule "YTD energy values"
when
Item P_BP8_ElMaalervisningKwh changed or Time cron "0 */5 * * * ?"
then
val Yearbeginn = now.withTimeAtStartOfDay.withDayOfYear(1)
logInfo("Rules", "Datum: "+Yearbeginn)
var Number YTDConsumption = P_BP8_ElMaalervisningKwh.deltaSince(Yearbeginn)
logInfo("Rules", "YTD consumption updated to: "+YTDConsumption )
if (YTDConsumption == null) {
YTDconsumptionITEM.postUpdate(P_BP8_ElMaalervisningKwh.state) //probably it would be nicer to put a not available info here
}
else {
postUpdate(YTDconsumptionITEM,YTDConsumption )
}
logInfo("Rules", "YTDconsumptionITEM updated to: "+YTDconsumptionITEM.state)
end
You need two items:
P_BP8_ElMaalervisningKwh
YTDconsumptionITEM
Of course you have to persist P_BP8_ElMaalervisningKwh (I am currently using rrd4j, want to change to influxdb).
I added your rule, it looks more or less the same to what I already did to your original rule from the October post. And it acts the same way, from what I can see in my log.
Reading your post once again, made me think a little bit more about you finally mentioning my meter value item must be persistent. In the first time I did not pay enough attention to that. The fact is, I assumed that was not necessary, since the value from the meter remains even I restart OpenHAB. But that’s of cores only the actual meter value, not the value at year begin, why deltaSince(Yearbeginn) is quite hard to use then, I guess!
However, I have chosen to solve it a little bit different.
rule "Set meter value year beginn"
when
Time cron "0 01 00 01 01 ?"
then
YearBeginnValue_El_kWh.state = P_BP8_ElMaalervisningKwh.state as DecimalType
end
rule "Calculate YTD energy value"
when
Item P_BP8_ElMaalervisningKwh changed
then
var Number TotalConsumption = P_BP8_ElMaalervisningKwh.state as DecimalType
var Number YearBeginn = YearBeginnValue_El_kWh.state as DecimalType
var Number YTDConsumption = TotalConsumption - YearBeginn
postUpdate(SitemapYTD_El_kWh, YTDConsumption)
end
I’m persisting YearBeginnValue_El_kWh with mapdb, which I’m already using for other items necessary to restore on startup.