opc java_Java OPC 代码

这是我项目的代码,算是真实业务实现,记录备份一下实现思路

因为业务就是简单的获取数据然后保存,所以还是容易理解的

1.任务详情

Java实现OPC通信的代码实现

最终实现对西门子的S7-300的PLC变量的值读写

2.实现情况

使用utgard实现通信:Java实现OPC通信

OPCserver:KEPserver6

制定变量列表:规定名称和类型

说明

PC和PLC通信,PC用TAG1之类的地址,PLC用BD1.INT05之类的地址,个人总结的表格,方便说明

OPCServer上定义的地址名称

硬件PLC上的地址

数据类型

说明:这个地址做什么用的

TAG1

DB1.INT00

short

心跳

TAG2

DB1.INT02

short

控制字

TAG3

DB1.STRING4,10

string

箱体信息

TAG4

DB1.D14

float

结果

地址定义在OPCServer上,实际截图

3c32fcf11e9ecf642b507f73c25efb87.png

制定交互流程:控制字的状态

心跳变量:TAG1,表示软件和硬件(这里是PLC)连接状态,这个是自己随便定义的,我的是:PLC一直写1,PC收到1写2,5秒内一直收不到1就是断开了。

控制字(状态变量):TAG2,作用是作为一个控制字,控制整个交互的流程,当是不同值时,PLC和PC要进行指定的读写动作。

这是我一开始画的

1b633b5f9adaa66d53329361db5415da.png

这是后来画的,就是PC和PLC的交互,比较清晰了

d80ac364ff99aeeeafddeacfae56c80b.png

实际的PLC地址编辑界面截图

3703711e84a9462c46fca1a0f5904054.png

3. 代码实现

按照官方例子写了一个通信类:通过配置信息,启动server,添加要读取的地址

配置信息是单独一个类:从配置文件读取IP什么的

然后是回调函数:某个地址,读到了某个值要怎么做,,在这就2个回调,心跳TAG1:读到1写入2,5秒超时,TAG2:是某个值时,怎么做。。。

读值和写值可以单独算一个方法类:我用到的数据类型就是几个,short,string,Long Array,对应写了几个方法

OPCServer上的地址配置也算是一个单独的类:我写在配置文件了,当时犹豫是不是放到数据库,感觉差别不大

Utgard有两种数据访问方式——直接通过item的read/write方法或者使用AccessBase(读取数据)

心跳TAG1:PC写2,PLC写1,逻辑是PC收到1写2,超时提示

控制字TAG2:PLC写0,1,3,4,5,6/7,PC写2,8

PC在写TAG2=1时,同时写入TAG3值

PLC在写TAG2=6/7时,同时写入TAG4值

读线程:每隔500ms读一次值,读到值后执行回调方法DataCallback()

不用另起线程,直接用这个Access线程循环读取控制字的值,回调方法对应调用item的read/write方法读写值

final AccessBase access = new SyncAccess(server, 500);

access.addItem(itemId, new DataCallback() {

@Override

public void changed(Item item, ItemState state) {

System.out.println("-----" + state);

}

});

// start reading

access.bind();

4.代码:OPCserver连接配置类

import java.io.IOException;

import java.util.Properties;

import org.openscada.opc.lib.common.ConnectionInformation;

/**

* 配置文件工具类

*/

