It is not strictly essential to have a BBMD; BBMD's are no longer being advocated for use since Bn/SC, and (UDPv4) Broadcasts are not strictly supported by IPv6 - you have to use a Multicast group to emulate them.
The important thing to be sure of is that you have request-response connectivity between the (BACnet) Client & Server - ideally for both (ICMP) ping (/'Echo Request') and BACnet/IP communication.
If you know the address details for your (BACnet) server, then you should be able to target it directly with 'YABE' & 'VTS', if not also with 'BACnet4j' too.
For example, using the NodeJS 'node-bacnet' package; the directed/'unicast' (/non-'broadcast') approach - reading the 'ObjId' from server device '127.1.2.2:47810' having a DOIN (Device Object Instance Number) of '321':
const bacnet = require('node-bacnet');
const client = new bacnet( { "port": 47816 });
client.whoIs("127.1.2.2:47810");
client.readProperty('127.1.2.2:47810', { "type": 8, "instance": 321 }, 75, (err, value) => {
console.log('value: ', value);
console.log('value: ', value. Values[0].value);
});
Output:
value: {
len: 14,
objectId: { type: 8, instance: 391 },
property: { id: 75, index: 4294967295 },
values: [ { type: 12, value: [Object] } ]
}
value: { type: 8, instance: 391 }
(Alongside ping, you can use 'Wireshark' and/or Windows 'netsh' for checking the network connectivity - but check your firewall rules too.)
...
I've not messed with Java for a long time, and have never tried using 'BACnet4J' until today - and have found it quite hard to get going with, but here's an example of me finding a (target) device that I know about (via a directed/'unicast' route), rather than via 'Who-Is'/'broadcast' (- IPv4 address '192.168.1.7' & port # '47810'/0xBAC2 with a DOIN value of '999'); I haven't tested the 'iAmReceived' code / I borrowed it from elsewhere :
// cls & java -classpath Lib\bacnet4j-3.2.2.jar;Lib\slf4j-api-1.7.9.jar;Lib\commons-lang3-3.12.0.jar Main.java
// https://github.com/MangoAutomation/BACnet4J/tree/master/release/3.2.2/
// "Download" button - https://github.com/MangoAutomation/BACnet4J/tree/master/release/3.2.2/bacnet4j-3.2.2.jar
// https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.9/
// https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.9/slf4j-api-1.7.9.jar
// https://commons.apache.org/proper/commons-lang/download_lang.cgi/
// https://dlcdn.apache.org//commons/lang/binaries/commons-lang3-3.12.0-bin.zip
// DVM ;)
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.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkUtils;
import com.serotonin.bacnet4j.npdu.Network;
import com.serotonin.bacnet4j.service.acknowledgement.ReadPropertyAck;
import com.serotonin.bacnet4j.service.confirmed.ReadPropertyRequest;
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;
class Main
{
private static LocalDevice localDevice;
public static void main(String[] args)
throws Exception
{
System.out.println();
// CONFIGURE: For your own NIC/network card
// (- UDPv4 'Broadcast' address)
IpNetwork network = new IpNetwork("192.168.1.255", 47814);
Transport transport = new DefaultTransport(network);
// transport.setTimeout(15000);
// transport.setSegTimeout(15000);
localDevice = new LocalDevice(1234, transport);
try
{
localDevice.initialize();
localDevice.getEventHandler().addListener(new Listener());
// localDevice.sendLocalBroadcast(new WhoIsRequest());
// localDevice.sendGlobalBroadcast(new WhoIsRequest());
// Using NIC/IP End-Point '192.168.1.7'/'192.168.1.7:47814'
// (- 'c0,a8,1,7,ba,c6'); using the same IP address as
// the target device but with a different port # -
// '47814' vs/to '47810'
for (Address addr : localDevice.getAllLocalAddresses())
{
System.out.println("\t" + addr);
}
System.out.println();
// CONFIGURE: For your own device
Address targAddr = IpNetworkUtils.toAddress("192.168.1.7", 47810);
System.out.println("TargAddr = '" + targAddr.toString() + "'");
System.out.println();
// localDevice.addRemoteDevice(targAddr, 999);
RemoteDevice targDevice = localDevice.findRemoteDevice(targAddr, 999);
if (targDevice != null)
{
System.out.println(targDevice.toString());
System.out.println();
getExtendedDeviceInformation(targDevice);
System.out.println("Object-Name = '" + targDevice.getName() + "'");
System.out.println();
System.out.println("Vendor-Identifier = '" + targDevice.getVendorId() + "'");
System.out.println("Vendor-Name = '" + targDevice.getVendorName() + "'");
System.out.println();
System.out.println("Protocol-Version = '" + targDevice.getProtocolVersion() + "'");
System.out.println("Protocol-Revision = '" + targDevice.getProtocolRevision() + "'");
System.out.println();
System.out.println("Services-Supported = '" + targDevice.getServicesSupported() + "'");
}
Thread.sleep(3000);
}
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();
System.out.flush();
}
}
static class Listener extends DeviceEventAdapter
{
// I haven't tested the 'iAmReceived()' code/method - I borrowed it from elsewhere
@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();
}
}
Folders & files:
│ Main.java
│ Run.cmd
│
├───.vscode
│ launch.json
│
└───Lib
bacnet4j-3.2.2.jar
commons-lang3-3.12.0.jar
slf4j-api-1.7.9.jar
My run (Windows 'Command Prompt') 'CMD' script (/Batch file):
java -classpath Lib\bacnet4j-3.2.2.jar;Lib\slf4j-api-1.7.9.jar;Lib\commons-lang3-3.12.0.jar Main.java
Environment:
'Windows 10 Pro' - '22H2' - '19045.3086'
openjdk version "17.0.7" 2023-04-18 LTS
OpenJDK Runtime Environment Corretto-17.0.7.7.1 (build 17.0.7+7-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.7.7.1 (build 17.0.7+7-LTS, mixed mode, sharing)
Output:
Address [networkNumber=0, macAddress=[c0,a8,1,7,ba,c6]]
Address [networkNumber=0, macAddress=[c0,a8,38,1,ba,c6]]
Address [networkNumber=0, macAddress=[ac,1b,c0,1,ba,c6]]
Address [networkNumber=0, macAddress=[ac,12,b0,1,ba,c6]]
TargAddr = 'Address [networkNumber=0, macAddress=[c0,a8,1,7,ba,c2]]'
RemoteDevice(instanceNumber=999, address=Address [networkNumber=0, macAddress=[c0,a8,1,7,ba,c2]])
ExtDevInfo: Getting 'Object-Name' . . .
ExtDevInfo: Getting 'Vendor-Identifier' . . .
ExtDevInfo: Getting 'Vendor-Name' . . .
ExtDevInfo: Getting 'Protocol-Version' . . .
ExtDevInfo: Getting 'Protocol-Revision' . . .
ExtDevInfo: Getting 'Protocol-Services-Supported' . . .
Object-Name = 'DVM BMD'
Vendor-Identifier = '24473'
Vendor-Name = 'DVM ;)'
Protocol-Version = '1'
Protocol-Revision = '7'
Services-Supported = '[true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, true, false, false, true, false, false, false, false, false, true, true, true, true, false, false, true, true, true, true, true, false, true, true, false]'
Hope this helps. ;D