Example #1
0
    def convert(self, _, body):
        try:
            data = body["data"]["value"]
            self.dict_result["deviceName"] = TBUtility.get_value(
                self.__config.get("deviceNameJsonExpression"),
                body,
                expression_instead_none=True)
            self.dict_result["deviceType"] = TBUtility.get_value(
                self.__config.get("deviceTypeJsonExpression"),
                body,
                expression_instead_none=True)
            self.dict_result["attributes"] = []
            self.dict_result["telemetry"] = []
            converted_bytes = bytearray.fromhex(data)
            if self.__config.get("extension-config") is not None:
                for telemetry_key in self.__config["extension-config"]:
                    value = None
                    byteorder = telemetry_key.get("byteorder", "big").lower()
                    signed = telemetry_key.get("signed", True)
                    if telemetry_key.get("byteAddress") is None:
                        interest_bytes = converted_bytes[
                            telemetry_key["fromByte"]:telemetry_key["toByte"]]
                        if telemetry_key["type"] == "float":
                            value = struct.unpack(
                                ">f" if byteorder == "big" else "<f",
                                interest_bytes)
                            value = value[0] if isinstance(value,
                                                           list) else None
                        if telemetry_key["type"] == "int":
                            value = int.from_bytes(interest_bytes,
                                                   byteorder=byteorder,
                                                   signed=signed)
                    else:
                        interest_byte = converted_bytes[
                            telemetry_key["byteAddress"]]
                        bits = "{0:{fill}8b}".format(interest_byte, fill='0')
                        bits = bits if byteorder == "big" else bits[::-1]
                        value = int(
                            bits[::-1][telemetry_key.get("fromBit"):
                                       telemetry_key.get("toBit")][::-1], 2)
                    if value is not None:
                        value = value * telemetry_key.get("multiplier", 1)
                        telemetry_to_send = {
                            telemetry_key["key"]: value
                        }  # creating telemetry data for sending into Thingsboard
                        # current_byte_position += self.__config["extension-config"][telemetry_key]
                        self.dict_result["telemetry"].append(
                            telemetry_to_send
                        )  # adding data to telemetry array
            else:
                self.dict_result["telemetry"] = {
                    "data": int(body, 0)
                }  # if no specific configuration in config file - just send data which received
            return self.dict_result

        except Exception as e:
            log.error(
                'Error in converter, for config: \n%s\n and message: \n%s\n',
                dumps(self.__config), body)
            log.exception(e)
Example #2
0
 def __get_converter(self, config, need_uplink):
     if config is None:
         return BytesCanUplinkConverter(
         ) if need_uplink else BytesCanDownlinkConverter()
     else:
         if need_uplink:
             uplink = config.get("uplink")
             return BytesCanUplinkConverter() if uplink is None \
                 else TBUtility.check_and_import(self.__connector_type, uplink)
         else:
             downlink = config.get("downlink")
             return BytesCanDownlinkConverter() if downlink is None \
                 else TBUtility.check_and_import(self.__connector_type, downlink)
 def __prepare_connectors_configuration(self, input_connector_config):
     try:
         self.__gateway.connectors_configs = {}
         for connector in input_connector_config['thingsboard'][
                 'connectors']:
             for input_connector in input_connector_config[
                     connector['type']]:
                 if input_connector['name'] == connector['name']:
                     if not self.__gateway.connectors_configs.get(
                             connector['type']):
                         self.__gateway.connectors_configs[
                             connector['type']] = []
                     self.__gateway.connectors_configs[
                         connector['type']].append({
                             "name": connector["name"],
                             "config": {
                                 connector['configuration']:
                                 input_connector["config"]
                             }
                         })
                     connector_class = TBUtility.check_and_import(
                         connector["type"],
                         self.__gateway._default_connectors.get(
                             connector["type"], connector.get("class")))
                     self.__gateway._implemented_connectors[
                         connector["type"]] = connector_class
     except Exception as e:
         LOG.exception(e)
Example #4
0
 def update(self):
     if self.__version["latest_version"] != self.__version[
             "current_version"]:
         result = TBUtility.install_package(
             "thingsboard-gateway", self.__version["latest_version"])
     else:
         result = "Congratulations! You have the latest version."
     return result
Example #5
0
 def __init__(self, gateway, config, connector_type):
     self.__connector_type = connector_type
     self.statistics = {'MessagesReceived': 0, 'MessagesSent': 0}
     super().__init__()
     self.__config = config
     self.setName(
         config.get(
             'name',
             'BACnet ' + ''.join(choice(ascii_lowercase)
                                 for _ in range(5))))
     self.__devices = []
     self.__device_indexes = {}
     self.__devices_address_name = {}
     self.__gateway = gateway
     self._application = TBBACnetApplication(self, self.__config)
     self.__bacnet_core_thread = Thread(target=run,
                                        name="BACnet core thread")
     self.__bacnet_core_thread.start()
     self.__stopped = False
     self.__config_devices = self.__config["devices"]
     self.default_converters = {
         "uplink_converter":
         TBUtility.check_and_import(self.__connector_type,
                                    "BACnetUplinkConverter"),
         "downlink_converter":
         TBUtility.check_and_import(self.__connector_type,
                                    "BACnetDownlinkConverter")
     }
     self.__request_functions = {
         "writeProperty": self._application.do_write_property,
         "readProperty": self._application.do_read_property
     }
     self.__available_object_resources = {}
     self.rpc_requests_in_progress = {}
     self.__connected = False
     self.daemon = True
Example #6
0
 def __load_converters(self, device):
     datatypes = [
         "attributes", "telemetry", "attribute_updates", "server_side_rpc"
     ]
     for datatype in datatypes:
         for datatype_config in device.get(datatype, []):
             try:
                 for converter_type in self.default_converters:
                     converter_object = self.default_converters[
                         converter_type] if datatype_config.get(
                             "class"
                         ) is None else TBUtility.check_and_import(
                             self.__connector_type, device.get("class"))
                     datatype_config[converter_type] = converter_object(
                         device)
             except Exception as e:
                 log.exception(e)
