如何从kepware获取标签属性(地址,描述)?

时间:2019-06-17 08:48:41

标签: tags auto-update opc-ua

我有一个关于自动化摄取管道的问题。我正在从kepware服务器读取所有标签,并使用nifi吸收它们。我正在使用opcua客户端来查看是否有一个已添加到kepware服务器的标签,并且还获取了该标签的描述和地址。但是这种方式太慢了,并使kepware服务器停止工作。

是否有任何方法可以检测kepware服务器中添加的标签和属性(地址,说明),而无需使用每10秒从服务器读取一次的轮询方法?

我正在使用以下内容,但效率不高,因为我们从kepware读取多达200000个标签:/

from opcua import Client, ua
from opcua.ua import status_codes
from threading import Thread
import threading
import logging
import time
import csv
import re

NUM_SUBSCRIPTIONS = 10


output_files_name_machines_tags = []
for i in range(NUM_SUBSCRIPTIONS):
    output_file = "../resources/machine_tags_"+str(i)+".txt"
    output_files_name_machines_tags.append(output_file)


output_file_name_special_tags = "../resources/advanced_Tags.txt"
tags_description = '../resources/tags_description.csv'

special_tag = "ns=2;s=_AdvancedTags"
Infos = ['Address','Description']


#logging.basicConfig(level=logging.WARN)
client = Client("opc.tcp://10.129.140.215:49320/",timeout=3600000)


class Industrial_Tags_Updater():
    list_machine_tags_changed = [False]*NUM_SUBSCRIPTIONS
    list_special_tags_changed = False
    list_machine_tags = [[] for i in range(NUM_SUBSCRIPTIONS)]
    list_special_tags = []
    output_description_tags = []
    output_description_tags_changed = False
    distribute_integer = 0
    nodes_to_be_described = []


    def process_tag_nodes(self, node_child_level_1):
        nodes_children_level_2 = node_child_level_1.get_children()

        #print(nodes_children_level_2)
        for node_child_level_2 in nodes_children_level_2:
            if not "._" in get_node_string(node_child_level_2):
                #print(node_child_level_2)
                nodes_children_level_3 = node_child_level_2.get_children()
                for node_child_level_3 in nodes_children_level_3:
                    tag_name = get_node_string(node_child_level_3)
                    if special_tag in tag_name:
                        nodes_children_level_4 = node_child_level_3.get_children()
                        for node_child_level_4 in nodes_children_level_4:
                            #print(get_node_string(node_child_level_4))
                            if not get_node_string(node_child_level_4) in self.list_special_tags:
                                self.list_special_tags_changed = True
                                self.list_special_tags.append(get_node_string(node_child_level_4))
                                self.output_description_tags.append([get_node_string(node_child_level_4)])

                    elif not "._" in tag_name:
                        if not any(tag_name in list for list in self.list_machine_tags):
                            for info in Infos:
                                self.nodes_to_be_described.append(tag_name+"._"+info)


        params = ua.ReadParameters()
        if self.nodes_to_be_described:
            for node_id_str in self.nodes_to_be_described:
                nodeid = ua.NodeId.from_string(node_id_str)
                attr = ua.ReadValueId()
                attr.NodeId = nodeid
                attr.AttributeId = ua.AttributeIds.Value
                params.NodesToRead.append(attr)

            results = client.uaclient.read(params)


            for i in range(0,len(results),len(Infos)):
                tag_str = params.NodesToRead[i].NodeId.to_string().replace('._'+Infos[0],'')
                if results[i].StatusCode.name != 'BadNodeIdUnknown':
                    tag_description = []
                    tag_description.append(tag_str)
                    for j in range(len(Infos)):
                        tag_description.append(results[i+j].Value.Value)
                    if tag_description not in self.output_description_tags:
                        self.output_description_tags.append(tag_description)
                        self.output_description_tags_changed = True
                        #print(tag_description)

                    if not any(tag_str in list for list in self.list_machine_tags):
                        self.list_machine_tags[int(self.distribute_integer/10)%NUM_SUBSCRIPTIONS].append(tag_str)
                        self.list_machine_tags_changed[int(self.distribute_integer/10)%NUM_SUBSCRIPTIONS] = True
                        self.distribute_integer += 1

                else :
                    node_child_level_3 = client.get_node(tag_str)   
                    nodes_children_level_4 = node_child_level_3.get_children()
                    for node_child_level_4 in nodes_children_level_4:
                        node_string = get_node_string(node_child_level_4)
                        if not any(node_string in list for list in self.list_machine_tags):
                            self.list_machine_tags[int(self.distribute_integer/10)%NUM_SUBSCRIPTIONS].append(node_string)
                            self.list_machine_tags_changed[int(self.distribute_integer/10)%NUM_SUBSCRIPTIONS] = True
                            self.output_description_tags.append([node_string])
                            self.distribute_integer += 1



    #Write the list of tags to be consumed by nifi processor
    def write_machine_tags_file(self, file, num_subscription):
        output_file = open(file, "w")
        output_file.write("\n".join(self.list_machine_tags[num_subscription]))
        output_file.close()
        print("List machine tags file updated pour la soubscription"+str(num_subscription))

    #Write the list of tags to be consumed by nifi processor
    def write_special_tags_file(self, ):
        output_file = open(output_file_name_special_tags, "w")
        output_file.write("\n".join(self.list_special_tags))
        output_file.close()
        print("List special tags file updated")

    def write_description_file(self, ):
        #write to a csv file the description of the tags
        infos_data = self.output_description_tags
        for i in range(len(infos_data)):
             infos_data[i] = (infos_data[i] + (len(Infos)+1) * [""])[:len(Infos)+1]

        fieldnames = ["Tag_name"]
        fieldnames.extend(Infos)
        infos_data.insert(0,fieldnames)

        with open(tags_description, 'w') as csvFile:
            writer = csv.writer(csvFile)
            writer.writerows(infos_data)
        print("Description tags file updated")
        csvFile.close()

    def reset_update_description_change(self, ):
        self.output_description_tags_changed = False
        self.output_description_tags = []

    def reset_update_machine_change(self, ):
        self.list_machine_tags_changed = [False]*NUM_SUBSCRIPTIONS

    def reset_update_special_change(self, ):
        self.list_special_tags_changed = False



