MaximumSince/minimumSince are not working as expected

Hi,

I am seeing the issue of persistance’s methods minimumSince/maximumSince retrieving the last value.

In the script, I am printing out the maximum/minimum since 20 minutes ago:
logInfo("rules", "Denis maximum: " + Denis.maximumSince(now.minusMinutes(20), "influxdb").timestamp) logInfo("rules", "Denis minimum: " + Denis.minimumSince(now.minusMinutes(20), "influxdb").timestamp)

This item “Denis” is a ContactItem, without any binding (changes state by an outside script)
I am using InfluxDB.

And HABmin is clearly showing the recent values here

But from the output it looks like the persistence only sees the last value:

2015-11-10 00:16:00.040 [INFO ] [org.openhab.model.script.rules] - Denis maximum: Tue Nov 10 00:16:00 CST 2015 2015-11-10 00:16:00.077 [INFO ] [org.openhab.model.script.rules] - Denis minimum: Tue Nov 10 00:16:00 CST 2015 2015-11-10 00:16:00.114 [INFO ] [org.openhab.model.script.rules] - HOME is not OCCUPIED 2015-11-10 00:17:00.040 [INFO ] [org.openhab.model.script.rules] - Denis maximum: Tue Nov 10 00:17:00 CST 2015 2015-11-10 00:17:00.077 [INFO ] [org.openhab.model.script.rules] - Denis minimum: Tue Nov 10 00:17:00 CST 2015 2015-11-10 00:17:00.110 [INFO ] [org.openhab.model.script.rules] - HOME is not OCCUPIED

Any ideas, guys?

You could add this line to your logback.xml and see a lot of new related information in openhab.cfg:

<logger name="org.openhab.persistence.influxdb.internal" level="TRACE"/>

Also, the meaning of “maximumSince” would not necessarily mean that you would get back an HistoricItem of a particular timestamp – since the persistence layer is computing a value based on a range of persisted states over the last 20 minutes, which timestamp should this HistoricItem have really? I would think the meaning of the timestamp for HistoricItems that are computed over a range of states would be meaningless.

Good idea. Let me try this.

You know, I never questioned that because I looked at the OH sources and if I am reading it correctly, “maximumSince” finds the max value over range, and then iterates over each value and finds the 1st “maximum” value. Of course, the returned value would have the maximum value and its timestamp.

I am referring to the file /openhab/bundles/core/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/extensions/PersistenceExtensions.java

watou,

Now here is a query, looked correct (7:50 am right now, I changed in the script to look back 80 minutes)

2015-11-10 07:50:00.825 [DEBUG] [i.i.InfluxDBPersistenceService] - got a query
2015-11-10 07:50:00.826 [TRACE] [i.i.InfluxDBPersistenceService] - filter itemname: Denis
2015-11-10 07:50:00.826 [TRACE] [i.i.InfluxDBPersistenceService] - filter ordering: ASCENDING
2015-11-10 07:50:00.827 [TRACE] [i.i.InfluxDBPersistenceService] - filter state: null
2015-11-10 07:50:00.827 [TRACE] [i.i.InfluxDBPersistenceService] - filter operator: EQ
2015-11-10 07:50:00.828 [TRACE] [i.i.InfluxDBPersistenceService] - filter getBeginDate: Tue Nov 10 06:30:00 CST 2015
2015-11-10 07:50:00.828 [TRACE] [i.i.InfluxDBPersistenceService] - filter getEndDate: null
2015-11-10 07:50:00.828 [TRACE] [i.i.InfluxDBPersistenceService] - filter getPageSize: 2147483647
2015-11-10 07:50:00.829 [TRACE] [i.i.InfluxDBPersistenceService] - filter getPageNumber: 0
2015-11-10 07:50:00.829 [TRACE] [i.i.InfluxDBPersistenceService] - appending limit 2147483647
2015-11-10 07:50:00.829 [TRACE] [i.i.InfluxDBPersistenceService] - startEntryNum 0
2015-11-10 07:50:00.830 [DEBUG] [i.i.InfluxDBPersistenceService] - query string: select value, time from Denis where  time > 1447158600s  order asc limit 2147483647

