Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions thingsboard_gateway/connectors/bacnet/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def __get_read_access_specifications(self, object_list, vendor_id):
object_id = object['objectId']
if not isinstance(object_id, ObjectIdentifier):
obj_str = f"{object['objectType']},{object_id}"
object_id = ObjectIdentifier(obj_str)
object_id = vendor_info.object_identifier(obj_str)

object_class = vendor_info.get_object_class(object_id[0])
if object_class is None:
Expand All @@ -249,7 +249,7 @@ def __get_read_access_specifications(self, object_list, vendor_id):
object['propertyId'] = {object['propertyId']}

for prop in object['propertyId']:
property_identifier = PropertyIdentifier(prop)
property_identifier = vendor_info.property_identifier(prop)

properties.append(property_identifier)

Expand Down Expand Up @@ -324,12 +324,12 @@ def decode_tag_list(self, tag_list, vendor_id):
result_list = []

for read_access_result in tag_list.listOfReadAccessResults:
object_identifier = read_access_result.objectIdentifier
object_identifier = vendor_info.object_identifier(read_access_result.objectIdentifier)
object_class = vendor_info.get_object_class(object_identifier[0])

for read_access_result_element in read_access_result.listOfResults:
try:
property_identifier = read_access_result_element.propertyIdentifier
property_identifier = vendor_info.property_identifier(read_access_result_element.propertyIdentifier)
property_array_index = read_access_result_element.propertyArrayIndex
read_result = read_access_result_element.readResult

Expand Down
4 changes: 4 additions & 0 deletions thingsboard_gateway/connectors/bacnet/bacnet_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from thingsboard_gateway.gateway.statistics.statistics_service import StatisticsService
from thingsboard_gateway.tb_utility.tb_logger import init_logger
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
from thingsboard_gateway.tb_utility.tb_loader import TBModuleLoader

try:
from bacpypes3.apdu import ErrorRejectAbortNack
Expand Down Expand Up @@ -73,6 +74,9 @@ def __init__(self, gateway, config, connector_type):
self.__parse_ede_config()
self.__log.debug('EDE config parsed')

# importing the proprietary package registers all available custom object types and properties
TBModuleLoader.import_package_files(connector_type, "proprietary")

if BackwardCompatibilityAdapter.is_old_config(config):
backward_compatibility_adapter = BackwardCompatibilityAdapter(config, self.__log)
self.__config = backward_compatibility_adapter.convert()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ def convert(self, config, data):

converted_values = self.__convert_data(values_group)
if len(converted_values) > 0:
data_key, unsed_values = self.__get_data_key_name(item_config['key'], converted_values)
data_key, unused_values = self.__get_data_key_name(item_config['key'], converted_values)

if len(unsed_values) == 1:
if len(unused_values) == 1:
datapoint_key = TBUtility.convert_key_to_datapoint_key(data_key,
device_report_strategy,
item_config,
self.__log)
converted_data_append_methods[item_config['type']]({datapoint_key: round(unsed_values[0]['value'], 2) if isinstance(unsed_values[0]['value'], float) else str(unsed_values[0]['value'])}) # noqa
converted_data_append_methods[item_config['type']]({datapoint_key: round(unused_values[0]['value'], 2) if isinstance(unused_values[0]['value'], float) else str(unused_values[0]['value'])}) # noqa
else:
for item in unsed_values:
for item in unused_values:
datapoint_key = TBUtility.convert_key_to_datapoint_key(f'{data_key}.{item["propName"]}',
device_report_strategy,
item_config,
Expand Down
78 changes: 78 additions & 0 deletions thingsboard_gateway/extensions/bacnet/proprietary/desigo_cc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""
# Siemens Desigo CC
# Register proprietary Objects and Properties
"""

from bacpypes3.constructeddata import ArrayOf
from bacpypes3.vendor import VendorInfo
from bacpypes3.basetypes import PropertyIdentifier
from bacpypes3.object import AnalogInputObject as _AnalogInputObject
from bacpypes3.object import PulseConverterObject as _PulseConverterObject
from bacpypes3.object import AnalogValueObject as _AnalogValueObject
from bacpypes3.object import DeviceObject as _DeviceObject
from bacpypes3.object import NetworkPortObject as _NetworkPortObject
from bacpypes3.primitivedata import (
ObjectType,
CharacterString,
)


# this vendor identifier reference is used when registering custom classes
_vendor_id = 7
_vendor_name = "Siemens Building Technologies"


class ProprietaryObjectType(ObjectType):
"""
This is a list of the object type enumerations for proprietary object types,
see Clause 23.4.1.
"""

pass


class ProprietaryPropertyIdentifier(PropertyIdentifier):
"""
This is a list of the property identifiers that are used in custom object
types or are used in custom properties of standard types.
"""

descriptionList = 3121


# create a VendorInfo object for this custom application before registering
# specialize object classes
_desigo_cc = VendorInfo(
_vendor_id, ProprietaryObjectType, ProprietaryPropertyIdentifier
)


class DesigoCCDeviceObject(_DeviceObject):
"""
When running as an instance of this custom device, the DeviceObject is
an extension of the one defined in bacpypes3.device
"""

descriptionList: CharacterString


class NetworkPortObject(_NetworkPortObject):
"""
When running as an instance of this custom device, the NetworkPortObject is
an extension of the one defined in bacpypes3.networkport (in this
case doesn't add any proprietary properties).
"""

pass


class DesigoCCAnalogInputObject(_AnalogInputObject):
descriptionList: ArrayOf(CharacterString)


class DesigoCCPulseConverterObject(_PulseConverterObject):
descriptionList: ArrayOf(CharacterString)


class DesigoCCAnalogValueObject(_AnalogValueObject):
descriptionList: ArrayOf(CharacterString)
29 changes: 29 additions & 0 deletions thingsboard_gateway/tb_utility/tb_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#

from importlib.util import module_from_spec, spec_from_file_location
from importlib import import_module
from inspect import getmembers, isclass
from logging import getLogger, setLoggerClass
from os import listdir, path
Expand Down Expand Up @@ -81,3 +82,31 @@ def import_module(extension_type, module_name):
log.error("Error while importing module %s from %s.", module_name, current_extension_path, exc_info=e)
errors.append(e)
return errors

@staticmethod
def import_package_files(extension_type, package_name):
errors = []
if len(TBModuleLoader.PATHS) == 0:
TBModuleLoader.find_paths()
try:
for current_path in TBModuleLoader.PATHS:
current_extension_path = current_path + path.sep + extension_type
package_path = current_extension_path + path.sep + package_name
if path.exists(package_path):
for file in listdir(package_path):
if not file.startswith("__") and (file.endswith(".py") or file.endswith(".pyc")):
try:
module_name, _ = path.splitext(file)
module = f'{package_path.replace("/", ".")}.{module_name}'
if module.startswith("."):
module = module[1:]
log.info("Import %s from %s.", module, package_path)
import_module(module)
except ImportError as e:
log.info(e.msg)
errors.append(e.msg)
continue
except Exception as e:
log.error("Error while importing package %s from %s.", package_name, package_path, exc_info=e)
errors.append(e)
return errors
Loading