浏览代码

完善iec和opc

hfxc226 2 年之前
父节点
当前提交
55c716bbfd

+ 154 - 0
platform-opc/pom.xml

@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>spring-boot-sb-base</artifactId>
+        <groupId>com.platform</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>platform-opc</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>8.0.15</version>
+        </dependency>
+        <dependency>
+            <groupId>com.platform</groupId>
+            <artifactId>platform-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+            <version>2.1.6.RELEASE</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!--jackson模块-->
+        <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-modules-java8</artifactId>
+            <version>${jackson.modules}</version>
+            <type>pom</type>
+            <scope>import</scope>
+        </dependency>
+        <!--netty-->
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+            <version>4.1.42.Final</version>
+        </dependency>
+        <!--测试依赖-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>net.logstash.logback</groupId>
+            <artifactId>logstash-logback-encoder</artifactId>
+            <version>4.9</version>
+        </dependency>
+
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>1.2.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+
+        <!--utgard -->
+        <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>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>1.3.0-alpha4</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.3.0-alpha4</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <finalName>spring-boot-sb-base-opc</finalName>
+
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>

+ 35 - 0
platform-opc/src/main/java/com/platform/opc/OpcApplication.java

@@ -0,0 +1,35 @@
+package com.platform.opc;
+
+import com.platform.opc.util.OpcUAClientUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.core.annotation.Order;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import java.util.TimeZone;
+
+/**
+ * @Description
+ * @Author chenli
+ * @Date 2019/7/22
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@SpringBootApplication
+@EnableScheduling
+@Order(1)
+@Slf4j
+public class OpcApplication implements CommandLineRunner {
+
+    public static void main(String[] args) {
+        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
+        SpringApplication.run(OpcApplication.class, args);
+    }
+
+    @Override
+    public void run(String... args) throws Exception {
+        OpcUAClientUtil.run();
+        Thread.sleep(1000000);
+    }
+}

+ 96 - 0
platform-opc/src/main/java/com/platform/opc/util/OpcUAClientUtil.java

@@ -0,0 +1,96 @@
+package com.platform.opc.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.openscada.opc.lib.common.ConnectionInformation;
+
+import org.jinterop.dcom.common.JIException;
+import org.jinterop.dcom.core.JIString;
+import org.jinterop.dcom.core.JIVariant;
+import org.openscada.opc.lib.common.ConnectionInformation;
+import org.openscada.opc.lib.da.AccessBase;
+import org.openscada.opc.lib.da.DataCallback;
+import org.openscada.opc.lib.da.Item;
+import org.openscada.opc.lib.da.ItemState;
+import org.openscada.opc.lib.da.Server;
+import org.openscada.opc.lib.da.SyncAccess;
+
+import java.util.concurrent.Executors;
+
+@Slf4j
+public class OpcUAClientUtil {
+
+    public static void run() throws Exception {
+        // 连接信息
+        final ConnectionInformation ci = new ConnectionInformation();
+        ci.setHost("192.168.108.108");         // 电脑IP
+        ci.setDomain("");                  // 域,为空就行
+        ci.setUser("OPCUser");             // 电脑上自己建好的用户名
+        ci.setPassword("123456");          // 用户名的密码
+
+        // 使用MatrikonOPC Server的配置
+        // ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305"); // MatrikonOPC的注册表ID,可以在“组件服务”里看到
+        // final String itemId = "u.u";    // 项的名字按实际
+
+        // 使用KEPServer的配置
+        ci.setClsid("7BC0CC8E-482C-47CA-ABDC-0FE7F9C6E729"); // KEPServer的注册表ID,可以在“组件服务”里看到
+        final String itemId = "u.u.u";    // 项的名字按实际,没有实际PLC,用的模拟器:simulator
+        // final String itemId = "通道 1.设备 1.标记 1";
+
+        // 启动服务
+        final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());
+
+        try {
+            // 连接到服务
+            server.connect();
+            // add sync access, poll every 500 ms,启动一个同步的access用来读取地址上的值,线程池每500ms读值一次
+            // 这个是用来循环读值的,只读一次值不用这样
+            final AccessBase access = new SyncAccess(server, 500);
+            // 这是个回调函数,就是读到值后执行这个打印,是用匿名类写的,当然也可以写到外面去
+            access.addItem(itemId, new DataCallback() {
+                @Override
+                public void changed(Item item, ItemState itemState) {
+                    int type = 0;
+                    try {
+                        type = itemState.getValue().getType(); // 类型实际是数字,用常量定义的
+                    } catch (JIException e) {
+                        e.printStackTrace();
+                    }
+                    System.out.println("监控项的数据类型是:-----" + type);
+                    System.out.println("监控项的时间戳是:-----" + itemState.getTimestamp().getTime());
+                    System.out.println("监控项的详细信息是:-----" + itemState);
+
+                    // 如果读到是short类型的值
+                    if (type == JIVariant.VT_I2) {
+                        short n = 0;
+                        try {
+                            n = itemState.getValue().getObjectAsShort();
+                        } catch (JIException e) {
+                            e.printStackTrace();
+                        }
+                        System.out.println("-----short类型值: " + n);
+                    }
+
+                    // 如果读到是字符串类型的值
+                    if(type == JIVariant.VT_BSTR) {  // 字符串的类型是8
+                        JIString value = null;
+                        try {
+                            value = itemState.getValue().getObjectAsString();
+                        } catch (JIException e) {
+                            e.printStackTrace();
+                        } // 按字符串读取
+                        String str = value.getString(); // 得到字符串
+                        System.out.println("-----String类型值: " + str);
+                    }
+                }
+            });
+            // start reading,开始读值
+            access.bind();
+            // wait a little bit,有个10秒延时
+            Thread.sleep(10 * 1000);
+            // stop reading,停止读取
+            access.unbind();
+        } catch (final JIException e) {
+            System.out.println(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));
+        }
+    }
+}

+ 6 - 0
platform-opc/src/main/resources/application-dev.yml

@@ -0,0 +1,6 @@
+spring:
+  application:
+    name: platform-opc
+platform:
+  slf4j:
+    data: D://logs

+ 6 - 0
platform-opc/src/main/resources/application-prod.yml

@@ -0,0 +1,6 @@
+spring:
+  application:
+    name: platform-opc
+platform:
+  slf4j:
+    data: D://xajg

+ 6 - 0
platform-opc/src/main/resources/application-test.yml

@@ -0,0 +1,6 @@
+spring:
+  application:
+    name: platform-opc
+platform:
+  slf4j:
+    data: D://xajg

+ 5 - 0
platform-opc/src/main/resources/application.yml

@@ -0,0 +1,5 @@
+spring:
+  profiles:
+    active: daoDev,serviceDev,dev
+  main:
+    web-application-type: none

+ 123 - 0
platform-opc/src/main/resources/logback-spring.xml

@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration debug="false" scan="false">
+    <springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue=""/>
+    <springProperty scop="context" name="platform.slf4j.data" source="platform.slf4j.data" defaultValue="D://home//project"/>
+    <springProperty scop="context" name="logstash.ip_port" source="logstash.ip_port" defaultValue=""/>
+    <property name="log.path" value="${platform.slf4j.data}/logs/${spring.application.name}"/>
+    <!-- 彩色日志格式 -->
+    <property name="CONSOLE_LOG_PATTERN"
+              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
+    <!-- 彩色日志依赖的渲染类 -->
+    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
+    <conversionRule conversionWord="wex"
+                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
+    <conversionRule conversionWord="wEx"
+                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
+    <!-- Console log output -->
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="error_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/error.log</file>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>ERROR</level>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 -->
+            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
+            <!--日志文件保留天数 -->
+            <maxFileSize>500MB</maxFileSize>
+            <!--日志文件保留天数 -->
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n
+            </pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <!-- Log file debug output -->
+    <appender name="info_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/info.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
+            <maxFileSize>500MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n
+            </pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <appender name="async_info_file" class="net.logstash.logback.appender.LoggingEventAsyncDisruptorAppender">
+        <appender-ref ref="info_file"/>
+    </appender>
+
+    <!--<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>${logstash.ip_port}</destination>
+        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
+        <queueSize>1048576</queueSize>
+        <keepAliveDuration>5 minutes</keepAliveDuration>
+        &lt;!&ndash;<customFields>{"application-name":"data-repo-interface"}</customFields>&ndash;&gt;
+        &lt;!&ndash;<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+            <evaluator> <!– 默认为 ch.qos.logback.classic.boolex.JaninoEventEvaluator –>
+                <expression>return message.contains("billing");</expression>
+            </evaluator>
+            <OnMatch>ACCEPT</OnMatch>
+            <OnMismatch>DENY</OnMismatch>
+        </filter>&ndash;&gt;
+    </appender>-->
+    <!-- logstash处理日志 -->
+    <!--<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>${logstash.ip_port}</destination>
+        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
+    </appender>
+
+    <logger name="elk_logger" level="INFO" additivity="false">
+        <appender-ref ref="LOGSTASH"/>
+    </logger>-->
+
+    <!-- 开发环境 -->
+    <springProfile name="dev">
+        <logger name="com.platform" level="DEBUG"/>
+        <logger name="com.platform.dao.mapper.upms.SysLogMapper" level="ERROR"/>
+
+        <root level="INFO">
+            <appender-ref ref="stdout"/>
+            <appender-ref ref="info_file"/>
+            <appender-ref ref="error_file"/>
+        </root>
+    </springProfile>
+
+    <!-- 测试环境 -->
+    <springProfile name="test">
+        <logger name="com.platform" level="DEBUG"/>
+        <logger name="com.platform.dao.mapper.upms.SysLogMapper" level="ERROR"/>
+        <root level="INFO">
+            <appender-ref ref="stdout"/>
+            <appender-ref ref="info_file"/>
+            <appender-ref ref="error_file"/>
+        </root>
+    </springProfile>
+
+    <!-- 生产环境 -->
+    <springProfile name="prod">
+        <logger name="com.platform" level="DEBUG"/>
+        <logger name="com.platform.dao.mapper.upms.SysLogMapper" level="ERROR"/>
+        <root level="INFO">
+            <appender-ref ref="async_info_file"/>
+            <appender-ref ref="error_file"/>
+        </root>
+    </springProfile>
+</configuration>

+ 0 - 18
platform-service/pom.xml

@@ -85,24 +85,6 @@
             <artifactId>spring-boot-starter-mail</artifactId>
             <artifactId>spring-boot-starter-mail</artifactId>
         </dependency>
         </dependency>
 
 
-        <!--start milo-->
-        <dependency>
-            <groupId>org.eclipse.milo</groupId>
-            <artifactId>sdk-client</artifactId>
-            <version>0.6.3</version>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcpkix-jdk15on</artifactId>
-            <version>1.57</version>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.milo</groupId>
-            <artifactId>sdk-server</artifactId>
-            <version>0.6.3</version>
-        </dependency>
-        <!--end milo-->
-
     </dependencies>
     </dependencies>
 
 
     <build>
     <build>

+ 0 - 44
platform-service/src/main/java/com/platform/service/opc/OpcUAClientService.java

@@ -1,44 +0,0 @@
-package com.platform.service.opc;
-import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
-import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
-import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
-import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
-import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
-import java.util.concurrent.CompletableFuture;
-import java.util.function.Predicate;
-/**
- * @author yaohj
- * @date 2020/7/30
- * OPC UA协议对象接口
- */
-public interface OpcUAClientService {
-    /**
-     * OPC UA服务器地址和接口
-     */
-    default String getEndpointUrl() {
-        return "opc.tcp://127.0.0.1:49320";
-    }
-    /**
-     * 过滤返回的server endpoint
-     */
-    default Predicate<EndpointDescription> endpointFilter() {
-        return e -> true;
-    }
-    /**
-     * 连接服务器的安全策略
-     * None、Basic128Rsa15、Basic256、Basic256Sha256、Aes128_Sha256_RsaOaep、Aes256_Sha256_RsaPss
-     */
-    default SecurityPolicy getSecurityPolicy() {
-        return SecurityPolicy.None;
-    }
-    /**
-     * 提供身份验证
-     */
-    default IdentityProvider getIdentityProvider() {
-        return new AnonymousProvider();
-    }
-    /**
-     * 读取
-     */
-    void readNodeList(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception;
-}

+ 0 - 98
platform-service/src/main/java/com/platform/service/opc/impl/KeyStoreLoader.java

@@ -1,98 +0,0 @@
-package com.platform.service.opc.impl;
-
-import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil;
-import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
-import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.*;
-import java.security.cert.X509Certificate;
-import java.util.regex.Pattern;
-
-class KeyStoreLoader {
-    private final Logger logger = LoggerFactory.getLogger(getClass());
-    private static final Pattern IP_ADDR_PATTERN = Pattern.compile(
-            "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
-    // 证书别名
-    private static final String CLIENT_ALIAS = "client-ai";
-    // 获取私钥的密码
-    private static final char[] PASSWORD = "password".toCharArray();
-    // 证书对象
-    private X509Certificate clientCertificate;
-    // 密钥对对象
-    private KeyPair clientKeyPair;
-
-    KeyStoreLoader load(Path baseDir) throws Exception {
-        // 创建一个使用`PKCS12`加密标准的KeyStore。KeyStore在后面将作为读取和生成证书的对象。
-        KeyStore keyStore = KeyStore.getInstance("PKCS12");
-        // PKCS12的加密标准的文件后缀是.pfx,其中包含了公钥和私钥。
-        // 而其他如.der等的格式只包含公钥,私钥在另外的文件中。
-        Path serverKeyStore = baseDir.resolve("example-client.pfx");
-        logger.info("Loading KeyStore at {}", serverKeyStore);
-        // 如果文件不存在则创建.pfx证书文件。
-        if (!Files.exists(serverKeyStore)) {
-            keyStore.load(null, PASSWORD);
-            // 用2048位的RAS算法。`SelfSignedCertificateGenerator`为Milo库的对象。
-            KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
-            // `SelfSignedCertificateBuilder`也是Milo库的对象,用来生成证书。
-            // 中间所设置的证书属性可以自行修改。
-            SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
-                    .setCommonName("Eclipse Milo Example Client")
-                    .setOrganization("digitalpetri")
-                    .setOrganizationalUnit("dev")
-                    .setLocalityName("Folsom")
-                    .setStateName("CA")
-                    .setCountryCode("US")
-                    .setApplicationUri("urn:eclipse:milo:examples:client")
-                    .addDnsName("localhost")
-                    .addIpAddress("127.0.0.1");
-            // Get as many hostnames and IP addresses as we can listed in the certificate.
-            for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
-                if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
-                    builder.addIpAddress(hostname);
-                } else {
-                    builder.addDnsName(hostname);
-                }
-            }
-            // 创建证书
-            X509Certificate certificate = builder.build();
-            // 设置对应私钥的别名,密码,证书链
-            keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{certificate});
-            try (OutputStream out = Files.newOutputStream(serverKeyStore)) {
-                // 保存证书到输出流
-                keyStore.store(out, PASSWORD);
-            }
-        } else {
-            try (InputStream in = Files.newInputStream(serverKeyStore)) {
-                // 如果文件存在则读取
-                keyStore.load(in, PASSWORD);
-            }
-        }
-        // 用密码获取对应别名的私钥。
-        Key serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
-        if (serverPrivateKey instanceof PrivateKey) {
-            // 获取对应别名的证书对象。
-            clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
-            // 获取公钥
-            PublicKey serverPublicKey = clientCertificate.getPublicKey();
-            // 创建Keypair对象。
-            clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey);
-        }
-        return this;
-    }
-
-    // 返回证书
-    X509Certificate getClientCertificate() {
-        return clientCertificate;
-    }
-
-    // 返回密钥对
-    KeyPair getClientKeyPair() {
-        return clientKeyPair;
-    }
-}

