openmucextensions / bacnet Goto Github PK
View Code? Open in Web Editor NEWOpenMUC BACnet/IP communication driver based on bacnet4J
OpenMUC BACnet/IP communication driver based on bacnet4J
BACnet objects provide various properties. Currently, the Present Value
property of the object will be selected when reding/writing a remote BACnet object. The BACnetServerConnection
class allows access to other properties using a # operator to separate the channel address from the object property that should be accessed. This should also be possible for remote devices.
Local devices created and used by bacnet4j are also able to provide BACnet objects (so the local device is a BACnet server, see this wiki page for details). OpenMUC applications should be able to add and remove objects to/from the local device and change the object's value.
If the channels.xml
contains more devices
using the same remoteDevicePort
, on startup for every device a scan for remote devices is started.
It would be better to do just one scan per BACnet "subnet" (i.e. per port or per local device).
If the channels.xml
contains more devices
using the same remoteDevicePort
, the following error is written in the log:
'Unable to connect to device XXXXX because error while creating local device: Address already in use. Will try again in 300000ms.'
Probably the local device is recreated but should be reused.
It doesn't make sense to configure different values for remote/local device port. Although, it is confusing to have two different settings for the port.
Replace both setting possibilities by a single one called "devicePort"
Broadcasting a WhoIsRequest
to find remote devices (device scan) seems not to be very reliable. During tests, devices have only been found randomly. Another way to find a specific device (with known remote device identifier and IP address) is to use the findRemoteDevice()
method:
String remoteDeviceIpAddress = "10.78.20.115";
int remoteDeviceIdentifier = 2138113;
RemoteDevice remoteDevice = localDevice.findRemoteDevice(IpNetworkUtils.toAddress(remoteDeviceIpAddress, port), remoteDeviceIdentifier);
This method seems to be more reliable. In tests, the method always returned the remote device. Therefore, the device identifier as well as the IP address of the remote device should be stored in the OpenMUC device settings string. When loading a configuration, the specific remote device should be obtained using the findRemoteDevice()
method.
RFC
If a device is configured from a foreign network segment, communication is done via a router (see #7). If multiple devices are configured using the same router (e.g. because they are in the same foreign network segment), COV-notification may not work properly.
If a COV-notification is sent for one object-property of one device, it seems that all BACnetConnection
-objects are notified. If the objects of the different devices have the same id and type, the according channels of both devices are updated.
Hi,
When scanning a device, I discovered 50 BACnet objects on one device. When "selecting all" and adding, it seems like its too much to handle for the openmuc (its running on a Siemens IOT2040, 400mhz cpu, 1gb memory, linux yocto 2.2). It misses some of the values, and some of them does not contain the scanned data, just a empty channel.
Maybe its possible to add a small delay between each "add" to the system?
For now, I scan, and edit the channels.xml manually instead:)
Best regards
Benjamin Kruger
Hi,
I can not find anything about BBMD in the Wiki, but I do find that the current version of BACnet4j should support it >3.2. Is it enough to set the broadcastIP on Scan to the foreign IP, and then it will use BBMD? I do not have any devices to test this, but I can imagine this must be a relevant question to more people..
/Ben
If the channels-configuration (channels.xml
) contains an channel address (which is used as object-name of the (remote) BACnet device) which is invalid, the driver throws an exception when trying to read the value and stops working (i.e. does not read the current value from other channels).
java.lang.NullPointerException: null
at com.serotonin.bacnet4j.type.Encodable.write(Encodable.java:234) ~[na:na]
at com.serotonin.bacnet4j.type.constructed.ReadAccessSpecification.write(ReadAccessSpecification.java:67) ~[na:na]
at com.serotonin.bacnet4j.type.constructed.SequenceOf.write(SequenceOf.java:62) ~[na:na]
at com.serotonin.bacnet4j.type.Encodable.write(Encodable.java:193) ~[na:na]
at com.serotonin.bacnet4j.service.confirmed.ReadPropertyMultipleRequest.write(ReadPropertyMultipleRequest.java:73) ~[na:na]
at com.serotonin.bacnet4j.transport.DefaultTransport$OutgoingConfirmed.sendImpl(DefaultTransport.java:311) ~[na:na]
at com.serotonin.bacnet4j.transport.DefaultTransport$Outgoing.send(DefaultTransport.java:281) ~[na:na]
at com.serotonin.bacnet4j.transport.DefaultTransport.run(DefaultTransport.java:392) ~[na:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_72]
In addition, shutdown of openMUC is not possible (stops at Deregistering driver: bacnet
).
Currently, there are two Connection classes for connections to local and remote devices with different functionality. By consolidating the two classes, common usage of connections (independent from the used connection) should be ensured.
Future behaviour to be discussed:
Present Value
should be possible in future)When doing a device-discovery for the driver in the "Channel Configurator", the driver fills the settings string for the devices which will be added after selection.
This settings-string is malformed since it contains a new-line character at the end. The channels.xml
looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<configuration>
<driver id="bacnet">
<device id="2098111">
<description>DB18'AS99</description>
<deviceAddress>2098111</deviceAddress>
<settings>remoteDevicePort=0xBAC1;broadcastIP=192.168.255.255
</settings>
</device>
</driver>
</configuration>
It should be
[...]
<description>DB18'AS99</description>
<deviceAddress>2098111</deviceAddress>
<settings>remoteDevicePort=0xBAC1;broadcastIP=192.168.255.255</settings>
[...]
Hi Folks,
I am trying to read Objects and Properties from BACnet interface. We are using example code of BACnet4J where our client code is expected to communicate with BACnet interface provided by LumInsight Desktop(Propriety Software).
So, in our case the device discovery is complete but we are stuck in how to read Site level and Group level information from BACnet interface.
Here is the output I am getting currently:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
initialized
Printing address...Address [networkNumber=0, macAddress=[a,2c,37,5,ba,c0]]
RemoteDevice(instanceNumber=10001, address=Address [networkNumber=0, macAddress=[a,2c,37,5,ba,c0]])
ObjectIdentifier:Device 10001
getName:LumInsight Virtual Router
getModelName:LIBI-01
Remote Device:RemoteDevice(instanceNumber=10001, address=Address [networkNumber=0, macAddress=[a,2c,37,5,ba,c0]])
User data:
device retrieved:[Device 10001]
property values: PropertyValues [values={ObjectPropertyReference(objectIdentifier=Device 10001, propertyIdentifier=presentValue, propertyArrayIndex=null)=errorClass=Property, errorCode=unknownProperty}]
errorClass=Property, errorCode=unknownProperty
The source code which I am referring and modified is as below:
`package org.openmucextensions.driver.bacnet;
import java.util.ArrayList;
import java.util.List;
import com.serotonin.bacnet4j.LocalDevice;
import com.serotonin.bacnet4j.RemoteDevice;
import com.serotonin.bacnet4j.RemoteObject;
import com.serotonin.bacnet4j.ServiceFuture;
import com.serotonin.bacnet4j.npdu.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkUtils;
import com.serotonin.bacnet4j.service.acknowledgement.ReadPropertyAck;
import com.serotonin.bacnet4j.service.acknowledgement.ReadPropertyMultipleAck;
import com.serotonin.bacnet4j.service.confirmed.ConfirmedRequestService;
import com.serotonin.bacnet4j.service.confirmed.ReadPropertyMultipleRequest;
import com.serotonin.bacnet4j.service.confirmed.ReadPropertyRequest;
import com.serotonin.bacnet4j.service.confirmed.WritePropertyRequest;
import com.serotonin.bacnet4j.transport.DefaultTransport;
import com.serotonin.bacnet4j.transport.Transport;
import com.serotonin.bacnet4j.type.constructed.Address;
import com.serotonin.bacnet4j.type.constructed.ReadAccessResult;
import com.serotonin.bacnet4j.type.constructed.ReadAccessSpecification;
import com.serotonin.bacnet4j.type.constructed.SequenceOf;
import com.serotonin.bacnet4j.type.enumerated.ObjectType;
import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier;
import com.serotonin.bacnet4j.type.primitive.Real;
import com.serotonin.bacnet4j.util.DiscoveryUtils;
import com.serotonin.bacnet4j.util.PropertyReferences;
import com.serotonin.bacnet4j.util.PropertyValues;
import com.serotonin.bacnet4j.util.RequestUtils;
public class ConnectDeviceSample {
static LocalDevice localDevice1;
public static void main(String[] args) {
IpNetwork network1 = new IpNetwork("10.44.55.5", 12345);
Transport transport1 = new DefaultTransport(network1);
transport1.addNetworkRouter(7771, IpNetworkUtils.toOctetString("10.44.55.5:47808"));
localDevice1 = new LocalDevice(92068, transport1);
try {
localDevice1.initialize();
System.out.println("initialized");
Address address1 = new Address(IpNetworkUtils.toOctetString("10.44.55.5:47808"));
System.out.println("Printing address..."+address1);
RemoteDevice d1 = localDevice1.findRemoteDevice(address1, 10001);
System.out.println(d1);
final ObjectIdentifier oi=d1.getObjectIdentifier();
DiscoveryUtils.getExtendedDeviceInformation(localDevice1, d1);
System.out.println("ObjectIdentifier:" +oi);
System.out.println("getName:"+d1.getName());
System.out.println("getModelName:"+d1.getModelName());
System.out.println("Remote Device:"+d1);
System.out.println("User data:");
/*retrieves device object*/
List<ObjectIdentifier> oids = ((SequenceOf<ObjectIdentifier>) RequestUtils.sendReadPropertyAllowNull(
localDevice1, d1, d1.getObjectIdentifier(), PropertyIdentifier.objectList)).getValues();
System.out.println("device retrieved:"+oids);
/*Read multiple values*/
PropertyReferences references = new PropertyReferences();
for (ObjectIdentifier objectIdentifier : oids) {
references.add(objectIdentifier, PropertyIdentifier.presentValue);
}
PropertyValues values = RequestUtils.readProperties(localDevice1, d1, references, null);
System.out.println("property values: "+values);
for (ObjectIdentifier objectIdentifier : oids) {
System.out.println(values.getString(objectIdentifier, PropertyIdentifier.presentValue));
}
} catch (Exception e) {
System.out.println(e.toString());
} finally {
localDevice1.terminate();
}
}
}`
Please find our device hierarchy in the image attached along with.
Any kind of help/advice is highly appreciated .
Thanks in advance.
Hi,
I have encountered a problem when scanning and using BACnet objects that have a punctuation mark in the object-name (channel address). The objects does not show on point scan, and it is not found if entered manually as a channel either. I can not find any limitations on signs in the BACnet standard for the "Character String" type that object-name is. I just want to set forward the issue if this is somehow a known limitation in any way. If not, I have to try to work around the limitation after finding the cause.
Ben
Hi,
I have dived into the functionallity in OpenMUC and these openmuc extensions. I am trying to create a solution that could do a device and/or bacnet object scan from the terminal (for remote, programmatically scan), just like the jmbus lib can do with the run-script.sh. Is this something that is already done, or should I write my own java program for this?
Best regards
Benjamin Krüger
I start the device server, using the test classs 'bacnet/src/test/java/bacnet4j/Server.java'. but can not find the device. please check the issue.
Objects of devices with another network number can be discovered using scan, but cannot be used. The integration of such channels results in the following exception (there are multiple occurrences of the same kind of exceptions):
Invalid arguments: router address not provided for remote recipient Address [networkNumber=1002, macAddress=[8,0,0,0,65,0]]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.