Show date/time of last sensor update

I wouldn’t add it to the GenericItem, see here a previous discussion. But we can think of other ways to make it more easily available to UIs through REST (although we have to be careful not to send too many events as some bindings might create several state updates per second).

2 Likes

Hi All

I have been doing this in openHAB for a while, but recently updated to the latest build and now everything shows as Green? Has something changed that would cause this?

I think same problem described here:
https://community.openhab.org/t/valuecolor-problems-after-update-to-oh2-2/37636

I have the same problem, just waiting for a new stable version which will (hopefully) fix this.

I use this lambda for timestamps:

val Functions$Function2<GenericItem, String, String> getTimestamp = [  //function (lambda) to get a timestamp. Returns formatted string and optionally updates an item
    item,
    date_format |
    
    var date_time_format = date_format
    if(date_format == "" || date_format === null) date_time_format = "%1$ta %1$tT" //default format Day Hour:Minute:Seconds
    var String Timestamp = String::format( date_time_format, new Date() )
    if(item != NULL && item !== null) {
        var t = new DateTimeType()
        
        if(item instanceof DateTimeItem) {
            postUpdate(item, t)
            logInfo("Last Update", item.name + " DateTimeItem updated at: " + Timestamp )
            }
        else if(item instanceof StringItem) {
            postUpdate(item, Timestamp)
            logInfo("Last Update", item.name + " StringItem updated at: " + Timestamp )
            }
        else
            logWarn("Last Update", item.name + " is not DateTime or String - not updating")
    }
    Timestamp
    ]

You call it in a rule like this:

rule "HEM Last Updated"
when
    Item HEM_C1 received update or
    Item HEM_C2 received update
then
    getTimestamp.apply(HEMLastUpdated, "")
end

or:

rule "Aeon Labs Multisensor LA Last Updated"
when
    Item AeonMS61LA changed or
    Item AeonMS62LA changed or
    Item AeonMS63LA changed or
    Item AeonMS64LA changed
then
    getTimestamp.apply(AeonMS6LastUpdatedLA, "%1$ta %1$tR")
end

or:

rule "Autolock Front Door"
when
    Item virtualfrontDoorDoorContact changed to CLOSED
then
    // Front Door Closed
    if(DoorTimer !== null) DoorTimer.cancel
    DoorTimer = null
    
    logInfo("FRONT_DOOR", "Front Door CLOSED - Master Sensor: " + FrontDoorSensorSelected.state )
    postUpdate(hallway_HSM200_setcolour, 3)  //RED (closed, unlocked)
        
    var String Timestamp = getTimestamp.apply(virtualfrontDoorLastUpdate, "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS")
    
    AutoRelock.apply(" by: Door Close Auto Lock", Timestamp, LockTimers, "FrontDoor", DoorRelockTime)

end

This way, it doesn’t matter if the item is a DateTime type, or a String, you can optionally specify the format of the string, and you can get the Timestamp value returned as a String to use in notifications, or logs etc.

I have implemented this LastUpdate method but it stopped changing the colors after updating Openhab to 2.2.0-1. The timer is still working. It seems valuecolor can not get the time in seconds from a DateTime item anymore. Any ideas?

Thank you for this!

I was looking for a way to date/time stamp the zWave nodes and this will do it . . .

Best, Jay

1 Like

I´m just trying your examples.

I have these PIR´s all around, and I want to know when they last fired.
I thought I could just

rule:

rule "Spisestue PIR Last Updated"
when
    Item spise_pir changed
then
    getTimestamp.apply(spise_pirUpdated, "%1$ta %1$tR")
end

Sitemap

		Text item=spise_pirUpdated label="Sidste åbnet [%1$tH:%1$tM %1$td.%1$tm.%1$tY]"

But it doesn´t really work…
Isn´t it possible to catch a timestamp from an action and create this time to an item, to show it in a sitemap?

This is the error I get:

2018-07-02 21:32:34.592 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Spisestue PIR Last Updated': The name 'getTimestamp' cannot be resolved to an item or type; line 5, column 5, length 12

You are missing the code under “I use this lambda for timestamps:”

I have no idea where to place that part, to be honest.

At the top of your .rules file.

Thx Rich.

Can´t get it to work. Tried with another PIR (Aeotec Multisensor6).

My rule file:

val Functions$Function2<GenericItem, String, String> getTimestamp = [  //function (lambda) to get a timestamp. Returns formatted string and optionally updates an item
    item,
    date_format |
    
    var date_time_format = date_format
    if(date_format == "" || date_format === null) date_time_format = "%1$ta %1$tT" //default format Day Hour:Minute:Seconds
    var String Timestamp = String::format( date_time_format, new Date() )
    if(item != NULL && item !== null) {
        var t = new DateTimeType()
        
        if(item instanceof DateTimeItem) {
            postUpdate(item, t)
            logInfo("Last Update", item.name + " DateTimeItem updated at: " + Timestamp )
            }
        else if(item instanceof StringItem) {
            postUpdate(item, Timestamp)
            logInfo("Last Update", item.name + " StringItem updated at: " + Timestamp )
            }
        else
            logWarn("Last Update", item.name + " is not DateTime or String - not updating")
    }
    Timestamp
    ]


rule "Multisensor6 PIR Last Updated"
when 
    Item ZWaveNode5ZW100MultiSensor6_MotionAlarm changed from OFF to ON
