예제 #1
0
    def server_side_rpc_handler(self, content):
        try:
            if content.get("device") is not None:

                log.debug("Modbus connector received rpc request for %s with content: %s", content["device"], content)
                if isinstance(self.__devices[content["device"]]["config"]["rpc"], dict):
                    rpc_command_config = self.__devices[content["device"]]["config"]["rpc"].get(content["data"]["method"])
                    if rpc_command_config is not None:
                        self.__process_rpc_request(content, rpc_command_config)
                elif isinstance(self.__devices[content["device"]]["config"]["rpc"], list):
                    for rpc_command_config in self.__devices[content["device"]]["config"]["rpc"]:
                        if rpc_command_config["tag"] == content["data"]["method"]:
                            self.__process_rpc_request(content, rpc_command_config)
                            break
                else:
                    log.error("Received rpc request, but method %s not found in config for %s.",
                              content["data"].get("method"),
                              self.get_name())
                    self.__gateway.send_rpc_reply(content["device"],
                                                  content["data"]["id"],
                                                  {content["data"]["method"]: "METHOD NOT FOUND!"})
            else:
                log.debug("Received RPC to connector: %r", content)
        except Exception as e:
            log.exception(e)
예제 #2
0
 def __function_to_device(self, config, unit_id):
     function_code = config.get('functionCode')
     result = None
     if function_code in (1, 2, 3, 4):
         result = self.__available_functions[function_code](config["address"],
                                                            config.get("objectsCount", config.get("registersCount",  config.get("registerCount", 1))),
                                                            unit=unit_id)
     elif function_code in (5, 6, 15, 16):
         result = self.__available_functions[function_code](config["address"],
                                                            config["payload"],
                                                            unit=unit_id)
     else:
         log.error("Unknown Modbus function with code: %i", function_code)
     log.debug("With result %s", str(result))
     if "Exception" in str(result):
         log.exception(result)
         result = str(result)
     return result
예제 #3
0
 def convert(self, config, data):
     self.__result["telemetry"] = []
     self.__result["attributes"] = []
     for config_data in data:
         for tag in data[config_data]:
             configuration = data[config_data][tag]["data_sent"]
             response = data[config_data][tag]["input_data"]
             byte_order = configuration.get("byteOrder", "LITTLE")
             endian_order = Endian.Little if byte_order.upper(
             ) == "LITTLE" else Endian.Big
             decoded_data = None
             if not isinstance(response, ModbusIOException):
                 if configuration["functionCode"] in [1, 2]:
                     result = response.bits
                     result = result if byte_order.upper(
                     ) == 'LITTLE' else result[::-1]
                     log.debug(result)
                     if "bit" in configuration:
                         decoded_data = result[configuration["bit"]]
                     else:
                         decoded_data = result[0]
                 elif configuration["functionCode"] in [3, 4]:
                     decoder = None
                     registers = response.registers
                     log.debug("Tag: %s Config: %s registers: %s", tag,
                               str(configuration), str(registers))
                     try:
                         decoder = BinaryPayloadDecoder.fromRegisters(
                             registers, byteorder=endian_order)
                     except TypeError:
                         # pylint: disable=E1123
                         decoder = BinaryPayloadDecoder.fromRegisters(
                             registers, endian=endian_order)
                     assert decoder is not None
                     decoded_data = self.__decode_from_registers(
                         decoder, configuration)
                     if configuration.get("divider"):
                         decoded_data = float(decoded_data) / float(
                             configuration["divider"])
                     if configuration.get("multiplier"):
                         decoded_data = decoded_data / configuration[
                             "multiplier"]
             else:
                 log.exception(response)
                 decoded_data = None
             log.debug("datatype: %s \t key: %s \t value: %s",
                       self.__datatypes[config_data], tag,
                       str(decoded_data))
             self.__result[self.__datatypes[config_data]].append(
                 {tag: decoded_data})
     log.debug(self.__result)
     return self.__result
