Display Time only from DateTime?

I’m trying to get the current time, add a number of minutes to it and update an item with the result. However I’m not sure how to extract the HH:MM from the DateTime variable.
So far I have:

import org.joda.time.*
var int WasherCycleTime = 132
rule "spit diags"
when Item Testing changed from ON to OFF then
{ var DateTime WashingCompleteDateTime = now.plusMinutes(WasherCycleTime)
    logInfo("Testing" ,"WashingCompleteTime" +WashingCompleteDateTime)
    var String WashingCompleteTime = String::format( "%1$tH:%1$tM", +WashingCompleteDateTime )
    logInfo("Testing" ,"WashingCompleteTime" +WashingCompleteTime)
	WashingReadyTime.sendCommand(WashingCompleteTime.toString)	
}	
end

Below how I read the current time; you may use OH Designer (Ctrl+Space) to get a list of available methods.

var String welcome = "Guten Morgen, es ist " + Wochentag + " " + now.getHourOfDay.intValue + " Uhr und " + (now.getMinuteOfHour.intValue) + " Minuten."

1 Like

First, you want your WashingReadyTime item to be a DateTime item in your .items file:

DateTime WashingReadyTime "Washing Ready at [%1$tH:%1$tM]"

Then you want your rule to look something like:

import org.joda.time.DateTime
import org.openhab.core.library.types.DateTimeType

val int WasherCycleTime = 132

rule "spit diags"
when
  Item Testing changed from ON to OFF 
then
  val DateTime WashingCompleteDateTime = now.plusMinutes(WasherCycleTime)
  logInfo("Testing" ,"WashingCompleteTime: " + WashingCompleteDateTime.toString)
  WashingReadyTime.postUpdate(new DateTimeType(WashingCompleteTime.toString))	
end

Since you just want to update the state of the WashingReady item, you would use postUpdate. If there were a binding or rule waiting to act on a command to that item, you would in that case use sendCommand.

Use val instead of var in cases where you are going to set and not change a variable.

2 Likes

Thanks for the detailed reply, I didn’t realise that the items file had that option!
The original post and its subsequent edit disappeared right after I’d posted it so I assumed it had gone.

Related to this, I have a bash script getting a last update date/time from rrdtool which reports ok on the command line with e.g. 12:37
and I have an Items line like this:
DateTime lastUD "Last Update Time was: [%1$tH:%1$tM]" <clock> (HouseTemps) {exec="<[bash@@/usr/share/openhab/lastTime.sh:1200:REGEX((.*?))]"}
but get no displayed result in the browser UI.
https://my.openhab.org/items displayed correct results.
Similar scripts and Items report temperature ok. The system is just not writing the datetime info.
Is it essential that I set up a rule for this and if so can anyone explain why the above does not do the job?

The reason why it’s not working is that the exec binding has a hardcoded list of item types that it supports, and DateTime items are not in the list:

            if (itemType.isAssignableFrom(NumberItem.class)) {
                return DecimalType.valueOf(transformedResponse);
            } else if (itemType.isAssignableFrom(ContactItem.class)) {
                return OpenClosedType.valueOf(transformedResponse);
            } else if (itemType.isAssignableFrom(SwitchItem.class)) {
                return OnOffType.valueOf(transformedResponse);
            } else if (itemType.isAssignableFrom(RollershutterItem.class)) {
                return PercentType.valueOf(transformedResponse);
            } else {
                return StringType.valueOf(transformedResponse);
            }

The binding ought to be improved so that it can update the state of any item type without any hardcoded lists. This is what I did to the MQTT binding in 1.8, so that binding no longer needs to know anything about items, other than the list of data types the item supports.

In the meantime, you could work around the issue by using a String item bound to the exec binding, and a rule that triggers on changed like:

rule WashingReadyDateTimeWorkaround
when
  Item WashingReadyDateTimeString changed
then
  WashingReadyTime.postUpdate(new DateTimeType(WashingReadyTimeString.state.toString))
end

I just opened issue #3823 to track this proposed enhancement.

I opened pull request #3832 that removes the need to create proxy items and rules to work around the hardcoded list of support items in the exec binding. Now, if a command returns a DateTime string, it can go directly to update a DateTime item. Likewise, if a command outputs a latitude,longitude, it can directly update a Location item, etc.

Examples:

Group Test (All)
String ExecString "ExecString [%s]" (Test) { exec="<[echo I am a String:60000:REGEX((.*?))]" }
Number ExecNumber "ExecNumber [%.1f]" (Test) { exec="<[echo -12345.432145663:50000:REGEX((.*?))]" }
Location ExecLocation "ExecLocation [%s]" (Test) { exec="<[echo 52.6406981,-9.503447:40000:REGEX((.*?))]" }
Switch ExecSwitch "ExecSwitch [%s]" (Test) { exec="<[echo ON:30000:REGEX((.*?))]" }
Contact ExecContact "ExecContact [%s]" (Test) { exec="<[echo OPEN:20000:REGEX((.*?))]" }
Rollershutter ExecRollershutter "ExecRollershutter [%d %%]" (Test) { exec="<[echo 60:10000:REGEX((.*?))]" }
Dimmer ExecDimmer "ExecDimmer [%d %%]" (Test) { exec="<[echo 30:70000:REGEX((.*?))]" }
DateTime ExecDateTime "ExecDateTime [%1$tH:%1$tM:%1$tS]" (Test) { exec="<[/tmp/printdate.sh:80000:REGEX((.*?))]" }

