[co7io] BACnet v2 binding for openHAB 2.x

Hi @splatch,

this is great ! I tried to install the binding, but must be doing something wrong. I copied the file in the addons folder and restarted the openhab2 service but I cannot find the binding in PaperUI and do not see it if I run the bundle:list command. Do I need to uninstall the old 1.13 binding ?

Hey Pierre,
There is no need to uninstall old binding. All you need is to drop KAR file to /usr/share/openhab2/addons, wait a bit and then go to Paper UI.

If you do not see binding in the UI then there are two diagnostic commands to run:

openhab> kar:list
KAR Name
─────────────────
siemens-2.5.1.M1
bacnet-2.5.1.M1
beckhoff-2.5.1.M1

and

openhab> feature:list|grep -i bacnet
co7io-binding-base                                x 2.5.1.M1         x          x Started     x bacnet                   x ConnectorIO Binding Base
openhab-binding-bacnet                            x 2.5.1.M1         x          x Uninstalled x bacnet                   x BACnet Binding
bacnet4j-wrapper                                  x 1.2.0            x          x Started     x bacnet                   x bacnet4j wrapper library
co7io-binding-bacnet                              x 2.5.1.M1         x x        x Started     x bacnet                   x BACnet Binding
bacnet                                            x 2.5.1.M1         x          x Uninstalled x bacnet                   x ConnectorIO - Binding - Features - Distributions

If you see bacnet-x.y.z in output of first command then you should be able to see openhab-binding-bacnet in the second one. The old binding do not have a feature nor marketplace item thus it should not interfere with anything.

Hi @splatch,

thanks, I see it now. I still cannot run it because de bind address is already being used by the previous version of the binding on my openhab machine.

I will set aside some time to test this in the next few days and will keep you posted.

@Pierre-Luc_Pelletier it should be sufficient just to stop old binding for tests. Since you asked about commands. That is procedure from the shell:

openhab> la -l|grep -i bacnet
246 x Active    x  80 x 1.2.0                   x mvn:org.code-house.bacnet4j/api/1.2.0
247 x Active    x  80 x 1.2.0                   x mvn:org.code-house.bacnet4j/ip/1.2.0
248 x Active    x  80 x 1.2.0                   x mvn:org.code-house.bacnet4j/mstp/1.2.0
249 x Active    x  80 x 2.5.1.M1                x mvn:org.connectorio.binding/bacnet/2.5.1.M1
261 x Active x  80 x 1.13.0.201812290105     x file:/usr/share/openhab2/addons/org.openhab.binding.bacnet-1.13.0.jar

From above list you can see that bundle 261 is old binding and you can stop it with command stop 261. If you will execute command refresh 249 it should cause re-allocation of port by new binding.

Thanks, I tried it and found a few things :

I seem to get an error on multi-state value objects

2020-05-05 16:08:04.857 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'multistate-value::90002' to inbox.

2020-05-05 16:08:04.861 [ERROR] [g.discovery.internal.PersistentInbox] - Could not post event of type 'added'.