public final class OPCConfiguration {

private final static ConnectionInformation ci;

private final static Properties prop;

public final static String CONFIG_USERNAME = "username";

public final static String CONFIG_PASSWORD = "password";

public final static String CONFIG_HOST = "host";

public final static String CONFIG_DOMAIN = "domain";

public final static String CONFIG_CLSID = "clsid";

public final static String CONFIG_PROGID = "progid";

private final static String CONFIG_FILE_NAME = "opc.properties";

/**

* 加载配置文件

*/

static {

ci = new ConnectionInformation();

prop = new Properties();

try {

prop.load(OPCConfiguration.class.getClassLoader().getResourceAsStream(CONFIG_FILE_NAME));

} catch (IOException e) {

e.printStackTrace();

}

}

/**

* 通过名字获得配置的值

*/

public static String getEntryValue(String name) {

return prop.getProperty(name);

}

/**

* 获得包含ClsId的连接信息

*/

public static ConnectionInformation getCLSIDConnectionInfomation() {

ci.setProgId(null);

getConnectionInfomation();

ci.setClsid(prop.getProperty(CONFIG_CLSID));

return ci;

}

/**

* 获得包含ProgId的连接信息

*/

public static ConnectionInformation getPROGIDConnectionInfomation() {

ci.setClsid(null);

getConnectionInfomation();

ci.setProgId(prop.getProperty(CONFIG_PROGID));

return ci;

}

/**

* 获得基础的连接信息

*/

private static void getConnectionInfomation() {

ci.setHost(prop.getProperty(CONFIG_HOST));

ci.setDomain(prop.getProperty(CONFIG_DOMAIN));

ci.setUser(prop.getProperty(CONFIG_USERNAME));

ci.setPassword(prop.getProperty(CONFIG_PASSWORD));

}

}

5.代码:通信实现类

package cn.com.tcb.assembly.management.listener;

import static cn.com.tcb.assembly.management.listener.OPCConfiguration.getCLSIDConnectionInfomation;

import java.util.concurrent.Executors;

import org.jinterop.dcom.common.JIException;

import org.openscada.opc.lib.common.ConnectionInformation;

import org.openscada.opc.lib.da.AccessBase;

import org.openscada.opc.lib.da.Group;

import org.openscada.opc.lib.da.Item;

import org.openscada.opc.lib.da.Server;

import org.openscada.opc.lib.da.SyncAccess;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

/**

* 功能:OPC通信线程 描述:通过循环读取心跳和状态控制字,按照商议好的交互流程读写变量

*/

public class OPCComm {

private static Logger logger = LoggerFactory.getLogger(OPCComm.class);

private Item item_heartbeat;

private Item item_status;

private Item item_ordernum;

private Item item_sn;

private Item item_boxnum;

private Item item_abnormal;

private Item item_finish;

private Item item_result;

private Server server;

/**

* 单例模式

*/

private static class SingletonHolder {

static final OPCComm doOPCComm = new OPCComm();

}

public static OPCComm getInstance() {

return SingletonHolder.doOPCComm;

}

/**

* 启动server 创建一个监控线程 创建一个写入线程

*/

public void init() throws Exception {

// 加载配置文件

final ConnectionInformation ci = getCLSIDConnectionInfomation();

// 创建server

final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());

try {

// 启动server

server.connect();

logger.info("This is {} message.", "OPCserver connect success");

this.server = server;

// 同步读取,500ms一次

final AccessBase access = new SyncAccess(server, 500);

access.addItem(OPCElement.ITEMID_HEARTBEAT, new DataCallBack_HeartBeat());

access.addItem(OPCElement.ITEMID_STATUS, new DataCallBack_Status());

// 添加一个组

final Group group = server.addGroup("sew");

item_heartbeat = group.addItem(OPCElement.ITEMID_HEARTBEAT);

item_status = group.addItem(OPCElement.ITEMID_STATUS);

item_ordernum = group.addItem(OPCElement.ITEMID_ORDERNUM);

item_sn = group.addItem(OPCElement.ITEMID_SN);

item_boxnum = group.addItem(OPCElement.ITEMID_BOXNUM);

item_abnormal = group.addItem(OPCElement.ITEMID_ABNORMAL);

item_finish = group.addItem(OPCElement.ITEMID_FINISH);

item_result = group.addItem(OPCElement.ITEMID_RESULT);

// start reading

access.bind();

} catch (final JIException e) {

System.out.println(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));

}

}

public Item getItem_heartbeat() {

return item_heartbeat;

}

public Item getItem_status() {

return item_status;

}

public Item getItem_ordernum() {

return item_ordernum;

}

public Item getItem_sn() {

return item_sn;

}

public Item getItem_boxnum() {

return item_boxnum;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值