/tmp/prindate.sh (in case it matters)

#!/bin/sh
date +%Y-%m-%dT%TZ

If anyone would care to test this change, here is a binding JAR you can use to replace the exec binding JAR you are currently using. Please let me know if it works for you (or not).

Thanks, John

UPDATE: This change is merged to be part of the 1.9 openHAB 1.x addons.

2 Likes

@watou
Thanks so much for your work with this.
The section of my Items file looks like this:
Number YahooWeatherCode “Today’s weather is [MAP(yahoo_weather_code.map):%s]” (weather) { http="<[http://weather.yahooapis.com/forecastrss?w=1103816:3600000:XSLT(yahoo_weather_code.xsl)]"}
Number Weather_Temperature “Outside Temperature [%.1f °C]” (weather) { http="<[http://weather.yahooapis.com/forecastrss?w=1103816&u=c:60000:XSLT(yahoo_weather_temperature.xsl)]" }
Number Weather_FeelsLike “Outside Feels Like [%.1f °C]” (weather) { http="<[http://weather.yahooapis.com/forecastrss?w=1103816&u=c:60000:XSLT(yahoo_weather_feelslike_temp.xsl)]" }
Number Weather_Temp_Max “Todays Maximum [%.1f °C]” (weather) { http="<[http://weather.yahooapis.com/forecastrss?w=1103816&u=c:900000:XSLT(yahoo_weather_forecast_high.xsl)]" }
Number Weather_Temp_Min “Todays Minimum [%.1f °C]” (weather) { http="<[http://weather.yahooapis.com/forecastrss?w=1103816&u=c:900000:XSLT(yahoo_weather_forecast_low.xsl)]" }
DateTime Weather_Sunset “Sunset today at [%1$tH:%1$tM]” (weather) { http="<[http://weather.yahooapis.com/forecastrss?p=1103816:900000:XSLT(yahoo_weather_sunset.xsl)]" }
DateTime Weather_LastUpdate “Last Update [%1$ta %1$tR]”
Number tempODoor “Current outdoor temperature :[%.1f °C]” (Outdoor, HouseTemps) {exec="<[bash@@/usr/share/openhab/tempODoor.sh:1200:REGEX((.?))]"}
Number tempSlab “Current Slab temperature :[%.1f °C]” (HouseTemps) {exec="<[bash@@/usr/share/openhab/tempSlab.sh:1200:REGEX((.
?))]"}
DateTime UpDateTime “Last Update Time was: [%1$tH:%1$tM] " (HouseTemps) {exec=”<[bash@@/usr/share/openhab/lastTime.sh:1200:REGEX((.*?))]"}

but I am getting no response after loading your revised exec .jar as shown:

Showing that both my script data and Yahoo’s sunset time (both DateTime) will not display.
My log file shows an exec error:
2016-01-20 18:26:31.072 [ERROR] [WaveController$ZWaveSendThread] - NODE 3: Timeout while sending message. Requeueing - 2 attempts left!
2016-01-20 18:26:31.078 [ERROR] [b.z.i.p.s.SendDataMessageClass] - NODE 3: Got an error while sending data. Resending message.
2016-01-20 18:27:23.053 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model ‘FrenchSt.items’
2016-01-20 18:27:26.949 [INFO ] [.service.AbstractActiveService] - HTTP Refresh Service has been shut down
2016-01-20 18:27:27.083 [INFO ] [.service.AbstractActiveService] - HTTP Refresh Service has been started
2016-01-20 18:30:00.155 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model ‘FrenchSt.items’
2016-01-20 18:30:03.005 [ERROR] [.service.AbstractActiveService] - Error while executing background thread Exec Refresh Service
2016-01-20 18:35:15.087 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model ‘tempsUpdate.rules’
2016-01-20 18:57:41.765 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model ‘FrenchSt.items’
2016-01-20 18:57:44.257 [INFO ] [.service.AbstractActiveService] - HTTP Refresh Service has been shut down
2016-01-20 18:57:44.274 [ERROR] [.service.AbstractActiveService] - Error while executing background thread Exec Refresh Service
2016-01-20 18:57:44.472 [INFO ] [.service.AbstractActiveService] - HTTP Refresh Service has been started

I probably have a basic error somewhere but have not been able to trace it.

The URL http://weather.yahooapis.com/forecastrss?p=1103816 gives me an error response. Typo?

<rss xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" version="2.0">
<channel>
<title>Yahoo! Weather - Error</title>
<description>Yahoo! Weather Error</description>
<item>
<title>City not found</title>
<description>Invalid Input /forecastrss?p=1103816</description>
</item>
</channel>
</rss>
<!--
 fan1632.sports.bf1.yahoo.com Wed Jan 20 08:10:44 PST 2016 
-->

