Show date/time of last sensor update

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.

My 2.5 VSC doesn’t like new Date() either.
import java.util.Date
at xxx.rules file head fixes that.

@rossko57 has the solution to this specific problem but looking at the code it’s kind of oddly constructed. I can’t really think of a case where using Date would be better than using ZonedDateTime or LocalDateTime. Especially since there is an implicit variable now.

To use those the rule would become:

val getTimestamp = [ GenericItem item, String date_format |
    val currTime = now;
    val date_time_format = if(date_format == "" || date_format === null) "%1$ta %1$tT" else date_format
    val timeStamp = String::format(date_time_format, currTime)
    if(item !== null) { // An Item can never be NULL, only an Item's state can be NULL 
        if(item instanceof DateTimeItem) {
            item.postUpdate(currTime);
            logInfo("Last Update", item.name + " DateTimeItem updated at: " + timeStamp)
        }
        else if(item instanceof StringItem) {
            item.postUpdate(timeStamp)
            logInfo("Last Update", item.name + " StringItem updated at: " + timeStamp)
        }
        else {
            logWarn("Last Update", item.name + " is not a DateTime or String - not updating")
        }
    }
    timeStamp
]
1 Like

Hi rossko57 & rlkoshak,

almost there, just one leftover:

item.postUpdate(currTime);

Will not work because it would mean a conversion from a DateTime to a state

[{
	"resource": "/Volumes/openHab-conf/rules/energy.rules",
	"owner": "_generated_diagnostic_collection_name_#0",
	"code": "org.eclipse.xtext.xbase.validation.IssueCodes.incompatible_types",
	"severity": 8,
	"message": "Type mismatch: cannot convert from DateTime to State",
	"startLineNumber": 31,
	"startColumn": 29,
	"endLineNumber": 31,
	"endColumn": 37
}]

I just replaced “currTime” with “timesStamp” in line:

  item.postUpdate(currTime);

…and that saved the day.

Thank your very much!!!