def get_udt_configuration(instance_path, category = None): """ Scans a UDT instance for members belonging to a UI category and returns their display configurations. Optional category argumen, if defined, it will returna filtered list. Beware of this instruction, it uses system.tag.readBlocking. Args: instance_path (str): The UDT path target_category (str): The filter criteria (e.g., 'Status', 'Control', 'Config'). Returns: list: A list of UDT items tagpaths and it's custom properties. """ # 1. Browse for all tags inside the instance fltr = {'tagType':'UdtInstance', 'recursive':True} results = system.tag.browse(instance_path, fltr) # Identify the properties we need for each tag founf property_names = [ '/parameters.item_label', '.uiAccessLevel', '.uiGroup', '.isHidden', '.uiStates', '.uiOrder', '.uiType', '.uiWidget', '/parameters.Parent_Asset_Label', '.uiFormat', '.uiConfig'] # 2. Build a flat list of paths to read everything in on Gatewya request read_paths = [] tags_found = [str(r['fullPath']) for r in results] for tag in tags_found: for prop in property_names: read_paths.append('%s%s' % (tag, prop)) all_values = system.tag.readBlocking(read_paths) # for value in all_values: # print value # 3. Process the result in 'chunks' # step by the length of properties output = [] step = len(property_names) for i in range(0, len(all_values), step): chunk = all_values[i : i + step] if category is not None and chunk[6].value != category: continue subpath = tags_found[i // step].split(instance_path)[-1] output.append({ "sub_path": subpath, "read_only": bool(chunk[0].value), "access_level": chunk[1].value, "group": chunk[2].value, "is_hidden": bool(chunk[3].value), "states": chunk[4].value, "order": chunk[5].value, "type": chunk[6].value, "widget": chunk[7].value, "label": chunk[8].value, "format": chunk[9].value, "config": chunk[10].value, }) return output def get_udt_configuration_async(instance_path, on_finished_callback): """ Scans a UDT instance for members belonging to a UI category and returns their display configurations. Args: instance_path (str): The UDT path target_category (str): The filter criteria (e.g., 'Status', 'Control', 'Config'). Returns: list: A list of strings representing the full paths to the matching tags. """ # 1. Browse for all tags inside the instance fltr = {'tagType':'UdtInstance', 'recursive':True} results = system.tag.browse(instance_path, fltr) # Identify the properties we need for each tag founf property_names = [ '.isReadOnly', '.uiAccessLevel', '.uiGroup', '.isHidden', '.uiStates', '.uiOrder', '.uiType', '.uiWidget', '/parameters.Parent_Asset_Label'] # 2. Build a flat list of paths to read everything in on Gatewya request read_paths = [] tags_found = [str(r['fullPath']) for r in results] for tag in tags_found: for prop in property_names: read_paths.append('%s%s' % (tag, prop)) def handle_read_finished(all_values): output = [] step = len(property_names) for i in range(0, len(all_values), step): chunk = all_values[i : i + step] output.append({ "tagPath": tags_found[i // step], "read_only": bool(chunk[0].value), "access_level": chunk[1].value, "group": chunk[2].value, "is_hidden": bool(chunk[3].value), "states": chunk[4].value, "order": chunk[5].value, "type": chunk[6].value, "widget": chunk[7].value, "label": chunk[8].value, }) on_finished_callback(output) system.tag.readAsync(read_paths, handle_read_finished) def generate_flex_array(list_tags, base_path): """ This function, generates de array for the flex repeater in details pages, it hides the elements based on is_hidden property and concatenates the dinamyc tagpath with the item sub path Args: instance_path (str): The UDT path Returns: list: A list of tags to be used in detail pages flex repeater. """ output = [] for item in list_tags: if item['is_hidden'] is True: continue new_item = dict(item) new_item['tagpath'] = base_path + str(item.get('sub_path', '')) tag= {'item': new_item} output.append(tag) return output