I have a device I integrated with a marketplace OH3.0 BACNet binding that seems to have disappeared for OH5. In the interest of supportability I’m switching to a ModBus binding since the controller also supports ModBus.
Question is the temperatures I get off the ModBus controller have some jitter I can’t smooth out in the controller. Few tenths of a degree for each sample. Temps are reported in millidegrees F in a uint32. Would be great to see an example of how to use a persistence service in a transformation to do a moving average. My guess is 20 or 30 samples would be about the right run length.
Also, get a mysterious issue with transforms.
Inline this works fine: JS(| Math.round(input / 1000))
However as a transformation script saved as tjs.js
“Channel number will not be updated since transformation was unsuccessful. Channel is expecting the following data types [DecimalType, QuantityType, UnDefType]. Input data: number value 82280 (value type ‘uint32’ taken into account) and bool value true. Transformation: org.openhab.binding.modbus.internal.ModbusTransformation@435399b6”
A solution could be to make a second item to store the low pass filtered value. Any updates to the MODBUS linked item could trigger a script (thinking JS script) where you can do the transformation with much more flexibility.
Also importantly it has a private/public cache to store values between runs of the script, which is needed for any rolling average.
Thanks! I completely agree gain-offset is a cleaner way to convert millidegrees to degrees.
What I’m looking for is a way to wrap a moving average around the value in the item. Currently I’m polling every 500msec to get reasonably fast updates. Just slowing down the sample rate won’t fix the problem because the device seems to be sending me a +/-100 millidegree random walk around the true value. Could be noise on the thermistor line, but doesn’t matter if I can low pass filter it in software.
A 5 or 10 second moving average would be ideal. Just looking for an example of how to use the persistence service in Javascript for the Item.
And why I get a type mismatch error when I invoke a script explicitly but not for inline.
Querying persistence is expensive. I very much doubt this could keep up with a half second polling period. You will probably want to use InMemory - Persistence Services | openHAB for this or store the data in the cache. You don’t want to be dependent on a file i/o operation for this.
It’s all in RAM so it might take up a little less RAM. But the difference will be mostly unmeasurable.
Don’t worry about those sorts of things until you know you get it working with the defaults and you can demonstrate there is a problem. Otherwise you are adding complexity for no reason.
Did you try @Alien’s suggestion? The input passed into a transformation is always a String. If you want to do math with it, you have to convert it to a number first.
Channel number will not be updated since transformation was unsuccessful. Channel is expecting the following data types [DecimalType, QuantityType, UnDefType]. Input data: number value 82280 (value type ‘uint32’ taken into account) and bool value true. Transformation: org.openhab.binding.modbus.internal.ModbusTransformation@2053c806
I tried stripping the transform down to
(function(data) {
return data;
})(input)
and get the same error.
In the meantime I reached out to the controller manufacturer who’s giving me some hardware and software support to try to smooth out the numbers before they get to OH.
The most important part of that error you’ve removed from your posting so I guess it’s coming from the binding in which case there really isn’t anything you can do from transformation to fix the error. There’s a problem with the binding and the Channel config.
Hi Asher,
Instead of averaging the measurement, why not round it? Example reading: 156324.
156324/1000=156.324 F it’s enough to round it to 156 F since the decimal values are just noise anyway. The accuracy of the reading depends on the tolerance of the thermistor and the length of the wires, especially if you are using a 0-10V voltage that is not very immune to interference, as well as on the resistance of the wires.
I am rounding to nearest degree F. But if the zone temp is 69.9 then .1 degrees of jitter move back and forth from 69 to 70. The average is helpful to stabilize the values which IRL are changing over minutes, not seconds.
As far as the binding. It’s a Modbus Data Thing. I import the value as a uint32 because that’s what is on the device. The only Item is linked to Value as a Number. The transform is happening in the Thing, not the Item.
It wasn’t clear if I’m misconfiguring something or if the Modbus binding may be sending the wrong type to the Transform. Still interesting that the inline version works while the script invocation does not.
Maybe I’ll have some luck working with the vendor and I have a tech support question into another vendor to see if they agree with one of his hardware suggestions. Unfortunately I can’t change out the thermistor wiring at this point. There’s analog noise somewhere but not easy to troubleshoot the cause.
Not if you are rounding. 69.5 to 70.4 will round to 70. 68.5 to 69.4 will round to 69.
Only if you truncate will it jitter at 69.9 with .1 degree of jitter.
You could still get jitter though if rounding and it’s moving between 69.4 and 69.5. Stuff like that can often smoothed out. For example, you could use the Basic Profiles - Transformation Services | openHAB to only allow states through to the Item that exceeds a given delta from the current state. For example, the new state must be at least .3 different from the current state or else it’s thrown away as noise.
It might be a misconfiguration but it’s important to understand that the value sent to a transformation is always a String and what the transformation returns is always a String. So it’s not a problem with the transformation. It seems like it’s more to do with the Item type or something internal to the binding. Without the name of the logger telling us where the error is coming from .
Are you just trying to type it in on that line? You can’t do that. You need to create a transformation under Settings → Transformations. You put the code in there and give it a name. Once saved, then you invoke the transformation using
JS(config:js:nameOfTransformation)
Or you put the code in a file under $OH_CONF/transformations and you’d use:
JS(nameOfFile)
When getting help for something like this, it is really helpful if you post too much information instead of limiting what you post or redacting it. In this case, if you have attempted to use the above transformation and when it didn’t work actually posted what you attempted (e.g. click on the code tab of your Thing and paste the full configuration here) it would have saved a whole lot of time.
A version directly as an ecma profile without persistence or cache. Just play with the parameters (the sum must be 10) to get the desired smoothing. Here it mixes 90% old with 10% new.
I tried changing the Modbus thing from uint32 to int32 and the error code changed to reflect the int32 type. So I wonder if the Modbus binding is not converting the type to string before it invokes the transform?