Bacnet binding question

Hello,

I am using the Bacnet binding to read values from and control a few specific devices a on network with a large number of Bacnet devices.

My problem is that device detection appears to be inconsistent. Some devices come up on device detection (when OH is booted up) and the next time OH comes up they don’t show up (even though I can see them in Yabe). Devices not discovered by the binding cannot be controlled as items unfortunately.

Using Yabe, they come up consistently only when I use the ‘Bacnet/Ethernet’ method for discovery (as opposed to ‘Bacnet/IP over UDP’) which gives similar results to the Bacnet binding (i.e. inconsistent discovery). So I know this is not a problem with the devices being offline. I have also increased the discovery timeout, but still no luck.

I have 2 questions :

1- If I know the device mac address and network number (data from Yabe), can I somehow add it manually to the list of devices the binding has ‘discovered’ so they can be interacted with on OH ?

2- Or alternatively, is there a way to force detection in the binding using Ethernet rather than IP/UDP ?

@splatch - I know you are probably the only person who can answer this question :wink:… Hopefully it can benefit others as well.

Thanks !

PL

Hey Pierre,
It’s great that bacnet binding gets some industrial users. :slight_smile:

Device discovery works with UDP and it is not reliable per say. With earlier versions of bacnet4j I observed that sometimes even my micro network with just one device didn’t show up properly (with 5s limit for discovery). I’m not sure if it was transport failure alone or it was connected with some flaw in bacnet4j.

Binding is currently done in very basic mode, in order to send messages device must be discovered to translate its identifier to address. This makes usage and configuration easier, but its definitely less reliable than expected. While I was learning bacnet specification I found this assumption wrong. You might not know but first version of binding you are using is build by learning reading code. With next major release of bacnet4j wrapper I would like to get it fixed so you could use either deviceId and rely on discovery or enter device address directly. With that option you will be able to get stable results regardless of network occupancy.

For now I can try to update bacnet4j version in wrapper because it was moved ahead. Version currently used in binding is 3.2.4. I think by moving to 4.1.5 we can get some additional fixes from which binding will benefit. I should be able to produce new build for you somewhere in early/mid next week.

On OpenHab side changing configuration to support device address is not an issue, but pushing it over, down to bacnet4j is another story. As client wrapper was intended to cut off as much as possible of bacnet it hides most of the details. I gonna take a look if its possible without breaking too many things at the same time.

Ethernet transport as far I see is still not supported by bacnet4j. Options we have is ip, ipv6 (both bound to udp) and mstp for serial connections. The last one is supported in 3.2.4, but I couldn’t find a working “bootstrap code” to add support for it via wrapper.

Cheers,
Lukasz

Thanks for the quick (and detailed) reply !

I think your idea of having the ability to specify device address (in addition to relying on discovery) is the best long term solution. It would give both ease of use (for simple bacnet implementations) and flexibility (needed for more complex installs).

I’ll give your new build with updated bacnet4j a try once you release it. I am not too optimistic though given the inconsistent discovery I also get with other tools like Yabe and Cimetrics.

Thanks again for your response on this and let me know if you need any help with logs/data/test cases to vet this out.

PL

Hi @splatch,

I see you have been updating the wrapper code (thanks for that work btw). Do you have an idea if you will be able to implement the option to use device address directly ?

Cheers !

PL

I’m on my way to do update in binding for OH 1.x over next couple of days.

I am considering also revamp for OH 2.x even just to to fetch data from BACnet devices, but I can’t promise anything on this part.

Kind regards,
Lukasz

A new release with all necessary changes is published: https://github.com/openhab/org.openhab.binding.bacnet/releases

Please test and let me know if new functionality works as expected. New option is described in README file on github.

Cheers & Enjoy,
Łukasz

Hi @splatch,

thanks so much for the new version. I tried it out today and I am getting an error. Here is my new item description :

Number	meter_1		"Meter [%.0f kWh]"	(gMeters)	{bacnet="device=60000,type=analogValue,id=10196,address=0.64.174.3:12098"}

After the binding completes startup and discovery (without finding this device), I get the following error in the logs when OH attempts to read the Property value :

2018-12-29 15:17:46.937 [WARN ] [cnet.internal.queue.ReadPropertyTask] - Could not set read property Property[60000.ANALOG_VALUE.10196]

