Java使用eclipse.milo连接KEPServerEx6服务器详细步骤(匿名访问)
目录
一、KEPServer的下载与安装
1.KEPServer的下载
2.KEPServer的安装
二、前期配置
1.KEPServer用户配置
2.OPCUA配置
三、KEPServer仿真添加
1.1添加Simulator通道
1.2添加Simulator设备
1.3添加Simulator标记
2.1添加OPC UA通道
2.2添加设备和标记
四、Java客户端编写
1.创建客户端方法
2.读取点位数据
3.创建客户端并读取数据
五、开始调试
六、结束
一、KEPServer的下载与安装
1.KEPServer的下载
有关KEPServer的下载可以参考该文章中的链接
KEPServer无时间限制版本
由于在官网下载KEPServerEx会有正版的时间限制,运行超出两个小时便无法连接,会提示“kepserver一个或多个功能有时间限制”。按照上述链接中的步骤操作后,重启电脑即可。
2.KEPServer的安装
KEPServer的安装网上有很多教程,此处便不再赘述。
在这一步安装时不建议更改路径
安装完毕后,在KEPServer6文件夹中运行server_admin.exe,右下角便会出现如下图标,代表成功运行:
二、前期配置
1.KEPServer用户配置
右键点击右下角的图标,弹出如下界面:
点击“设置”,选择用户管理器,点击Administrators然后新建用户,代表在该管理员组下新建用户
此处填写用户名和密码。用户名随意,密码需要是14位的字符串,并由大小写字母、特殊字符和数组组成。在这里放一个我测试用的现成的:adminopc:P@ssw0rd123123123
添加完毕后,点击确定。该账号后续需要使用。
2.OPCUA配置
在右键后的悬浮窗中点击“OPCUA 配置”,进入如下页面
最一开始是只有opc.tcp://HOME:49320这个URL的。点击添加。
如果你需要在本地测试,即KEPServer服务端与你的java客户端在同一台电脑上,则选择“仅限本地主机”。由于我的KEPServer服务器在另一台电脑上,故选择第二个。
在这里我选择安全策略为无。另外两种安全策略都勾上也是可以的,在此我仅测试匿名访问。
三、KEPServer仿真添加
在右键点击后的悬浮窗中,点击配置,进入如下页面
首先右键项目,选择属性,检查自己是否开启了匿名登录
1.1添加Simulator通道
我们可以右键“连接性”新建通道
也可以点击连接性,点击上方的该图标添加通道
我们首先新建一个Simulator类型的通道,用于后续的导入测试。选择通道类型为Simulator
名称可以随意取
接下来一直下一步就可以,直到建立通道完毕,点击完成。这便是我们新建的通道。
1.2添加Simulator设备
在上述添加通道完毕后,直接点击添加设备。设备名称命名为device(随意)
之后一直下一步即可,添加设备完毕。
1.3添加Simulator标记
接下来为该通道的该设备添加标记
标记的设置如下:
名称设置为tag1,地址我以网上的大部分例子为参考,设置为K0001。16位设备的内存配置被模拟为一块编号从0到9999的位置。字的寻址方式为相对于块开始的偏移。而K开头的代表常量,R开头的则代表寄存器。
添加第一个标记完毕后,我们可以右键设备,继续添加第二个标记,名称设置为tag2,地址设置为K0002
最后结果如下:
我们可以点击该图标,快速创建一个本地的客户端模拟器,来验证是否连接成功。
当Quality为良好时,则代表连接成功
2.1添加OPC UA通道
我们按照上述方式,继续添加第二个通道,该通道类型选择OPCUA Client
接下来的步骤是我们需要注意的。
①对于端点URL:如果你的客户端和服务端都在同一台电脑上,则使用opc.tcp://localhost:49320作为端点URL(也就是EndPoint URL)是没有问题的。但如果你的客户端和服务端在两台电脑上,则需要更换URL。
点击端点URL右边的三个点,进入UA服务器浏览器。选择如上的URL。192.168.1.10是你本机的ip。也可以通过ipconfig来查询你本机的ip地址。点击None-None,然后点击确定,外面的端点URL便会改变。所以其实在外面自己将localhost改为你本机的ip地址也是可以的。
②对于安全策略:该安全策略需要与你后续客户端中的安全策略相对应。所以在此我选择无安全策略。同时,该处的安全策略需要与二:OPCUA配置中,对应URL的安全策略配置一致。
然后继续下一步,进入该步骤。此处的用户名和密码需要与你在二中KEPServer用户配置中的用户名和密码一致。
2.2添加设备和标记
在刚刚新建的通道中添加设备,设备名称命名为deviceopc。继续下一步,直到该步选择导入项。
可能会报的错误:无法连接至UA服务器'opc.tcp://127.0.0.1:49320'进行浏览。
原因1:密码设置有误,格式不正确,需14位并带有大小写字母、特殊字符与数字。
原因2:在OPCUA配置中,URL为opc.tcp://127.0.0.1:49320的项目的安全策略配置与2.1中添加通道的安全策略配置不一样。由于我是匿名访问,在此处的安全策略配置选择无。
导入标记。找到我们这1.3中添加的两个标记,点击添加项即可。然后点击确定。
接下来继续下一步,此处的模拟可以选择开启,然后点击完成。
添加完毕后的标记如下,请牢记该地址:
我们打开Quick Client,检查连接状况:
四、Java客户端编写
该Java项目中我使用了SpringBoot框架,需在pom中引入milo库:
org.eclipse.milo sdk-client 0.6.10 org.bouncycastle bcpkix-jdk15on 1.69 org.eclipse.milo sdk-server 0.6.10
新建一个OpcUAClient类用于创建客户端和进行读写操作。
1.创建客户端方法
public static OpcUaClient createClientNewEndpoint(String endPointUrl, String username, String password) { System.out.println(endPointUrl); IdentityProvider identityProvider = new AnonymousProvider(); if (!StringUtils.isEmpty(username) || !StringUtils.isEmpty(password)) { identityProvider = new UsernameProvider(username, password); } try { Function selectEndpoint = endpoints -> { final Optional endpoint = endpoints .stream() //SecurityPolicy.Basic256 .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri())) .findFirst(); EndpointDescription newEndpoint = new EndpointDescription(endPointUrl, endpoint.get().getServer(), endpoint.get().getServerCertificate(), endpoint.get().getSecurityMode(), endpoint.get().getSecurityPolicyUri(), endpoint.get().getUserIdentityTokens(), endpoint.get().getTransportProfileUri(), endpoint.get().getSecurityLevel()); return Optional.of(newEndpoint); }; IdentityProvider finalIdentityProvider = identityProvider; OpcUaClient opcClient = OpcUaClient.create(endPointUrl, selectEndpoint, configBuilder -> configBuilder .setApplicationName(LocalizedText.english("plc")) .setApplicationUri("urn:eclipse:milo:examples:client") //访问方式 .setIdentityProvider(finalIdentityProvider) .setRequestTimeout(UInteger.valueOf(10000)) .build() ); opcClient.connect().get(); System.out.println("连接成功:success"); return opcClient; } catch (Exception e) { e.printStackTrace(); System.out.println("======== opc connection fail ========"); } return null; }
其中对于EndpointDescription对象进行了重新构造,否则可能会报如下的错误:UaException: status=Bad_Timeout, message=io.netty.channel.ConnectTimeoutException: connection timed out: /192.168.53.124:49320。具体参考文章如下:
Milo连接OPU UA报错UaException: status=Bad_Timeout, message=io.hg_netty.channel.ConnectTimeoutException:
由于我此处是匿名访问,所以过滤的安全策略为SecurityPolicu.None.getUri()。如果在KEPServer和添加通道时的安全策略有变,例如使用了Basic256Sha256等,则代码中也需要相应地变更过滤的方法。
2.读取点位数据
public static Object readValue(String identifier, OpcUaClient client) { System.out.println("点位数据:" + identifier); NodeId nodeId = new NodeId(NAME_SPACE, identifier); DataValue value = null; try { value = client.readValue(0.0, TimestampsToReturn.Both, nodeId).get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } if (Objects.nonNull(value) && Objects.nonNull(value.getValue()) && Objects.nonNull(value.getValue().getValue())) { return value.getValue().getValue(); } return null; }
其中NAME_SPACE为我设置的命名空间索引,为一个整数。在KEPServer中,命名空间索引一般为2,在我们上面创建的点位地址中也可以看到。
需要注意的是传入的identifier参数。我们前面了解到OPCUA的地址表示类型通常为ns=x;s=。其中ns代表namespace,表示节点所在的命名空间,命名空间是一种机制,用于区分不同来源的节点ID。在OPC UA中,每个服务器都可以定义多个命名空间;后者则为该节点的唯一标识。
我们通常使用NodeId nodeId = new NodeId建立一个新的NodeId对象,需要传入第一个参数为namespaceIndex,即为该节点所在的命名空间的索引 ;identifier表示节点的唯一标识符,这个标识符可以是一个数字、字符串或其他类型,具体取决于命名空间和服务器的配置。
我们可以查看源码,发现我们传入的identifer可以有多种类型:
identifier有以下几种可能的类型:
- 数值型(Numeric):当节点的标识符是一个整数时,identifier会是一个数值型,例如int或UInt32
- 字符串型(String):如果节点的标识符是一个字符串,identifier就会是String类型
- 全局唯一标识符(GUID):对于全局唯一的标识符, identifier为GUID类型
- 不透明型(Opaque):当节点的标识符是二进制数据时,identifier为字符串ByteString类型。
我们再额外加一个断开连接的方法:
public static void disconnect(OpcUaClient client) { try { client.disconnect().get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
3.创建客户端并读取数据
我直接写在了该项目的主程序中,代码如下,传入对应参数:
@SpringBootApplication public class Application { public static void main(String[] args) throws Exception { //运行主程序 SpringApplication.run(Application.class, args); String endPointUrl = "opc.tcp://192.168.1.10:49320"; OpcUaClient client = OpcUaUtil.createClientNewEndpoint(endPointUrl, "adminopc", "P@ssw0rd123123123"); //====== 1.读数据 ====== //=====只采集一次点位数据===== Object value = OpcUaUtil.readValue("opctest.device.tag1", client); System.out.println("当前点位值: " + value); OpcUaUtil.disconnect(client); Thread.sleep(Integer.MAX_VALUE); } }
在开始读取前,我们可以先修改一下这些标记的值。打开QuickClient,找到我们在2.2中添加的标记,点击更改值:
写入值后,点击Apply,再点击确定。修改完毕后,不要关闭QuickClient。
我们也可以右键该标记,查看它的属性:
修改完毕后,点击保存:
请注意,在开始调试前,请检查①你的两台电脑是否处于同一个局域网下②你服务端所在电脑的防火墙是否关闭。如果不想关闭防火墙,可只开启特定端口,操作如下:
进入防火墙高级设置:
选择入站规则:
新建规则:
选择端口设置,并添加你想要开放的端口:
添加完毕后,可在客户端电脑的终端使用telnet命令来验证该端口是否已经开启。若显示connected即表示端口开启成功。
五、开始调试
启动主程序,控制台成功信息如下:
在某些情况下,KEPServer的标记的值会持续变动(本人也不太清楚)有条件的也可以使用下面的服务端进行调试。该调试工具界面较为清晰,使用起来门槛更低更为简便。
同时在该服务端调试工具中,有一些初始化的点位会持续变动:
我们也可以在主程序中轮循获取点位值:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); //每隔1秒钟读取一次点位的值 executorService.scheduleAtFixedRate(() -> { Object value = OpcUaUtil.readValue(1003, client); System.out.println("当前点位值: " + value); }, 0, 1, TimeUnit.SECONDS); //设置15秒后关闭客户端连接和执行器 executorService.schedule(() -> { OpcUaUtil.disconnect(client); executorService.shutdown(); }, 15, TimeUnit.SECONDS);
六、结束
KEPServer匿名访问的全部程序如上。如有需要更改安全策略的可以对应同步更改进行测试。
在Java代码中只给出了基本的读单个点位数据的方法,如有需要其它多个读、写、多个写的方法的朋友,可以私信我要源码,我会直接给你的。