예제 #4
0
 def __connect_to_current_master(self, device=None):
     connect_attempt_count = 5
     connect_attempt_time_ms = 100
     if device is None:
         device = list(self.__devices.keys())[0]
     if self.__devices[device].get('master') is None:
         self.__devices[device]['master'], self.__devices[device]['available_functions'] = self.__configure_master(
             self.__devices[device]["config"])
     if self.__devices[device]['master'] != self.__current_master:
         self.__current_master = self.__devices[device]['master']
         self.__available_functions = self.__devices[device]['available_functions']
     connect_attempt_count = self.__devices[device]["config"].get("connectAttemptCount", connect_attempt_count)
     connect_attempt_time_ms = self.__devices[device]["config"].get("connectAttemptTimeMs", connect_attempt_time_ms)
     attempt = 0
     if not self.__current_master.is_socket_open():
         while not self.__current_master.is_socket_open() and attempt < connect_attempt_count:
             attempt = attempt + 1
             self.__current_master.connect()
             if not self.__current_master.is_socket_open():
                 time.sleep(connect_attempt_time_ms / 1000)
             log.debug("Modbus trying connect to %s", device)
     if attempt > 0 and self.__current_master.is_socket_open():
         log.debug("Modbus connected.")
예제 #5
0
 def __process_rpc_request(self, content, rpc_command_config):
     if rpc_command_config is not None:
         rpc_command_config["unitId"] = self.__devices[content["device"]]["config"]["unitId"]
         self.__connect_to_current_master(content["device"])
         # if rpc_command_config.get('bit') is not None:
         #     rpc_command_config["functionCode"] = 6
         if rpc_command_config.get("functionCode") in (5, 6, 15, 16):
             rpc_command_config["payload"] = self.__devices[content["device"]]["downlink_converter"].convert(
                 rpc_command_config, content)
         response = None
         try:
             response = self.__function_to_device(rpc_command_config, rpc_command_config["unitId"])
         except Exception as e:
             log.exception(e)
             response = e
         if isinstance(response, (ReadRegistersResponseBase, ReadBitsResponseBase)):
             to_converter = {"rpc": {content["data"]["method"]: {"data_sent": rpc_command_config,
                                                                 "input_data": response}}}
             response = self.__devices[content["device"]]["converter"].convert(config={**self.__devices[content["device"]]["config"],
                                                                                                  "byteOrder": self.__devices[content["device"]]["config"].get("byteOrder", self.__byte_order),
                                                                                                  "wordOrder": self.__devices[content["device"]]["config"].get("wordOrder", self.__word_order)}, data=to_converter)
             log.debug("Received RPC method: %s, result: %r", content["data"]["method"], response)
             # response = {"success": response}
         elif isinstance(response, (WriteMultipleRegistersResponse,
                                    WriteMultipleCoilsResponse,
                                    WriteSingleCoilResponse,
                                    WriteSingleRegisterResponse)):
             log.debug("Write %r", str(response))
             response = {"success": True}
         if content.get("id") or (content.get("data") is not None and content["data"].get("id")):
             if isinstance(response, Exception):
                 self.__gateway.send_rpc_reply(content["device"],
                                               content["data"]["id"],
                                               {content["data"]["method"]: str(response)})
             else:
                 self.__gateway.send_rpc_reply(content["device"],
                                               content["data"]["id"],
                                               response)
         log.debug("%r", response)
