OPC获取所有item的树型索引

本文详细介绍了对OPC相关代码进行优化的方法,包括提高读取大量点位树型结构的效率,根据枝干节点名获取所有叶子节点,以及判断节点类型等关键功能。通过具体代码示例,展示了如何构建和操作树型结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前不久又对opc相关代码做了优化,这里记录一下(2019-06-03)
这次主要新增或优化了以下功能:
当点位(ITEM)数量很多很多时,优化读取树型结构的效率;
根据一个枝干节点的名字获取该枝干下所有叶子节点;
判断一个名字对应节点的类型(枝干节点、叶子节点、都不是);

直接上代码

1. 树型结构

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author ws
 * @date 2019/3/12
 */
public class MapTree {
    String key;
    String value;
    List<MapTree> children;

    public MapTree() {
        key = null;
        value = null;
        children = new ArrayList<>();
        children.clear();
    }
    public MapTree(String key, String value) {
        this.key = key;
        this.value = value;
        children = new ArrayList<>();
        children.clear();
    }
    /**
     * 添加子树
     */
    public void addTree(MapTree mapTree) {
        children.add(mapTree);
    }

    /**
     * 根据key获取子树
     */
    public MapTree getChild(String key) {
        if (this.isEmpty()) {
            return null;
        } else {
            for (MapTree child : this.children) {
                if (child.key.equals(key)) {
                    return child;
                }
            }
            return null;
        }
    }

    /**
     * 置空树
     */
    public void clearTree() {
        key = null;
        value = null;
        children.clear();
    }

    /**
     * 获得树根
     */
    public MapTree root() {
        return this;
    }

    /**
     * 获取根节点的数据,放入一个map中
     */
    public Map<String, String> getRoot() {
        Map<String, String> m = new HashMap<>(1);
        m.put(key, value);
        return m;
    }

    /**
     * 判空
     */
    public boolean isEmpty() {
        return (this.children.isEmpty() && this.key == null && this.value == null);
    }

    /**
     * 判断是否为叶子节点
     */
    public boolean isLeaf() {
        return this.children.isEmpty();
    }

    /**
     * 返回当前子树(亦或是叶子)的孩子节点个数
     */
    public int size() {
        if (this.isEmpty()) {
            return 0;
        } else if (this.isLeaf()) {
            return 1;
        } else {
            return this.children.size();
        }
    }
}

2. 类私有变量

写就行了,先别管它是什么,待会用到你就知道了。

	private Server server = null;
    private Group group = null;
    private List<String> leavesList = new ArrayList<>();
    public List<String> getLeavesList() {
        return leavesList;
    }

3. 判断节点类型

	// 不存在则返回-1
    // 是枝干但是该枝干下叶子数为0则返回0
    // 是叶子则返回1
    // 是枝干且有叶子节点则返回2,所有叶子节点通过该类的getLeavesList()方法获取
    public Integer getAllLeaves(String istr) throws Exception {
        List<String> list = new ArrayList<>();
        TreeBrowser treeBrowser = server.getTreeBrowser();
        Branch curBranch = treeBrowser.browseBranches();
        String[] branch = istr.replace(".", ",").split(",");

        for (int index = 0; index < branch.length; index++) {
            treeBrowser.fillBranches(curBranch);
            if (curBranch.getBranches().size() > 0) {
                // 当前分支是否有这个子分支
                boolean hasBranch = false;
                for (Branch b : curBranch.getBranches()) {
                    if (b.getName().equals(branch[index])) {
                        hasBranch = true;
                        curBranch = b;
                        break;
                    }
                }
                if (!hasBranch) {
                    treeBrowser.fillLeaves(curBranch);
                    if (curBranch.getLeaves().size() > 0) {
                        // 当前分支是否有这个叶子
                        boolean hasLeaf = false;
                        for (Leaf lf : curBranch.getLeaves()) {
                            if (lf.getName().equals(branch[index])) {
                                hasLeaf = true;
                                break;
                            }
                        }
                        return hasLeaf ? 1 : -1;
                    } else {
                        // 也没这个叶子
                        return -1;
                    }

                }
            } else {
                // 如果遍历到了传进来分支的最后一个节点且当前分支叶子节点数>0
                if (index != branch.length - 1) {
                    return -1;
                }
                treeBrowser.fillLeaves(curBranch);
                if (curBranch.getLeaves().size() > 0) {
                    // 当前分支是否有这个叶子
                    boolean hasLeaf = false;
                    for (Leaf lf : curBranch.getLeaves()) {
                        if (lf.getName().equals(branch[index])) {
                            hasLeaf = true;
                            break;
                        }
                    }
                    return hasLeaf ? 1 : -1;
                } else {
                    return -1;
                }
            }
        }
        browseSubTree(treeBrowser, list, curBranch);
        if (list.size() == 0) {
            return 0;
        } else {
            leavesList = list;
            return 2;
        }

    }

    private void browseSubTree(TreeBrowser treeBrowser, List<String> list, Branch branch) {
        try {
            treeBrowser.fillBranches(branch);
        } catch (Exception ignored) {
        }
        try {
            treeBrowser.fillLeaves(branch);
        } catch (Exception ignored) {
        }
        Iterator iter = branch.getLeaves().iterator();
        while (iter.hasNext()) {
            Leaf leaf = (Leaf) iter.next();
            list.add(leaf.getItemId());
        }

        iter = branch.getBranches().iterator();
        while (iter.hasNext()) {
            Branch subBranch = (Branch) iter.next();
            //key和value都是subBranch.getName(),即群组名
            browseSubTree(treeBrowser, list, subBranch);
        }
    }

