• Recent
    • Tags
    • Popular
    • Register
    • Login

    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 Mango 5 Documentation Website

    switching from bacnet4j3 to bacnet4j4 using special ObjectProperties

    BACnet4J general discussion
    3
    15
    4.1k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • BerndB
      Bernd
      last edited by Bernd

      Hello community,

      I'm searching for an example how to use the old ObjectProperties.addPropertyTypeDefinition in bacnet4j4 now. I don't know how to add new ObjectProperties.

      In the past ObjectProperties could be defined like this:

            ObjectProperties.addPropertyTypeDefinition(ObjectType.lifeSafetyZone,
                                                       PropertyIdentifier.forId(MY_SPECIAL_VALUE),
                                                       CharacterString.class, true, false);
      
      

      Now the add- function is private, so bacnet4j cannot handle answers for the PropertieIdentifier with the value of MY_SPECIAL_VALUE. Because of this the Objectpropertie is undefined. RequestUtils.readProperties causes failures in parsing the ComplexAck.

      RequestUtils.readProperties(localDevice, d, oprs, null);
      

      with oprs

      
               final List<ObjectPropertyReference> oprs = new ArrayList<>();
               oprs.add(new ObjectPropertyReference(oId, PropertyIdentifier.objectName));
               oprs.add(new ObjectPropertyReference(oId, PropertyIdentifier.description));
               oprs.add(new ObjectPropertyReference(oId,
                           PropertyIdentifier.forId(MY_SPECIAL_VALUE)));
      

      Stack-Trace:

      Caused by: com.serotonin.bacnet4j.exception.BACnetException: property: missing-required-parameter
      	at com.serotonin.bacnet4j.transport.ServiceFutureImpl.result(ServiceFutureImpl.java:76) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.transport.ServiceFutureImpl.get(ServiceFutureImpl.java:63) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.util.RequestUtils.readProperties(RequestUtils.java:313) ~[bacnet4j-4.1.6.jar:?]
      	... 13 more
      Caused by: com.serotonin.bacnet4j.exception.BACnetErrorException: property: missing-required-parameter
      	at com.serotonin.bacnet4j.type.Encodable.popEnd(Encodable.java:186) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.primitive.Primitive.createPrimitive(Primitive.java:67) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.Encodable.readANY(Encodable.java:368) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.constructed.Choice.read(Choice.java:102) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.constructed.Choice.<init>(Choice.java:75) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.Encodable.readChoice(Encodable.java:267) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.constructed.ReadAccessResult$Result.<init>(ReadAccessResult.java:141) ~[bacnet4j-4.1.6.jar:?]
      	at sun.reflect.GeneratedConstructorAccessor45.newInstance(Unknown Source) ~[?:?]
      	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[?:1.8.0_131]
      	at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[?:1.8.0_131]
      	at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:230) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.constructed.SequenceOf.<init>(SequenceOf.java:87) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.Encodable.readSequenceOf(Encodable.java:309) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.Encodable.readOptionalSequenceOf(Encodable.java:342) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.constructed.ReadAccessResult.<init>(ReadAccessResult.java:75) ~[bacnet4j-4.1.6.jar:?]
      	at sun.reflect.GeneratedConstructorAccessor48.newInstance(Unknown Source) ~[?:?]
      	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[?:1.8.0_131]
      	at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[?:1.8.0_131]
      	at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:230) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.constructed.SequenceOf.<init>(SequenceOf.java:74) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.type.Encodable.readSequenceOf(Encodable.java:298) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.service.acknowledgement.ReadPropertyMultipleAck.<init>(ReadPropertyMultipleAck.java:56) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.service.acknowledgement.AcknowledgementService.createAcknowledgementService(AcknowledgementService.java:52) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.apdu.ComplexACK.parseServiceData(ComplexACK.java:211) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.transport.DefaultTransport.completeComplexAckResponse(DefaultTransport.java:757) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.transport.DefaultTransport.receiveAPDU(DefaultTransport.java:679) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.transport.DefaultTransport.receiveImpl(DefaultTransport.java:573) ~[bacnet4j-4.1.6.jar:?]
      	at com.serotonin.bacnet4j.transport.DefaultTransport.run(DefaultTransport.java:493) ~[bacnet4j-4.1.6.jar:?]
      	at java.lang.Thread.run(Unknown Source) [?:1.8.0_131]
      

      Wireshark of this special property:
      0_1540911576455_9ba43268-66c0-4d62-a396-00a85ab8de9c-grafik.png
      Is someone able to show me a way to fix my problem?

      Many thanks in advance,

      Bernd

      1 Reply Last reply Reply Quote 0
      • carnecroC
        carnecro
        last edited by

        Did you find a solution? I have exactly the same problem.

        1 Reply Last reply Reply Quote 0
        • phildunlapP
          phildunlap
          last edited by phildunlap

          I believe the intention, but I can't speak for the author, is that if you've got custom properties you should be overriding the appropriate classes (ObjectProperties, PropertyIdentifier, ObjectType, etc) with classes modified to support your situation.

          1 Reply Last reply Reply Quote 0
          • carnecroC
            carnecro
            last edited by

            Not so easy, PropertyIdentifier, that is the most important for me, has private constructor.

            1 Reply Last reply Reply Quote 0
            • carnecroC
              carnecro
              last edited by

              And ObjectProperties.add() has private access in com.serotonin.bacnet4j.obj.ObjectProperties.

              Making a gateway I need to map a proprietary point attributes to BACnet point properties. However, some of the attributes do not have a standard equivalent on the BACnet side. For example, we have multiple alarm levels on the analog value object (HiLevel1=warning, HiLevel2=alarm, HiLevel3=fault), etc. I really did not find any way how to add proprietary (custom) properties to a standard BACnet object except to modify the original code.

              1 Reply Last reply Reply Quote 0
              • phildunlapP
                phildunlap
                last edited by

                Correct.

                Those classes are for the most part large enumerations such that modifying them would be straightforward.

                1 Reply Last reply Reply Quote 0
                • carnecroC
                  carnecro
                  last edited by

                  I found a way, how to add my own proprietary identifier! The static method PropertyIdentifier.forId adds the new id into the idMap when the id does not exist. Unfortunatelly, the new property name is not added into the nameMap and prettyMap, so I added the names directly.

                  public class MyPropertyIdentifier extends PropertyIdentifier {
                  
                      public static final PropertyIdentifier myProperty = PropertyIdentifier.forId(2048);
                  
                      public MyPropertyIdentifier(ByteQueue queue) throws BACnetErrorException {
                          super(queue);
                      }
                  
                      static {
                  
                          // Enumerated.init(MyPropertyIdentifier.class, idMap, nameMap, prettyMap);
                          getNameMap().put("my-property", myProperty);
                          getPrettyMap().put(2048, "my-property");
                      }
                  }
                  

                  However, adding the new property identifier to an object is not possible because the add methods are private. The library, without source code modifications, is not conform with the chapter 23 of the BACnet specification.

                  1 Reply Last reply Reply Quote 0
                  • phildunlapP
                    phildunlap
                    last edited by phildunlap

                    I should reiterate that I'm not the original author so I'm speculating on both the proper way to add objects and the intention.

                    I just read chapter 23 of ASHRAE-D-86451 for the first time but found nothing about extending BACnet being a runtime feature, or something that should only require API calls. Seems more intended for people implementing things in devices, no? Nevertheless, one can see that enabling runtime modification of the ObjectProperties would violate the stipulation that should a vendor define proprietary objects they must also have a registered vendor ID with ASHRAE such that your enumerations of properties are not unknowable for interoperability, was my reading.

                    Use of BACnet4J without modifying the source will give you a vendor ID associated with Infinite Automation Systems too, see https://github.com/infiniteautomation/BACnet4J/blob/master/src/main/java/com/serotonin/bacnet4j/obj/DeviceObject.java

                    But if you really want to commit to runtime modification, you could deviate from the spec and reflect the add method out of being private, but I don't think that's the right thing to do. You'll have to do something to not present our vendor ID on the device object, though, since your proprietary objects are not described in knowing the device is using vanilla BACnet4J.

                    1 Reply Last reply Reply Quote 0
                    • carnecroC
                      carnecro
                      last edited by

                      OK, maybe this was the motivation to close the add() methods. But I purchased the library to implement it in my own device where I need the proprietary properties. Looks like I have to contact the author if I am even entitled to make a change in the source code.

                      1 Reply Last reply Reply Quote 0
                      • phildunlapP
                        phildunlap
                        last edited by phildunlap

                        BACnet4J is owned and licensed by Infinite Automation Systems, Inc. You can contact sales@infiniteautomation.com to inquire about purchasing a license to use it privately in a closed-source manner. The license certainly permits subsequent modification for your application. Note also that BACnet4J is released under the GPL: https://github.com/infiniteautomation/BACnet4J/blob/master/license.txt

                        So if you're comfortable releasing whatever you're creating open source under the GPL you do not need to acquire a license.

                        1 Reply Last reply Reply Quote 0
                        • carnecroC
                          carnecro
                          last edited by

                          I purchased the license because I am using it in my closed project. The question is if I am allowed to make changes in the code I purchased. I will clear it with the sales.

                          1 Reply Last reply Reply Quote 0
                          • phildunlapP
                            phildunlap
                            last edited by phildunlap

                            I confirmed you have a license. Yes you may privately modify BACnet4J for derivative uses. What you purchased was, "BacNet4J Commercial License for unlimited use in Custom Products" where the key word is unlimited. The only thing forbidden then would be selling derivative BACnet4J licenses (the right to sell private licenses is not granted in making custom products) to my knowledge, but sales could clarify that if need be.

                            1 Reply Last reply Reply Quote 0
                            • carnecroC
                              carnecro
                              last edited by

                              Thank you for clarification.

                              1 Reply Last reply Reply Quote 0
                              • BerndB
                                Bernd
                                last edited by Bernd

                                Hello,
                                unfortunately, only now I have had time to get involved in this discussion. I have now bypassed my problem by limiting the reading of multiple properties in a request to read the properties known to bacnet4j. The proprietary properties I read now individually with a single read request from the device. This is not nice and for me it means losing time with bacnet4j version 4, but I get the information in several reading cycles, which I read under bacnet4j version 3 in one reading cycle. Since I have seen that bacnet4j version 5 is now shipped, I'll try to find a way to get the information from the device I'm interrogating in one read cycle. The topic propertyArrayIndex from release notes version 5 could perhaps be the cause of the my problem. I will continue to report if my problem with version 5 can be solved.

                                            case LIFE_SAFETY_POINT :
                                               final Encodable value = new ReadProperty(localDevice, remoteDevice)
                                                     .readProperty(oId, PropertyIdentifier.forId(MY_SPECIAL_PROBLEM_EVENT_MESSAGE_TEXTS),
                                                                   new UnsignedInteger(3));
                                               logger.debug("Encodable: [{}]", value);
                                               txt = ((CharacterString) value).getValue();
                                
                                
                                1 Reply Last reply Reply Quote 0
                                • BerndB
                                  Bernd
                                  last edited by

                                  My Problem is fixed with bacnet4j 5 thank you.

                                  It is possible again to add proprietary values:

                                        final ObjectPropertyTypeDefinition o = new ObjectPropertyTypeDefinition(
                                              ObjectType.lifeSafetyZone, true, new PropertyTypeDefinition(
                                                    PropertyIdentifier.forId(MY_SPECIAL_VALUE), CharacterString.class, true));
                                        ObjectProperties.getObjectPropertyTypeDefinitions(ObjectType.lifeSafetyPoint).add(o);
                                        final ObjectPropertyTypeDefinition o2 = new ObjectPropertyTypeDefinition(
                                              ObjectType.lifeSafetyPoint, true, new PropertyTypeDefinition(
                                                    PropertyIdentifier.forId(MY_SPECIAL_VALUE), CharacterString.class, true));
                                        ObjectProperties.getObjectPropertyTypeDefinitions(ObjectType.lifeSafetyPoint).add(o2);
                                  
                                  

                                  in this example above MY_SPECIAL_VALUE is a list (SequenceOf<CharacterString>)

                                  1 Reply Last reply Reply Quote 0
                                  • First post
                                    Last post