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

NotificationClassObject - recipient, how to set correctly? #366

Open SQ9MDD opened 4 years ago

SQ9MDD commented 4 years ago

Hi.

I'm stuck. I created a BV object that is related to the EVC object. However, I cannot correctly set the recipient list.

My code for EVC:

some_destination = Destination(
        validDays=[1, 1, 1, 1, 1, 1, 1],
        fromTime=(0, 0, 0, 0),
        toTime=(23, 59, 59, 99),
        recipient=Recipient(device=('objectIdentifier', 12345)),  
        processIdentifier=1,
        issueConfirmedNotifications=True,
        transitions=[1, 1, 1],
    )

    some_object = NotificationClassObject(
        objectIdentifier=('notificationClass', 1),
        objectType='notificationClass',
        objectName='ALARM',
        notificationClass=1,
        priority=ArrayOf(Unsigned)([255, 255, 255]),
        ackRequired=[1, 1, 1],
        recipientList=SequenceOf(Destination)([some_destination]),
    )    
    device.add_object(some_object)

And the error is:

exception: TypeError('invalid result datatype, expecting ListOfDestination and got SequenceOfDestination') Traceback (most recent call last): File "C:\Python38-32\lib\site-packages\bacpypes\app.py", line 382, in indication helperFn(apdu) File "C:\Python38-32\lib\site-packages\bacpypes\service\object.py", line 320, in do_ReadPropertyMultipleRequest read_access_result_element = read_property_to_result_element(obj, propertyIdentifier, propertyArrayIndex) File "C:\Python38-32\lib\site-packages\bacpypes\service\object.py", line 206, in read_property_to_result_element read_result.propertyValue = read_property_to_any(obj, propertyIdentifier, propertyArrayIndex) File "C:\Python38-32\lib\site-packages\bacpypes\service\object.py", line 177, in read_property_to_any raise TypeError("invalid result datatype, expecting %s and got %s" \ TypeError: invalid result datatype, expecting ListOfDestination and got SequenceOfDestination exception: TypeError('invalid constructor datatype') Traceback (most recent call last): File "C:\Python38-32\lib\site-packages\bacpypes\app.py", line 382, in indication helperFn(apdu) File "C:\Python38-32\lib\site-packages\bacpypes\service\object.py", line 75, in do_ReadPropertyRequest value = datatype(value) File "C:\Python38-32\lib\site-packages\bacpypes\constructeddata.py", line 575, in __init__ raise TypeError("invalid constructor datatype") TypeError: invalid constructor datatype

Recipient list tab in EVC object is empty:

obraz

Is any way to set recipient list like adressess or broadcast ?

SQ9MDD commented 4 years ago

OK

One step forward...

    some_destination = Destination(
        validDays=[1, 1, 1, 1, 1, 1, 1],
        fromTime=(0, 0, 0, 0),
        toTime=(23, 59, 59, 99),
        recipient=Recipient(device=this_device.objectIdentifier),
        processIdentifier=1,
        issueConfirmedNotifications=True,
        transitions=[1, 1, 1],
    )

    some_object = NotificationClassObject(
        objectIdentifier=('notificationClass', 1),
        description='Maintenance EVC',
        objectType='notificationClass',
        objectName='Maintenance',
        notificationClass=1,
        priority=ArrayOf(Unsigned)([70, 80, 190]),
        ackRequired=[1, 1, 1],
        recipientList=ListOf(Destination)([some_destination]),
    )    
    device.add_object(some_object)

It seems to work that way, at least it doesn't end up with an error message.

obraz

But i need to change this:

device=this_device.objectIdentifier

to Broadcast to everyone in my loco network.

Any advice?

JoelBender commented 4 years ago

Notice in basetypes that a Recipient is a choice between a device and an address, and that the address is a DeviceAddress, which has a networkNumber and macAddress. The special network number zero (0) can be used for the local network, and the MAC address would be the octet string version of the broadcast address for the network.

Note: I have not tried this, but if your local address is 192.168.1.12/24, the result should be:

Recipient(address=DeviceAddress(networkNumber=0, maxAddress=Address("192.168.1.255").addrAddr))
SQ9MDD commented 4 years ago

Hi Joel thanx 4 your answer.

I did as you wrote. I had to add more:

from bacpypes.pdu import Address
from bacpypes.basetypes import Destination, Recipient, DeviceAddress

Unfortunately, it ended with another error message:

Traceback (most recent call last):
  File "E:\Dropbox\algorytmy-python\BacNetTelegramGW\source\gateway.py", line 231, in <module>
    main()
  File "E:\Dropbox\algorytmy-python\BacNetTelegramGW\source\gateway.py", line 159, in main
    recipient=Recipient(address=DeviceAddress(networkNumber=0, maxAddress=Address("192.168.88.255").addrAddr)),
  File "C:\Python38-32\lib\site-packages\bacpypes\constructeddata.py", line 72, in __init__
    super(Sequence, self).__init__(*args, **other_kwargs)
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
SQ9MDD commented 4 years ago

Next little step.

It should be: macAddress not maxAddress

this code works without error but notifications are not send to my OWS:

    some_destination = Destination(
        validDays=[1, 1, 1, 1, 1, 1, 1],
        fromTime=(0, 0, 0, 0),
        toTime=(23, 59, 59, 99),
        #recipient=Recipient(device=('device',32123)),
        recipient=Recipient(address=DeviceAddress(networkNumber=0, macAddress=Address("10.9.48.255").addrAddr)),
        #recipient=Recipient(device=(this_device.objectIdentifier)),
        processIdentifier=1,
        issueConfirmedNotifications=True,
        transitions=[1, 0, 0],
    )

I check few variants of destination host IP address, mac adress, also broadcast ip, brodcast mac. Something is missing and I can't understand how to send a notification to others.

For example: recipient brodcast mac obraz

recipient ip specific host with OWS obraz

recipient brodcast ip: obraz

kasper0 commented 4 years ago

Could you please capture your network traffic and share with us? It would be great to see the configuration of BV/EC as well. Are you sure that after registering the recipient, there is an event, which causes the transition to the "ToAlarm" state?

henrisokka commented 3 years ago

Hey, commenting here as not sure if I should add a new issue or not.

When following the example seen above I get an error invalid constructor datatype

notify_obj = NotificationClassObject(
        objectName='alarms',
        objectIdentifier=("notificationClass", notification_class),
        notificationClass=Unsigned(1),
        priority=ArrayOf(Unsigned)(None),
        ackRequired=EventTransitionBits([0, 1, 0]),
        recipientList=ListOf(Destination)([some_destination]),
        reliabilityEvaluationInhibit=Boolean(True)
    )

error:

[BACNET] apdu data: {'function': 'ReadPropertyRequest', 'objectIdentifier': ('notificationClass', 1), 'propertyIdentifier': 'recipientList'})
exception: TypeError('invalid constructor datatype')
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/bacpypes/app.py", line 382, in indication
    helperFn(apdu)
  File "/usr/local/lib/python3.9/site-packages/bacpypes/service/object.py", line 75, in do_ReadPropertyRequest
    value = datatype(value)
  File "/usr/local/lib/python3.9/site-packages/bacpypes/constructeddata.py", line 575, in __init__
    raise TypeError("invalid constructor datatype")
TypeError: invalid constructor datatype
Message from Kafka, checking if site is testingsite in

However when passing just an array to recipient list I get no error: recipientList=[some_destination]

Is this a bug or am I missing something?