Kepware软件基本操作及使用Java Utgard实现OPC通信

一、环境搭建(基于win10 64位专业版)

1、Kepware 的下载、安装及使用

https://www.cnblogs.com/ioufev/p/9366877.html

2、重要:OPC 和 DCOM 配置(OPC DA 必须配置)

https://www.cnblogs.com/ioufev/p/9365919.html

二、使用 Utgard 实现 OPC 通信 1、添加 Maven 依赖 <!--utgard start--> <dependency> <groupId>org.openscada.external</groupId> <artifactId>org.openscada.external.jcifs</artifactId> <version>1.2.25</version> <exclusions> <exclusion> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.openscada.jinterop</groupId> <artifactId>org.openscada.jinterop.core</artifactId> <version>2.1.8</version> </dependency> <dependency> <groupId>org.openscada.jinterop</groupId> <artifactId>org.openscada.jinterop.deps</artifactId> <version>1.5.0</version> <exclusions> <exclusion> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.openscada.utgard</groupId> <artifactId>org.openscada.opc.dcom</artifactId> <version>1.5.0</version> </dependency> <dependency> <groupId>org.openscada.utgard</groupId> <artifactId>org.openscada.opc.lib</artifactId> <version>1.5.0</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.61</version> </dependency> <!--utgard end--> 2、简单读取示例 public class ReadTest { public static void main(String[] args) { //opc连接信息 final ConnectionInformation ci = new ConnectionInformation(); ci.setHost("127.0.0.1"); ci.setUser("OPCUser"); ci.setPassword("111111"); ci.setClsid("7BC0CC8E-482C-47CA-ABDC-0FE7F9C6E729"); //ci.setProgId(""); //要读取的标记 String item = "通道 1.设备 1.TAG1"; //连接对象 final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor()); try { //建立连接 server.connect(); //添加一个组 Group group = server.addGroup(); //将标记添加到组里 Item addItem = group.addItem(item); //读取标记的值 JIVariant variant = addItem.read(true).getValue(); //获取string类型的值 String value = variant.getObjectAsString().getString(); System.out.println("读到值:" + value); } catch (UnknownHostException | AlreadyConnectedException | JIException | NotConnectedException | DuplicateGroupException | AddFailedException e) { e.printStackTrace(); } finally { //关闭连接 server.disconnect(); } } }

kepware 客户端看到的点位信息:

Kepware软件基本操作及使用Java Utgard实现OPC通信

程序运行结果:

Kepware软件基本操作及使用Java Utgard实现OPC通信

(1)OPC 连接信息解释:

Host——本地主机/网络主机IP (示例:localhost(默认)、127.0.0.1)

Domain——域(默认为localhost)

User——用户名

Password——用户登录密码

Clsid——应用在注册表中相对应的CLSID值

Grogid——应用在注册表中对应的程序名称

Clsid 和 Grogid 作用相同,只要设置一个就可以了,如果两个都设置了,程序会优先选择Clsid。建议使用Clsid,因为使用Grogid时,Openscada的内部处理还是会通过JISystem.getClsidFromProgId( progId )方法将其转换为Clsid,并且还需要进行服务器上用户的权限的高级配置才可以使用。

查找Clsid的方法:搜索“组件服务”,找到“DCOM 配置”选项,找到安装的 kepware 服务器名称,右边可以看到“应用程序 ID”,如下图所示

Kepware软件基本操作及使用Java Utgard实现OPC通信

Kepware软件基本操作及使用Java Utgard实现OPC通信

(2)Kepware 与 Utgard 中类型对应:

在 java Utgard 里面类型使用数字来表示的,比如 String 类型是 8,在上面读取结果的图片中可以看到读取到的类型确实是8

Kepware软件基本操作及使用Java Utgard实现OPC通信

为了得到正确的数据类型我们需要对读到的结果判断一下,工具类如下,添加了常见类型的判断

@Slf4j public class OpcUtil { private OpcUtil() { } /** * 读单个值 */ public static String readValue(Item item) { try { ItemState state = item.read(true); return getValue(state); } catch (JIException e) { e.printStackTrace(); } return null; } /** * 读一组值,对于读取异常的点位会返回null值 */ public static List<String> readValues(Group group, List<String> tags) { //添加到group中,如果添加失败则添加null List<Item> items = tags.stream().map(tag -> { try { return group.addItem(tag); } catch (Exception e) { log.info(e.toString()); } return null; }).collect(Collectors.toList()); List<String> result = new ArrayList<>(); try { //读取所有的值,过滤null值,否则会出异常 Map<Item, ItemState> map = group.read(true, items.stream().filter(Objects::nonNull).toArray(Item[]::new)); //解析 for (Item item : items) { if (item == null) { result.add(null); continue; } String value = getValue(map.get(item)); result.add(value); } } catch (JIException e) { e.printStackTrace(); } return result; } /** * 如果是 bool、string、short、int等直接返回字符串; * 如果是 long 类型的数组,返回数字内容间加点,对应 long,数组,大小为6 * 如果是 float 类型的数组,返回数字内容间加逗号,对应 float,数组,大小为20 */ private static String getValue(ItemState state) { JIVariant variant = state.getValue(); try { int type = variant.getType(); //Boolean if (type == JIVariant.VT_BOOL) { boolean value = variant.getObjectAsBoolean(); return String.valueOf(value); } //String else if (type == JIVariant.VT_BSTR) { return variant.getObjectAsString().getString(); } //Word DWord else if (type == JIVariant.VT_UI2 || type == JIVariant.VT_UI4) { Number value = variant.getObjectAsUnsigned().getValue(); return String.valueOf(value); } //Sort else if (type == JIVariant.VT_I2) { short value = variant.getObjectAsShort(); return String.valueOf(value); } //Float else if (type == JIVariant.VT_R4) { float value = variant.getObjectAsFloat(); return String.valueOf(value); } //long 类型的数组 else if (type == 8195) { JIArray jarr = variant.getObjectAsArray(); Integer[] arr = (Integer[]) jarr.getArrayInstance(); StringBuilder value = new StringBuilder(); for (Integer i : arr) { value.append(i).append("."); } String res = value.substring(0, value.length() - 1); // "25.36087601.1.1.18.36"-->"25.36087601.01.0001.18.36" String[] array = res.split("[.]"); return array[0] + "." + array[1] + "." + new DecimalFormat("00").format(Long.valueOf(array[2])) + "." + new DecimalFormat("0000").format(Long.valueOf(array[3])) + "." + array[4] + "." + array[5]; } //float 类型的数组 else if (type == 8196) { JIArray jarr = variant.getObjectAsArray(); Float[] arr = (Float[]) jarr.getArrayInstance(); StringBuilder value = new StringBuilder(); for (Float f : arr) { value.append(f).append(","); } return value.substring(0, value.length() - 1); } //其他类型 else { Object value = variant.getObject(); return String.valueOf(value); } } catch (JIException e) { e.printStackTrace(); } return null; } /** * 写值到变量 */ public static void writeValue(Item item, String val) { try { JIVariant value = new JIVariant(val); item.write(value); } catch (JIException e) { e.printStackTrace(); } } /** * 写值到变量:数组 */ public static void writeValueToArr(Item item, String[] snArray) { try { //构造写入数据 Long[] integerData = new Long[snArray.length]; for (int i = 0; i < snArray.length; i++) { integerData[i] = Long.valueOf(snArray[i]); } final JIArray array = new JIArray(integerData, false); final JIVariant value = new JIVariant(array); item.write(value); } catch (JIException e) { e.printStackTrace(); } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzswp.html