Example #7
0
    def send_to_storage(self, connector_name, data):
        #print("[TBGatewayService send_to_storage]",connector_name,data)
        if not connector_name == self.name:
            if not TBUtility.validate_converted_data(data):
                log.error("Data from %s connector is invalid.", connector_name)
                return None
            if data["deviceName"] not in self.get_devices():
                self.add_device(
                    data["deviceName"],
                    {"connector": self.available_connectors[connector_name]},
                    wait_for_publish=True,
                    device_type=data["deviceType"])
            if not self.__connector_incoming_messages.get(connector_name):
                self.__connector_incoming_messages[connector_name] = 0
            else:
                self.__connector_incoming_messages[connector_name] += 1
        else:
            data["deviceName"] = "currentThingsBoardGateway"

        telemetry = {}
        telemetry_with_ts = []
        for item in data["telemetry"]:
            if item.get("ts") is None:
                telemetry = {**telemetry, **item}
            else:
                telemetry_with_ts.append({
                    "ts": item["ts"],
                    "values": {
                        **item["values"]
                    }
                })
        if telemetry_with_ts:
            data["telemetry"] = telemetry_with_ts
        else:
            data["telemetry"] = {"ts": int(time() * 1000), "values": telemetry}

        json_data = dumps(data)
        #print("[TBGatewayService send_to_storage json_data]",json_data)
        save_result = self._event_storage.put(json_data)
        if not save_result:
            log.error(
                'Data from the device "%s" cannot be saved, connector name is %s.',
                data["deviceName"], connector_name)
Example #8
0
    def add_device(self, data):
        if self.__devices_address_name.get(data["address"]) is None:
            for device in self.__config_devices:
                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"))
                        device_information = {
                            **data,
                            **self.__get_requests_configs(device),
                            "type":
                            device["deviceType"],
                            "config":
                            device,
                            "attributes":
                            device.get("attributes", []),
                            "telemetry":
                            device.get("timeseries", []),
                            "poll_period":
                            device.get("pollPeriod", 5000),
                            "deviceName":
                            device_name,
                        }
                        if config_address == data["address"] or \
                                (config_address, GlobalBroadcast) or \
                                (isinstance(config_address, LocalBroadcast) and isinstance(device["address"], LocalStation)) or \
                                (isinstance(config_address, (LocalStation, RemoteStation)) and isinstance(data["address"], (
                                LocalStation, RemoteStation))):
                            self.__devices_address_name[data[
                                "address"]] = device_information["deviceName"]
                            self.__devices.append(device_information)

                        log.debug(data["address"].addrType)
                    except Exception as e:
                        log.exception(e)