Then I see a lot of values being pulled from InfluxDB, this part is right - both 0s and 1s.

2015-11-10 07:50:00.877 [TRACE] [i.i.InfluxDBPersistenceService] - adding historic item Denis: time 1.447159260133E12 value 1.0
2015-11-10 07:50:00.877 [TRACE] [i.i.InfluxDBPersistenceService] - digitalvalue 1
2015-11-10 07:50:00.878 [TRACE] [i.i.InfluxDBPersistenceService] - adding historic item Denis: time 1.447159320147E12 value 0.0
2015-11-10 07:50:00.878 [TRACE] [i.i.InfluxDBPersistenceService] - digitalvalue 0

So it must be a problem somewhere else :frowning:

I’m not 100% positive, but it looks like a disagreement between PersistenceExtensions.maximumSince that only seems to work on DecimalType states [1], and InfluxDBPersistenceService.objectToState, which returns states of the correct type (OpenClosedType). So when maximumSince is looping through the returned HistoricItems, it is only checking DecimalType states to determine which is maximum. Since this leaves maximumHistoricItem set to null, the method synthesizes a brand new HistoricItem using the current time [2].

I don’t know the proper resolution to this apparent disagreement, but it deserves an issue in github.

	static public HistoricItem maximumSince(final Item item, AbstractInstant timestamp, String serviceName) {
		Iterable<HistoricItem> result = getAllStatesSince(item, timestamp, serviceName);
		Iterator<HistoricItem> it = result.iterator();
		HistoricItem maximumHistoricItem = null;
		DecimalType maximum = (DecimalType) item.getStateAs(DecimalType.class);
		while(it.hasNext()) {
			HistoricItem historicItem = it.next();
			State state = historicItem.getState();
			if (state instanceof DecimalType) { // <-- [1] HERE
				DecimalType value = (DecimalType) state;
				if(maximum==null || value.compareTo(maximum)>0) {
					maximum = value;
					maximumHistoricItem = historicItem;
				}
			}
		}
		if(maximumHistoricItem==null && maximum!=null) {
			// the maximum state is the current one, so construct a historic item on the fly
			final DecimalType state = maximum;
			return new HistoricItem() {
				
				public Date getTimestamp() {
					return Calendar.getInstance().getTime();  // <-- [2] HERE
				}
				
				public State getState() {
					return state;
				}
				
				public String getName() {
					return item.getName();
				}
			};
		} else {
			return maximumHistoricItem;
		}
	} 

Another way of looking at it is: the concept of “maximum” and “minimum” does not apply to non-numeric states, like OpenClosedType, OnOffType, etc. Even though InfluxDB stores them sensibly as “0” and “1”, that is really an implementation detail of the InfluxDB layer. I would not have a good argument against that position, should someone in the know present it. Is there a different persistent extension method you could use instead to achieve what you’re after?

watou, I think you are right - ContactItem comes out as a non-numeric value and these persistence functions don’t work as expected. Yes, I can switch to use the type “Number” instead of ContactItem because it’s script-driven value anyways. I just wanted to get to the bottom of it and it’s a shame that these little things are not spelled out anywhere.

@watou - your theory was right - as soon as I switched to using Number (0s and 1s) instead of Contact, the script was able to produce correct results for “maximumSince” function.

So this is when this topic ends :smile:

1 Like

This discussion saved me tons of time :-).
I didn’t want to change the Contact item for a Number one, so I ended up using the current state and changedSince instead of maximumSince.

Here is what I ended with to know if motion was detected in the last 30 minutes :

mainRoom_motion.state == CLOSED && !mainRoom_motion.changedSince(now.minusMinutes(30))

One note though : updating the documentation to make it clear that maximumSince and minimumSince only works with number items (same for all other restrictions that might apply to other persistence extensions).

1 Like