From 8d3989dff1164588d45dbb30506da1a6e1094005 Mon Sep 17 00:00:00 2001
From: 张世豪 <979909237@qq.com>
Date: 星期一, 29 十二月 2025 14:27:47 +0800
Subject: [PATCH] 解决了车头朝向的问题

---
 src/gecaoji/GecaojiMeg.java                |    7 
 src/gecaoji/Device.java                    |   19 -
 src/sendMQTT/Server.java                   |  112 ++++----
 src/dikuai/daohangyulan.java               |   13 
 .classpath                                 |   26 -
 src/sendMQTT/ControlCommandSender.java     |  266 +++++++++++++++++++
 src/sendMQTT/HTTPUtils/ControlCommand.java |  134 +++++++++
 src/gecaoji/Getgecaojiimu_data.java        |    3 
 set.properties                             |   32 +-
 src/zhuye/Shouye.java                      |  189 +++++++++++++
 10 files changed, 676 insertions(+), 125 deletions(-)

diff --git a/.classpath b/.classpath
index f039d23..6eb8a24 100644
--- a/.classpath
+++ b/.classpath
@@ -1,20 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
-		<attributes>
-			<attribute name="module" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jackson-annotations-2.15.2.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jackson-core-2.15.2.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jackson-databind-2.15.2.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jSerialComm-2.10.4.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jts-core-1.19.0.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/lombok-1.18.36.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/MQTT-1.0-SNAPSHOT.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/org.eclipse.paho.client.mqttv3-1.2.2.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/slf4j-api-1.7.30.jar"/>
-	<classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/slf4j-simple-1.7.30.jar"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jackson-annotations-2.15.2.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jackson-core-2.15.2.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jackson-databind-2.15.2.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jSerialComm-2.10.4.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jts-core-1.19.0.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/lombok-1.18.36.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/MQTT-1.0-SNAPSHOT.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/org.eclipse.paho.client.mqttv3-1.2.2.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/slf4j-api-1.7.30.jar"/>
+	<classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/slf4j-simple-1.7.30.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/set.properties b/set.properties
index 453134b..b6d9106 100644
--- a/set.properties
+++ b/set.properties
@@ -1,19 +1,19 @@
-#Mower Configuration Properties - Updated
-#Sun Dec 28 20:35:53 GMT+08:00 2025
+#Current work land selection updated
+#Mon Dec 29 14:26:39 CST 2025
 appVersion=-1
-simCardNumber=-1
-currentWorkLandNumber=LAND1
-serialBaudRate=115200
 boundaryLengthVisible=false
-idleTrailDurationSeconds=60
-handheldMarkerId=1872
-viewCenterX=-60.00
-viewCenterY=-34.94
-manualBoundaryDrawingMode=false
-mowerId=6258
-serialPortName=COM15
-serialAutoConnect=true
-mapScale=8.60
-measurementModeEnabled=false
-firmwareVersion=-1
+currentWorkLandNumber=LAND1
 cuttingWidth=200
+firmwareVersion=-1
+handheldMarkerId=1872
+idleTrailDurationSeconds=60
+manualBoundaryDrawingMode=false
+mapScale=12.32
+measurementModeEnabled=false
+mowerId=6258
+serialAutoConnect=true
+serialBaudRate=115200
+serialPortName=COM15
+simCardNumber=-1
+viewCenterX=-53.78
+viewCenterY=-35.02
diff --git a/src/dikuai/daohangyulan.java b/src/dikuai/daohangyulan.java
index bf29464..3cc7dde 100644
--- a/src/dikuai/daohangyulan.java
+++ b/src/dikuai/daohangyulan.java
@@ -471,12 +471,13 @@
         }
         
         // 鍥炬爣榛樿鏈濅笅锛�270搴︼級锛岄渶瑕佽绠楁棆杞搴︿娇杞﹀ご鏈濆悜琛岄┒鏂瑰悜
-        // 濡傛灉杩愬姩鏂瑰悜鍚戜笂锛�90搴︼級鈫� 闇�瑕佹棆杞�180搴︼紙270 - 90 = 180锛�
-        // 濡傛灉杩愬姩鏂瑰悜鍚戝彸锛�0搴︼級鈫� 闇�瑕佹棆杞�270搴︼紙270 - 0 = 270锛�
-        // 濡傛灉杩愬姩鏂瑰悜鍚戝乏锛�180搴︼級鈫� 闇�瑕佹棆杞�90搴︼紙270 - 180 = 90锛�
-        // 濡傛灉杩愬姩鏂瑰悜鍚戜笅锛�270搴︼級鈫� 闇�瑕佹棆杞�0搴︼紙270 - 270 = 0锛�
-        // 鍏紡锛歨eading = (270 - atan2Angle + 360) % 360
-        double heading = (270.0 - atan2Angle + 360.0) % 360.0;
+        // 鍧愭爣绯伙細North(+Y) -> Screen Down(90). East(+X) -> Screen Right(0).
+        // atan2: North(90), East(0).
+        // 鐩爣锛歂orth -> Icon Down(0 rot). East -> Icon Right(270 rot).
+        // 90 -> 0.
+        // 0 -> 270.
+        // 鍏紡锛歨eading = (atan2Angle + 270) % 360
+        double heading = (atan2Angle + 270.0) % 360.0;
         
         return heading;
     }
diff --git a/src/gecaoji/Device.java b/src/gecaoji/Device.java
index bb96f57..15efd71 100644
--- a/src/gecaoji/Device.java
+++ b/src/gecaoji/Device.java
@@ -66,8 +66,6 @@
     // 瀹炴椂閫熷害
     private String heading;
     // 鑸悜瑙�
-    private String pitch;
-    // 淇话瑙�
     private String roll; // 妯粴瑙� 瑙掑害
     private String yaw; // 鍋忚埅瑙� 瑙掑害
     private String battery_level; // 鐢垫睜鐢甸噺鐧惧垎姣�
@@ -166,7 +164,6 @@
         if (realtimeY != null) properties.setProperty("realtimeY", realtimeY);
         if (realtimeSpeed != null) properties.setProperty("realtimeSpeed", realtimeSpeed);
         if (heading != null) properties.setProperty("heading", heading);
-        if (pitch != null) properties.setProperty("pitch", pitch);
         if (roll != null) properties.setProperty("roll", roll);
         if (yaw != null) properties.setProperty("yaw", yaw);
         if (battery_level != null) properties.setProperty("battery_level", battery_level);
@@ -225,7 +222,6 @@
         target.realtimeY = properties.getProperty("realtimeY", "-1");
         target.realtimeSpeed = properties.getProperty("realtimeSpeed", "-1");
         target.heading = properties.getProperty("heading", "-1");
-        target.pitch = properties.getProperty("pitch", "-1");
         target.roll = properties.getProperty("roll", "-1");
         target.yaw = properties.getProperty("yaw", "-1");
         target.battery_level = properties.getProperty("battery_level", "-1");
@@ -276,7 +272,6 @@
         target.realtimeY = "-1";
         target.realtimeSpeed = "-1";
         target.heading = "-1";
-        target.pitch = "-1";
         target.roll = "-1";
         target.yaw = "-1";
         target.battery_level = "-1";
@@ -384,9 +379,6 @@
             case "heading":
                 this.heading = value;
                 return true;
-            case "pitch":
-                this.pitch = value;
-                return true;
             case "roll":
                 this.roll = value;
                 return true;
@@ -547,7 +539,7 @@
         satelliteCount = defaultIfEmpty(sanitizeField(fields, 7));
         differentialAge = defaultIfEmpty(sanitizeField(fields, 13));
         battery_level = defaultIfEmpty(sanitizeField(fields, 16));
-        pitch = defaultIfEmpty(sanitizeField(fields, 17));
+        yaw = defaultIfEmpty(sanitizeField(fields, 17));
         realtimeSpeed = defaultIfEmpty(sanitizeField(fields, 18));
         GupdateTime = String.valueOf(System.currentTimeMillis());
     }
@@ -924,14 +916,6 @@
         this.heading = heading;
     }
 
-    public String getPitch() { // 鑾峰彇淇话瑙�
-        return pitch;
-    }
-
-    public void setPitch(String pitch) { // 璁剧疆淇话瑙�
-        this.pitch = pitch;
-    }
-
     public String getRoll() {
         return roll;
     }
@@ -1138,7 +1122,6 @@
                 ", realtimeY='" + realtimeY + '\'' +
                 ", realtimeSpeed='" + realtimeSpeed + '\'' +
                 ", heading='" + heading + '\'' +
-                ", pitch='" + pitch + '\'' +
                 ", roll='" + roll + '\'' +
                 ", yaw='" + yaw + '\'' +
                 ", battery_level='" + battery_level + '\'' +
diff --git a/src/gecaoji/GecaojiMeg.java b/src/gecaoji/GecaojiMeg.java
index 589c883..802827b 100644
--- a/src/gecaoji/GecaojiMeg.java
+++ b/src/gecaoji/GecaojiMeg.java
@@ -40,7 +40,6 @@
     private JLabel errorCodeLabel;
     private JLabel errorMessageLabel;
     private JLabel rollLabel;
-    private JLabel pitchLabel;
     private JLabel yawLabel;
     
     private JLabel updateTimeLabel;
@@ -249,9 +248,6 @@
         // 妯粴瑙�
         addLabelRow(grid, gbc, currentRow++, "妯粴瑙掞細", rollLabel = createValueLabel(), titleFont, valueFont);
         
-        // 淇话瑙�
-        addLabelRow(grid, gbc, currentRow++, "淇话瑙掞細", pitchLabel = createValueLabel(), titleFont, valueFont);
-        
         // 鍋忚埅瑙�
         addLabelRow(grid, gbc, currentRow++, "鍋忚埅瑙掞細", yawLabel = createValueLabel(), titleFont, valueFont);
 
@@ -380,7 +376,6 @@
         errorCodeLabel = null;
         errorMessageLabel = null;
         rollLabel = null;
-        pitchLabel = null;
         yawLabel = null;
         
         updateTimeLabel = null;
@@ -419,7 +414,6 @@
         errorCodeLabel.setText(formatDeviceValue(device.getError_code()));
         errorMessageLabel.setText(formatDeviceValue(device.getError_message()));
         rollLabel.setText(formatDeviceValue(device.getRoll()));
-        pitchLabel.setText(formatDeviceValue(device.getPitch()));
         yawLabel.setText(formatDeviceValue(device.getYaw()));
         
         updateTimeLabel.setText(formatTimestamp(device.getGupdateTime()));
@@ -445,7 +439,6 @@
         if (errorCodeLabel != null) errorCodeLabel.setText(value);
         if (errorMessageLabel != null) errorMessageLabel.setText(value);
         if (rollLabel != null) rollLabel.setText(value);
-        if (pitchLabel != null) pitchLabel.setText(value);
         if (yawLabel != null) yawLabel.setText(value);
         
         if (updateTimeLabel != null) updateTimeLabel.setText(value);
diff --git a/src/gecaoji/Getgecaojiimu_data.java b/src/gecaoji/Getgecaojiimu_data.java
index 97c5248..b1da2c1 100644
--- a/src/gecaoji/Getgecaojiimu_data.java
+++ b/src/gecaoji/Getgecaojiimu_data.java
@@ -9,9 +9,6 @@
                 return;
             }
             
-            if (status.getPitch() != null) {
-                device.setPitch(String.valueOf(status.getPitch()));
-            }
             if (status.getRoll() != null) {
                 device.setRoll(String.valueOf(status.getRoll()));
             }
diff --git a/src/sendMQTT/ControlCommandSender.java b/src/sendMQTT/ControlCommandSender.java
new file mode 100644
index 0000000..2961499
--- /dev/null
+++ b/src/sendMQTT/ControlCommandSender.java
@@ -0,0 +1,266 @@
+package sendMQTT;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import sendMQTT.HTTPUtils.ControlCommand;
+import set.Setsys;
+import user.Usrdell;
+
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.paho.client.mqttv3.MqttClient;
+import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+
+/**
+ * 璁惧鎺у埗鎸囦护MQTT鍙戦�佸伐鍏风被
+ * 鐢ㄤ簬鍚戣澶囧彂閫佹帶鍒舵寚浠わ紙鍚姩銆佸仠姝€�佹殏鍋溿�佹仮澶嶃�佺揣鎬ュ仠姝㈢瓑锛�
+ */
+public class ControlCommandSender {
+    
+    private static final String DEFAULT_HOST = "tcp://39.99.43.227:1883";
+    private static final String DEFAULT_CLIENT_ID_PREFIX = "control_";
+    
+    private final String host;
+    private final String clientId;
+    
+    /**
+     * 鏋勯�犲嚱鏁�
+     * @param host MQTT broker鍦板潃锛屼緥濡� "tcp://39.99.43.227:1883"
+     * @param clientId MQTT瀹㈡埛绔疘D
+     */
+    public ControlCommandSender(String host, String clientId) {
+        this.host = host != null ? host : DEFAULT_HOST;
+        this.clientId = clientId != null ? clientId : (DEFAULT_CLIENT_ID_PREFIX + System.currentTimeMillis());
+    }
+    
+    /**
+     * 浣跨敤榛樿閰嶇疆鍒涘缓鍙戦�佸櫒
+     * @return ControlCommandSender瀹炰緥
+     */
+    public static ControlCommandSender createDefault() {
+        return new ControlCommandSender(DEFAULT_HOST, DEFAULT_CLIENT_ID_PREFIX + System.currentTimeMillis());
+    }
+    
+    /**
+     * 鍙戦�佹帶鍒舵寚浠�
+     * 
+     * @param msgId 娑堟伅鍞竴鏍囪瘑
+     * @param userId 鐢ㄦ埛ID
+     * @param deviceId 璁惧缂栧彿
+     * @param command 鎺у埗鍛戒护锛歴tart(鍚姩), stop(鍋滄), pause(鏆傚仠), resume(鎭㈠), emergency_stop(绱ф�ュ仠姝�)
+     * @param value1 鍙傛暟1锛堝彲閫夛紝Double绫诲瀷锛�
+     * @param value2 鍙傛暟2锛堝彲閫夛紝String绫诲瀷锛�
+     * @param value3 鍙傛暟3锛堝彲閫夛紝Integer绫诲瀷锛�
+     * @return 鏄惁鍙戦�佹垚鍔�
+     * @throws MqttException MQTT鍙戦�佸紓甯�
+     */
+    public boolean sendControlCommand(String msgId, String userId, String deviceId, 
+                                     String command, Double value1, String value2, Integer value3) 
+            throws MqttException {
+        // 鏋勫缓鍙傛暟瀵硅薄
+        ControlCommand.ControlParameters parameters = new ControlCommand.ControlParameters(
+                value1, value2, value3
+        );
+        
+        // 鏋勫缓鎺у埗鎸囦护瀵硅薄
+        long timestamp = System.currentTimeMillis();
+        ControlCommand controlCommand = new ControlCommand(
+                msgId,
+                timestamp,
+                userId,
+                deviceId,
+                command,
+                parameters
+        );
+        
+        // 杞崲涓篔SON瀛楃涓�
+        String jsonString = toJsonString(controlCommand);
+        if (jsonString == null) {
+            throw new MqttException(new Exception("JSON搴忓垪鍖栧け璐�"));
+        }
+        
+        // 鍙戦�丮QTT娑堟伅
+        return sendMQTT(jsonString, userId, deviceId);
+    }
+    
+
+    
+
+    
+    /**
+     * 灏咰ontrolCommand瀵硅薄杞崲涓篔SON瀛楃涓�
+     */
+    private String toJsonString(ControlCommand command) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(command);
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    /**
+     * 鍙戦�丮QTT娑堟伅
+     * 
+     * @param messageJson JSON娑堟伅鍐呭
+     * @param userId 鐢ㄦ埛ID
+     * @param deviceId 璁惧缂栧彿
+     * @return 鏄惁鍙戦�佹垚鍔�
+     * @throws MqttException MQTT鍙戦�佸紓甯�
+     */
+    private boolean sendMQTT(String messageJson, String userId, String deviceId) throws MqttException {
+        MqttClient client = null;
+        try {
+            // 鏋勫缓涓婚锛歛pp/{user_id}/mower/{device_id}/control
+            String topic = String.format("app/%s/mower/%s/control", userId, deviceId);
+            
+            // 鍒涘缓MQTT杩炴帴閫夐」
+            MqttConnectOptions options = new MqttConnectOptions();
+            options.setCleanSession(true);
+            
+            // 鍒涘缓MQTT瀹㈡埛绔苟杩炴帴
+            client = new MqttClient(host, clientId);
+            client.connect(options);
+            
+            // 鍒涘缓娑堟伅骞跺彂閫�
+            MqttMessage message = new MqttMessage();
+            message.setPayload(messageJson.getBytes("UTF-8"));
+            client.publish(topic, message);
+                      
+            return true;
+            
+        } catch (UnsupportedEncodingException e) {
+            throw new MqttException(e);
+        } finally {
+            // 鏂紑杩炴帴
+            if (client != null && client.isConnected()) {
+                try {
+                    client.disconnect();
+                    client.close();
+                } catch (MqttException e) {
+                    // 蹇界暐鏂紑杩炴帴鏃剁殑寮傚父
+                }
+            }
+        }
+    }
+
+    static String msgId = "hxzkcontrol_hxzkcontrol_20151104" ;            
+    String userId=Usrdell.getUserEmail();//鐢ㄦ埛ID
+	String deviceId=Setsys.getMowerIdValue();//璁惧ID
+	private static double battery = 90.0;
+    private static String token = "abcd123ds";
+    private static int type = 0;
+    /**
+     * 鍚姩鍛戒护锛坰tart锛�
+     * 鈼忓姛鑳斤細寮�濮嬫墽琛岄璁剧殑璺緞瑙勫垝浠诲姟鎴栦粠鏆傚仠鐘舵�佺户缁繍琛�
+     * 鈼忓簲鐢ㄥ満鏅細寮�濮嬪壊鑽変綔涓氥�佺户缁鏆傚仠鐨勪换鍔�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @param deviceId 璁惧ID
+     * @return 鍙戦�佺粨鏋滐紝true琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+     */
+    public static boolean sendStartCommand(String userId, String deviceId) {
+        try {
+            ControlCommandSender sender = ControlCommandSender.createDefault();            
+            boolean result = sender.sendControlCommand(msgId, userId, deviceId, "start", battery, token, type);            
+            return result;
+        } catch (Exception e) {
+            System.err.println("鍚姩鍛戒护鍙戦�佸け璐�: " + e.getMessage());
+            e.printStackTrace();
+            return false;
+        }
+    }
+    
+    /**
+     * 鍋滄鍛戒护锛坰top锛�
+     * 鈼忓姛鑳斤細姝e父鍋滄鍓茶崏鏈鸿繍琛岋紝淇濆瓨褰撳墠鐘舵��
+     * 鈼忓簲鐢ㄥ満鏅細瀹屾垚浣滀笟鍚庣殑姝e父鍋滄銆佺敤鎴蜂富鍔ㄥ仠姝�
+     * 鈼忕壒鐐癸細骞崇ǔ鍑忛�熷仠姝紝璁板綍鍋滄浣嶇疆
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @param deviceId 璁惧ID
+     * @return 鍙戦�佺粨鏋滐紝true琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+     */
+    public static boolean sendStopCommand(String userId, String deviceId) {
+        try {
+            ControlCommandSender sender = ControlCommandSender.createDefault();           
+            boolean result = sender.sendControlCommand(msgId, userId, deviceId, "stop", battery, token, type);            
+            return result;
+        } catch (Exception e) {
+            System.err.println("鍋滄鍛戒护鍙戦�佸け璐�: " + e.getMessage());
+            e.printStackTrace();
+            return false;
+        }
+    }
+    
+    /**
+     * 鏆傚仠鍛戒护锛坧ause锛�
+     * 鈼忓姛鑳斤細涓存椂鏆傚仠褰撳墠杩愯锛屼繚鎸佽澶囧氨缁姸鎬�
+     * 鈼忓簲鐢ㄥ満鏅細涓存椂妫�鏌ャ�侀伩璁╅殰纰嶇墿銆佺敤鎴蜂复鏃朵腑鏂�
+     * 鈼忕壒鐐癸細鍙揩閫熸仮澶嶏紝鏃犻渶閲嶆柊鍒濆鍖�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @param deviceId 璁惧ID
+     * @return 鍙戦�佺粨鏋滐紝true琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+     */
+    public static boolean sendPauseCommand(String userId, String deviceId) {
+    	try {
+            ControlCommandSender sender = ControlCommandSender.createDefault();            
+            boolean result = sender.sendControlCommand(msgId, userId, deviceId, "pause", battery, token, type);
+            
+            return result;
+        } catch (Exception e) {
+            System.err.println("鏆傚仠鍛戒护鍙戦�佸け璐�: " + e.getMessage());
+            e.printStackTrace();
+            return false;
+        }
+    }
+    
+    /**
+     * 鎭㈠鍛戒护锛坮esume锛�
+     * 鈼忓姛鑳斤細浠庢殏鍋滅姸鎬佹仮澶嶄箣鍓嶇殑杩愯
+     * 鈼忓簲鐢ㄥ満鏅細鏆傚仠鍚庣户缁綔涓�
+     * 鈼忕壒鐐癸細浠庢殏鍋滅偣缁х画鎵ц锛屼繚鎸佽矾寰勮繛缁��
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @param deviceId 璁惧ID
+     * @return 鍙戦�佺粨鏋滐紝true琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+     */
+    public static boolean sendResumeCommand(String userId, String deviceId) {
+        try {
+            ControlCommandSender sender = ControlCommandSender.createDefault();
+            boolean result = sender.sendControlCommand(msgId, userId, deviceId, "resume", battery, token, type);            
+            return result;
+        } catch (Exception e) {            
+            e.printStackTrace();
+            return false;
+        }
+    }
+    
+    /**
+     * 绱ф�ュ仠姝㈠懡浠わ紙emergency_stop锛�
+     * 鈼忓姛鑳斤細绔嬪嵆鍋滄鎵�鏈夊姩浣滐紝鍒囨柇鍔ㄥ姏杈撳嚭
+     * 鈼忓簲鐢ㄥ満鏅細绱ф�ユ儏鍐点�佸畨鍏ㄥ▉鑳併�佽澶囧紓甯�
+     * 鈼忕壒鐐癸細鏈�楂樹紭鍏堢骇锛岄渶瑕佹墜鍔ㄥ浣嶆墠鑳介噸鏂板惎鍔�
+     * 
+     * @param userId 鐢ㄦ埛ID
+     * @param deviceId 璁惧ID
+     * @return 鍙戦�佺粨鏋滐紝true琛ㄧず鎴愬姛锛宖alse琛ㄧず澶辫触
+     */
+    public static boolean sendEmergencyStopCommand(String userId, String deviceId) {
+        try {
+            ControlCommandSender sender = ControlCommandSender.createDefault();            
+            boolean result = sender.sendControlCommand(msgId, userId, deviceId, "emergency_stop", battery, token, type);
+                        return result;
+        } catch (Exception e) {
+            System.err.println("绱ф�ュ仠姝㈠懡浠ゅ彂閫佸け璐�: " + e.getMessage());
+            e.printStackTrace();
+            return false;
+        }
+    }
+     
+    
+}
+
diff --git a/src/sendMQTT/HTTPUtils/ControlCommand.java b/src/sendMQTT/HTTPUtils/ControlCommand.java
new file mode 100644
index 0000000..7c94b85
--- /dev/null
+++ b/src/sendMQTT/HTTPUtils/ControlCommand.java
@@ -0,0 +1,134 @@
+package sendMQTT.HTTPUtils;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * 璁惧鎺у埗鎸囦护JSON缁撴瀯
+ * 涓婚锛歛pp/{user_id}/mower/{device_id}/control
+ */
+
+public class ControlCommand {
+    
+    @JsonProperty("msg_id")
+    private String msgId;
+    
+    private long timestamp;
+    
+    @JsonProperty("user_id")
+    private String userId;
+    
+    @JsonProperty("device_id")
+    private String deviceId;
+    
+    private String command; // start, stop, pause, resume, emergency_stop
+    
+    private ControlParameters parameters;
+    
+    public ControlCommand() {
+    }
+
+
+
+    public ControlCommand(String msgId, long timestamp, String userId, String deviceId, 
+                         String command, ControlParameters parameters) {
+        this.msgId = msgId;
+        this.timestamp = timestamp;
+        this.userId = userId;
+        this.deviceId = deviceId;
+        this.command = command;
+        this.parameters = parameters;
+    }
+
+    public String getMsgId() {
+        return msgId;
+    }
+
+    public void setMsgId(String msgId) {
+        this.msgId = msgId;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    public String getCommand() {
+        return command;
+    }
+
+    public void setCommand(String command) {
+        this.command = command;
+    }
+
+    public ControlParameters getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(ControlParameters parameters) {
+        this.parameters = parameters;
+    }
+
+    /**
+     * 鎺у埗鍙傛暟鍐呴儴绫�
+     */
+
+    public static class ControlParameters {
+        private Double value1;
+        private String value2;
+        private Integer value3;
+        
+        public ControlParameters() {
+        }
+        
+        public ControlParameters(Double value1, String value2, Integer value3) {
+            this.value1 = value1;
+            this.value2 = value2;
+            this.value3 = value3;
+        }
+
+        public Double getValue1() {
+            return value1;
+        }
+
+        public void setValue1(Double value1) {
+            this.value1 = value1;
+        }
+
+        public String getValue2() {
+            return value2;
+        }
+
+        public void setValue2(String value2) {
+            this.value2 = value2;
+        }
+
+        public Integer getValue3() {
+            return value3;
+        }
+
+        public void setValue3(Integer value3) {
+            this.value3 = value3;
+        }
+    }
+}
+
diff --git a/src/sendMQTT/Server.java b/src/sendMQTT/Server.java
index bcf26e4..c1f7471 100644
--- a/src/sendMQTT/Server.java
+++ b/src/sendMQTT/Server.java
@@ -16,66 +16,66 @@
 
 
 public class Server {
-   static String host="tcp://39.99.43.227:1883";
-   static String clientId="1231@qq.com";
+	static String host="tcp://39.99.43.227:1883";
+	static String clientId="1231@qq.com";
 
-    /**
-     * 鑾峰彇褰撳墠绯荤粺鏃堕棿
-     * @return 鏍煎紡鍖栫殑鏃堕棿瀛楃涓诧紝鏍煎紡涓� "yyyy-MM-dd HH:mm:ss"
-     */
-    public static String getCurrentSystemTime() {
-        LocalDateTime now = LocalDateTime.now();
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-        return now.format(formatter);
-    }
+	/**
+	 * 鑾峰彇褰撳墠绯荤粺鏃堕棿
+	 * @return 鏍煎紡鍖栫殑鏃堕棿瀛楃涓诧紝鏍煎紡涓� "yyyy-MM-dd HH:mm:ss"
+	 */
+	public static String getCurrentSystemTime() {
+		LocalDateTime now = LocalDateTime.now();
+		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+		return now.format(formatter);
+	}
 
-    /**
-     * 鑾峰彇褰撳墠绯荤粺鏃堕棿锛堣嚜瀹氫箟鏍煎紡锛�
-     * @param pattern 鏃堕棿鏍煎紡妯″紡锛屼緥濡� "yyyy-MM-dd HH:mm:ss"銆�"yyyy/MM/dd HH:mm:ss" 绛�
-     * @return 鏍煎紡鍖栫殑鏃堕棿瀛楃涓�
-     */
-    public static String getCurrentSystemTime(String pattern) {
-        LocalDateTime now = LocalDateTime.now();
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
-        return now.format(formatter);
-    }
+	/**
+	 * 鑾峰彇褰撳墠绯荤粺鏃堕棿锛堣嚜瀹氫箟鏍煎紡锛�
+	 * @param pattern 鏃堕棿鏍煎紡妯″紡锛屼緥濡� "yyyy-MM-dd HH:mm:ss"銆�"yyyy/MM/dd HH:mm:ss" 绛�
+	 * @return 鏍煎紡鍖栫殑鏃堕棿瀛楃涓�
+	 */
+	public static String getCurrentSystemTime(String pattern) {
+		LocalDateTime now = LocalDateTime.now();
+		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
+		return now.format(formatter);
+	}
 
- 
 
-    private static void testCode() {
-        String mes_id="hxzkcontrol_20151104";//娑堟伅ID
-        String userId=Usrdell.getUserEmail();//鐢ㄦ埛ID
-        String deviceID=Setsys.getMowerIdValue();//璁惧ID
-        String protiesFilePath="./dikuai.properties";//鍦板潡淇℃伅閰嶇疆鏂囦欢
-        String json = PropertiesFileUploader.movePathSend(mes_id,userId, deviceID, protiesFilePath);//鐢熸垚缁欒澶囦笅鍙戠殑JSON
-        sendMQTT(json, host, clientId,deviceID);
-    }
+	/**鍙戦�佸壊鑽夎矾寰�*/
+	public static void sendMowingPath() {
+		String mes_id="hxzkcontrol_20151104";//娑堟伅ID
+		String userId=Usrdell.getUserEmail();//鐢ㄦ埛ID
+		String deviceID=Setsys.getMowerIdValue();//璁惧ID
+		String protiesFilePath="./dikuai.properties";//鍦板潡淇℃伅閰嶇疆鏂囦欢
+		String json = PropertiesFileUploader.movePathSend(mes_id,userId, deviceID, protiesFilePath);//鐢熸垚缁欒澶囦笅鍙戠殑JSON
+		sendMQTT(json, host, clientId,deviceID);
+	}
 
-    private static void sendMQTT(String messageJson, String host, String clientId,String deviceID)  {
-        try {
-            String topic="app/p/mower/"+deviceID+"/path";
-            MqttConnectOptions options = new MqttConnectOptions();
-            options.setCleanSession(true);
-            MqttClient client = new MqttClient(host, clientId);
-            client.connect(options);
-            // 娣诲姞鍏抽棴閽╁瓙锛岀▼搴忛��鍑烘椂鍏抽棴杩炴帴
-            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
-                try {
-                    if (client.isConnected()) {
-                        client.disconnect();
-                        client.close();
-                    }
-                } catch (Exception e) {
-                }
-            }));
-            MqttMessage message = new MqttMessage();
-            message.setPayload(messageJson.getBytes("UTF-8"));
-            client.publish(topic, message);
-        } catch (MqttException e) {
-            throw new RuntimeException(e);
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException(e);
-        }
-    }
+	private static void sendMQTT(String messageJson, String host, String clientId,String deviceID)  {
+		try {
+			String topic="app/p/mower/"+deviceID+"/path";
+			MqttConnectOptions options = new MqttConnectOptions();
+			options.setCleanSession(true);
+			MqttClient client = new MqttClient(host, clientId);
+			client.connect(options);
+			// 娣诲姞鍏抽棴閽╁瓙锛岀▼搴忛��鍑烘椂鍏抽棴杩炴帴
+			Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+				try {
+					if (client.isConnected()) {
+						client.disconnect();
+						client.close();
+					}
+				} catch (Exception e) {
+				}
+			}));
+			MqttMessage message = new MqttMessage();
+			message.setPayload(messageJson.getBytes("UTF-8"));
+			client.publish(topic, message);
+		} catch (MqttException e) {
+			throw new RuntimeException(e);
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(e);
+		}
+	}
 
 }
diff --git a/src/zhuye/Shouye.java b/src/zhuye/Shouye.java
index d8d6c82..2ba846a 100644
--- a/src/zhuye/Shouye.java
+++ b/src/zhuye/Shouye.java
@@ -9,9 +9,11 @@
 
 import java.awt.*;
 import java.awt.event.*;
+import java.awt.geom.Point2D;
 
 import chuankou.dellmessage;
 import chuankou.sendmessage;
+import chuankou.DataListener;
 import chuankou.SerialPortService;
 import dikuai.Dikuai;
 import dikuai.Dikuaiguanli;
@@ -32,11 +34,12 @@
 import java.util.Locale;
 import java.util.concurrent.atomic.AtomicBoolean;
 // import java.util.function.Consumer;
-import chuankou.DataListener;
-import java.awt.geom.Point2D;
-
-import publicway.Gpstoxuzuobiao;
+import sendMQTT.ControlCommandSender;
+import sendMQTT.Server;
+import user.Usrdell;
+import dikuai.Dikuaiguanli;
 import publicway.Fanhuibutton;
+import publicway.Gpstoxuzuobiao;
 
 /**
  * 棣栭〉鐣岄潰 - 閫傞厤6.5瀵哥珫灞忥紝浣跨敤鐙珛鐨凪apRenderer杩涜缁樺埗
@@ -1782,6 +1785,17 @@
 				return;
 			}
 			
+			// 妫�鏌ヨ矾寰処D鏄惁鍖归厤
+			if (!checkPathIdMatch()) {
+				startButtonShowingPause = true;
+				statusLabel.setText("寰呮満");
+				updateStartButtonAppearance();
+				return;
+			}
+			
+			// 鍙戦�佸紑濮嬫寚浠�
+			sendControlCommand("start");
+			
 			statusLabel.setText("浣滀笟涓�");
 			if (stopButtonActive) {
 				stopButtonActive = false;
@@ -1794,6 +1808,8 @@
 			return;
 		}
 		} else {
+			// 鍙戦�佹殏鍋滄寚浠�
+			sendControlCommand("pause");
 			statusLabel.setText("鏆傚仠涓�");
 			pauseMowingSession();
 		}
@@ -1801,6 +1817,169 @@
 	}
 
 	/**
+	 * 妫�鏌ヨ矾寰処D鏄惁鍖归厤
+	 * @return 濡傛灉鍖归厤杩斿洖true锛屽惁鍒欒繑鍥瀎alse
+	 */
+	private boolean checkPathIdMatch() {
+		Device device = Device.getGecaoji();
+		if (device == null) {
+			showCustomMessageDialog("鏃犳硶鑾峰彇鍓茶崏鏈轰俊鎭紝璇锋鏌ヨ澶囪繛鎺�", "鎻愮ず");
+			return false;
+		}
+		
+		String savedPathId = device.getPath_id_saved();
+		String currentLandNumber = Dikuaiguanli.getCurrentWorkLandNumber();
+		
+		if (currentLandNumber == null) {
+			showCustomMessageDialog("璇峰厛閫夋嫨浣滀笟鍦板潡", "鎻愮ず");
+			return false;
+		}
+		
+		// 濡傛灉璺緞ID涓嶅尮閰嶏紙娉ㄦ剰澶勭悊null鍜�-1鐨勬儏鍐碉級
+		boolean isMatch = savedPathId != null && savedPathId.equals(currentLandNumber);
+		
+		if (!isMatch) {
+			showPathMismatchDialog(currentLandNumber);
+			return false;
+		}
+		
+		return true;
+	}
+	
+	/**
+	 * 鏄剧ず璺緞涓嶅尮閰嶅璇濇
+	 */
+	private void showPathMismatchDialog(String landNumber) {
+		Window parentWindow = SwingUtilities.getWindowAncestor(this);
+		JDialog dialog = new JDialog(parentWindow, "璺緞涓嶅尮閰�", Dialog.ModalityType.APPLICATION_MODAL);
+		dialog.setLayout(new BorderLayout(20, 20));
+		dialog.setResizable(false);
+		
+		JPanel contentPanel = new JPanel(new BorderLayout(0, 15));
+		contentPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20));
+		contentPanel.setBackground(Color.WHITE);
+		
+		JLabel messageLabel = new JLabel("<html><div style='text-align: center;'>褰撳墠鍓茶崏鏈鸿矾寰勪笌閫変腑鍦板潡涓嶄竴鑷�<br>鏄惁绔嬪嵆鍙戦�佸湴鍧� " + landNumber + " 鐨勮矾寰勪俊鎭紵</div></html>");
+		messageLabel.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 14));
+		messageLabel.setHorizontalAlignment(SwingConstants.CENTER);
+		contentPanel.add(messageLabel, BorderLayout.CENTER);
+		
+		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0));
+		buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
+		buttonPanel.setOpaque(false);
+		
+		JButton sendButton = buttonset.createStyledButton("绔嬪嵆鍙戦��", THEME_COLOR);
+		JButton cancelButton = buttonset.createStyledButton("鍙栨秷", new Color(150, 150, 150));
+		
+		sendButton.addActionListener(e -> {
+			dialog.dispose();
+			sendMowingPathAndCheck(landNumber);
+		});
+		
+		cancelButton.addActionListener(e -> dialog.dispose());
+		
+		buttonPanel.add(sendButton);
+		buttonPanel.add(cancelButton);
+		
+		contentPanel.add(buttonPanel, BorderLayout.SOUTH);
+		dialog.add(contentPanel, BorderLayout.CENTER);
+		
+		dialog.pack();
+		dialog.setLocationRelativeTo(this);
+		dialog.setVisible(true);
+	}
+	
+	/**
+	 * 鍙戦�佸壊鑽夎矾寰勫苟妫�鏌ョ粨鏋�
+	 */
+	private void sendMowingPathAndCheck(String expectedLandNumber) {
+		// 鏄剧ず鍙戦�佷腑鎻愮ず
+		JDialog progressDialog = new JDialog(SwingUtilities.getWindowAncestor(this), "鍙戦�佷腑", Dialog.ModalityType.MODELESS);
+		progressDialog.setLayout(new BorderLayout());
+		JLabel label = new JLabel("姝e湪鍙戦�佽矾寰勪俊鎭�...", SwingConstants.CENTER);
+		label.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 40));
+		progressDialog.add(label);
+		progressDialog.pack();
+		progressDialog.setLocationRelativeTo(this);
+		progressDialog.setVisible(true);
+		
+		// 寮傛鍙戦��
+		new Thread(() -> {
+			try {
+				Server.sendMowingPath();
+				
+				// 杞妫�鏌ヨ矾寰処D鏄惁鏇存柊
+				int maxRetries = 10; // 鏈�澶氱瓑寰�10绉�
+				boolean success = false;
+				
+				for (int i = 0; i < maxRetries; i++) {
+					Thread.sleep(1000);
+					Device device = Device.getGecaoji();
+					if (device != null) {
+						// 鍒锋柊璁惧鏁版嵁
+						device.initFromProperties(); 
+						String currentPathId = device.getPath_id_saved();
+						if (expectedLandNumber.equals(currentPathId)) {
+							success = true;
+							break;
+						}
+					}
+				}
+				
+				final boolean finalSuccess = success;
+				SwingUtilities.invokeLater(() -> {
+					progressDialog.dispose();
+					if (finalSuccess) {
+						showCustomMessageDialog("璺緞鍙戦�佹垚鍔燂紒", "鎻愮ず");
+					} else {
+						// 鍗充娇瓒呮椂涔熸彁绀哄彂閫佸畬鎴愶紝璁╃敤鎴峰啀娆″皾璇曞紑濮�
+						showCustomMessageDialog("璺緞鍙戦�佹寚浠ゅ凡鍙戝嚭锛岃绋嶅悗閲嶈瘯寮�濮嬩綔涓�", "鎻愮ず");
+					}
+				});
+				
+			} catch (Exception e) {
+				SwingUtilities.invokeLater(() -> {
+					progressDialog.dispose();
+					showCustomMessageDialog("鍙戦�佸け璐�: " + e.getMessage(), "閿欒");
+				});
+			}
+		}).start();
+	}
+	
+	/**
+	 * 鍙戦�佹帶鍒舵寚浠�
+	 * @param command start/stop/pause/resume
+	 */
+	private void sendControlCommand(String command) {
+		new Thread(() -> {
+			try {
+				String userId = Usrdell.getUserEmail();
+				String deviceId = Setsys.getMowerIdValue();
+				String msgId = "hxzkcontrol_" + System.currentTimeMillis();
+				
+				if (userId == null || deviceId == null) {
+					System.err.println("鏃犳硶鍙戦�佹寚浠わ細鐢ㄦ埛ID鎴栬澶嘔D涓虹┖");
+					return;
+				}
+				
+				// 鐗规畩澶勭悊锛氬鏋滄槸resume鎸囦护锛堝嵆浠庢殏鍋滅姸鎬佸啀娆$偣鍑诲紑濮嬶級
+				String finalCommand = command;
+				if ("start".equals(command) && "鏆傚仠涓�".equals(statusLabel.getText())) {
+					finalCommand = "resume";
+				}
+				
+				ControlCommandSender sender = ControlCommandSender.createDefault();
+				sender.sendControlCommand(msgId, userId, deviceId, finalCommand, 0.0, "", 0);
+				
+			} catch (Exception e) {
+				e.printStackTrace();
+				SwingUtilities.invokeLater(() -> 
+					showCustomMessageDialog("鎸囦护鍙戦�佸け璐�: " + e.getMessage(), "閿欒"));
+			}
+		}).start();
+	}
+
+	/**
 	 * 妫�鏌ュ壊鑽夋満鏄惁鍦ㄥ綋鍓嶉�変腑鐨勪綔涓氬湴鍧楄竟鐣岃寖鍥村唴
 	 * @return 濡傛灉鍓茶崏鏈哄湪杈圭晫鍐呰繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse骞舵樉绀烘彁绀�
 	 */
@@ -1895,6 +2074,8 @@
 		stopButtonActive = !stopButtonActive;
 		updateStopButtonIcon();
 		if (stopButtonActive) {
+			// 鍙戦�佸仠姝㈡寚浠�
+			sendControlCommand("stop");
 			statusLabel.setText("宸茬粨鏉�");
 			startButtonShowingPause = false;
 			stopMowingSession();

--
Gitblit v1.10.0