mirror of
https://github.com/thingsboard/thingsboard-gateway
synced 2025-10-26 22:31:42 +08:00
Added more logging and improvements for OPC-UA Connector and improvements for remote configuration
This commit is contained in:
@@ -68,7 +68,7 @@ class OpcUaConnector(Thread, Connector):
|
|||||||
if self.__server_conf["identity"].get("password"):
|
if self.__server_conf["identity"].get("password"):
|
||||||
self.client.set_password(self.__server_conf["identity"].get("password"))
|
self.client.set_password(self.__server_conf["identity"].get("password"))
|
||||||
|
|
||||||
self.setName(self.__server_conf.get("name", 'OPC-UA Default ' + ''.join(choice(ascii_lowercase) for _ in range(5))) + " Connector")
|
# self.setName(self.__server_conf.get("name", 'OPC-UA Default ' + ''.join(choice(ascii_lowercase) for _ in range(5))) + " Connector")
|
||||||
self.__opcua_nodes = {}
|
self.__opcua_nodes = {}
|
||||||
self._subscribed = {}
|
self._subscribed = {}
|
||||||
self.data_to_send = []
|
self.data_to_send = []
|
||||||
@@ -173,15 +173,18 @@ class OpcUaConnector(Thread, Connector):
|
|||||||
for childId in node.get_children():
|
for childId in node.get_children():
|
||||||
ch = self.client.get_node(childId)
|
ch = self.client.get_node(childId)
|
||||||
current_var_path = '.'.join(x.split(":")[1] for x in ch.get_path(20000, True))
|
current_var_path = '.'.join(x.split(":")[1] for x in ch.get_path(20000, True))
|
||||||
|
if self.__server_conf.get("showMap"):
|
||||||
|
log.info("Looking for name: %s", current_var_path)
|
||||||
if self.__interest_nodes:
|
if self.__interest_nodes:
|
||||||
if ch.get_node_class() == ua.NodeClass.Object:
|
if ch.get_node_class() == ua.NodeClass.Object:
|
||||||
for interest_node in self.__interest_nodes:
|
for interest_node in self.__interest_nodes:
|
||||||
for int_node in interest_node:
|
for int_node in interest_node:
|
||||||
subrecursion_level = recursion_level
|
subrecursion_level = recursion_level
|
||||||
if subrecursion_level != recursion_level + len(interest_node[int_node]["deviceNamePattern"].split("\\.")):
|
if subrecursion_level != recursion_level + len(interest_node[int_node]["deviceNamePattern"].split("\\.")):
|
||||||
if ch.get_display_name().Text in TBUtility.get_value(interest_node[int_node]["deviceNamePattern"], get_tag=True).split('.') or \
|
if ch.get_display_name().Text in TBUtility.get_value(interest_node[int_node]["deviceNamePattern"], get_tag=True).split('\\.') or \
|
||||||
re.search(TBUtility.get_value(interest_node[int_node]["deviceNodePattern"], get_tag=True), ch.get_display_name().Text):
|
re.search(TBUtility.get_value(interest_node[int_node]["deviceNodePattern"].split("\\.")[recursion_level+1], get_tag=True), ch.get_display_name().Text):
|
||||||
self.__search_name(ch, subrecursion_level+1)
|
if interest_node[int_node].get("deviceName") is None:
|
||||||
|
self.__search_name(ch, subrecursion_level+1)
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
elif ch.get_node_class() == ua.NodeClass.Variable:
|
elif ch.get_node_class() == ua.NodeClass.Variable:
|
||||||
@@ -212,13 +215,16 @@ class OpcUaConnector(Thread, Connector):
|
|||||||
if not self.__gateway.get_devices().get(full_device_name):
|
if not self.__gateway.get_devices().get(full_device_name):
|
||||||
self.__gateway.add_device(full_device_name, {"connector": None})
|
self.__gateway.add_device(full_device_name, {"connector": None})
|
||||||
self.__gateway.update_device(full_device_name, "connector", self)
|
self.__gateway.update_device(full_device_name, "connector", self)
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
if re.search(int_node.split('\\.')[recursion_level-2], ch.get_display_name().Text):
|
if re.search(int_node.split('\\.')[recursion_level], ch.get_display_name().Text):
|
||||||
self.__search_name(ch, recursion_level+1)
|
if interest_node[int_node].get("deviceName") is None:
|
||||||
|
self.__search_name(ch, recursion_level+1)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
if re.search(int_node.split('\\.')[-1], ch.get_display_name().Text):
|
if re.search(int_node.split('\\.')[-1], ch.get_display_name().Text):
|
||||||
self.__search_name(ch, recursion_level+1)
|
if interest_node[int_node].get("deviceName") is None:
|
||||||
|
self.__search_name(ch, recursion_level+1)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
@@ -241,12 +247,13 @@ class OpcUaConnector(Thread, Connector):
|
|||||||
for interest_node in self.__interest_nodes:
|
for interest_node in self.__interest_nodes:
|
||||||
for int_node in interest_node:
|
for int_node in interest_node:
|
||||||
try:
|
try:
|
||||||
name_to_check = int_node.split('\\.')[recursion_level-1] if '\\.' in int_node else int_node
|
name_to_check = int_node.split('\\.')[recursion_level+1] if '\\.' in int_node else int_node
|
||||||
name_to_check = int_node.split('.')[recursion_level-1] if '.' in int_node else name_to_check
|
# name_to_check = int_node.split('.')[recursion_level] if '.' in int_node else name_to_check
|
||||||
except IndexError:
|
except IndexError:
|
||||||
name_to_check = int_node.split('\\.')[-1] if '\\.' in int_node else int_node
|
name_to_check = int_node.split('\\.')[-1] if '\\.' in int_node else int_node
|
||||||
name_to_check = int_node.split('.')[-1] if '.' in int_node else name_to_check
|
# name_to_check = int_node.split('.')[-1] if '.' in int_node else name_to_check
|
||||||
if re.search(name_to_check, ch.get_display_name().Text):
|
log.debug("%s\t%s", name_to_check, ch.get_display_name().Text)
|
||||||
|
if re.search(name_to_check.replace("\\", "\\\\"), ch.get_display_name().Text):
|
||||||
try:
|
try:
|
||||||
methods = ch.get_methods()
|
methods = ch.get_methods()
|
||||||
for method in methods:
|
for method in methods:
|
||||||
@@ -260,7 +267,7 @@ class OpcUaConnector(Thread, Connector):
|
|||||||
self.__search_tags(ch, subrecursion_level+1, sub)
|
self.__search_tags(ch, subrecursion_level+1, sub)
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
self.__search_tags(ch, recursion_level+1, sub)
|
# self.__search_tags(ch, recursion_level+1, sub)
|
||||||
elif ch.get_node_class() == ua.NodeClass.Variable:
|
elif ch.get_node_class() == ua.NodeClass.Variable:
|
||||||
try:
|
try:
|
||||||
for interest_node in self.__interest_nodes:
|
for interest_node in self.__interest_nodes:
|
||||||
@@ -273,8 +280,8 @@ class OpcUaConnector(Thread, Connector):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
name_to_check = int_node.split('\\.')[-1] if '\\.' in int_node else int_node
|
name_to_check = int_node.split('\\.')[-1] if '\\.' in int_node else int_node
|
||||||
name_to_check = int_node.split('.')[-1] if '.' in int_node else name_to_check
|
# name_to_check = int_node.split('.')[-1] if '.' in int_node else name_to_check
|
||||||
if re.search(name_to_check.replace('$', ''), current_var_path):
|
if re.search(name_to_check.replace('$', ''), current_var_path.split(".")[-2]):
|
||||||
tags = []
|
tags = []
|
||||||
if interest_node[int_node].get("attributes"):
|
if interest_node[int_node].get("attributes"):
|
||||||
tags.extend(interest_node[int_node]["attributes"])
|
tags.extend(interest_node[int_node]["attributes"])
|
||||||
@@ -283,11 +290,11 @@ class OpcUaConnector(Thread, Connector):
|
|||||||
for tag in tags:
|
for tag in tags:
|
||||||
target = TBUtility.get_value(tag["path"], get_tag=True)
|
target = TBUtility.get_value(tag["path"], get_tag=True)
|
||||||
try:
|
try:
|
||||||
tag_name_for_check = target.split('\\.')[recursion_level-1] if '\\.' in target else target
|
tag_name_for_check = target.split('\\.')[recursion_level] if '\\.' in target else target
|
||||||
tag_name_for_check = target.split('.')[recursion_level-1] if '.' in target else tag_name_for_check
|
# tag_name_for_check = target.split('.')[recursion_level] if '.' in target else tag_name_for_check
|
||||||
except IndexError:
|
except IndexError:
|
||||||
tag_name_for_check = target.split('\\.')[-1] if '\\.' in target else target
|
tag_name_for_check = target.split('\\.')[-1] if '\\.' in target else target
|
||||||
tag_name_for_check = target.split('.')[-1] if '.' in target else tag_name_for_check
|
# tag_name_for_check = target.split('.')[-1] if '.' in target else tag_name_for_check
|
||||||
current_node_name = ch.get_display_name().Text
|
current_node_name = ch.get_display_name().Text
|
||||||
if current_node_name == tag_name_for_check:
|
if current_node_name == tag_name_for_check:
|
||||||
sub.subscribe_data_change(ch)
|
sub.subscribe_data_change(ch)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class RemoteConfigurator:
|
|||||||
self.__new_configuration = loads(decoded_configuration)
|
self.__new_configuration = loads(decoded_configuration)
|
||||||
self.__old_connectors_configs = self.__gateway._connectors_configs
|
self.__old_connectors_configs = self.__gateway._connectors_configs
|
||||||
self.__new_general_configuration_file = self.__new_configuration.get("thingsboard")
|
self.__new_general_configuration_file = self.__new_configuration.get("thingsboard")
|
||||||
if self.__old_configuration != self.__new_configuration:
|
if self.__old_configuration != decoded_configuration:
|
||||||
log.info("Remote configuration received: \n %s", decoded_configuration)
|
log.info("Remote configuration received: \n %s", decoded_configuration)
|
||||||
self.__process_connectors_configuration()
|
self.__process_connectors_configuration()
|
||||||
self.__old_configuration = self.__new_configuration
|
self.__old_configuration = self.__new_configuration
|
||||||
@@ -95,7 +95,7 @@ class RemoteConfigurator:
|
|||||||
|
|
||||||
def __apply_new_connectors_configuration(self):
|
def __apply_new_connectors_configuration(self):
|
||||||
try:
|
try:
|
||||||
self.__gateway._load_connectors(self.__new_configuration["thingsboard"])
|
self.__gateway._load_connectors(self.__new_configuration["thingsboard"], False)
|
||||||
for connector_name in self.__gateway.available_connectors:
|
for connector_name in self.__gateway.available_connectors:
|
||||||
try:
|
try:
|
||||||
self.__gateway.available_connectors[connector_name].close()
|
self.__gateway.available_connectors[connector_name].close()
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ class TBGatewayService:
|
|||||||
break
|
break
|
||||||
if self.__remote_configurator is not None and not self.__request_config_after_connect and \
|
if self.__remote_configurator is not None and not self.__request_config_after_connect and \
|
||||||
self.tb_client.is_connected() and not self.tb_client.client.get_subscriptions_in_progress():
|
self.tb_client.is_connected() and not self.tb_client.client.get_subscriptions_in_progress():
|
||||||
self.__check_shared_attributes()
|
|
||||||
self.__request_config_after_connect = True
|
self.__request_config_after_connect = True
|
||||||
|
self.__check_shared_attributes()
|
||||||
|
|
||||||
|
|
||||||
if cur_time - gateway_statistic_send > 60.0 and self.tb_client.is_connected():
|
if cur_time - gateway_statistic_send > 60.0 and self.tb_client.is_connected():
|
||||||
@@ -132,7 +132,7 @@ class TBGatewayService:
|
|||||||
str(connector_camel_case + ' EventsSent').replace(' ', '')]
|
str(connector_camel_case + ' EventsSent').replace(' ', '')]
|
||||||
self.tb_client.client.send_telemetry(summary_messages)
|
self.tb_client.client.send_telemetry(summary_messages)
|
||||||
gateway_statistic_send = time.time()
|
gateway_statistic_send = time.time()
|
||||||
self.__check_shared_attributes()
|
# self.__check_shared_attributes()
|
||||||
except KeyboardInterrupt as e:
|
except KeyboardInterrupt as e:
|
||||||
log.info("Stopping...")
|
log.info("Stopping...")
|
||||||
self.__close_connectors()
|
self.__close_connectors()
|
||||||
@@ -162,6 +162,10 @@ class TBGatewayService:
|
|||||||
if self.__remote_configurator is not None and shared_attributes.get("configuration"):
|
if self.__remote_configurator is not None and shared_attributes.get("configuration"):
|
||||||
try:
|
try:
|
||||||
self.__remote_configurator.process_configuration(shared_attributes.get("configuration"))
|
self.__remote_configurator.process_configuration(shared_attributes.get("configuration"))
|
||||||
|
|
||||||
|
self.__send_thread = Thread(target=self.__read_data_from_storage, daemon=True,
|
||||||
|
name="Send data to Thingsboard Thread")
|
||||||
|
self.__send_thread.start()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
if client_attributes is not None:
|
if client_attributes is not None:
|
||||||
@@ -169,6 +173,10 @@ class TBGatewayService:
|
|||||||
if self.__remote_configurator is not None and content.get("configuration"):
|
if self.__remote_configurator is not None and content.get("configuration"):
|
||||||
try:
|
try:
|
||||||
self.__remote_configurator.process_configuration(content.get("configuration"))
|
self.__remote_configurator.process_configuration(content.get("configuration"))
|
||||||
|
|
||||||
|
self.__send_thread = Thread(target=self.__read_data_from_storage, daemon=True,
|
||||||
|
name="Send data to Thingsboard Thread")
|
||||||
|
self.__send_thread.start()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
remote_logging_level = shared_attributes.get('RemoteLoggingLevel') if shared_attributes is not None else content.get("RemoteLoggingLevel")
|
remote_logging_level = shared_attributes.get('RemoteLoggingLevel') if shared_attributes is not None else content.get("RemoteLoggingLevel")
|
||||||
@@ -215,12 +223,11 @@ class TBGatewayService:
|
|||||||
with open(self._config_dir + connector['configuration'], 'r') as conf_file:
|
with open(self._config_dir + connector['configuration'], 'r') as conf_file:
|
||||||
try:
|
try:
|
||||||
connector_conf = load(conf_file)
|
connector_conf = load(conf_file)
|
||||||
|
if not self._connectors_configs.get(connector['type']):
|
||||||
|
self._connectors_configs[connector['type']] = []
|
||||||
|
self._connectors_configs[connector['type']].append({"name": connector["name"], "config": {connector['configuration']: connector_conf}})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
log.error("Cannot read from file: %s", conf_file)
|
|
||||||
if not self._connectors_configs.get(connector['type']):
|
|
||||||
self._connectors_configs[connector['type']] = []
|
|
||||||
self._connectors_configs[connector['type']].append({"name": connector["name"], "config": {connector['configuration']: connector_conf}})
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
@@ -349,8 +356,8 @@ class TBGatewayService:
|
|||||||
else:
|
else:
|
||||||
time.sleep(.01)
|
time.sleep(.01)
|
||||||
else:
|
else:
|
||||||
self.__request_config_after_connect = False
|
|
||||||
time.sleep(.1)
|
time.sleep(.1)
|
||||||
|
self.__request_config_after_connect = False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|||||||
@@ -167,7 +167,8 @@ class TBDeviceMqttClient:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def _on_disconnect(self, client, userdata, rc):
|
def _on_disconnect(self, client, userdata, rc):
|
||||||
self.__is_connected = False
|
log.debug(client)
|
||||||
|
log.debug("Disconnected")
|
||||||
|
|
||||||
def _on_connect(self, client, userdata, flags, rc, *extra_params):
|
def _on_connect(self, client, userdata, flags, rc, *extra_params):
|
||||||
result_codes = {
|
result_codes = {
|
||||||
@@ -182,6 +183,7 @@ class TBDeviceMqttClient:
|
|||||||
if rc == 0:
|
if rc == 0:
|
||||||
self.__is_connected = True
|
self.__is_connected = True
|
||||||
log.info("connection SUCCESS")
|
log.info("connection SUCCESS")
|
||||||
|
log.debug(client)
|
||||||
self._client.subscribe(ATTRIBUTES_TOPIC, qos=1)
|
self._client.subscribe(ATTRIBUTES_TOPIC, qos=1)
|
||||||
self._client.subscribe(ATTRIBUTES_TOPIC + "/response/+", 1)
|
self._client.subscribe(ATTRIBUTES_TOPIC + "/response/+", 1)
|
||||||
self._client.subscribe(RPC_REQUEST_TOPIC + '+')
|
self._client.subscribe(RPC_REQUEST_TOPIC + '+')
|
||||||
@@ -212,7 +214,9 @@ class TBDeviceMqttClient:
|
|||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
self._client.disconnect()
|
self._client.disconnect()
|
||||||
log.info("Disconnected from ThingsBoard!")
|
log.debug(self._client)
|
||||||
|
log.debug("Disconnecting from ThingsBoard")
|
||||||
|
self.__is_connected = False
|
||||||
|
|
||||||
def _on_message(self, client, userdata, message):
|
def _on_message(self, client, userdata, message):
|
||||||
content = TBUtility.decode(message)
|
content = TBUtility.decode(message)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class TBUtility:
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
module = util.module_from_spec(module_spec)
|
module = util.module_from_spec(module_spec)
|
||||||
log.debug(module)
|
log.debug(str(module))
|
||||||
try:
|
try:
|
||||||
module_spec.loader.exec_module(module)
|
module_spec.loader.exec_module(module)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user