JoelBender / bacpypes

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

Problem Reading Length of Huge Object List #248

Open pshank opened 5 years ago

pshank commented 5 years ago

Hello!

I seem to be running into a problem reading the 0 index of the objectList on the 'device' object. I have been able to successfully read this value from a different BACnet device that had 290+ BACnet objects. This new device has closer to 850 BACnet objects. When I attempt to read a single value from the objectList, I receive a 'segmentationnotsupported' error

The main difference between the old and new devices is that the new device supports segmentation (segmentedBoth) whereas I am using the BACpypes library along with my own bacnetip.py script which allows me to use the readpropertymultiple and whoisiam modules without a console. I was under the impression that segmentation is not supported using BACpypes, is that correct?

So is my problem that this new device is expecting my Gateway to handle segmentation? I had thought that the bacnet device would default to non-segmentation if mine was defined as 'noSegmentation', but perhaps I am wrong.

The following is the output from the ReadPropertyMultiple command with the --debug bacpypes.appservice.ClientSSM flag enabled.

read 192.168.254.101 device:<Instance#> objectList 0
DEBUG:bacpypes.appservice.ClientSSM:__init__ <bacpypes.appservice.StateMachineAccessPoint object at 0xb6670870> <Address 192.168.254.101>
DEBUG:bacpypes.appservice.ClientSSM:indication <bacpypes.apdu.ConfirmedRequestPDU(14,1) instance at 0xb6670d70L>
    <bacpypes.apdu.ConfirmedRequestPDU(14,1) instance at 0xb6670d70L>
        pduDestination = <Address 192.168.254.101>
        pduExpectingReply = 1
        pduNetworkPriority = 0
        apduType = 0
        apduService = 14
        apduInvokeID = 1
        pduData = x'0c.02.18.6a.0b.1e.09.4c.19.00.1f'
DEBUG:bacpypes.appservice.ClientSSM:    - segment size: 1024
DEBUG:bacpypes.appservice.ClientSSM:    - invoke ID: 1
DEBUG:bacpypes.appservice.ClientSSM:    - segment count: 1
DEBUG:bacpypes.appservice.ClientSSM:set_state 2 (AWAIT_CONFIRMATION) timer=3000
DEBUG:bacpypes.appservice.ClientSSM:request <bacpypes.apdu.ConfirmedRequestPDU(14,1) instance at 0xb66704d0L>
    <bacpypes.apdu.ConfirmedRequestPDU(14,1) instance at 0xb66704d0L>
        pduDestination = <Address 192.168.254.101>
        pduExpectingReply = 1
        pduNetworkPriority = 0
        apduType = 0
        apduSeg = False
        apduMor = False
        apduSA = False
        apduMaxSegs = 4
        apduMaxResp = 4
        apduService = 14
        apduInvokeID = 1
        pduData = x'0c.02.18.6a.0b.1e.09.4c.19.00.1f'
DEBUG:bacpypes.appservice.ClientSSM:confirmation <bacpypes.apdu.AbortPDU(None,1) instance at 0xb6670d90L>
    <bacpypes.apdu.AbortPDU(None,1) instance at 0xb6670d90L>
        pduSource = <Address 192.168.254.101>
        pduDestination = <Address 192.168.254.43>
        pduExpectingReply = False
        pduNetworkPriority = 0
        apduType = 7
        apduSrv = True
        apduInvokeID = 1
        apduAbortRejectReason = 4
        pduData = x''
DEBUG:bacpypes.appservice.ClientSSM:await_confirmation <bacpypes.apdu.AbortPDU(None,1) instance at 0xb6670d90L>
    <bacpypes.apdu.AbortPDU(None,1) instance at 0xb6670d90L>
        pduSource = <Address 192.168.254.101>
        pduDestination = <Address 192.168.254.43>
        pduExpectingReply = False
        pduNetworkPriority = 0
        apduType = 7
        apduSrv = True
        apduInvokeID = 1
        apduAbortRejectReason = 4
        pduData = x''
DEBUG:bacpypes.appservice.ClientSSM:    - server aborted
DEBUG:bacpypes.appservice.ClientSSM:set_state 7 (ABORTED) timer=0
DEBUG:bacpypes.appservice.ClientSSM:    - remove from active transactions
DEBUG:bacpypes.appservice.ClientSSM:response <bacpypes.apdu.AbortPDU(None,1) instance at 0xb6670d90L>
    <bacpypes.apdu.AbortPDU(None,1) instance at 0xb6670d90L>
        pduSource = <Address 192.168.254.101>
        pduDestination = <Address 192.168.254.43>
        pduExpectingReply = False
        pduNetworkPriority = 0
        apduType = 7
        apduSrv = True
        apduInvokeID = 1
        apduAbortRejectReason = 4
        pduData = x''
segmentationNotSupported

Not sure if this is a bug, or just poor configuration on my end. Unfortunately, I am unable to change the segmentation mode of the devices I am trying to read.

If my device requires segmentation for this to work at all, are there any existing examples of how segmentation is implemented that you know of?

Thank you!

JoelBender commented 5 years ago

Segmentation is supported in BACpypes, and while the test coverage is not complete with respect to the 135.1 testing and conformance standard, it has been holding up. Configure your local device object with one of the enumerations you would like to have (segmented receive, transmit, or both), but as you state you can't change the device you are talking to.

Reading the length of the object list should absolutely not require segmentation! The .19.00.1f at the end of the APDU is bothering me, that should be .29.00.

JoelBender commented 5 years ago

Yea, that .19.00 is a context encoded value with the wrong tag number, and the .1f after that is a closing tag. Something weird is going on with your client and the server abort is misleading.

JoelBender commented 5 years ago

Gah! I didn't read the original problem correctly, this is a ReadPropertyMultiple not ReadProperty so the encoding is correct. The request decodes into

    listOfReadAccessSpecs
        [0] objectIdentifier = ('device', 1600011)
            listOfPropertyReferences
                [0] propertyIdentifier = 'objectList'
                    propertyArrayIndex = 0L

Can you check to make sure the device supports this service by reading the protocol services supported property? Maybe the abort it's sending back has the wrong reason code.

ChristianTremblay commented 4 years ago

@pshank have you fixed your issue ?