Browse Source

完善iec和opc

hfxc226 2 years ago
parent
commit
3403cc93d5

+ 5 - 4
platform-iec/src/main/java/com/ydl/iec/iec104/core/ScheduledTaskPool.java

@@ -185,11 +185,11 @@ public class ScheduledTaskPool {
                     while (sendTestStatus) {
                         try {
                             // ctx.channel().writeAndFlush(BasicInstruction104.getGeneralCallRuleDetail104());
-                            Thread.sleep(1000 * 60 * 2);// 2分钟判断一次是否发送一次电度总召唤
+                            Thread.sleep(1000 * 60 * 2);// 2分钟判断一次是否发送一次电度总召唤,确保一个小时必须发一次
                             // 判断是否需要发送电度
                             if (isNeedSendDegree()) {
                                 if ( sendDegreeCallNum==0) {
-                                    LOGGER.info("电度召唤指令,并累加1" + sendDegreeCallNum++);
+                                    LOGGER.info("电度召唤指令,并累加" + sendDegreeCallNum++);
                                     ctx.channel().writeAndFlush(BasicInstruction104.getGeneralCallRuleDetail104Degree());
                                 }else{
                                     LOGGER.info("电度召唤指令该小时内,已经发送,开始清零" );
@@ -208,7 +208,8 @@ public class ScheduledTaskPool {
 
     /**
      * 判断是否需要发送电度召唤
-     * 每两分钟发起一次,判断时间是否在0,3分内,在此期间内,必然发起一次
+     * 每两分钟发起一次,判断时间是否在3,8分钟内,在此期间内,必然发起一次
+     * 不从0开始,因为0有时候哈光宇数据还没有
      *
      * @return
      */
@@ -216,7 +217,7 @@ public class ScheduledTaskPool {
         LocalTime time = LocalTime.now();
         int minute = time.getMinute();
         System.out.println(minute);
-        if (minute >= 0 && minute <= 3) {
+        if (minute >= 3 && minute <= 55) {
             return true;
         }
         return false;

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

@@ -38,7 +38,7 @@ public interface OpcUAClientService {
         return new AnonymousProvider();
     }
     /**
-     * 实际操作服务、由实现类重写实现
+     * 读取
      */
-    void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception;
+    void readNodeList(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception;
 }

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

@@ -0,0 +1,98 @@
+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;
+    }
+}

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

@@ -0,0 +1,48 @@
+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 - 41
platform-service/src/main/java/com/platform/service/opc/impl/OpcUAClientService.java

@@ -1,41 +0,0 @@
-package com.platform.service.opc.impl;
-
-import com.google.common.collect.ImmutableList;
-import com.platform.service.opc.OpcUAClientService;
-import lombok.AllArgsConstructor;
-import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
-import org.eclipse.milo.opcua.stack.core.types.builtin.*;
-import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
-import org.springframework.stereotype.Service;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-@AllArgsConstructor
-@Service("OpcUAClientService")
-class OpcUAClientServiceImpl implements OpcUAClientService {
-    /**
-     * 覆盖接口的方法,建立和OPC UA的服务
-     */
-    @Override
-    public void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception {
-        // 同步建立连接
-        client.connect().get();
-        // 异步读取数据
-        readTagData(client).thenAccept(values -> {
-            DataValue nodeId_Tag1 = values.get(0);
-            DataValue nodeId_Tag2 = values.get(1);
-            System.out.println("#########Tag1=" + nodeId_Tag1.getValue().getValue());
-            System.out.println("#########Tag2=" + nodeId_Tag2.getValue().getValue());
-            future.complete(client);
-        });
-    }
-    /**
-     * 读取标签点的数据
-     */
-    private CompletableFuture<List<DataValue>> readTagData(OpcUaClient client) {
-        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);
-        return client.readValues(0.0, TimestampsToReturn.Both, nodeIds);
-    }
-}
-

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

@@ -0,0 +1,196 @@
+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);
+        }
+    }
+
+
+}
+

+ 148 - 146
platform-service/src/main/java/com/platform/service/sb/impl/SbMeasureLogServiceImpl.java

@@ -56,7 +56,7 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
     public boolean cascadingDeleteByKey(String id) {
         int result = mapper.deleteByPrimaryKey(id);
         Weekend<CheckProjectStandardRelation> weekend = new Weekend<>(CheckProjectStandardRelation.class);
-        weekend.weekendCriteria().andEqualTo(CheckProjectStandardRelation::getStandardId,id);
+        weekend.weekendCriteria().andEqualTo(CheckProjectStandardRelation::getStandardId, id);
         return true;
     }
 
@@ -79,13 +79,13 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
     public void saveBatchByDTO(SbMeasureLogDTO model) {
         List<SbInfo> sbInfos = new ArrayList<>();
         // 检定校验 1、是否有非计量设备 2 、是否有未设置检定周期设备
-        String info = validateMeasure(model.getSbIds(),sbInfos);
-        if(StringUtils.isNotBlank(info)){
+        String info = validateMeasure(model.getSbIds(), sbInfos);
+        if (StringUtils.isNotBlank(info)) {
             throw new DeniedException(info);
         }
         SbInfo updInfo = null;
-        String serialNo = "B-"+DateUtils.dateToString(LocalDateTime.now(),DateUtils.PATTERNYMDHMS);
-        for(SbInfo sbInfo : sbInfos){
+        String serialNo = "B-" + DateUtils.dateToString(LocalDateTime.now(), DateUtils.PATTERNYMDHMS);
+        for (SbInfo sbInfo : sbInfos) {
             // 保存检定记录
             model.setSbId(sbInfo.getId());
             SbMeasureLog sbMeasureLog = super.saveModelByDTO(model);
@@ -106,16 +106,16 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
         }
     }
 
-    private String validateMeasure(List<String> sbIds,List<SbInfo> sbInfos){
+    private String validateMeasure(List<String> sbIds, List<SbInfo> sbInfos) {
         String info = "";
-        for(String sbId : sbIds){
+        for (String sbId : sbIds) {
             SbInfo sbInfo = sbInfoMapper.selectByPrimaryKey(sbId);
-            if((!sbInfo.getUseType().equals(SbUseType.BGCL.getValue())) && (!sbInfo.getUseType().equals(SbUseType.TZSB.getValue()))){
-                info = "非计量和非特种的设备, 无需填报检定记录,设备名称【"+sbInfo.getName() + "】";
+            if ((!sbInfo.getUseType().equals(SbUseType.BGCL.getValue())) && (!sbInfo.getUseType().equals(SbUseType.TZSB.getValue()))) {
+                info = "非计量和非特种的设备, 无需填报检定记录,设备名称【" + sbInfo.getName() + "】";
                 break;
             }
-            if(sbInfo.getCheckPeriod() == null){
-                info = "检定设备的检定周期未设置,设备名称【"+sbInfo.getName() + "】";
+            if (sbInfo.getCheckPeriod() == null) {
+                info = "检定设备的检定周期未设置,设备名称【" + sbInfo.getName() + "】";
                 break;
             }
             sbInfos.add(sbInfo);
@@ -126,9 +126,9 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
     @Override
     public AbstractPageResultBean<SbMeasureLog> selectPageInfo(SbMeasureLogDTO record, int pageNum, int pageSize) {
         PageHelper.startPage(pageNum, pageSize);
-        if(record.getType() == null || record.getType() == 1){
+        if (record.getType() == null || record.getType() == 1) {
 
-        }else{
+        } else {
 
         }
         AbstractPageResultBean<SbMeasureLog> pageInfo = new MyPage(mapper.selectList(record));
@@ -142,128 +142,129 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
         SbInfo sbInfo = sbInfoMapper.selectByPrimaryKey(model.getSbId());
         SbInfo tempInfo = new SbInfo();
         tempInfo.setId(sbInfo.getId());
-        // 判断设备状态,如果是在库,直接修改设备状态即可
-        if(model.getSbStatus()){
-            sbInfo.setStatus(SbInfoStatusEnum.IN_STORE.getValue());
-            String remark = "设备状态由【"+SbInfoStatusEnum.getNameByValue(sbInfo.getStatus())+"】 ---> 【";
-            remark += "在库】";
-            handleSbChangeRecord(remark,model,tempInfo,CommonConstants.CHANGE_TYPE_SB_STATUS);
-            return null;
-        }else{
-            model.setCheckUserId(SecurityUtils.getUserInfo().getUserId()); // 谁操作即是检定记录人
-            if(SbUseType.BGCL.getValue().equals(sbInfo.getUseType())){
-                model.setType(1);
-            }else if(SbUseType.TZSB.getValue().equals(sbInfo.getUseType())){
-                model.setType(2);
-            }
-            SbMeasureLog sbMeasureLog = super.saveModelByDTO(model);
-            model.setId(sbMeasureLog.getId());
-            tempInfo.setParentId(sbInfo.getParentId());
-            tempInfo.setPositionId(sbInfo.getPositionId());
-            if(sbInfo.getUseType().equals(SbUseType.BGCL.getValue())){
-                model.setType(1);
-            }else if(sbInfo.getUseType().equals(SbUseType.BGCL.getValue())){
-                model.setType(2);
-            }
-            sbInfo.setCheckDate(model.getLastDate());
-            Integer checkPeriod = 0;// 默认12个月
-            if(model.getCheckPeriod() != null){
-                checkPeriod = model.getCheckPeriod();
-            }else{
-                throw new BusinessException("检定设备的检定周期未设置,无法计算下次检定日期,请先设置");
-            }
-            sbInfo.setNextCheckDate(model.getLastDate().minusMonths(-checkPeriod).minusDays(1));
-            sbInfo.setZaiz(model.getName());// 检定单位
-            sbInfo.setSbdh(model.getNo());// 检定编号
-            sbInfo.setRemark(model.getRemark());// 备注
-            sbInfo.setDph(model.getRequirement());// 检定人
-            sbInfo.setMeasureStatus(YesNoEnum.NO.getValue());// 每次检定后, 检定状态改为正常
-            sbInfo.setCheckPeriod(model.getCheckPeriod()); // 检定周期
-            // 设备位置变动
-            boolean insertAllocate = Boolean.FALSE; // 设备位置
-            boolean insertParent = Boolean.FALSE; // 父设备
-            boolean insertNo = Boolean.FALSE; // 设备位号
-            boolean insertZzh = Boolean.FALSE; // 出厂编码
-            String oldPositionId = getPureString(sbInfo.getPositionId());
-            String oldParentId = getPureString(sbInfo.getParentId());
-            String positionId = getPureString(model.getSbPositionId());
-            String parentId = getPureString(model.getSbParentId());
-            String oldSbPositionNo = getPureString(sbInfo.getPositionNo()); // 设备位号
-            String positionNo = getPureString(model.getSbPositionNo());
-            String oldZzh = getPureString(sbInfo.getZzh()); // 原出厂编码
-            String zzh = getPureString(model.getZzh()); // 出厂编码
-            StringBuilder remark1 = new StringBuilder();
-            StringBuilder remark2 = new StringBuilder();
-            StringBuilder remark3 = new StringBuilder();
-            if(!oldPositionId.equals(positionId)){
-                insertAllocate = Boolean.TRUE;
-                sbInfo.setPositionId(positionId);
-                String before = oldPositionId == "" ? oldPositionId : sbPositionMapper.selectNameById(oldPositionId);
-                remark1.append("设备位置变动【" + before).append("】 ---> ");
-                String after = positionId == "" ? positionId : sbPositionMapper.selectNameById(positionId);
-                remark1.append("【" + after + "】");
-            }
-            if(!oldParentId.equals(parentId)){
-                insertParent = Boolean.TRUE;
-                sbInfo.setParentId(parentId);
-                remark2.append("父设备变动【" + sbInfo.getName()).append("】 ---> ");
-                String after = parentId == "" ? parentId : sbInfoMapper.selectNameById(parentId);
-                remark2.append("【" + after + "】");
-            }
-            if(!oldSbPositionNo.equals(positionNo)){
-                if(StringUtils.isNotBlank(sbInfo.getParentId())){
-                    // 子设备判断,传输过来的位号,是否存在于sb_location
-                    SbLocation location = new SbLocation();
-                    location.setNo(positionNo);
-                    if(sbLocationMapper.selectCount(location) == 0){
-                        insertLocation(model.getSbPositionNo(),sbInfo);
-                    }
-                }
-                insertNo = Boolean.TRUE;
-                remark3.append("设备位号变动【"+sbInfo.getPositionNo()).append("】 ---> ");
-                remark3.append("【"+positionNo+"】");
-                // 位号变动,父设备也有可能变动
+        // 判断设备状态,如果是在库,修改设备状态即可
+
+        model.setCheckUserId(SecurityUtils.getUserInfo().getUserId()); // 谁操作即是检定记录人
+        if (SbUseType.BGCL.getValue().equals(sbInfo.getUseType())) {
+            model.setType(1);
+        } else if (SbUseType.TZSB.getValue().equals(sbInfo.getUseType())) {
+            model.setType(2);
+        }
+        SbMeasureLog sbMeasureLog = super.saveModelByDTO(model);
+        model.setId(sbMeasureLog.getId());
+        tempInfo.setParentId(sbInfo.getParentId());
+        tempInfo.setPositionId(sbInfo.getPositionId());
+        if (sbInfo.getUseType().equals(SbUseType.BGCL.getValue())) {
+            model.setType(1);
+        } else if (sbInfo.getUseType().equals(SbUseType.BGCL.getValue())) {
+            model.setType(2);
+        }
+        sbInfo.setCheckDate(model.getLastDate());
+        Integer checkPeriod = 0;// 默认12个月
+        if (model.getCheckPeriod() != null) {
+            checkPeriod = model.getCheckPeriod();
+        } else {
+            throw new BusinessException("检定设备的检定周期未设置,无法计算下次检定日期,请先设置");
+        }
+        sbInfo.setNextCheckDate(model.getLastDate().minusMonths(-checkPeriod).minusDays(1));
+        sbInfo.setZaiz(model.getName());// 检定单位
+        sbInfo.setSbdh(model.getNo());// 检定编号
+        sbInfo.setRemark(model.getRemark());// 备注
+        sbInfo.setDph(model.getRequirement());// 检定人
+        sbInfo.setMeasureStatus(YesNoEnum.NO.getValue());// 每次检定后, 检定状态改为正常
+        sbInfo.setCheckPeriod(model.getCheckPeriod()); // 检定周期
+        // 设备位置变动
+        boolean insertAllocate = Boolean.FALSE; // 设备位置
+        boolean insertParent = Boolean.FALSE; // 父设备
+        boolean insertNo = Boolean.FALSE; // 设备位号
+        boolean insertZzh = Boolean.FALSE; // 出厂编码
+        String oldPositionId = getPureString(sbInfo.getPositionId());
+        String oldParentId = getPureString(sbInfo.getParentId());
+        String positionId = getPureString(model.getSbPositionId());
+        String parentId = getPureString(model.getSbParentId());
+        String oldSbPositionNo = getPureString(sbInfo.getPositionNo()); // 设备位号
+        String positionNo = getPureString(model.getSbPositionNo());
+        String oldZzh = getPureString(sbInfo.getZzh()); // 原出厂编码
+        String zzh = getPureString(model.getZzh()); // 出厂编码
+        StringBuilder remark1 = new StringBuilder();
+        StringBuilder remark2 = new StringBuilder();
+        StringBuilder remark3 = new StringBuilder();
+        if (!oldPositionId.equals(positionId)) {
+            insertAllocate = Boolean.TRUE;
+            sbInfo.setPositionId(positionId);
+            String before = oldPositionId == "" ? oldPositionId : sbPositionMapper.selectNameById(oldPositionId);
+            remark1.append("设备位置变动【" + before).append("】 ---> ");
+            String after = positionId == "" ? positionId : sbPositionMapper.selectNameById(positionId);
+            remark1.append("【" + after + "】");
+        }
+        if (!oldParentId.equals(parentId)) {
+            insertParent = Boolean.TRUE;
+            sbInfo.setParentId(parentId);
+            remark2.append("父设备变动【" + sbInfo.getName()).append("】 ---> ");
+            String after = parentId == "" ? parentId : sbInfoMapper.selectNameById(parentId);
+            remark2.append("【" + after + "】");
+        }
+        if (!oldSbPositionNo.equals(positionNo)) {
+            if (StringUtils.isNotBlank(sbInfo.getParentId())) {
+                // 子设备判断,传输过来的位号,是否存在于sb_location
                 SbLocation location = new SbLocation();
                 location.setNo(positionNo);
-                List<SbLocation> locations = sbLocationMapper.select(location);
-                if(locations != null && locations.size() > 0){
-                    sbInfo.setParentId(locations.get(0).getSbId());
+                if (sbLocationMapper.selectCount(location) == 0) {
+                    insertLocation(model.getSbPositionNo(), sbInfo);
                 }
-                sbInfo.setPositionNo(model.getSbPositionNo()); // 设备位号
-            }
-            StringBuilder remark4 = new StringBuilder();
-            if(!oldZzh.equals(zzh)){
-                insertZzh = Boolean.TRUE;
-                remark4.append("设备原号变动【"+oldZzh).append("】 ---> ");
-                remark4.append("【"+zzh+"】");
-                sbInfo.setZzh(zzh);
-            }
-            // 保存文件
-            sysFileService.saveFile(model.getId(), SysFileTypeEnum.Sb_MEASURE_IMGS.getValue(), model.getCheckImgList());
-            sysFileService.saveFile(model.getId(), SysFileTypeEnum.Sb_MEASURE_FILES.getValue(), model.getCheckFileList());
-            // 写入调拨记录
-            if(insertAllocate){
-                handleSbChangeRecord(remark1.toString(),model,tempInfo,CommonConstants.CHANGE_TYPE_SB_POSITION);
             }
-            if(insertParent){
-                handleSbChangeRecord(remark2.toString(),model,tempInfo,CommonConstants.CHANGE_TYPE_SB_PARENT);
-            }
-            if(insertNo){
-                handleSbChangeRecord(remark3.toString(),model,tempInfo,CommonConstants.CHANGE_TYPE_SB_NO);
+            insertNo = Boolean.TRUE;
+            remark3.append("设备位号变动【" + sbInfo.getPositionNo()).append("】 ---> ");
+            remark3.append("【" + positionNo + "】");
+            // 位号变动,父设备也有可能变动
+            SbLocation location = new SbLocation();
+            location.setNo(positionNo);
+            List<SbLocation> locations = sbLocationMapper.select(location);
+            if (locations != null && locations.size() > 0) {
+                sbInfo.setParentId(locations.get(0).getSbId());
             }
-            if(insertZzh){
-                handleSbChangeRecord(remark4.toString(),model,tempInfo,CommonConstants.CHANGE_TYPE_SB_ZZH);
-            }
-            sbInfoMapper.updateByPrimaryKey(sbInfo);
-            return sbMeasureLog;
+            sbInfo.setPositionNo(model.getSbPositionNo()); // 设备位号
         }
+        StringBuilder remark4 = new StringBuilder();
+        if (!oldZzh.equals(zzh)) {
+            insertZzh = Boolean.TRUE;
+            remark4.append("设备原号变动【" + oldZzh).append("】 ---> ");
+            remark4.append("【" + zzh + "】");
+            sbInfo.setZzh(zzh);
+        }
+        // 保存文件
+        sysFileService.saveFile(model.getId(), SysFileTypeEnum.Sb_MEASURE_IMGS.getValue(), model.getCheckImgList());
+        sysFileService.saveFile(model.getId(), SysFileTypeEnum.Sb_MEASURE_FILES.getValue(), model.getCheckFileList());
+        // 写入调拨记录
+        if (insertAllocate) {
+            handleSbChangeRecord(remark1.toString(), model, tempInfo, CommonConstants.CHANGE_TYPE_SB_POSITION);
+        }
+        if (insertParent) {
+            handleSbChangeRecord(remark2.toString(), model, tempInfo, CommonConstants.CHANGE_TYPE_SB_PARENT);
+        }
+        if (insertNo) {
+            handleSbChangeRecord(remark3.toString(), model, tempInfo, CommonConstants.CHANGE_TYPE_SB_NO);
+        }
+        if (insertZzh) {
+            handleSbChangeRecord(remark4.toString(), model, tempInfo, CommonConstants.CHANGE_TYPE_SB_ZZH);
+        }
+        // 更新设备状态
+        if (model.getSbStatus()) {
+            sbInfo.setStatus(SbInfoStatusEnum.IN_STORE.getValue());
+            String remark = "设备状态由【" + SbInfoStatusEnum.getNameByValue(sbInfo.getStatus()) + "】 ---> 【";
+            remark += "在库】";
+            handleSbChangeRecord(remark, model, tempInfo, CommonConstants.CHANGE_TYPE_SB_STATUS);
+        }
+        sbInfoMapper.updateByPrimaryKey(sbInfo);
+        return sbMeasureLog;
+
     }
 
-    private String getPureString(String info){
+    private String getPureString(String info) {
         return StringUtils.isBlank(info) ? "" : info;
     }
 
-    private void insertLocation(String sbPositionNo,SbInfo sbInfo){
+    private void insertLocation(String sbPositionNo, SbInfo sbInfo) {
         SbLocation location = new SbLocation();
         location.setId(IdGeneratorUtils.getObjectId());
         location.setNo(sbPositionNo);
@@ -278,12 +279,13 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
 
     /**
      * 保存变更记录
+     *
      * @param remark
      * @param model
      * @param sb
      * @param type
      */
-    void handleSbChangeRecord(String remark,SbMeasureLogDTO model,SbInfo sb,String type){
+    void handleSbChangeRecord(String remark, SbMeasureLogDTO model, SbInfo sb, String type) {
         SbChangeRecord record = new SbChangeRecord();
         record.setId(IdGeneratorUtils.getObjectId());
         record.setChangeType(Integer.parseInt(type));
@@ -292,7 +294,7 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
         record.setCreatedUserId(SecurityUtils.getUserInfo().getUserId());
         record.setCreatedUserName(SecurityUtils.getUserInfo().getUsername());
         record.setSbId(sb.getId());
-        switch (type){
+        switch (type) {
             case CommonConstants.CHANGE_TYPE_SB_POSITION:
                 record.setOldPositionId(sb.getPositionId());
                 record.setPositionId(model.getSbPositionId());
@@ -305,7 +307,7 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
                 dto.setChangeType(record.getChangeType());
                 dto.setSbNoId(model.getSbPositionNo());
                 SbChangeRecord oldRecord = sbChangeRecordMapper.getLastOne(dto);
-                if(oldRecord != null){
+                if (oldRecord != null) {
                     oldRecord.setEndTime(LocalDateTime.now());
                     sbChangeRecordMapper.updateByPrimaryKey(oldRecord);
                 }
@@ -328,19 +330,19 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
         // 更新设备下次检定日期
         SbInfo sbInfo = sbInfoMapper.selectByPrimaryKeyForUpdate(model.getSbId());
         sbInfo.setCheckDate(model.getLastDate());
-        if(sbInfo.getUseType().equals(SbUseType.BGCL.getValue())){
+        if (sbInfo.getUseType().equals(SbUseType.BGCL.getValue())) {
             model.setType(1);
-        }else if(sbInfo.getUseType().equals(SbUseType.BGCL.getValue())){
+        } else if (sbInfo.getUseType().equals(SbUseType.BGCL.getValue())) {
             model.setType(2);
-        }else{
+        } else {
             throw new BusinessException("非计量和非特种的设备,无需填报检定记录");
         }
         super.modModelByDTO(model);
 
         Integer checkPeriod = 12;// 默认12个月
-        if(sbInfo.getCheckPeriod() != null){
+        if (sbInfo.getCheckPeriod() != null) {
             checkPeriod = sbInfo.getCheckPeriod();
-        }else{
+        } else {
             throw new BusinessException("检定设备的检定周期未设置,无法计算下次检定日期,请先设置");
         }
         sbInfo.setNextCheckDate(model.getLastDate().minusMonths(-checkPeriod).minusDays(1));
@@ -385,10 +387,10 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
         List<SysFile> checkImgList = ListUtils.newArrayList();
         List<SysFile> checkFileList = ListUtils.newArrayList();
         sysFiles.forEach(item -> {
-            if (item.getType().equals( SysFileTypeEnum.Sb_MEASURE_IMGS.getValue())) {
+            if (item.getType().equals(SysFileTypeEnum.Sb_MEASURE_IMGS.getValue())) {
                 checkImgList.add(item);
             }
-            if (item.getType().equals( SysFileTypeEnum.Sb_MEASURE_FILES.getValue())) {
+            if (item.getType().equals(SysFileTypeEnum.Sb_MEASURE_FILES.getValue())) {
                 checkFileList.add(item);
             }
         });
@@ -398,16 +400,16 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
     }
 
     @Override
-    public List<MeasureLogReportVO> getMonthReport(SbMeasureLogDTO sbMeasureLogDTO, Integer searchYear , LocalDate startMonth, LocalDate endMonth) {
+    public List<MeasureLogReportVO> getMonthReport(SbMeasureLogDTO sbMeasureLogDTO, Integer searchYear, LocalDate startMonth, LocalDate endMonth) {
         List<Map<String, LocalDateTime>> monthStartAndEndList = new ArrayList<Map<String, LocalDateTime>>();
         LocalDateTime searchStartTime = null;
         LocalDateTime searchEndTime = null;
-        if(searchYear != null){
+        if (searchYear != null) {
             LocalDate localDate = LocalDate.now();
             int year = localDate.getYear();
             // 如2021-10-15号码,则month=10,需要计算到11月份,需要加1
             int month = localDate.getMonthValue();
-            if(searchYear<year){
+            if (searchYear < year) {
                 month = 12;
                 year = searchYear;
             }
@@ -415,7 +417,7 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
             // 当前年份只统计到当前月,历史年份统计全年
             searchStartTime = DateUtils.getFirstDayOfThisYear(year);
             searchEndTime = DateUtils.getLastDayOfMonth(year, month);
-        }else{
+        } else {
             monthStartAndEndList = DateUtils.getMonthStartAndEndByYear(startMonth, endMonth);
             searchStartTime = DateUtils.getFirstDayOfMonth(startMonth);
             searchEndTime = DateUtils.getLastDayOfMonth(endMonth);
@@ -426,7 +428,7 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
         List<SbMeasureLogVO> list = mapper.selectList(sbMeasureLogDTO);
 
         List<MeasureLogReportVO> result = new ArrayList<>();
-        for(Map<String, LocalDateTime> map: monthStartAndEndList){
+        for (Map<String, LocalDateTime> map : monthStartAndEndList) {
             MeasureLogReportVO vo = new MeasureLogReportVO();
             List<SbMeasureLogVO> detailList = new ArrayList<>();
             vo.setYear(map.get("searchStartTimeMonth").getYear());
@@ -435,17 +437,17 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
             int totalFinishNum = 0;
             int totalWaitNum = 0;
             double finishRate = 0;
-            for(SbMeasureLogVO sbMeasureLogVO: list){
-                if(sbMeasureLogVO.getLastDate().isAfter(map.get("searchStartTimeMonth").toLocalDate()) && sbMeasureLogVO.getLastDate().isBefore(map.get("searchEndTimeMonth").toLocalDate())){
-                    totalNum ++;
-                    totalFinishNum ++;
+            for (SbMeasureLogVO sbMeasureLogVO : list) {
+                if (sbMeasureLogVO.getLastDate().isAfter(map.get("searchStartTimeMonth").toLocalDate()) && sbMeasureLogVO.getLastDate().isBefore(map.get("searchEndTimeMonth").toLocalDate())) {
+                    totalNum++;
+                    totalFinishNum++;
                     detailList.add(sbMeasureLogVO);
                 }
             }
 
-            if(totalNum != 0){
+            if (totalNum != 0) {
                 totalWaitNum = totalNum - totalFinishNum;
-                finishRate = BigDecimalUtil.decimal(BigDecimalUtil.div(totalFinishNum*100, totalNum),2);
+                finishRate = BigDecimalUtil.decimal(BigDecimalUtil.div(totalFinishNum * 100, totalNum), 2);
             }
             vo.setTotalNum(totalNum);
             // vo.setTotalFinishNum(totalFinishNum);
@@ -459,7 +461,7 @@ public class SbMeasureLogServiceImpl extends BaseServiceImpl<SbMeasureLogMapper,
 
     @Override
     public void saveBatchMeasureLog(BatchSbMeasureLog batchSbMeasureLog) {
-        if(batchSbMeasureLog.getSbMeasureLogDTOList() != null && batchSbMeasureLog.getSbMeasureLogDTOList().size() > 0){
+        if (batchSbMeasureLog.getSbMeasureLogDTOList() != null && batchSbMeasureLog.getSbMeasureLogDTOList().size() > 0) {
             batchSbMeasureLog.getSbMeasureLogDTOList().forEach(item -> {
                 this.saveModelByDTO(item);
             });