def __safe_apply_connection_configuration(self): apply_start = time() * 1000 self.__old_tb_client = self.__gateway.tb_client try: self.__old_tb_client.unsubscribe('*') self.__old_tb_client.stop() self.__old_tb_client.disconnect() self.__gateway.tb_client = TBClient( self.__new_general_configuration_file["thingsboard"], self.__old_tb_client.get_config_folder_path()) self.__gateway.tb_client.connect() connection_state = False while time( ) * 1000 - apply_start < self.__apply_timeout * 1000 and not connection_state: connection_state = self.__gateway.tb_client.is_connected() sleep(.1) if not connection_state: self.__revert_configuration() LOG.info( "The gateway cannot connect to the ThingsBoard server with a new configuration." ) return False else: self.__old_tb_client.stop() self.__gateway.subscribe_to_required_topics() return True except Exception as e: LOG.exception(e) self.__revert_configuration() return False
def __revert_configuration(self): try: LOG.info("Remote general configuration will be restored.") self.__new_general_configuration_file = self.__old_general_configuration_file self.__gateway.tb_client.disconnect() self.__gateway.tb_client.stop() self.__gateway.tb_client = TBClient( self.__old_general_configuration_file["thingsboard"]) self.__gateway.tb_client.connect() self.__gateway.subscribe_to_required_topics() LOG.debug("%s connection has been restored", str(self.__gateway.tb_client.client._client)) except Exception as e: LOG.exception("Exception on reverting configuration occurred:") LOG.exception(e)
def __safe_apply_connection_configuration(self): apply_start = time() * 1000 self.__old_tb_client = self.__gateway.tb_client try: self.__old_tb_client.pause() except Exception as e: log.exception(e) self.__revert_configuration() return False try: tb_client = TBClient( self.__new_general_configuration_file["thingsboard"]) tb_client.connect() except Exception as e: log.exception(e) self.__revert_configuration() return False self.__gateway.tb_client = tb_client try: connection_state = False while time( ) * 1000 - apply_start < self.__apply_timeout * 1000 and not connection_state: connection_state = self.__gateway.tb_client.is_connected() sleep(.1) if not connection_state: self.__revert_configuration() log.info( "The gateway cannot connect to the ThingsBoard server with a new configuration." ) return False else: self.__old_tb_client.unsubscribe("*") self.__old_tb_client.stop() self.__gateway.tb_client.client.gw_set_server_side_rpc_request_handler( self.__gateway._rpc_request_handler) self.__gateway.tb_client.client.set_server_side_rpc_request_handler( self.__gateway._rpc_request_handler) self.__gateway.tb_client.client.subscribe_to_all_attributes( self.__gateway._attribute_update_callback) self.__gateway.tb_client.client.gw_subscribe_to_all_attributes( self.__gateway._attribute_update_callback) return True except Exception as e: log.exception(e) self.__revert_configuration() return False
def __init__(self, config_file=None): self.stopped = False self.__lock = RLock() if config_file is None: config_file = path.dirname(path.dirname( path.abspath(__file__))) + '/config/tb_gateway.yaml'.replace( '/', path.sep) with open(config_file) as general_config: self.__config = safe_load(general_config) self._config_dir = path.dirname(path.abspath(config_file)) + path.sep logging_error = None try: logging.config.fileConfig(self._config_dir + "logs.conf", disable_existing_loggers=False) except Exception as e: logging_error = e global log log = logging.getLogger('service') log.info("Gateway starting...") self.__updater = TBUpdater() self.__updates_check_period_ms = 300000 self.__updates_check_time = 0 self.version = self.__updater.get_version() log.info("ThingsBoard IoT gateway version: %s", self.version["current_version"]) self.available_connectors = {} self.__connector_incoming_messages = {} self.__connected_devices = {} self.__saved_devices = {} self.__events = [] self.name = ''.join(choice(ascii_lowercase) for _ in range(64)) self.__rpc_register_queue = Queue(-1) self.__rpc_requests_in_progress = {} self.__connected_devices_file = "connected_devices.json" self.tb_client = TBClient(self.__config["thingsboard"], self._config_dir) self.tb_client.connect() self.subscribe_to_required_topics() self.__subscribed_to_rpc_topics = True if logging_error is not None: self.tb_client.client.send_telemetry({ "ts": time() * 1000, "values": { "LOGS": "Logging loading exception, logs.conf is wrong: %s" % (str(logging_error), ) } }) TBLoggerHandler.set_default_handler() self.counter = 0 self.__rpc_reply_sent = False global main_handler self.main_handler = main_handler self.remote_handler = TBLoggerHandler(self) self.main_handler.setTarget(self.remote_handler) self._default_connectors = DEFAULT_CONNECTORS self._implemented_connectors = {} self._event_storage_types = { "memory": MemoryEventStorage, "file": FileEventStorage, } self.__gateway_rpc_methods = { "ping": self.__rpc_ping, "stats": self.__form_statistics, "devices": self.__rpc_devices, "update": self.__rpc_update, "version": self.__rpc_version, } self.__remote_shell = None if self.__config["thingsboard"].get("remoteShell"): log.warning( "Remote shell is enabled. Please be carefully with this feature." ) self.__remote_shell = RemoteShell( platform=self.__updater.get_platform(), release=self.__updater.get_release()) self.__rpc_remote_shell_command_in_progress = None self.__sheduled_rpc_calls = [] self.__rpc_sheduled_methods_functions = { "restart": { "function": execv, "arguments": (executable, [executable.split(pathsep)[-1]] + argv) }, "reboot": { "function": system, "arguments": ("reboot 0", ) }, } self._event_storage = self._event_storage_types[ self.__config["storage"]["type"]](self.__config["storage"]) self.connectors_configs = {} self.__remote_configurator = None self.__request_config_after_connect = False self.__init_remote_configuration() self._load_connectors() self._connect_with_connectors() self.__load_persistent_devices() self._published_events = Queue(-1) self._send_thread = Thread(target=self.__read_data_from_storage, daemon=True, name="Send data to Thingsboard Thread") self._send_thread.start() log.info("Gateway started.") try: gateway_statistic_send = 0 connectors_configuration_check_time = 0 while not self.stopped: cur_time = time() * 1000 if not self.tb_client.is_connected( ) and self.__subscribed_to_rpc_topics: self.__subscribed_to_rpc_topics = False if self.tb_client.is_connected( ) and not self.__subscribed_to_rpc_topics: for device in self.__saved_devices: self.add_device( device, { "connector": self.__saved_devices[device]["connector"] }, device_type=self.__saved_devices[device] ["device_type"]) self.subscribe_to_required_topics() self.__subscribed_to_rpc_topics = True if self.__sheduled_rpc_calls: for rpc_call_index in range(len( self.__sheduled_rpc_calls)): rpc_call = self.__sheduled_rpc_calls[rpc_call_index] if cur_time > rpc_call[0]: rpc_call = self.__sheduled_rpc_calls.pop( rpc_call_index) result = None try: result = rpc_call[1]["function"]( *rpc_call[1]["arguments"]) except Exception as e: log.exception(e) if result == 256: log.warning( "Error on RPC command: 256. Permission denied." ) if (self.__rpc_requests_in_progress or not self.__rpc_register_queue.empty() ) and self.tb_client.is_connected(): new_rpc_request_in_progress = {} if self.__rpc_requests_in_progress: for rpc_in_progress, data in self.__rpc_requests_in_progress.items( ): if cur_time >= data[1]: data[2](rpc_in_progress) self.cancel_rpc_request(rpc_in_progress) self.__rpc_requests_in_progress[ rpc_in_progress] = "del" new_rpc_request_in_progress = { key: value for key, value in self.__rpc_requests_in_progress.items() if value != 'del' } if not self.__rpc_register_queue.empty(): rpc_request_from_queue = self.__rpc_register_queue.get( False) topic = rpc_request_from_queue["topic"] data = rpc_request_from_queue["data"] new_rpc_request_in_progress[topic] = data self.__rpc_requests_in_progress = new_rpc_request_in_progress else: try: sleep(.1) except Exception as e: log.exception(e) break if not self.__request_config_after_connect and self.tb_client.is_connected( ) and not self.tb_client.client.get_subscriptions_in_progress( ): self.__request_config_after_connect = True self.__check_shared_attributes() if cur_time - gateway_statistic_send > self.__config[ "thingsboard"].get( "statsSendPeriodInSeconds", 3600) * 1000 and self.tb_client.is_connected(): summary_messages = self.__form_statistics() # with self.__lock: self.tb_client.client.send_telemetry(summary_messages) gateway_statistic_send = time() * 1000 # self.__check_shared_attributes() if cur_time - connectors_configuration_check_time > self.__config[ "thingsboard"].get( "checkConnectorsConfigurationInSeconds", 60) * 1000: self.check_connector_configuration_updates() connectors_configuration_check_time = time() * 1000 if cur_time - self.__updates_check_time >= self.__updates_check_period_ms: self.__updates_check_time = time() * 1000 self.version = self.__updater.get_version() except KeyboardInterrupt: self.__stop_gateway() except Exception as e: log.exception(e) self.__stop_gateway() self.__close_connectors() log.info("The gateway has been stopped.") self.tb_client.stop()
def __init__(self, config_file=None): self.__lock = RLock() if config_file is None: config_file = path.dirname(path.dirname( path.abspath(__file__))) + '/config/tb_gateway.yaml'.replace( '/', path.sep) with open(config_file) as general_config: config = safe_load(general_config) self._config_dir = path.dirname(path.abspath(config_file)) + path.sep logging.config.fileConfig(self._config_dir + "logs.conf") global log log = logging.getLogger('service') log.info("Gateway starting...") self.version = get_distribution('thingsboard_gateway').version log.info("ThingsBoard IoT gateway version: %s", self.version) self.available_connectors = {} self.__connector_incoming_messages = {} self.__connected_devices = {} self.__saved_devices = {} self.__events = [] self.name = ''.join(choice(ascii_lowercase) for _ in range(64)) self.__rpc_requests_in_progress = {} self.__connected_devices_file = "connected_devices.json" self.tb_client = TBClient(config["thingsboard"]) self.tb_client.connect() self.subscribe_to_required_topics() self.counter = 0 self.__rpc_reply_sent = False global main_handler self.main_handler = main_handler self.remote_handler = TBLoggerHandler(self) self.main_handler.setTarget(self.remote_handler) self._default_connectors = { "mqtt": "MqttConnector", "modbus": "ModbusConnector", "opcua": "OpcUaConnector", "ble": "BLEConnector", "request": "RequestConnector", "can": "CanConnector" } self._implemented_connectors = {} self._event_storage_types = { "memory": MemoryEventStorage, "file": FileEventStorage, } self.__gateway_rpc_methods = { "ping": self.__rpc_ping, "stats": self.__form_statistics, "devices": self.__rpc_devices, } self.__sheduled_rpc_calls = [] self.__self_rpc_sheduled_methods_functions = { "restart": { "function": execv, "arguments": (executable, [executable.split(pathsep)[-1]] + argv) }, "reboot": { "function": system, "arguments": ("reboot 0", ) }, } self._event_storage = self._event_storage_types[ config["storage"]["type"]](config["storage"]) self.connectors_configs = {} self._load_connectors(config) self._connect_with_connectors() self.__remote_configurator = None self.__request_config_after_connect = False if config["thingsboard"].get("remoteConfiguration"): try: self.__remote_configurator = RemoteConfigurator(self, config) except Exception as e: log.exception(e) if self.__remote_configurator is not None: self.__remote_configurator.send_current_configuration() self.__load_persistent_devices() self._published_events = Queue(-1) self._send_thread = Thread(target=self.__read_data_from_storage, daemon=True, name="Send data to Thingsboard Thread") self._send_thread.start() log.info("Gateway started.") try: gateway_statistic_send = 0 while True: cur_time = time() * 1000 if self.__sheduled_rpc_calls: for rpc_call_index in range(len( self.__sheduled_rpc_calls)): rpc_call = self.__sheduled_rpc_calls[rpc_call_index] if cur_time > rpc_call[0]: rpc_call = self.__sheduled_rpc_calls.pop( rpc_call_index) result = None try: result = rpc_call[1]["function"]( *rpc_call[1]["arguments"]) except Exception as e: log.exception(e) if result == 256: log.warning( "Error on RPC command: 256. Permission denied." ) if self.__rpc_requests_in_progress and self.tb_client.is_connected( ): for rpc_in_progress, data in self.__rpc_requests_in_progress.items( ): if cur_time >= data[1]: data[2](rpc_in_progress) self.cancel_rpc_request(rpc_in_progress) self.__rpc_requests_in_progress[ rpc_in_progress] = "del" new_rpc_request_in_progress = { key: value for key, value in self.__rpc_requests_in_progress.items() if value != 'del' } self.__rpc_requests_in_progress = new_rpc_request_in_progress else: try: sleep(.1) except Exception as e: log.exception(e) break if not self.__request_config_after_connect and self.tb_client.is_connected( ) and not self.tb_client.client.get_subscriptions_in_progress( ): self.__request_config_after_connect = True self.__check_shared_attributes() if cur_time - gateway_statistic_send > 5000.0 and self.tb_client.is_connected( ): summary_messages = self.__form_statistics() # with self.__lock: self.tb_client.client.send_telemetry(summary_messages) gateway_statistic_send = time() * 1000 # self.__check_shared_attributes() except KeyboardInterrupt: log.info("Stopping...") self.__close_connectors() log.info("The gateway has been stopped.") self.tb_client.stop() except Exception as e: log.exception(e) self.__close_connectors() log.info("The gateway has been stopped.") self.tb_client.stop()
def __init__(self, config_file=None): if config_file is None: config_file = path.dirname(path.dirname( path.abspath(__file__))) + '/config/tb_gateway.yaml'.replace( '/', path.sep) with open(config_file) as general_config: config = safe_load(general_config) self._config_dir = path.dirname(path.abspath(config_file)) + path.sep logging.config.fileConfig(self._config_dir + "logs.conf") global log log = logging.getLogger('service') self.available_connectors = {} self.__connector_incoming_messages = {} self.__connected_devices = {} self.__saved_devices = {} self.__events = [] self.name = ''.join(choice(ascii_lowercase) for _ in range(64)) self.__rpc_requests_in_progress = {} self.__connected_devices_file = "connected_devices.json" self.tb_client = TBClient(config["thingsboard"]) self.tb_client.connect() self.subscribe_to_required_topics() global main_handler self.main_handler = main_handler self.remote_handler = TBLoggerHandler(self) self.main_handler.setTarget(self.remote_handler) self._default_connectors = { "mqtt": "MqttConnector", "modbus": "ModbusConnector", "opcua": "OpcUaConnector", "ble": "BLEConnector", } self._implemented_connectors = {} self._event_storage_types = { "memory": MemoryEventStorage, "file": FileEventStorage, } self._event_storage = self._event_storage_types[ config["storage"]["type"]](config["storage"]) self.connectors_configs = {} self._load_connectors(config) self._connect_with_connectors() self.__remote_configurator = None self.__request_config_after_connect = False if config["thingsboard"].get("remoteConfiguration"): try: self.__remote_configurator = RemoteConfigurator(self, config) except Exception as e: log.exception(e) if self.__remote_configurator is not None: self.__remote_configurator.send_current_configuration() self.__load_persistent_devices() self.__published_events = Queue(0) self.__send_thread = Thread(target=self.__read_data_from_storage, daemon=True, name="Send data to Thingsboard Thread") self.__send_thread.start() try: gateway_statistic_send = 0 while True: cur_time = time.time() * 1000 if self.__rpc_requests_in_progress and self.tb_client.is_connected( ): for rpc_in_progress, data in self.__rpc_requests_in_progress.items( ): if cur_time >= data[1]: data[2](rpc_in_progress) self.cancel_rpc_request(rpc_in_progress) self.__rpc_requests_in_progress[ rpc_in_progress] = "del" new_rpc_request_in_progress = { key: value for key, value in self.__rpc_requests_in_progress.items() if value != 'del' } self.__rpc_requests_in_progress = new_rpc_request_in_progress else: try: time.sleep(1) except Exception as e: log.exception(e) break if not self.__request_config_after_connect and \ self.tb_client.is_connected() and not self.tb_client.client.get_subscriptions_in_progress(): self.__request_config_after_connect = True self.__check_shared_attributes() if cur_time - gateway_statistic_send > 60000.0 and self.tb_client.is_connected( ): summary_messages = self.__form_statistics() self.tb_client.client.send_telemetry(summary_messages) gateway_statistic_send = time.time() * 1000 # self.__check_shared_attributes() except KeyboardInterrupt: log.info("Stopping...") self.__close_connectors() log.info("The gateway has been stopped.") self.tb_client.stop() except Exception as e: log.exception(e) self.__close_connectors() log.info("The gateway has been stopped.") self.tb_client.stop()
def __init__(self, config_file=None): if config_file is None: config_file = path.dirname(path.dirname( path.abspath(__file__))) + '/config/tb_gateway.yaml' with open(config_file) as general_config: config = safe_load(general_config) self._config_dir = path.dirname(path.abspath(config_file)) + '/' logging.config.fileConfig(self._config_dir + "logs.conf") global log log = logging.getLogger('service') self.available_connectors = {} self.__connector_incoming_messages = {} self.__connected_devices = {} self.__saved_devices = {} self.__events = [] self.name = ''.join(choice(ascii_lowercase) for _ in range(64)) self.__rpc_requests_in_progress = {} self.__connected_devices_file = "connected_devices.json" self.tb_client = TBClient(config["thingsboard"]) self.tb_client.connect() self.tb_client.client.gw_set_server_side_rpc_request_handler( self._rpc_request_handler) self.tb_client.client.set_server_side_rpc_request_handler( self._rpc_request_handler) self.tb_client.client.subscribe_to_all_attributes( self._attribute_update_callback) self.tb_client.client.gw_subscribe_to_all_attributes( self._attribute_update_callback) global main_handler self.main_handler = main_handler self.remote_handler = TBLoggerHandler(self) self.main_handler.setTarget(self.remote_handler) self._default_connectors = { "mqtt": "MqttConnector", "modbus": "ModbusConnector", "opcua": "OpcUaConnector", "ble": "BLEConnector", } self._implemented_connectors = {} self._event_storage_types = { "memory": MemoryEventStorage, "file": FileEventStorage, } self._event_storage = self._event_storage_types[ config["storage"]["type"]](config["storage"]) self._connectors_configs = {} self._load_connectors(config) self._connect_with_connectors() self.__remote_configurator = None self.__request_config_after_connect = False if config["thingsboard"].get("remoteConfiguration"): try: self.__remote_configurator = RemoteConfigurator(self, config) except Exception as e: log.exception(e) if self.__remote_configurator is not None: self.__remote_configurator.send_current_configuration() self.__load_persistent_devices() self.__published_events = Queue(0) self.__send_thread = Thread(target=self.__read_data_from_storage, daemon=True, name="Send data to Thingsboard Thread") self.__send_thread.start() try: gateway_statistic_send = 0 while True: cur_time = time.time() if self.__rpc_requests_in_progress and self.tb_client.is_connected( ): for rpc_in_progress in self.__rpc_requests_in_progress: if cur_time >= self.__rpc_requests_in_progress[ rpc_in_progress][1]: self.__rpc_requests_in_progress[rpc_in_progress][ 2](rpc_in_progress) self.cancel_rpc_request(rpc_in_progress) time.sleep(0.1) else: try: time.sleep(1) except Exception as e: log.exception(e) break if not self.__request_config_after_connect and \ self.tb_client.is_connected() and not self.tb_client.client.get_subscriptions_in_progress(): self.__request_config_after_connect = True self.__check_shared_attributes() if cur_time - gateway_statistic_send > 60.0 and self.tb_client.is_connected( ): summary_messages = {"eventsProduced": 0, "eventsSent": 0} telemetry = {} for connector in self.available_connectors: if self.available_connectors[connector].is_connected(): connector_camel_case = connector[0].lower( ) + connector[1:].replace(' ', '') telemetry[(connector_camel_case + ' EventsProduced').replace(' ', '')] = \ self.available_connectors[connector].statistics['MessagesReceived'] telemetry[(connector_camel_case + ' EventsSent').replace(' ', '')] = \ self.available_connectors[connector].statistics['MessagesSent'] self.tb_client.client.send_telemetry(telemetry) summary_messages['eventsProduced'] += telemetry[ str(connector_camel_case + ' EventsProduced').replace(' ', '')] summary_messages['eventsSent'] += telemetry[str( connector_camel_case + ' EventsSent').replace( ' ', '')] self.tb_client.client.send_telemetry(summary_messages) gateway_statistic_send = time.time() # self.__check_shared_attributes() except KeyboardInterrupt as e: log.info("Stopping...") self.__close_connectors() log.info("The gateway has been stopped.") self.tb_client.stop() except Exception as e: log.exception(e) self.__close_connectors() log.info("The gateway has been stopped.") self.tb_client.stop()
def __init__(self, config_file=None): if config_file is None: config_file = path.dirname(path.dirname( path.abspath(__file__))) + '/config/tb_gateway.yaml' with open(config_file) as config: config = safe_load(config) self.__config_dir = path.dirname(path.abspath(config_file)) + '/' logging.config.fileConfig(self.__config_dir + "logs.conf") global log log = logging.getLogger('service') self.available_connectors = {} self.__connector_incoming_messages = {} self.__connected_devices = {} self.__saved_devices = {} self.__events = [] self.__rpc_requests_in_progress = {} self.__connected_devices_file = "connected_devices.json" self.tb_client = TBClient(config["thingsboard"]) self.main_handler = logging.handlers.MemoryHandler(1000) self.remote_handler = TBLoggerHandler(self) self.main_handler.setTarget(self.remote_handler) self.__default_connectors = { "mqtt": "MqttConnector", "modbus": "ModbusConnector", "opcua": "OpcUaConnector", "ble": "BLEConnector", } self.__implemented_connectors = {} self.__event_storage_types = { "memory": MemoryEventStorage, "file": FileEventStorage, } self.__load_connectors(config) self.__connect_with_connectors() self.__load_persistent_devices() self.__published_events = Queue(0) self.__send_thread = Thread(target=self.__read_data_from_storage, daemon=True, name="Send data to Thingsboard Thread") self.__event_storage = self.__event_storage_types[ config["storage"]["type"]](config["storage"]) self.tb_client.connect() self.tb_client.client.gw_set_server_side_rpc_request_handler( self.__rpc_request_handler) self.tb_client.client.set_server_side_rpc_request_handler( self.__rpc_request_handler) self.tb_client.client.subscribe_to_all_attributes( self.__attribute_update_callback) self.tb_client.client.gw_subscribe_to_all_attributes( self.__attribute_update_callback) self.__send_thread.start() try: gateway_statistic_send = 0 while True: cur_time = time.time() if self.__rpc_requests_in_progress and self.tb_client.is_connected( ): for rpc_in_progress in self.__rpc_requests_in_progress: if cur_time >= self.__rpc_requests_in_progress[ rpc_in_progress][1]: self.__rpc_requests_in_progress[ rpc_in_progress][2](rpc_in_progress) self.cancel_rpc_request(rpc_in_progress) time.sleep(0.1) else: time.sleep(1) if cur_time - gateway_statistic_send > 60.0 and self.tb_client.is_connected( ): summary_messages = { "eventsProduced": 0, "eventsSent": 0 } telemetry = {} for connector in self.available_connectors: if self.available_connectors[ connector].is_connected(): connector_camel_case = connector[0].lower( ) + connector[1:].replace(' ', '') telemetry[(connector_camel_case + ' EventsProduced').replace(' ', '')] = \ self.available_connectors[connector].statistics['MessagesReceived'] telemetry[(connector_camel_case + ' EventsSent').replace(' ', '')] = \ self.available_connectors[connector].statistics['MessagesSent'] self.tb_client.client.send_telemetry(telemetry) summary_messages[ 'eventsProduced'] += telemetry[str( connector_camel_case + ' EventsProduced').replace(' ', '')] summary_messages['eventsSent'] += telemetry[ str(connector_camel_case + ' EventsSent').replace(' ', '')] self.tb_client.client.send_telemetry(summary_messages) gateway_statistic_send = time.time() except Exception as e: log.exception(e) for device in self.__connected_devices: log.debug("Close connection for device %s", device) try: current_connector = self.__connected_devices[ device].get("connector") if current_connector is not None: current_connector.close() log.debug("Connector %s closed connection.", current_connector.get_name()) except Exception as e: log.error(e)