Skip to content

Commit 592d0b1

Browse files
authored
Merge pull request #1970 from samson0v/master
Fixed finding device name/profile from relative node path
2 parents cea28c0 + 95d9617 commit 592d0b1

File tree

1 file changed

+34
-18
lines changed

1 file changed

+34
-18
lines changed

thingsboard_gateway/connectors/opcua/opcua_connector.py

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -588,15 +588,14 @@ async def __find_nodes(self, node_list_to_search, current_parent_node, nodes, pa
588588
node_paths = [node['path'] if isinstance(node, dict) else node for node in nodes]
589589
current_node_path = '.'.join(
590590
node_path.split(':')[-1] for node_path in node_paths) + '.' + child_node.Name
591-
if not current_node_path in self.__scanning_nodes_cache:
591+
if current_node_path not in self.__scanning_nodes_cache:
592592
self.__scanning_nodes_cache[current_node_path] = [*nodes, {
593593
'path': f'{child_node.NamespaceIndex}:{child_node.Name}', 'node': node}]
594594
if self.__show_map and path:
595595
if children_nodes_count < 1000 or counter % 1000 == 0:
596596
self.__log.info('Checking path: %s', path + '.' + f'{child_node.Name}')
597597

598-
if re.fullmatch(re.escape(node_list_to_search[0]), child_node.Name) or node_list_to_search[0].split(':')[
599-
-1] == child_node.Name:
598+
if re.fullmatch(re.escape(node_list_to_search[0]), child_node.Name) or node_list_to_search[0].split(':')[-1] == child_node.Name:
600599
if self.__show_map:
601600
self.__log.info('Found node: %s', child_node.Name)
602601
new_nodes = [*nodes, {'path': f'{child_node.NamespaceIndex}:{child_node.Name}', 'node': node}]
@@ -643,7 +642,7 @@ async def find_node_name_space_index(self, path):
643642
unresolved = path[resolved_level:]
644643
return await self.__find_nodes(unresolved, current_parent_node=parent_node, nodes=resolved)
645644

646-
async def _get_device_info_by_pattern(self, pattern, get_first=False):
645+
async def _get_device_info_by_pattern(self, pattern, get_first=False, parent_node=None):
647646
"""
648647
Method used to retrieve device name/profile by pattern.
649648
Device name/profile can consist of path expressions or NodeId expressions but not both.
@@ -653,7 +652,7 @@ async def _get_device_info_by_pattern(self, pattern, get_first=False):
653652
3. If no matches found, returns the pattern as is.
654653
"""
655654

656-
search_results = await self.__get_device_expression_value_by_path(pattern)
655+
search_results = await self.__get_device_expression_value_by_path(pattern, parent_node=parent_node)
657656
if len(search_results) > 0:
658657
return search_results[0] if get_first else search_results
659658

@@ -663,10 +662,10 @@ async def _get_device_info_by_pattern(self, pattern, get_first=False):
663662

664663
return [pattern]
665664

666-
async def __get_device_expression_value_by_path(self, pattern: str) -> List[str]:
665+
async def __get_device_expression_value_by_path(self, pattern: str, parent_node=None) -> List[str]:
667666
results = []
668667

669-
search_result = re.search(r"\${([A-Za-z.:\\\d\[\]]+)}", pattern)
668+
search_result = re.search(r"\${([A-Za-z.:_\-\\\d\[\]]+)}", pattern)
670669
if search_result:
671670
try:
672671
group = search_result.group(0)
@@ -675,7 +674,7 @@ async def __get_device_expression_value_by_path(self, pattern: str) -> List[str]
675674
self.__log.error('Invalid pattern: %s', pattern)
676675
return results
677676

678-
nodes = await self.find_nodes(node_path)
677+
nodes = await self.find_nodes(node_path, current_parent_node=parent_node)
679678
self.__log.debug('Found device name nodes: %s', nodes)
680679

681680
for node in nodes:
@@ -785,23 +784,33 @@ async def _create_new_devices(self):
785784
continue
786785
self.__log.debug('Found devices: %s', nodes)
787786

788-
device_names = await self._get_device_info_by_pattern(
789-
device_config.get('deviceInfo', {}).get('deviceNameExpression'))
787+
for node in nodes:
788+
device_name_expression = device_config.get('deviceInfo', {}).get('deviceNameExpression')
789+
790+
is_abs_path = self.__is_absolute_path(device_name_expression)
791+
device_names = await self._get_device_info_by_pattern(device_name_expression,
792+
parent_node=node[-1]['node'] if not is_abs_path else None)
793+
794+
for device_name in device_names:
795+
scanned_devices.append(device_name)
790796

791-
for device_name in device_names:
792-
scanned_devices.append(device_name)
793-
if device_name not in existing_devices:
794-
for node in nodes:
797+
if device_name not in existing_devices:
795798
converter = self.__load_converter(device_config)
796-
device_profile = await self._get_device_info_by_pattern(
797-
device_config.get('deviceInfo', {}).get('deviceProfileExpression', 'default'),
798-
get_first=True)
799+
800+
device_profile_expression = device_config.get('deviceInfo', {}).get('deviceProfileExpression',
801+
'default')
802+
is_abs_path = self.__is_absolute_path(device_profile_expression)
803+
device_profile = await self._get_device_info_by_pattern(device_profile_expression,
804+
get_first=True,
805+
parent_node=node[-1]['node'] if not is_abs_path else None)
806+
799807
device_config = {**device_config, 'device_name': device_name, 'device_type': device_profile}
800808
device_path = [node_path_node_object['path'] for node_path_node_object in node]
801809
self.__device_nodes.append(
802810
Device(path=device_path, name=device_name, device_profile=device_profile,
803811
config=device_config,
804-
converter=converter(device_config, self.__converter_log),
812+
converter=converter(
813+
device_config, self.__converter_log),
805814
converter_for_sub=converter(device_config,
806815
self.__converter_log) if self.__enable_subscriptions else None,
807816
device_node=node[-1]['node'],
@@ -1467,6 +1476,13 @@ async def __fetch_server_limitations(self):
14671476
def __is_node_identifier(path):
14681477
return isinstance(path, str) and re.match(r"(ns=\d+;[isgb]=[^}]+)", path)
14691478

1479+
@staticmethod
1480+
def __is_absolute_path(path):
1481+
try:
1482+
return path.replace('${', '').split('\\.')[0] == 'Root'
1483+
except Exception:
1484+
return False
1485+
14701486

14711487
class SubHandler:
14721488
def __init__(self, queue, logger, status_change_callback):

0 commit comments

Comments
 (0)