关于java 服务端连接 OPC DA server 三天一路走来从小白到连接成功的坑,使用JeasyOPC

公司需要对接一些设备服务,是部署在windows的OPC Server 。对于一个连opc都没接触过的人来说除了去百度别无他法

首先连上了对应的windows服务器 有部署了服务和相应的OPC连接工具,连接工具可以测试连接并且可以看到是可以连接上的

可以看到使用的是 什么Martrikon OPC Explorer 工具

先去这个工具官网看一下有没有连接示例

找了一下好吧是我想多了并没有 ,那就只能找别的了,他们设备第三方也提供不出来。

那就网上找吧,找到一篇文章,包括OPC基础信息以及简介

Java OPC client开发踩坑记_weixin_33834075的博客-CSDN博客

只是浅看了一下了解了一下DCOM配置

最后了解到了这样一个开源包

j-Interopicon-default.png?t=N7T8https://www.oschina.net/informat/j-interop

j-Interop (Java - DCOM Access Bridge) 是实现DCOM wire protocol (MSRPC)的一个开源类包。可用于开发双向,Non-Native,能够与任何COM组件交互的纯Java应用程序。该项目全部采用纯Java实现并 且没有使用JNI(Java Native Interface)来提供对COM的访问。

        <dependency>
            <groupId>org.jinterop</groupId>
            <artifactId>j-interop</artifactId>
            <version>3.0.0</version>
        </dependency>

依赖可以直接引用,找不到的可以去远程仓库找其他版本

可以看到里面有个test 测试包

有测试代码,直接上手开始测试

Recieved FAULT
org.jinterop.dcom.common.JIException: Access is denied, please check whether the [domain-username-password] are correct. Also, if not already done please check the GETTING STARTED and FAQ sections in readme.htm. They provide information on how to correctly configure the Windows machine for DCOM access, so as to avoid such exceptions.  [0x00000005]
    at org.jinterop.dcom.core.JIComServer.init(JIComServer.java:661)
    at org.jinterop.dcom.core.JIComServer.initialise(JIComServer.java:496)
    at org.jinterop.dcom.core.JIComServer.<init>(JIComServer.java:460)
    at org.jinterop.dcom.core.JIComServer.<init>(JIComServer.java:391)

本地测试的时候始终报这个异常,

网上梭巡一番说DCOM需要配置

参考

DCOM for Windows 7, 10, & Server 2008R2 (softwaretoolbox.com)

OPC和DCOM配置 - ioufev - 博客园 (cnblogs.com)

这些都做了之后 ,测试时可以查看windows日志,显示身份审核成功,可以就是报上面那个错误

各种两天尝试下选择了放弃,换个赛道看看

最后使用JeasyOpc

这是开源的,网上下载

JEasyOPC download | SourceForge.net

项目在这里面用编译器打开

这个项目需要用32位的jdk 运行,我是在这边下载的

64位和32位JDK 1.8下载和环境变量配置_jdk 1.8 32位_liu0621的博客-CSDN博客z

下载好了之后直接进行jdk替换重命名   使用java -version  看有无成功

如果还是64bit  ,需要用   where java  看有几个javapath   如果多个,需要修改别的,把jdk32位bin中的java.exe 覆盖掉其他的,或者直接把别的删掉或重命名如java1.exe

打成jar

先创建一个target 目录

 编译命令  

javac -cp "lib/*" -d target src\java\javafish\clients\opc\*.java src\java\javafish\clients\opc\asynch\*.java src\java\javafish\clients\opc\browser\*.java src\java\javafish\clients\opc\component\*.java src\java\javafish\clients\opc\exception\*.java src\java\javafish\clients\opc\lang\*.java src\java\javafish\clients\opc\property\*.java src\java\javafish\clients\opc\variant\*.java

打包需要在创建   META-INF/MANIFEST.MF    可以使空白

jar -cvfm jeasy2.3.2.jar META-INF\MANIFEST.MF -C target .

然后引入自己的项目中

<dependency>
    <groupId>jeasyopc.jar</groupId>
    <artifactId>jeasyopc.jar</artifactId>
    <version>1.0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/src/main/resources/lib/jeasy2.3.2.jar</systemPath>
</dependency>

开始测试  测试代码在下面

如果出现 jeasyopc Translate doesn't exist. System terminated. 的问题 需要改源码

他是获取资源文件失败

这是我的放的位置

文件在前面下载的里面都有

因为位置固定所以源码获取文件直接写死

  static {

    Properties props = new Properties();
    ClassLoader cl = PropertyLoader.class.getClassLoader();
    try {
      props.load(cl.getResourceAsStream("javafish/clients/opc/lang/Translate.properties"));
    } catch (IOException e) {
      e.printStackTrace();
    }
    // load properties
//    props = PropertyLoader.loadProperties(Translate.class.getName());
    // set current locale
    String lang = props.getProperty("locale");
    if (lang == null || lang.trim().equals("")) {
      locale = Locale.getDefault();
    } else {
      locale = new Locale(props.getProperty("locale"));
    }
    // prepare lang resources
    resourceBundle = ResourceBundle.getBundle(props.getProperty("resource"), locale);
  }

如果还是报错可以右键资源文件获取路径直接粘过去

中途可能还会遇见别的错误