+ 0 - 48
platform-service/src/main/java/com/platform/service/opc/impl/OpcUAClientFactory.java

@@ -1,48 +0,0 @@
-package com.platform.service.opc.impl;
-
-import com.platform.service.opc.OpcUAClientService;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
-import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
-import org.eclipse.milo.opcua.stack.core.Stack;
-import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
-import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
-import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-@Slf4j
-public class OpcUAClientFactory {
-
-    /**
-     * 创建OPC UA的服务连接对象
-     */
-    public static OpcUaClient createClient() throws Exception {
-        //opc ua服务端地址
-        String endPointUrl = "opc.tcp://192.168.0.169:49320";
-        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
-        Files.createDirectories(securityTempDir);
-        if (!Files.exists(securityTempDir)) {
-            throw new Exception("unable to create security dir: " + securityTempDir);
-        }
-        return OpcUaClient.create(endPointUrl,
-                endpoints ->
-                        endpoints.stream()
-                                .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
-                                .findFirst(),
-                configBuilder ->
-                        configBuilder
-                                .setApplicationName(LocalizedText.english("eclipse milo opc-ua client"))
-                                .setApplicationUri("urn:eclipse:milo:examples:client")
-                                //访问方式
-                                .setIdentityProvider(new AnonymousProvider())
-                                .setRequestTimeout(UInteger.valueOf(5000))
-                                .build()
-        );
-    }
-}