then
    getTimestamp.apply(ZWaveNode5ZW100MultiSensor6_MotionAlarmUpdated, "%1$ta %1$tR")
end

My item:

String ZWaveNode5ZW100MultiSensor6_MotionAlarmUpdated <clock>

And my sitemap:

		Text item=ZWaveNode5ZW100MultiSensor6_MotionAlarmUpdated label="Sidste åbnet [%1$tH:%1$tM %1$td.%1$tm.%1$tY]"

This is my log:

2018-07-02 22:42:40.676 [vent.ItemStateChangedEvent] - ZWaveNode5ZW100MultiSensor6_MotionAlarm changed from OFF to ON
2018-07-02 22:42:41.412 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Multisensor6 PIR Last Updated': null

I really have no idea whether the above code is applicable to your Items and sensors and such. I don’t know what problem it is trying to solve. It seems overly complex to me. Hopefully the poster of the code can help out.

My goal was to resolve when a PIR registered latest motion detected in a timestamp I could show in a sitemap.

Like this:

The label “sidst åbnet” and then time, is when this PIR last went on. (ie latest motion detected).
The difference however, this example is the xiami motion sensor, which has a channel for latest motion detected.

All my other PIR´s I´ve got doesn´t have this channel.
So I thought (expected I guess) I could “build” a timestamp from a rule using the build-in (now) time, and just show this time (latest motion detected) in sitemap. Just like the Xiaomi sensor.

In fact, I would expect this to work with all kinds of items which change state. I also thought this would be a peace of cake rule. Guess I was wrong.

I’ve got rules like this

rule "trip U2apron"
when
	Item motion_U2apron changed to OPEN        // motion begin
then
	motion_U2apron_stamp.postUpdate(new DateTimeType())   //defaults to now
        ..... do other stuff
end

The xxx_stamp is a DateTime type Item, do the formatting you want in its label.

Contact motion_U2apron "PIR U2 apron [MAP(motion.map):%s]" <motion> {modbus="<[slave21DI:4:trigger=CHANGED,transformation=JS(mbinvert.js)]"}
DateTime motion_U2apron_stamp "PIR U2 apron last [%1$td/%1$tm %1$tR]" <iclock> (gMotion_stamps)

Note the stamp represents only when signal started, many PIRs won’t retrigger if faced with continuous motion.

I include the stamps in mapdb persistence, but not the PIRs

1 Like

Ahh, thank you very much rossko. I works like a dream!

It’s a bit overcomplicated, but it was intended to provide a “lastupdated” timestamp whether the Date item is a DateTime type or a String.

You have to include this at the top of your rules to include lambda’s in OH2

import org.eclipse.xtext.xbase.lib.Functions    //apparently needed for OH2 lambda's

Then as long as your item is a DateTime type, or a String, your code should work. You can also get the Timestamp back as a String (which I use in push notifications or e-mails).

This may no longer be the case in OH 2.3. I’m still exploring but I think we are back to being able to define lambdas as follows and without the import and no longer get warnings:

val getTimestamp = [ GenericItem item, String date_format |
    // code

    // last line returns a String
]

Hi everyone,

the Date() function no longer works on my OH2.5 installation, however, it did work for more than a year.

[{
	"resource": "/Volumes/openHab-conf/rules/TimeStampX.rules",
	"owner": "_generated_diagnostic_collection_name_#0",
	"code": "org.eclipse.xtext.diagnostics.Diagnostic.Linking",
	"severity": 8,
	"message": "Date cannot be resolved.",
	"startLineNumber": 6,
	"startColumn": 65,
	"endLineNumber": 6,
	"endColumn": 69
}]
Does it have to do with the change of the repositories to jfrog?

NTP-Binding is installed:

binding-ntp - 2.5.12
$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
$ dpkg --list | grep openhab
ii  openhab2  2.5.12-1 all openhab2
$ cat /etc/apt/sources.list.d/openhab2.list
# deb https://dl.bintray.com/openhab/apt-repo2 stable main
deb https://openhab.jfrog.io/artifactory/openhab-linuxpkg stable main

I shouldn’t think so. Perhaps your Java version updated.
When you’re ready, share your rule.

val getTimestamp =
[ GenericItem item, String date_format |
    var date_time_format = date_format;
    if (date_format == "" || date_format === null) date_time_format = "%1$ta %1$tT"; //default format Day Hour:Minute:Seconds
    var String Timestamp = String::format(date_time_format, new Date());
    if (item != NULL && item !== null) {
      var t = new DateTimeType();    
      if (item instanceof DateTimeItem) {
        item.postUpdate(t.toString); // 26.09.2020 (AK) object!
        logInfo("Last Update", item.name + " DateTimeItem updated at: " + Timestamp );
      }
      else if (item instanceof StringItem) {
        item.postUpdate(Timestamp);  // 26.09.2020 (AK)
        logInfo("Last Update", item.name + " StringItem updated at: " + Timestamp );
      }
      else
        logWarn("Last Update", item.name + " is not DateTime or String - not updating");
        // logWarn("Item State: ", item.state.toString);
    }
    Timestamp;
]

And even if stripped down to this

val getTimestamp = [ GenericItem item, String date_format |
    // code
    var date_time_format = date_format;
    var String Timestamp = String::format(date_time_format, new Date());
    Timestamp; // last line returns a String
]

Visual Studio prompts me with the aforementioned error.