Assuming you meant http://weather.yahooapis.com/forecastrss?w=1103816, and also assuming that yahoo_weather_sunset.xsl extracts the sunset attribute from <yweather:astronomy sunrise="6:20 am" sunset="8:40 pm"/>, then the issue is this: You have to supply the string version of a DateTimeType as either yyyy-MM-dd'T'HH:mm:ss or yyyy-MM-dd'T'HH:mm:ssz. (See the Java doc about these two format strings.) I don’t know if it’s possible to do this in XSLT, but if it is, it’s probably pretty ugly. The alternative is to again use a proxy item and a rule.

Also, everywhere you have the URL http://weather.yahooapis.com/forecastrss?w=1103816&u=c is another HTTP GET request to Yahoo! You could much decrease the overhead in fetching weather data if you replaced them all with yahooForecast (or the like) and added these lines to openhab.cfg:

http:yahooForecast.url=http://weather.yahooapis.com/forecastrss?w=1103816&u=c
http:yahooForecast.updateInterval=900000

Lastly, I notice you use both http://weather.yahooapis.com/forecastrss?w=1103816 and http://weather.yahooapis.com/forecastrss?w=1103816&u=c. Is this intentional?

Sort of. It was the result of a search while looking for an answer. ?w=1103816 is correct.

Thanks I will have a go at getting this implemented and also the openhab.cfg improvement.

Yes - as I understand it the &u=c calls for units of degrees Celsius so is only required where a temperature is being fetched and not for text info e.g. weather condition.

I have not seen further occurrences of “Error while executing background thread Exec Refresh Service” errors. Do you see any issues that could be causing to DateTime item to not display?

If you could use the same URL for caching by the HTTP binding with the u=c parameter, then openHAB will only be hitting Yahoo! every updateInterval milliseconds.

The only issue I could see was the strong possibility that your XSLT transformation is not returning a full DateTime string, as described above. If you can’t transform the XML input into one of the two accepted formats, you would have to resort to a proxy String item, a rule that took the state of that string item on changed, convert it into the accepted format, and then

Weather_Sunset.postUpdate(new DateTimeType(yourProperlyFormattedStringVar))

Sorry that should have been about the bash script Item from:

There is an issue in openHAB 1.8.0 (and possibly earlier versions, not sure) where the startup script will change the permissions of files in various openHAB directories, including removing the execute permission bit. I’m hoping it will be fixed in 1.8.1. @rlkoshak has a workaround he recently shared in the meantime in another forum topic. If you try to run /usr/share/openhab/lastTime.sh from a prompt as the same user that’s running the openHAB server, does it print out a DateTime string in the proper format?

Also, do you really want to run that script every 1.2 seconds?

I run openhab service as root user with sudo service openhab start.
Then
bash /usr/share/openhab/lastTime.sh
21:38
sudo bash /usr/share/openhab/lastTime.sh
21:38

Actually 1200 seconds will do.

My updated XSLT got as far as:

        <xsl:variable name="sunsT" select="'//yweather:astronomy/@sunset'" />
        </xsl:variable>

        <xsl:template match="/">
                <xsl:value-of select="format-dateTime($sunsT, '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]')" />
        </xsl:template>

but without success so far. Throws an exception.

The script would have to output the full date and time in one of the two supported formats – it’s the only way to populate a DateTime item.

According the wiki page for the Exec binding, the refresh interval is expressed in milliseconds, not seconds!

You might want to experiment with some online XSLT tester to confirm the proper XSLT transformation output.

I want to add a transform tester to the Paper UI in openHAB 2.0, so users have a single place to go to ensure their transforms work as expected.

Sir, you are a gentleman and a scholar. Looking nice, thank you.
Script now includes: rrdtool last /home/robspi/temps.rrd | xargs | awk '{print strftime("%Y-%m-%d'T'%H:%M:%S", $0)}' to achieve the desired HH:MM format.

I will go off and do some more work on my XSLT

1 Like

That work around is here.

It involves moving away from the exec binding and instead using a rule and exectuteCommandLine. In the rule I reset the permissions of needed files before executing the main script.

1 Like

Returning to this:

None of the on-line XSLT testers I tried could resolve the syntax so went back to Exec binding approach with this as my Items line:
String Weather_Sunset "Sunset today at " <clock> (weather) { exec="<[bash@@/home/robspi/sunsetTime.sh:120000:REGEX((.*?))]"}
and the script containing:
curl -s http://weather.yahooapis.com/forecastrss?w=1103816 |grep astronomy| awk -F\" '{print $4 ,$5 + "%Y-%m-%d'T'%H:%M:%S" }' | sed 's/..$//'

since
curl -s http://weather.yahooapis.com/forecastrss?w=1103816 |grep astronomy
returns:
<yweather:astronomy sunrise="6:24 am" sunset="8:38 pm"/>
But OH does not display the result whether the Item is a String or DateTime (which I did not expect would work). No errors in the log but no display either.

In this item, you need a [%s] placeholder at the end of the item’s label for it to show the state of the item.

And it works. Must have missed this in the documentation. Hope all of my q’s and your prompt answers prove to be helpful for some others as well. Thnks.

1 Like