I am new to bacnet automation and to bacnet4j, We have a bacnet server that broadcast bacnet points and I could see that in yabe manually by adding the device. In this case, my laptop and the server are connected to the same network. How can i automate the same? I need to read and write the values. From where should i start? could anyone help
How to automate reading and writing values in yabe with bacnet4j Jar
317 views Asked by Viji Lakshmi AtThere are 3 answers
An answer of mine (if not out of date) might help slightly, at least as a bare-bones starting-point (possibly accelerating your progress) -
https://stackoverflow.com/questions/77480088/connect-to-bacnet-device-with-java-using-bacnet4j/77501045#77501045
Forewarning: I'm not a BACnet4J developer nor a Java developer; and I'm using Windows 10.
To start with, you could add 'SLF4J' ('reload4') to get a small sense of what is occurring, e.g. something like so (- having got the libraries online):
-classpath %CD%;Lib\bacnet4j-3.2.2.jar;Lib\slf4j-api-1.7.36.jar;Lib\commons-lang3-3.12.0.jar;Lib\reload4j-1.2.19.jar;Lib\slf4j-reload4j-1.7.36.jar
E.g. With the 'log4j.properties' configured:
log = Logs
# Define the root logger with appender file
log4j.rootLogger = DEBUG, FILE
# Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=${log}/Log.txt
# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%d %m%n
And at the beginning of your 'main()' method - to be sure you've configured the logging properly:
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("- Main() -");
You can also (install &) run Wireshark (as Administrator), and put a 'capture filter' of something like 'udp portrange 47808-47823' to see the BACnet/IP traffic that is flowing.
Now more so to your question.
After the device's 'initialize()', you probably need a 'Listener' class to listen out for the 'I-Am's being received:
localDevice.getEventHandler().addListener(new Listener());
With listener class that is something remotely like this:
static class Listener extends DeviceEventAdapter
{
@Override
public void iAmReceived(RemoteDevice d)
{
try
{
System.out.println("IAm received from " + d);
System.out.println("Segmentation: " + d.getSegmentationSupported());
d.setSegmentationSupported(Segmentation.noSegmentation);
Address a = new Address(new Unsigned16(0), new OctetString(new byte[] { (byte) 0xc0, (byte) 0xa8, 0x1,
0x5, (byte) 0xba, (byte) 0xc0 }));
System.out.println("Equals: " + a.equals(d.getAddress()));
getExtendedDeviceInformation(d);
System.out.println("Done getting extended information");
List oids = ((SequenceOf) RequestUtils.sendReadPropertyAllowNull(localDevice, d,
d.getObjectIdentifier(), PropertyIdentifier.objectList)).getValues();
System.out.println(oids);
}
catch (BACnetException e)
{
e.printStackTrace();
}
}
}
static void getExtendedDeviceInformation(RemoteDevice d)
throws BACnetException
{
ObjectIdentifier oid = d.getObjectIdentifier();
ReadPropertyAck ack;
// -
System.out.println("ExtDevInfo: Getting 'Object-Name' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.objectName)).get()
);
d.setName(ack.getValue().toString());
// -
System.out.println("ExtDevInfo: Getting 'Vendor-Identifier' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.vendorIdentifier)).get()
);
d.setVendorId(((Unsigned16) ack.getValue()).intValue());
// -
System.out.println("ExtDevInfo: Getting 'Vendor-Name' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.vendorName)).get()
);
d.setVendorName(ack.getValue().toString());
// -
System.out.println("ExtDevInfo: Getting 'Protocol-Version' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolVersion)).get()
);
d.setProtocolVersion((UnsignedInteger) ack.getValue());
// -
System.out.println("ExtDevInfo: Getting 'Protocol-Revision' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolRevision)).get()
);
d.setProtocolRevision((UnsignedInteger) ack.getValue());
// -
// Get the device's supported services
System.out.println("ExtDevInfo: Getting 'Protocol-Services-Supported' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolServicesSupported))
).get();
d.setServicesSupported((ServicesSupported) ack.getValue());
// -
System.out.println();
}
But I'm guessing that this framework, will not fire the listener's 'iAmReceived()' method, if it's for the same device, so you would either need to define another 'device' (/might be good to try as an alternative/easier? starting-point test), or as you've done try using another device (- unless I'm wrong I'm not sure why this API does not appear to have a 'client'-only class / you seem to have to use a 'device' as being the client).
But I'm guessing the problem with you set-up, might be the (local/'255.255.255.255') 'Who-Is' broadcast, whereby it's only going to broadcast to the local subnet, and to devices that are using the same port #; so in terms of orchestrating that, you'd probably be better off using the IPv4 (only) range of addresses (- IPv6 is cack in this regard in that they've reduced the localhost to being only 1 address rather than like IPv4 a localhost range of addresses or even 5-10 addresses?!), so you can have both the client and server device listening upon the same (Class 'A') network but with the same port #.
Ignoring the fact that I seem to have a newer(?) version of the BACnet4J library, i.e. method-names differences:
IpNetwork network =
new IpNetworkBuilder()
.localBindAddress("127.0.0.1")
.port(47810)
.subnetMask(hostAddress)
.build();
E.g. Possibly something close to what could work for two local host addresses:
// https://repo1.maven.org/maven2/org/slf4j/slf4j-reload4j/1.7.36/
import java.util.List;
import com.serotonin.bacnet4j.LocalDevice;
import com.serotonin.bacnet4j.RemoteDevice;
import com.serotonin.bacnet4j.event.DeviceEventAdapter;
import com.serotonin.bacnet4j.exception.BACnetException;
import com.serotonin.bacnet4j.exception.BACnetTimeoutException;
// import com.serotonin.bacnet4j.npdu.Network;
import com.serotonin.bacnet4j.npdu.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkBuilder;
// import com.serotonin.bacnet4j.npdu.ip.IpNetworkUtils;
import com.serotonin.bacnet4j.service.acknowledgement.ReadPropertyAck;
import com.serotonin.bacnet4j.service.confirmed.ReadPropertyRequest;
import com.serotonin.bacnet4j.service.unconfirmed.WhoIsRequest;
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.SequenceOf;
import com.serotonin.bacnet4j.type.constructed.ServicesSupported;
import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
import com.serotonin.bacnet4j.type.enumerated.Segmentation;
import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier;
import com.serotonin.bacnet4j.type.primitive.OctetString;
import com.serotonin.bacnet4j.type.primitive.Unsigned16;
import com.serotonin.bacnet4j.type.primitive.UnsignedInteger;
import com.serotonin.bacnet4j.util.RequestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class Main
{
private static LocalDevice localDevice;
public static void main(String[] args)
throws Exception
{
try
{
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("- Main() -");
String hostAddress = "127.255.255.255";
//String hostAddress = "192.168.0.255";
//String hostAddress = "192.168.56.255";
//String hostAddress = "192.168.255.255";
IpNetwork network =
new IpNetworkBuilder()
.localBindAddress("127.0.0.1")
.port(47810)
.subnetMask(hostAddress)
.build();
Transport transport = new DefaultTransport(network);
localDevice = new LocalDevice(3227671, transport);
localDevice.initialize();
localDevice.getEventHandler().addListener(new Listener());
localDevice.sendGlobalBroadcast(new WhoIsRequest());
int remoteId = 999;
List<RemoteDevice> remoteDevices = localDevice.getRemoteDevices();
Thread.sleep(3000);
RemoteDevice d = remoteDevices.get(0);
ObjectIdentifier oid = d.getObjectIdentifier();
ReadPropertyAck ack;
// -
System.out.println("ExtDevInfo: Getting 'Object-Name' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.objectName)).get()
);
d.setName(ack.getValue().toString());
// -
System.out.println("ExtDevInfo: Getting 'Vendor-Identifier' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.vendorIdentifier)).get()
);
d.setVendorId(((Unsigned16) ack.getValue()).intValue());
// -
System.out.println("ExtDevInfo: Getting 'Vendor-Name' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.vendorName)).get()
);
d.setVendorName(ack.getValue().toString());
// -
System.out.println("ExtDevInfo: Getting 'Protocol-Version' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolVersion)).get()
);
d.setProtocolVersion((UnsignedInteger) ack.getValue());
// -
System.out.println("ExtDevInfo: Getting 'Protocol-Revision' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolRevision)).get()
);
d.setProtocolRevision((UnsignedInteger) ack.getValue());
// -
// Get the device's supported services
System.out.println("ExtDevInfo: Getting 'Protocol-Services-Supported' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolServicesSupported))
).get();
d.setServicesSupported((ServicesSupported) ack.getValue());
// -
System.out.println();
}
catch (BACnetTimeoutException exc)
{
System.out.flush();
System.err.println(exc.getMessage());
System.err.flush();
}
catch (BACnetException exc)
{
System.out.flush();
System.err.println(exc.getMessage());
System.err.flush();
}
catch (Exception exc)
{
System.out.flush();
System.err.println(exc.getMessage());
System.err.flush();
}
finally
{
localDevice.terminate();
System.out.println();
}
}
static class Listener extends DeviceEventAdapter
{
@Override
public void iAmReceived(RemoteDevice d)
{
try
{
System.out.println("IAm received from " + d);
System.out.println("Segmentation: " + d.getSegmentationSupported());
d.setSegmentationSupported(Segmentation.noSegmentation);
Address a = new Address(new Unsigned16(0), new OctetString(new byte[] { (byte) 0xc0, (byte) 0xa8, 0x1,
0x5, (byte) 0xba, (byte) 0xc0 }));
System.out.println("Equals: " + a.equals(d.getAddress()));
return;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
static void getExtendedDeviceInformation(RemoteDevice d)
throws BACnetException
{
ObjectIdentifier oid = d.getObjectIdentifier();
ReadPropertyAck ack;
// -
System.out.println("ExtDevInfo: Getting 'Object-Name' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.objectName)).get()
);
d.setName(ack.getValue().toString());
// -
System.out.println("ExtDevInfo: Getting 'Vendor-Identifier' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.vendorIdentifier)).get()
);
d.setVendorId(((Unsigned16) ack.getValue()).intValue());
// -
System.out.println("ExtDevInfo: Getting 'Vendor-Name' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.vendorName)).get()
);
d.setVendorName(ack.getValue().toString());
// -
System.out.println("ExtDevInfo: Getting 'Protocol-Version' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolVersion)).get()
);
d.setProtocolVersion((UnsignedInteger) ack.getValue());
// -
System.out.println("ExtDevInfo: Getting 'Protocol-Revision' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolRevision)).get()
);
d.setProtocolRevision((UnsignedInteger) ack.getValue());
// -
// Get the device's supported services
System.out.println("ExtDevInfo: Getting 'Protocol-Services-Supported' . . .");
ack =
(ReadPropertyAck)
(
localDevice.send(
d,
new ReadPropertyRequest(
oid,
PropertyIdentifier.protocolServicesSupported))
).get();
d.setServicesSupported((ServicesSupported) ack.getValue());
// -
System.out.println();
}
}
I found the initial learning curve to get started with BACnet4J somewhat steep, however I was able to get started with BAC0 far quicker (which is in Python). You may find that easier.