MangoAutomation / BACnet4J

BACnet/IP stack written in Java. Forked from http://sourceforge.net/projects/bacnet4j/
GNU General Public License v3.0
183 stars 110 forks source link

TimerTask can not work with RequestUtils #13

Closed char1st closed 7 years ago

char1st commented 7 years ago

I want run a periodic task use Timertask and ScheduledExecutorService to run RequestUtils.getProperties , but is not work , and I found there is no request send to remoteDevice.

    static void find(Long period, TimeUnit unit, Boolean isTest) {
        try {
            SequenceOf<ObjectIdentifier> objList = RequestUtils.getObjectList(localDevice, d);
            List<ObjectIdentifier> logOids = getLogOids(objList);
            TimerTask task = new TimerTask() {
                @Override
                public void run() {
                    for (ObjectIdentifier i : logOids) {
                        try {
                            List<ReadAccessSpecification> specs = new ArrayList<ReadAccessSpecification>();
                            specs.add(new ReadAccessSpecification(i, PropertyIdentifier.presentValue));
                            specs.add(new ReadAccessSpecification(i, PropertyIdentifier.units));
                            specs.add(new ReadAccessSpecification(i, PropertyIdentifier.objectName));
                            specs.add(new ReadAccessSpecification(i, PropertyIdentifier.description));
                            specs.add(new ReadAccessSpecification(i, PropertyIdentifier.objectType));
                            ReadPropertyMultipleRequest multipleRequest = new ReadPropertyMultipleRequest(
                                    new SequenceOf<ReadAccessSpecification>(specs));
                            localDevice.send(d, multipleRequest);
                            ReadPropertyMultipleAck send = localDevice.send(d, multipleRequest).get();
                            SequenceOf<ReadAccessResult> readAccessResults = send.getListOfReadAccessResults();
                            System.out.print(i.getInstanceNumber() + " " + i.getObjectType() + ", ");
                            for (ReadAccessResult result : readAccessResults) {
                                for (ReadAccessResult.Result r : result.getListOfResults()) {
                                    System.out.print(r.getReadResult() + ", ");
                                }
                            }
                        } catch (Exception e) {
                        }
                    }
                }
            };
            ScheduledExecutorService scheduledPool = Executors.newSingleThreadScheduledExecutor();
            scheduledPool.scheduleWithFixedDelay(task, 0, period, unit);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

What is the rigth way use RequestUtils in Timertask ?

This under code can work, Why?

    static void find(Long period, Boolean isTest) {
        try {
            SequenceOf<ObjectIdentifier> objList = RequestUtils.getObjectList(localDevice, d);
            List<ObjectIdentifier> logOids = getLogOids(objList);
            while (true) {
                for (ObjectIdentifier i : logOids) {
                    try {
                        List<ReadAccessSpecification> specs = new ArrayList<ReadAccessSpecification>();
                        specs.add(new ReadAccessSpecification(i, PropertyIdentifier.presentValue));
                        specs.add(new ReadAccessSpecification(i, PropertyIdentifier.units));
                        specs.add(new ReadAccessSpecification(i, PropertyIdentifier.objectName));
                        specs.add(new ReadAccessSpecification(i, PropertyIdentifier.description));
                        specs.add(new ReadAccessSpecification(i, PropertyIdentifier.objectType));
                        ReadPropertyMultipleRequest multipleRequest = new ReadPropertyMultipleRequest(
                                new SequenceOf<ReadAccessSpecification>(specs));
                        localDevice.send(d, multipleRequest);
                        ReadPropertyMultipleAck send = localDevice.send(d, multipleRequest).get();
                        SequenceOf<ReadAccessResult> readAccessResults = send.getListOfReadAccessResults();
                        System.out.print(i.getInstanceNumber() + " " + i.getObjectType() + ", ");
                        for (ReadAccessResult result : readAccessResults) {
                            for (ReadAccessResult.Result r : result.getListOfResults()) {
                                System.out.print(r.getReadResult() + ", ");
                            }
                        }
                    } catch (Exception e) {
                    }
                }
                ThreadUtils.sleep(period);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
mlohbihler commented 7 years ago

This is not the problem, but you are using a TimerTask only as a Runnable. You would normally use it with a java.util.Timer. Also, the local device already has a scheduled executor, so you can simplify the async code by doing this:

        localDevice.scheduleWithFixedDelay(() -> {
            for (final ObjectIdentifier i : logOids) {
                ...
            }
        }, 0, period, unit);

But back to your question. What is the problem you are seeing when you run async?

char1st commented 7 years ago

THX . Please excuse me for my poor English. My problem is When I use the first method , the code lookes like hang at localDevice.send(d, multipleRequest) ,and there is no bacnet package send to remoteDevice show in the wireshark .

mlohbihler commented 7 years ago

It could be that while your async code was running the local device was terminated in the other thread.

char1st commented 7 years ago

I found the local device in the first method is not isInitialized , and had to initialize agine then terminate it in the end. I will use the localDevice.scheduleWithFixedDelay() . My fault .... I terminate the local device at Main in finally block .

mlohbihler commented 7 years ago

I have added a check to ensure that the local device is initialized before it will attempt to send requests.