Exemple #1
0
    def convert(self, config, data):
        try:
            if data["data"].get("id") is None:
                attribute_key = list(data["data"].keys())[0]
                attribute_value = list(data["data"].values())[0]

                result = {
                    "url":
                    self.__config["requestUrlExpression"].replace(
                        "${attributeKey}", quote(attribute_key)).replace(
                            "${attributeValue}",
                            quote(attribute_value)).replace(
                                "${deviceName}", quote(data["device"])),
                    "data":
                    self.__config["valueExpression"].replace(
                        "${attributeKey}", quote(attribute_key)).replace(
                            "${attributeValue}",
                            quote(attribute_value)).replace(
                                "${deviceName}", quote(data["device"]))
                }
            else:
                request_id = str(data["data"]["id"])
                method_name = data["data"]["method"]

                result = {
                    "url":
                    self.__config["requestUrlExpression"].replace(
                        "${requestId}", request_id).replace(
                            "${methodName}",
                            method_name).replace("${deviceName}",
                                                 quote(data["device"])),
                    "data":
                    self.__config["valueExpression"].replace(
                        "${requestId}", request_id).replace(
                            "${methodName}",
                            method_name).replace("${deviceName}",
                                                 quote(data["device"]))
                }

                result['url'] = TBUtility.replace_params_tags(
                    result['url'], data)

                data_tags = TBUtility.get_values(config.get('valueExpression'),
                                                 data['data'],
                                                 'params',
                                                 get_tag=True)
                data_values = TBUtility.get_values(
                    config.get('valueExpression'),
                    data['data'],
                    'params',
                    expression_instead_none=True)

                for (tag, value) in zip(data_tags, data_values):
                    result['data'] = result["data"].replace(
                        '${' + tag + '}', str(value))

            return result
        except Exception as e:
            log.exception(e)
Exemple #2
0
    def server_side_rpc_handler(self, content):
        self.__log.info("Incoming server-side RPC: %s", content)

        # Check whether one of my RPC handlers can handle this request
        for rpc_config in self.__server_side_rpc:
            if search(rpc_config["deviceNameFilter"], content["device"]) \
                    and search(rpc_config["methodFilter"], content["data"]["method"]) is not None:

                # This handler seems able to handle the request
                self.__log.info("Candidate RPC handler found")

                expects_response = rpc_config.get("responseTopicExpression")
                defines_timeout = rpc_config.get("responseTimeout")

                # 2-way RPC setup
                if expects_response and defines_timeout:
                    expected_response_topic = rpc_config["responseTopicExpression"] \
                        .replace("${deviceName}", str(content["device"])) \
                        .replace("${methodName}", str(content["data"]["method"])) \
                        .replace("${requestId}", str(content["data"]["id"]))

                    expected_response_topic = TBUtility.replace_params_tags(
                        expected_response_topic, content)

                    timeout = time() * 1000 + rpc_config.get("responseTimeout")

                    # Start listenting on the response topic
                    self.__log.info("Subscribing to: %s",
                                    expected_response_topic)
                    self.__subscribe(expected_response_topic,
                                     rpc_config.get("responseTopicQoS", 1))

                    # Wait for subscription to be carried out
                    sub_response_timeout = 10

                    while expected_response_topic in self.__subscribes_sent.values(
                    ):
                        sub_response_timeout -= 1
                        sleep(0.1)
                        if sub_response_timeout == 0:
                            break

                    # Ask the gateway to enqueue this as an RPC response
                    self.__gateway.register_rpc_request_timeout(
                        content, timeout, expected_response_topic,
                        self.rpc_cancel_processing)

                    # Wait for RPC to be successfully enqueued, which never fails.
                    while self.__gateway.is_rpc_in_progress(
                            expected_response_topic):
                        sleep(0.1)

                elif expects_response and not defines_timeout:
                    self.__log.info(
                        "2-way RPC without timeout: treating as 1-way")

                # Actually reach out for the device
                request_topic: str = rpc_config.get("requestTopicExpression") \
                    .replace("${deviceName}", str(content["device"])) \
                    .replace("${methodName}", str(content["data"]["method"])) \
                    .replace("${requestId}", str(content["data"]["id"]))

                request_topic = TBUtility.replace_params_tags(
                    request_topic, content)

                data_to_send_tags = TBUtility.get_values(
                    rpc_config.get('valueExpression'),
                    content['data'],
                    'params',
                    get_tag=True)
                data_to_send_values = TBUtility.get_values(
                    rpc_config.get('valueExpression'),
                    content['data'],
                    'params',
                    expression_instead_none=True)

                data_to_send = rpc_config.get('valueExpression')
                for (tag, value) in zip(data_to_send_tags,
                                        data_to_send_values):
                    data_to_send = data_to_send.replace(
                        '${' + tag + '}', str(value))

                try:
                    self.__log.info("Publishing to: %s with data %s",
                                    request_topic, data_to_send)
                    self._client.publish(request_topic,
                                         data_to_send,
                                         retain=rpc_config.get(
                                             'retain', False))

                    if not expects_response or not defines_timeout:
                        self.__log.info(
                            "One-way RPC: sending ack to ThingsBoard immediately"
                        )
                        self.__gateway.send_rpc_reply(
                            device=content["device"],
                            req_id=content["data"]["id"],
                            success_sent=True)

                    # Everything went out smoothly: RPC is served
                    return

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

        self.__log.error("RPC not handled: %s", content)
