Number:Time UoM formatting question

Background: I am using the System binding to monitor its uptime, via its cpu#uptime channel which returns a value in minutes.

So I declare my Item with a UoM format string [%.0f min] as shown below…

Number:Time System_CPU_Uptime "System CPU Uptime [%.0f min]" <time> {channel="systeminfo:computer:xxxx:cpu#uptime"}

And I declare my Sitemap entry with a UoM format string [%.0f h] as shown below…

Text item=System_CPU_Uptime label="System CPU Uptime [%.1f h]"

And indeed these two UoM format strings result in a read value of (say) “90 min” being displayed as “1.5 h” fully as one would expect.

Question: what is the correct UoM format string for the Sitemap entry to display (say) “90 min” as “1:30” instead of “1.5 h” ??

Use DateTime formatting strings. For example the runtime of my UPS is formatted as %1$tH:%1$tM:%1$tS which is currently showing

1 Like

@rlkoshak many thanks for this. I suppose I could wait 24 hours, but let me ask you this anyway now: do you know what happens when the hours roll over 24h, and how I would capture the days in the format string. AFAIK for DateTime’s the days would be a day of month rather than an elapsed total number of days. Or??

I don’t know because I’ve not had a Number:time that big. I look forward to finding out from you tomorrow what happens. :wink:

For the days, I’d use %1tj which gives you the day of the year. But that’s assuming that the hours > 24 doesn’t work and it wraps back to 0. If it doesn’t it probably doesn’t matter and %1td will probable work. If we have to use day of year and you need more than 365 days you’ll probably need a rule or JS transform to handle.

I’m not sure what code handles this the value is not a DateTime so it might be smart enough to handle it properly.

1 Like

Thanks again Rich. I will get back to you in one day…

Just to report back: It seems that %1$tH does wrap at 24hours, and nominally %1%tj seems to work(ish) but oddly it was showing 0 days yesterday, and it shows 2 days today (see below). I’m not sure if this is a problem in the raw data from the System binding (or from my CPU clock), or if it is a problem in the format string. I will explore further, and report back again.

1 Like

^
The raw value returned from the System binding is 1673 minutes which is a little over 27 hours. So evidently the format string is wrong to show 2 days and 3 hours. Is this a bug, or am I missing something?

Remember that you are (ab)using date-time formats. $tj is ‘day of year’, isn’t it? First day of year is 1, so <24hrs is day one. These are not duration or elapsed time formats. Clock hours and minutes begin at 00, but dates begin at 1.

So why was it showing day 0 yesterday (less than 24 hours elapsed) and day 2 today (27 hours elapsed)?

Set your root value back to what it was, and find out. This just isn’t going to do what you want.

Sorry but I don’t understand what you are suggesting here?

Set your Item value to 999 minutes, see what day value you get.

You are right, it shows 1 day.

1 Like

I think a little transform for your display is going to be the best bet.
Knew I’d poked around this before -

Thanks @rossko57 you are right. However in the meantime I had written my own transform below.

Notes:

  • The Item definition casts the Channel’s Number:Time value to a String (%s)
  • The transformation script casts it back to a DateTime
  • And the script also has to scale the value /1000 (I am not sure why…)

Item

String System_CPU_Uptime "System CPU Uptime [JS(uptime.js):%s]" <time> {channel="systeminfo:computer:g24:cpu#uptime"}

uptime.js

(function(dateTimeString) {
    var mins = Date.parse(dateTimeString)/1000;
    var days = Math.floor(mins / (24 * 60));
    mins = mins % (24 * 60);
    var hours = Math.floor(mins / 60);
    mins = mins % 60;
    return days + "d, " + hours + "h, " +  mins + "m";
})(input)    

I think that’s why, you’re getting some default effect in milliseconds but it will be going all wrong because it ignores the supplied ‘mins’ unit without a real Quantity type involved…

Err. Not really. It is even odder than that…

I did some debugging and I can see the following…

  • The transform is called with a proper date argument string (e.g. “1970-01-01T01:03:18+01:00”) – which is indeed the actual uptime 3 hours 18 minutes (aka 198 minutes) since the machine was powered on.

  • The val mins = Date.parse(dateTimeString)/1000 statement produces a value (e.g. 198) – which is identical to the actual uptime – in minutes!!

  • The function returns a string (e.g. “0d, 3h, 18m”) which is also identical to the actual uptime.

So it seems that openHAB itself is behaving as it is supposed to, and that the error is actually in the JavaScript Date.parse() function; which actually returns a result in milli-minutes instead of milli-seconds – contrary to what is written in that function’s documentation.

=> So I wonder if openHAB is using a “funky” JavaScript interpreter of some sort?

PS in case it might be relevant, my system is running on Raspbian

If your binding channel is really of number:time type I would be very suspicious of what happens when you link it to a String type Item. Clearly the channel should not be sending “1970-01-01T01:03:18+01:00” to the Item (what would be the meaning of +01:00 in a duration) and I suspect the framework is messing up when mis-matching types.
Not so much a bug as a misconfiguration.

It’s been seen before that a hopeless channel-Item mismatch can result in unexpected datetime looking results, with no time involved. I expect its just the last action in a list of possible intternal transforms.

You are right.

Indeed. That string is completely munged; the correct string is 1970-01-01T03:18:00. (I forgive Date.parse() for choking on such a munged string). But IMHO if the framework can’t deliver a valid DateTime string, it should certainly not send a munged string; it should ideally send something valid, but otherwise it should send nothing at all. (Perhaps I will fix the code and raise a PR accordingly…)


Below is my second attempt at an Item definition and matching JavaScript transform: this (also) produces the correct display – without the ‘benefit’ of having one bug coincidentally correct another.

Item

Number:Time System_CPU_Uptime "System CPU Uptime [JS(24g-uptime.js):%d]" <time> {channel="systeminfo:computer:g24:cpu#uptime"}

uptime.js

(function(mins) {
    var days = Math.floor(mins / (24 * 60));
    mins = mins % (24 * 60);
    var hours = Math.floor(mins / 60);
    mins = mins % 60;
    return days + "d, " + hours + "h, " +  mins + "m";
})(input)    

Need to take a bit of care - it could be perfectly viable to send from number:time type channel to a String type Item … with an appropriate transform profile. The channel should not block this.