JoelBender / bacpypes

BACpypes provides a BACnet application layer and network layer written in Python for daemons, scripting, and graphical interfaces.
MIT License
303 stars 129 forks source link

Support for new point types #389

Open Safrone opened 3 years ago

Safrone commented 3 years ago

I was using the evaluation version of this BACnet simulator for testing (http://www.scadaengine.com/software6.html) and I noticed some points were listed as proprietary but appear to have official definitions:

the object_types were:

31: timer 32: accessCredential 55: binaryLightingOutput 57: elevatorGroup 58: escalator 59: lift

additionally, some object parameters failed to properly cast out their values:

In [91]: bacnet.read('20:0x010000000000@192.168.1.199 eventEnrollment 0 faultParameters')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-91-9a7fc5372277> in <module>
----> 1 bacnet.read('20:0x010000000000@192.168.1.199 eventEnrollment 0 faultParameters')

~/enertiv/data_handler/device/reader/bacnet.py in read(self, args, arr_index, vendor_id, bacoid, timeout, prop_id_required)
   1073             value = apdu.propertyValue.cast_out(datatype.subtype)
   1074         else:
-> 1075           value = apdu.propertyValue.cast_out(datatype)
   1076
   1077         self._log.debug("{:<20} {:<20}".format("value", "datatype"))

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/constructeddata.py in cast_out(self, klass)
   1359
   1360             # let it decode itself
-> 1361             value.decode(t)
   1362
   1363             # make sure everything was consumed

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/constructeddata.py in decode(self, taglist)
   1185                 break
   1186         else:
-> 1187             raise AttributeError("missing choice of %s" % (self.__class__.__name__,))
   1188
   1189         # now save the value and None everywhere else

AttributeError: missing choice of FaultParameter
In [119]: bacnet.read('20:0x010000000000@192.168.1.199 largeAnalogValue 1 covIncrement')
---------------------------------------------------------------------------
InvalidTag                                Traceback (most recent call last)
<ipython-input-119-c54cf328d894> in <module>
----> 1 bacnet.read('20:0x010000000000@192.168.1.199 largeAnalogValue 1 covIncrement')

~/enertiv/data_handler/device/reader/bacnet.py in read(self, args, arr_index, vendor_id, bacoid, timeout, prop_id_required)
   1073             value = apdu.propertyValue.cast_out(datatype.subtype)
   1074         else:
-> 1075           value = apdu.propertyValue.cast_out(datatype)
   1076
   1077         self._log.debug("{:<20} {:<20}".format("value", "datatype"))

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/constructeddata.py in cast_out(self, klass)
   1344
   1345             # a helper cooperates between the atomic value and the tag
-> 1346             helper = klass(self.tagList[0])
   1347
   1348             # return the value

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/primitivedata.py in __init__(self, arg)
    608             pass
    609         elif isinstance(arg, Tag):
--> 610             self.decode(arg)
    611         elif isinstance(arg, int):
    612             if not self.is_valid(arg):

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/primitivedata.py in decode(self, tag)
    641     def decode(self, tag):
    642         if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.unsignedAppTag):
--> 643             raise InvalidTag("unsigned application tag required")
    644         if len(tag.tagData) == 0:
    645             raise InvalidTag("invalid tag length")

InvalidTag: unsigned application tag required
In [130]: bacnet.read('20:0x010000000000@192.168.1.199 octetstringValue 1 presentValue')
---------------------------------------------------------------------------
InvalidTag                                Traceback (most recent call last)
<ipython-input-130-1670c6e721b8> in <module>
----> 1 bacnet.read('20:0x010000000000@192.168.1.199 octetstringValue 1 presentValue')

~/enertiv/data_handler/device/reader/bacnet.py in read(self, args, arr_index, vendor_id, bacoid, timeout, prop_id_required)
   1073             value = apdu.propertyValue.cast_out(datatype.subtype)
   1074         else:
-> 1075           value = apdu.propertyValue.cast_out(datatype)
   1076
   1077         self._log.debug("{:<20} {:<20}".format("value", "datatype"))

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/constructeddata.py in cast_out(self, klass)
   1344
   1345             # a helper cooperates between the atomic value and the tag
-> 1346             helper = klass(self.tagList[0])
   1347
   1348             # return the value

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/primitivedata.py in __init__(self, arg)
    899             pass
    900         elif isinstance(arg, Tag):
--> 901             self.decode(arg)
    902         elif isinstance(arg, str):
    903             self.value = arg

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/primitivedata.py in decode(self, tag)
    916     def decode(self, tag):
    917         if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.characterStringAppTag):
--> 918             raise InvalidTag("character string application tag required")
    919         if len(tag.tagData) == 0:
    920             raise InvalidTag("invalid tag length")

InvalidTag: character string application tag required
In [138]: pl = bacnet.readMultiple('20:0x010000000000@192.168.1.199 networkPort 1 bacnetIPGlobalAddress')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-138-0c201cb060a4> in <module>
----> 1 pl = bacnet.readMultiple('20:0x010000000000@192.168.1.199 networkPort 1 bacnetIPGlobalAddress')

~/enertiv/data_handler/venv/lib/python3.6/site-packages/BAC0/core/io/Read.py in readMultiple(self, args, request_dict, vendor_id, timeout, prop_id_required)
    352                                 value = None
    353                             else:
--> 354                                 value = propertyValue.cast_out(datatype)
    355
    356                             self._log.debug(

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/constructeddata.py in cast_out(self, klass)
   1359
   1360             # let it decode itself
-> 1361             value.decode(t)
   1362
   1363             # make sure everything was consumed

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/constructeddata.py in decode(self, taglist)
    291                     # build a value and decode it
    292                     value = element.klass()
--> 293                     value.decode(taglist)
    294
    295                     # save the result

~/enertiv/data_handler/venv/lib/python3.6/site-packages/bacpypes/constructeddata.py in decode(self, taglist)
   1185                 break
   1186         else:
-> 1187             raise AttributeError("missing choice of %s" % (self.__class__.__name__,))
   1188
   1189         # now save the value and None everywhere else

AttributeError: missing choice of HostAddress
JoelBender commented 3 years ago

The 389-support-for-new-point-types branch has the new objects and properties and it passes the tests. If this works for you I'll merge it into develop, test again, and release it as 0.18.4.