예제 #6
0
    def convert(self, config, data):
        self.__result["telemetry"] = []
        self.__result["attributes"] = []
        for config_data in data:
            if self.__result.get(config_data) is None:
                self.__result[config_data] = []
            for tag in data[config_data]:
                log.debug(tag)
                data_sent = data[config_data][tag]["data_sent"]
                input_data = data[config_data][tag]["input_data"]
                log.debug("Called convert function from %s with args",
                          self.__class__.__name__)
                log.debug(data_sent)
                log.debug(input_data)
                result = None
                if data_sent.get("functionCode") == 1 or data_sent.get(
                        "functionCode") == 2:
                    result = input_data.bits
                    log.debug(result)
                    if "registerCount" in data_sent:
                        result = result[:data_sent["registerCount"]]
                    else:
                        result = result[0]
                elif data_sent.get("functionCode") == 3 or data_sent.get(
                        "functionCode") == 4:
                    result = input_data.registers
                    byte_order = data_sent.get("byteOrder", "LITTLE")
                    reg_count = data_sent.get("registerCount", 1)
                    type_of_data = data_sent["type"]
                    try:
                        if byte_order == "LITTLE":
                            decoder = BinaryPayloadDecoder.fromRegisters(
                                result, byteorder=Endian.Little)
                        elif byte_order == "BIG":
                            decoder = BinaryPayloadDecoder.fromRegisters(
                                result, byteorder=Endian.Big)
                        else:
                            log.warning("byte order is not BIG or LITTLE")
                            continue
                    except Exception as e:
                        log.error(e)
                    if type_of_data == "string":
                        result = decoder.decode_string(2 * reg_count)
                    elif type_of_data == "long":
                        if reg_count == 1:
                            result = decoder.decode_16bit_int()
                        elif reg_count == 2:
                            result = decoder.decode_32bit_int()
                        elif reg_count == 4:
                            result = decoder.decode_64bit_int()
                        else:
                            log.warning(
                                "unsupported register count for long data type in response for tag %s",
                                data_sent["tag"])
                            continue
                    elif type_of_data == "double":
                        if reg_count == 2:
                            result = decoder.decode_32bit_float()
                        elif reg_count == 4:
                            result = decoder.decode_64bit_float()
                        else:
                            log.warning(
                                "unsupported register count for double data type in response for tag %s",
                                data_sent["tag"])
                            continue
                    elif type_of_data == "bit":
                        if "bit" in data_sent:
                            if type(result) == list:
                                if len(result) > 1:
                                    log.warning(
                                        "with bit parameter only one register is expected, got more then one in response for tag %s",
                                        data_sent["tag"])
                                    continue
                                result = result[0]
                            position = 15 - data_sent["bit"]  # reverse order
                            # transform result to string representation of a bit sequence, add "0" to make it longer >16
                            result = "0000000000000000" + str(bin(result)[2:])
                            # get length of 16, then get bit, then cast it to int(0||1 from "0"||"1", then cast to boolean)
                            result = bool(
                                int((result[len(result) - 16:])[15 -
                                                                position]))
                        else:
                            log.error(
                                "Bit address not found in config for modbus connector for tag: %s",
                                data_sent["tag"])

                    else:
                        log.warning(
                            "unknown data type, not string, long or double in response for tag %s",
                            data_sent["tag"])
                        continue
                try:
                    self.__result[config_data].append({tag: int(result)})
                except ValueError:
                    self.__result[config_data].append({tag: int(result, 16)})
        self.__result["telemetry"] = self.__result.pop("timeseries")
        log.debug(self.__result)
        return self.__result
예제 #7
0
    def convert(self, config, data):
        byte_order_str = config.get("byteOrder", "LITTLE")
        byte_order = Endian.Big if byte_order_str.upper(
        ) == "BIG" else Endian.Little
        builder = BinaryPayloadBuilder(byteorder=byte_order)
        builder_functions = {
            "string": builder.add_string,
            "bits": builder.add_bits,
            "8int": builder.add_8bit_int,
            "16int": builder.add_16bit_int,
            "32int": builder.add_32bit_int,
            "64int": builder.add_64bit_int,
            "8uint": builder.add_8bit_uint,
            "16uint": builder.add_16bit_uint,
            "32uint": builder.add_32bit_uint,
            "64uint": builder.add_64bit_uint,
            "16float": builder.add_16bit_float,
            "32float": builder.add_32bit_float,
            "64float": builder.add_64bit_float
        }
        value = None
        if data.get("data") and data["data"].get("params") is not None:
            value = data["data"]["params"]
        else:
            value = config["value"]
        lower_type = config.get("type", config.get("tag", "error")).lower()
        if lower_type == "error":
            log.error('"type" and "tag" - not found in configuration.')
        variable_size = config.get("registerCount", 1) * 8
        if lower_type in ["integer", "dword", "dword/integer", "word", "int"]:
            lower_type = str(variable_size) + "int"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](value)
        elif lower_type in [
                "uint", "unsigned", "unsigned integer", "unsigned int"
        ]:
            lower_type = str(variable_size) + "uint"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](value)
        elif lower_type in ["float", "double"]:
            lower_type = str(variable_size) + "float"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](value)
        elif lower_type in ["coil", "bits"]:
            assert builder_functions.get("bits") is not None
            builder_functions["bits"](value)
        elif lower_type in ["string"]:
            assert builder_functions.get("string") is not None
            builder_functions[lower_type](value)
        elif lower_type in ["bit"]:
            bits = [0 for _ in range(8)]
            bits[config["bit"] - 1] = int(value)
            log.debug(bits)
            builder.add_bits(bits)
            return builder.to_string()
        else:
            log.error("Unknown variable type")

        builder_converting_functions = {
            5: builder.to_coils,
            15: builder.to_coils,
            6: builder.to_registers,
            16: builder.to_registers
        }

        function_code = config["functionCode"]

        if function_code in builder_converting_functions:
            builder = builder_converting_functions[function_code]()
            if "Exception" in str(builder):
                log.exception(builder)
                builder = str(builder)
            return builder
        log.warning(
            "Unsupported function code, for the device %s in the Modbus Downlink converter",
            config["device"])
        return None
