Dominik
Dominik

Reputation: 31

Reading and writing values from devices with BACnet4J 6.0.1

I am new to BACnet4J. I am trying to read and write values as a client using BACnet4J 6.0.1 . I have tried 2 test servers. With the test server from https://sourceforge.net/projects/bacnetserver/ I got at least a jerk message from the device with the ID 260002. However, if I now want to read the information from the device, I get a BADTIMEOUT.

With the second TestServer "BACsim" from "PolarSoft® Inc." I get an other error message with the same code already when I initialize the localDevice.

I have read several times that the port must be different if I get this error message but I have to listen on the same port as the server is acting.

But I am not sure if I need a localdevice at all to be able to read or write values.

Eclpise Consol with TestServer 1: TimeOut at: DiscoveryUtils.getExtendedDeviceInformation(localDevice, device);

Device: 1: BACnet4J device 1 Discovered device RemoteDevice(instanceNumber=260002, address=Address [networkNumber=0, macAddress=[c0,a8,38,1,ba,c0]]) InstanceNumber: 260002 Timeout: The device did not respond in time. Error fetching extended device information: null com.serotonin.bacnet4j.exception.BACnetTimeoutException at com.serotonin.bacnet4j.transport.ServiceFutureImpl.result(ServiceFutureImpl.java:75) at com.serotonin.bacnet4j.transport.ServiceFutureImpl.get(ServiceFutureImpl.java:64) at com.serotonin.bacnet4j.util.DiscoveryUtils.getExtendedDeviceInformation(DiscoveryUtils.java:48) at Main$3.iAmReceived(Main.java:499) at com.serotonin.bacnet4j.event.DeviceEventHandler.fireIAmReceived(DeviceEventHandler.java:97) at com.serotonin.bacnet4j.service.unconfirmed.IAmRequest.lambda$handle$0(IAmRequest.java:115) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: com.serotonin.bacnet4j.exception.BACnetTimeoutException at com.serotonin.bacnet4j.transport.DefaultTransport.lambda$expire$1(DefaultTransport.java:957) at com.serotonin.bacnet4j.transport.UnackedMessageContext.useConsumer(UnackedMessageContext.java:162) at com.serotonin.bacnet4j.transport.DefaultTransport.expire(DefaultTransport.java:957) at com.serotonin.bacnet4j.transport.DefaultTransport.run(DefaultTransport.java:525) ... 1 more

Console TestServer 1:

enter image description here

Eclpise Consol with TestServer 2:

Device: 1: BACnet4J device 1 java.net.BindException: Address already in use: Cannot bind at java.base/java.net.DualStackPlainDatagramSocketImpl.socketBind(Native Method) at java.base/java.net.DualStackPlainDatagramSocketImpl.bind0(DualStackPlainDatagramSocketImpl.java:84) at java.base/java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:135) at java.base/java.net.DatagramSocket.bind(DatagramSocket.java:394) at com.serotonin.bacnet4j.npdu.ip.IpNetwork.initialize(IpNetwork.java:167) at com.serotonin.bacnet4j.transport.DefaultTransport.initialize(DefaultTransport.java:186) at com.serotonin.bacnet4j.LocalDevice.initialize(LocalDevice.java:318) at com.serotonin.bacnet4j.LocalDevice.initialize(LocalDevice.java:311) at Main.test5(Main.java:514) at Main.main(Main.java:56)

This is all my code so far:

IpNetwork network = new IpNetworkBuilder()
                .withLocalBindAddress("192.168.XX.X")
                .withBroadcast("192.168.XX.XXX", 24)
                .withPort(47808)
                .withReuseAddress(true)
                .build();

        DefaultTransport transport = new DefaultTransport(network);
        transport.setTimeout(5000); 
        transport.setSegTimeout(2000); 

        final LocalDevice localDevice = new LocalDevice(1, transport);
        System.out.println("Device: " + localDevice);

        localDevice.getEventHandler().addListener(new DeviceEventAdapter() {
            @Override
            public void iAmReceived(RemoteDevice device) {
                System.out.println("Discovered device " + device);

                System.out.println("InstanceNumber: " + device.getInstanceNumber());

                ObjectIdentifier deviceObjectIdentifier = new ObjectIdentifier(ObjectType.device, device.getInstanceNumber());
                ReadPropertyRequest request = new ReadPropertyRequest(deviceObjectIdentifier, PropertyIdentifier.vendorName);

                try {
                    Address deviceAddress = device.getAddress();
                    ReadPropertyAck ack = localDevice.send(deviceAddress, request).get();

                    if (ack != null) {
                        System.out.println("Vendor Name: " + ack.getValue());
                    } else {
                        System.out.println("Ack was null. The device might not have responded.");
                    }
                } catch (BACnetTimeoutException e) {
                    System.out.println("Timeout: The device did not respond in time.");
                } catch (BACnetException e) {
                    e.printStackTrace();
                }

                // Erweiterte Geräteinformationen abrufen
                try {
                    DiscoveryUtils.getExtendedDeviceInformation(localDevice, device);
                    System.out.println("Extended device information retrieved successfully.");
                } catch (BACnetException e) {
                    System.out.println("Error fetching extended device information: " + e.getMessage());
                    e.printStackTrace();
                }
            }

            @Override
            public void iHaveReceived(RemoteDevice device, RemoteObject object) {
                System.out.println("Value reported " + device + " " + object);
            }
        });

        try {
            localDevice.initialize();
        } catch (Exception e) {
            e.printStackTrace();
        }

        localDevice.sendGlobalBroadcast(new WhoIsRequest());

        List<RemoteDevice> remoteDevices = localDevice.getRemoteDevices();
        for (RemoteDevice device : remoteDevices) {
            System.out.println("Remote device: " + device);
        }

        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }

        localDevice.terminate();
    }

I also listened to the port with WireShark to see if there was any data transfer at all:

enter image description here

I am not sure if I have understood the topic correctly and if this is the right approach at all, but unfortunately this is the only thing I could find.

Many thanks in advance!

Upvotes: 0

Views: 41

Answers (1)

DennisVM-D2i
DennisVM-D2i

Reputation: 488

The simple answer (or at least starting point) would be to change the port number (or even change it to use a different NIC/network-card's address instead), as it looks to be clashing with the server's use of the same IPv4 address & port # (- it's hard to know for sure as you've replaced the last two IP address octets/bytes with 'XX.X' & 'XX.XXX' but that's unnecessary/there's no value in doing so as you appear to be using a private network address); hence the "Address already in use: Cannot bind ..." error/exception message.

I.E. You have specified to reuse the address (- reuse-address/'SO_REUSEADDR' socket-option), but not to reuse the port # (- which apparently the reuse-port/'SO_REUSEPORT' socket-option is not as well supported as the reuse-address option).

Upvotes: 0

Related Questions