thingsboard / thingsboard-gateway

Open-source IoT Gateway - integrates devices connected to legacy and third-party systems with ThingsBoard IoT Platform using Modbus, CAN bus, BACnet, BLE, OPC-UA, MQTT, ODBC and REST protocols
https://thingsboard.io/docs/iot-gateway/what-is-iot-gateway/
Apache License 2.0
1.72k stars 829 forks source link

[BUG] BACnet Connector BUG #429

Closed ZHYZhanghaiyan closed 3 years ago

ZHYZhanghaiyan commented 3 years ago

Hello!

Describe the bug

When two bacnet devices are connected, only one bacnet device can be successfully connected to thingsboard. thingsboard-gateway will report the following error:

Error traceback: _""2020-11-12 10:56:49" - ERROR - [bacnet_connector.py] - bacnet_connector - 252 - 'name'" Traceback (most recent call last): File "D:\……\thingsboard-gateway-release-2.5.2\thingsboard_gateway\connectors\bacnet\bacnet_connector.py", line 229, in add_device device_name = device["deviceName"].replace("${" + device_name_tag + "}", data.pop("name")) KeyError: 'name' ""2020-11-12 10:56:49" - ERROR - [bacnet_connector.py] - bacnet_connector - 252 - 'name'" Traceback (most recent call last): File "D:\……\thingsboard-gateway-release-2.5.2\thingsboard_gateway\connectors\bacnet\bacnet_connector.py", line 229, in add_device device_name = device["deviceName"].replace("${" + device_nametag + "}", data.pop("name")) KeyError: 'name'

Connector name (If bug in the some connector): [ BACnet Connector ]

The configuration in bactnet.json is as follows:

Configuration: _{ "general": { "address": "xx.xx.xx.xx", "maxApduLengthAccepted": 1024, "objectIdentifier": 599, "objectName": "TBgateway", "segmentationSupported": "segmentedBoth", "vendorIdentifier": 15 }, "devices": [{ "deviceName": "BACnet Device1 ${objectName}", "deviceType": "default", "keepaliveRound": 3, "pollPeriod": 1000, "address": "xx.xx.xx.xx:52719", "timeseries": [{ "key": "AF-A1", "objectId": "analogInput:0", "propertyId": "presentValue", "type": "double" }] }, { "deviceName": "BACnet Device2 ${objectName}", "deviceType": "default", "keepaliveRound": 3, "pollPeriod": 5000, "address": "xx.xx.xx.xx:64264", "timeseries": [{ "key": "AF-A2", "objectId": "analogInput:1", "propertyId": "presentValue", "type": "double" }] } ] }​

Versions :

After debugging, it is found that the error location is as follows in the add_device(self,data) method of bacbet_connector.py:

def add_device(self, data):
    if self.__devices_address_name.get(data["address"]) is None:
        for device in self.__config_devices:
                try:
                    config_address = Address(device["address"])
                    device_name_tag = TBUtility.get_value(device["deviceName"], get_tag=True)
                    device_name = device["deviceName"].replace("${" + device_name_tag + "}", data.pop("name"))​
                    ​……

                    log.debug(data["address"].addrType)
                except Exception as e:
                    log.exception(e)​

The reason for the error is: if n devices are configured in bactnet.json, the add_device() method will be called n times; each call to this method will traverse n times in the for loop, and each traversal will execute data.pop("name" ) Operation, so that every time the method is called, there is no "name" attribute in the "data" after the first traversal, and data.pop(". name") is also executed for n-1 traversals from the second traversal will cause an error.

Modify the code as follows, and two bacnet devices are successfully connected to thingsboard:

def add_device(self, data):
    if self.__devices_address_name.get(data["address"]) is None:
        for device in self.__config_devices:

            ######Code changes#########
            if device["address"] == data["address"]:

                try:
                    config_address = Address(device["address"])
                    device_name_tag = TBUtility.get_value(device["deviceName"], get_tag=True)
                    device_name = device["deviceName"].replace("${" + device_name_tag + "}", data.pop("name"))
                    ……

                    log.debug(data["address"].addrType)
                except Exception as e:
                    log.exception(e)​

But I am not sure whether this modification will affect the normal operation of other protocols such as MODBUS, BLE, etc., so I will report this problem to you, and want to determine if this problem is a code bug? If so, is my modification correct or reasonable? Or is it that you have fixed this bug?

Above, good luck!

imbeacon commented 3 years ago

Hi @ZHYZhanghaiyan ,

Thank you for your investigations, bacnet_connector.py is use only for BACnet protocol, so you are able to modify it without worries about other connectors. Also, I have added your fix into the gateway, you may get it by pulling from the repository.

ingempo commented 3 years ago

Hi @ZHYZhanghaiyan !

So, to fix the bug, just you add if device["address"] == data["address"]: line? Or it must change another thing?

ZHYZhanghaiyan commented 3 years ago

Hi @ZHYZhanghaiyan !

So, to fix the bug, just you add if device["address"] == data["address"]: line? Or it must change another thing?

Yes, just add this line of code.