java.lang.NullPointerException: null

	at org.eclipse.smarthome.config.discovery.dto.DiscoveryResultDTOMapper.map(DiscoveryResultDTOMapper.java:41) ~[?:?]

	at org.eclipse.smarthome.config.discovery.inbox.events.InboxEventFactory.map(InboxEventFactory.java:129) ~[?:?]

	at org.eclipse.smarthome.config.discovery.inbox.events.InboxEventFactory.createAddedEvent(InboxEventFactory.java:85) ~[?:?]

	at org.eclipse.smarthome.config.discovery.internal.PersistentInbox.postEvent(PersistentInbox.java:532) ~[?:?]

	at org.eclipse.smarthome.config.discovery.internal.PersistentInbox.notifyListeners(PersistentInbox.java:524) ~[?:?]

	at org.eclipse.smarthome.config.discovery.internal.PersistentInbox.add(PersistentInbox.java:222) ~[?:?]

	at org.eclipse.smarthome.config.discovery.internal.PersistentInbox.thingDiscovered(PersistentInbox.java:376) ~[?:?]

	at org.eclipse.smarthome.config.discovery.internal.DiscoveryServiceRegistryImpl$1.run(DiscoveryServiceRegistryImpl.java:265) ~[?:?]

	at org.eclipse.smarthome.config.discovery.internal.DiscoveryServiceRegistryImpl$1.run(DiscoveryServiceRegistryImpl.java:1) ~[?:?]

	at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_222]

	at org.eclipse.smarthome.config.discovery.internal.DiscoveryServiceRegistryImpl.thingDiscovered(DiscoveryServiceRegistryImpl.java:262) ~[?:?]

	at org.eclipse.smarthome.config.discovery.AbstractDiscoveryService.thingDiscovered(AbstractDiscoveryService.java:279) ~[?:?]

	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[?:1.8.0_222]

	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[?:1.8.0_222]

	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[?:1.8.0_222]

	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382) ~[?:1.8.0_222]

	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) ~[?:1.8.0_222]

	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) ~[?:1.8.0_222]

	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[?:1.8.0_222]

	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[?:1.8.0_222]

	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_222]

	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) ~[?:1.8.0_222]

	at org.connectorio.binding.bacnet.internal.discovery.BACnetPropertyDiscoveryService.lambda$startScan$2(BACnetPropertyDiscoveryService.java:84) ~[?:?]

	at java.util.Optional.ifPresent(Optional.java:159) [?:1.8.0_222]

	at org.connectorio.binding.bacnet.internal.discovery.BACnetPropertyDiscoveryService.startScan(BACnetPropertyDiscoveryService.java:81) [bundleFile:?]

	at org.eclipse.smarthome.config.discovery.AbstractDiscoveryService.startScan(AbstractDiscoveryService.java:209) [bundleFile:?]

	at org.eclipse.smarthome.config.discovery.internal.DiscoveryServiceRegistryImpl.startScan(DiscoveryServiceRegistryImpl.java:382) [bundleFile:?]

	at org.eclipse.smarthome.config.discovery.internal.DiscoveryServiceRegistryImpl.startScans(DiscoveryServiceRegistryImpl.java:358) [bundleFile:?]

	at org.eclipse.smarthome.config.discovery.internal.DiscoveryServiceRegistryImpl.startScan(DiscoveryServiceRegistryImpl.java:216) [bundleFile:?]

	at org.eclipse.smarthome.io.rest.core.internal.discovery.DiscoveryResource.scan(DiscoveryResource.java:97) [bundleFile:?]

	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_222]

	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_222]

	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_222]

	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_222]

	at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) [bundleFile:?]

	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) [bundleFile:?]

	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) [bundleFile:?]

	at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) [bundleFile:?]

	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) [bundleFile:?]

	at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) [bundleFile:?]

	at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) [bundleFile:?]

	at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) [bundleFile:?]

	at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) [bundleFile:?]

	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [bundleFile:?]

	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [bundleFile:?]

	at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [bundleFile:?]

	at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [bundleFile:?]

	at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [bundleFile:?]

	at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [bundleFile:?]

	at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [bundleFile:?]

	at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [bundleFile:?]

	at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) [bundleFile:?]

	at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) [bundleFile:?]

	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) [bundleFile:?]

	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) [bundleFile:?]

	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) [bundleFile:?]

	at com.eclipsesource.jaxrs.publisher.internal.ServletContainerBridge.service(ServletContainerBridge.java:76) [bundleFile:?]

	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:852) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:544) [bundleFile:9.4.20.v20190813]

	at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) [bundleFile:?]

	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:536) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1581) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1307) [bundleFile:9.4.20.v20190813]

	at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:293) [bundleFile:?]

	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:482) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1549) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1204) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [bundleFile:9.4.20.v20190813]

	at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) [bundleFile:?]

	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.Server.handle(Server.java:494) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:374) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:268) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:782) [bundleFile:9.4.20.v20190813]

	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:918) [bundleFile:9.4.20.v20190813]

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

The other thing is I have a master device (on the Bacnet/IP network) fronting a slave device connected to it via MS/TP. The old binding supported it after you made some modifications, but the discovery does not seem to work for the slave device with the new binding. It works fine on the master one connected via Bacnet/IP.

Happy to send you more details on the setup or other logs if you want to troubleshoot this further.

Thanks !

Hey Pierre,
I can do additional round with multistate objects/properties. With regard to mstp over ip - underlying library in v2 binding is the same as it was for legacy one thus it should not change much.

I’ve checked older topic you made Bacnet binding error on start - and it seems that error we been fixing was related to address handling.
In order to fully support your case I would need to take a look on installation and wireshark dumps cause you have a nested device of two kinds. Currently binding requires ip devices to be attached to ip bridge and mstp devices to be attached to mstp bridge, what you have is a device with mstp address under ip bridge and ip network. It is possible to be covered, yet I need to determine how to construct valid frames for that.

