String formatting

Hello
I am struggling with the formatting of a parameter to be passed to a bash script.

the script needs 2 parameters in the following format:
tt hh:mm:ss

where tt is a temperature setpoint (0-40) and is contained in a Item of type Number
hh
mm
ss

are respectively hours, minutes and secods again contained in number items.

the problem I have is padding them with o when less then 10.

That is
8 9:30:00
should be output to the bash as
08 09:30:00

Any help is appreciated… after that my OpenHab Heatmiser thermostats setup is almost ready for sharing.

TX

I THINK the following will work. I don’t know if you need the “$” characters or not.

val outStr = String::format("%1$02d %2$02d:%3$02d:%4$02d",
                                       (MySetpoint.state as DecimalType).intValue,
                                       (MyHours.state as DecimalType).intValue,
                                       (MyMinutes.state as DecimalType).intValue,
                                       (MySeconds.state as DecimalType).intValue)

I’ve made up the names of your Items above of course.

What this does is create a formatted String using the Java format syntax. You should have at least a passing familiarity with this as it is the same syntax used to format Item’s labels in the Sitemap and Items files (the stuff in the [ ]).

So the above String breaks down as follows:

%1 -> The first argument
$ -> Start of the formatting string that will apply to the %1
0 -> zero pad numbers that are smaller than the number of digits specified
2 -> always print at least two digits
d -> treat the value as a integer

So %1$02d means treat the first argument as an integer, print two digits and if the number is less than ten zero pad it so it is two digits. So %2$02d means do the same thing but with the second argument, and so on.

The syntax is documented here, but it is quite extensive and difficult to read if you are in a hurry.

6 Likes

thanks .
I will try and adapt the cody asap…
was trying:

format("$1tH $2tH:$3tM:00", HW_WWDTemp.state, HW_WWDHour.state, HW_WWDMinute.state )

after reading some java docs…

yep now reading. very similar. tx tx tx

Uhm…
this is the snippet of the rule with your suggestion:
rule “Change Schedule”
when
Item HW_WWDTemp changed
or Item HW_WWDHour changed
or Item HW_WWDMinute changed
or Item HW_LWDTemp changed
or Item HW_LWDHour changed
or Item HW_LWDMinute changed
or Item HW_RWDTemp changed
or Item HW_RWDHour changed
or Item HW_RWDMinute changed
or Item HW_SWDTemp changed
or Item HW_SWDHour changed
or Item HW_SWDMinute changed
or Item HW_WWETemp changed
or Item HW_WWEHour changed
or Item HW_WWEMinute changed
or Item HW_SWETemp changed
or Item HW_SWEHour changed
or Item HW_SWEMinute changed
then
lock1.lock()
try {

logInfo("Heatmiser", "Schedule change intercepted" )
val outStr = String::format("%1$02d%@@%2$02d:%3$02d:00",
                                   (HW_WWDTemp.state as DecimalType).intValue,
                                   (HW_WWDHour.state as DecimalType).intValue,
                                   (HW_WWDMinute.state as DecimalType).intValue)
logInfo("Heatmiser", "Schedule change evaluated" + outStr)

// var s = “/home/pi/heatmiser-wifi-read-only/openhabscripts/hw_settemp.sh@@”+HW_SetTemperature.state
// executeCommandLine(s)
logInfo(“Heatmiser”, “Schedule change executed”)
}
} finally {
// release the lock - we are ready to process the next event
logInfo(“Heatmiser”, “Schedule changed”)
lock1.unlock()
}
end

If I look at the log after a change in one of the widget of the clause is touched
2016-01-05 00:16:31.455 [INFO ] [openhab.model.script.Heatmiser] - Schedule change intercepted
2016-01-05 00:16:31.465 [INFO ] [openhab.model.script.Heatmiser] - Schedule changed
2016-01-05 00:17:14.834 [INFO ] [openhab.model.script.Heatmiser] - Schedule change intercepted
2016-01-05 00:17:14.846 [INFO ] [openhab.model.script.Heatmiser] - Schedule changed

I see I jump from the watchpont " Schedule Change Intercepted"
directly to the “Schedule Changed”

That is the expression is not evaluated or possibly is throwing some exception (due to the values?) that is however not output to the log.

the items definition are the following:

Number HW_WWDTemp
Number HW_WWDHour
Number HW_WWDMinute

the seconds are fixed to 00 as we are not programming F1 Racing cars :wink:

It is almost certainly throwing an exception. Add a catch(Throwable t) { } clause to the mix and print out the exception to see what it doesn’t like.

Like I mentioned, it may not need the '$'s, or it could be something else entirely. Hopefully the exception will give a clue. From reading the docs it does look like format() will throw an exception at the slightest provocation.

You have to be sure that HW_WWDTemp, HW_WWDHour and HW_WWDTempMinute items currently hold DecimalType states. Could you try something like

logInfo("Heatmiser", "Schedule change intercepted" )
val int temp   = if (HW_WWDTemp.state instanceof DecimalType) (HW_WWDTemp.state as DecimalType).intValue else 0
val int hour   = if (HW_WWDHour.state instanceof DecimalType) (HW_WWDHour.state as DecimalType).intValue else 0
val int minute = if (HW_WWDMinute.state instanceof DecimalType) (HW_WWDMinute.state as DecimalType).intValue) else 0
val outStr = String::format("%1$02d@@%2$02d:%3$02d:00", temp, hour, minute)
logInfo("Heatmiser", "Schedule change evaluated" + outStr)
1 Like

Thanks for the suggestion.

Very “clean” I will adopt it.

I am pretty sure the items contain values at the moment of execution of the rule (I see it in the log) but I will include the code in the widget update section of the rules and in the update on modify section:

currently I run the widget update at startup (event system startup) and every 5 minutes via cron event.
Nonethless I rely on the fact that rule ran at startup and that it ran succesfullly but… you never know.

slowly getting to the target… thanks all