예제 #8
0
    def convert(self, config, data):
        byte_order_str = config.get("byteOrder", "LITTLE")
        word_order_str = config.get("wordOrder", "LITTLE")
        byte_order = Endian.Big if byte_order_str.upper(
        ) == "BIG" else Endian.Little
        word_order = Endian.Big if word_order_str.upper(
        ) == "BIG" else Endian.Little
        repack = config.get("repack", False)
        builder = BinaryPayloadBuilder(byteorder=byte_order,
                                       wordorder=word_order,
                                       repack=repack)
        builder_functions = {
            "string": builder.add_string,
            "bits": builder.add_bits,
            "8int": builder.add_8bit_int,
            "16int": builder.add_16bit_int,
            "32int": builder.add_32bit_int,
            "64int": builder.add_64bit_int,
            "8uint": builder.add_8bit_uint,
            "16uint": builder.add_16bit_uint,
            "32uint": builder.add_32bit_uint,
            "64uint": builder.add_64bit_uint,
            "16float": builder.add_16bit_float,
            "32float": builder.add_32bit_float,
            "64float": builder.add_64bit_float
        }
        value = None
        if data.get("data") and data["data"].get("params") is not None:
            value = data["data"]["params"]
        else:
            value = config.get("value", 0)

        lower_type = config.get("type", config.get("tag", "error")).lower()

        if lower_type == "error":
            log.error('"type" and "tag" - not found in configuration.')
        variable_size = config.get(
            "objectsCount",
            config.get("registersCount", config.get("registerCount", 1))) * 16

        if lower_type in ["integer", "dword", "dword/integer", "word", "int"]:
            lower_type = str(variable_size) + "int"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](int(value))
        elif lower_type in [
                "uint", "unsigned", "unsigned integer", "unsigned int"
        ]:
            lower_type = str(variable_size) + "uint"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](int(value))
        elif lower_type in ["float", "double"]:
            lower_type = str(variable_size) + "float"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](float(value))
        elif lower_type in ["coil", "bits", "coils", "bit"]:
            assert builder_functions.get("bits") is not None
            if variable_size / 8 > 1.0:
                builder_functions["bits"](bytes(value, encoding='UTF-8')) if isinstance(value, str) else \
                    builder_functions["bits"](bytes(value))
            else:
                return bytes(int(value))
        elif lower_type in ["string"]:
            assert builder_functions.get("string") is not None
            builder_functions[lower_type](value)
        elif lower_type in builder_functions and 'int' in lower_type:
            builder_functions[lower_type](int(value))
        elif lower_type in builder_functions and 'float' in lower_type:
            builder_functions[lower_type](float(value))
        elif lower_type in builder_functions:
            builder_functions[lower_type](value)
        else:
            log.error("Unknown variable type")

        builder_converting_functions = {
            5: builder.to_coils,
            15: builder.to_coils,
            6: builder.to_registers,
            16: builder.to_registers
        }

        function_code = config["functionCode"]

        if function_code in builder_converting_functions:
            builder = builder_converting_functions[function_code]()
            log.debug(builder)
            if "Exception" in str(builder):
                log.exception(builder)
                builder = str(builder)
            if variable_size <= 16:
                if isinstance(builder,
                              list) and len(builder) not in (8, 16, 32, 64):
                    builder = builder[0]
            else:
                if isinstance(builder, list) and len(builder) not in (2, 4):
                    log.warning(
                        "There is a problem with the value builder. Only the first register is written."
                    )
                    builder = builder[0]
            return builder
        log.warning(
            "Unsupported function code, for the device %s in the Modbus Downlink converter",
            config["device"])
        return None