Best,
Łukasz

Hi @splatch,

the V1 binding works fine for my use case as it is, but I am happy to help troubleshoot on this new one if you want to cover the use case. If so, let me know what kind of wireshark capture you need and I will do my best to give you the info.

The best would be
A) discovery of devices
B) command to mstp device

Based on that I will be able to determine how to constuct requests. You can generate above using any bacnet tool - ie YABE.

Hi @splatch,

sent you the pcap files via direct message. Let me know if you need anything more.

Hello,
i have successfully installed the add-on. I also see the bacnet objects. Unfortunately I cannot write on the objects. I can only read the values. Where can I look for the error?

It is not an error, write part is not implemented yet. I haven’t had time to fully port 1.x functionality.

Aaa ok. good to know. Do you already have an idea in which version this could be possible? That would be a useful function for my building project.

I am currently busy with canopen binding and updates for OH3. I can take a look on bacnet writing somewhere in next week. Are you fine with analog/binary/multistate input/output types or you need something more?

Hello,
thank you for the info.
The following types are currently interesting for me to read and write:

AI / AO / AV
BI / BO /
MI / MO / MV

Otherwise your add-on will work without any problems.
With the expansion of the write function, I can perfectly equip the control from the manufacturer Kieback & Peter (Germany) with a small visualization. Editing schedules is then the crown in the end. But that’s not really that important for me personally.

High praise for your work.

@Kaoth I’ve uploaded 2.5.2-SNAPSHOT version of binding with support for writes, please test (you need to go over download procedure again).

Most of things gets mapped to ints so you need to work a bit with sitemaps. It works for analogs and binary I/O. I have no possibility to test multistate objects.

Anyone else interested in OH3 testing - please stand up! :slight_smile:

Best,
Łukasz

Hello Łukasz,
I just tested that. I can write the AV’s.
But I have a problem with the BO’s. I can write this. The outputs on the PLC control then also switch on, but I can then no longer switch off via OpenHab.
It’s like a button that turns on once. In the “Paper UI” the slider is not echoed either.
It immediately jumps back to the “OFF” position.

Am I doing something wrong?

Greetings
Marcus

I believe this might be related to binding logic which is currently implemented. My test device have read only binary outputs hence I can’t test what’s going on.

I have to take a closer look on that.

Hello, i am quite new to openhab, really starting to love it. Wanted to try the BACnet binding, looks very interesting. but when i try to install i get the following error. it is on a new OH3. What am i doing wrong?

2020-12-25 17:55:03.038 [ERROR] [core.karaf.internal.FeatureInstaller] - Failed installing ‘openhab-binding-bacnet’: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=openhab-binding-bacnet; type=karaf.feature; version="[2.5.2.SNAPSHOT,2.5.2.SNAPSHOT]"; filter:="(&(osgi.identity=openhab-binding-bacnet)(type=karaf.feature)(version>=2.5.2.SNAPSHOT)(version<=2.5.2.SNAPSHOT))" [caused by: Unable to resolve openhab-binding-bacnet/2.5.2.SNAPSHOT: missing requirement [openhab-binding-bacnet/2.5.2.SNAPSHOT] osgi.identity; osgi.identity=co7io-binding-bacnet; type=karaf.feature [caused by: Unable to resolve co7io-binding-bacnet/2.5.2.SNAPSHOT: missing requirement [co7io-binding-bacnet/2.5.2.SNAPSHOT] osgi.identity; osgi.identity=org.connectorio.binding.bacnet; type=osgi.bundle; version="[2.5.2.SNAPSHOT,2.5.2.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve org.connectorio.binding.bacnet/2.5.2.SNAPSHOT: missing requirement [org.connectorio.binding.bacnet/2.5.2.SNAPSHOT] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.connectorio.binding.base.config)(version>=2.5.0)(!(version>=3.0.0)))" [caused by: Unable to resolve org.connectorio.binding.base/2.5.2.SNAPSHOT: missing requirement [org.connectorio.binding.base/2.5.2.SNAPSHOT] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.eclipse.smarthome.core.thing)(version>=2.5.0)(!(version>=3.0.0)))"]]]]

Version which is published is compatible with OH2. I pushed updated source code to github. All necessary changes to compile against OH3 are there. I haven’t had time to test and deploy most recent binary build. I will post update soon. Sorry that it takes so long.

Thanks for your quick answer! Hope to see the updated version soon, happy to test for you :+1: