From 310a1841c3ba3331529d5791605ef1fba24c3ecd Mon Sep 17 00:00:00 2001
From: chen.llin <1442464845@qq.comm>
Date: 星期日, 18 一月 2026 14:56:33 +0800
Subject: [PATCH] 倾斜度

---
 src/main/java/com/zy/service/CrnTiltRecordService.java          |   11 
 src/main/java/com/zy/controller/CrnController.java              |   21 +
 src/main/java/com/rfid/uhf288/Device.java                       |    6 
 src/main/java/com/zy/core/properties/ScheduleProperties.java    |   23 +
 src/main/java/com/zy/mapper/CrnTiltRecordMapper.java            |   15 +
 src/main/java/com/zy/service/impl/CrnTiltRecordServiceImpl.java |   15 +
 src/main/java/com/zy/task/CrnTiltRecordTask.java                |  416 ++++++++++++++++++++++++++++++++++
 src/main/java/com/zy/entity/CrnTiltRecord.java                  |  200 ++++++++++++++++
 8 files changed, 703 insertions(+), 4 deletions(-)

diff --git a/src/main/java/com/rfid/uhf288/Device.java b/src/main/java/com/rfid/uhf288/Device.java
index ee221d2..f6b26a2 100644
--- a/src/main/java/com/rfid/uhf288/Device.java
+++ b/src/main/java/com/rfid/uhf288/Device.java
@@ -48,9 +48,9 @@
 			// 鏂规硶1: 浣跨敤缁濆璺緞鐩存帴鍔犺浇DLL
 			try {
 			// 浣跨敤鐪熷疄璺緞鍔犺浇DLL
-			String projectBaseDir = "D:\\apache-tomcat-8.5.57\\webapps";
-			String mainDllPath = projectBaseDir + "\\wcs\\WEB-INF\\classes\\lib\\" + mainDllName;
-			String depDllPath = projectBaseDir + "\\wcs\\WEB-INF\\classes\\lib\\" + depDllName;
+			String projectBaseDir = "D:\\apache-tomcat-8.5.57";
+			String mainDllPath = projectBaseDir + "\\webapps\\" + mainDllName;
+			String depDllPath = projectBaseDir + "\\webapps\\" + depDllName;
 			
 			File mainDllFile = new File(mainDllPath);
 			File depDllFile = new File(depDllPath);
diff --git a/src/main/java/com/zy/controller/CrnController.java b/src/main/java/com/zy/controller/CrnController.java
index 0a83618..079e063 100644
--- a/src/main/java/com/zy/controller/CrnController.java
+++ b/src/main/java/com/zy/controller/CrnController.java
@@ -35,11 +35,13 @@
 import com.zy.core.properties.SlaveProperties;
 import com.zy.core.properties.SystemProperties;
 import com.zy.core.thread.RgvThread;
+import com.zy.task.CrnTiltRecordTask;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.util.ArrayList;
@@ -68,6 +70,8 @@
     private MainServiceImpl mainService;
     @Autowired
     private LocMastService locMastService;
+    @Autowired
+    private CrnTiltRecordTask crnTiltRecordTask;
 
 
     @ManagerAuth(memo = "杩涜涓殑鍛戒护")
@@ -529,5 +533,20 @@
         return false;
     }
 
-
+    /**
+     * 鎵嬪姩瑙﹀彂鍫嗗灈鏈哄�炬枩搴﹁褰�
+     * @param crnNo 鍫嗗灈鏈虹紪鍙凤紝濡傛灉涓虹┖鍒欒褰曟墍鏈夊爢鍨涙満
+     * @return
+     */
+    @PostMapping("/tiltRecord/manual")
+    @ManagerAuth
+    public R manualTiltRecord(@RequestParam(required = false) Integer crnNo) {
+        try {
+            crnTiltRecordTask.manualRecord(crnNo);
+            return R.ok("鎵嬪姩瑙﹀彂鍊炬枩搴﹁褰曟垚鍔�");
+        } catch (Exception e) {
+            log.error("鎵嬪姩瑙﹀彂鍊炬枩搴﹁褰曞け璐�", e);
+            return R.error("鎵嬪姩瑙﹀彂澶辫触锛�" + e.getMessage());
+        }
+    }
 }
