Code-House / bacnet4j-wrapper

Simple facade for bacnet4j api.
GNU General Public License v3.0
48 stars 20 forks source link

getting Bacnet TimeOut Exception while Reading properties of remote devices. #20

Closed yasar456 closed 11 months ago

yasar456 commented 1 year ago

I am using the following code and able to successfully get remote devices on network. Getting error as

com.serotonin.bacnet4j.transport.DefaultTransport] [Thread: BACnet4J transport for device 123] Message: Timeout on key Key(address=Address [networkNumber=0, macAddress=[c0,a8,4,29,ba,c0]], linkService=null, invokeId=82, fromServer=true)

                                try {
                for (RemoteDevice singleRemoteDevice : remoteDevices) {

                    logger.info("remote device instance detail {}",
                            singleRemoteDevice.getObjectIdentifier().getInstanceNumber());

                    if (!(singleRemoteDevice.getObjectIdentifier().getInstanceNumber() == 178041)) {
                        continue;
                    }
                    logger.info("Device Name {}", singleRemoteDevice.getObjectIdentifier());

                    for (int i = 0; i < 117; i++) {
                        try {
                            long time = System.currentTimeMillis();
                            logger.info("Start Time {}", time);
                            String paramName = null;
                            try {

                                paramName = (String) RequestUtils
                                        .sendReadPropertyAllowNull(localDevice, singleRemoteDevice,
                                                new ObjectIdentifier(2, i), PropertyIdentifier.objectName)
                                        .toString();
                            } catch (BACnetException e) {
                                e.printStackTrace();
                            }
                            long time1 = System.currentTimeMillis();
                            logger.info("Time Taken in millis to read Param Value {}", time1 - time);
                            if (!paramList.contains(paramName)) {
                                continue;
                            }

                            String unit = (String) RequestUtils.sendReadPropertyAllowNull(localDevice,
                                    singleRemoteDevice, new ObjectIdentifier(2, i), PropertyIdentifier.units)
                                    .toString();
                            Real value = (Real) RequestUtils.sendReadPropertyAllowNull(localDevice,
                                    singleRemoteDevice, new ObjectIdentifier(2, i),
                                    PropertyIdentifier.presentValue);

                            logger.info("Time Taken in millis to read Param Value {}", time1 - time);
                            StatusFlags status = (StatusFlags) RequestUtils.sendReadPropertyAllowNull(localDevice,
                                    singleRemoteDevice, new ObjectIdentifier(2, i), PropertyIdentifier.statusFlags);

                            System.out.println(i + ": Value read from the BACnet device: " + value + " " + unit
                                    + " " + paramName + " " + status);

                            CreateJson.Data data = null;
                            String deviceId = "S28611687853199791";
                            String standardEnergyParam = config.setting.paramMap.get(paramName);
                            data = createJson.createData(deviceId, standardEnergyParam, System.currentTimeMillis(),
                                    value.toString());

                            if (config.setting.isPost) {
                                logger.info("data posted {}", mapper.writeValueAsString(data));
                                if (postData.postData(this.config.setting.url, this.config.setting.port,
                                        mapper.writeValueAsString((Object) data), this.config.setting.endPoint,
                                        this.config.setting.isUseProxy, this.config.setting.proxyUrl,
                                        this.config.setting.proxyPort)) {
                                    logger.info("data posted successfully for deviceId {} and value {}", deviceId,
                                            value);
                                    isDone = true;
                                    Thread.sleep(1000);
                                }
                            }
                        } catch (BACnetException e) {
                            e.printStackTrace();
                            Thread.sleep(10000);
                        }
                    }
                }
splatch commented 1 year ago

Code which you provide is bacnet4j itself. Which request does fail for you? Depending on device kind (and supported options) you can use read property multiple request and pack unit, value and status flags in single readout reducing network load.

yasar456 commented 1 year ago

Thanks for your prompt response.

I already tried to read only Present value and set instance for 1 only, but still got the same error. When trying to get data by connecting with YABE tool , it works fine.

I am not able to figure out the issue. I also tried to set transport.setTimeOut to 60 seconds but no help. Can you suggest what other things that I should look for. Stack Trace is as

   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.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:175)