java.lang.UnsatisfiedLinkError: no JCustomOpc in java.library.path

这个是对应的dll文件没找到  ,文件在源码资源中也有,本来是放在lib 下的   再加上JCustomOpc.properties的配置去查找

但是在运行的时候死活找不到

直接放在windows系统中,这两个都放一下,然后 改为 library.path =JCustomOpc

连接测试

@PostMapping(test3)
	@Override
	public void myCont()  {
		log.info("JOPC 开始初始化");
		JOpc.coInitialize();
		log.info("建立JOPC服务对象");
		JOpc jopc = new JOpc("localhost", "TsRun.OpcServer", "JOPC");
		try {
			jopc.connect();
		} catch (ConnectivityException e) {
			e.printStackTrace();
		}
		System.out.println("OJBC连接成功");
		OpcGroup[] groupsAsArray = jopc.getGroupsAsArray();
		System.out.println(groupsAsArray.length);
		for (OpcGroup opcGroup:groupsAsArray){
			System.out.println("opcgropName"+opcGroup.getGroupName());
			ArrayList<OpcItem> items = opcGroup.getItems();
			for (OpcItem opcItem:items) {
				System.out.println("itemName"+opcItem.getItemName());
				System.out.println("itemValue"+opcItem.getValue());
				Variant varin = new Variant(false);
				opcItem.setValue(varin);
				try {
					jopc.synchWriteItem(opcGroup,opcItem);
				} catch (SynchWriteException e) {
					e.printStackTrace();
				}
				break;
			}
		}

	}

呜呜呜,连接终于成功了,好了连接成功证明已经完成了80%

再继续往下看到输出的group length为0,我连续用连接工具加了好几个都是零,这不由得沉思,难道用的不是公共的,每个连接只属于自己的? 这完全有可能,每个连接都维护着自己组与item

假如是这样我们就需要一直维护并保存着一个连接。并且新建分组和添加item 还需要与你的业务应用层面相互吻合接口进行控制和获取数据。

好了,话不多说 上代码浅浅测试一下

public void myCont()  {
		log.info("JOPC 开始初始化");
		JOpc.coInitialize();
		log.info("建立JOPC服务对象");
		JOpc jopc = new JOpc("localhost", "TsRun.OpcServer", "JOPC");
		try {
			jopc.connect();
		} catch (ConnectivityException e) {
			e.printStackTrace();
		}
		System.out.println("OJBC连接成功");
		OpcGroup opcGroup1 = new OpcGroup("1",true,10000,0.0F);
		OpcItem groupItem = new OpcItem("DDC22.1#累计运行时间", true, "DDC22.1#累计运行时间");
		opcGroup1.addItem(groupItem);
		jopc.addGroup(opcGroup1);
		try {
			log.info("开始注册分组");
			jopc.registerGroups();
			log.info("注册分组成功");
		} catch (UnableAddGroupException e) {
			e.printStackTrace();
		} catch (UnableAddItemException e) {
			e.printStackTrace();
		}
		try {
			log.info("读取数据");
			System.out.println("读取数据成功=="+jopc.synchReadItem(opcGroup1, groupItem).getValue());
		} catch (SynchReadException e) {
			e.printStackTrace();
		}
		OpcGroup[] groupsAsArray = jopc.getGroupsAsArray();
		System.out.println(groupsAsArray.length);
		for (OpcGroup opcGroup:groupsAsArray){
			System.out.println("opcgropName"+opcGroup.getGroupName());
			ArrayList<OpcItem> items = opcGroup.getItems();
			for (OpcItem opcItem:items) {
				System.out.println("itemName"+opcItem.getItemName());
				System.out.println("itemValue"+opcItem.getValue());
			}
		}


	}

 我就知道不会这么顺利

再继续看吧,无法注册到组中

jeasyopc 使用 - jsspring的个人空间 - OSCHINA - 中文开源技术交流社区

找了篇文章看了一下好像我的顺序有问题,改一改

把item 去掉 组注册成功了,那就是item 添加有问题

这个问题不好找,因为调用的是dll库  网上找了下资源,发现有获取所有分支和item,尝试一下

	@Override
	public void myCont2() {
		JOpcBrowser jbrowser = new JOpcBrowser("localhost", "TsRun.OpcServer", "JOPC");

		try {
			jbrowser.connect();
		} catch (ConnectivityException e) {
			e.printStackTrace();
		}
		try {
			String[] branches = jbrowser.getOpcBranch("");
			System.out.println("branches=="+Arrays.toString(branches));
			for (String s:branches) {
				String[] opcItems = jbrowser.getOpcItems(s, true);
				for (String string:opcItems) {
					System.out.println("item=="+string);
				}

			}
		} catch (UnableBrowseBranchException e) {
			e.printStackTrace();
		} catch (UnableIBrowseException e) {
			e.printStackTrace();
		} catch (UnableBrowseLeafException e) {
			e.printStackTrace();
		} catch (UnableAddItemException e) {
			e.printStackTrace();
		} catch (UnableAddGroupException e) {
			e.printStackTrace();
		}
	}

有结果没报错,万幸

基本就是编码问题了这个搞定应该就好了吧

看了下那个方法的源码

格式就是 fullName;   itemType  ; itemName;   值

未完。。。。。。。有大佬了解这个乱码问题的求多多指教下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值