Exemple #3
0
    def _convert_json_file(self, data):
        dict_result = {
            "deviceName": None,
            "deviceType": None,
            "attributes": [],
            "telemetry": []
        }

        try:
            if self.__config.get("devicePatternName") is not None:
                device_name_tags = TBUtility.get_values(
                    self.__config.get("devicePatternName"), data, get_tag=True)
                device_name_values = TBUtility.get_values(
                    self.__config.get("devicePatternName"),
                    data,
                    expression_instead_none=True)

                dict_result["deviceName"] = self.__config.get(
                    "devicePatternName")
                for (device_name_tag,
                     device_name_value) in zip(device_name_tags,
                                               device_name_values):
                    is_valid_key = "${" in self.__config.get("devicePatternName") and "}" in \
                                   self.__config.get("devicePatternName")
                    dict_result['deviceName'] = dict_result['deviceName'].replace('${' + str(device_name_tag) + '}',
                                                                                  str(device_name_value)) \
                        if is_valid_key else device_name_tag

            else:
                log.error(
                    "The expression for looking \"deviceName\" not found in config %s",
                    dumps(self.__config))

            if self.__config.get("devicePatternType") is not None:
                device_type_tags = TBUtility.get_values(
                    self.__config.get("devicePatternType"), data, get_tag=True)
                device_type_values = TBUtility.get_values(
                    self.__config.get("devicePatternType"),
                    data,
                    expression_instead_none=True)
                dict_result["deviceType"] = self.__config.get(
                    "devicePatternType")

                for (device_type_tag,
                     device_type_value) in zip(device_type_tags,
                                               device_type_values):
                    is_valid_key = "${" in self.__config.get("devicePatternType") and "}" in \
                                   self.__config.get("devicePatternType")
                    dict_result["deviceType"] = dict_result["deviceType"].replace('${' + str(device_type_tag) + '}',
                                                                                  str(device_type_value)) \
                        if is_valid_key else device_type_tag
        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 self.__data_types:
                dict_result[self.__data_types[datatype]] = []

                for datatype_config in self.__config.get(datatype, []):
                    values = TBUtility.get_values(datatype_config["value"],
                                                  data,
                                                  datatype_config["type"],
                                                  expression_instead_none=True)
                    values_tags = TBUtility.get_values(
                        datatype_config["value"],
                        data,
                        datatype_config["type"],
                        get_tag=True)

                    keys = TBUtility.get_values(datatype_config["key"],
                                                data,
                                                datatype_config["type"],
                                                expression_instead_none=True)
                    keys_tags = TBUtility.get_values(datatype_config["key"],
                                                     data,
                                                     get_tag=True)

                    full_key = datatype_config["key"]
                    for (key, key_tag) in zip(keys, keys_tags):
                        is_valid_key = "${" in datatype_config["key"] and "}" in \
                                       datatype_config["key"]
                        full_key = full_key.replace(
                            '${' + str(key_tag) +
                            '}', str(key)) if is_valid_key else key_tag

                    full_value = datatype_config["value"]
                    for (value, value_tag) in zip(values, values_tags):
                        is_valid_value = "${" in datatype_config["value"] and "}" in \
                                         datatype_config["value"]

                        full_value = full_value.replace(
                            '${' + str(value_tag) +
                            '}', str(value)) if is_valid_value else str(value)

                    if datatype == 'timeseries' and (data.get("ts") is not None
                                                     or data.get("timestamp")
                                                     is not None):
                        dict_result[self.__data_types[datatype]].append({
                            "ts":
                            data.get('ts', data.get('timestamp', int(time()))),
                            'values': {
                                full_key: full_value
                            }
                        })
                    else:
                        dict_result[self.__data_types[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
    def convert(self, config, data):
        datatypes = {"attributes": "attributes",
                     "timeseries": "telemetry"}
        dict_result = {"deviceName": None, "deviceType": None, "attributes": [], "telemetry": []}

        try:
            if self.__config.get("deviceNameJsonExpression") is not None:
                device_name_tags = TBUtility.get_values(self.__config.get("deviceNameJsonExpression"), data,
                                                        get_tag=True)
                device_name_values = TBUtility.get_values(self.__config.get("deviceNameJsonExpression"), data,
                                                          expression_instead_none=True)

                dict_result['deviceName'] = self.__config.get("deviceNameJsonExpression")
                for (device_name_tag, device_name_value) in zip(device_name_tags, device_name_values):
                    is_valid_key = "${" in self.__config.get("deviceNameJsonExpression") and "}" in \
                                   self.__config.get("deviceNameJsonExpression")
                    dict_result['deviceName'] = dict_result['deviceName'].replace('${' + str(device_name_tag) + '}',
                                                                                  str(device_name_value)) \
                        if is_valid_key else device_name_tag

            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:
                device_type_tags = TBUtility.get_values(self.__config.get("deviceTypeJsonExpression"), data,
                                                        get_tag=True)
                device_type_values = TBUtility.get_values(self.__config.get("deviceTypeJsonExpression"), data,
                                                          expression_instead_none=True)

                dict_result["deviceType"] = self.__config.get("deviceTypeJsonExpression")
                for (device_type_tag, device_type_value) in zip(device_type_tags, device_type_values):
                    is_valid_key = "${" in self.__config.get("deviceTypeJsonExpression") and "}" in \
                                   self.__config.get("deviceTypeJsonExpression")
                    dict_result["deviceType"] = dict_result["deviceType"].replace('${' + str(device_type_tag) + '}',
                                                                                  str(device_type_value)) \
                        if is_valid_key else device_type_tag

            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))
        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, []):
                    values = TBUtility.get_values(datatype_config["value"], data, datatype_config["type"],
                                                  expression_instead_none=True)
                    values_tags = TBUtility.get_values(datatype_config["value"], data, datatype_config["type"],
                                                       get_tag=True)

                    keys = TBUtility.get_values(datatype_config["key"], data, datatype_config["type"],
                                                expression_instead_none=True)
                    keys_tags = TBUtility.get_values(datatype_config["key"], data, get_tag=True)

                    full_key = datatype_config["key"]
                    for (key, key_tag) in zip(keys, keys_tags):
                        is_valid_key = "${" in datatype_config["key"] and "}" in \
                                       datatype_config["key"]
                        full_key = full_key.replace('${' + str(key_tag) + '}',
                                                    str(key)) if is_valid_key else key_tag

                    full_value = datatype_config["value"]
                    for (value, value_tag) in zip(values, values_tags):
                        is_valid_value = "${" in datatype_config["value"] and "}" in \
                                         datatype_config["value"]

                        full_value = full_value.replace('${' + str(value_tag) + '}',
                                                        str(value)) if is_valid_value else str(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