Help with modbus binding and transformation

Hello,

Yes, I can read multiple uint16, then extract lo and hi, and then create multiple rules… but Now I have idea, and maybe it’s works.
I can read one single uint64. in this uint64 I can work only as a string, because Number format truncate it. in uint64 I receive a string: “3969090754143982356”

" 3969090754143982356" = 37:15:0B:03:02:0A:13:14‬ = sec, min, hour, dayofweek, day, month, yearlo, yearhi

I found some github function: https://github.com/peterolson/BigInteger.js

my task is from uint64 use javascript and transform to datetime

Ed

That’s interesting, it would be nice to see an example. It’s my understanding that the Number type used in openHAB internally holds numbers as Java BigDecimal types - and that should be expandable to any precision in theory.
Some part of openHAB framework may limit it.

Carry on. The binding provides all the tools to read a collection of bytes, but of course you do not have to use those and could do something different.

You could implement all or part in a JS transform at the channel. I think I’d probably do that in two parts - one JS to get date from two registers, one to get time from the other two.

It’s worth reminding that there is no such thing as 64-bit or even bytes at the Modbus protocol level. Everything is handled as 16-bit registers, and how we choose to use or arrange those is up to us.

Hello,

seems my idea works. I use function from https://github.com/peterolson/BigInteger.js
and then my transformation looks like:
(function(inputData) {
var str = decToHex(inputData);
var year = parseInt(str.slice(-2), 16)*100+parseInt(str.slice(-4, -2), 16);
var month = parseInt(str.slice(-6, -4), 16) - 1;
var day = parseInt(str.slice(-8, -6), 16);
var hours = parseInt(str.slice(-12, -10), 16);
var minutes = parseInt(str.slice(-14, -12), 16);
var seconds = parseInt(str.slice(0, -14), 16);
var d = new Date(year, month, day, hours, minutes, seconds)
return d;
})(input)

If I retrieve this item as a string, I see correct time. but I return datetime as a return. How I can get item as a Datetime? where is my mistake???

DateTime reg40037 “Actual Date [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS]” { channel=“modbus:data:id2:poolpoll:reg40037:datetime” }

Ed

Everything the JS transform returns to the channel is actually presented as a string behind the scenes. The framework then parses this into something that “fits” the channel/Item type, in this case an openHAB datetime.

Javascript’s idea of a Date is not the same as openHAB’s Datetime.
For a first attempt, I’d try returning the JS myDate.toString()
You might need to play with formatting though.

EDIT - this looks useful, myDate.toISOString() for ISO-8601 text

Hello,