org.code_house.bacnet4j.wrapper.api.BacNetClientException: Could not get property value

	at org.code_house.bacnet4j.wrapper.ip.BacNetIpClient.getPropertyValue(BacNetIpClient.java:182) [206:org.openhab.binding.bacnet:1.13.0.201812290105]

	at org.openhab.binding.bacnet.internal.queue.ReadPropertyTask.run(ReadPropertyTask.java:49) [206:org.openhab.binding.bacnet:1.13.0.201812290105]

	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]

	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:?]

	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:?]

	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:?]

	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]

	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]

	at java.lang.Thread.run(Thread.java:748) [?:?]

Caused by: com.serotonin.bacnet4j.exception.BACnetException: java.io.IOException: Invalid argument (sendto failed)

	at com.serotonin.bacnet4j.transport.ServiceFutureImpl.result(ServiceFutureImpl.java:79) ~[?:?]

	at com.serotonin.bacnet4j.transport.ServiceFutureImpl.get(ServiceFutureImpl.java:64) ~[?:?]

	at org.code_house.bacnet4j.wrapper.ip.BacNetIpClient.getPropertyValue(BacNetIpClient.java:178) ~[?:?]

	... 8 more

Caused by: com.serotonin.bacnet4j.exception.BACnetException: java.io.IOException: Invalid argument (sendto failed)

	at com.serotonin.bacnet4j.npdu.ip.IpNetwork.sendPacket(IpNetwork.java:315) ~[?:?]

	at com.serotonin.bacnet4j.npdu.ip.IpNetwork.sendNPDU(IpNetwork.java:306) ~[?:?]

	at com.serotonin.bacnet4j.npdu.Network.sendAPDU(Network.java:118) ~[?:?]

	at com.serotonin.bacnet4j.transport.DefaultTransport.sendForResponse(DefaultTransport.java:991) ~[?:?]

	at com.serotonin.bacnet4j.transport.DefaultTransport$OutgoingConfirmed.sendImpl(DefaultTransport.java:405) ~[?:?]

	at com.serotonin.bacnet4j.transport.DefaultTransport$Outgoing.send(DefaultTransport.java:336) ~[?:?]

	at com.serotonin.bacnet4j.transport.DefaultTransport.run(DefaultTransport.java:486) ~[?:?]

	... 1 more

Caused by: java.io.IOException: Invalid argument (sendto failed)

	at java.net.PlainDatagramSocketImpl.send(Native Method) ~[?:?]

	at java.net.DatagramSocket.send(DatagramSocket.java:693) ~[?:?]

	at com.serotonin.bacnet4j.npdu.ip.IpNetwork.sendPacket(IpNetwork.java:312) ~[?:?]

	at com.serotonin.bacnet4j.npdu.ip.IpNetwork.sendNPDU(IpNetwork.java:306) ~[?:?]

	at com.serotonin.bacnet4j.npdu.Network.sendAPDU(Network.java:118) ~[?:?]

	at com.serotonin.bacnet4j.transport.DefaultTransport.sendForResponse(DefaultTransport.java:991) ~[?:?]

	at com.serotonin.bacnet4j.transport.DefaultTransport$OutgoingConfirmed.sendImpl(DefaultTransport.java:405) ~[?:?]

	at com.serotonin.bacnet4j.transport.DefaultTransport$Outgoing.send(DefaultTransport.java:336) ~[?:?]

	at com.serotonin.bacnet4j.transport.DefaultTransport.run(DefaultTransport.java:486) ~[?:?]

	... 1 more

Any ideas ? I also tried adding in the network number and it does not work either.

PL

Thanks for report. I will take a look on it.

Hey @splatch,

I did some further testing and was able to make it work. I somehow had to uninstall the binding, clean OH cache and reinstall after and now it works !

I tested priority writing and that works as well. I will test further and let you know if I find issues.

Thanks again !

PL

1 Like

Hello @splatch,

everything tested out fine. The only thing that I could not do (and this may just be another enhancement) is to relinquish the priority set in the priority array. The use case is there is some controller logic setting the value most of the time at priority level 8. I want to override that on a temporary basis by setting a value at priority level 1 but then be able to relinquish the priority set at level 1 so that the controller logic takes over.

I tried passing null (but that is not supported by openhab - at least for number items) and passing ‘UNDEF’, though supported by OH, does not remove the value either.