+ 0 - 196
platform-service/src/main/java/com/platform/service/opc/impl/OpcUAClientServiceImpl.java

@@ -1,196 +0,0 @@
-package com.platform.service.opc.impl;
-
-import com.google.common.collect.ImmutableList;
-import com.platform.service.opc.OpcUAClientService;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
-import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription;
-import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscriptionManager;
-import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
-import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedSubscription;
-import org.eclipse.milo.opcua.stack.core.AttributeId;
-import org.eclipse.milo.opcua.stack.core.UaException;
-import org.eclipse.milo.opcua.stack.core.types.builtin.*;
-import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
-import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode;
-import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
-import org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemCreateRequest;
-import org.eclipse.milo.opcua.stack.core.types.structured.MonitoringParameters;
-import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;
-import org.springframework.stereotype.Service;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicInteger;
-
-@Service("opcUAClientService")
-@Slf4j
-public class OpcUAClientServiceImpl implements OpcUAClientService {
-    private static AtomicInteger atomicInteger = new AtomicInteger(0);
-    /**
-     * 读取数据支持单个,多个节点数据
-     */
-    @Override
-    public void readNodeList(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception {
-        // 同步建立连接
-        client.connect().get();
-        // 异步读取数据
-        NodeId nodeId_Tag1 = new NodeId(2, "Channel1.Device1.Tag1");
-        NodeId nodeId_Tag2 = new NodeId(2, "Channel1.Device1.Tag2");
-        List<NodeId> nodeIds = ImmutableList.of(nodeId_Tag1, nodeId_Tag2);
-        CompletableFuture<List<DataValue>>  listCompletableFuture = client.readValues(0.0, TimestampsToReturn.Both, nodeIds);
-        listCompletableFuture.thenAccept(values -> {
-            DataValue dataValue1 = values.get(0);
-            DataValue dataValue2 = values.get(1);
-            System.out.println("#########Tag1=" + dataValue1.getValue().getValue());
-            System.out.println("#########Tag2=" + dataValue2.getValue().getValue());
-            future.complete(client);
-        });
-    }
-
-    /**
-     * 写入单个节点数据
-     *
-     * @param client
-     * @throws Exception
-     */
-    private static void writeNodeValue(OpcUaClient client) throws Exception {
-        //节点
-        NodeId nodeId = new NodeId(2, "TD-01.SB-01.AG-01");
-        short i = 3;
-        //创建数据对象,此处的数据对象一定要定义类型,不然会出现类型错误,导致无法写入
-        DataValue nowValue = new DataValue(new Variant(i), null, null);
-        //写入节点数据
-        StatusCode statusCode = client.writeValue(nodeId, nowValue).join();
-        System.out.println("结果:" + statusCode.isGood());
-    }
-
-    /**
-     * 订阅(单个)
-     *
-     * @param client
-     * @throws Exception
-     */
-    private static void subscribe(OpcUaClient client) throws Exception {
-        //创建发布间隔1000ms的订阅对象
-        client.getSubscriptionManager()
-                .createSubscription(1000.0)
-                .thenAccept(t -> {
-                    //节点
-                    NodeId nodeId = new NodeId(2, "TD-01.SB-01.AG-01");
-                    ReadValueId readValueId = new ReadValueId(nodeId, AttributeId.Value.uid(), null, null);
-                    //创建监控的参数
-                    MonitoringParameters parameters = new MonitoringParameters(UInteger.valueOf(atomicInteger.getAndIncrement()), 1000.0, null, UInteger.valueOf(10), true);
-                    //创建监控项请求
-                    //该请求最后用于创建订阅。
-                    MonitoredItemCreateRequest request = new MonitoredItemCreateRequest(readValueId, MonitoringMode.Reporting, parameters);
-                    List<MonitoredItemCreateRequest> requests = new ArrayList<>();
-                    requests.add(request);
-                    //创建监控项,并且注册变量值改变时候的回调函数。
-                    t.createMonitoredItems(
-                            TimestampsToReturn.Both,
-                            requests,
-                            (item, id) -> item.setValueConsumer((it, val) -> {
-                                System.out.println("nodeid :" + it.getReadValueId().getNodeId());
-                                System.out.println("value :" + val.getValue().getValue());
-                            })
-                    );
-                }).get();
-
-        //持续订阅
-        Thread.sleep(Long.MAX_VALUE);
-    }
-
-    /**
-     * 批量订阅
-     *
-     * @param client
-     * @throws Exception
-     */
-    private static void managedSubscriptionEvent(OpcUaClient client) throws Exception {
-        final CountDownLatch eventLatch = new CountDownLatch(1);
-        //添加订阅监听器,用于处理断线重连后的订阅问题
-        client.getSubscriptionManager().addSubscriptionListener(new CustomSubscriptionListener(client));
-        //处理订阅业务
-        handlerNode(client);
-        //持续监听
-        eventLatch.await();
-    }
-
-    /**
-     * 处理订阅业务
-     *
-     * @param client OPC UA客户端
-     */
-    private static void handlerNode(OpcUaClient client) {
-        try {
-            //创建订阅
-            ManagedSubscription subscription = ManagedSubscription.create(client);
-
-            //你所需要订阅的key
-            List<String> key = new ArrayList<>();
-            key.add("TD-01.SB-01.AG-01");
-            key.add("TD-01.SB-01.AG-02");
-
-            List<NodeId> nodeIdList = new ArrayList<>();
-            for (String s : key) {
-                nodeIdList.add(new NodeId(2, s));
-            }
-
-            //监听
-            List<ManagedDataItem> dataItemList = subscription.createDataItems(nodeIdList);
-            for (ManagedDataItem managedDataItem : dataItemList) {
-                managedDataItem.addDataValueListener((t) -> {
-                    System.out.println(managedDataItem.getNodeId().getIdentifier().toString() + ":" + t.getValue().getValue().toString());
-                });
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * 自定义订阅监听
-     */
-    private static class CustomSubscriptionListener implements UaSubscriptionManager.SubscriptionListener {
-
-        private OpcUaClient client;
-
-        CustomSubscriptionListener(OpcUaClient client) {
-            this.client = client;
-        }
-
-        public void onKeepAlive(UaSubscription subscription, DateTime publishTime) {
-            log.debug("onKeepAlive");
-        }
-
-        public void onStatusChanged(UaSubscription subscription, StatusCode status) {
-            log.debug("onStatusChanged");
-        }
-
-        public void onPublishFailure(UaException exception) {
-            log.debug("onPublishFailure");
-        }
-
-        public void onNotificationDataLost(UaSubscription subscription) {
-            log.debug("onNotificationDataLost");
-        }
-
-        /**
-         * 重连时 尝试恢复之前的订阅失败时 会调用此方法
-         * @param uaSubscription 订阅
-         * @param statusCode 状态
-         */
-        public void onSubscriptionTransferFailed(UaSubscription uaSubscription, StatusCode statusCode) {
-            log.debug("恢复订阅失败 需要重新订阅");
-            //在回调方法中重新订阅
-            handlerNode(client);
-        }
-    }
-
-
-}
-

+ 2 - 2
platform-service/src/main/java/com/platform/service/sb/impl/SbInfoServiceImpl.java

@@ -1396,9 +1396,9 @@ public class SbInfoServiceImpl extends BaseServiceImpl<SbInfoMapper, SbInfo, SbI
         }
         }
         PageHelper.startPage(pageNum, pageSize);
         PageHelper.startPage(pageNum, pageSize);
         List<SbInfoVO> sbList = mapper.selectVOList(model);
         List<SbInfoVO> sbList = mapper.selectVOList(model);
-        for (SbInfoVO vo : sbList) {
+       /* for (SbInfoVO vo : sbList) {
             vo.setChildren(new ArrayList<>());
             vo.setChildren(new ArrayList<>());
-        }
+        }*/
 
 
           /*if (SbInfoChildEnum.IS_PARENT.getValue().equals(model.getIsChild()) && !CollectionUtils.isEmpty(sbList)) {
           /*if (SbInfoChildEnum.IS_PARENT.getValue().equals(model.getIsChild()) && !CollectionUtils.isEmpty(sbList)) {
             for (SbInfoVO vo : sbList) {
             for (SbInfoVO vo : sbList) {

+ 0 - 94
platform-service/src/main/java/handler/opc/KeyStoreLoader.java

@@ -1,94 +0,0 @@
-package handler.opc;
-
-import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil;
-import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
-import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.*;
-import java.security.cert.X509Certificate;
-import java.util.regex.Pattern;
-class KeyStoreLoader {
-    private final Logger logger = LoggerFactory.getLogger(getClass());
-    private static final Pattern IP_ADDR_PATTERN = Pattern.compile(
-            "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
-    // 证书别名
-    private static final String CLIENT_ALIAS = "client-ai";
-    // 获取私钥的密码
-    private static final char[] PASSWORD = "password".toCharArray();
-    // 证书对象
-    private X509Certificate clientCertificate;
-    // 密钥对对象
-    private KeyPair clientKeyPair;
-    KeyStoreLoader load(Path baseDir) throws Exception {
-        // 创建一个使用`PKCS12`加密标准的KeyStore。KeyStore在后面将作为读取和生成证书的对象。
-        KeyStore keyStore = KeyStore.getInstance("PKCS12");
-        // PKCS12的加密标准的文件后缀是.pfx,其中包含了公钥和私钥。
-        // 而其他如.der等的格式只包含公钥,私钥在另外的文件中。
-        Path serverKeyStore = baseDir.resolve("example-client.pfx");
-        logger.info("Loading KeyStore at {}", serverKeyStore);
-        // 如果文件不存在则创建.pfx证书文件。
-        if (!Files.exists(serverKeyStore)) {
-            keyStore.load(null, PASSWORD);
-            // 用2048位的RAS算法。`SelfSignedCertificateGenerator`为Milo库的对象。
-            KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
-            // `SelfSignedCertificateBuilder`也是Milo库的对象,用来生成证书。
-            // 中间所设置的证书属性可以自行修改。
-            SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
-                    .setCommonName("Eclipse Milo Example Client")
-                    .setOrganization("digitalpetri")
-                    .setOrganizationalUnit("dev")
-                    .setLocalityName("Folsom")
-                    .setStateName("CA")
-                    .setCountryCode("US")
-                    .setApplicationUri("urn:eclipse:milo:examples:client")
-                    .addDnsName("localhost")
-                    .addIpAddress("127.0.0.1");
-            // Get as many hostnames and IP addresses as we can listed in the certificate.
-            for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
-                if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
-                    builder.addIpAddress(hostname);
-                } else {
-                    builder.addDnsName(hostname);
-                }
-            }
-            // 创建证书
-            X509Certificate certificate = builder.build();
-            // 设置对应私钥的别名,密码,证书链
-            keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{certificate});
-            try (OutputStream out = Files.newOutputStream(serverKeyStore)) {
-                // 保存证书到输出流
-                keyStore.store(out, PASSWORD);
-            }
-        } else {
-            try (InputStream in = Files.newInputStream(serverKeyStore)) {
-                // 如果文件存在则读取
-                keyStore.load(in, PASSWORD);
-            }
-        }
-        // 用密码获取对应别名的私钥。
-        Key serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
-        if (serverPrivateKey instanceof PrivateKey) {
-            // 获取对应别名的证书对象。
-            clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
-            // 获取公钥
-            PublicKey serverPublicKey = clientCertificate.getPublicKey();
-            // 创建Keypair对象。
-            clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey);
-        }
-        return this;
-    }
-    // 返回证书
-    X509Certificate getClientCertificate() {
-        return clientCertificate;
-    }
-    // 返回密钥对
-    KeyPair getClientKeyPair() {
-        return clientKeyPair;
-    }
-}
-

+ 1 - 0
pom.xml

@@ -18,6 +18,7 @@
         <module>platform-office</module>
         <module>platform-office</module>
         <module>platform-activiti</module>
         <module>platform-activiti</module>
         <module>platform-iec</module>
         <module>platform-iec</module>
+        <module>platform-opc</module>
     </modules>
     </modules>
 
 
     <properties>
     <properties>