Group:DateTime:MIN not displayed in sitemap

  • Platform information:
    • Hardware: RaspberryPi 3b
    • openHAB version:
  • Issue of the topic: please be detailed explaining your issue
    I have a problem with my DateTime group item.
    I want to display the oldest value of sensor updates.
    The members of the group are updated rule based.
    All members in the sitemap are displayed correctly.
    Only the group state is UNDEF and so not displayed.
    Can someone help.
  • Please post configurations (if applicable):
    • Items configuration related to the issue
Group:DateTime:MIN gLastSeen "Last Seen [%1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS]" <calendar> (gHome)
DateTime GF_HL_MO_1_LastSeen "LastSeen GF_HL_MO_1 [%1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS] "  <calendar> (gLastSeen)
DateTime GF_K_MO_1_LastSeen "LastSeen GF_K_MO_1 [%1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS]" <calenadar> (gLastSeen)
DateTime OU_GA_T_1_LastSeen "LastSeen OU_GA_T_1 [%1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS]" <calendar> (gLastSeen)
  • Sitemap configuration related to the issue
sitemap first label="My Hell" {
        Frame label="LastSeen" {
                Text item=gLastSeen icon="calendar"
                Group item=gLastSeen
        }
}
  • Rules code related to the issue
 rule "Sensor updates LastSeen"
    when 
         Member of gSensor received update
    then 
         val sensor = triggeringItem;
         val na = sensor.name;
         val split = na.split("_");
         val String itemName = split.get(0) + '_' + split.get(1) + '_' + split.get(2) + '_' + split.get(3) + '_LastSeen'
                           gLastSeen.members.filter[i | i.name.equals(itemName)].forEach [item | item.postUpdate(new DateTimeType); logInfo("lastseen.rules", "Item " + itemName + " updated.");]  
    end
  • Services configuration related to the issue
  • If logs where generated please post these here using code fences:

I’m not at all sure that MIN/MAX aggregations are implemented for DateTime Group types. Not every function makes sense for every possible type e.g. what should AVG or SUM do with dates?

The docs do say that MIN/MAX/AVG are for “decimal type” (Number)

EDIT - so, how to do it instead? Using Group functions is a neat idea, but you’d have to do it with a Group of Number Items holding the “timestamp” as an epoch integer.
Easy enough to populate those from your timestamping rule.
For display, you could use a transform to convert epoch to readable - a javascript I should think.

Or abandon the group, and have your rule populate a dedicated “oldest” Item. The rule would have to retrieve the “old” individual value before updating the timestamp, and compare with current “oldest”.
Hmm, then you’d still need to search for the next-oldest. That’s an interesting little task … I can feel a sorted list coming on somewhere.

In Rules DSL a map/reduce would work I think. Something like:

var oldestDT = MyDateTimes.members.map[(state as DateTimeType).zonedDateTime].reduce[oldest, curr | oldest = if(curr.isBefore(oldest)) curr else oldest]

In Python:

oldestDT = reduce(lambda: oldest, curr: oldest = curr if curr.isBefore(oldest) else oldest,
                  [items[dt.name].getZonedDateTime() for dt in ir.getItem("MyDateTimes")])

I just typed in the above two lines, there may be typos, especially in the Python verison. See Design Pattern: Working with Groups in Rules for details.

1 Like

Thanks for the help!
I did it like this:

In the rule I changed to

item.postUpdate(now.millis);

Group:Number:MIN gLastSeen “Last Seen [JS(millisToDate.js):%s]” (gHome)

(function(i) {
       return new Date(parseInt(i)).toString();
})(input)

I am also trying to a get the oldest lastupdate datetime from a group.

rule "Record LastUpdateTest"
when
  Member of LastUpdateTest changed
then
  logInfo("LastUpdateTest", "Groupmembertest start")
  
  var oldestDT = LastUpdateTest.members.map[(state as DateTimeType).zonedDateTime].reduce[oldest, curr | oldest = if(curr.isBefore(oldest)) curr else oldest]
 
  logInfo("LastUpdateTest", oldestDT.toStrings)
  logInfo("LastUpdateTest", "Groupmembertest end")
end

I get the error:
Rule ‘Record LastUpdateTest’: Couldn’t invoke ‘assignValueTo’ for feature param oldest

The group LastUpdateTest contains only DateTime items. They are linked to zwave devices with the profile timestamp-update.

I think the reduce is wrong. You don’t do the assignment in the lambda.

....reduce[oldest, curr | if(curr.isBefore(oldest)) curr else oldest]

Yes, it works now. Must made that error when copied and corrected it for my enviroment.

I coincidentally stepped into this and started thinking about enhancing our available group aggregation function by support for MIN and MAX. What I found was an undocumented bunch of DateTime group functions: LATEST and EARLIEST. I guess they will help you to get what you want.

Usage:

Group:DateTime:LATEST   gLastSeen     "Last Seen [%1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS]" <calendar>
Group:DateTime:EARLIEST gLatestUpdate "Latest Update [%1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS]" <calendar>

PR for updating the docs: https://github.com/openhab/openhab-docs/pull/1206

// Edit: I will add an example tomorrow to clarify the behavior.

5 Likes

Useful companion features to channel profiles timestamp-update and timestamp-change

Wonder how long those have been there and how many other little useful features are hiding in OH like this. I could have used this years ago. Great find!

They are available for more than two years (see PR). And I found a piece of documentation in the Concepts -> Items section. Imo Configuration Guide -> Items is a better place for it. No need to describe it twice. Just add a cross reference in the first location.

Example:

Assuming we have a Group containing three timestamps: now().minusDays(10), now() and now().plusSeconds(30). The EARLIEST function returns now().minusDays(10), the LATEST function returns now().plusSeconds(30).

1 Like