Please Note This forum exists for community support for the Mango product family and the Radix IoT Platform. Although Radix IoT employees participate in this forum from time to time, there is no guarantee of a response to anything posted here, nor can Radix IoT, LLC guarantee the accuracy of any information expressed or conveyed. Specific project questions from customers with active support contracts are asked to send requests to support@radixiot.com.

Radix IoT Website Mango 3 Documentation Website Mango 4 Documentation Website

  • In response to the requests for information from developers, we are adding this forum for information about BACnet4J. It is a general purposes BACnet IP implementation written in Java that is used by Mango, but can be used for other purposes as well. So go ahead... everything you wanted to know, ask away!


  • Hi!

    First of all I'd like to thank you for making your great work public.

    I've played aroud with BACnet4J for a while and it makes a quite stable impression.

    What I'm missing most is a documentation. However after having a close look at your example code I manged to set up a local device. I've tested it with a commercial BOWS.
    By doing this I've encountered some problems:

    -Binding BACnet device to a specific IP-Adress: Running the BOWS in a VMWare the device has to bind to the IP-Adress of the virtual network. I extended the LocalDevice and the IpMessageControl-Class in the following way:

    LocalDevice
    add String ownIP:
        private String ownIP = "255.255.255.255"; 
    
    adding a setter and a getter:
    
        public String setOwnIP (String ownIP){
            this.ownIP= ownIP;
        }
        
        public String getOwnIP () {
            return ownIP;
        }
    
    adding initializeOwnIP:
    
        public void initializeOwnIP() throws IOException {
            eventHandler.initialize();
            messageControl.setOwnIP(ownIP);
            messageControl.initializeOwnIP();
        }
    
    IPMessageControl:
    
    adding String ownIP:
        private String ownIP = "255.255.255.255"; 
    
    adding setter and getter
    
        public String setOwnIP (String ownIP){
            this.ownIP= ownIP;
        }
        
        public String getOwnIP () {
            return ownIP;
        }  
    
    adding InitializeOwnIP:
    
     public void initializeOwnIP() throws IOException {
            incomingExecutorService = Executors.newCachedThreadPool();
            InetAddress IP = InetAddress.getByName(ownIP);
            socket = new DatagramSocket(port,IP);
            start();        
        } 
    

    -there's a bug in the AddListElementRequest-Class: Members of the list must be unique. There was no check for this condition. I've changed the handle method in the following way:

    
        public AcknowledgementService handle(LocalDevice localDevice, Address from, Network network)
                throws BACnetException {
            BACnetObject obj = localDevice.getObject(objectIdentifier);
            if (obj == null)
                throw createException(ErrorClass.property, ErrorCode.writeAccessDenied, new UnsignedInteger(1));
            
            Encodable e;
            try {
                e = obj.getProperty(propertyIdentifier, propertyArrayIndex);
            }
            catch (BACnetServiceException ex) {
                throw createException(ErrorClass.property, ErrorCode.invalidArrayIndex, new UnsignedInteger(1));
            }
            if (!(e instanceof SequenceOf<?>))
                throw createException(ErrorClass.property, ErrorCode.propertyIsNotAnArray, new UnsignedInteger(1));
            
            SequenceOf<Encodable> propList = (SequenceOf<Encodable>)e;
            
            PropertyValue pv = new PropertyValue(propertyIdentifier, propertyArrayIndex, listOfElements, null);
            if (localDevice.getEventHandler().checkAllowPropertyWrite(obj, pv)) {
                for (Encodable pr : listOfElements){
                    boolean isIn = false;
                    for (Encodable pl : propList) {
                        if (pl.equals(pr))
                                isIn = true;
                    }
                    if (!isIn)
                        propList.add(pr);
                }
                localDevice.getEventHandler().propertyWritten(obj, pv);
            }
            else
                throw createException(ErrorClass.property, ErrorCode.writeAccessDenied, new UnsignedInteger(1));
            
            return null;
        }
    
    
    • There's no Alarm-machine implemented yet: EventNotifications can only be sent by hand. It would be nice if there would be a similar mechanism for sending Event-Notifications as it is implemented for COV-Notifications - it just works. And I found no way to handle Alarm-Acknowledgements. The GetEventInformation-Service is also not supported.
      Are there any plans to implement these?

    Any comments about my patches are welcome. Maybe they make it into the distribution :-).

    BR
    Stefan


  • Hi Stefan,

    Thanks for your post.

    We've added a "localBindAddress" parameter to a new LocalDevice constructor to deal with multihomed devices - it will still default to 0.0.0.0 if another address is not specified. And you are correct that AddListElement should only add unique elements. Both of these changes have been committed. Thanks for pointing them out.

    You'll need to help me out with the other stuff though:
    [list]I'm not sure what an "Alarm-machine" is. The specification makes no reference.[/list]

    [list]Aren't Event-Notifications intrinsic, and so need to be handled by client code? COVs are easy to recognize automatically.[/list]

    [list]AlarmAcknowledgement and GetEventInformation are currently not implemented as you've noted. This is because the implementation was written primarily for operator-side development. We don't yet have any plans to implement this.[/list]


  • Thanks for posting this library. There was a mention of example code.

    I downloaded the jar, but can not find the example code? Where is it, please?

    Also, are there going to be Java DOCS?

    Thanks again,

    -David


  • Hello together

    also from my side many thanks for open this project here in sourceforge.net. I downloaded the bacnet4J.jar file too and have seen that the jar file contains only precompiled classes? Is the source code open too? Perhaps I have not enough experience witch java but how can I get the java source?

    Many thanks for your help in advance
    Oliver


  • @Anonymous said:

    Thanks for posting this library. There was a mention of example code.

    I downloaded the jar, but can not find the example code? Where is it, please?

    Also, are there going to be Java DOCS?

    Thanks again,

    -David

    Hi David and Oliver,

    We have released version 1.02 which includes a zip file of the source. (The source was always available via SFs CVS repository, but i believe you would need to sign up for it somehow.) You will find the example code in the source in the zip under the "test" sub-package.

    m@


  • Oh, we just added javadocs to the release as well.


  • Hello together,

    I'm using BACnet4J and everything is fine when looking at it with testtools like Chipkin BACnet Explorer.
    Unfortunately in my first real world application with siemens PXM10/PXC64-U controller I encountered some problems.

    Siemens controller makes Who-Has request (with device instance low/high limit), but BACnet4J says com.serotonin.bacnet4j.exception.BACnetException: Error while creating APDU
    When sending Who-Has with VTS (without device instance low/high limit), BACnet4J gives I-Have

    wireshark capture.txt (K12)

    +---------+---------------+----------+
    15:49:52,131,892 ETHER
    |0 |00|1c|23|b0|87|46|00|0a|e6|b5 |75|c1|08|00|45|00|00|33|03|42 |00|00|80|11|b4|ae|c0|a8|00|bc |c0|a8|00|bd|ba|c0|ba|c0|00|1f |ba|76|81|0a|00|17|01|20|ff|ff |00|ff|10|07|3d|09|00|65|69 |62|74|65|6d|70|31|

    +---------+---------------+----------+
    15:49:52,136,357 ETHER
    |0 |00|0a|e6|b5|75|c1|00|1c|23|b0 |87|46|08|00|45|00|00|39|24|25|00 |00|80|11|93|c5|c0|a8|00|bd|c0|a8 |00|bc|ba|c0|ba|c0|00|25|7e|bc|81 |0a|00|1d|01|00|10|01|c4|02|00|04 |40|c4|00|00|00|02|75|09|00|65|69 |62|74|65|6d|70|31|

    +---------+---------------+----------+
    15:50:21,706,694 ETHER
    |0 |00|1c|23|b0|87|46|00|0a|e6|b5 |75|c1|08|00|45|00|00|39|04|81 |00|00|80|11|b3|69|c0|a8|00|bc |c0|a8|00|bd|ba|c0|ba|c0|00|25 |6c|06|81|0a|00|1d|01|20|ff|ff |00|ff|10|07|0a|04|40|1a|04|40 |3d|09|00|65|69|62|74|65|6d |70|31|

    When siemens controller requests subscribeCOV, BACnet4J gives ACK subscribeCOV, but there are no COVnotifications following, no matter how long I wait or how widely present-value is changed.

    many thanks for any comments

    sebastian


  • Hi Sebastian,

    It seems as if the Who-Has request with device instance low/high is invalid. I haven't analyzed it in detail, but have you checked it against your test tools?

    Re COV subscriptions, there are a couple of things that could be happening. The first is that the lease time has expired, but i assume you sent in a reasonable number of seconds in the expiry property.

    The second is that the object type or property is invalid for COV notifications. Valid object types are accumulator, binaryInput, binaryOutput, binaryValue, lifeSafetyPoint, multiStateInput, multiStateOutput, and multiStateValue. Valid properties are presentValue and statusFlags. I would agree that an ACK should probably not be sent if these validations fail, but currently that is not the case.


  • hi mlohbihler,
    i am using BACnet4j too. very thanks to you.
    but, i have similar problem, Mr.sebastian's

    i received who-has packet.

    0x81, 0x0b, 0x00, 0x19, 0x01, 0x20, 0xff, 0xff,
    0x00, 0xff, 0x10, 0x07, 0x09, 0x00, 0x1b, 0x3f,
    0xff, 0xff, 0x3d, 0x05, 0x00, 0x45, 0x4c, 0x45,
    0x43
    It refers to the information below.
    device instance low limit : 0
    device instance high limit : 4194303
    object name : ELEC

    but BACnet4j occurred exception.

    
    Exception in thread "main" com.serotonin.bacnet4j.exception.BACnetException: Error while creating APDU: 
    	at com.serotonin.bacnet4j.npdu.ip.IpMessageControl$IncomingMessageExecutor.runImpl(IpMessageControl.java:500)
    	at com.serotonin.bacnet4j.npdu.ip.IpMessageControl$IncomingMessageExecutor.access$0(IpMessageControl.java:464)
    	at com.serotonin.bacnet4j.npdu.ip.IpMessageControl.main(IpMessageControl.java:770)
    Caused by: com.serotonin.bacnet4j.exception.BACnetErrorException
    	at com.serotonin.bacnet4j.type.Encodable.popStart(Encodable.java:109)
    	at com.serotonin.bacnet4j.type.Encodable.readWrapped(Encodable.java:323)
    	at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:185)
    	at com.serotonin.bacnet4j.type.Encodable.readOptional(Encodable.java:210)
    	at com.serotonin.bacnet4j.service.unconfirmed.WhoHasRequest.<init>(WhoHasRequest.java:109)
    	at com.serotonin.bacnet4j.service.unconfirmed.UnconfirmedRequestService.createUnconfirmedRequestService(UnconfirmedRequestService.java:50)
    	at com.serotonin.bacnet4j.apdu.UnconfirmedRequest.<init>(UnconfirmedRequest.java:62)
    	at com.serotonin.bacnet4j.apdu.APDU.createAPDU(APDU.java:38)
    	at com.serotonin.bacnet4j.npdu.ip.IpMessageControl$IncomingMessageExecutor.runImpl(IpMessageControl.java:497)
    	... 2 more
    

    i think BACnet4j can't find context start/end tags.
    this problem occurs only 'who-has packet with device instance low/high limit'.


  • Thanks for reporting this. There was a problem in the Who-Has deserialization. A fix has been checked into the CVS repo. Note that the constructor API has changed slightly for this class as well.