Does not help me :(…

Ed

Why, what happens? This is like getting blood out of a stone.

Hello,

nothing happens. when I try to declare item as a datetime, I see “-”

Try to learn, how I can return datetime format to item from transformation, and can’t find solution yet.

example:
JS transformation return for me “return new date()”

I want to see it as a datetime in items. I can see it as a string, but not as a datetime.

Ed

Ed

So you didn’t try
return d.toISOString()
?

Yes,

when I convert it toISOString, then I see item as a string:
String reg40037 “Actual Date” { channel=“modbus:data:id2:poolpoll:reg40037:string” } returns to me “2019-10-09T12:24:36.000Z”
Then I change to datetime:
DateTime reg40037 “Actual Date” { channel=“modbus:data:id2:poolpoll:reg40037:dateTime” returns for me “-”

Ed

events.log and openhab.log to go with that, please?

You can create two Items at the same time (different names), one string and one datetime, to link to the same modbus data Thing via appropriate channels to get a good view of what is going on.

strange,

when I change in items to : “modbus:data:id2:poolpoll:reg40037:datetime”, lowercase, now it’s shows me a date. thanks for help

Ed

Hello,

Maybe you also have experience with TimeZones.

(function(inputData) {
var str = decToHex(inputData);
var year = parseInt(str.slice(-2), 16)*100+parseInt(str.slice(-4, -2), 16);
var month = parseInt(str.slice(-6, -4), 16) - 1;
var day = parseInt(str.slice(-8, -6), 16);
var hours = parseInt(str.slice(-12, -10), 16);
var minutes = parseInt(str.slice(-14, -12), 16);
var seconds = parseInt(str.slice(0, -14), 16);
var d = new Date(year, month, day, hours, minutes, seconds);
return d.toISOString();
})(input)

My hours now set to 15, but I see them in returned datetime as 12. Seems because my current timezone is +3:00…

P.S. I also make a test:
var d = new Date();
return d.toISOString();
Ed

And I also see the current time in UTC.
how I can add my current timezone? I setup my timezone in system settings.

when I see logs. my NTP server return datetime in local timezone, but toISOString returns in UTC
2019-10-09 20:12:39.787 [vent.ItemStateChangedEvent] - reg40037 changed from 2019-10-09T17:12:12.000+0000 to 2019-10-09T17:12:13.000+0000
2019-10-09 20:12:39.907 [vent.ItemStateChangedEvent] - CurrentTime changed from 2019-10-09T20:12:38.905+0300 to 2019-10-09T20:12:39.906+0300

Ed

Well, we do have to get the syntax correct. I’d missed dateTime for datetime.

No idea. This is what the Z in your ISO date is about.

A moments googling for “javascript timezone” suggests javascript timezone support is bit inconsistent.
That doesn’t really matter here - I guess what you really want is to pass the reported datetime from the modbus device into an openHAB Item without anyone interfering with it.
The Z at the end of your current ISO date indicates UTC, so openHAB is taking what says it is a UTC time and converting it to your local zone.

Really, javascript ought to replace the Z with your local zone, but we cannot fix that.

You could just do string replace of Z with your local offset +0300
but that’s bit rubbish, what happens if you move or with summer time etc.

However, I think you can simply remove the Z and the openHAB parser will assume a datetime in openHAB’s current local timezone (i.e. it doesn’t matter what javascript thinks the timezone is)

Hello,

Remove “Z” does not help :).
I try to check NTP binding sources. they use
SimpleDateFormat for time formating.

Ed

Well, what are you going to do next?

EDIT - what is it you are trying to achieve?

Here’s how it works (OH2.4)
Example Items

DateTime testDate1 "my datetime1 [%1$tR]"
DateTime testDate2 "my datetime2 [%1$tR]"
DateTime testDate3 "my datetime3 [%1$tR]"

Example rule, ISO strings to DateTime Items

	testDate1.postUpdate("2019-10-09T12:24:36.000Z")
	Thread::sleep(500)
	testDate2.postUpdate("2019-10-09T12:24:36.000")
	Thread::sleep(500)
	testDate3.postUpdate("2019-10-09T12:24:36.000+0300")

events log

2019-10-14 22:26:12.957 [vent.ItemStateChangedEvent] - testDate1 changed from NULL to 2019-10-09T12:24:36.000+0000
2019-10-14 22:26:13.440 [vent.ItemStateChangedEvent] - testDate2 changed from NULL to 2019-10-09T12:24:36.000+0100
2019-10-14 22:26:13.939 [vent.ItemStateChangedEvent] - testDate3 changed from NULL to 2019-10-09T12:24:36.000+0300

So, the given ISO date string is stored together with whatever timezone we give.
But - it does not adjust the stored time with that timezone as it is parsed.

Z means “zero”, UTC (Item 1)
My timezone is currently +0100, and given no timezone in the input string it defaults to this (Item 2).
If a timezone is specified, that gets stored (Item 3)

Displaying these Items on a sitemap gives them ALL as 12:24, that is to say the timezone is not taken into account by the display format.
But - bear in mind this in OH2.4

There has been changes since then


So far as I can tell, that change means that the sitemap display of a DateTime WILL now take the stored timezone into account.


So, what should you do? Depends what you want.
I will guess that -
a) You are getting a datetime via Modbus with NO timezone info
b) You would like to store this as though it were in the same timezone as your openHAB system.

This should be simple enough - get your javascript to return an ISO date string WITHOUT the Z on the end.