Example #9
0
    def _on_message(self, client, userdata, message):
        self.statistics['MessagesReceived'] += 1
        content = TBUtility.decode(message)
        #print("[MqttConnector] content", content)
        # Check if message topic exists in mappings "i.e., I'm posting telemetry/attributes" ---------------------------
        topic_handlers = [regex for regex in self.__mapping_sub_topics if fullmatch(regex, message.topic)]
        # for regex in self.__mapping_sub_topics:
        #     print("[MqttConnector] self.__mapping_sub_topics",regex)

        if topic_handlers:
            # Note: every topic may be associated to one or more converter. This means that a single MQTT message
            # may produce more than one message towards ThingsBoard. This also means that I cannot return after
            # the first successful conversion: I got to use all the available ones.
            # I will use a flag to understand whether at least one converter succeeded
            request_handled = False

            for topic in topic_handlers:
                available_converters = self.__mapping_sub_topics[topic]
                for converter in available_converters:
                    try:
                        converted_content = converter.convert(message.topic, content)
                        #print("[MqttConnector] converted_content", converted_content)

                        if converted_content:
                            request_handled = True
                            self.__gateway.send_to_storage(self.name, converted_content)
                            self.statistics['MessagesSent'] += 1
                            self.__log.debug("Successfully converted message from topic %s", message.topic)
                        else:
                            continue
                    except Exception as e:
                        log.exception(e)

            if not request_handled:
                self.__log.error('Cannot find converter for the topic:"%s"! Client: %s, User data: %s',
                                 message.topic,
                                 str(client),
                                 str(userdata))

            # Note: if I'm in this branch, this was for sure a telemetry/attribute push message
            # => Execution must end here both in case of failure and success
            return None

        # Check if message topic exists in connection handlers "i.e., I'm connecting a device" -------------------------
        topic_handlers = [regex for regex in self.__connect_requests_sub_topics if fullmatch(regex, message.topic)]
        if topic_handlers:
            for topic in topic_handlers:
                handler = self.__connect_requests_sub_topics[topic]

                found_device_name = None
                found_device_type = 'default'

                # Get device name, either from topic or from content
                if handler.get("deviceNameTopicExpression"):
                    device_name_match = search(handler["deviceNameTopicExpression"], message.topic)
                    if device_name_match is not None:
                        found_device_name = device_name_match.group(0)
                elif handler.get("deviceNameJsonExpression"):
                    found_device_name = TBUtility.get_value(handler["deviceNameJsonExpression"], content)

                # Get device type (if any), either from topic or from content
                if handler.get("deviceTypeTopicExpression"):
                    device_type_match = search(handler["deviceTypeTopicExpression"], message.topic)
                    found_device_type = device_type_match.group(0) if device_type_match is not None else handler["deviceTypeTopicExpression"]
                elif handler.get("deviceTypeJsonExpression"):
                    found_device_type = TBUtility.get_value(handler["deviceTypeJsonExpression"], content)

                if found_device_name is None:
                    self.__log.error("Device name missing from connection request")
                    continue

                # Note: device must be added even if it is already known locally: else ThingsBoard
                # will not send RPCs and attribute updates
                self.__log.info("Connecting device %s of type %s", found_device_name, found_device_type)
                self.__gateway.add_device(found_device_name, {"connector": self}, device_type=found_device_type)

            # Note: if I'm in this branch, this was for sure a connection message
            # => Execution must end here both in case of failure and success
            return None

        # Check if message topic exists in disconnection handlers "i.e., I'm disconnecting a device" -------------------
        topic_handlers = [regex for regex in self.__disconnect_requests_sub_topics if fullmatch(regex, message.topic)]
        if topic_handlers:
            for topic in topic_handlers:
                handler = self.__disconnect_requests_sub_topics[topic]

                found_device_name = None
                found_device_type = 'default'

                # Get device name, either from topic or from content
                if handler.get("deviceNameTopicExpression"):
                    device_name_match = search(handler["deviceNameTopicExpression"], message.topic)
                    if device_name_match is not None:
                        found_device_name = device_name_match.group(0)
                elif handler.get("deviceNameJsonExpression"):
                    found_device_name = TBUtility.get_value(handler["deviceNameJsonExpression"], content)

                # Get device type (if any), either from topic or from content
                if handler.get("deviceTypeTopicExpression"):
                    device_type_match = search(handler["deviceTypeTopicExpression"], message.topic)
                    if device_type_match is not None:
                        found_device_type = device_type_match.group(0)
                elif handler.get("deviceTypeJsonExpression"):
                    found_device_type = TBUtility.get_value(handler["deviceTypeJsonExpression"], content)

                if found_device_name is None:
                    self.__log.error("Device name missing from disconnection request")
                    continue

                if found_device_name in self.__gateway.get_devices():
                    self.__log.info("Disconnecting device %s of type %s", found_device_name, found_device_type)
                    self.__gateway.del_device(found_device_name)
                else:
                    self.__log.info("Device %s was not connected", found_device_name)

                break

            # Note: if I'm in this branch, this was for sure a disconnection message
            # => Execution must end here both in case of failure and success
            return None

        # Check if message topic exists in attribute request handlers "i.e., I'm asking for a shared attribute" --------
        topic_handlers = [regex for regex in self.__attribute_requests_sub_topics if fullmatch(regex, message.topic)]
        if topic_handlers:
            try:
                for topic in topic_handlers:
                    handler = self.__attribute_requests_sub_topics[topic]

                    found_device_name = None
                    found_attribute_name = None

                    # Get device name, either from topic or from content
                    if handler.get("deviceNameTopicExpression"):
                        device_name_match = search(handler["deviceNameTopicExpression"], message.topic)
                        if device_name_match is not None:
                            found_device_name = device_name_match.group(0)
                    elif handler.get("deviceNameJsonExpression"):
                        found_device_name = TBUtility.get_value(handler["deviceNameJsonExpression"], content)

                    # Get attribute name, either from topic or from content
                    if handler.get("attributeNameTopicExpression"):
                        attribute_name_match = search(handler["attributeNameTopicExpression"], message.topic)
                        if attribute_name_match is not None:
                            found_attribute_name = attribute_name_match.group(0)
                    elif handler.get("attributeNameJsonExpression"):
                        found_attribute_name = TBUtility.get_value(handler["attributeNameJsonExpression"], content)

                    if found_device_name is None:
                        self.__log.error("Device name missing from attribute request")
                        continue

                    if found_attribute_name is None:
                        self.__log.error("Attribute name missing from attribute request")
                        continue

                    self.__log.info("Will retrieve attribute %s of %s", found_attribute_name, found_device_name)
                    self.__gateway.tb_client.client.gw_request_shared_attributes(
                        found_device_name,
                        [found_attribute_name],
                        lambda data, *args: self.notify_attribute(
                            data,
                            found_attribute_name,
                            handler.get("topicExpression"),
                            handler.get("valueExpression")))

                    break

            except Exception as e:
                log.exception(e)

            # Note: if I'm in this branch, this was for sure an attribute request message
            # => Execution must end here both in case of failure and success
            return None

        # Check if message topic exists in RPC handlers ----------------------------------------------------------------
        # The gateway is expecting for this message => no wildcards here, the topic must be evaluated as is
        if message.topic in self.__gateway.rpc_requests_in_progress:
            self.__gateway.rpc_with_reply_processing(message.topic, content)
            return None

        self.__log.debug("Received message to topic \"%s\" with unknown interpreter data: \n\n\"%s\"",
                         message.topic,
                         content)
Example #10
0
    def _on_connect(self, client, userdata, flags, result_code, *extra_params):

        result_codes = {
            1: "incorrect protocol version",
            2: "invalid client identifier",
            3: "server unavailable",
            4: "bad username or password",
            5: "not authorised",
            }

        if result_code == 0:
            self._connected = True
            self.__log.info('%s connected to %s:%s - successfully.',
                            self.get_name(),
                            self.__broker["host"],
                            self.__broker.get("port", "1883"))

            self.__log.debug("Client %s, userdata %s, flags %s, extra_params %s",
                             str(client),
                             str(userdata),
                             str(flags),
                             extra_params)

            self.__mapping_sub_topics = {}

            # Setup data upload requests handling ----------------------------------------------------------------------
            for mapping in self.__mapping:
                try:
                    # Load converter for this mapping entry ------------------------------------------------------------
                    # mappings are guaranteed to have topicFilter and converter fields. See __init__
                    default_converter_class_name = "JsonMqttUplinkConverter"
                    # Get converter class from "extension" parameter or default converter
                    converter_class_name = mapping["converter"].get("extension", default_converter_class_name)
                    # Find and load required class
                    module = TBModuleLoader.import_module(self._connector_type, converter_class_name)
                    if module:
                        self.__log.debug('Converter %s for topic %s - found!', converter_class_name, mapping["topicFilter"])
                        converter = module(mapping)
                    else:
                        self.__log.error("Cannot find converter for %s topic", mapping["topicFilter"])
                        continue

                    # Setup regexp topic acceptance list ---------------------------------------------------------------
                    regex_topic = TBUtility.topic_to_regex(mapping["topicFilter"])

                    # There may be more than one converter per topic, so I'm using vectors
                    if not self.__mapping_sub_topics.get(regex_topic):
                        self.__mapping_sub_topics[regex_topic] = []

                    self.__mapping_sub_topics[regex_topic].append(converter)

                    # Subscribe to appropriate topic -------------------------------------------------------------------
                    self.__subscribe(mapping["topicFilter"], mapping.get("subscriptionQos", 1))

                    self.__log.info('Connector "%s" subscribe to %s',
                                    self.get_name(),
                                    TBUtility.regex_to_topic(regex_topic))

                except Exception as e:
                    self.__log.exception(e)

            # Setup connection requests handling -----------------------------------------------------------------------
            for request in [entry for entry in self.__connect_requests if entry is not None]:
                # requests are guaranteed to have topicFilter field. See __init__
                self.__subscribe(request["topicFilter"], request.get("subscriptionQos", 1))
                topic_filter = TBUtility.topic_to_regex(request.get("topicFilter"))
                self.__connect_requests_sub_topics[topic_filter] = request

            # Setup disconnection requests handling --------------------------------------------------------------------
            for request in [entry for entry in self.__disconnect_requests if entry is not None]:
                # requests are guaranteed to have topicFilter field. See __init__
                self.__subscribe(request["topicFilter"], request.get("subscriptionQos", 1))
                topic_filter = TBUtility.topic_to_regex(request.get("topicFilter"))
                self.__disconnect_requests_sub_topics[topic_filter] = request

            # Setup attributes requests handling -----------------------------------------------------------------------
            for request in [entry for entry in self.__attribute_requests if entry is not None]:
                # requests are guaranteed to have topicFilter field. See __init__
                self.__subscribe(request["topicFilter"], request.get("subscriptionQos", 1))
                topic_filter = TBUtility.topic_to_regex(request.get("topicFilter"))
                self.__attribute_requests_sub_topics[topic_filter] = request

        else:
            if result_code in result_codes:
                self.__log.error("%s connection FAIL with error %s %s!", self.get_name(), result_code, result_codes[result_code])
            else:
                self.__log.error("%s connection FAIL with unknown error!", self.get_name())