예제 #9
0
    def convert(self, config, data):
        byte_order = config["byteOrder"] if config.get("byteOrder") else "LITTLE"
        if byte_order == "LITTLE":
            builder = BinaryPayloadBuilder(byteorder=Endian.Little)
        elif byte_order == "BIG":
            builder = BinaryPayloadBuilder(byteorder=Endian.Big)
        else:
            log.warning("byte order is not BIG or LITTLE")
            return
        reg_count = config.get("registerCount", 1)
        value = config["value"]
        if config.get("tag") is not None:
            tags = (findall('[A-Z][a-z]*', config["tag"]))
            if "Coil" in tags:
                builder.add_bits(value)
            elif "String" in tags:
                builder.add_string(value)
            elif "Double" in tags:
                if reg_count == 4:
                    builder.add_64bit_float(value)
                else:
                    log.warning("unsupported amount of registers with double type for device %s in Downlink converter",
                                self.__config["deviceName"])
                    return
            elif "Float" in tags:
                if reg_count == 2:
                    builder.add_32bit_float(value)
                else:
                    log.warning("unsupported amount of registers with float type for device %s in Downlink converter",
                                self.__config["deviceName"])
                    return
            elif "Integer" in tags or "DWord" in tags or "DWord/Integer" in tags or "Word" in tags:
                if reg_count == 1:
                    builder.add_16bit_int(value)
                elif reg_count == 2:
                    builder.add_32bit_int(value)
                elif reg_count == 4:
                    builder.add_64bit_int(value)
                else:
                    log.warning("unsupported amount of registers with integer/word/dword type for device %s in Downlink converter",
                                self.__config["deviceName"])
                    return
            else:
                log.warning("unsupported hardware data type for device %s in Downlink converter",
                            self.__config["deviceName"])

        if config.get("bit") is not None:
            bits = [0 for _ in range(8)]
            bits[config["bit"]-1] = int(value)
            log.debug(bits)
            builder.add_bits(bits)
            return builder.to_string()

        if config["functionCode"] in [5, 15]:
            return builder.to_coils()
        elif config["functionCode"] in [6, 16]:
            return builder.to_registers()
        else:
            log.warning("Unsupported function code,  for device %s in Downlink converter",
                        self.__config["deviceName"])
        return
 def convert(self, config, data):
     self.__result["telemetry"] = []
     self.__result["attributes"] = []
     for config_data in data:
         for tag in data[config_data]:
             try:
                 configuration = data[config_data][tag]["data_sent"]
                 response = data[config_data][tag]["input_data"]
                 if configuration.get("byteOrder"):
                     byte_order = configuration["byteOrder"]
                 elif config.get("byteOrder"):
                     byte_order = config["byteOrder"]
                 else:
                     byte_order = "LITTLE"
                 if configuration.get("wordOrder"):
                     word_order = configuration["wordOrder"]
                 elif config.get("wordOrder"):
                     word_order = config.get("wordOrder", "BIG")
                 else:
                     word_order = "BIG"
                 endian_order = Endian.Little if byte_order.upper(
                 ) == "LITTLE" else Endian.Big
                 word_endian_order = Endian.Little if word_order.upper(
                 ) == "LITTLE" else Endian.Big
                 decoded_data = None
                 if not isinstance(response,
                                   ModbusIOException) and not isinstance(
                                       response, ExceptionResponse):
                     if configuration["functionCode"] in [1, 2]:
                         result = response.bits
                         result = result if byte_order.upper(
                         ) == 'LITTLE' else result[::-1]
                         log.debug(result)
                         if configuration["type"].lower() == "bits":
                             decoded_data = result[:configuration.get(
                                 "objectsCount",
                                 configuration.
                                 get("registersCount",
                                     configuration.get("registerCount", 1)
                                     ))]
                             if len(decoded_data) == 1 and isinstance(
                                     decoded_data, list):
                                 decoded_data = decoded_data[0]
                         else:
                             decoded_data = result[0]
                     elif configuration["functionCode"] in [3, 4]:
                         decoder = None
                         registers = response.registers
                         log.debug("Tag: %s Config: %s registers: %s", tag,
                                   str(configuration), str(registers))
                         try:
                             decoder = BinaryPayloadDecoder.fromRegisters(
                                 registers,
                                 byteorder=endian_order,
                                 wordorder=word_endian_order)
                         except TypeError:
                             # pylint: disable=E1123
                             decoder = BinaryPayloadDecoder.fromRegisters(
                                 registers,
                                 endian=endian_order,
                                 wordorder=word_endian_order)
                         assert decoder is not None
                         decoded_data = self.__decode_from_registers(
                             decoder, configuration)
                         if configuration.get("divider"):
                             decoded_data = float(decoded_data) / float(
                                 configuration["divider"])
                         if configuration.get("multiplier"):
                             decoded_data = decoded_data * configuration[
                                 "multiplier"]
                 else:
                     log.exception(response)
                     decoded_data = None
                 if config_data == "rpc":
                     return decoded_data
                 log.debug("datatype: %s \t key: %s \t value: %s",
                           self.__datatypes[config_data], tag,
                           str(decoded_data))
                 if decoded_data is not None:
                     self.__result[self.__datatypes[config_data]].append(
                         {tag: decoded_data})
             except Exception as e:
                 log.exception(e)
     log.debug(self.__result)
     return self.__result
