ChristianTremblay / BAC0

BAC0 - Library depending on BACpypes3 (Python 3) to build automation script for BACnet applications
GNU Lesser General Public License v3.0
170 stars 98 forks source link

Write on local device with external software #439

Closed Sekiro-kost closed 5 months ago

Sekiro-kost commented 8 months ago

Hello

I have created a script, to create a BACnet device, to add values coming from different sources (loraWan, zigbee, etcc) on this bacnet device, on my Linux machine. I can also update these bacnet points via :

my_device["Current_TempLora"].presentValue = 24

No problem, I can read this information via a third-party program on another machine, on the same network.

However, I can't write to these bacnet points from an external program.

Here's how my device and its points are created:

def start_device(device, arrayCmds):
    logging.debug("Starting BACnet device")
    _new_objects = []
    try:
        for x in arrayCmds:
            formatVariableEnter = type(x['PresentValue'])
            if formatVariableEnter is str:
                continue

            new_object = analog_input(  
                instance=int(x['CmdId']),
                name=str(x['NameCmd']),
                description=str(x['Description']),
                presentValue=formatVariableEnter(x['PresentValue']),
                properties={"units": str(x['Unite'])},
            )

            _new_objects.append(new_object)

        for obj in _new_objects:
            obj.add_objects_to_application(device)

        return device
    except Exception as e:
          logging.error('ERREUR DANS CONSTRUCTION DEVICE BACNET AVEC LA COMMANDE >>>' + str(x['NameCmd']) + '. VERIFIEZ SES PARAMETRES (UNITES etc..) : ' + str(e))
Sekiro-kost commented 8 months ago

I also tried this :

def start_device(device, arrayCmds):
    logging.debug("Starting BACnet device")
    av = []
    try:
        for x in arrayCmds:
            logging.debug(x)

            new_object = create_AV(oid=int(x['CmdId']), name=str(x['NameCmd']), pv=0, pv_writable=True)
            new_object.units = EngineeringUnits(str(x['Unite']))
            new_object.description = CharacterString(str(x['Description']))
            new_object.presentValue = float(x['PresentValue'])         
            av.append(new_object)

        for each in av:
            device.this_application.add_object(each)

        logging.debug(av)        
        return device

With my other software, I try to write on this point, but nothing happens. It works only in my script, I attempt to write with av.presentValue = x.x

bbartling commented 8 months ago

Maybe try glancing at this older issue for a fake air handling unit: https://github.com/ChristianTremblay/BAC0/issues/381

I did all my points with a flag True for is_commandable:

# create AHU duct pressure setpoint point
_new_objects = analog_value(
    name="DAP-SP",
    properties={"units": "inchesOfWater"},
    description="AHU Duct Pressure Setpoint",
    presentValue=1, is_commandable=True
)
Sekiro-kost commented 8 months ago

Maybe try glancing at this older issue for a fake air handling unit: #381

I did all my points with a flag True for is_commandable:

# create AHU duct pressure setpoint point
_new_objects = analog_value(
    name="DAP-SP",
    properties={"units": "inchesOfWater"},
    description="AHU Duct Pressure Setpoint",
    presentValue=1, is_commandable=True
)

Thank you, I will test your solution

Sekiro-kost commented 8 months ago

In my logs, I can see that when I tried to write a null value from my external software :

[2024-01-17 11:01:12]DEBUG : - execution reject: InvalidParameterDatatype('presentValue must be of type Real')

so we can see that something is going on

But If I try a valid value, I no longer get the error, but the value doesn't change on my bacnet device, even with your suggested method

I will try to subscribe COV, and change presentValue in my original script, not by the external programm

bbartling commented 8 months ago

so you need to do something like:

from bacpypes.primitivedata import Real

in your code do a type(var) check or isinstance ... in BACnet there is a bunch of odd ball data types and a Real is one of them which bacpypes can handle... Maybe also look in the bacpypes or BAC0 docs it may have something in there for the different data types.

Here's an example in my code where I have ran into issues like this before too:

    async def update_bacnet_api(self, value):
        electric_meter_obj = self.bacnet.this_application.get_object_name("demand-response-level")
        electric_meter_obj.presentValue = value

        # update adr payload value to the BACnet API
        adr_sig_object = self.bacnet.this_application.get_object_name(
            "demand-response-level"
        )
        adr_sig_object.presentValue = Real(value)

        # update electric meter write value from BAS for open ADR report
        electric_meter_obj = self.bacnet.this_application.get_object_name("power-level")

        # default value is a BACnet primitive data type called Real that
        if isinstance(electric_meter_obj.presentValue, Real):
            self.building_meter = electric_meter_obj.presentValue.value
        else:
            self.building_meter = electric_meter_obj.presentValue

BTW bacpypes3 which is out and BAC0 is in the process of getting a retrofit from legacy bacpypes to the newer async asyncio bacpypes3 version I think all the data types of BACnet will be handled under the hood so in the future hopefully soon you wouldnt even have to worry about this type of stuff....

ChristianTremblay commented 8 months ago

Juste être sûr de comprendre.... You want to create an analog value object in your device on which you could write, via BACnet, from another device. Right ? Like a setpoint.

Sekiro-kost commented 8 months ago

Yes,exactly.

but i re tried this morning,and its works 😉

thanks all

Im just trying right Now to add Cov for Watch the events of writin’asks

But doesnt work for the moment

github-actions[bot] commented 6 months ago

This issue had no activity for a long period of time. If this issue is still required, please update the status or else, it will be closed. Please note that an issue can be reopened if required.