Example #11
0
 def __search_general_info(self, device):
     result = []
     match_devices = []
     self.__search_node(self.__opcua_nodes["root"],
                        TBUtility.get_value(device["deviceNodePattern"],
                                            get_tag=True),
                        result=match_devices)
     for device_node in match_devices:
         if device_node is not None:
             result_device_dict = {
                 "deviceName": None,
                 "deviceType": None,
                 "deviceNode": device_node,
                 "configuration": deepcopy(device)
             }
             name_pattern_config = device["deviceNamePattern"]
             name_expression = TBUtility.get_value(name_pattern_config,
                                                   get_tag=True)
             if "${" in name_pattern_config and "}" in name_pattern_config:
                 log.debug("Looking for device name")
                 device_name_from_node = ""
                 if name_expression == "$DisplayName":
                     device_name_from_node = device_node.get_display_name(
                     ).Text
                 elif name_expression == "$BrowseName":
                     device_name_from_node = device_node.get_browse_name(
                     ).Name
                 elif name_expression == "$NodeId.Identifier":
                     device_name_from_node = str(
                         device_node.nodeid.Identifier)
                 else:
                     name_path = self._check_path(name_expression,
                                                  device_node)
                     device_name_node = []
                     self.__search_node(device_node,
                                        name_path,
                                        result=device_name_node)
                     device_name_node = device_name_node[0]
                     if device_name_node is not None:
                         device_name_from_node = device_name_node.get_value(
                         )
                 if device_name_from_node == "":
                     log.error(
                         "Device name node not found with expression: %s",
                         name_expression)
                     return None
                 full_device_name = name_pattern_config.replace(
                     "${" + name_expression + "}",
                     str(device_name_from_node)).replace(
                         name_expression, str(device_name_from_node))
             else:
                 full_device_name = name_expression
             result_device_dict["deviceName"] = full_device_name
             log.debug("Device name: %s", full_device_name)
             if device.get("deviceTypePattern"):
                 device_type_expression = TBUtility.get_value(
                     device["deviceTypePattern"], get_tag=True)
                 if "${" in device_type_expression and "}" in device_type_expression:
                     type_path = self._check_path(device_type_expression,
                                                  device_node)
                     device_type_node = []
                     self.__search_node(device_node,
                                        type_path,
                                        result=device_type_node)
                     device_type_node = device_type_node[0]
                     if device_type_node is not None:
                         device_type = device_type_node.get_value()
                         full_device_type = device_type_expression.replace(
                             "${" + device_type_expression + "}",
                             device_type).replace(device_type_expression,
                                                  device_type)
                     else:
                         log.error(
                             "Device type node not found with expression: %s",
                             device_type_expression)
                         full_device_type = "default"
                 else:
                     full_device_type = device_type_expression
                 result_device_dict["deviceType"] = full_device_type
                 log.debug("Device type: %s", full_device_type)
             else:
                 result_device_dict["deviceType"] = "default"
             result.append(result_device_dict)
         else:
             log.error(
                 "Device node not found with expression: %s",
                 TBUtility.get_value(device["deviceNodePattern"],
                                     get_tag=True))
     return result