예제 #11
0
    def convert(self, config, data):
        byte_order_str = config.get("byteOrder", "LITTLE")
        byte_order = Endian.Big if byte_order_str.upper(
        ) == "BIG" else Endian.Little
        builder = BinaryPayloadBuilder(byteorder=byte_order)
        builder_functions = {
            "string": builder.add_string,
            "bits": builder.add_bits,
            "8int": builder.add_8bit_int,
            "16int": builder.add_16bit_int,
            "32int": builder.add_32bit_int,
            "64int": builder.add_64bit_int,
            "8uint": builder.add_8bit_uint,
            "16uint": builder.add_16bit_uint,
            "32uint": builder.add_32bit_uint,
            "64uint": builder.add_64bit_uint,
            "16float": builder.add_16bit_float,
            "32float": builder.add_32bit_float,
            "64float": builder.add_64bit_float
        }

        value = config["value"]
        lower_type = config["tag"].lower()
        variable_size = config.get("registerCount", 1) * 8
        if lower_type in ["integer", "dword", "dword/integer", "word"]:
            lower_type = str(variable_size) + "int"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](value)
        elif lower_type in [
                "uint", "unsigned", "unsigned integer", "unsigned int"
        ]:
            lower_type = str(variable_size) + "uint"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](value)
        elif lower_type in ["float", "double"]:
            lower_type = str(variable_size) + "float"
            assert builder_functions.get(lower_type) is not None
            builder_functions[lower_type](value)
        elif lower_type in ["coil", "bits"]:
            assert builder_functions.get("bits") is not None
            builder_functions["bits"](value)
        elif lower_type in ["string"]:
            assert builder_functions.get("string") is not None
            builder_functions[lower_type](value)
        elif lower_type in ["bit"]:
            bits = [0 for _ in range(8)]
            bits[config["bit"] - 1] = int(value)
            log.debug(bits)
            builder.add_bits(bits)
            return builder.to_string()

        builder_converting_functions = {
            5: builder.to_coils,
            15: builder.to_coils,
            6: builder.to_registers,
            16: builder.to_registers
        }

        function_code = config["functionCode"]

        if function_code in builder_converting_functions:
            return builder_converting_functions[function_code]()
        log.warning(
            "Unsupported function code, for the device %s in the Modbus Downlink converter",
            self.__config["deviceName"])
        return None
