diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/device_driver/standard_inspect_site_smart200/ItemProtocol.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/device_driver/standard_inspect_site_smart200/ItemProtocol.java
index 3f3a727..ba8a1c8 100644
--- a/acs/hd/nladmin-system/src/main/java/org/nl/acs/device_driver/standard_inspect_site_smart200/ItemProtocol.java
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/device_driver/standard_inspect_site_smart200/ItemProtocol.java
@@ -22,6 +22,7 @@ public class ItemProtocol {
     public static String item_hour = "hour";
     public static String item_minute = "minute";
     public static String item_second = "second";
+    public static String item_flag ="flag";
 
 
     private StandardInspectSiteSmartDeviceDriver driver;
@@ -70,6 +71,10 @@ public class ItemProtocol {
         return this.getOpcStringValue(item_second);
     }
 
+    public String getFlag() {
+        return this.getOpcStringValue(item_flag);
+    }
+
 
 
     //是否有货
@@ -115,6 +120,7 @@ public class ItemProtocol {
         list.add(new ItemDto(item_hour, "时", "VB1059"));
         list.add(new ItemDto(item_minute, "分", "VB1060"));
         list.add(new ItemDto(item_second, "秒", "VB1061"));
+        list.add(new ItemDto(item_flag, "气缸状态", "V700.6"));
 
 
         return list;
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/device_driver/standard_inspect_site_smart200/StandardInspectSiteSmartDeviceDriver.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/device_driver/standard_inspect_site_smart200/StandardInspectSiteSmartDeviceDriver.java
index 9f33194..23bc082 100644
--- a/acs/hd/nladmin-system/src/main/java/org/nl/acs/device_driver/standard_inspect_site_smart200/StandardInspectSiteSmartDeviceDriver.java
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/device_driver/standard_inspect_site_smart200/StandardInspectSiteSmartDeviceDriver.java
@@ -120,7 +120,7 @@ public class StandardInspectSiteSmartDeviceDriver extends AbstractOpcDeviceDrive
     private Boolean apply_material = false;
 
     //暂定 0就绪 1请求取货 2取货完成 3请求放货 4放货完成 5取货完成离开 6放货完成离开 7请求进入区域 8请求离开区域
-    int flag;
+//    int flag;
 
     String devicecode;
 
@@ -175,6 +175,9 @@ public class StandardInspectSiteSmartDeviceDriver extends AbstractOpcDeviceDrive
     private String time;
     private String last_time;
 
+    //气缸分离状态0-不分离,1分离
+    private String flag;
+    private String last_flag;
 
     @Override
     public Device getDevice() {
@@ -199,6 +202,7 @@ public class StandardInspectSiteSmartDeviceDriver extends AbstractOpcDeviceDrive
             second = this.itemProtocol.getSecond();
             time= new StringBuilder().append(year).append(month).append(day)
                     .append(hour).append(minute).append(second).toString();
+            flag=this.itemProtocol.getFlag();
 
             if (mode != last_mode) {
                 if (mode == 5) {
@@ -374,6 +378,7 @@ public class StandardInspectSiteSmartDeviceDriver extends AbstractOpcDeviceDrive
         last_minute = minute;
         last_second = second;
         last_time = time;
+        last_flag = flag;
 
 
     }
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/DeviceOpcProtocolRunable.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/DeviceOpcProtocolRunable.java
index 33ded01..e96fd86 100644
--- a/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/DeviceOpcProtocolRunable.java
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/DeviceOpcProtocolRunable.java
@@ -4,27 +4,33 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import lombok.extern.slf4j.Slf4j;
-import org.nl.modules.udw.UnifiedDataAccessor;
-import org.nl.modules.udw.UnifiedDataAccessorFactory;
-import org.nl.utils.RedisUtils;
-import org.nl.utils.SpringContextHolder;
-import org.openscada.opc.lib.da.Group;
-import org.openscada.opc.lib.da.Item;
-import org.openscada.opc.lib.da.ItemState;
-import org.openscada.opc.lib.da.Server;
+import org.nl.acs.udw.UnifiedDataAccessor;
+import org.nl.acs.udw.UnifiedDataAccessorFactory;
+import org.nl.acs.udw.UnifiedDataAppService;
+import org.openscada.opc.lib.da.*;
 
 import java.util.*;
 
+
 @Slf4j
-public class DeviceOpcProtocolRunable implements Runnable {
+public class DeviceOpcProtocolRunable implements Runnable, DataCallback, ServerConnectionStateListener {
     List<OpcItemDto> protocols;
     OpcServerManageDto OpcServer;
     int error_num;
     String message;
+    int maxResartNum;
+    private Server server;
+    private Group group;
+    boolean flag = false;
+    private int all_null;
+    private Map<String, OpcItemDto> itemSearchCache;
 
     public DeviceOpcProtocolRunable() {
         this.error_num = 0;
+        this.all_null = 0;
         this.message = null;
+        this.itemSearchCache = new HashMap();
+        this.server = null;
     }
 
     public List<OpcItemDto> getProtocols() {
@@ -43,32 +49,58 @@ public class DeviceOpcProtocolRunable implements Runnable {
         this.OpcServer = opcServer;
     }
 
-    OpcItemDto getItem(String item) {
-        Iterator var2 = this.protocols.iterator();
 
-        OpcItemDto dto;
-        do {
-            if (!var2.hasNext()) {
-                return null;
-            }
+    private OpcItemDto getItem(String item) {
+        OpcItemDto x = (OpcItemDto) this.itemSearchCache.get(item);
+        if (x == null) {
+            Iterator var3 = this.protocols.iterator();
 
-            dto = (OpcItemDto) var2.next();
-        } while (!StrUtil.equals(item, dto.getItem_code()));
+            while (var3.hasNext()) {
+                OpcItemDto dto = (OpcItemDto) var3.next();
+                if (StrUtil.equals(item, dto.getItem_code())) {
+                    x = dto;
+                    this.itemSearchCache.put(item, dto);
+                    break;
+                }
+            }
+        }
 
-        return dto;
+        return x;
     }
 
+
     @Override
     public void run() {
+        if (OpcConfig.opc_item_read_using_callback) {
+            this.runNew();
+        } else {
+            this.runOld();
+        }
+    }
+
+
+    private void runOld() {
         while (true) {
+            start:
             try {
-                Server server = OpcServerUtl.getServerWithOutException(this.OpcServer.getOpc_host(), this.OpcServer.getCls_id(), this.OpcServer.getUser(), this.OpcServer.getPassword(), this.OpcServer.getDomain());
-                Group group = server.addGroup();
+                if (this.group != null) {
+                    group.clear();
+                    group.remove();
+                    log.trace("清理group...");
+                }
+                if (this.server != null) {
+                    server.disconnect();
+                    log.trace("清理server...");
+                }
+
+                this.server = OpcServerUtl.getServerWithOutException(this.OpcServer.getOpc_host(), this.OpcServer.getCls_id(), this.OpcServer.getUser(), this.OpcServer.getPassword(), this.OpcServer.getDomain());
+                this.server.addStateListener(this);
+                group = this.server.addGroup();
                 List<String> itemsString = new ArrayList();
-                Iterator it = this.protocols.iterator();
+                Iterator var3 = this.protocols.iterator();
 
-                while (it.hasNext()) {
-                    OpcItemDto protocol = (OpcItemDto) it.next();
+                while (var3.hasNext()) {
+                    OpcItemDto protocol = (OpcItemDto) var3.next();
                     String item = protocol.getItem_code();
                     itemsString.add(item);
                 }
@@ -76,47 +108,57 @@ public class DeviceOpcProtocolRunable implements Runnable {
                 Map<String, Item> itemsMap = new LinkedHashMap();
                 boolean is_error = false;
                 StringBuilder err_message = new StringBuilder();
-                Iterator var7 = itemsString.iterator();
+                Iterator var6 = itemsString.iterator();
 
-                while (var7.hasNext()) {
-                    String string = (String) var7.next();
+                while (var6.hasNext()) {
+                    String string = (String) var6.next();
 
                     try {
-                        itemsMap.put(string, group.addItem(string));
+                        Item item = group.addItem(string);
+                        itemsMap.put(string, item);
                         log.trace("添加成功 {}", string);
-                    } catch (Exception var29) {
-                        err_message.append(string + ":" + var29.getMessage());
+                    } catch (Exception var26) {
+                        err_message.append(string + ":" + var26.getMessage());
                         if (!is_error) {
                             is_error = true;
                         }
                     }
                 }
 
+                String tag;
                 if (is_error) {
-                    log.info("设备OPC数据同步配置异常");
+                    tag = err_message.toString();
+                    log.warn("{}:{}", OpcConfig.resource_code, tag);
                 }
 
                 if (!OpcStartTag.is_run) {
                     OpcStartTag.is_run = true;
                 }
 
-                //线程名
-                String tag = Thread.currentThread().getName();
-                if (this.OpcServer != null) {
-                    tag = tag + this.OpcServer.getOpc_code();
+                tag = "";
+                if (log.isWarnEnabled()) {
+                    tag = Thread.currentThread().getName();
+                    if (this.OpcServer != null) {
+                        tag = tag + this.getOpcGroupID();
+                    }
                 }
-                UnifiedDataAccessor accessor_value = UnifiedDataAccessorFactory.getAccessor(OpcConfig.udw_opc_value_key);
 
+                UnifiedDataAccessor accessor_value = UnifiedDataAccessorFactory.getAccessor(OpcConfig.udw_opc_value_key);
                 boolean time_out = false;
 
-                label97:
-                while (true) {
+                while (DeviceOpcSynchronizeAutoRun.isRun) {
                     long begin = System.currentTimeMillis();
+                    if (log.isTraceEnabled()) {
+                        log.trace("{} 开始记时{}", tag, DateUtil.now());
+                    }
+
                     Map<Item, ItemState> itemStatus = group.read(true, (Item[]) itemsMap.values().toArray(new Item[0]));
                     long end = System.currentTimeMillis();
-                    log.trace("{} 开始记时{}", tag, DateUtil.now());
                     long duration = end - begin;
-                    log.trace("{} 读取耗时:{}", tag, duration);
+                    if (log.isTraceEnabled()) {
+                        log.trace("{} 读取耗时:{}", tag, duration);
+                    }
+
                     if (duration > 1000L) {
                         if (!time_out) {
                             log.warn("{} 读取超时 : {}", tag, duration);
@@ -127,84 +169,197 @@ public class DeviceOpcProtocolRunable implements Runnable {
                         time_out = false;
                     }
 
+                    boolean valueAllNotNull = false;
                     Set<Item> items = itemStatus.keySet();
                     Iterator var18 = items.iterator();
 
-                    while (true) {
-                        Item item;
-                        //当前值
-                        Object value;
-                        //旧的值
-                        Object his;
-                        do {
-                            if (!var18.hasNext()) {
-                                end = System.currentTimeMillis();
-                                log.trace("{}", itemsString);
-                                log.trace("{} 计算完成耗时{}", tag, end - begin);
-                                Thread.sleep((long) OpcConfig.synchronized_millisecond);
-                                if (this.error_num != 0) {
-                                    this.error_num = 0;
-                                    this.message = null;
-                                }
-                                continue label97;
+                    while (var18.hasNext()) {
+                        Item item = (Item) var18.next();
+                        ItemState itemState = (ItemState) itemStatus.get(item);
+                        Object value = OpcUtl.getValue(item, itemState);
+                        if (value != null) {
+                            valueAllNotNull = true;
+                        }
+
+                        String itemId = item.getId();
+                        Object his = accessor_value.getValue(itemId);
+                        if (itemState.getQuality()==QualityTypeValue.OPC_QUALITY_GOOD && his != null) {
+                            log.warn("opc 值不健康 item: {}, 状态: {}", itemId, itemState.getQuality());
+                            valueAllNotNull = true;
+                        }
+
+                        if (!UnifiedDataAppService.isEquals(value, his)) {
+                            OpcItemDto itemDto = this.getItem(itemId);
+                            if (true) {
+                                this.logItemChanged(itemId, accessor_value, value, itemDto);
+                            }
+                            if(!ObjectUtil.isEmpty(value)){
+                                accessor_value.setValue(itemId, value);
                             }
+                        }
+                    }
+
+                    end = System.currentTimeMillis();
+                    if (log.isTraceEnabled()) {
+                        log.trace("{}", itemsString);
+                        log.trace("{} 计算完成耗时{}", tag, end - begin);
+                    }
 
-                            item = (Item) var18.next();
-                            ItemState itemState = (ItemState) itemStatus.get(item);
-                            value = OpcUtl.getValue(item, itemState);
-//                            his = accessor_value.getValue(item.getId());
-                            RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
-                            his=redisUtils.get(item.getId());
+                    ThreadUtl.sleep((long) OpcConfig.synchronized_millisecond);
+                    if (this.error_num != 0) {
+                        this.error_num = 0;
+                        this.message = null;
+                    }
+
+                    if (!valueAllNotNull) {
+                        int random = (new Random()).nextInt(10) + 1;
+                        random *= 1000;
+                        if (this.all_null < 3) {
+                            if (log.isWarnEnabled()) {
+                                log.warn("{} 所有内容都为空, all_null:{} ,暂定{}s", tag, all_null,5000 + random);
+                            }
 
-                            if (!ObjectUtil.equal(itemState.getQuality(), QualityTypeValue.OPC_QUALITY_GOOD) && his != null) {
-                                log.warn("opc 值不健康 item: {}, 状态: {}", item.getId(), itemState.getQuality());
+                            ThreadUtl.sleep((long) (5000 + random));
+                        } else if (this.all_null < 6) {
+                            if (log.isWarnEnabled()) {
+                                log.warn(tag + "重新创建server");
+                                log.warn("{} 所有内容都为空, all_null:{} ,暂定{}s", tag, all_null,30000 + random);
                             }
-                        } while (ObjectUtil.equal(value, his));//如果两次的值相等,不走下面的代码
-
-                        OpcItemDto itemDto = this.getItem(item.getId());
-                        if (itemDto.getNeed_log() != null && itemDto.getNeed_log()) {
-                            StringBuilder sb = new StringBuilder();
-                            //设备的ITEM项
-                            List<String> relate_items = itemDto.getRelate_items();
-                            Iterator var26 = relate_items.iterator();
-
-                            while (var26.hasNext()) {
-                                String relate = (String) var26.next();
-                                Object obj = accessor_value.getValue(relate);
-                                sb.append("key:" + relate + "value:" + obj + ";");
+//                            ThreadUtl.sleep((long) (30000 + random));
+                            ThreadUtl.sleep((long) ((new Random()).nextInt(3) +1) * 1000);
+                            break start;
+                        } else if (this.all_null < 12) {
+                            if (log.isWarnEnabled()) {
+                                log.warn("{} 所有内容都为空, all_null:{} ,暂定{}ms", tag, all_null, '\uea60' + random);
                             }
 
-                            log.info("信号{}变更从{}->{};信号快照:{}", new Object[]{item.getId(), his, value, sb});
+                            ThreadUtl.sleep((long) ('\uea60' + random));
+                        } else {
+                            if (log.isWarnEnabled()) {
+                                log.warn("{} 所有内容都为空, all_null:{} ,暂定{}ms", tag, all_null, 120000 + random);
+                            }
 
+                            ThreadUtl.sleep((long) (120000 + random));
                         }
-                        //设置值
-                        accessor_value.setValue(item.getId(), value);
-                        RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
-                        redisUtils.set(item.getId(), value);
 
+                        ++this.all_null;
+                    } else {
+                        this.all_null = 0;
+                    }
+//                    break start;
 
+                }
+
+                log.warn("opc线程停止。。。");
+                return;
+            } catch (Exception var27) {
+                if (this.server != null) {
+                    try {
+                        this.server.disconnect();
+                    } catch (Exception var25) {
                     }
                 }
-            } catch (Exception var30) {
+
+                this.server = null;
+                if (!DeviceOpcSynchronizeAutoRun.isRun) {
+                    log.warn("opc线程停止2。。。");
+                    return;
+                }
+
                 String error_message = "设备信息同步异常";
                 if (!StrUtil.equals(this.message, error_message)) {
-                    log.warn("", var30);
+                    log.warn(error_message, var27);
+                }
+
+                ThreadUtl.sleep((long) (OpcConfig.synchronized_exception_wait_second * 1000));
+                ++this.error_num;
+                if (this.error_num > 3 && !StrUtil.equals(this.message, error_message)) {
+                    this.message = error_message;
+                }
+            }
+        }
+    }
+
+
+    private void runNew() {
+        Async20Access accessor = null;
+
+        while (true) {
+            String opcGroupId = this.getOpcGroupID();
+
+            try {
+                if (this.server == null) {
+                    this.server = OpcServerUtl.getServerWithOutException(this.OpcServer.getOpc_host(), this.OpcServer.getCls_id(), this.OpcServer.getUser(), this.OpcServer.getPassword(), this.OpcServer.getDomain());
+                    this.server.addStateListener(this);
+                    accessor = new Async20Access(this.server, OpcConfig.synchronized_millisecond, true);
+                    Iterator var9 = this.protocols.iterator();
+
+                    while (var9.hasNext()) {
+                        OpcItemDto protocol = (OpcItemDto) var9.next();
+                        String itemId = protocol.getItem_code();
+                        accessor.addItem(itemId, this);
+                    }
+
+                    accessor.bind();
+                    log.info("Async20Access bind {}", opcGroupId);
+                }
+
+                Thread.sleep((long) (OpcConfig.synchronized_exception_wait_second * 1000));
+            } catch (Exception var8) {
+                if (accessor != null) {
+                    try {
+                        log.warn("Async20Access unbind {}", opcGroupId);
+                        accessor.unbind();
+                    } catch (Exception var7) {
+                        var7.printStackTrace();
+                    }
+
+                    accessor = null;
+                }
+
+                if (this.server != null) {
+                    try {
+                        this.server.disconnect();
+                    } catch (Exception var6) {
+                    }
+
+                    this.server = null;
+                }
+
+                if (var8 instanceof InterruptedException) {
+                    log.warn("OPC 同步线程(%s)被中断", opcGroupId);
+                    return;
                 }
 
-                try {
-                    Thread.sleep((long) (OpcConfig.synchronized_exception_wait_second * 1000));
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
+                log.warn("设备信息同步异常", var8);
+                ThreadUtl.sleep((long) (OpcConfig.synchronized_exception_wait_second * 1000));
+                String error_message = var8.getMessage();
+                if (error_message == null) {
+                    error_message = var8.toString();
                 }
+
                 ++this.error_num;
                 if (this.error_num > 3 && !StrUtil.equals(this.message, error_message)) {
-                    log.info("设备同步通信异常");
                     this.message = error_message;
                 }
             }
         }
     }
 
+
+    public void connectionStateChanged(boolean connected) {
+        if (!connected) {
+            this.server = null;
+        }
+
+        log.warn("opc server {} {}", this.getOpcGroupID(), connected ? "connected" : "disconnected");
+    }
+
+    private String getOpcGroupID() {
+        String var10000 = this.OpcServer.getOpc_code();
+        return var10000 + "(" + this.protocols.size() + " items)";
+    }
+
     public static String formatDuring(long mss) {
         long days = mss / 86400000L;
         long hours = mss % 86400000L / 3600000L;
@@ -212,4 +367,55 @@ public class DeviceOpcProtocolRunable implements Runnable {
         long seconds = mss % 60000L / 1000L;
         return days + " days " + hours + " hours " + minutes + " minutes " + seconds + " seconds ";
     }
+
+
+    public void changed(Item item, ItemState itemState) {
+        String itemId = item.getId();
+
+        try {
+            Object value = OpcUtl.getValue(item, itemState);
+            UnifiedDataAccessor accessor_value = UnifiedDataAccessorFactory.getAccessor(OpcConfig.udw_opc_value_key);
+            accessor_value.setValue(itemId, value);
+
+//            if (value != null) {
+//                if (log.isTraceEnabled()) {
+//                    log.trace("Item {} new value: {}, Timestamp: {}", new Object[]{itemId, itemState.getValue(), itemState.getTimestamp().getTime()});
+//                }
+//            } else if (log.isInfoEnabled()) {
+//                log.info("Item {} new value: {}, Timestamp: {}, Quality: {}", new Object[]{itemId, itemState.getValue(), itemState.getTimestamp().getTime(), itemState.getQuality()});
+//            }
+            log.trace("Item {} new value: {}, Timestamp: {}", new Object[]{itemId, itemState.getValue(), itemState.getTimestamp().getTime()});
+
+            OpcItemDto itemDto = this.getItem(itemId);
+//            if (Boolean.TRUE.equals(itemDto.getNeed_log())) {
+//                this.logItemChanged(itemId, accessor_value, value, itemDto);
+//            }
+            this.logItemChanged(itemId, accessor_value, value, itemDto);
+
+        } catch (Exception var7) {
+            log.error(itemId, var7);
+        }
+
+    }
+
+    private void logItemChanged(String itemId, UnifiedDataAccessor accessor_value, Object value, OpcItemDto itemDto) {
+        Object his = accessor_value.getValue(itemId);
+        List<String> relate_items = itemDto.getRelate_items();
+        if (relate_items != null && !relate_items.isEmpty()) {
+            StringBuilder sb = new StringBuilder();
+            Iterator var8 = relate_items.iterator();
+
+            while (var8.hasNext()) {
+                String relate = (String) var8.next();
+                Object obj = accessor_value.getValue(relate);
+                sb.append("key:" + relate + "value:" + obj + ";");
+            }
+            log.warn("设备:{}信号{}变更从{}->{};信号快照:{}", new Object[]{itemDto.getDevice_code(), itemId, his, value, sb});
+//            this.businessLogger.setResource(itemDto.getDevice_code(), itemDto.getDevice_name()).log("信号{}变更从{}->{};信号快照:{}", new Object[]{itemId, his, value, sb});
+        } else {
+            log.warn("设备:{}信号{}变更从{}->{};信号快照:{}", new Object[]{itemDto.getDevice_code(), itemId, his, value});
+//            this.businessLogger.setResource(itemDto.getDevice_code(), itemDto.getDevice_name()).log("信号{}变更从{}->{}", new Object[]{itemId, his, value});
+        }
+    }
+
 }
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/DeviceOpcSynchronizeAutoRun.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/DeviceOpcSynchronizeAutoRun.java
index 1ca65ab..769db3c 100644
--- a/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/DeviceOpcSynchronizeAutoRun.java
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/DeviceOpcSynchronizeAutoRun.java
@@ -17,6 +17,7 @@ import java.util.concurrent.Executors;
  */
 @Component
 public class DeviceOpcSynchronizeAutoRun extends AbstractAutoRunnable {
+    public static boolean isRun = false;
     ExecutorService executorService = Executors.newCachedThreadPool();
     @Autowired
     private DeviceAppService deviceAppService;
@@ -36,6 +37,7 @@ public class DeviceOpcSynchronizeAutoRun extends AbstractAutoRunnable {
     @Override
     public void autoRun() throws Exception {
         {
+            isRun = true;
 
             Map<String, OpcServerManageDto> servers = this.opcServerManageService.queryAllServerMap();
             Map<String, List<List<OpcItemDto>>> pros;
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/OpcConfig.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/OpcConfig.java
index cadf67c..f1158d0 100644
--- a/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/OpcConfig.java
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/OpcConfig.java
@@ -10,4 +10,6 @@ public class OpcConfig {
     public static String opc_server_default_group = "group";
     public static String resource_code = "opc_sync";
     public static String resource_name = "opc同步";
+    //OPC 数据同步是否采用回调机制实现。之前是线程定期全部读,效率低。
+    public static Boolean opc_item_read_using_callback = false;
 }
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/ThreadUtl.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/ThreadUtl.java
new file mode 100644
index 0000000..c2e51c0
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/opc/ThreadUtl.java
@@ -0,0 +1,21 @@
+package org.nl.acs.opc;
+
+/**
+ * @author ldjun
+ * @version 1.0
+ * @date 2023年02月01日 11:28
+ * @desc desc
+ */
+public class ThreadUtl {
+    private ThreadUtl() {
+    }
+
+    public static void sleep(long times) throws RuntimeException {
+        try {
+            Thread.sleep(times);
+        } catch (InterruptedException var3) {
+            throw new RuntimeException(var3);
+        }
+    }
+}
+
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UdwConfig.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UdwConfig.java
new file mode 100644
index 0000000..8b03a9a
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UdwConfig.java
@@ -0,0 +1,10 @@
+package org.nl.acs.udw;
+
+public class UdwConfig {
+
+    //历史记录最大数量
+    public static int max_history_length = 10;
+
+    public UdwConfig() {
+    }
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedData.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedData.java
new file mode 100644
index 0000000..0ebbb7c
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedData.java
@@ -0,0 +1,25 @@
+package org.nl.acs.udw;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class UnifiedData {
+    private Object value;
+    private Date last_modify_date;
+
+    public UnifiedData() {
+        this.last_modify_date = new Date();
+    }
+
+    public UnifiedData(Object value) {
+        this.value = value;
+        this.last_modify_date = new Date();
+    }
+
+    public void changeValue(Object value) {
+        this.value = value;
+        this.last_modify_date = new Date();
+    }
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAccessor.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAccessor.java
new file mode 100644
index 0000000..559373f
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAccessor.java
@@ -0,0 +1,17 @@
+package org.nl.acs.udw;
+
+import java.util.List;
+
+public interface UnifiedDataAccessor {
+    List<String> getAllKey();
+
+    Object getValue(String key);
+
+    void setValue(String key, Object value);
+
+    UnifiedData getUnifiedData(String key);
+
+    List<UnifiedData> getHistoryUnifiedData(String key);
+
+    void setValueWithPersistence(String key, Object value);
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAccessorFactory.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAccessorFactory.java
new file mode 100644
index 0000000..1626862
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAccessorFactory.java
@@ -0,0 +1,20 @@
+package org.nl.acs.udw;
+
+import org.nl.acs.udw.service.impl.UnifiedDataAccessorImpl;
+import org.nl.acs.udw.service.impl.UnifiedDataAppServiceImpl;
+
+public class UnifiedDataAccessorFactory {
+    public UnifiedDataAccessorFactory() {
+    }
+
+    public static UnifiedDataAppService getUnifiedDataAppService() {
+        return UnifiedDataAppServiceImpl.getInstance();
+    }
+
+    public static UnifiedDataAccessor getAccessor(String unified_key) {
+        UnifiedDataAccessorImpl accessor = new UnifiedDataAccessorImpl();
+        accessor.setUnifiedKey(unified_key);
+        accessor.setUnifiedDataService(getUnifiedDataAppService());
+        return accessor;
+    }
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAppService.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAppService.java
new file mode 100644
index 0000000..7c3e429
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/UnifiedDataAppService.java
@@ -0,0 +1,47 @@
+package org.nl.acs.udw;
+
+import cn.hutool.core.util.ObjectUtil;
+import org.nl.acs.udw.service.impl.UnifiedDataUnit;
+
+import java.util.List;
+
+public interface UnifiedDataAppService {
+    /**
+     * 获取所有的key
+     *
+     * @return
+     */
+    List<String> getAllUnifiedKey();
+
+    /**
+     * 根据key获取数据单元
+     *
+     * @param key
+     * @return
+     */
+    UnifiedDataUnit getUnifiedDataUnit(String key);
+
+    UnifiedData getUnifiedData(String var1, String var2);
+
+    Object getValue(String var1, String var2);
+
+    void setValue(String var1, String var2, Object var3);
+
+    void setValueNoLog(String var1, String var2, Object var3);
+
+    List<UnifiedData> getHistoryUnifiedData(String var1, String var2);
+
+    List<String> getAllDataKey(String var1);
+
+    void removeValue(String var1, String var2);
+
+    void setValueWithPersistenceNoLog(String var1, String var2, Object var3);
+
+    void setValueWithPersistence(String var1, String var2, Object var3);
+
+    void removeValueWithPersistence(String var1, String var2);
+
+    static boolean isEquals(Object a, Object b) {
+        return ObjectUtil.equal(a, b);
+    }
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/dto/UdwDto.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/dto/UdwDto.java
new file mode 100644
index 0000000..0a7e198
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/dto/UdwDto.java
@@ -0,0 +1,16 @@
+package org.nl.acs.udw.dto;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 统一数据源管理
+ */
+@Data
+public class UdwDto {
+    private String unified_key;
+    private String key;
+    private Object value;
+    private Date last_modify_date;
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/UdwManageService.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/UdwManageService.java
new file mode 100644
index 0000000..034bd3f
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/UdwManageService.java
@@ -0,0 +1,16 @@
+package org.nl.acs.udw.service;
+
+import com.alibaba.fastjson.JSONObject;
+import org.nl.acs.udw.dto.UdwDto;
+
+import java.util.List;
+
+public interface UdwManageService {
+    /**
+     * 根据条件查询
+     *
+     * @param where
+     * @return
+     */
+    List<UdwDto> queryByConditions(JSONObject where);
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/BadRequestException.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/BadRequestException.java
new file mode 100644
index 0000000..47edd00
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/BadRequestException.java
@@ -0,0 +1,41 @@
+/*
+ *  Copyright 2019-2020 Zheng Jie
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.nl.acs.udw.service.impl;
+
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
+
+/**
+ * @author Zheng Jie
+ * @date 2018-11-23
+ * 统一异常处理
+ */
+@Getter
+public class BadRequestException extends RuntimeException{
+
+    private Integer status = BAD_REQUEST.value();
+
+    public BadRequestException(String msg){
+        super(msg);
+    }
+
+    public BadRequestException(HttpStatus status, String msg){
+        super(msg);
+        this.status = status.value();
+    }
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataAccessorImpl.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataAccessorImpl.java
new file mode 100644
index 0000000..995ab9a
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataAccessorImpl.java
@@ -0,0 +1,47 @@
+package org.nl.acs.udw.service.impl;
+
+import org.nl.acs.udw.UnifiedData;
+import org.nl.acs.udw.UnifiedDataAccessor;
+import org.nl.acs.udw.UnifiedDataAppService;
+
+import java.util.List;
+
+public class UnifiedDataAccessorImpl implements UnifiedDataAccessor {
+    private String unified_key;
+    private UnifiedDataAppService unifiedDataAppService;
+
+    public UnifiedDataAccessorImpl() {
+    }
+
+    public void setUnifiedKey(String unified_key) {
+        this.unified_key = unified_key;
+    }
+
+    public void setUnifiedDataService(UnifiedDataAppService unifiedDataService) {
+        this.unifiedDataAppService = unifiedDataService;
+    }
+
+    public List<String> getAllKey() {
+        return this.unifiedDataAppService.getAllDataKey(this.unified_key);
+    }
+
+    public Object getValue(String key) {
+        return this.unifiedDataAppService.getValue(this.unified_key, key);
+    }
+
+    public void setValue(String key, Object value) {
+        this.unifiedDataAppService.setValue(this.unified_key, key, value);
+    }
+
+    public void setValueWithPersistence(String key, Object value) {
+        this.unifiedDataAppService.setValueWithPersistence(this.unified_key, key, value);
+    }
+
+    public UnifiedData getUnifiedData(String key) {
+        return this.unifiedDataAppService.getUnifiedData(this.unified_key, key);
+    }
+
+    public List<UnifiedData> getHistoryUnifiedData(String key) {
+        return this.unifiedDataAppService.getHistoryUnifiedData(this.unified_key, key);
+    }
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataAppServiceImpl.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataAppServiceImpl.java
new file mode 100644
index 0000000..4c32258
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataAppServiceImpl.java
@@ -0,0 +1,188 @@
+package org.nl.acs.udw.service.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.nl.acs.udw.UdwConfig;
+import org.nl.acs.udw.UnifiedData;
+import org.nl.acs.udw.UnifiedDataAppService;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+public class UnifiedDataAppServiceImpl implements UnifiedDataAppService {
+    public static UnifiedDataAppService unifiedDataAppService;
+    private Map<String, UnifiedDataUnit> factory = Collections.synchronizedMap(new HashMap());
+
+    private UnifiedDataAppServiceImpl() {
+    }
+
+    public static UnifiedDataAppService getInstance() {
+        if (unifiedDataAppService == null) {
+            Class var0 = UnifiedDataAppServiceImpl.class;
+            synchronized (UnifiedDataAppServiceImpl.class) {
+                if (unifiedDataAppService == null) {
+                    unifiedDataAppService = new UnifiedDataAppServiceImpl();
+                }
+            }
+        }
+        return unifiedDataAppService;
+    }
+
+    public List<String> getAllUnifiedKey() {
+        return new ArrayList(this.factory.keySet());
+    }
+
+    public UnifiedDataUnit getUnifiedDataUnit(String unified_key) {
+        UnifiedDataUnit dataUnit = (UnifiedDataUnit) this.factory.get(unified_key);
+        return dataUnit == null ? null : dataUnit;
+    }
+
+    public List<String> getAllDataKey(String unified_key) {
+        UnifiedDataUnit dataUnit = (UnifiedDataUnit) this.factory.get(unified_key);
+        if (dataUnit == null) {
+            return new ArrayList();
+        } else {
+            Map<String, UnifiedData> storage = dataUnit.getStorage();
+            return new ArrayList(storage.keySet());
+        }
+    }
+
+    public UnifiedData getUnifiedData(String unified_key, String key) {
+        UnifiedDataUnit dataUnit = this.getUnifiedDataUnit(unified_key);
+        if (dataUnit == null) {
+            return null;
+        } else {
+            Map<String, UnifiedData> storage = dataUnit.getStorage();
+            return (UnifiedData) storage.get(key);
+        }
+    }
+
+    public Object getValue(String unified_key, String key) {
+        UnifiedData unifiedData = this.getUnifiedData(unified_key, key);
+        return unifiedData == null ? null : unifiedData.getValue();
+    }
+
+    public void removeValueWithPersistence(String unified_key, String key) {
+        UnifiedDataUnit dataUnit = this.getUnifiedDataUnit(unified_key);
+        if (dataUnit != null) {
+            Map<String, UnifiedData> storage = dataUnit.getStorage();
+            if (storage.containsKey(key)) {
+                storage.remove(key);
+            }
+
+            Map<String, List<UnifiedData>> history = dataUnit.getHistory();
+            if (history.containsKey(key)) {
+                history.remove(key);
+            }
+
+            /*PersistenceService persistenceService = PersistenceServiceFactory.getPersistenceService();
+            persistenceService.deleteData(unified_key, key);*/
+        }
+    }
+
+    public void removeValue(String unified_key, String key) {
+        UnifiedDataUnit dataUnit = this.getUnifiedDataUnit(unified_key);
+        if (dataUnit != null) {
+            Map<String, UnifiedData> storage = dataUnit.getStorage();
+            if (storage.containsKey(key)) {
+                storage.remove(key);
+            }
+
+            Map<String, List<UnifiedData>> history = dataUnit.getHistory();
+            if (history.containsKey(key)) {
+                history.remove(key);
+            }
+
+            if (history.size() == 0) {
+                this.factory.remove(unified_key);
+            }
+
+        }
+    }
+
+    public void setValueNoLog(String unified_key, String key, Object value) {
+        this.setValue(unified_key, key, value, false, false);
+    }
+
+    public void setValue(String unified_key, String key, Object value) {
+        this.setValue(unified_key, key, value, false, true);
+    }
+
+    public void setValueWithPersistenceNoLog(String unified_key, String key, Object value) {
+        this.setValue(unified_key, key, value, true, false);
+    }
+
+    public void setValueWithPersistence(String unified_key, String key, Object value) {
+        this.setValue(unified_key, key, value, true, true);
+    }
+
+    public synchronized void setValue(String unified_key, String key, Object value, boolean save, boolean is_log) {
+        if (unified_key == null) {
+            throw new BadRequestException("");
+            //throw new BusinessException(SystemMessage.cant_be_empty, new Object[]{"unified_key"});
+        } else if (key == null) {
+            throw new BadRequestException("");
+            //throw new BusinessException(SystemMessage.cant_be_empty, new Object[]{"key"});
+        } else {
+            if (!this.factory.containsKey(unified_key)) {
+                this.factory.put(unified_key, new UnifiedDataUnit(unified_key));
+            }
+
+            UnifiedDataUnit dataUnit = (UnifiedDataUnit) this.factory.get(unified_key);
+            Map<String, UnifiedData> storage = dataUnit.getStorage();
+            if (!storage.containsKey(key)) {
+                storage.put(key, new UnifiedData());
+            }
+
+            UnifiedData unifiedData = (UnifiedData) storage.get(key);
+            if (!UnifiedDataAppService.isEquals(unifiedData.getValue(), value)) {
+                Map<String, List<UnifiedData>> history = dataUnit.getHistory();
+                List<UnifiedData> historyunifiedData = (List) history.get(key);
+                if (historyunifiedData == null) {
+                    history.put(key, new ArrayList());
+                }
+
+                UnifiedData historydata = new UnifiedData();
+                historydata.setLast_modify_date(unifiedData.getLast_modify_date());
+                historydata.setValue(unifiedData.getValue());
+
+                while (((List) history.get(key)).size() > UdwConfig.max_history_length) {
+                    ((List) history.get(key)).remove(UdwConfig.max_history_length);
+                }
+
+                ((List) history.get(key)).add(0, historydata);
+                Object oldvalue = unifiedData.getValue();
+                unifiedData.changeValue(value);
+                if (save) {
+                    /*PersistenceService persistenceService = PersistenceServiceFactory.getPersistenceService();
+                    persistenceService.saveData(unified_key, key, StringUtl.getString(value));
+                    if (is_log) {
+                        this.businessLogger.setResource(unified_key, unified_key);
+                        this.businessLogger.setMaterial(key, key);
+                        this.businessLogger.setContainer(StringUtl.getString(value));
+                        this.businessLogger.log("统一数据源中: unit: {}, key: {}, 值: {} 更改为 {}。", new Object[]{unified_key, key, oldvalue, value});
+                    }*/
+                }
+
+                if (is_log && key != null && !key.endsWith("heartbeat") && !key.endsWith("distancex") && !key.endsWith("distancey") && !key.endsWith("Xwz") && !key.endsWith("Ywz") && !key.endsWith("Zwz")) {
+                    log.trace("统一数据源中: unit: {}, key: {}, 值: {} 更改为 {}。", new Object[]{unified_key, key, oldvalue, value});
+                }
+            }
+
+        }
+    }
+
+    public List<UnifiedData> getHistoryUnifiedData(String unified_key, String key) {
+        UnifiedDataUnit dataUnit = this.getUnifiedDataUnit(unified_key);
+        if (dataUnit == null) {
+            return new ArrayList();
+        } else {
+            Map<String, List<UnifiedData>> history = dataUnit.getHistory();
+            List<UnifiedData> result = (List) history.get(key);
+            return (List) (result == null ? new ArrayList() : result);
+        }
+    }
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataUnit.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataUnit.java
new file mode 100644
index 0000000..a5866c4
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/udw/service/impl/UnifiedDataUnit.java
@@ -0,0 +1,21 @@
+package org.nl.acs.udw.service.impl;
+
+import lombok.Data;
+import org.nl.acs.udw.UnifiedData;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class UnifiedDataUnit {
+    private String unifiedKey;
+    private Map<String, UnifiedData> storage = Collections.synchronizedMap(new HashMap());
+    private Map<String, List<UnifiedData>> history = Collections.synchronizedMap(new HashMap());
+
+    public UnifiedDataUnit(String unifiedKey) {
+        this.unifiedKey = unifiedKey;
+    }
+
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/util/CallBack.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/util/CallBack.java
new file mode 100644
index 0000000..573c421
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/util/CallBack.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020  the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.nl.acs.util;
+
+/**
+ * @author: liaojinlong
+ * @date: 2020/6/9 17:02
+ * @since: 1.0
+ * @see {@link SpringContextHolder}
+ * 针对某些初始化方法,在SpringContextHolder 初始化前时,<br>
+ * 可提交一个 提交回调任务。<br>
+ * 在SpringContextHolder 初始化后,进行回调使用
+ */
+
+public interface CallBack {
+    /**
+     * 回调执行方法
+     */
+    void executor();
+
+    /**
+     * 本回调任务名称
+     * @return /
+     */
+    default String getCallBackName() {
+        return Thread.currentThread().getId() + ":" + this.getClass().getName();
+    }
+}
+
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/acs/util/SpringContextHolder.java b/acs/hd/nladmin-system/src/main/java/org/nl/acs/util/SpringContextHolder.java
new file mode 100644
index 0000000..86d9992
--- /dev/null
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/acs/util/SpringContextHolder.java
@@ -0,0 +1,157 @@
+/*
+ *  Copyright 2019-2020 Zheng Jie
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.nl.acs.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.env.Environment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Jie
+ * @date 2019-01-07
+ */
+@Slf4j
+public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
+
+    private static ApplicationContext applicationContext = null;
+    //数据库连接的bean名字
+    public  static   String dataSourceBeanName="dataSource";
+    private static final List<CallBack> CALL_BACKS = new ArrayList<>();
+    private static boolean addCallback = true;
+
+    /**
+     * 针对 某些初始化方法,在SpringContextHolder 未初始化时 提交回调方法。
+     * 在SpringContextHolder 初始化后,进行回调使用
+     *
+     * @param callBack 回调函数
+     */
+    public synchronized static void addCallBacks(CallBack callBack) {
+        if (addCallback) {
+            SpringContextHolder.CALL_BACKS.add(callBack);
+        } else {
+            log.warn("CallBack:{} 已无法添加!立即执行", callBack.getCallBackName());
+            callBack.executor();
+        }
+    }
+    public static ApplicationContext getApplicationContext() {
+        try {
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return  applicationContext;
+
+    }
+
+    /**
+     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) {
+        assertContextInjected();
+        return (T) applicationContext.getBean(name);
+    }
+
+    /**
+     * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+     */
+    public static <T> T getBean(Class<T> requiredType) {
+        assertContextInjected();
+        return applicationContext.getBean(requiredType);
+    }
+
+    /**
+     * 获取SpringBoot 配置信息
+     *
+     * @param property     属性key
+     * @param defaultValue 默认值
+     * @param requiredType 返回类型
+     * @return /
+     */
+    public static <T> T getProperties(String property, T defaultValue, Class<T> requiredType) {
+        T result = defaultValue;
+        try {
+            result = getBean(Environment.class).getProperty(property, requiredType);
+        } catch (Exception ignored) {}
+        return result;
+    }
+
+    /**
+     * 获取SpringBoot 配置信息
+     *
+     * @param property 属性key
+     * @return /
+     */
+    public static String getProperties(String property) {
+        return getProperties(property, null, String.class);
+    }
+
+    /**
+     * 获取SpringBoot 配置信息
+     *
+     * @param property     属性key
+     * @param requiredType 返回类型
+     * @return /
+     */
+    public static <T> T getProperties(String property, Class<T> requiredType) {
+        return getProperties(property, null, requiredType);
+    }
+
+    /**
+     * 检查ApplicationContext不为空.
+     */
+    private static void assertContextInjected() {
+        if (applicationContext == null) {
+            throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
+                    ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
+        }
+    }
+
+    /**
+     * 清除SpringContextHolder中的ApplicationContext为Null.
+     */
+    private static void clearHolder() {
+        log.debug("清除SpringContextHolder中的ApplicationContext:"
+                + applicationContext);
+        applicationContext = null;
+    }
+
+    @Override
+    public void destroy() {
+        SpringContextHolder.clearHolder();
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        if (SpringContextHolder.applicationContext != null) {
+            log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
+        }
+        SpringContextHolder.applicationContext = applicationContext;
+        if (addCallback) {
+            for (CallBack callBack : SpringContextHolder.CALL_BACKS) {
+                callBack.executor();
+            }
+            CALL_BACKS.clear();
+        }
+        SpringContextHolder.addCallback = false;
+    }
+}
diff --git a/acs/hd/nladmin-system/src/main/java/org/nl/start/auto/run/NDCSocketConnectionAutoRun.java b/acs/hd/nladmin-system/src/main/java/org/nl/start/auto/run/NDCSocketConnectionAutoRun.java
index 5a61842..c6e5ccc 100644
--- a/acs/hd/nladmin-system/src/main/java/org/nl/start/auto/run/NDCSocketConnectionAutoRun.java
+++ b/acs/hd/nladmin-system/src/main/java/org/nl/start/auto/run/NDCSocketConnectionAutoRun.java
@@ -220,17 +220,32 @@ public class NDCSocketConnectionAutoRun extends AbstractAutoRunnable {
                             //检测站点smart200
                             if (device.getDeviceDriver() instanceof StandardInspectSiteSmartDeviceDriver) {
                                 standardInspectSiteSmartDeviceDriver = (StandardInspectSiteSmartDeviceDriver) device.getDeviceDriver();
-                                inst.setExecute_status("1");
-                                instructionService.update(inst);
-                                data = AgvService.sendAgvOneModeInst(phase, index, 0);
+                                log.info("flag:"+standardInspectSiteSmartDeviceDriver.getFlag());
+                                log.info("time:"+standardInspectSiteSmartDeviceDriver.getTime());
+                                log.info("Product_code:"+standardInspectSiteSmartDeviceDriver.getProduct_code());
+                                log.info("Product_specifications:"+standardInspectSiteSmartDeviceDriver.getProduct_specifications());
+                                log.info("Weight:"+standardInspectSiteSmartDeviceDriver.getWeight());
+                                if("1".equals(standardInspectSiteSmartDeviceDriver.getFlag())) {
+                                    inst.setExecute_status("1");
+                                    instructionService.update(inst);
+                                    data = AgvService.sendAgvOneModeInst(phase, index, 0);
+                                }
                             }
 
                         }
                         // 取货完成请求离开
                         else if (phase == 0x05) {
-                            if (ObjectUtil.isEmpty(inst)) {
-                                logServer.deviceExecuteLog("未找到指令号对应的指令:", "", "", String.valueOf(ikey));
-                                break;
+//                            if (ObjectUtil.isEmpty(inst)) {
+//                                logServer.deviceExecuteLog("未找到指令号对应的指令:", "", "", String.valueOf(ikey));
+//                                break;
+//                            }
+                            //普通站点
+                            if (device.getDeviceDriver() instanceof StandardOrdinarySiteDeviceDriver) {
+                                standardOrdinarySiteDeviceDriver = (StandardOrdinarySiteDeviceDriver) device.getDeviceDriver();
+                                inst.setExecute_status("5");
+                                instructionService.update(inst);
+                                data = AgvService.sendAgvOneModeInst(phase, index, 0);
+                                flag = true;
                             }
                             if (device.getDeviceDriver() instanceof StandardInspectSiteDeviceDriver) {
                                 standardInspectSiteDeviceDriver = (StandardInspectSiteDeviceDriver) device.getDeviceDriver();
@@ -312,6 +327,14 @@ public class NDCSocketConnectionAutoRun extends AbstractAutoRunnable {
                                     logServer.deviceExecuteLog(device_code, "", "", "AGV请求放货设备{}有货,无法反馈");
                                 }
                             }
+                            if (device.getDeviceDriver() instanceof StandardOrdinarySiteDeviceDriver) {
+                                standardOrdinarySiteDeviceDriver = (StandardOrdinarySiteDeviceDriver) device.getDeviceDriver();
+                                inst.setExecute_status("3");
+                                instructionService.update(inst);
+                                data = AgvService.sendAgvOneModeInst(phase, index, 0);
+                                flag = true;
+
+                            }
                             // 检验取放货条件
                             JSONObject agv_check = device_extra_table
                                     .query("is_delete = '0' AND extra_code = 'agv_check' AND device_code = '" + device.getDevice_code() + "'")
diff --git a/lms/hd/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/service/impl/SendMaterialServiceImpl.java b/lms/hd/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/service/impl/SendMaterialServiceImpl.java
index 9765056..3198acc 100644
--- a/lms/hd/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/service/impl/SendMaterialServiceImpl.java
+++ b/lms/hd/nladmin-system/src/main/java/org/nl/wms/pda/sendmaterial/service/impl/SendMaterialServiceImpl.java
@@ -11,7 +11,10 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.nl.modules.system.util.CodeUtil;
 import org.nl.utils.SecurityUtils;
+import org.nl.utils.SpringContextHolder;
 import org.nl.wms.pda.sendmaterial.service.SendMaterialService;
+import org.nl.wms.sch.service.dto.PointDto;
+import org.nl.wms.sch.service.impl.PointServiceImpl;
 import org.nl.wms.sch.tasks.SendMaterialTask;
 import org.nl.wms.st.inbill.service.dto.RegionioDto;
 import org.nl.wql.WQL;
@@ -146,6 +149,22 @@ public class SendMaterialServiceImpl implements SendMaterialService {
             // 创建任务并自动下发
             String taskId = sendMaterialTask.createTask(param);
 
+            PointServiceImpl pointService = SpringContextHolder.getBean(PointServiceImpl.class);
+            PointDto nextPointDto = pointService.findByCode(nextPointCode);
+            PointDto startPointDto = pointService.findByCode(startPointCode);
+            // 如果终点为仓位(待检区),则需要添加库存
+            if (StrUtil.equals(nextPointDto.getPoint_type(), "01")) {
+                JSONObject struct = new JSONObject();
+                struct.put("stockrecord_id", IdUtil.getSnowflake(1, 1).nextId());
+                struct.put("struct_id", nextPointDto.getPoint_id());
+                struct.put("struct_code", nextPointDto.getPoint_code());
+                struct.put("struct_name", nextPointDto.getPoint_name());
+                struct.put("region_id", startPointDto.getRegion_id());
+                struct.put("quality_scode", "00");// 待检品
+                struct.put("instorage_time", DateUtil.now());
+                WQLObject.getWQLObject("st_ivt_structivt").insert(struct);
+            }
+
             // 创建并下发成功后更新搬运记录
             JSONObject json = new JSONObject();
             json.put("task_id", taskId);
diff --git a/lms/hd/nladmin-system/src/main/resources/logback-spring.xml b/lms/hd/nladmin-system/src/main/resources/logback-spring.xml
index d74fc23..276a6a4 100644
--- a/lms/hd/nladmin-system/src/main/resources/logback-spring.xml
+++ b/lms/hd/nladmin-system/src/main/resources/logback-spring.xml
@@ -12,8 +12,13 @@ https://juejin.cn/post/6844903775631572999
     <contextName>nlAdmin</contextName>
     <property name="log.charset" value="utf-8"/>
     <property name="log.pattern"
-              value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/>
+              value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss.SSS}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/>
     <springProperty scope="context" name="logPath" source="logging.file.path" defaultValue="logs"/>
+    <springProperty scope="context" name="lokiUrl" source="loki.url"/>
+    <springProperty scope="context" name="systemName" source="loki.systemName"/>
+    <property name="LOKI_URL" value="${lokiUrl}"/>
+    <property name="SYSTEM_NAME" value="${systemName}"/>
+    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
     <property name="LOG_HOME" value="${logPath}"/>
     <!--引入默认的一些设置-->
 <!--    <include resource="log/AutoCreateInst.xml"/>-->