Example #12
0
 def __search_nodes_and_subscribe(self, device_info):
     sub_nodes = []
     information_types = {
         "attributes": "attributes",
         "timeseries": "telemetry"
     }
     for information_type in information_types:
         for information in device_info["configuration"][information_type]:
             information_key = information["key"]
             config_path = TBUtility.get_value(information["path"],
                                               get_tag=True)
             information_path = self._check_path(config_path,
                                                 device_info["deviceNode"])
             information["path"] = '${%s}' % information_path
             information_nodes = []
             self.__search_node(device_info["deviceNode"],
                                information_path,
                                result=information_nodes)
             for information_node in information_nodes:
                 if information_node is not None:
                     try:
                         information_value = information_node.get_value()
                     except:
                         log.error("Err get_value: %s",
                                   str(information_node))
                         continue
                     log.debug(
                         "Node for %s \"%s\" with path: %s - FOUND! Current values is: %s",
                         information_type, information_key,
                         information_path, str(information_value))
                     if device_info.get("uplink_converter") is None:
                         configuration = {
                             **device_info["configuration"], "deviceName":
                             device_info["deviceName"],
                             "deviceType":
                             device_info["deviceType"]
                         }
                         if device_info["configuration"].get(
                                 'converter') is None:
                             converter = OpcUaUplinkConverter(configuration)
                         else:
                             converter = TBModuleLoader.import_module(
                                 self._connector_type, configuration)
                         device_info["uplink_converter"] = converter
                     else:
                         converter = device_info["uplink_converter"]
                     self.subscribed[information_node] = {
                         "converter": converter,
                         "path": information_path,
                         "config_path": config_path
                     }
                     if not device_info.get(
                             information_types[information_type]):
                         device_info[
                             information_types[information_type]] = []
                     converted_data = converter.convert(
                         (config_path, information_path), information_value)
                     self.statistics['MessagesReceived'] = self.statistics[
                         'MessagesReceived'] + 1
                     self.data_to_send.append(converted_data)
                     self.statistics['MessagesSent'] = self.statistics[
                         'MessagesSent'] + 1
                     log.debug("Data to ThingsBoard: %s", converted_data)
                     if not self.__server_conf.get("disableSubscriptions",
                                                   False):
                         sub_nodes.append(information_node)
                 else:
                     log.error(
                         "Node for %s \"%s\" with path %s - NOT FOUND!",
                         information_type, information_key,
                         information_path)
     if not self.__server_conf.get("disableSubscriptions", False):
         if self.__sub is None:
             self.__sub = self.client.create_subscription(
                 self.__server_conf.get("subCheckPeriodInMillis", 500),
                 self.__sub_handler)
         if sub_nodes:
             self.__sub.subscribe_data_change(sub_nodes)
             log.debug("Added subscription to nodes: %s", str(sub_nodes))
Example #13
0
    def convert(self, config, data):
        #print("[JsonRequestUplinkConverter convert]", self.__config, data)
        if isinstance(data, (bytes, str)):
            data = loads(data)
        datatypes = {"attributes": "attributes", "timeseries": "telemetry"}
        dict_result = {
            "deviceName": None,
            "deviceType": None,
            "udoi": None,
            "schemaId": None,
            "attributes": [],
            "telemetry": []
        }
        try:
            if self.__config['converter'].get(
                    "deviceNameJsonExpression") is not None:
                dict_result["deviceName"] = TBUtility.get_value(
                    self.__config['converter'].get("deviceNameJsonExpression"),
                    data,
                    expression_instead_none=True)
            else:
                log.error(
                    "The expression for looking \"deviceName\" not found in config %s",
                    dumps(self.__config['converter']))
            if self.__config['converter'].get(
                    "deviceTypeJsonExpression") is not None:
                dict_result["deviceType"] = TBUtility.get_value(
                    self.__config['converter'].get("deviceTypeJsonExpression"),
                    data,
                    expression_instead_none=True)
            else:
                log.error(
                    "The expression for looking \"deviceType\" not found in config %s",
                    dumps(self.__config['converter']))
            if self.__config['converter'].get("udoi") is not None:
                dict_result["udoi"] = TBUtility.get_value(
                    self.__config['converter'].get("udoi"),
                    data,
                    expression_instead_none=True)
            else:
                log.error(
                    "The expression for looking \"udoi\" not found in config %s",
                    dumps(self.__config['converter']))
            if self.__config['converter'].get("schemaId") is not None:
                dict_result["schemaId"] = TBUtility.get_value(
                    self.__config['converter'].get("schemaId"),
                    data,
                    expression_instead_none=True)
            else:
                log.error(
                    "The expression for looking \"schemaId\" not found in config %s",
                    dumps(self.__config['converter']))
        except Exception as e:
            log.exception(e)

        try:
            for datatype in self.__datatypes:
                current_datatype = self.__datatypes[datatype]

                for datatype_object_config in self.__config["converter"].get(
                        datatype, []):
                    #print("[JsonRequestUplinkConverter convert datatype_object_config]",datatype_object_config)
                    datatype_object_config_key = TBUtility.get_value(
                        datatype_object_config["key"],
                        data,
                        datatype_object_config["type"],
                        expression_instead_none=True)
                    datatype_object_config_value = TBUtility.get_value(
                        datatype_object_config["value"],
                        data,
                        datatype_object_config["type"],
                        expression_instead_none=True)
                    #print("[JsonRequestUplinkConverter convert]",datatype_object_config_key,datatype_object_config_value)
                    if datatype_object_config_key is not None and datatype_object_config_value is not None:
                        dict_result[current_datatype].append({
                            datatype_object_config_key:
                            datatype_object_config_value
                        })
                    else:
                        error_string = "Cannot find the key in the input data" if datatype_object_config_key is None else "Cannot find the value from the input data"
                        log.error(error_string)
        except Exception as e:
            log.exception(e)
        #print("[JsonRequestUplinkConverter convert dict_result]",dict_result)
        return dict_result
Example #14
0
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.

from random import choice
from threading import Thread
from time import time, sleep
from string import ascii_lowercase

from tb_utility.tb_utility import TBUtility

try:
    from bacpypes.core import run, stop
except ImportError:
    print("BACnet library not found - installing...")
    TBUtility.install_package("bacpypes", ">=0.18.0")
    from bacpypes.core import run, stop

from bacpypes.pdu import Address, GlobalBroadcast, LocalBroadcast, LocalStation, RemoteStation

from connectors.connector import Connector, log
from connectors.bacnet.bacnet_utilities.tb_gateway_bacnet_application import TBBACnetApplication