Let me know if this makes any sense…

Thanks again for all your work on this !

PL

There is definitely a gap in binding as it does not handle writing of UNDEF and Null values. What you describe seems to be a valid use case. I will provide an updated version of binding with support for these.

Cheers,
Łukasz

1 Like

Thanks. I think this is not quite passing a NULL value for the item but using passing a

com.serotonin.bacnet4j.type.primitive.Null 

instance as property value at the set priority level

Hello @splatch

I entered an issue in the github page for the bacnet binding so you have a ‘formal’ tracking entry for this. No rush on the request, obviously, just wanted to put it in the right place.

Thanks again !

PL

I’ve added support for null values. Please build & test new version of code.

BR,
Łukasz

Hi @splatch

I tried the new code and ran into some issues :

1- Null can only be sent to string items in OH (so need to change number items to string - which is not too much of an issue)

2- once the item is converted to string, I get this error when issuing NULL :

2019-01-08 21:23:55.779 [ERROR] [net.internal.queue.WritePropertyTask] - Unexpected error while setting value NULL for property Property[61001.ANALOG_OUTPUT.101]
java.lang.IllegalArgumentException: Could not parse number value out of string NULL. Make sure value is parsable float
	at org.openhab.binding.bacnet.internal.BacNetValueConverter.encodeFloat(BacNetValueConverter.java:146) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.openhab.binding.bacnet.internal.BacNetValueConverter.openHabTypeToBacNetValue(BacNetValueConverter.java:123) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.openhab.binding.bacnet.internal.BacNetBinding$2.toBacNet(BacNetBinding.java:127) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.openhab.binding.bacnet.internal.BacNetBinding$2.toBacNet(BacNetBinding.java:1) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.code_house.bacnet4j.wrapper.ip.BacNetIpClient.getBacNetValue(BacNetIpClient.java:226) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.code_house.bacnet4j.wrapper.ip.BacNetIpClient.setPropertyValue(BacNetIpClient.java:241) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.openhab.binding.bacnet.internal.queue.WritePropertyTask.run(WritePropertyTask.java:62) [191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]

Am I missing something ?

Are you sending UnDefType.NULL or just null value? Second one is still not covered - also “NULL” encoded as string will also not go.

Kind regards,
Lukasz

I was sending ‘null’.

I tried UnDefType.null and got the same error :

java.lang.IllegalArgumentException: Could not parse number value out of string UnDefType.NULL. Make sure value is parsable float
	at org.openhab.binding.bacnet.internal.BacNetValueConverter.encodeFloat(BacNetValueConverter.java:146) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.openhab.binding.bacnet.internal.BacNetValueConverter.openHabTypeToBacNetValue(BacNetValueConverter.java:123) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.openhab.binding.bacnet.internal.BacNetBinding$2.toBacNet(BacNetBinding.java:127) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.openhab.binding.bacnet.internal.BacNetBinding$2.toBacNet(BacNetBinding.java:1) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.code_house.bacnet4j.wrapper.ip.BacNetIpClient.getBacNetValue(BacNetIpClient.java:226) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.code_house.bacnet4j.wrapper.ip.BacNetIpClient.setPropertyValue(BacNetIpClient.java:241) ~[191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at org.openhab.binding.bacnet.internal.queue.WritePropertyTask.run(WritePropertyTask.java:62) [191:org.openhab.binding.bacnet:1.13.0.201901072357]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
	at java.lang.Thread.run(Thread.java:748) [?:?]

Sorry to jump in!
I’m trying to add Bacnet binding to openhab2, but I could not find any complete guide.
Can anyone help me to do it?
What I had done is:
Download bacnet binding from github and change the extension of file from zip to jar
Copy jar file to addons folder
Creating bacnet.cfg file in service folder, based on readme instructions.
Creating .item file based on instructions
But implementing binding is not succeeded.
Your helps and comments is appreciated

Have you enabled the 1.x compatibility layer ? Instructions are here : https://www.openhab.org/docs/developer/legacy/compatibilitylayer.html

Let us know how it works out

FYI, I’ve been working on new version of binding last week. It works under OH 2.5. I am done with initial tests (including also some real life equipment) and it looks good:

I still have a lot of work left to do as binding supports currently only retrieval of present value in polling mode. I need to stabilize it a bit before publishing.

Cheers & stay tuned!
Łukasz

1 Like