另,如果你只是想要知道它是不是枝干节点,用下面这个

4. 获取枝干节点

	// 获取一个枝干下的所有叶子,
    // 如果没有或者枝干名字错误则返回大小为0的List
    public List<String> getLeaves(String str) {
        List<String> items = new ArrayList<>();
        Collection<String> browse = null;
        try {
            browse = server.getFlatBrowser().browse();
        } catch (UnknownHostException | JIException e) {
            log.info("Failed to get flat browser of opc server " +
                    "while getting leaves of : {} ", str, e);
            return items;
        }
        for (String item : browse) {
            if (item.contains(str + ".")) {
                try {
                    group.addItem(item);
                    items.add(item);
                } catch (Exception ignored) {
                }
            }
        }
        return items;
    }

5. 获取树型结构

如果点位数量不多,用这个

	public MapTree getAllItems() {
        MapTree tree = new MapTree();
        try {
            TreeBrowser treeBrowser = this.server.getTreeBrowser();
            if (treeBrowser != null) {
                this.browserTree(treeBrowser, new Branch(), tree);
            }
        } catch (Exception e) {
            log.info("Get tree browser failed.", e);
        }

        return tree;
    }

    public void browserTree(TreeBrowser treeBrowser, Branch branch, MapTree tree) {

        try {
            treeBrowser.fillBranches(branch);
        } catch (Exception ignored) {
        }
        try {
            treeBrowser.fillLeaves(branch);
        } catch (Exception ignored) {
        }

        Iterator iter = branch.getLeaves().iterator();
        while (iter.hasNext()) {
            Leaf leaf = (Leaf) iter.next();
            //key是leaf.getName(),value是leaf.getItemId()
            tree.addTree(new MapTree(leaf.getName(), leaf.getItemId()));
            //this.itemList.put(leaf.getName(),leaf.getItemId())
        }

        iter = branch.getBranches().iterator();
        while (iter.hasNext()) {
            Branch subBranch = (Branch) iter.next();
            //key和value都是subBranch.getName(),即群组名
            tree.addTree(new MapTree(subBranch.getName(), subBranch.getName()));
            this.browserTree(treeBrowser, subBranch, tree.getChild(subBranch.getName()));
        }
    }

但是如果点位数量很多,比如好几万甚至更多,需要考虑效率问题,就用下面这个

// 获取平铺的所有item
    public MapTree getListItems() {
        MapTree tree = new MapTree();
        try {
            Collection<String> items = server.getFlatBrowser().browse();
            for (String s : items) {
                String[] split = s.replace(".", ",").split(",");
                MapTree t = tree.root();
                int index = -1;
                for (String i : split) {
                    index += i.length() + 1;
                    if (t.getChild(i) == null) {
                        String branchName = s.substring(0, index);
                        t.addTree(new MapTree(i, branchName));
                    }
                    t = t.getChild(i);
                }
            }
        } catch (UnknownHostException | JIException e) {
            log.info("Get flat browser failed.", e);

        }
        return tree;
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值