Java实现OPCDA数据监听与写入

      监听OPC服务端,接收订阅标记的数据。通过Java观察者模式,只有当订阅的标记发生改变,系统才会捕捉到改变的数据,并对数据进行操作。
      为了更方便的操作OPC,将OPC的配置信息写入application.yml配置文件中。


application.yml
opc:
  host: 192.168.1.205
  domain:
  user: OPCUser
  password: 123456
  progId: Kepware.KEPServerEX.V6
  itemIdList:
    - Memorybase.Device01.TAG01
    - Memorybase.Device01.TAG02
    - Memorybase.Device01.TAG03
SpringUtil.java

将类注入到Spring容器

package com.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtil implements ApplicationContextAware{
	private static ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		if (SpringUtil.applicationContext == null) {
			SpringUtil.applicationContext = applicationContext;
		}
	}
	
	/**
	 * 获取applicationContext
	 * @return
	 */
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	/**
	 * 通过name获取bean
	 * @param name
	 * @return
	 */
	public static Object getBean(String name) {
		return getApplicationContext().getBean(name);
	}
	
	/**
	 * 通过class获取bean
	 * @param <T>
	 * @param clazz
	 * @return
	 */
	public static <T> T getBean(Class<T> clazz) {
		return getApplicationContext().getBean(clazz);
	}
	
	/**
	 * 通过name,以及clazz返回指定的bean
	 * @param <T>
	 * @param name
	 * @param clazz
	 * @return
	 */
	public static <T> T getBean(String name,Class<T> clazz) {
		return getApplicationContext().getBean(name,clazz);
	}
}

OpcProperties.java

读取yml配置文件中的值,在需要使用配置的类中通过@Autowried注册用getter()方法获取值

package com.opc;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
@ConfigurationProperties(prefix = "opc")
public class OpcProperties {
    private String host;
    private String domain;
    private String user;
    private String password;
    private String progId;
    private List<String> itemIdList;

    public OpcProperties() {
    }

    public OpcProperties(String host, String domain, String user, String password, String progId, List<String> itemIdList) {
        this.host = host;
        this.domain = domain;
        this.user = user;
        this.password = password;
        this.progId = progId;
        this.itemIdList = itemIdList;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getProgId() {
        return progId;
    }

    public void setProgId(String progId) {
        this.progId = progId;
    }

    public List<String> getItemIdList() {
        return itemIdList;
    }

    public void setItemIdList(List<String> itemIdList) {
        this.itemIdList = itemIdList;
    }
}

OpcMap.java

将读到的OPC的数据放入Map集合,方便后面对OPC的数据进行读写操作。

package com.opc;

import java.util.HashMap;
import java.util.Map;

/**
 * 操作OPC数据
 */
public class OpcMap {

	private static Map<String, Object> opcMap = new HashMap<String, Object>();

	/**
	 * 数据放入opcMap集合
	 */
	public static void putMap(String itemId, Object value) {
		opcMap.put(itemId, value);
	}

	/**
	 * 根据opc标签从opcMap集合中读数据
	 */
	public static Object getMap(String ItemId) {
		return opcMap.get(ItemId);
	}

}

OpcClient.java

建立OPC客户端,实现连接、异步读取数据等操作

package com.opc;

import com.result.Result;
import org.jinterop.dcom.common.JIException;
import org.openscada.opc.dcom.list.ClassDetails;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.da.*;
import org.openscada.opc.lib.da.browser.FlatBrowser;
import org.openscada.opc.lib.list.Categories;
import org.openscada.opc.lib.list.Category;
import org.openscada.opc.lib.list.ServerList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.UnknownHostException;
import java.util.Collection;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

public class OpcClient extends Observable {
    private Server mServer = null;

    private static final Logger LOGGER = LoggerFactory.getLogger(OpcClient.class);

    /**
     * 连接opc服务
     *
     * @param host
     * @param progId
     * @param user
     * @param password
     * @param domain
     * @return
     */
    public synchronized boolean connectionServer(String host, String progId, String user, String password, String domain) throws UnknownHostException {
        boolean mState = false;
        ServerList serverList = null;

        try {
            // 获取server上的opc server列表
            serverList = new ServerList(host, user, password, domain);
            // 连接server
            final ConnectionInformation connectionInfo = new ConnectionInformation();
            connectionInfo.setHost(host);
            connectionInfo.setClsid(serverList.getClsIdFromProgId(progId));
            connectionInfo.setUser(user);
            connectionInfo.setPassword(password);

            ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
            mServer = new Server(connectionInfo, executor);
            mServer.connect();

            mServer.addStateListener(new ServerConnectionStateListener() {

                @Override
                public void connectionStateChanged(boolean connected) {
                    LOGGER.info("connectionStateChanged state = {}", connected);
                }
            });
            mState = true;
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        } finally {
            if (!mState) {
                mServer = null;
            }
        }
        return mState;
    }

    /**
     * 断开opc连接
     */
    public synchronized void disconnectServer() {
        if (mServer == null) {
            return;
        }
        mServer.disconnect();
        mServer = null;
    }

