OPC UA JAVA开发笔记(四):数据写入
這一節我們來將如何實現Client端的數據持續寫入OPC UA。一下程序均在Spring Boot環境中,請先添加相應的依賴
我們獲取數據的REST API為:http://localhost:8080/coors/machine
為了不斷的從REST API中獲取JSON數據并解析,首先我們引入fastjson用來解析JSON數據
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.61</version> </dependency>我們需要寫入的JSON數據格式為(這里可以用GSON生成對應的類):
{ "X": 10.0, "Z": 10.0, "Y": 20.0 }新建一個Model用于存儲數據
@Data public class Coordinate {/*** X : 10.0* Z : 10.0* Y : 20.0*/private double X;private double Z;private double Y;public List<Variant> getVariants(){return Arrays.asList(new Variant(X), new Variant(Y), new Variant(Z));} }其中getVariants方法返回一個包含三個軸坐標值的List集合
接著我們新建一個類,類中添加如下方法,用于將數據寫入:
public OpcUaOperation{ public void writeNodeValues(List<NodeId> nodeIds, List<Variant> variants) {try {//連接到唯一運行的client,可以根據自己的情況建立一個OpcUAClientOpcUaClient client = ClientGen.getOpcUaClient();//創建連接client.connect().get();List<DataValue> values =variants.stream().map(DataValue::valueOnly).collect(toList());List<StatusCode> statusCodes =client.writeValues(nodeIds, values).get();//如果寫入出錯則打印錯誤信息statusCodes.forEach(statusCode -> {if (statusCode.isBad()) log.error("The Writing is wrong");});} catch (Exception e) {log.error(e.getMessage());}} }為了不斷的從REST API中獲取數據,我們采用Spring Boot中的@Scheduled注解
這個注解會使被標記的方法每隔n毫秒執行一次 fixed表示固定的時間間隔
@Slf4j @Component @EnableScheduling //通過這個注解開啟Scheduled public class CNCCoorsCollecting {@AutowiredOpcUaOperation opcUaOperation;@AutowiredRestTemplate restTemplate;//必須是http://開頭的,不然restTemplate不能解析private static String cncUrl = "http://localhost:8080";@Scheduled(fixedDelay = 50)public void coorsCollecting() {try {String axis_data = cncUrl + "/coors/machine";ResponseEntity<String> responseEntity =restTemplate.exchange(axis_data, HttpMethod.GET, null, String.class);String json = responseEntity.getBody();//獲取到JSON對象所封裝的數據Coordinate coordinate = JSON.parseObject(json, Coordinate.class);opcUaOperation.writeNodeValues(KND.axises, coordinate.getVariants());} catch (Exception e) {log.error("Axises Data Collecting Wrong");}} }其中這一段特別說明一下
ResponseEntity<String> responseEntity =restTemplate.exchange(axis_data, HttpMethod.GET, null, String.class);String json = responseEntity.getBody();//獲取到JSON對象所封裝的數據Coordinate coordinate = JSON.parseObject(json, Coordinate.class);其中KND.axises的定義如下,是一個包含了三個軸的Identifier的List集合
public static String KND_AXIS_X = KND_AXIS + prefix + "X"; public static String KND_AXIS_Y = KND_AXIS + prefix + "Y"; public static String KND_AXIS_Z = KND_AXIS + prefix + "Z";//初始化軸集合 public static final List<NodeId> axises = Arrays.asList(new NodeId(CNC, KND_AXIS_X),new NodeId(CNC, KND_AXIS_Y),new NodeId(CNC, KND_AXIS_Z));接下來我們來改造原本的數據寫入程序,有閱讀過milo源碼的朋友們應該知道,作者Kevin是一個函數式編程的忠實愛好者,他的許多的類都是基于Java 8的各種函數式以及多線程包編寫的,我們按照他的思路,對于原本的單線程寫入程序進行改造。
CompletableFuture.supplyAsync(() ->restTemplate.exchange(axis_data, HttpMethod.GET, null, String.class)).thenApply(HttpEntity::getBody).thenApply(json -> JSON.parseObject(json, Coordinate.class)).thenAccept(coordinate -> opcUaOperation.writeNodeValues(KND.axises, coordinate.getVariants())).get();雖然整體寫入可以應用多線程的思想,但是整個執行流程有著明確的先后順序,所以用thenApply方法將前后的結果依次連接。
thenApply可以將上一個CompletableFuture的結果作為輸入,并且將這一部分流水線單線程化。
.
注意這里的多線程主要是為了與客戶端的其他操作并行,在數據獲取這個流水線中它依然需要單線程執行 – 因為有嚴格的先后順序關系
這樣我們就實現了對于一個有著固定工業IP的設備的OPC UA數據寫入。
總結
以上是生活随笔為你收集整理的OPC UA JAVA开发笔记(四):数据写入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebRTC教程 - 使用SIPML5
- 下一篇: APUE书