at com.serotonin.bacnet4j.util.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:151)
at com.ll.handlers.BacnetHandler.startPolling(BacnetHandler.java:141)
at com.ll.handlers.BacnetHandler.start(BacnetHandler.java:75)
at com.ll.handlers.BacnetHandler.run(BacnetHandler.java:69)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

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 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.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:175) at com.serotonin.bacnet4j.util.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:151) at com.ll.handlers.BacnetHandler.startPolling(BacnetHandler.java:141) at com.ll.handlers.BacnetHandler.start(BacnetHandler.java:75) at com.ll.handlers.BacnetHandler.run(BacnetHandler.java:69) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) 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 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.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:175) at com.serotonin.bacnet4j.util.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:151) at com.ll.handlers.BacnetHandler.startPolling(BacnetHandler.java:141) at com.ll.handlers.BacnetHandler.start(BacnetHandler.java:75) at com.ll.handlers.BacnetHandler.run(BacnetHandler.java:69) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) 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 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.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:175) at com.serotonin.bacnet4j.util.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:151) at com.ll.handlers.BacnetHandler.startPolling(BacnetHandler.java:141) at com.ll.handlers.BacnetHandler.start(BacnetHandler.java:75) at com.ll.handlers.BacnetHandler.run(BacnetHandler.java:69) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) 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 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.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:175) at com.serotonin.bacnet4j.util.RequestUtils.sendReadPropertyAllowNull(RequestUtils.java:151) at com.ll.handlers.BacnetHandler.startPolling(BacnetHandler.java:141) at com.ll.handlers.BacnetHandler.start(BacnetHandler.java:75) at com.ll.handlers.BacnetHandler.run(BacnetHandler.java:69) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) 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

splatch commented 1 year ago

Eearlier versions of bacnet4j had difficulties with coordination of calls happening from thread which did network related operations. Wrapper library you reported issue for dispatches own requests to separate thread to detach from notification thread used by bacnet4j. I am not sure if that's still a case, but if you experience failure with first call you make it could be a case. Timeout errors you get are related with lack of answer from device, so network level timeout adjustment won't help. Are you sure you use proper device/network/object identifier? BTW you can check with wireshark if device answers for your call, but bacnet4j misses it for some reason.

yasar456 commented 1 year ago

I am using following code for devices/network/object identifier

try { logger.info("Started Polling"); IpNetworkBuilder builder = new IpNetworkBuilder();

// int port = 47808; // String localBindAddress = "0.0.0.0"; // String broadcastAddress = "192.168.20.195"; // String subnetMask = "192.168.20.0"; // int localNetworkNumber = 0; // boolean reuseAddress = true;

        int port = Config.bacnetPort;
        String localBindAddress = Config.localBindAddress;
        String broadcastAddress = Config.broadcastAddress;
        String subnetMask = Config.subnetMask;
        int localNetworkNumber = Config.localNetworkNumber;
        boolean reuseAddress = Config.isReuseAddress;

        IpNetwork ipNetwork = builder.withPort(port).withLocalBindAddress(localBindAddress)
                .withSubnet(subnetMask, 24).withLocalNetworkNumber(localNetworkNumber)
                .withReuseAddress(reuseAddress).build();

        Transport transport = new DefaultTransport(ipNetwork);
        LocalDevice localDevice = new LocalDevice(123, transport);
        localDevice.getEventHandler().addListener(new DeviceEventAdapter());
        localDevice.initialize();
        Thread.sleep(20000);
        RemoteDeviceDiscoverer devices = localDevice.startRemoteDeviceDiscovery();
        Thread.sleep(20000);
        List<RemoteDevice> remoteDevices = devices.getRemoteDevices();
        logger.info("Number of devices Found {}" ,remoteDevices.size());

Its working fine till this point, but unable to read properties from the object. Though using YABE tool , it works fine

splatch commented 1 year ago

Can you try below code? It uses wrapper code made in this repository, so it wraps in a way bacnet4j logic for you. You will need to declare dependency on org.code-house.bacnet4j:ip:1.3.0-alpha3 module.

  public static void main(String[] args) {
    BacNetClient client = new BacNetIpClient("<bind ip>", "<broadcast ip>", 1339);
    client.start();

    Set<Device> devices = client.discoverDevices(2000);
    for (Device device : devices) {
      if (device.getInstanceNumber() != 178041) {
        continue;
      }

      List<BacNetObject> objects = client.getDeviceObjects(device);
      for (BacNetObject object : objects) {
        List<String> propertyNames = client.getObjectPropertyNames(object);
        for (String property : propertyNames) {
          System.out.println(
              object + "." + property + "=" + client.getObjectPropertyValue(object, property, new BypassBacnetConverter())
          );
        }
      }
    }

    client.stop();
  }

This should enumerate all objects of a device with all attributes on each object. It might take a while, but this way you will be able to confirm if issue comes from your code or bacnet4j itself.

splatch commented 11 months ago

@yasar456 can you please confirm if issue was solved somewhat different or still remains? Please close issue if it does not bother you any more.

yasar456 commented 11 months ago

HI, Issue has been resolved. It occurred as I was using YABE tool and my application simultaneously. When I closed YABE, all details were fetched.