    /**
     * 显示server上的opc服务器应用列表
     *
     * @param host
     * @param user
     * @param password
     * @param domain
     */
    public void showAllOPCServer(String host, String user, String password, String domain) {
        try {
            ServerList serverList = new ServerList(host, user, password, domain);
            Collection<ClassDetails> detailList = serverList.listServersWithDetails(new Category[]{Categories.OPCDAServer10, Categories.OPCDAServer20}, new Category[]{});
            for (ClassDetails details : detailList) {
                LOGGER.info("ClsId=" + details.getClsId() + ",ProgId=" + details.getProgId() + ",Description=" + details.getDescription());
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        }
    }

    /**
     * 检查OPC server 中是否包含指定的监测点列表
     *
     * @param list
     * @return
     */
    public boolean checkItemList(List<String> list) {
        // 获取OPCSserver上的所有监测点
        FlatBrowser flatBrowser = mServer.getFlatBrowser();
        if (flatBrowser == null) {
            return false;
        }
        try {
            Collection<String> collection = flatBrowser.browse();
            return collection.containsAll(list);
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        }
        return false;
    }

    /**
     * 异步读取数据
     *
     * @param itemIdList
     * @param period
     */
    public void readObjectList(List<String> itemIdList, int period) {
        AccessBase accessBase;
        try {
            accessBase = new Async20Access(mServer, period, true);
            for (String itemId : itemIdList) {
                accessBase.addItem(itemId, new DataCallback() {
                    @Override
                    public void changed(Item item, ItemState itemState) {
                        try {
                            Object value = itemState.getValue().getObject();
                            setData(itemId, value);
                            OpcMap.putMap(itemId, value);//监听到的数据放入map集合中
                        } catch (JIException e) {
                            LOGGER.error(e.getMessage());
                        }
                    }
                });
            }
            while (true) {
                accessBase.bind();
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
        }
    }

    /**
     * 向OPC中写数据
     *
     * @param value
     */
    public void writeOPC(Object value) {
        try {
            // Add a new group,添加一个组,这个用来就读值或者写值一次,而不是循环读取或者写入
            // 组的名字随意,给组起名字是因为,server可以addGroup也可以removeGroup,读一次值,就先添加组,然后移除组,再读一次就再添加然后删除
            Group group = mServer.addGroup("test");
            // Add a new item to the group,
            // 将一个item加入到组,item名字就是MatrikonOPC Server或者KEPServer上面建的项的名字
            Item item = group.addItem("channel01.device01.tag03");
            //LOGGER.info("\n向OPC" + item.getId() + "中写入值");
            item.write(new JIVariant(value.toString()));
            mServer.removeGroup(group, true);
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error(e.getMessage());
        }
    }

    /**
     * 注册
     *
     * @param observer
     */
    public void subscribe(Observer observer) {
        this.addObserver(observer);
    }

    /**
     * 数据变化通知观察者
     *
     * @param itemId
     * @param value
     */
    private void setData(String itemId, Object value) {
        setChanged();
        notifyObservers(new Result(itemId, value));
    }
}

UtgardTutorial.java

使用Utgard框架完成对OPC的操作

package com.utgard;

import com.opc.OpcClient;
import com.opc.OpcMap;
import com.opc.OpcProperties;
import com.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.net.UnknownHostException;
import java.util.Observable;
import java.util.Observer;

/**
 * 操作OPC UA
 */
@Configuration
public class UtgardTutorial {
    private static final Logger LOGGER = LoggerFactory.getLogger(UtgardTutorial.class);

    @Autowired
    private OpcProperties opc;

    public void start(){
        OpcClient opcClient = new OpcClient();
        // 显示server上的opc server应用列表
        opcClient.showAllOPCServer(opc.getHost(), opc.getUser(), opc.getPassword(), opc.getDomain());

        // 连接指定的opc server
        try {
            boolean ret = opcClient.connectionServer(opc.getHost(), opc.getProgId(), opc.getUser(), opc.getPassword(), opc.getDomain());
            if (!ret) {
                LOGGER.info("connect opc server fail");
                return;
            }

            ret = opcClient.checkItemList(opc.getItemIdList());
            if (!ret) {
                LOGGER.info("not contain item list");
                return;
            }

            // 注册回调
            opcClient.subscribe(new Observer() {
                @Override
                public void update(Observable o, Object arg) {
                    Result result = (Result) arg;
                    OpcMap.putMap(result.getItemId(),result.getValue());//改变的值放入集合
                    LOGGER.info("\n----------发送改变的数据----------" + "\nitemId:" + result.getItemId() + "\nvalue:" + result.getValue() + "\n------------------------------");
                    // 向opc中写入数据
                    opcClient.writeOPC(result.getValue());
                }
            });

            // 添加监测点数据
            opcClient.readObjectList(opc.getItemIdList(), 500);
        } catch (UnknownHostException e) {
            LOGGER.error(e.getMessage());
        }
    }
}

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Java OPC UA 是一种基于Java编程语言开发OPC UA(开放式平台通讯统一架构)实现OPC UA是一种跨平台、跨网络的通信协议,用于在工业自动化系统中的不同设备之间进行数据交换。Java OPC UA提供了一套可扩展的API(应用程序接口),用于实现OPC UA客户端和服务器的通信。 使用Java OPC UA,我们可以轻松地开发OPC UA客户端和服务器应用程序。对于开发者来说,Java是一种常用且广泛支持的编程语言,具有良好的跨平台性能。通过Java OPC UA,我们可以在不同的操作系统上构建可靠的OPC UA应用程序,这些应用程序可以在Windows、Linux、Mac等平台上运行。 Java OPC UA提供了丰富的功能和工具,方便开发者使用。它提供了标准的OPC UA功能,如节点浏览、属性读写、方法调用等。此外,Java OPC UA还提供了一些高级功能,如安全性、事件触发和历史数据访问等。这些功能可以帮助我们更好地控制和监控工业自动化系统中的设备和数据Java OPC UA的使用也非常灵活和可扩展。我们可以根据自己的需求进行定制和扩展。它支持多种网络传输协议,如TCP、HTTP和HTTPS。我们还可以使用不同的编码和解码方式,如二进制和XML。这使得Java OPC UA适用于各种不同的应用场景。 总而言之,Java OPC UA是一种强大的工具,可用于开发实现工业自动化系统中的数据交换和通信。它提供了丰富的功能和灵活的使用方式,使开发者能够更好地控制和监控系统中的设备和数据
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值