if __name__ == "__main__":

    def get_node_string(node):
        return node.nodeid.to_string()

    try:
        client.connect()
        objects = client.get_objects_node()
        nodes_children_level_1 = objects.get_children()
        #print(nodes_children_level_1)
        nodes_level_1_filtred = []
        nodes_level_1_filtred.append(client.get_node(special_tag))
        for node_child_level_1 in nodes_children_level_1:
            pattern = r'ns=2;s=[^_]'
            if re.match(pattern, get_node_string(node_child_level_1)):
                nodes_level_1_filtred.append(node_child_level_1)

        tags_updater = Industrial_Tags_Updater()

        #print(nodes_level_1_filtred)
        while True:
            #Creation of threads
            threads_list = []
            for node_child_level_1 in nodes_level_1_filtred:
                threads_list.append(Thread(target=tags_updater.process_tag_nodes, args=(node_child_level_1, )))

            #launching threads
            for thread in threads_list:
                thread.start()
            #waiting the threds to be finished
            for thread in threads_list:
                thread.join()

            #print("finished")

            if tags_updater.list_special_tags_changed or True in tags_updater.list_machine_tags_changed or tags_updater.output_description_tags_changed:
                tags_updater.write_description_file()
                tags_updater.reset_update_description_change()

            for i in range(NUM_SUBSCRIPTIONS):
                if tags_updater.list_machine_tags_changed[i]:
                    tags_updater.write_machine_tags_file(output_files_name_machines_tags[i], i)

            tags_updater.reset_update_machine_change()

            if tags_updater.list_special_tags_changed:
                tags_updater.write_special_tags_file()
                tags_updater.reset_update_special_change()


            #Schedule the the threads to run evry minutes
            time.sleep(10)

    finally:
        client.disconnect()

我们可以在kepware中添加事件以告知客户端已添加标签吗,还是可以使用kepware API在人们在此API中添加标签的地方?我不知道是否有解决此问题的解决方案,请帮忙!

0 个答案:

没有答案