[Solved] OHv2: persistence... Cannot assign a value in null context

I log this in a rule:

    logInfo("AR.2.00", "ar_RainYesterday........: {}", ar_RainYesterday)
    logInfo("AR.2.01", "ar_RainTotal............: {}", ar_RainTotal)
    logInfo("AR.2.02", "ar_RainTotal...SoD......: {}", ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j"))
    logInfo("AR.2.03", "ar_RainTotal...SoD-1....: {}", ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(1), "rrd4j"))
    ar_RainYesterday = (ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j") - ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(1), "rrd4j"))

Results in this error:

2019-08-13 19:59:00.027 [INFO ] [lipse.smarthome.model.script.AR.2.01] - ar_RainTotal............: ar_RainTotal (Type=NumberItem, State=573.787, Label=Rain Total, Category=clouds_rain, Groups=[gAccuRite])
2019-08-13 19:59:00.040 [INFO ] [lipse.smarthome.model.script.AR.2.02] - ar_RainTotal...SoD......: 0.000
2019-08-13 19:59:00.055 [INFO ] [lipse.smarthome.model.script.AR.2.03] - ar_RainTotal...SoD-1....: -0.0000000000001
2019-08-13 19:59:00.086 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Rainfall prior to today': An error occurred during the script execution: Cannot assign a value in null context.

I am out of ideas on how to fix this. :frowning:

What is ar_RainYesterday ? Is that a variable you have declared somewhere hidden? What type?

1 Like

Well, thank you! You asked the right question… and as always: silly me!
It is an item and as such requires .postUpdate()

    ar_RainYesterday.postUpdate(ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j") - ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(1), "rrd4j"))

… which works… as in, at least it does not throw an error.

However, I noticed further issues with my rules.

rule "Rainfall prior to today"
  when
    //         s m h D M DoW Y
    //Time cron "0 1 0 * * ?   *"
    Time cron "0 0/1 * 1/1 * ? *"
    // here: 00:01; use http://www.cronmaker.com/
  then
    // update yesterday, with last night mm minus night before mm
    //logInfo("AR.2.00", "ar_RainYesterday........: {}", ar_RainYesterday)
    logInfo("AR.2.01", "ar_RainTotal............: {}", ar_RainTotal)
    //logInfo("AR.2.02", "ar_RainTotal...SoD......: {}", ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j"))
    ar_RainYesterday.postUpdate(ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j") - ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(1), "rrd4j"))
    logInfo("AR.2.03", "ar_RainTotal...SoD-1....: {}", ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(1), "rrd4j"))

    // update last 7 days
    ar_RainWeek.postUpdate(ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j") - ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(7), "rrd4j"))
    logInfo("AR.2.04", "ar_RainWeek.............: {}", ar_RainWeek)

    // update last 30 days
    ar_RainMonth.postUpdate(ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j") - ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(30), "rrd4j"))
    logInfo("AR.2.05", "ar_RainMonth............: {}", ar_RainMonth)

    // update last 30 days
    ar_RainQuarter.postUpdate(ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j") - ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(90), "rrd4j"))
    logInfo("AR.2.06", "ar_RainQuarter..........: {}", ar_RainQuarter)

    // update last 365 days
    ar_RainYear.postUpdate(ar_RainTotal.deltaSince(now.withTimeAtStartOfDay, "rrd4j") - ar_RainTotal.deltaSince(now.withTimeAtStartOfDay.minusDays(365), "rrd4j"))
    logInfo("AR.2.07", "ar_RainYear.............: {}", ar_RainYear)

end

The total rainfall was recorded for the first time on Aug 10th.
The total rainfall is the only value the weather station reports, meaning I have to calculate all other values, and for simplicity/testing sake started with the value prior to today.

However, I am not getting the 573mm as a rainfall for all items but yesterday.

2019-08-13 20:44:00.032 [INFO ] [lipse.smarthome.model.script.AR.2.01] - ar_RainTotal............: ar_RainTotal (Type=NumberItem, State=573.787, Label=Rain Total, Category=clouds_rain, Groups=[gAccuRite])
2019-08-13 20:44:00.056 [INFO ] [lipse.smarthome.model.script.AR.2.03] - ar_RainTotal...SoD-1....: -0.0000000000001
2019-08-13 20:44:00.074 [INFO ] [lipse.smarthome.model.script.AR.2.04] - ar_RainWeek.............: ar_RainWeek (Type=NumberItem, State=0.000, Label=Rainfall last 7 days, Category=clouds_rain, Groups=[gAccuRite])
2019-08-13 20:44:00.087 [INFO ] [lipse.smarthome.model.script.AR.2.05] - ar_RainMonth............: ar_RainMonth (Type=NumberItem, State=0.000, Label=Rainfall last 30 days, Category=clouds_rain, Groups=[gAccuRite])
2019-08-13 20:44:00.099 [INFO ] [lipse.smarthome.model.script.AR.2.06] - ar_RainQuarter..........: ar_RainQuarter (Type=NumberItem, State=0.000, Label=Rainfall last 90 days, Category=clouds_rain, Groups=[gAccuRite])
2019-08-13 20:44:00.115 [INFO ] [lipse.smarthome.model.script.AR.2.07] - ar_RainYear.............: ar_RainYear (Type=NumberItem, State=0.000, Label=Rainfall last 365 days, Category=clouds_rain, Groups=[gAccuRite])

What am I missing?

rrd4j compresses data i.e. throws original data away over time.
I think you must use everyMinute strategy to give deltaSince a chance of working by extrapolation.
Even then I’m not sure it works properly - lots of threads of people having trouble with this combination but no-one reporting success in the end. You could be the first :slight_smile:

My persistence rule:

  gPersist_rrd4j*         : strategy = everyMinute, restoreOnStartup, everyChange

and my items:

Group    gAccuRite																		(gAll, gPersist_rrd4j)
...
Number   ar_RainToday			"Rainfall today [%.0f mm]"							<clouds_rain>	(gAccuRite, gAccuRiteRain_Chart)
Number   ar_RainLast24H			"Rainfall last 24 hours [%.0f mm]"					<clouds_rain>	(gAccuRite)
Number   ar_RainYesterday		"Rainfall yesterday [%.0f mm]"						<clouds_rain>	(gAccuRite)
Number   ar_RainWeek			"Rainfall last 7 days [%.0f mm]"					<clouds_rain>	(gAccuRite)
Number   ar_RainMonth			"Rainfall last 30 days [%.0f mm]"					<clouds_rain>	(gAccuRite)
Number   ar_RainQuarter			"Rainfall last 90 days [%.0f mm]"					<clouds_rain>	(gAccuRite)
Number   ar_RainYear			"Rainfall last 365 days [%.0f mm]"					<clouds_rain>	(gAccuRite)

I think it has nothing to do with persistence.

The results are correct, because all I have recorded since Aug 10th is the same value; hence no delta, no matter what I chose as difference… it is always zero until a new ‘total’ value arrives.

Will persist values of all members of group gPersist_rrd4j
So far as I can see, the only member is gAccuRite which has no value of its own.

It does not consider any “sub-members” if the thing you are persisting happens to be a group itself.

I’m guessing ar_RainToday happens to gets persisted by its group membership of gAccuRiteRain_Chart by a strategy we cannot see.

The Item you’re using with deltaSince is ar_RainTotal … which doesn’t appear in any strategy you’ve shown us.

Ouch… are you saying that for an item to be persisted it has to be listed on its own?

My persist file has this comment:

// - "groupitem*" for all members of a group item (excl. the group item itself)

Which means to me I can use a group item to persist its members!

In this case, you ask to persist the value of the members of group gPersist_rrd4j
I can see only one member of that, which is gAccuRite
That happens to be a group as well, but that is of no interest to persistence - you asked it to store the value of that Item. (groups can have their own values, like SUM)

You don’t have to specify individual Items in persistence, you can use groups, but you must make sure the Items that want to persist are direct members of that group. Members of members don’t count here.

Thanks got it! Will change it.

Hmm, just had another look… why does this chart then work? … the only persistence is with the Group gAccuRite (gAll, gPersist_rrd4j)
image
… and I have other group items.

Here all items:

/ ----- 190810 MaxG: created
// ----- AccuRite 5in1 outdoor weather station
Group    gAccuRite																		(gAll, gPersist_rrd4j)

// AccuRite Weather Charts
Group    gAccuRiteTemp_Chart
Number   gAccuRiteTemp_Chart_Period

Group    gAccuRiteHumi_Chart
Number   gAccuRiteHumi_Chart_Period

Group    gAccuRiteWind_Chart
Number   gAccuRiteWind_Chart_Period

Group    gAccuRiteRain_Chart
Number   gAccuRiteRain_Chart_Period

// data received
String   ar_DataReceived		"AccuRite data"																		{mqtt="<[mymosquitto:ArgyleCourt/Property/AcuRite5in1:state:default]"}
DateTime ar_LastUpdated			"AccuRite: Last update [%1$td/%1$tm %1$tH:%1$tM]"	<calendar>	(gAccuRite, gLUP)

// data being extracted
Number   ar_Temperature			"Outdoor temperature [%.1f °C]"						<temperature>	(gAccuRite, gAccuRiteTemp_Chart, gSensors_Temperature)
Number   ar_Humidity			"Outdoor Humidity [%.0f %%]"						<temperature>	(gAccuRite, gAccuRiteHumi_Chart)
Number   ar_WindSpeed			"Wind speed at present [%.0f km/h]"	    			<wind>			(gAccuRite, gAccuRiteWind_Chart)
Number   ar_WindDir		    	"Wind direction [%.0f°]"			    			<wind>			(gAccuRite)
String   ar_WindDirText	    	"Wind direction [SCALE(wind_direction.scale):%s]" 	<wind>			(gAccuRite)
String   ar_Battery		    	"AccuRite Battery [%s]"		    					<battery4>		(gAccuRite)
Number   ar_RainTotal			"Rain Total [%.0f mm]"								<clouds_rain>	(gAccuRite)

// data being derived / calculated
Number   ar_TemperatureMin		"Outdoor temperature minimum [%.1f °C]"				<temperature>	(gAccuRite, gAccuRiteTemp_Chart)
Number   ar_TemperatureMax		"Outdoor temperature maximum [%.1f °C]"				<temperature>	(gAccuRite, gAccuRiteTemp_Chart)
Number   ar_HumidityMin			"Outdoor humidity minimum [%.0f %%]"				<temperature>	(gAccuRite, gAccuRiteHumi_Chart)
Number   ar_HumidityMax			"Outdoor humidity maximum [%.0f %%]"				<temperature>	(gAccuRite, gAccuRiteHumi_Chart)
Number   ar_Humidex				"Outdoor Humidex [SCALE(humidex.scale):%s]"							(gAccuRite)
Number   ar_WindSpeedMin	   	"Wind speed minimum [%.0f km/h]"    				<wind>			(gAccuRite, gAccuRiteWind_Chart)
Number   ar_WindSpeedMax		"Wind speed maximum [%.0f km/h]"    				<wind>			(gAccuRite, gAccuRiteWind_Chart)
Number   ar_RainToday			"Rainfall today [%.0f mm]"							<clouds_rain>	(gAccuRite, gAccuRiteRain_Chart)
Number   ar_RainLast24H			"Rainfall last 24 hours [%.0f mm]"					<clouds_rain>	(gAccuRite)
Number   ar_RainYesterday		"Rainfall yesterday [%.0f mm]"						<clouds_rain>	(gAccuRite)
Number   ar_RainWeek			"Rainfall last 7 days [%.0f mm]"					<clouds_rain>	(gAccuRite)
Number   ar_RainMonth			"Rainfall last 30 days [%.0f mm]"					<clouds_rain>	(gAccuRite)
Number   ar_RainQuarter			"Rainfall last 90 days [%.0f mm]"					<clouds_rain>	(gAccuRite)
Number   ar_RainYear			"Rainfall last 365 days [%.0f mm]"					<clouds_rain>	(gAccuRite)

Duh… got it… most items are a member of gAccuRite!
Thanks again for bearing with me; it’s 22:00 here; I should go to bed and not write rules!

Well, on looking into this groups thing properly it’s all rather vague and I suspect behaviour changed at some point. Now I don’t know.

You can use REST API to see if individual Items are being persisted, you should take the reported number of datapoints with a pinch of salt in rrd4j but it is a start.