class BACnetConnector(Thread, Connector):
    def __init__(self, gateway, config, connector_type):
        self.__connector_type = connector_type
        self.statistics = {'MessagesReceived': 0, 'MessagesSent': 0}
        super().__init__()
        self.__config = config
        self.setName(
Example #15
0
from threading import Thread
from time import sleep, time
from random import choice
from string import ascii_lowercase
from socket import gethostbyname
from re import search

from connectors.connector import Connector, log
from tb_utility.tb_loader import TBModuleLoader
from tb_utility.tb_utility import TBUtility

try:
    import puresnmp
except ImportError:
    TBUtility.install_package("puresnmp")
    import puresnmp

from puresnmp.exc import Timeout as SNMPTimeoutException


class SNMPConnector(Connector, Thread):
    def __init__(self, gateway, config, connector_type):
        super().__init__()
        self.daemon = True
        self.__gateway = gateway
        self._connected = False
        self.__stopped = False
        self._connector_type = connector_type
        self.__config = config
        self.__devices = self.__config["devices"]
Example #16
0
#     limitations under the License.

import time
import threading
from random import choice
from string import ascii_lowercase

from tb_utility.tb_loader import TBModuleLoader
from tb_utility.tb_utility import TBUtility

# Try import Pymodbus library or install it and import
try:
    from pymodbus.constants import Defaults
except ImportError:
    print("Modbus library not found - installing...")
    TBUtility.install_package("pymodbus", ">=2.3.0")
    TBUtility.install_package('pyserial')
    from pymodbus.constants import Defaults

from pymodbus.client.sync import ModbusTcpClient, ModbusUdpClient, ModbusSerialClient, ModbusRtuFramer, ModbusSocketFramer
from pymodbus.bit_write_message import WriteSingleCoilResponse, WriteMultipleCoilsResponse
from pymodbus.register_write_message import WriteMultipleRegistersResponse, WriteSingleRegisterResponse
from pymodbus.register_read_message import ReadRegistersResponseBase
from pymodbus.bit_read_message import ReadBitsResponseBase
from pymodbus.exceptions import ConnectionException

from connectors.connector import Connector, log
from connectors.modbus.constants import *
from connectors.modbus.bytes_modbus_uplink_converter import BytesModbusUplinkConverter
from connectors.modbus.bytes_modbus_downlink_converter import BytesModbusDownlinkConverter
Example #17
0
import re
import sched
import time
from threading import Thread
from copy import copy
from random import choice
from string import ascii_lowercase

from tb_utility.tb_utility import TBUtility

try:
    from can import Notifier, BufferedReader, Message, CanError, ThreadSafeBus
except ImportError:
    print("CAN library not found - installing...")
    TBUtility.install_package("python-can")
    from can import Notifier, BufferedReader, Message, CanError, ThreadSafeBus

from connectors.can.bytes_can_downlink_converter import BytesCanDownlinkConverter
from connectors.can.bytes_can_uplink_converter import BytesCanUplinkConverter
from connectors.connector import Connector, log


class CanConnector(Connector, Thread):
    CMD_REGEX = r"^(\d{1,2}):(\d{1,2}):?(big|little)?:(\d+)$"
    VALUE_REGEX = r"^(\d{1,2}):((?:-1)?|\d{1,2}):?(big|little)?:(bool|boolean|int|long|float|double|string|raw):?([0-9A-Za-z-_]+)?$"

    NO_CMD_ID = "no_cmd"
    UNKNOWN_ARBITRATION_ID = -1

    DEFAULT_RECONNECT_PERIOD = 30.0
Example #18
0
 def convert(self, config, data):
     datatypes = {"attributes": "attributes", "timeseries": "telemetry"}
     dict_result = {
         "deviceName": None,
         "deviceType": None,
         "attributes": [],
         "telemetry": []
     }
     try:
         if self.__config.get("deviceNameExpression") is not None:
             dict_result["deviceName"] = TBUtility.get_value(
                 self.__config.get("deviceNameExpression"),
                 data,
                 expression_instead_none=True)
         else:
             log.error(
                 "The expression for looking \"deviceName\" not found in config %s",
                 dumps(self.__config))
         if self.__config.get("deviceTypeExpression") is not None:
             dict_result["deviceType"] = TBUtility.get_value(
                 self.__config.get("deviceTypeExpression"),
                 data,
                 expression_instead_none=True)
         else:
             log.error(
                 "The expression for looking \"deviceType\" not found in config %s",
                 dumps(self.__config))
     except Exception as e:
         log.error(
             'Error in converter, for config: \n%s\n and message: \n%s\n',
             dumps(self.__config), data)
         log.exception(e)
     try:
         for datatype in datatypes:
             dict_result[datatypes[datatype]] = []
             for datatype_config in self.__config.get(datatype, []):
                 value = TBUtility.get_value(datatype_config["value"],
                                             data,
                                             datatype_config["type"],
                                             expression_instead_none=True)
                 value_tag = TBUtility.get_value(datatype_config["value"],
                                                 data,
                                                 datatype_config["type"],
                                                 get_tag=True)
                 key = TBUtility.get_value(datatype_config["key"],
                                           data,
                                           datatype_config["type"],
                                           expression_instead_none=True)
                 key_tag = TBUtility.get_value(datatype_config["key"],
                                               data,
                                               get_tag=True)
                 if ("${" not in str(value) and "}" not in str(value)) \
                    and ("${" not in str(key) and "}" not in str(key)):
                     is_valid_key = isinstance(
                         key, str) and "${" in datatype_config[
                             "key"] and "}" in datatype_config["key"]
                     is_valid_value = isinstance(
                         value, str) and "${" in datatype_config[
                             "value"] and "}" in datatype_config["value"]
                     full_key = datatype_config["key"].replace(
                         '${' + str(key_tag) +
                         '}', str(key)) if is_valid_key else key
                     full_value = datatype_config["value"].replace(
                         '${' + value_tag +
                         '}', value) if is_valid_value else value
                     if datatype == 'timeseries' and (
                             data.get("ts") is not None
                             or data.get("timestamp") is not None):
                         dict_result[datatypes[datatype]].append({
                             "ts":
                             data.get('ts',
                                      data.get('timestamp', int(time()))),
                             'values': {
                                 full_key: full_value
                             }
                         })
                     else:
                         dict_result[datatypes[datatype]].append(
                             {full_key: full_value})
     except Exception as e:
         log.error(
             'Error in converter, for config: \n%s\n and message: \n%s\n',
             dumps(self.__config), str(data))
         log.exception(e)
     return dict_result
Example #19
0
from os import path
from pathlib import Path
from time import sleep
from random import choice
from string import ascii_lowercase
from threading import Thread
from simplejson import dumps, load

from tb_utility.tb_loader import TBModuleLoader
from tb_utility.tb_utility import TBUtility

try:
    import pyodbc
except ImportError:
    print("ODBC library not found - installing...")
    TBUtility.install_package("pyodbc")
    import pyodbc

from connectors.odbc.odbc_uplink_converter import OdbcUplinkConverter

from connectors.connector import Connector, log


class OdbcConnector(Connector, Thread):
    DEFAULT_SEND_IF_CHANGED = False
    DEFAULT_RECONNECT_STATE = True
    DEFAULT_SAVE_ITERATOR = False
    DEFAULT_RECONNECT_PERIOD = 60
    DEFAULT_POLL_PERIOD = 60
    DEFAULT_ENABLE_UNKNOWN_RPC = False
    DEFAULT_OVERRIDE_RPC_PARAMS = False
Example #20
0
 def _on_message(self, client, userdata, message):
     content = TBUtility.decode(message)
     TBDeviceMqttClient._on_decoded_message(self, content, message)
     self._on_decoded_message(content, message)
Example #21
0
from threading import Thread
from string import ascii_lowercase
from random import choice
from time import time
from re import fullmatch
from queue import Queue
from simplejson import loads, JSONDecodeError

from tb_utility.tb_loader import TBModuleLoader
from tb_utility.tb_utility import TBUtility

try:
    from requests import Timeout, request as regular_request
except ImportError:
    print("Requests library not found - installing...")
    TBUtility.install_package("requests")
    from requests import Timeout, request as regular_request
import requests
from requests.auth import HTTPBasicAuth as HTTPBasicAuthRequest
from requests.exceptions import RequestException
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':ADH-AES128-SHA256'

try:
    from flask import Flask, jsonify, request
except ImportError:
    print("Flask library not found - installing...")
    TBUtility.install_package("flask")
    from flask import Flask, jsonify, request
try:
    from flask_restful import reqparse, abort, Api, Resource
except ImportError:
Example #22
0
from queue import Queue
from random import choice
from string import ascii_lowercase
from time import sleep, time
from re import fullmatch
from json import JSONDecodeError
import json

from tb_utility.tb_loader import TBModuleLoader
from tb_utility.tb_utility import TBUtility

try:
    from requests import Timeout, request
except ImportError:
    print("Requests library not found - installing...")
    TBUtility.install_package("requests")
    from requests import Timeout, request
import requests
from requests.auth import HTTPBasicAuth
from requests.exceptions import RequestException

from connectors.connector import Connector, log
from connectors.request.json_request_uplink_converter import JsonRequestUplinkConverter
from connectors.request.json_request_downlink_converter import JsonRequestDownlinkConverter

# pylint: disable=E1101
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':ADH-AES128-SHA256'


class RequestConnector(Connector, Thread):
    def __init__(self, gateway, config, connector_type):
 def convert(self, config, data):
     #print("[JsonMqttUplinkConverter]",config,data)
     #print("[JsonMqttUplinkConverter] self.__config",self.__config)
     datatypes = {"attributes": "attributes", "timeseries": "telemetry"}
     dict_result = {
         "deviceName": None,
         "deviceType": None,
         "attributes": [],
         "telemetry": []
     }
     try:
         if self.__config.get("deviceNameJsonExpression") is not None:
             dict_result["deviceName"] = TBUtility.get_value(
                 self.__config.get("deviceNameJsonExpression"),
                 data,
                 expression_instead_none=True)
         elif self.__config.get("deviceNameTopicExpression") is not None:
             search_result = search(
                 self.__config["deviceNameTopicExpression"], config)
             if search_result is not None:
                 dict_result["deviceName"] = search_result.group(0)
             else:
                 log.debug(
                     "Regular expression result is None. deviceNameTopicExpression parameter will be interpreted as a deviceName\n Topic: %s\nRegex: %s",
                     config, self.__config.get("deviceNameTopicExpression"))
                 dict_result["deviceName"] = self.__config.get(
                     "deviceNameTopicExpression")
         else:
             log.error(
                 "The expression for looking \"deviceName\" not found in config %s",
                 dumps(self.__config))
         if self.__config.get("deviceTypeJsonExpression") is not None:
             dict_result["deviceType"] = TBUtility.get_value(
                 self.__config.get("deviceTypeJsonExpression"),
                 data,
                 expression_instead_none=True)
         elif self.__config.get("deviceTypeTopicExpression") is not None:
             search_result = search(
                 self.__config["deviceTypeTopicExpression"], config)
             if search_result is not None:
                 dict_result["deviceType"] = search_result.group(0)
             else:
                 log.debug(
                     "Regular expression result is None. deviceTypeTopicExpression will be interpreted as a deviceType\n Topic: %s\nRegex: %s",
                     config, self.__config.get("deviceTypeTopicExpression"))
                 dict_result["deviceType"] = self.__config.get(
                     "deviceTypeTopicExpression")
         else:
             log.error(
                 "The expression for looking \"deviceType\" not found in config %s",
                 dumps(self.__config))
         if self.__config.get("udoi") is not None:
             dict_result["udoi"] = TBUtility.get_value(
                 self.__config.get("udoi"),
                 data,
                 expression_instead_none=True)
         else:
             log.error(
                 "The expression for looking \"udoi\" not found in config %s",
                 dumps(self.__config['converter']))
         if self.__config.get("schemaId") is not None:
             dict_result["schemaId"] = TBUtility.get_value(
                 self.__config.get("schemaId"),
                 data,
                 expression_instead_none=True)
         else:
             log.error(
                 "The expression for looking \"schemaId\" not found in config %s",
                 dumps(self.__config['converter']))
     except Exception as e:
         log.error(
             'Error in converter, for config: \n%s\n and message: \n%s\n',
             dumps(self.__config), data)
         log.exception(e)
     try:
         for datatype in datatypes:
             #print("datatype",datatype)
             dict_result[datatypes[datatype]] = []
             for datatype_config in self.__config.get(datatype, []):
                 #print("[JsonMqttUplinkConverter] datatype_config",datatype_config)
                 value = TBUtility.get_value(datatype_config["value"],
                                             data,
                                             datatype_config["type"],
                                             expression_instead_none=True)
                 #print("[JsonMqttUplinkConverter]",value)
                 value_tag = TBUtility.get_value(datatype_config["value"],
                                                 data,
                                                 datatype_config["type"],
                                                 get_tag=True)
                 #print("[JsonMqttUplinkConverter]",value_tag)
                 key = TBUtility.get_value(datatype_config["key"],
                                           data,
                                           datatype_config["type"],
                                           expression_instead_none=True)
                 #print("[JsonMqttUplinkConverter]",key)
                 key_tag = TBUtility.get_value(datatype_config["key"],
                                               data,
                                               get_tag=True)
                 #print("[JsonMqttUplinkConverter]",key_tag)
                 #print("[JsonMqttUplinkConverter]",value,value_tag,key,key_tag)
                 if ("${" not in str(value) and "}" not in str(value)) \
                    and ("${" not in str(key) and "}" not in str(key)):
                     is_valid_key = isinstance(
                         key, str) and "${" in datatype_config[
                             "key"] and "}" in datatype_config["key"]
                     is_valid_value = isinstance(
                         value, str) and "${" in datatype_config[
                             "value"] and "}" in datatype_config["value"]
                     full_key = datatype_config["key"].replace(
                         '${' + str(key_tag) +
                         '}', str(key)) if is_valid_key else key_tag
                     full_value = datatype_config["value"].replace(
                         '${' + str(value_tag) +
                         '}', str(value)) if is_valid_value else value
                     #print("[JsonMqttUplinkConverter]",is_valid_key,is_valid_value,full_key,full_value)
                     if datatype == 'timeseries' and (
                             data.get("ts") is not None
                             or data.get("timestamp") is not None):
                         dict_result[datatypes[datatype]].append({
                             "ts":
                             data.get('ts',
                                      data.get('timestamp', int(time()))),
                             'values': {
                                 full_key: full_value
                             }
                         })
                     else:
                         dict_result[datatypes[datatype]].append(
                             {full_key: full_value})
     except Exception as e:
         log.error(
             'Error in converter, for config: \n%s\n and message: \n%s\n',
             dumps(self.__config), str(data))
         log.exception(e)
     return dict_result
Example #24
0
from concurrent.futures import CancelledError, TimeoutError as FuturesTimeoutError
from copy import deepcopy
from random import choice
from threading import Thread
from string import ascii_lowercase
import regex
from simplejson import dumps

from tb_utility.tb_loader import TBModuleLoader
from tb_utility.tb_utility import TBUtility

try:
    from opcua import Client, ua
except ImportError:
    print("OPC-UA library not found")
    TBUtility.install_package("opcua")
    from opcua import Client, ua
from connectors.connector import Connector, log
from connectors.opcua.opcua_uplink_converter import OpcUaUplinkConverter


class OpcUaConnector(Thread, Connector):
    def __init__(self, gateway, config, connector_type):
        self._connector_type = connector_type
        self.statistics = {'MessagesReceived': 0, 'MessagesSent': 0}
        super().__init__()
        self.__gateway = gateway
        self.__server_conf = config.get("server")
        self.__interest_nodes = []
        self.__available_object_resources = {}
        self.__show_map = self.__server_conf.get("showMap", False)
Example #25
0
 def _on_message(self, client, userdata, message):
     content = TBUtility.decode(message)
     super()._on_decoded_message(content, message)
     self._on_decoded_message(content, message)
Example #26
0
 def __fill_interest_devices(self):
     if self.__config.get('devices') is None:
         log.error(
             'Devices not found in configuration file. BLE Connector stopped.'
         )
         self._connected = False
         return None
     for interest_device in self.__config.get('devices'):
         keys_in_config = ['attributes', 'telemetry']
         if interest_device.get('MACAddress') is not None:
             default_converter = BytesBLEUplinkConverter(interest_device)
             interest_uuid = {}
             for key_type in keys_in_config:
                 for type_section in interest_device.get(key_type):
                     if type_section.get("characteristicUUID") is not None:
                         converter = None
                         if type_section.get('converter') is not None:
                             try:
                                 module = TBUtility.check_and_import(
                                     self.__connector_type,
                                     type_section['converter'])
                                 if module is not None:
                                     log.debug(
                                         'Custom converter for device %s - found!',
                                         interest_device['MACAddress'])
                                     converter = module(interest_device)
                                 else:
                                     log.error(
                                         "\n\nCannot find extension module for device %s .\nPlease check your configuration.\n",
                                         interest_device['MACAddress'])
                             except Exception as e:
                                 log.exception(e)
                         else:
                             converter = default_converter
                         if converter is not None:
                             if interest_uuid.get(
                                     type_section["characteristicUUID"].
                                     upper()) is None:
                                 interest_uuid[type_section[
                                     "characteristicUUID"].upper()] = [{
                                         'section_config':
                                         type_section,
                                         'type':
                                         key_type,
                                         'converter':
                                         converter
                                     }]
                             else:
                                 interest_uuid[type_section[
                                     "characteristicUUID"].upper()].append({
                                         'section_config':
                                         type_section,
                                         'type':
                                         key_type,
                                         'converter':
                                         converter
                                     })
                     else:
                         log.error(
                             "No characteristicUUID found in configuration section for %s:\n%s\n",
                             key_type, pformat(type_section))
             if self.__devices_around.get(
                     interest_device['MACAddress'].upper()) is None:
                 self.__devices_around[
                     interest_device['MACAddress'].upper()] = {}
             self.__devices_around[interest_device['MACAddress'].upper(
             )]['device_config'] = interest_device
             self.__devices_around[interest_device['MACAddress'].upper(
             )]['interest_uuid'] = interest_uuid
         else:
             log.error(
                 "Device address not found, please check your settings.")