diff --git a/src/main/java/com/zy/core/properties/ScheduleProperties.java b/src/main/java/com/zy/core/properties/ScheduleProperties.java
new file mode 100644
index 0000000..ec074f1
--- /dev/null
+++ b/src/main/java/com/zy/core/properties/ScheduleProperties.java
@@ -0,0 +1,23 @@
+package com.zy.core.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 瀹氭椂浠诲姟閰嶇疆
+ * Created on 2024
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "schedule")
+public class ScheduleProperties {
+
+    /**
+     * 瀹氭椂浠诲姟鎬诲紑鍏�
+     * true: 鍚敤鎵�鏈夊畾鏃朵换鍔★紙榛樿锛�
+     * false: 绂佺敤鎵�鏈夊畾鏃朵换鍔�
+     */
+    private boolean enabled = true;
+
+}
diff --git a/src/main/java/com/zy/entity/CrnTiltRecord.java b/src/main/java/com/zy/entity/CrnTiltRecord.java
new file mode 100644
index 0000000..eda434d
--- /dev/null
+++ b/src/main/java/com/zy/entity/CrnTiltRecord.java
@@ -0,0 +1,200 @@
+package com.zy.entity;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.baomidou.mybatisplus.enums.IdType;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 鍫嗗灈鏈哄�炬枩搴﹁褰曞疄浣撶被
+ * 鐢ㄤ簬瀛樺偍姣忓懆璁板綍鐨勫爢鍨涙満鍊炬枩搴︽暟鎹�
+ */
+@TableName("asr_crn_tilt_record")
+public class CrnTiltRecord implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭ID
+     */
+    @ApiModelProperty(value = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鍫嗗灈鏈虹紪鍙�
+     */
+    @ApiModelProperty(value = "鍫嗗灈鏈虹紪鍙�")
+    @TableField("crn_no")
+    private Integer crnNo;
+
+    /**
+     * 鍊炬枩搴﹀�硷紙搴︽垨寮у害锛屾牴鎹疄闄呬紶鎰熷櫒鍗曚綅锛�
+     */
+    @ApiModelProperty(value = "鍊炬枩搴﹀��")
+    @TableField("tilt_value")
+    private Float tiltValue;
+
+    /**
+     * X鏂瑰悜鍊炬枩搴�
+     */
+    @ApiModelProperty(value = "X鏂瑰悜鍊炬枩搴�")
+    @TableField("tilt_x")
+    private Float tiltX;
+
+    /**
+     * Y鏂瑰悜鍊炬枩搴�
+     */
+    @ApiModelProperty(value = "Y鏂瑰悜鍊炬枩搴�")
+    @TableField("tilt_y")
+    private Float tiltY;
+
+    /**
+     * Z鏂瑰悜鍊炬枩搴�
+     */
+    @ApiModelProperty(value = "Z鏂瑰悜鍊炬枩搴�")
+    @TableField("tilt_z")
+    private Float tiltZ;
+
+    /**
+     * 璁板綍鏃ユ湡锛堟瘡鍛ㄨ褰曚竴娆★級
+     */
+    @ApiModelProperty(value = "璁板綍鏃ユ湡")
+    @TableField("record_date")
+    private Date recordDate;
+
+    /**
+     * 璁板綍鏃堕棿
+     */
+    @ApiModelProperty(value = "璁板綍鏃堕棿")
+    @TableField("record_time")
+    private Date recordTime;
+
+    /**
+     * 涓婃璁板綍鐨勫�炬枩搴﹀�硷紙鐢ㄤ簬瀵规瘮锛�
+     */
+    @ApiModelProperty(value = "涓婃璁板綍鐨勫�炬枩搴﹀��")
+    @TableField("prev_tilt_value")
+    private Float prevTiltValue;
+
+    /**
+     * 鍊炬枩搴﹀彉鍖栭噺锛堝綋鍓嶅��-涓婃鍊硷級
+     */
+    @ApiModelProperty(value = "鍊炬枩搴﹀彉鍖栭噺")
+    @TableField("tilt_change")
+    private Float tiltChange;
+
+    /**
+     * 璁板綍绫诲瀷锛欰UTO-鑷姩璁板綍锛孧ANUAL-鎵嬪姩瑙﹀彂
+     */
+    @ApiModelProperty(value = "璁板綍绫诲瀷")
+    @TableField("record_type")
+    private String recordType;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Integer getCrnNo() {
+        return crnNo;
+    }
+
+    public void setCrnNo(Integer crnNo) {
+        this.crnNo = crnNo;
+    }
+
+    public Float getTiltValue() {
+        return tiltValue;
+    }
+
+    public void setTiltValue(Float tiltValue) {
+        this.tiltValue = tiltValue;
+    }
+
+    public Float getTiltX() {
+        return tiltX;
+    }
+
+    public void setTiltX(Float tiltX) {
+        this.tiltX = tiltX;
+    }
+
+    public Float getTiltY() {
+        return tiltY;
+    }
+
+    public void setTiltY(Float tiltY) {
+        this.tiltY = tiltY;
+    }
+
+    public Float getTiltZ() {
+        return tiltZ;
+    }
+
+    public void setTiltZ(Float tiltZ) {
+        this.tiltZ = tiltZ;
+    }
+
+    public Date getRecordDate() {
+        return recordDate;
+    }
+
+    public void setRecordDate(Date recordDate) {
+        this.recordDate = recordDate;
+    }
+
+    public String getRecordDate$() {
+        if (recordDate == null) {
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd").format(recordDate);
+    }
+
+    public Date getRecordTime() {
+        return recordTime;
+    }
+
+    public void setRecordTime(Date recordTime) {
+        this.recordTime = recordTime;
+    }
+
+    public String getRecordTime$() {
+        if (recordTime == null) {
+            return "";
+        }
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(recordTime);
+    }
+
+    public Float getPrevTiltValue() {
+        return prevTiltValue;
+    }
+
+    public void setPrevTiltValue(Float prevTiltValue) {
+        this.prevTiltValue = prevTiltValue;
+    }
+
+    public Float getTiltChange() {
+        return tiltChange;
+    }
+
+    public void setTiltChange(Float tiltChange) {
+        this.tiltChange = tiltChange;
+    }
+
+    public String getRecordType() {
+        return recordType;
+    }
+
+    public void setRecordType(String recordType) {
+        this.recordType = recordType;
+    }
+}
diff --git a/src/main/java/com/zy/mapper/CrnTiltRecordMapper.java b/src/main/java/com/zy/mapper/CrnTiltRecordMapper.java
new file mode 100644
index 0000000..e0dbb45
--- /dev/null
+++ b/src/main/java/com/zy/mapper/CrnTiltRecordMapper.java
@@ -0,0 +1,15 @@
+package com.zy.mapper;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.zy.entity.CrnTiltRecord;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 鍫嗗灈鏈哄�炬枩搴﹁褰� Mapper
+ */
+@Mapper
+@Repository
+public interface CrnTiltRecordMapper extends BaseMapper<CrnTiltRecord> {
+
+}
diff --git a/src/main/java/com/zy/service/CrnTiltRecordService.java b/src/main/java/com/zy/service/CrnTiltRecordService.java
new file mode 100644
index 0000000..d623208
--- /dev/null
+++ b/src/main/java/com/zy/service/CrnTiltRecordService.java
@@ -0,0 +1,11 @@
+package com.zy.service;
+
+import com.baomidou.mybatisplus.service.IService;
+import com.zy.entity.CrnTiltRecord;
+
+/**
+ * 鍫嗗灈鏈哄�炬枩搴﹁褰� Service 鎺ュ彛
+ */
+public interface CrnTiltRecordService extends IService<CrnTiltRecord> {
+
+}
diff --git a/src/main/java/com/zy/service/impl/CrnTiltRecordServiceImpl.java b/src/main/java/com/zy/service/impl/CrnTiltRecordServiceImpl.java
new file mode 100644
index 0000000..69be47c
--- /dev/null
+++ b/src/main/java/com/zy/service/impl/CrnTiltRecordServiceImpl.java
@@ -0,0 +1,15 @@
+package com.zy.service.impl;
+
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.zy.entity.CrnTiltRecord;
+import com.zy.mapper.CrnTiltRecordMapper;
+import com.zy.service.CrnTiltRecordService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 鍫嗗灈鏈哄�炬枩搴﹁褰� Service 瀹炵幇绫�
+ */
+@Service
+public class CrnTiltRecordServiceImpl extends ServiceImpl<CrnTiltRecordMapper, CrnTiltRecord> implements CrnTiltRecordService {
+
+}
diff --git a/src/main/java/com/zy/task/CrnTiltRecordTask.java b/src/main/java/com/zy/task/CrnTiltRecordTask.java
new file mode 100644
index 0000000..62c8846
--- /dev/null
+++ b/src/main/java/com/zy/task/CrnTiltRecordTask.java
@@ -0,0 +1,416 @@
+package com.zy.task;
+
+import HslCommunication.Core.Types.OperateResult;
+import HslCommunication.Core.Types.OperateResultExOne;
+import HslCommunication.Profinet.Siemens.SiemensPLCS;
+import HslCommunication.Profinet.Siemens.SiemensS7Net;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.zy.core.model.CrnSlave;
+import com.zy.core.properties.SlaveProperties;
+import com.zy.entity.CrnTiltRecord;
+import com.zy.service.CrnTiltRecordService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 鍫嗗灈鏈哄�炬枩搴﹁褰曞畾鏃朵换鍔�
+ * 姣忓懆璁板綍涓�娆″爢鍨涙満鐨勫�炬枩搴︽暟鎹�
+ * 
+ * 璇存槑锛�
+ * 1. 鏍规嵁"璐ф灦鍊炬枩搴�.txt"鍜�"鍫嗗灈鏈篲DB101鍙戦�亀cs淇℃伅.pdf"鏂囨。
+ * 2. 鍊炬枩搴︽暟鎹粠 PLC 鐨� DB101 鏁版嵁鍧楄鍙栵紙鍏蜂綋鍋忕Щ閲忛渶瑕佹牴鎹疄闄呬紶鎰熷櫒閰嶇疆纭畾锛�
+ * 3. 姣忓懆鎵ц涓�娆★紙榛樿姣忓懆涓�鍑屾櫒2鐐规墽琛岋級
+ */
+@Slf4j
+@Component
+public class CrnTiltRecordTask implements ApplicationListener<ContextRefreshedEvent> {
+
+    @Autowired
+    private SlaveProperties slaveProperties;
+
+    @Autowired
+    private CrnTiltRecordService crnTiltRecordService;
+
+    private boolean startupRecordExecuted = false;
+
+    /**
+     * 绯荤粺鍚姩鍚庤嚜鍔ㄨ褰曚竴娆″�炬枩搴︽暟鎹�
+     * 浣跨敤 ApplicationListener 鐩戝惉 ContextRefreshedEvent锛岀‘淇濆湪 Spring 涓婁笅鏂囧畬鍏ㄥ垵濮嬪寲鍚庢墽琛�
+     */
+    @Override
+    public void onApplicationEvent(ContextRefreshedEvent event) {
+        // 閬垮厤閲嶅鎵ц锛圫pring 鍙兘浼氳Е鍙戝娆′簨浠讹級
+        if (startupRecordExecuted) {
+            return;
+        }
+        startupRecordExecuted = true;
+        
+        log.info("========== 绯荤粺鍚姩锛屽紑濮嬫墽琛屽爢鍨涙満鍊炬枩搴﹀惎鍔ㄨ褰� ==========");
+        
+        // 寤惰繜10绉掓墽琛岋紝纭繚绯荤粺瀹屽叏鍚姩锛屾暟鎹簱杩炴帴绛夐兘宸插氨缁�
+        new Thread(() -> {
+            try {
+                log.info("鍊炬枩搴﹀惎鍔ㄨ褰曚换鍔″皢鍦�10绉掑悗鎵ц...");
+                Thread.sleep(10000);
+                log.info("寮�濮嬫墽琛屽�炬枩搴﹀惎鍔ㄨ褰曚换鍔�...");
+                recordTiltDataOnStartup();
+            } catch (InterruptedException e) {
+                log.error("鍚姩璁板綍浠诲姟琚腑鏂�", e);
+            } catch (Exception e) {
+                log.error("鍚姩璁板綍浠诲姟鎵ц寮傚父", e);
+            }
+        }, "CrnTiltRecord-Startup").start();
+    }
+
+    /**
+     * 鍚姩鏃惰褰曞�炬枩搴︽暟鎹紙涓嶆鏌ュ綋澶╂槸鍚﹀凡璁板綍锛�
+     */
+    private void recordTiltDataOnStartup() {
+        log.info("========== 寮�濮嬫墽琛屽�炬枩搴﹀惎鍔ㄨ褰� ==========");
+        try {
+            if (slaveProperties == null) {
+                log.error("SlaveProperties 鏈敞鍏ワ紝璺宠繃鍚姩鍊炬枩搴﹁褰�");
+                return;
+            }
+            
+            if (crnTiltRecordService == null) {
+                log.error("CrnTiltRecordService 鏈敞鍏ワ紝璺宠繃鍚姩鍊炬枩搴﹁褰�");
+                return;
+            }
+            
+            List<CrnSlave> crnSlaves = slaveProperties.getCrn();
+            if (crnSlaves == null || crnSlaves.isEmpty()) {
+                log.warn("娌℃湁閰嶇疆鍫嗗灈鏈猴紝璺宠繃鍚姩鍊炬枩搴﹁褰�");
+                return;
+            }
+            
+            log.info("鎵惧埌 {} 鍙板爢鍨涙満锛屽紑濮嬭褰曞�炬枩搴︽暟鎹�", crnSlaves.size());
+
+            Date recordDate = new Date();
+            Calendar cal = Calendar.getInstance();
+            cal.setTime(recordDate);
+            cal.set(Calendar.HOUR_OF_DAY, 0);
+            cal.set(Calendar.MINUTE, 0);
+            cal.set(Calendar.SECOND, 0);
+            cal.set(Calendar.MILLISECOND, 0);
+            Date recordDateOnly = cal.getTime();
+
+            int successCount = 0;
+            int failCount = 0;
+
+            for (CrnSlave crnSlave : crnSlaves) {
+                try {
+                    // 璇诲彇鍊炬枩搴︽暟鎹�
+                    CrnTiltRecord record = readTiltDataFromPLC(crnSlave);
+                    if (record != null) {
+                        record.setCrnNo(crnSlave.getId());
+                        record.setRecordDate(recordDateOnly);
+                        record.setRecordTime(recordDate);
+                        record.setRecordType("STARTUP"); // 鍚姩鏃惰褰�
+
+                        // 鑾峰彇涓婃璁板綍鐢ㄤ簬瀵规瘮
+                        EntityWrapper<CrnTiltRecord> lastWrapper = new EntityWrapper<>();
+                        lastWrapper.eq("crn_no", crnSlave.getId());
+                        lastWrapper.orderBy("record_date", false);
+                        lastWrapper.orderBy("record_time", false);
+                        lastWrapper.last("OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY");
+                        CrnTiltRecord lastRecord = crnTiltRecordService.selectOne(lastWrapper);
+                        
+                        if (lastRecord != null && lastRecord.getTiltValue() != null) {
+                            // 瀵规瘮鍊炬枩搴�
+                            record.setPrevTiltValue(lastRecord.getTiltValue());
+                            if (record.getTiltValue() != null) {
+                                float change = record.getTiltValue() - lastRecord.getTiltValue();
+                                record.setTiltChange(change);
+                                log.info("鍫嗗灈鏈簕}鍚姩鍊炬枩搴﹀姣旓細褰撳墠鍊�={}, 涓婃鍊�={}, 鍙樺寲閲�={}", 
+                                    crnSlave.getId(), record.getTiltValue(), 
+                                    lastRecord.getTiltValue(), change);
+                            }
+                        }
+
+                        // 淇濆瓨鍒版暟鎹簱
+                        if (crnTiltRecordService.insert(record)) {
+                            successCount++;
+                            log.info("鍫嗗灈鏈簕}鍚姩鍊炬枩搴﹁褰曟垚鍔燂細鍊炬枩搴�={}, X={}, Y={}, Z={}, 鍙樺寲閲�={}", 
+                                crnSlave.getId(), record.getTiltValue(), 
+                                record.getTiltX(), record.getTiltY(), record.getTiltZ(),
+                                record.getTiltChange() != null ? record.getTiltChange() : 0);
+                        } else {
+                            failCount++;
+                            log.error("鍫嗗灈鏈簕}鍚姩鍊炬枩搴﹁褰曚繚瀛樺け璐�", crnSlave.getId());
+                        }
+                    } else {
+                        failCount++;
+                        log.error("鍫嗗灈鏈簕}鍚姩鍊炬枩搴︽暟鎹鍙栧け璐�", crnSlave.getId());
+                    }
+                } catch (Exception e) {
+                    failCount++;
+                    log.error("鍫嗗灈鏈簕}鍚姩鍊炬枩搴﹁褰曞紓甯�", crnSlave.getId(), e);
+                }
+            }
+
+            log.info("鍫嗗灈鏈哄�炬枩搴﹀惎鍔ㄨ褰曞畬鎴愶細鎴愬姛{}鏉★紝澶辫触{}鏉�", successCount, failCount);
+        } catch (Exception e) {
+            log.error("鍫嗗灈鏈哄�炬枩搴﹀惎鍔ㄨ褰曚换鍔℃墽琛屽紓甯�", e);
+        }
+    }
+
+    /**
+     * 姣忓懆璁板綍涓�娆″爢鍨涙満鍊炬枩搴︽暟鎹�
+     * cron琛ㄨ揪寮忥細0 0 2 ? * MON 琛ㄧず姣忓懆涓�鍑屾櫒2鐐规墽琛�
+     * 濡傛灉闇�瑕佷慨鏀规墽琛屾椂闂达紝鍙互璋冩暣cron琛ㄨ揪寮�
+     */
+    @Scheduled(cron = "0 0 2 ? * MON")
+    public void recordCrnTiltData() {
+        log.info("寮�濮嬫墽琛屽爢鍨涙満鍊炬枩搴﹁褰曚换鍔�...");
+        
+        try {
+            List<CrnSlave> crnSlaves = slaveProperties.getCrn();
+            if (crnSlaves == null || crnSlaves.isEmpty()) {
+                log.warn("娌℃湁閰嶇疆鍫嗗灈鏈猴紝璺宠繃鍊炬枩搴﹁褰�");
+                return;
+            }
+
+            Date recordDate = new Date();
+            Calendar cal = Calendar.getInstance();
+            cal.setTime(recordDate);
+            // 璁剧疆涓哄綋澶╃殑寮�濮嬫椂闂达紙00:00:00锛�
+            cal.set(Calendar.HOUR_OF_DAY, 0);
+            cal.set(Calendar.MINUTE, 0);
+            cal.set(Calendar.SECOND, 0);
+            cal.set(Calendar.MILLISECOND, 0);
+            Date recordDateOnly = cal.getTime();
+
+            int successCount = 0;
+            int failCount = 0;
+
+            for (CrnSlave crnSlave : crnSlaves) {
+                try {
+                    // 妫�鏌ユ湰鍛ㄦ槸鍚﹀凡缁忚褰曡繃
+                    EntityWrapper<CrnTiltRecord> wrapper = new EntityWrapper<>();
+                    wrapper.eq("crn_no", crnSlave.getId());
+                    wrapper.ge("record_date", recordDateOnly);
+                    wrapper.le("record_date", new Date(recordDateOnly.getTime() + 24 * 60 * 60 * 1000 - 1));
+                    
+                    int count = crnTiltRecordService.selectCount(wrapper);
+                    if (count > 0) {
+                        log.info("鍫嗗灈鏈簕}鏈懆宸茶褰曡繃鍊炬枩搴︽暟鎹紝璺宠繃", crnSlave.getId());
+                        continue;
+                    }
+
+                    // 璇诲彇鍊炬枩搴︽暟鎹�
+                    CrnTiltRecord record = readTiltDataFromPLC(crnSlave);
+                    if (record != null) {
+                        record.setCrnNo(crnSlave.getId());
+                        record.setRecordDate(recordDateOnly);
+                        record.setRecordTime(recordDate);
+                        record.setRecordType("AUTO"); // 鑷姩璁板綍
+
+                        // 鑾峰彇涓婃璁板綍鐢ㄤ簬瀵规瘮
+                        EntityWrapper<CrnTiltRecord> lastWrapper = new EntityWrapper<>();
+                        lastWrapper.eq("crn_no", crnSlave.getId());
+                        lastWrapper.orderBy("record_date", false);
+                        lastWrapper.orderBy("record_time", false);
+                        lastWrapper.last("OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY");
+                        CrnTiltRecord lastRecord = crnTiltRecordService.selectOne(lastWrapper);
+                        
+                        if (lastRecord != null && lastRecord.getTiltValue() != null) {
+                            // 瀵规瘮鍊炬枩搴�
+                            record.setPrevTiltValue(lastRecord.getTiltValue());
+                            if (record.getTiltValue() != null) {
+                                float change = record.getTiltValue() - lastRecord.getTiltValue();
+                                record.setTiltChange(change);
+                                log.info("鍫嗗灈鏈簕}鍊炬枩搴﹀姣旓細褰撳墠鍊�={}, 涓婃鍊�={}, 鍙樺寲閲�={}", 
+                                    crnSlave.getId(), record.getTiltValue(), 
+                                    lastRecord.getTiltValue(), change);
+                            }
+                        }
+
+                        // 淇濆瓨鍒版暟鎹簱
+                        if (crnTiltRecordService.insert(record)) {
+                            successCount++;
+                            log.info("鍫嗗灈鏈簕}鍊炬枩搴﹁褰曟垚鍔燂細鍊炬枩搴�={}, X={}, Y={}, Z={}, 鍙樺寲閲�={}", 
+                                crnSlave.getId(), record.getTiltValue(), 
+                                record.getTiltX(), record.getTiltY(), record.getTiltZ(),
+                                record.getTiltChange() != null ? record.getTiltChange() : 0);
+                        } else {
+                            failCount++;
+                            log.error("鍫嗗灈鏈簕}鍊炬枩搴﹁褰曚繚瀛樺け璐�", crnSlave.getId());
+                        }
+                    } else {
+                        failCount++;
+                        log.error("鍫嗗灈鏈簕}鍊炬枩搴︽暟鎹鍙栧け璐�", crnSlave.getId());
+                    }
+                } catch (Exception e) {
+                    failCount++;
+                    log.error("鍫嗗灈鏈簕}鍊炬枩搴﹁褰曞紓甯�", crnSlave.getId(), e);
+                }
+            }
+
+            log.info("鍫嗗灈鏈哄�炬枩搴﹁褰曚换鍔″畬鎴愶細鎴愬姛{}鏉★紝澶辫触{}鏉�", successCount, failCount);
+        } catch (Exception e) {
+            log.error("鍫嗗灈鏈哄�炬枩搴﹁褰曚换鍔℃墽琛屽紓甯�", e);
+        }
+    }
+
+    /**
+     * 浠� PLC 璇诲彇鍊炬枩搴︽暟鎹�
+     * 
+     * 娉ㄦ剰锛氭牴鎹疄闄呬紶鎰熷櫒閰嶇疆锛屽�炬枩搴︽暟鎹彲鑳藉瓨鍌ㄥ湪锛�
+     * 1. DB101 鐨勬煇涓亸绉婚噺浣嶇疆锛堥渶瑕佹牴鎹�"璐ф灦鍊炬枩搴�.txt"鏂囨。纭畾鍏蜂綋浣嶇疆锛�
+     * 2. 鎴栬�呭叾浠栨暟鎹潡
+     * 
+     * 褰撳墠瀹炵幇鍋囪鍊炬枩搴︽暟鎹瓨鍌ㄥ湪 DB101 鐨勫亸绉婚噺浣嶇疆锛堥渶瑕佹牴鎹疄闄呴厤缃皟鏁达級
+     * 
+     * @param crnSlave 鍫嗗灈鏈洪厤缃�
+     * @return 鍊炬枩搴﹁褰曞璞★紝濡傛灉璇诲彇澶辫触杩斿洖null
+     */
+    private CrnTiltRecord readTiltDataFromPLC(CrnSlave crnSlave) {
+        SiemensS7Net siemensNet = null;
+        try {
+            // 鍒涘缓 PLC 杩炴帴
+            siemensNet = new SiemensS7Net(SiemensPLCS.S1200, crnSlave.getIp());
+            siemensNet.setRack(crnSlave.getRack().byteValue());
+            siemensNet.setSlot(crnSlave.getSlot().byteValue());
+            
+            OperateResult connect = siemensNet.ConnectServer();
+            if (!connect.IsSuccess) {
+                log.error("鍫嗗灈鏈簕} PLC杩炴帴澶辫触锛歿}", crnSlave.getId(), connect.Message);
+                return null;
+            }
+
+            // 璇诲彇鍊炬枩搴︽暟鎹�
+            // 娉ㄦ剰锛氭牴鎹�"璐ф灦鍊炬枩搴�.txt"鏂囨。锛岄渶瑕佺‘瀹氬�炬枩搴︽暟鎹湪 DB101 涓殑鍏蜂綋鍋忕Щ閲�
+            // 鍋囪鍊炬枩搴︽暟鎹瓨鍌ㄥ湪 DB101.56 寮�濮嬬殑浣嶇疆锛堥渶瑕佹牴鎹疄闄呴厤缃皟鏁达級
+            // 璇诲彇4涓猂eal绫诲瀷鏁版嵁锛圶銆乊銆乑鍊炬枩搴﹀拰鎬诲�炬枩搴︼級锛屾瘡涓猂eal鍗�4瀛楄妭锛屽叡16瀛楄妭
+            OperateResultExOne<byte[]> result = siemensNet.Read("DB101.56", (short) 16);
+            
+            if (!result.IsSuccess) {
+                log.error("鍫嗗灈鏈簕}璇诲彇鍊炬枩搴︽暟鎹け璐ワ細{}", crnSlave.getId(), result.Message);
+                return null;
+            }
+
+            CrnTiltRecord record = new CrnTiltRecord();
+            
+            // 瑙f瀽鍊炬枩搴︽暟鎹紙鏍规嵁瀹為檯浼犳劅鍣ㄦ暟鎹牸寮忚皟鏁达級
+            // 鍋囪锛氬亸绉婚噺0-3: X鏂瑰悜鍊炬枩搴�(Real)锛屽亸绉婚噺4-7: Y鏂瑰悜鍊炬枩搴�(Real)锛屽亸绉婚噺8-11: Z鏂瑰悜鍊炬枩搴�(Real)锛屽亸绉婚噺12-15: 鎬诲�炬枩搴�(Real)
+            record.setTiltX(siemensNet.getByteTransform().TransSingle(result.Content, 0));
+            record.setTiltY(siemensNet.getByteTransform().TransSingle(result.Content, 4));
+            record.setTiltZ(siemensNet.getByteTransform().TransSingle(result.Content, 8));
+            record.setTiltValue(siemensNet.getByteTransform().TransSingle(result.Content, 12));
+
+            log.debug("鍫嗗灈鏈簕}鍊炬枩搴︽暟鎹鍙栨垚鍔燂細X={}, Y={}, Z={}, 鎬诲�炬枩搴�={}", 
+                crnSlave.getId(), record.getTiltX(), record.getTiltY(), 
+                record.getTiltZ(), record.getTiltValue());
+
+            return record;
+        } catch (Exception e) {
+            log.error("鍫嗗灈鏈簕}璇诲彇鍊炬枩搴︽暟鎹紓甯�", crnSlave.getId(), e);
+            return null;
+        } finally {
+            if (siemensNet != null) {
+                try {
+                    siemensNet.ConnectClose();
+                } catch (Exception e) {
+                    log.warn("鍏抽棴PLC杩炴帴寮傚父", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * 鎵嬪姩瑙﹀彂璁板綍锛堢敤浜庢祴璇曟垨鎵嬪姩璁板綍锛�
+     * @param crnNo 鍫嗗灈鏈虹紪鍙凤紝濡傛灉涓簄ull鍒欒褰曟墍鏈夊爢鍨涙満
+     */
+    public void manualRecord(Integer crnNo) {
+        log.info("鎵嬪姩瑙﹀彂鍫嗗灈鏈哄�炬枩搴﹁褰曚换鍔★紝鍫嗗灈鏈虹紪鍙凤細{}", crnNo);
+        
+        try {
+            List<CrnSlave> crnSlaves = slaveProperties.getCrn();
+            if (crnSlaves == null || crnSlaves.isEmpty()) {
+                log.warn("娌℃湁閰嶇疆鍫嗗灈鏈猴紝璺宠繃鍊炬枩搴﹁褰�");
+                return;
+            }
+
+            Date recordDate = new Date();
+            Calendar cal = Calendar.getInstance();
+            cal.setTime(recordDate);
+            cal.set(Calendar.HOUR_OF_DAY, 0);
+            cal.set(Calendar.MINUTE, 0);
+            cal.set(Calendar.SECOND, 0);
+            cal.set(Calendar.MILLISECOND, 0);
+            Date recordDateOnly = cal.getTime();
+
+            int successCount = 0;
+            int failCount = 0;
+
+            for (CrnSlave crnSlave : crnSlaves) {
+                // 濡傛灉鎸囧畾浜嗗爢鍨涙満缂栧彿锛屽彧璁板綍鎸囧畾鐨勫爢鍨涙満
+                if (crnNo != null && !crnNo.equals(crnSlave.getId())) {
+                    continue;
+                }
+                
+                try {
+                    // 璇诲彇鍊炬枩搴︽暟鎹�
+                    CrnTiltRecord record = readTiltDataFromPLC(crnSlave);
+                    if (record != null) {
+                        record.setCrnNo(crnSlave.getId());
+                        record.setRecordDate(recordDateOnly);
+                        record.setRecordTime(recordDate);
+                        record.setRecordType("MANUAL"); // 鎵嬪姩瑙﹀彂
+
+                        // 鑾峰彇涓婃璁板綍鐢ㄤ簬瀵规瘮
+                        EntityWrapper<CrnTiltRecord> lastWrapper = new EntityWrapper<>();
+                        lastWrapper.eq("crn_no", crnSlave.getId());
+                        lastWrapper.orderBy("record_date", false);
+                        lastWrapper.orderBy("record_time", false);
+                        lastWrapper.last("OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY");
+                        CrnTiltRecord lastRecord = crnTiltRecordService.selectOne(lastWrapper);
+                        
+                        if (lastRecord != null && lastRecord.getTiltValue() != null) {
+                            // 瀵规瘮鍊炬枩搴�
+                            record.setPrevTiltValue(lastRecord.getTiltValue());
+                            if (record.getTiltValue() != null) {
+                                float change = record.getTiltValue() - lastRecord.getTiltValue();
+                                record.setTiltChange(change);
+                                log.info("鍫嗗灈鏈簕}鍊炬枩搴﹀姣旓細褰撳墠鍊�={}, 涓婃鍊�={}, 鍙樺寲閲�={}", 
+                                    crnSlave.getId(), record.getTiltValue(), 
+                                    lastRecord.getTiltValue(), change);
+                            }
+                        }
+
+                        // 淇濆瓨鍒版暟鎹簱
+                        if (crnTiltRecordService.insert(record)) {
+                            successCount++;
+                            log.info("鍫嗗灈鏈簕}鎵嬪姩鍊炬枩搴﹁褰曟垚鍔燂細鍊炬枩搴�={}, X={}, Y={}, Z={}, 鍙樺寲閲�={}", 
+                                crnSlave.getId(), record.getTiltValue(), 
+                                record.getTiltX(), record.getTiltY(), record.getTiltZ(),
+                                record.getTiltChange() != null ? record.getTiltChange() : 0);
+                        } else {
+                            failCount++;
+                            log.error("鍫嗗灈鏈簕}鍊炬枩搴﹁褰曚繚瀛樺け璐�", crnSlave.getId());
+                        }
+                    } else {
+                        failCount++;
+                        log.error("鍫嗗灈鏈簕}鍊炬枩搴︽暟鎹鍙栧け璐�", crnSlave.getId());
+                    }
+                } catch (Exception e) {
+                    failCount++;
+                    log.error("鍫嗗灈鏈簕}鍊炬枩搴﹁褰曞紓甯�", crnSlave.getId(), e);
+                }
+            }
+
+            log.info("鎵嬪姩鍫嗗灈鏈哄�炬枩搴﹁褰曚换鍔″畬鎴愶細鎴愬姛{}鏉★紝澶辫触{}鏉�", successCount, failCount);
+        } catch (Exception e) {
+            log.error("鎵嬪姩鍫嗗灈鏈哄�炬枩搴﹁褰曚换鍔℃墽琛屽紓甯�", e);
+        }
+    }
+}

--
Gitblit v1.9.1