예제 #12
0
    def __process_devices(self):
        for device in self.__devices:
            current_time = time.time()
            device_responses = {"timeseries": {},
                                "attributes": {},
                                }
            to_send = {}
            try:
                for config_data in device_responses:
                    #log.info(config_data)
                    if self.__devices[device]["config"].get(config_data) is not None:
                        unit_id = self.__devices[device]["config"]["unitId"]
                        if self.__devices[device]["next_"+config_data+"_check"] < current_time:
                            self.__connect_to_current_master(device)
                            #  Reading data from device
                            for interested_data in range(len(self.__devices[device]["config"][config_data])):
                                current_data = self.__devices[device]["config"][config_data][interested_data]
                                current_data["deviceName"] = device
                                input_data = self.__function_to_device(current_data, unit_id)
                                # if not isinstance(input_data, ReadRegistersResponseBase) and input_data.isError():
                                #     log.exception(input_data)
                                #     continue
                                device_responses[config_data][current_data["tag"]] = {"data_sent": current_data,
                                                                                      "input_data": input_data}

                            log.debug("Checking %s for device %s", config_data, device)
                            self.__devices[device]["next_"+config_data+"_check"] = current_time + self.__devices[device]["config"][config_data+"PollPeriod"]/1000
                            log.debug(device_responses)
                            converted_data = {}
                            try:
                                converted_data = self.__devices[device]["converter"].convert(config={**self.__devices[device]["config"],
                                                                                                     "byteOrder": self.__devices[device]["config"].get("byteOrder", self.__byte_order),
                                                                                                     "wordOrder": self.__devices[device]["config"].get("wordOrder", self.__word_order)},
                                                                                             data=device_responses)
                            except Exception as e:
                                log.error(e)

                            if converted_data and self.__devices[device]["config"].get("sendDataOnlyOnChange"):
                                self.statistics['MessagesReceived'] += 1
                                to_send = {"deviceName": converted_data["deviceName"], "deviceType": converted_data["deviceType"]}
                                if to_send.get("telemetry") is None:
                                    to_send["telemetry"] = []
                                if to_send.get("attributes") is None:
                                    to_send["attributes"] = []
                                for telemetry_dict in converted_data["telemetry"]:
                                    for key, value in telemetry_dict.items():
                                        if self.__devices[device]["last_telemetry"].get(key) is None or \
                                           self.__devices[device]["last_telemetry"][key] != value:
                                            self.__devices[device]["last_telemetry"][key] = value
                                            to_send["telemetry"].append({key: value})
                                for attribute_dict in converted_data["attributes"]:
                                    for key, value in attribute_dict.items():
                                        if self.__devices[device]["last_attributes"].get(key) is None or \
                                           self.__devices[device]["last_attributes"][key] != value:
                                            self.__devices[device]["last_attributes"][key] = value
                                            to_send["attributes"].append({key: value})
                                        # to_send["telemetry"] = converted_data["telemetry"]
                                # if converted_data["attributes"] != self.__devices[device]["attributes"]:
                                    # self.__devices[device]["last_attributes"] = converted_data["attributes"]
                                    # to_send["attributes"] = converted_data["attributes"]
                                if not to_send.get("attributes") and not to_send.get("telemetry"):
                                    # self.__gateway.send_to_storage(self.get_name(), to_send)
                                    # self.statistics['MessagesSent'] += 1
                                    log.debug("Data has not been changed.")
                            elif converted_data and self.__devices[device]["config"].get("sendDataOnlyOnChange") is None or not self.__devices[device]["config"].get("sendDataOnlyOnChange"):
                                self.statistics['MessagesReceived'] += 1
                                to_send = {"deviceName": converted_data["deviceName"],
                                           "deviceType": converted_data["deviceType"]}
                                # if converted_data["telemetry"] != self.__devices[device]["telemetry"]:
                                self.__devices[device]["last_telemetry"] = converted_data["telemetry"]
                                to_send["telemetry"] = converted_data["telemetry"]
                                # if converted_data["attributes"] != self.__devices[device]["attributes"]:
                                self.__devices[device]["last_attributes"] = converted_data["attributes"]
                                to_send["attributes"] = converted_data["attributes"]
                                # self.__gateway.send_to_storage(self.get_name(), to_send)
                                # self.statistics['MessagesSent'] += 1
                #log.info(to_send)
                # 数据添加到存储队列?
                if to_send.get("attributes") or to_send.get("telemetry"):
                    self.__gateway.send_to_storage(self.get_name(), to_send)
                    self.statistics['MessagesSent'] += 1
            except ConnectionException:
                time.sleep(5)
                log.error("Connection lost! Reconnecting...")
            except Exception as e:
                log.exception(e)