826220679@qq.com
3 小时以前 69b40096cb0ae965f2a3e92672b880edfe7d04d2
优化了登录页面
已修改40个文件
已添加2个文件
804 ■■■■ 文件已修改
.classpath 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Obstacledge.properties 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dikuai.properties 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
set.properties 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Mqttmessage/Client.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Mqttmessage/PushCallback.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bianjie/BoundaryAlgorithm.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/DataListener.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/Sendmsg.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/SerialDataReceiver.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/SerialPortAutoConnector.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/SerialPortNativeLoader.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/denglu/Denglu.java 134 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/denglu/RegistrationFrame.java 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/denglu/UserChuShiHua.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/gecaoji/MowerSafetyDistanceCalculator.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/login/LoginTestRunner.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/lujing/AoxinglujingHaveObstacel.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/lujing/AoxinglujingNoObstacle.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/lujing/MowingPathGenerationPage.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/lujing/YixinglujingHaveObstacel.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/lujing/YixinglujingNoObstacle.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/sendMQTT/HTTPUtils/PropertiesFileUploader.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/sendMQTT/Server.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/set/Setsys.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udpdell/Mqttserver.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/udpdell/UDPServer.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/user/Usrdell.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/FiniteChecker.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/yaokong/Control03.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/yaokong/Control05.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/yaokong/Control06.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/yaokong/Control07.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/yaokong/SteeringCommandSender.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/Coordinate.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/MapRenderer.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/ShouyeLauncher.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/WangfanDraw.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/adddikuaiyulan.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/pointandnumber.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/tuowei.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
user.properties 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.classpath
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" path="src"/>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
    <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>
Obstacledge.properties
@@ -1,5 +1,5 @@
# å‰²è‰æœºåœ°å—障碍物配置文件
# ç”Ÿæˆæ—¶é—´ï¼š2025-12-27T13:39:05.917584700
# ç”Ÿæˆæ—¶é—´ï¼š2025-12-27T16:33:13.889689700
# åæ ‡ç³»ï¼šWGS84(度分格式)
# ============ åœ°å—基准站配置 ============
@@ -12,8 +12,3 @@
# æ ¼å¼ï¼šplot.[地块编号].obstacle.[障碍物名称].originalCoords=[坐标串]
# æ ¼å¼ï¼šplot.[地块编号].obstacle.[障碍物名称].xyCoords=[坐标串]
# --- åœ°å—LAND1的障碍物 ---
plot.LAND1.obstacle.障碍物1.shape=1
plot.LAND1.obstacle.障碍物1.originalCoords=0.000000,N;0.000000,E;0.000000,N;0.000000,E;0.000000,N;0.000000,E;0.000000,N;0.000000,E
plot.LAND1.obstacle.障碍物1.xyCoords=53.95,39.88;55.58,45.69;64.53,45.45;66.97,40.57
dikuai.properties
@@ -1,5 +1,5 @@
#Dikuai Properties
#Sat Dec 27 13:39:05 GMT+08:00 2025
#Sat Dec 27 16:33:13 GMT+08:00 2025
LAND1.intelligentSceneAnalysis=-1
LAND1.mowingSafetyDistance=0.53
LAND1.landArea=577.12
@@ -11,8 +11,8 @@
LAND1.returnPathRawCoordinates=-1
LAND1.boundaryOriginalXY=-1
LAND1.mowingWidth=1.00
LAND1.plannedPath=73.871028,49.873176;50.776259,50.037243;41.965934,22.443191;49.612130,19.993609;51.845415,34.259086;66.290000,36.696945;66.290000,21.401369;78.088741,24.750277;73.871028,49.873176;73.955072,49.372566;50.616974,49.538362;50.298405,48.540599;74.123160,48.371347;74.291248,47.370128;49.979836,47.542837;49.661267,46.545075;74.459336,46.368908;74.627423,45.367689;49.342698,45.547313;49.024129,44.549551;55.663908,44.502382;64.552007,44.439240;74.795511,44.366470;74.963599,43.365250;65.098159,43.435335;55.361561,43.504504;48.705560,43.551789;48.386992,42.554027;55.059215,42.506627;65.644310,42.431430;75.131687,42.364031;75.299775,41.362812;66.190462,41.427525;54.756869,41.508750;48.068423,41.556265;47.749854,40.558503;54.454523,40.510872;59.489469,40.475104;75.467863,40.361592;75.635951,39.360373;47.431285,39.560741;47.112716,38.562978;75.804039,38.359154;75.972127,37.357934;46.794147,37.565216;46.475578,36.567454;64.753396,36.437608;66.290000,36.426692;76.140215,36.356715;76.308303,35.355496;66.290000,35.426666;59.067471,35.477976;46.157009,35.569692;45.838440,34.571930;53.381545,34.518343;66.290000,34.426641;76.476391,34.354276;76.644478,33.353057;66.290000,33.426616;51.731282,33.530042;45.519871,33.574168;45.201302,32.576406;51.574900,32.531127;66.290000,32.426591;76.812566,32.351838;76.980654,31.350618;66.290000,31.426565;51.418519,31.532213;44.882733,31.578644;44.564164,30.580882;51.262137,30.533299;66.290000,30.426540;77.148742,30.349399;77.316830,29.348180;66.290000,29.426515;51.105755,29.534385;44.245595,29.583120;43.927026,28.585357;50.949373,28.535470;66.290000,28.426490;77.484918,28.346960;77.653006,27.345741;66.290000,27.426464;50.792992,27.536556;43.608458,27.587595;43.289889,26.589833;50.636610,26.537642;66.290000,26.426439;77.821094,26.344522;77.989182,25.343302;66.290000,25.426414;50.480228,25.538727;42.971320,25.592071;42.652751,24.594309;50.323846,24.539813;66.290000,24.426389;76.687398,24.352525;73.250178,23.376918;66.290000,23.426363;50.167465,23.540899;42.334182,23.596547;42.015613,22.598785;50.011083,22.541985;66.290000,22.426338;69.812957,22.401311;66.375737,21.425704;66.290000,21.426313;49.854701,21.543070;44.660415,21.579971;47.852711,20.557267;49.698319,20.544156
LAND1.updateTime=2025-12-27 13\:39\:05
LAND1.plannedPath=73.87,49.87;50.78,50.04;41.97,22.44;49.61,19.99;51.85,34.26;66.29,36.70;66.29,21.40;78.09,24.75;73.87,49.87;73.96,49.37;50.62,49.54;50.30,48.54;74.12,48.37;74.29,47.37;49.98,47.54;49.66,46.55;74.46,46.37;74.63,45.37;49.34,45.55;49.02,44.55;74.80,44.37;74.96,43.37;48.71,43.55;48.39,42.55;75.13,42.36;75.30,41.36;48.07,41.56;47.75,40.56;75.47,40.36;75.64,39.36;47.43,39.56;47.11,38.56;75.80,38.36;75.97,37.36;46.79,37.57;46.48,36.57;64.75,36.44;66.29,36.43;76.14,36.36;76.31,35.36;66.29,35.43;59.07,35.48;46.16,35.57;45.84,34.57;53.38,34.52;66.29,34.43;76.48,34.35;76.64,33.35;66.29,33.43;51.73,33.53;45.52,33.57;45.20,32.58;51.57,32.53;66.29,32.43;76.81,32.35;76.98,31.35;66.29,31.43;51.42,31.53;44.88,31.58;44.56,30.58;51.26,30.53;66.29,30.43;77.15,30.35;77.32,29.35;66.29,29.43;51.11,29.53;44.25,29.58;43.93,28.59;50.95,28.54;66.29,28.43;77.48,28.35;77.65,27.35;66.29,27.43;50.79,27.54;43.61,27.59;43.29,26.59;50.64,26.54;66.29,26.43;77.82,26.34;77.99,25.34;66.29,25.43;50.48,25.54;42.97,25.59;42.65,24.59;50.32,24.54;66.29,24.43;76.69,24.35;73.25,23.38;66.29,23.43;50.17,23.54;42.33,23.60;42.02,22.60;50.01,22.54;66.29,22.43;69.81,22.40;66.38,21.43;66.29,21.43;49.85,21.54;44.66,21.58;47.85,20.56;49.70,20.54
LAND1.updateTime=2025-12-27 16\:33\:13
LAND1.baseStationCoordinates=3949.89151752,N,11616.79267501,E
LAND1.boundaryPointInterval=-1
LAND1.createTime=2025-12-23 17\:08\:09
@@ -21,6 +21,6 @@
LAND1.landName=123
LAND1.mowingTrack=-1
LAND1.boundaryOriginalCoordinates=39.831522,116.279873,49.25;39.831524,116.279878,49.25;39.831525,116.279878,49.24;39.831524,116.279912,49.30;39.831524,116.279911,49.29;39.831523,116.279911,49.23;39.831521,116.279915,49.31;39.831517,116.279925,49.34;39.831514,116.279940,49.30;39.831514,116.279957,49.28;39.831516,116.279974,49.28;39.831518,116.279991,49.29;39.831521,116.280008,49.24;39.831524,116.280025,49.30;39.831526,116.280042,49.24;39.831529,116.280059,49.29;39.831529,116.280076,49.26;39.831530,116.280093,49.32;39.831531,116.280110,49.28;39.831533,116.280127,49.28;39.831535,116.280144,49.26;39.831539,116.280161,49.27;39.831544,116.280175,49.25;39.831551,116.280190,49.24;39.831558,116.280204,49.26;39.831566,116.280219,49.26;39.831574,116.280234,49.22;39.831583,116.280248,49.24;39.831591,116.280260,49.24;39.831600,116.280272,49.23;39.831608,116.280285,49.18;39.831615,116.280298,49.12;39.831618,116.280312,49.11;39.831618,116.280328,49.12;39.831615,116.280342,49.15;39.831610,116.280356,49.21;39.831602,116.280369,49.23;39.831592,116.280379,49.25;39.831581,116.280388,49.25;39.831569,116.280394,49.19;39.831559,116.280395,49.23;39.831552,116.280387,49.28;39.831547,116.280373,49.32;39.831544,116.280357,49.33;39.831541,116.280340,49.29;39.831539,116.280324,49.27;39.831536,116.280307,49.24;39.831534,116.280290,49.25;39.831531,116.280273,49.26;39.831527,116.280257,49.28;39.831522,116.280242,49.21;39.831514,116.280232,49.28;39.831504,116.280229,49.24;39.831491,116.280230,49.33;39.831478,116.280233,49.34;39.831466,116.280236,49.31;39.831454,116.280239,49.31;39.831441,116.280242,49.26;39.831429,116.280244,49.23;39.831416,116.280247,49.25;39.831402,116.280250,49.22;39.831389,116.280253,49.25;39.831376,116.280256,49.26;39.831364,116.280258,49.24;39.831351,116.280261,49.25;39.831338,116.280265,49.26;39.831324,116.280268,49.20;39.831311,116.280271,49.16;39.831298,116.280274,49.17;39.831285,116.280277,49.22;39.831271,116.280278,49.16;39.831261,116.280273,49.23
LAND1.obstacleCoordinates=(53.95,39.88;55.58,45.69;64.53,45.45;66.97,40.57)
LAND1.obstacleCoordinates=-1
LAND1.boundaryCoordinates=50.39,50.57;74.32,50.40;78.69,24.37;65.76,20.70;65.76,36.07;52.31,33.80;50.04,19.30;41.30,22.10
LAND1.mowingBladeWidth=0.51
set.properties
@@ -1,5 +1,5 @@
#Mower Configuration Properties - Updated
#Sat Dec 27 13:39:12 GMT+08:00 2025
#Current work land selection updated
#Sat Dec 27 20:42:43 GMT+08:00 2025
appVersion=-1
simCardNumber=-1
currentWorkLandNumber=LAND1
@@ -7,13 +7,13 @@
boundaryLengthVisible=false
idleTrailDurationSeconds=60
handheldMarkerId=1872
viewCenterX=-60.00
viewCenterY=-34.94
viewCenterX=-61.89
viewCenterY=-39.06
manualBoundaryDrawingMode=false
mowerId=6258
serialPortName=COM15
serialAutoConnect=true
mapScale=10.32
mapScale=17.84
measurementModeEnabled=false
firmwareVersion=-1
cuttingWidth=200
src/Mqttmessage/Client.java
@@ -57,7 +57,6 @@
     */
    public void connect() throws MqttException {
        if (client != null && client.isConnected()) {
            System.out.println("MQTT客户端已连接,ClientId: " + clientId);
            return;
        }
        
@@ -78,7 +77,6 @@
        
        // æ‰§è¡Œè¿žæŽ¥
        client.connect(options);
        System.out.println("MQTT连接成功!ClientId: " + clientId + ", æœåС噍: " + host + ", ä¸»é¢˜: " + topic);
        
        // å¯åŠ¨è¿žæŽ¥ç›‘æŽ§çº¿ç¨‹
        startConnectionMonitor();
@@ -95,7 +93,6 @@
            connect();
        }
        client.subscribe(topic, qos);
        System.out.println("已订阅主题: " + topic + ", QoS: " + qos);
    }
    
    /**
@@ -132,7 +129,6 @@
                    Thread.sleep(5000);  // æ¯5秒检查一次
                    
                    if (client != null && !client.isConnected()) {
                        System.out.println("检测到MQTT连接断开,尝试重连... ClientId: " + clientId);
                        try {
                            // å°è¯•重新连接
                            if (!client.isConnected()) {
@@ -140,7 +136,6 @@
                                // é‡è¿žæˆåŠŸåŽé‡æ–°è®¢é˜…
                                if (client.isConnected()) {
                                    client.subscribe(topic, qos);
                                    System.out.println("连接监控:重连成功并重新订阅主题: " + topic);
                                }
                            }
                        } catch (Exception e) {
@@ -167,7 +162,6 @@
        connectionMonitorThread.setDaemon(true);
        connectionMonitorThread.setName("MQTT-ConnectionMonitor-" + clientId);
        connectionMonitorThread.start();
        System.out.println("已启动MQTT连接监控线程: " + clientId);
    }
    
    /**
@@ -228,13 +222,11 @@
    public static boolean connectMQTT() {
        // é˜²æ­¢é‡å¤é‡è¿ž
        if (isReconnecting) {
            System.out.println("MQTT正在重连中,跳过本次重连请求");
            return false;
        }
        
        // æ£€æŸ¥æ˜¯å¦å·²ç»è¿žæŽ¥
        if (areClientsConnected()) {
            System.out.println("MQTT客户端已连接,无需重复连接");
            return true;
        }
        
@@ -269,7 +261,6 @@
                    if (gpsClient != null && gpsClient.isConnected()) {
                        gpsClient.subscribe();
                        gpsSuccess = true;
                        System.out.println("GPS主题MQTT连接并订阅成功");
                    }
                } catch (MqttException e) {
                    System.err.println("GPS主题MQTT连接失败: " + e.getMessage());
@@ -291,7 +282,6 @@
                    if (responseClient != null && responseClient.isConnected()) {
                        responseClient.subscribe();
                        responseSuccess = true;
                        System.out.println("响应主题MQTT连接并订阅成功");
                    }
                } catch (MqttException e) {
                    System.err.println("响应主题MQTT连接失败: " + e.getMessage());
@@ -305,10 +295,8 @@
                }
                if (gpsSuccess && responseSuccess) {
                    System.out.println("所有MQTT主题连接并订阅成功!");
                    return true;
                } else if (gpsSuccess || responseSuccess) {
                    System.out.println("部分MQTT主题连接成功");
                    return true;
                } else {
                    System.err.println("所有MQTT主题连接失败");
@@ -337,13 +325,11 @@
    public static boolean connectMQTT(String host, String deviceId, String userEmail) {
        // é˜²æ­¢é‡å¤é‡è¿ž
        if (isReconnecting) {
            System.out.println("MQTT正在重连中,跳过本次重连请求");
            return false;
        }
        
        // æ£€æŸ¥æ˜¯å¦å·²ç»è¿žæŽ¥
        if (areClientsConnected()) {
            System.out.println("MQTT客户端已连接,无需重复连接");
            return true;
        }
        
@@ -376,7 +362,6 @@
                    if (gpsClient != null && gpsClient.isConnected()) {
                        gpsClient.subscribe();
                        gpsSuccess = true;
                        System.out.println("GPS主题MQTT连接并订阅成功");
                    }
                } catch (MqttException e) {
                    System.err.println("GPS主题MQTT连接失败: " + e.getMessage());
@@ -398,7 +383,6 @@
                    if (responseClient != null && responseClient.isConnected()) {
                        responseClient.subscribe();
                        responseSuccess = true;
                        System.out.println("响应主题MQTT连接并订阅成功");
                    }
                } catch (MqttException e) {
                    System.err.println("响应主题MQTT连接失败: " + e.getMessage());
@@ -412,10 +396,8 @@
                }
                if (gpsSuccess && responseSuccess) {
                    System.out.println("所有MQTT主题连接并订阅成功!");
                    return true;
                } else if (gpsSuccess || responseSuccess) {
                    System.out.println("部分MQTT主题连接成功");
                    return true;
                } else {
                    System.err.println("所有MQTT主题连接失败");
@@ -447,7 +429,6 @@
            Client mqttClient = new Client(host, topic, clientId);
            mqttClient.connect();
            mqttClient.subscribe(qos);
            System.out.println("MQTT客户端创建并订阅成功,主题: " + topic + ", ClientId: " + clientId);
            return mqttClient;
        } catch (MqttException e) {
            System.err.println("MQTT客户端创建失败: " + e.getMessage() + ", ä¸»é¢˜: " + topic);
@@ -474,12 +455,10 @@
        try {
            if (gpsClient != null) {
                gpsClient.close();
                System.out.println("GPS主题MQTT连接已断开");
                gpsClient = null;
            }
            if (responseClient != null) {
                responseClient.close();
                System.out.println("响应主题MQTT连接已断开");
                responseClient = null;
            }
        } catch (Exception e) {
src/Mqttmessage/PushCallback.java
@@ -66,7 +66,6 @@
                    try {
                        // é‡æ–°è®¢é˜…主题
                        clientInstance.getClient().subscribe(topic, qos);
                        System.out.println("MQTT重连成功,已重新订阅主题: " + topic);
                        return;  // é‡è¿žæˆåŠŸï¼Œé€€å‡ºå¾ªçŽ¯
                    } catch (Exception e) {
                        System.err.println("重新订阅主题失败: " + e.getMessage());
@@ -74,9 +73,6 @@
                }
                
                retryCount++;
                if (retryCount % 5 == 0) {
                    System.out.println("等待MQTT自动重连... (" + retryCount + "/" + maxRetries + ")");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("重连线程被中断");
@@ -92,7 +88,6 @@
                    clientInstance.connect();
                    if (clientInstance.isConnected()) {
                        clientInstance.subscribe(qos);
                        System.out.println("手动重连成功,已重新订阅主题: " + topic);
                    }
                }
            } catch (Exception e) {
@@ -102,7 +97,7 @@
    }
    public void deliveryComplete(IMqttDeliveryToken token) {
        System.out.println("deliveryComplete---------" + token.isComplete());
        // äº¤ä»˜å®Œæˆå›žè°ƒ
    }
    public void messageArrived(String topic, MqttMessage message) throws Exception {
src/bianjie/BoundaryAlgorithm.java
@@ -116,30 +116,21 @@
    // é«˜çº§å¤„理边界数据方法
    public List<Coordinate> processBoundaryDataAdvanced(String gnggaData, double baseLat, double baseLon, 
                                                       BoundaryParameters params) {
        System.out.println("开始处理边界数据...");
        System.out.println("基准站坐标: " + baseLat + ", " + baseLon);
        System.out.println("参数: é—´éš”=" + params.interval + "ç±³, è§’度阈值=" + params.angleThreshold + "度");
        // 1. è§£æžGNGGA数据
        List<Coordinate> rawPoints = parseGNGGA(gnggaData, baseLat, baseLon);
        System.out.println("解析到原始点: " + rawPoints.size() + " ä¸ª");
        
        if (rawPoints.size() < 3) {
            System.out.println("数据点不足,无法形成边界");
            return new ArrayList<>();
        }
        
        // 2. è¿‡æ»¤å’Œå¹³æ»‘数据
        List<Coordinate> filteredPoints = filterAndSmoothPoints(rawPoints);
        System.out.println("过滤后点: " + filteredPoints.size() + " ä¸ª");
        
        // 3. é«˜çº§è¾¹ç•Œç‚¹ä¼˜åŒ–
        List<Coordinate> optimizedPoints = optimizeBoundaryPointsAdvanced(filteredPoints, params);
        System.out.println("优化后边界点: " + optimizedPoints.size() + " ä¸ª");
        
        // 4. è¾¹ç•Œè´¨é‡è¯„ä¼°
        BoundaryQuality quality = evaluateBoundaryQuality(optimizedPoints);
        System.out.println(quality.toString());
        
        return optimizedPoints;
    }
@@ -167,7 +158,6 @@
        // 5. è‡ªåŠ¨é€‰æ‹©é¢„è®¾åœºæ™¯
        selectPresetAutomatically(analysis);
        
        System.out.println(analysis.toString());
        return analysis;
    }
@@ -287,8 +277,6 @@
        } else {
            analysis.suggestedPreset = "复杂小区域";
        }
        System.out.println("自动场景选择得分: " + String.format("%.2f", score) + " -> " + analysis.suggestedPreset);
    }
    // æ ¹æ®åœºæ™¯åç§°èŽ·å–å‚æ•°
@@ -312,7 +300,6 @@
        }
        
        String[] records = gnggaData.split("\\$GNGGA");
        System.out.println("找到GNGGA记录: " + (records.length - 1) + " æ¡");
        
        for (String record : records) {
            try {
@@ -325,7 +312,6 @@
                
                String[] fields = trimmedRecord.split(",");
                if (fields.length < 7) {
                    System.out.println("记录字段不足: " + trimmedRecord);
                    continue;
                }
                
@@ -334,12 +320,10 @@
                try {
                    fixStatus = Integer.parseInt(fields[6]);
                } catch (NumberFormatException e) {
                    System.out.println("定位状态格式错误: " + fields[6]);
                    continue;
                }
                
                if (fixStatus != 4) {
                    System.out.println("跳过非高精度定位点,状态: " + fixStatus);
                    continue;
                }
                
@@ -415,8 +399,6 @@
            double speed = calculateDistance(points.get(i-1), points.get(i));
            if (speed < 5.0) { // æœ€å¤§åˆç†é€Ÿåº¦ä¸º5ç±³/秒
                filtered.add(points.get(i));
            } else {
                System.out.println("移除高速点: é€Ÿåº¦=" + speed + "ç±³/秒");
            }
        }
        
@@ -462,7 +444,6 @@
        
        // 1. é¦–先进行道格拉斯-普克算法简化
        List<Coordinate> simplified = douglasPeuckerSimplification(points, params.simplificationTolerance);
        System.out.println("道格拉斯-普克简化后: " + simplified.size() + " ä¸ªç‚¹");
        
        // 2. åŸºäºŽè·ç¦»å’Œè§’度的进一步优化
        optimized.add(simplified.get(0));
src/chuankou/DataListener.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
package chuankou;
public interface DataListener<T> {
    void accept(T t);
}
src/chuankou/Sendmsg.java
@@ -95,7 +95,6 @@
     */
    public static void enableDebugMode() {
        DEBUG_MODE = true;
        System.out.println("[" + getCurrentTime() + "] Sendmsg调试模式已启用");
    }
    /**
@@ -103,7 +102,6 @@
     */
    public static void disableDebugMode() {
        DEBUG_MODE = false;
        System.out.println("[" + getCurrentTime() + "] Sendmsg调试模式已禁用");
    }
    /**
@@ -111,7 +109,6 @@
     */
    public static void setDebugMode(boolean debug) {
        DEBUG_MODE = debug;
        System.out.println("[" + getCurrentTime() + "] Sendmsg调试模式: " + (debug ? "启用" : "禁用"));
    }
    /**
@@ -123,10 +120,6 @@
        // æ¸…理ThreadLocal资源
        TIME_FORMATTER.remove();
        STRING_BUILDER_CACHE.remove();
        if (DEBUG_MODE) {
            System.out.println("[" + getCurrentTime() + "] Sendmsg资源清理完成");
        }
    }
    /**
src/chuankou/SerialDataReceiver.java
@@ -36,9 +36,6 @@
        // æ£€æŸ¥ç¼“冲区容量,动态处理
        if (!ensureBufferCapacity(rawData.length)) {
            // ç¼“冲区不足时,清理并重新开始
            if (debugEnabled) {
                System.out.println("缓冲区不足,清空缓冲区重新开始");
            }
            bufferPosition = 0;
        }
        
@@ -79,9 +76,6 @@
            int startIndex = findStartMarker();
            if (startIndex == -1) {
                // æ²¡æœ‰æ‰¾åˆ°èµ·å§‹æ ‡è®°ï¼Œæ¸…空无效数据
                if (debugEnabled) {
                    System.out.println("未找到起始标记,清空缓冲区");
                }
                bufferPosition = 0;
                return;
            }
@@ -100,9 +94,6 @@
            
            // æ£€æŸ¥æ•°æ®é•¿åº¦æœ‰æ•ˆæ€§
            if (dataLength < 0 || totalPacketLength > BUFFER_SIZE) {
                if (debugEnabled) {
                    System.out.println("无效数据长度: " + dataLength + ", è·³è¿‡èµ·å§‹å­—节");
                }
                // è·³è¿‡é”™è¯¯çš„起始标记,继续查找
                compactBuffer(startIndex + 1);
                continue;
@@ -118,10 +109,6 @@
            // æå–完整数据包
            byte[] packet = Arrays.copyOfRange(dataBuffer, startIndex, startIndex + totalPacketLength);
            
            if (debugEnabled) {
                System.out.println("解析到完整数据包: " + bytesToHex(packet));
            }
            // æ·»åŠ åˆ°è¿”å›žåˆ—è¡¨
            completePackets.add(packet);
            
@@ -162,24 +149,7 @@
     * æ‰“印原始数据(调试用)
     */
    private void printRawData(String prefix, byte[] data, int maxPrintLength) {
        if (data == null || data.length == 0) {
            System.out.println(prefix + ": ç©ºæ•°æ®");
            return;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(prefix).append(" [长度: ").append(data.length).append("]: ");
        int printLength = Math.min(data.length, maxPrintLength);
        for (int i = 0; i < printLength; i++) {
            sb.append(String.format("%02X ", data[i]));
        }
        if (data.length > maxPrintLength) {
            sb.append("... [截断,总长度: ").append(data.length).append("]");
        }
        System.out.println(sb.toString());
        // è°ƒè¯•输出已移除
    }
    
    /**
src/chuankou/SerialPortAutoConnector.java
@@ -30,7 +30,6 @@
        if (opened) {
            service.ensureCaptureRunning();
            service.setPaused(false);
            System.out.println("串口自动连接成功: " + portName + " @ " + baudRate);
        } else {
            System.err.println("串口自动连接失败: " + portName + " @ " + baudRate);
        }
src/chuankou/SerialPortNativeLoader.java
@@ -33,8 +33,7 @@
        if (libraryConfigured) {
            return;
        }
        System.out.println("开始初始化 jSerialComm æœ¬åœ°åº“...");
        
        // ç¬¬ä¸€æ­¥ï¼šè®¾ç½®ç³»ç»Ÿå±žæ€§ï¼Œé˜»æ­¢è‡ªåŠ¨ä¸‹è½½
        setCriticalSystemProperties();
@@ -43,14 +42,12 @@
        try {
            extractNativeLibraryFromResources();
            libraryConfigured = true;
            System.out.println("jSerialComm æœ¬åœ°åº“初始化成功");
        } catch (Exception e) {
            System.err.println("从资源提取 DLL å¤±è´¥: " + e.getMessage());
            // å°è¯•备用方案
            try {
                setupLibraryFromFileSystem();
                libraryConfigured = true;
                System.out.println("从文件系统加载 jSerialComm æˆåŠŸ");
            } catch (Exception ex) {
                System.err.println("所有加载方式都失败: " + ex.getMessage());
                // æœ€åŽå°è¯•:允许 jSerialComm ä½¿ç”¨é»˜è®¤æ–¹å¼
@@ -70,9 +67,7 @@
        
        // ç¦ç”¨æ—¥å¿—和调试
        System.setProperty("com.fazecast.jSerialComm.debug", "false");
        System.setProperty("com.fazecast.jSerialComm.log", "false");
        System.out.println("已设置 jSerialComm ç³»ç»Ÿå±žæ€§");
        System.setProperty("com.fazecast.jSerialComm.log", "false");
    }
    /**
@@ -92,7 +87,6 @@
        
        // æ£€æŸ¥ DLL æ˜¯å¦å·²å­˜åœ¨ä¸”可用
        if (Files.exists(dllPath)) {
            System.out.println("DLL å·²å­˜åœ¨äºŽ: " + dllPath);
            // è®¾ç½®åº“路径
            System.setProperty(LIB_PROPERTY, targetDir.toString());
            return;
@@ -132,8 +126,6 @@
            }
        }
        
        System.out.println("DLL å·²æå–到: " + dllPath);
        // è®¾ç½®åº“路径
        System.setProperty(LIB_PROPERTY, targetDir.toString());
        System.setProperty("java.library.path", 
@@ -155,7 +147,6 @@
        for (String path : possiblePaths) {
            File dllFile = new File(path);
            if (dllFile.exists()) {
                System.out.println("找到 DLL: " + dllFile.getAbsolutePath());
                // ä½¿ç”¨ DLL æ‰€åœ¨ç›®å½•
                File parentDir = dllFile.getParentFile();
                System.setProperty(LIB_PROPERTY, parentDir.getAbsolutePath());
src/denglu/Denglu.java
@@ -10,6 +10,7 @@
import user.Usrdell;
import Mqttmessage.Client;
import login.LoginVerifier;
import publicway.buttonset;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
@@ -22,11 +23,10 @@
    private JPasswordField passwordField;
    private JCheckBox rememberMe;
    private JButton loginButton;
    private JButton registerButton;
    private Map<String, Map<String, String>> translations;
    private JPanel mainPanel;
    private JLabel usernameLabel, passwordLabel;
    private JLabel forgotPassword, noAccountLabel, signupLink, appInfoLabel;
    private JLabel forgotPassword, noAccountLabel, signupLink;
    // ä¸»é¢˜é¢œè‰²
    private final Color THEME_COLOR = new Color(46, 139, 87);
@@ -56,7 +56,6 @@
        zh.put("sign_up", "立即注册");
        zh.put("app_title", "智能割草系统");
        zh.put("window_title", "智能割草系统 - ç™»å½•");
        zh.put("app_info", "智能割草系统 Â© 2023 - æ™ºèƒ½å‰²è‰è§£å†³æ–¹æ¡ˆ");
        zh.put("register_button", "注册新账户");
        translations.put("zh", zh);
@@ -71,7 +70,6 @@
        en.put("sign_up", "Sign Up");
        en.put("app_title", "Smart Mowing System");
        en.put("window_title", "Smart Mowing System - Login");
        en.put("app_info", "Smart Mowing System Â© 2023 - Intelligent Lawn Care");
        en.put("register_button", "Create New Account");
        translations.put("en", en);
@@ -86,7 +84,6 @@
        es.put("sign_up", "Regístrate");
        es.put("app_title", "Sistema de Corte Inteligente");
        es.put("window_title", "Sistema de Corte Inteligente - Iniciar Sesión");
        es.put("app_info", "Sistema de Corte Inteligente Â© 2023 - Soluciones Inteligentes");
        es.put("register_button", "Crear Nueva Cuenta");
        translations.put("es", es);
@@ -101,7 +98,6 @@
        fr.put("sign_up", "S'inscrire");
        fr.put("app_title", "Système de Tonte Intelligent");
        fr.put("window_title", "Système de Tonte Intelligent - Connexion");
        fr.put("app_info", "Système de Tonte Intelligent Â© 2023 - Solutions de Tonte");
        fr.put("register_button", "Créer un Nouveau Compte");
        translations.put("fr", fr);
@@ -116,7 +112,6 @@
        de.put("sign_up", "Registrieren");
        de.put("app_title", "Intelligentes Mähsystem");
        de.put("window_title", "Intelligentes Mähsystem - Anmeldung");
        de.put("app_info", "Intelligentes Mähsystem Â© 2023 - Mählösungen");
        de.put("register_button", "Neues Konto Erstellen");
        translations.put("de", de);
    }
@@ -158,12 +153,12 @@
        // ä¸»è¡¨å•区域
        JPanel formPanel = createFormPanel();
        
        // åº•部应用信息
        JPanel appInfoPanel = createAppInfoPanel();
        // åº•部面板(包含注册链接)
        JPanel bottomPanel = createBottomPanel();
        
        mainPanel.add(topPanel, BorderLayout.NORTH);
        mainPanel.add(formPanel, BorderLayout.CENTER);
        mainPanel.add(appInfoPanel, BorderLayout.SOUTH);
        mainPanel.add(bottomPanel, BorderLayout.SOUTH);
        
        add(mainPanel);
    }
@@ -226,75 +221,21 @@
        rememberForgotPanel.add(rememberMe, BorderLayout.WEST);
        rememberForgotPanel.add(forgotPassword, BorderLayout.EAST);
        
        // ç™»å½•按钮 - æ°´å¹³å±…中,长度与文本框宽度保持相近
        // ç™»å½•按钮 - ä½¿ç”¨buttonset创建,水平居中,长度与文本框宽度保持相近
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        buttonPanel.setBackground(Color.WHITE);
        buttonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 50));
        
        loginButton = new JButton("登录");
        loginButton.setBackground(THEME_COLOR);
        loginButton.setForeground(Color.WHITE);
        // ä½¿ç”¨buttonset创建登录按钮,使用主题色
        loginButton = buttonset.createStyledButton("登录", THEME_COLOR);
        loginButton.setFont(new Font("PingFang SC", Font.BOLD, 15));
        // è®¾ç½®ç™»å½•按钮长度接近文本框宽度
        loginButton.setPreferredSize(new Dimension(300, 48));
        loginButton.setBorderPainted(false);
        loginButton.setFocusPainted(false);
        loginButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        // é¼ æ ‡æ‚¬åœæ•ˆæžœ
        loginButton.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                loginButton.setBackground(THEME_HOVER_COLOR);
            }
            public void mouseExited(MouseEvent e) {
                loginButton.setBackground(THEME_COLOR);
            }
        });
        loginButton.setMinimumSize(new Dimension(300, 48));
        loginButton.setMaximumSize(new Dimension(300, 48));
        
        buttonPanel.add(loginButton);
        
        // æ³¨å†ŒæŒ‰é’® - æ›´æ˜Žæ˜¾çš„æ³¨å†Œå…¥å£
        JPanel registerButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        registerButtonPanel.setBackground(Color.WHITE);
        registerButtonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 45));
        registerButton = new JButton("注册新账户");
        registerButton.setBackground(Color.WHITE);
        registerButton.setForeground(THEME_COLOR);
        registerButton.setFont(new Font("PingFang SC", Font.BOLD, 14));
        registerButton.setPreferredSize(new Dimension(180, 42));
        registerButton.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(THEME_COLOR),
            BorderFactory.createEmptyBorder(5, 15, 5, 15)
        ));
        registerButton.setFocusPainted(false);
        registerButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        // æ³¨å†ŒæŒ‰é’®æ‚¬åœæ•ˆæžœ
        registerButton.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                registerButton.setBackground(new Color(240, 250, 240));
            }
            public void mouseExited(MouseEvent e) {
                registerButton.setBackground(Color.WHITE);
            }
        });
        registerButtonPanel.add(registerButton);
        // æ³¨å†Œé“¾æŽ¥ï¼ˆä¿ç•™åŽŸæœ‰çš„æ–‡æœ¬é“¾æŽ¥ï¼‰
        JPanel signupPanel = new JPanel();
        signupPanel.setBackground(Color.WHITE);
        noAccountLabel = new JLabel("还没有账户? ");
        noAccountLabel.setFont(new Font("PingFang SC", Font.PLAIN, 12));
        noAccountLabel.setForeground(new Color(120, 120, 120));
        signupLink = new JLabel("立即注册");
        signupLink.setFont(new Font("PingFang SC", Font.BOLD, 12));
        signupLink.setForeground(THEME_COLOR);
        signupLink.setCursor(new Cursor(Cursor.HAND_CURSOR));
        signupPanel.add(noAccountLabel);
        signupPanel.add(signupLink);
        // ç»„装表单
    formPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        formPanel.add(usernameLabel);
@@ -308,26 +249,33 @@
        formPanel.add(rememberForgotPanel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 20)));
        formPanel.add(buttonPanel); // ç™»å½•按钮
        formPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        formPanel.add(registerButtonPanel); // æ³¨å†ŒæŒ‰é’®
        formPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        formPanel.add(signupPanel); // ä¿ç•™åŽŸæœ‰çš„æ³¨å†Œé“¾æŽ¥
        
        return formPanel;
    }
    private JPanel createAppInfoPanel() {
        JPanel appInfoPanel = new JPanel();
        appInfoPanel.setBackground(Color.WHITE);
        appInfoPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 5, 0));
        appInfoLabel = new JLabel(
            getTranslationValue(currentLanguageCode, "app_info", "智能割草系统 Â© 2023")
        );
        appInfoLabel.setFont(new Font("PingFang SC", Font.PLAIN, 10));
        appInfoLabel.setForeground(new Color(150, 150, 150));
        appInfoPanel.add(appInfoLabel);
    private JPanel createBottomPanel() {
        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
        bottomPanel.setBackground(Color.WHITE);
        
        return appInfoPanel;
        // æ³¨å†Œé“¾æŽ¥ï¼ˆæ”¾åˆ°é¡µé¢æœ€ä¸‹æ–¹ï¼‰
        JPanel signupPanel = new JPanel();
        signupPanel.setBackground(Color.WHITE);
        noAccountLabel = new JLabel("还没有账户? ");
        noAccountLabel.setFont(new Font("PingFang SC", Font.PLAIN, 12));
        noAccountLabel.setForeground(new Color(120, 120, 120));
        signupLink = new JLabel("立即注册");
        signupLink.setFont(new Font("PingFang SC", Font.BOLD, 12));
        signupLink.setForeground(THEME_COLOR);
        signupLink.setCursor(new Cursor(Cursor.HAND_CURSOR));
        signupPanel.add(noAccountLabel);
        signupPanel.add(signupLink);
        signupPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 5, 0));
        // æ³¨å†Œé“¾æŽ¥æ”¾åœ¨æœ€åº•部
        bottomPanel.add(signupPanel);
        return bottomPanel;
    }
    private void setupEventHandlers() {
@@ -356,9 +304,6 @@
                openRegistrationWindow();
            }
        });
        // æ³¨å†ŒæŒ‰é’®ç‚¹å‡»äº‹ä»¶ - æ‰“开注册窗口
        registerButton.addActionListener(e -> openRegistrationWindow());
    }
    private void updateLanguage(String language) {
@@ -375,10 +320,6 @@
            loginButton.setText(getTranslationValue(langCode, "login_button", loginButton.getText()));
            noAccountLabel.setText(getTranslationValue(langCode, "no_account", noAccountLabel.getText()));
            signupLink.setText(getTranslationValue(langCode, "sign_up", signupLink.getText()));
            appInfoLabel.setText(getTranslationValue(langCode, "app_info", appInfoLabel.getText()));
            // æ›´æ–°æ³¨å†ŒæŒ‰é’®æ–‡æœ¬
            registerButton.setText(getTranslationValue(langCode, "register_button", registerButton.getText()));
            // æ›´æ–°çª—口标题
            setTitle(getTranslationValue(langCode, "window_title", getTitle()));
@@ -607,8 +548,6 @@
    }
    public static void launchMainApp() {
        System.out.println("准备打开主应用程序...");
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
@@ -624,14 +563,11 @@
                mainFrame.setResizable(true);
                mainFrame.setLocationRelativeTo(null);
                mainFrame.setVisible(true);
                System.out.println("主应用程序已启动");
                
                // å¯åŠ¨åŽè¿žæŽ¥MQTT
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("正在连接MQTT服务器...");
                        Client.lianjiemqqt();
                    }
                }).start();
@@ -677,11 +613,7 @@
            Device.initializeActiveDevice(setsys.getMowerId());
            UDPServer.startAsync();//启动数据接收线程
            // æ˜¾ç¤ºåˆå§‹æ•°æ®
            System.out.println("初始用户名: " + UserChuShiHua.getProperty("userName"));
            System.out.println("初始密码: " + UserChuShiHua.getProperty("password"));
            // å¯åŠ¨ç™»å½•ç•Œé¢ï¼ˆè‡ªåŠ¨ç™»å½•é€»è¾‘åœ¨ loadUserPreferences ä¸­å¤„理)
            EventQueue.invokeLater(() -> {
                try {
src/denglu/RegistrationFrame.java
@@ -3,6 +3,7 @@
import ui.UIConfig;
import login.EmailCodeSender;
import login.UserRegister;
import publicway.buttonset;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
@@ -264,31 +265,12 @@
        ));
        verificationCodeField.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        // å‘送验证码按钮 - å•独一行
        sendCodeButton = new JButton("发送验证码");
        sendCodeButton.setBackground(THEME_COLOR);
        sendCodeButton.setForeground(Color.WHITE);
        // å‘送验证码按钮 - ä½¿ç”¨buttonset创建
        sendCodeButton = buttonset.createStyledButton("发送验证码", THEME_COLOR);
        sendCodeButton.setFont(new Font("PingFang SC", Font.BOLD, 14));
        sendCodeButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35));
        sendCodeButton.setBorderPainted(false);
        sendCodeButton.setFocusPainted(false);
        sendCodeButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        sendCodeButton.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        // éªŒè¯ç æŒ‰é’®æ‚¬åœæ•ˆæžœ
        sendCodeButton.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                if (sendCodeButton.isEnabled()) {
                    sendCodeButton.setBackground(THEME_HOVER_COLOR);
                }
            }
            public void mouseExited(MouseEvent e) {
                if (sendCodeButton.isEnabled()) {
                    sendCodeButton.setBackground(THEME_COLOR);
                }
            }
        });
        // å¯†ç  - æ ‡ç­¾å·¦å¯¹é½
        passLabel = new JLabel("密码");
        passLabel.setFont(new Font("PingFang SC", Font.BOLD, 13));
@@ -321,36 +303,16 @@
        passwordHintLabel.setForeground(Color.RED);
        passwordHintLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        // æ³¨å†ŒæŒ‰é’® - å•独一行,长度与文本框相同
        registerButton = new JButton("注册");
        registerButton.setBackground(THEME_COLOR);
        registerButton.setForeground(Color.WHITE);
        // æ³¨å†ŒæŒ‰é’® - ä½¿ç”¨buttonset创建,长度与文本框相同
        registerButton = buttonset.createStyledButton("注册", THEME_COLOR);
        registerButton.setFont(new Font("PingFang SC", Font.BOLD, 14));
        registerButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 40));
        registerButton.setBorderPainted(false);
        registerButton.setFocusPainted(false);
        registerButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        registerButton.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        // æ³¨å†ŒæŒ‰é’®æ‚¬åœæ•ˆæžœ
        registerButton.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                registerButton.setBackground(THEME_HOVER_COLOR);
            }
            public void mouseExited(MouseEvent e) {
                registerButton.setBackground(THEME_COLOR);
            }
        });
        // å–消按钮 - å•独一行,长度与文本框相同
        cancelButton = new JButton("取消");
        cancelButton.setBackground(Color.LIGHT_GRAY);
        cancelButton.setForeground(Color.DARK_GRAY);
        // å–消按钮 - ä½¿ç”¨buttonset创建,长度与文本框相同
        cancelButton = buttonset.createStyledButton("取消", Color.LIGHT_GRAY);
        cancelButton.setFont(new Font("PingFang SC", Font.BOLD, 14));
        cancelButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 40));
        cancelButton.setBorderPainted(false);
        cancelButton.setFocusPainted(false);
        cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        cancelButton.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        // ç»„装表单 - ç¼©å°è¡Œé—´è·
src/denglu/UserChuShiHua.java
@@ -11,7 +11,6 @@
        userProperties = new Properties();
        try (InputStream input = new FileInputStream(FILE_PATH)) {
            userProperties.load(input);
            System.out.println("用户数据初始化成功!");
        } catch (IOException e) {
            System.err.println("初始化失败,文件未找到或读取错误: " + e.getMessage());
        }
src/gecaoji/MowerSafetyDistanceCalculator.java
@@ -87,7 +87,6 @@
        
        // ç¡®ä¿è¡Œé—´è·ä¸ºæ­£æ•°
        if (rowSpacing <= 0) {
            System.out.println("警告:割草宽度过小,无法保证全覆盖");
            rowSpacing = cuttingWidth; // è¿”回原始值
        }
        
src/login/LoginTestRunner.java
@@ -7,8 +7,6 @@
public class LoginTestRunner {
    
    public static void main(String[] args) {
        System.out.println("========== ç™»å½•功能测试开始 ==========\n");
        // æµ‹è¯•邮箱验证码发送
        //testSendEmailCode();
        
@@ -25,79 +23,32 @@
     * æµ‹è¯•发送邮箱验证码
     */
    private static void testSendEmailCode() {
        System.out.println("【测试1】发送邮箱验证码");
        System.out.println("----------------------------------------");
        // æµ‹è¯•正常邮箱
        String testEmail = "979909237@qq.com";
        System.out.println("测试邮箱: " + testEmail);
        
        EmailCodeSender.EmailCodeResponse response = EmailCodeSender.sendEmailCode(testEmail);
        System.out.println("请求结果:");
        System.out.println("  âœ“ æˆåŠŸ: " + response.isSuccess());
        System.out.println("  âœ“ çŠ¶æ€ç : " + response.getStatusCode());
        System.out.println("  âœ“ æ¶ˆæ¯: " + response.getMessage());
        if (response.getResponseBody() != null && !response.getResponseBody().isEmpty()) {
            System.out.println("  âœ“ å“åº”体: " + response.getResponseBody());
        }
        System.out.println();
    }
    
    /**
     * æµ‹è¯•登录验证
     */
    private static void testVerifyLogin() {
        System.out.println("【测试2】登录验证");
        System.out.println("----------------------------------------");
        String email = "979909237@qq.com";
        String password = "password123";
        
        System.out.println("测试参数:");
        System.out.println("  - é‚®ç®±: " + email);
        System.out.println("  - å¯†ç : " + password);
        LoginVerifier.LoginVerifyResponse response = LoginVerifier.verifyLogin(email, password);
        System.out.println("验证结果:");
        System.out.println("  âœ“ æˆåŠŸ: " + response.isSuccess());
        System.out.println("  âœ“ çŠ¶æ€ç : " + response.getStatusCode());
        System.out.println("  âœ“ æ¶ˆæ¯: " + response.getMessage());
        if (response.getResponseBody() != null && !response.getResponseBody().isEmpty()) {
            System.out.println("  âœ“ å“åº”体: " + response.getResponseBody());
        }
        System.out.println();
    }
    
    /**
     * æµ‹è¯•用户注册
     */
    private static void testUserRegister() {
        System.out.println("【测试3】用户注册");
        System.out.println("----------------------------------------");
        String email = "979909237@qq.com";
        String password = "password123";
        String code = "709212";
        String nickname = "zshTest";
        
        System.out.println("测试参数:");
        System.out.println("  - é‚®ç®±: " + email);
        System.out.println("  - å¯†ç : " + password);
        System.out.println("  - éªŒè¯ç : " + code);
        System.out.println("  - æ˜µç§°: " + nickname);
        UserRegister.RegisterResponse response = UserRegister.register(email, password, code, nickname,password);
        System.out.println("注册结果:");
        System.out.println("  âœ“ æˆåŠŸ: " + response.isSuccess());
        System.out.println("  âœ“ çŠ¶æ€ç : " + response.getStatusCode());
        System.out.println("  âœ“ æ¶ˆæ¯: " + response.getMessage());
        if (response.getResponseBody() != null && !response.getResponseBody().isEmpty()) {
            System.out.println("  âœ“ å“åº”体: " + response.getResponseBody());
        }
        System.out.println();
    }
    
src/lujing/AoxinglujingHaveObstacel.java
@@ -108,6 +108,14 @@
        List<PathSegment> zigZag = generateFixedZigZag(workArea, obstacles, bestAngle, width, currentPos);
        finalPath.addAll(zigZag);
        // æ ¼å¼åŒ–坐标:保留两位小数
        for (PathSegment segment : finalPath) {
            segment.start.x = Math.round(segment.start.x * 100.0) / 100.0;
            segment.start.y = Math.round(segment.start.y * 100.0) / 100.0;
            segment.end.x = Math.round(segment.end.x * 100.0) / 100.0;
            segment.end.y = Math.round(segment.end.y * 100.0) / 100.0;
        }
        return finalPath;
    }
src/lujing/AoxinglujingNoObstacle.java
@@ -77,6 +77,14 @@
        
        finalPath.addAll(zigZagLines);
        // æ ¼å¼åŒ–坐标:保留两位小数
        for (PathSegment segment : finalPath) {
            segment.start.x = Math.round(segment.start.x * 100.0) / 100.0;
            segment.start.y = Math.round(segment.start.y * 100.0) / 100.0;
            segment.end.x = Math.round(segment.end.x * 100.0) / 100.0;
            segment.end.y = Math.round(segment.end.y * 100.0) / 100.0;
        }
        return finalPath;
    }
src/lujing/MowingPathGenerationPage.java
@@ -831,7 +831,7 @@
        if (sb.length() > 0) {
            sb.append(";");
        }
        sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
        sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y));
    }
    /**
@@ -852,7 +852,7 @@
        if (sb.length() > 0) {
            sb.append(";");
        }
        sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
        sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y));
    }
    
    /**
@@ -873,7 +873,7 @@
        if (sb.length() > 0) {
            sb.append(";");
        }
        sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
        sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y));
    }
    /**
@@ -894,7 +894,7 @@
        if (sb.length() > 0) {
            sb.append(";");
        }
        sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
        sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y));
    }
    
    // ========== UI辅助方法 ==========
src/lujing/YixinglujingHaveObstacel.java
@@ -54,6 +54,17 @@
        
        finalPath.addAll(scanPath);
        
        // 10. æ ¼å¼åŒ–坐标:保留两位小数
        for (PathSegment segment : finalPath) {
            segment.start.x = Math.round(segment.start.x * 100.0) / 100.0;
            segment.start.y = Math.round(segment.start.y * 100.0) / 100.0;
            segment.end.x = Math.round(segment.end.x * 100.0) / 100.0;
            segment.end.y = Math.round(segment.end.y * 100.0) / 100.0;
        }
        // 11. æ‰“印输出路径坐标
        printPathCoordinates(finalPath);
        return finalPath;
    }
    
@@ -610,6 +621,44 @@
        return points;
    }
    
    /**
     * æ‰“印输出路径坐标到控制台
     */
    private static void printPathCoordinates(List<PathSegment> path) {
        if (path == null || path.isEmpty()) {
            System.out.println("路径为空");
            return;
        }
        System.out.println("========== è·¯å¾„坐标输出 ==========");
        System.out.println("总路径段数: " + path.size());
        System.out.println();
        System.out.println("路径坐标序列 (格式: x,y;x,y;...):");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < path.size(); i++) {
            PathSegment segment = path.get(i);
            if (i == 0) {
                // ç¬¬ä¸€ä¸ªæ®µçš„起点
                sb.append(String.format("%.2f,%.2f", segment.start.x, segment.start.y));
            }
            // æ¯ä¸ªæ®µçš„终点
            sb.append(";");
            sb.append(String.format("%.2f,%.2f", segment.end.x, segment.end.y));
        }
        System.out.println(sb.toString());
        System.out.println();
        System.out.println("详细路径信息:");
        for (int i = 0; i < path.size(); i++) {
            PathSegment segment = path.get(i);
            String type = segment.isMowing ? "割草" : "空走";
            System.out.println(String.format("段 %d [%s]: (%.2f,%.2f) -> (%.2f,%.2f)",
                i + 1, type, segment.start.x, segment.start.y, segment.end.x, segment.end.y));
        }
        System.out.println("==================================");
    }
    public static class Point {
        public double x, y;
        public Point(double x, double y) { this.x = x; this.y = y; }
src/lujing/YixinglujingNoObstacle.java
@@ -1,6 +1,8 @@
package lujing;
import java.util.*;
import java.util.Set;
import java.util.HashSet;
/**
 * å¼‚形草地路径规划 - å‡¹å¤šè¾¹å½¢å…¼å®¹ä¼˜åŒ–版 V5.0
@@ -59,6 +61,14 @@
        
        finalPath.addAll(scanPath);
        // 8. æ ¼å¼åŒ–坐标:保留两位小数
        for (PathSegment segment : finalPath) {
            segment.start.x = Math.round(segment.start.x * 100.0) / 100.0;
            segment.start.y = Math.round(segment.start.y * 100.0) / 100.0;
            segment.end.x = Math.round(segment.end.x * 100.0) / 100.0;
            segment.end.y = Math.round(segment.end.y * 100.0) / 100.0;
        }
        return finalPath;
    }
@@ -100,7 +110,7 @@
            for (PathSegment s : lineSegmentsInRow) {
                if (Math.hypot(currentPos.x - s.start.x, currentPos.y - s.start.y) > 0.01) {
                    // å¦‚果间距大于1cm,添加空走路径
                    segments.add(new PathSegment(currentPos, s.start, false));
                    addSafeConnection(segments, currentPos, s.start, polygon);
                }
                segments.add(s);
                currentPos = s.end;
@@ -139,12 +149,31 @@
    private static List<Double> getXIntersections(List<Point> rotatedPoly, double y) {
        List<Double> xIntersections = new ArrayList<>();
        double tolerance = 1e-6;
        for (int i = 0; i < rotatedPoly.size(); i++) {
            Point p1 = rotatedPoly.get(i);
            Point p2 = rotatedPoly.get((i + 1) % rotatedPoly.size());
            if ((p1.y <= y && p2.y > y) || (p2.y <= y && p1.y > y)) {
            // è·³è¿‡æ°´å¹³è¾¹ï¼ˆé¿å…ä¸Žæ‰«æçº¿é‡åˆæ—¶çš„特殊情况)
            if (Math.abs(p1.y - p2.y) < tolerance) {
                continue;
            }
            // æ£€æŸ¥æ˜¯å¦ç›¸äº¤ï¼ˆä½¿ç”¨ä¸¥æ ¼ä¸ç­‰å¼é¿å…é¡¶ç‚¹é‡å¤ï¼‰
            if ((p1.y < y && p2.y >= y) || (p2.y < y && p1.y >= y)) {
                double x = p1.x + (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y);
                xIntersections.add(x);
                // ç®€å•去重:检查是否已存在相近的点
                boolean isDuplicate = false;
                for (double existingX : xIntersections) {
                    if (Math.abs(x - existingX) < tolerance) {
                        isDuplicate = true;
                        break;
                    }
                }
                if (!isDuplicate) {
                    xIntersections.add(x);
                }
            }
        }
        return xIntersections;
@@ -171,7 +200,7 @@
        return maxY - minY;
    }
    private static List<Point> getInsetPolygon(List<Point> points, double margin) {
    public static List<Point> getInsetPolygon(List<Point> points, double margin) {
        List<Point> result = new ArrayList<>();
        int n = points.size();
        for (int i = 0; i < n; i++) {
@@ -207,12 +236,114 @@
        return result;
    }
    private static void addSafeConnection(List<PathSegment> segments, Point start, Point end, List<Point> polygon) {
        if (isSegmentSafe(start, end, polygon)) {
            segments.add(new PathSegment(start, end, false));
        } else {
            List<Point> path = getBoundaryPath(start, end, polygon);
            for (int i = 0; i < path.size() - 1; i++) {
                segments.add(new PathSegment(path.get(i), path.get(i+1), false));
            }
        }
    }
    private static boolean isSegmentSafe(Point p1, Point p2, List<Point> polygon) {
        Point mid = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
        if (!isPointInPolygon(mid, polygon)) return false;
        for (int i = 0; i < polygon.size(); i++) {
            Point a = polygon.get(i);
            Point b = polygon.get((i + 1) % polygon.size());
            if (isSamePoint(p1, a) || isSamePoint(p1, b) || isSamePoint(p2, a) || isSamePoint(p2, b)) continue;
            if (segmentsIntersect(p1, p2, a, b)) return false;
        }
        return true;
    }
    private static boolean isSamePoint(Point a, Point b) {
        return Math.abs(a.x - b.x) < 1e-4 && Math.abs(a.y - b.y) < 1e-4;
    }
    private static boolean segmentsIntersect(Point a, Point b, Point c, Point d) {
        return ccw(a, c, d) != ccw(b, c, d) && ccw(a, b, c) != ccw(a, b, d);
    }
    private static boolean ccw(Point a, Point b, Point c) {
        return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
    }
    private static boolean isPointInPolygon(Point p, List<Point> polygon) {
        boolean result = false;
        for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) {
            if ((polygon.get(i).y > p.y) != (polygon.get(j).y > p.y) &&
                (p.x < (polygon.get(j).x - polygon.get(i).x) * (p.y - polygon.get(i).y) / (polygon.get(j).y - polygon.get(i).y) + polygon.get(i).x)) {
                result = !result;
            }
        }
        return result;
    }
    private static List<Point> getBoundaryPath(Point start, Point end, List<Point> polygon) {
        int idx1 = getEdgeIndex(start, polygon);
        int idx2 = getEdgeIndex(end, polygon);
        if (idx1 == -1 || idx2 == -1 || idx1 == idx2) {
            return Arrays.asList(start, end);
        }
        List<Point> path1 = new ArrayList<>();
        path1.add(start);
        int curr = idx1;
        while (curr != idx2) {
            path1.add(polygon.get((curr + 1) % polygon.size()));
            curr = (curr + 1) % polygon.size();
        }
        path1.add(end);
        List<Point> pathRev = new ArrayList<>();
        pathRev.add(start);
        curr = idx1;
        while (curr != idx2) {
            pathRev.add(polygon.get(curr));
            curr = (curr - 1 + polygon.size()) % polygon.size();
        }
        pathRev.add(polygon.get((idx2 + 1) % polygon.size()));
        pathRev.add(end);
        return getPathLength(path1) < getPathLength(pathRev) ? path1 : pathRev;
    }
    private static double getPathLength(List<Point> path) {
        double len = 0;
        for (int i = 0; i < path.size() - 1; i++) {
            len += Math.hypot(path.get(i).x - path.get(i+1).x, path.get(i).y - path.get(i+1).y);
        }
        return len;
    }
    private static int getEdgeIndex(Point p, List<Point> poly) {
        for (int i = 0; i < poly.size(); i++) {
            Point p1 = poly.get(i);
            Point p2 = poly.get((i + 1) % poly.size());
            if (distToSegment(p, p1, p2) < 1e-3) return i;
        }
        return -1;
    }
    private static double distToSegment(Point p, Point s, Point e) {
        double l2 = (s.x - e.x)*(s.x - e.x) + (s.y - e.y)*(s.y - e.y);
        if (l2 == 0) return Math.hypot(p.x - s.x, p.y - s.y);
        double t = ((p.x - s.x) * (e.x - s.x) + (p.y - s.y) * (e.y - s.y)) / l2;
        t = Math.max(0, Math.min(1, t));
        return Math.hypot(p.x - (s.x + t * (e.x - s.x)), p.y - (s.y + t * (e.y - s.y)));
    }
    private static Point rotatePoint(Point p, double angle) {
        double cos = Math.cos(angle), sin = Math.sin(angle);
        return new Point(p.x * cos - p.y * sin, p.x * sin + p.y * cos);
    }
    private static void ensureCounterClockwise(List<Point> points) {
    public static void ensureCounterClockwise(List<Point> points) {
        double sum = 0;
        for (int i = 0; i < points.size(); i++) {
            Point p1 = points.get(i), p2 = points.get((i + 1) % points.size());
src/sendMQTT/HTTPUtils/PropertiesFileUploader.java
@@ -146,7 +146,6 @@
        
        // è°ƒç”¨Server.propertiesFileToJson方法生成JSON字符串
        String jsonData = propertiesFileToJson(filePath);
        System.out.println("已成功将Properties文件转换为JSON: " + filePath);
        
        // æž„建完整的URL(包含filename参数,进行URL编码)
        String encodedFilename = URLEncoder.encode(filename, StandardCharsets.UTF_8.name());
@@ -170,7 +169,6 @@
            ObjectMapper objectMapper = new ObjectMapper();
            FileUploadResponse response = objectMapper.readValue(responseJson, FileUploadResponse.class);
            
            System.out.println("文件上传成功: " + response.getSavedFilename());
            return response;
            
        } finally {
src/sendMQTT/Server.java
@@ -71,7 +71,6 @@
            MqttMessage message = new MqttMessage();
            message.setPayload(messageJson.getBytes("UTF-8"));
            client.publish(topic, message);
            System.out.println("发送数据到主题: " + topic);
        } catch (MqttException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
src/set/Setsys.java
@@ -264,14 +264,7 @@
     * æ˜¾ç¤ºå½“前所有属性值
     */
    public void displayProperties() {
        System.out.println("当前属性值:");
        System.out.println("mowerId: " + (mowerId != null ? mowerId : "未设置"));
        System.out.println("cuttingWidth: " + (cuttingWidth != null ? cuttingWidth : "未设置"));
        System.out.println("simCardNumber: " + (simCardNumber != null ? simCardNumber : "未设置"));
    System.out.println("handheldMarkerId: " + (handheldMarkerId != null ? handheldMarkerId : "未设置"));
        System.out.println("firmwareVersion: " + (firmwareVersion != null ? firmwareVersion : "未设置"));
        System.out.println("appVersion: " + (appVersion != null ? appVersion : "未设置"));
        System.out.println("idleTrailDurationSeconds: " + idleTrailDurationSeconds);
        // æ˜¾ç¤ºå±žæ€§åŠŸèƒ½å·²ç¦ç”¨
    }
    /**
src/udpdell/Mqttserver.java
@@ -23,7 +23,6 @@
        ResponseData responseData = null;
        try {
            responseData = DeviceMessageParser.parseResponseData(responseJson);
            System.out.println("原始消息ID: " + responseData.getOriginalMsgId());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
@@ -61,10 +60,8 @@
                "  }\n" +
                "}";
        try {
            System.out.println("=== GPS数据解析示例(新协议格式) ===");
            GPSData gpsData2 = DeviceMessageParser.parseGPSData(gpsJsonStr);
            String string2 = gpsData2.toString();
            System.out.println(string2);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
@@ -85,7 +82,6 @@
                0.5,   // é€Ÿåº¦0.5ç±³/秒
                10     // æŒç»­10秒
        );
        System.out.println(json2);
    }
src/udpdell/UDPServer.java
@@ -50,8 +50,6 @@
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
        try (DatagramSocket socket = new DatagramSocket(PORT)) {
            System.out.println("UDPServer started on port " + PORT);
            while (!Thread.currentThread().isInterrupted()) {
                byte[] buffer = new byte[BUFFER_SIZE];
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
@@ -86,7 +84,6 @@
            return;
        }
        int sequence = incrementReceivedPacketCounter();
        System.out.println("收到了差分数据(" + sequence + "):" + message);
        // ä½¿ç”¨Gpstoxuzuobiao处理并获取XY坐标
        double[] xy = Gpstoxuzuobiao.processGNGGAToXY(message);
@@ -97,7 +94,6 @@
        Coordinate.parseGNGGAToCoordinateList(message);
        int count = Coordinate.coordinates.size();
        System.out.println("savenum:" + count);
        Device.updateFromGNGGA(message, fields[15]);
    }
@@ -118,7 +114,6 @@
            return;
        }
        int sequence = incrementReceivedPacketCounter();
        System.out.println("收到了串口数据(" + sequence + "):" + message);
        // ä½¿ç”¨Gpstoxuzuobiao处理并获取XY坐标
        double[] xy = Gpstoxuzuobiao.processGNGGAToXY(message);
@@ -129,7 +124,6 @@
        Coordinate.dellchuankougngga(message);
        int count = Coordinate.coordinates.size();
        System.out.println("savenum:" + count);
        Device.updateFromSerialGNGGA(message);
    }
src/user/Usrdell.java
@@ -32,7 +32,6 @@
            userProperties = new Properties();
            try (FileInputStream input = new FileInputStream(PROPERTIES_FILE)) {
                userProperties.load(input);
                System.out.println("用户属性初始化成功!");
            } catch (IOException e) {
                System.err.println("初始化失败,文件未找到或读取错误: " + e.getMessage());
                // å¦‚果文件不存在,创建默认属性
src/utils/FiniteChecker.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package utils;
/**
 * å·¥å…·ç±»ï¼šæ£€æŸ¥double值是否有限(兼容低版本Java)
 * ç”¨äºŽæ›¿ä»£ Double.isFinite() æ–¹æ³•
 */
public final class FiniteChecker {
    private FiniteChecker() {
        // å·¥å…·ç±»ï¼Œä¸å…è®¸å®žä¾‹åŒ–
    }
    /**
     * æ£€æŸ¥double值是否有限(不是NaN或无穷大)
     * @param value è¦æ£€æŸ¥çš„double值
     * @return true如果值是有限的,false如果是NaN或无穷大
     */
    public static boolean isFinite(double value) {
        return !Double.isNaN(value) && !Double.isInfinite(value);
    }
}
src/yaokong/Control03.java
@@ -217,9 +217,6 @@
        nextForward = clampSpeed(nextForward);
        byte[] payload = buildSteeringCommandBytes((byte) nextSteering, (byte) nextForward);
        
        // è°ƒè¯•:打印发送的数据
        System.out.println("发送转向指令: " + bytesToHex(payload));
        boolean success = sendmessage.sendViaActive(payload);
        if (success) {
            currentSteeringSpeed = nextSteering;
@@ -299,23 +296,17 @@
     * æµ‹è¯•函数:验证转向指令构建
     */
    public static void testBuildSteeringCommand() {
        System.out.println("=== æµ‹è¯•修正后的转向指令构建 ===");
        // æµ‹è¯•1:直行前进
        byte[] cmd1 = buildSteeringCommandBytes((byte)0, (byte)50);
        System.out.println("直行前进50: " + bytesToHex(cmd1));
        
        // æµ‹è¯•2:左转前进
        byte[] cmd2 = buildSteeringCommandBytes((byte)-30, (byte)40);
        System.out.println("左转前进: " + bytesToHex(cmd2));
        
        // æµ‹è¯•3:右转后退
        byte[] cmd3 = buildSteeringCommandBytes((byte)20, (byte)-60);
        System.out.println("右转后退: " + bytesToHex(cmd3));
        
        // æµ‹è¯•4:停止
        byte[] cmd4 = buildSteeringCommandBytes((byte)0, (byte)0);
        System.out.println("停止: " + bytesToHex(cmd4));
    }
      
}
src/yaokong/Control05.java
@@ -158,9 +158,6 @@
        }
        byte[] payload = buildPowerCommandBytes(powerValue);
        
        // è°ƒè¯•:打印发送的数据
        System.out.println("发送电源控制指令: " + bytesToHex(payload));
        return sendmessage.sendViaActive(payload);
    }
    
@@ -186,14 +183,10 @@
     * æµ‹è¯•函数:验证电源控制指令构建
     */
    public static void testBuildPowerCommand() {
        System.out.println("=== æµ‹è¯•电源控制指令构建 ===");
        // æµ‹è¯•1:启动指令
        byte[] cmd1 = buildPowerCommandBytes((byte)1);
        System.out.println("启动机器: " + bytesToHex(cmd1));
        
        // æµ‹è¯•2:关闭指令
        byte[] cmd2 = buildPowerCommandBytes((byte)0);
        System.out.println("关闭机器: " + bytesToHex(cmd2));
    }
}
src/yaokong/Control06.java
@@ -180,8 +180,6 @@
        }
        byte[] payload = buildBladeCommandBytes((byte) targetHeight);
        
        // è°ƒè¯•:打印发送的数据
        System.out.println("发送刀盘升降指令: " + bytesToHex(payload));
        
        boolean success = sendmessage.sendViaActive(payload);
        if (success) {
@@ -228,18 +226,13 @@
     * æµ‹è¯•函数:验证刀盘升降指令构建
     */
    public static void testBuildBladeCommand() {
        System.out.println("=== æµ‹è¯•刀盘升降指令构建 ===");
        // æµ‹è¯•1:提升指令
        byte[] cmd1 = buildBladeCommandBytes((byte)50);
        System.out.println("提升50%: " + bytesToHex(cmd1));
        
        // æµ‹è¯•2:降低指令
        byte[] cmd2 = buildBladeCommandBytes((byte)-30);
        System.out.println("降低30%: " + bytesToHex(cmd2));
        
        // æµ‹è¯•3:归零指令
        byte[] cmd3 = buildBladeCommandBytes((byte)0);
        System.out.println("归零: " + bytesToHex(cmd3));
    }
}
src/yaokong/Control07.java
@@ -157,9 +157,6 @@
        }
        byte[] payload = buildLightCommandBytes(lightValue);
        
        // è°ƒè¯•:打印发送的数据
        System.out.println("发送大灯控制指令: " + bytesToHex(payload));
        return sendmessage.sendViaActive(payload);
    }
    
@@ -185,14 +182,10 @@
     * æµ‹è¯•函数:验证大灯控制指令构建
     */
    public static void testBuildLightCommand() {
        System.out.println("=== æµ‹è¯•大灯控制指令构建 ===");
        // æµ‹è¯•1:开灯指令
        byte[] cmd1 = buildLightCommandBytes((byte)1);
        System.out.println("开启大灯: " + bytesToHex(cmd1));
        
        // æµ‹è¯•2:关灯指令
        byte[] cmd2 = buildLightCommandBytes((byte)0);
        System.out.println("关闭大灯: " + bytesToHex(cmd2));
    }
}
src/yaokong/SteeringCommandSender.java
@@ -19,9 +19,6 @@
        // ä½¿ç”¨ä¿®æ­£åŽçš„æ–¹æ³•构建指令
        byte[] commandBytes = buildSteeringCommandBytes(steeringSpeed, forwardSpeed);
        
        // è°ƒè¯•:打印发送的数据
        System.out.println("发送修正后的转向指令: " + bytesToHex(commandBytes));
        // å‘送数据
        outputStream.write(commandBytes);
        outputStream.flush();
src/zhuye/Coordinate.java
@@ -276,8 +276,6 @@
            String line;
            StringBuilder gnggaData = new StringBuilder();
            System.out.println("开始读取GNGGA文件: " + file.getAbsolutePath());
            while ((line = reader.readLine()) != null) {
                // æ¸…理数据:移除多余的空格和换行
                line = line.trim();
@@ -295,18 +293,6 @@
            if (gnggaData.length() > 0) {
                parseGNGGAToCoordinateList(gnggaData.toString());
                loadedCount = coordinates.size();
                System.out.println("成功加载 " + loadedCount + " ä¸ªåæ ‡ç‚¹");
                // è¾“出统计信息
                if (loadedCount > 0) {
                    double[] elevationRange = getElevationRange();
                    double avgElevation = getAverageElevation();
                    System.out.println("海拔统计: èŒƒå›´=" + String.format("%.2f", elevationRange[0]) +
                            " - " + String.format("%.2f", elevationRange[1]) + "ç±³, å¹³å‡=" +
                            String.format("%.2f", avgElevation) + "ç±³");
                }
            } else {
                System.out.println("文件中未找到有效的GNGGA数据");
            }
        } catch (IOException e) {
src/zhuye/MapRenderer.java
@@ -18,6 +18,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.Consumer;
import java.io.File;
import set.Setsys;
import gecaoji.Device;
@@ -632,7 +633,7 @@
     * æ·»åŠ å¯¼èˆªé¢„è§ˆè½¨è¿¹ç‚¹
     */
    public void addNavigationPreviewTrackPoint(Point2D.Double point) {
        if (point != null && Double.isFinite(point.x) && Double.isFinite(point.y)) {
        if (point != null && isFinite(point.x) && isFinite(point.y)) {
            navigationPreviewTrack.add(new Point2D.Double(point.x, point.y));
            if (visualizationPanel != null) {
                visualizationPanel.repaint();
@@ -750,7 +751,7 @@
            return;
        }
        Point2D.Double position = mower.getPosition();
        if (position == null || !Double.isFinite(position.x) || !Double.isFinite(position.y)) {
        if (position == null || !isFinite(position.x) || !isFinite(position.y)) {
            pendingTrackBreak = true;
            return;
        }
@@ -776,7 +777,7 @@
        }
        realtimeMowingTrack.add(candidate);
        if (!pendingTrackBreak && lastPoint != null && Double.isFinite(distance)) {
        if (!pendingTrackBreak && lastPoint != null && isFinite(distance)) {
            trackLengthMeters += distance;
        }
@@ -807,7 +808,7 @@
        }
        Point2D.Double position = mower.getPosition();
        if (position == null || !Double.isFinite(position.x) || !Double.isFinite(position.y)) {
        if (position == null || !isFinite(position.x) || !isFinite(position.y)) {
            return;
        }
@@ -852,7 +853,7 @@
        // åˆ·æ–°mower位置,使用最新的Device数据
        mower.refreshFromDevice();
        Point2D.Double position = mower.getPosition();
        if (position == null || !Double.isFinite(position.x) || !Double.isFinite(position.y)) {
        if (position == null || !isFinite(position.x) || !isFinite(position.y)) {
            return;
        }
@@ -963,7 +964,7 @@
    }
    private String formatTrackCoordinate(double value) {
        if (!Double.isFinite(value)) {
        if (!isFinite(value)) {
            return "0";
        }
        return String.format(Locale.US, "%.3f", value);
@@ -1154,7 +1155,7 @@
            try {
                double x = Double.parseDouble(parts[0].trim());
                double y = Double.parseDouble(parts[1].trim());
                if (!Double.isFinite(x) || !Double.isFinite(y)) {
                if (!isFinite(x) || !isFinite(y)) {
                    continue;
                }
                Point2D.Double current = new Point2D.Double(x, y);
@@ -1459,6 +1460,7 @@
        String safetyDistance = null;
        String obstaclesCoords = null;
        String mowingPattern = null;
        String plannedPathStr = null;
        
        // ä»Žå½“前地块编号获取地块信息
        if (currentBoundaryLandNumber != null) {
@@ -1468,6 +1470,8 @@
                mowingWidth = landData.getMowingWidth();
                safetyDistance = landData.getMowingSafetyDistance();
                mowingPattern = landData.getMowingPattern();
                // ä»Žåœ°å—获取plannedPath属性值作为路径
                plannedPathStr = landData.getPlannedPath();
                
                // èŽ·å–éšœç¢ç‰©åæ ‡
                try {
@@ -1525,9 +1529,18 @@
            }
        }
        
        // å¦‚果从地块获取到了路径,使用地块的路径;否则使用currentPlannedPath
        List<Point2D.Double> pathToDraw = currentPlannedPath;
        if (plannedPathStr != null && !plannedPathStr.trim().isEmpty() && !"-1".equals(plannedPathStr.trim())) {
            // ä»Žåœ°å—获取的路径
            pathToDraw = lujingdraw.parsePlannedPath(plannedPathStr);
        }
        // è°ƒç”¨å¸¦åœ°å—信息的绘制方法
        lujingdraw.drawPlannedPath(g2d, currentPlannedPath, scale, arrowScale,
        if (pathToDraw != null && pathToDraw.size() >= 2) {
            lujingdraw.drawPlannedPath(g2d, pathToDraw, scale, arrowScale,
                                   boundaryCoords, mowingWidth, safetyDistance, obstaclesCoords, mowingPattern);
        }
    }
    private void drawCircleSampleMarkers(Graphics2D g2d, List<double[]> markers, double scale) {
@@ -1549,7 +1562,7 @@
        FontMetrics metrics = g2d.getFontMetrics(labelFont);
        
        for (double[] pt : markers) {
            if (pt == null || pt.length < 2 || !Double.isFinite(pt[0]) || !Double.isFinite(pt[1])) {
            if (pt == null || pt.length < 2 || !isFinite(pt[0]) || !isFinite(pt[1])) {
                continue;
            }
            double x = pt[0];
@@ -1647,7 +1660,7 @@
                }
                double x = pt[0];
                double y = pt[1];
                if (!Double.isFinite(x) || !Double.isFinite(y)) {
                if (!isFinite(x) || !isFinite(y)) {
                    continue;
                }
                circleSampleMarkers.add(new double[]{x, y});
@@ -1870,7 +1883,7 @@
    private double computeSelectionThresholdPixels() {
        double scaleFactor = Math.max(0.5, scale);
        double diameterScale = boundaryPointSizeScale * (previewSizingEnabled ? PREVIEW_BOUNDARY_MARKER_SCALE : 1.0d);
        if (!Double.isFinite(diameterScale) || diameterScale <= 0.0d) {
        if (!isFinite(diameterScale) || diameterScale <= 0.0d) {
            diameterScale = 1.0d;
        }
        double markerDiameterWorld = Math.max(1.0, (10.0 / scaleFactor) * 0.2 * diameterScale);
@@ -2035,7 +2048,7 @@
    }
    private boolean isPointInsideActiveBoundary(Point2D.Double point) {
        if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) {
        if (point == null || !isFinite(point.x) || !isFinite(point.y)) {
            return false;
        }
        if (realtimeTrackLandNumber == null) {
@@ -2046,7 +2059,7 @@
    }
    private boolean isPointInsideBoundary(Point2D.Double point, Path2D.Double path) {
        if (point == null || path == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) {
        if (point == null || path == null || !isFinite(point.x) || !isFinite(point.y)) {
            return false;
        }
        if (path.contains(point.x, point.y)) {
@@ -2067,7 +2080,7 @@
        Path2D.Double path = new Path2D.Double();
        boolean started = false;
        for (Point2D.Double point : boundary) {
            if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) {
            if (point == null || !isFinite(point.x) || !isFinite(point.y)) {
                continue;
            }
            if (!started) {
@@ -2103,7 +2116,7 @@
        // è®¾ç½®ç‚¹çš„大小(随缩放变化)
        double scaleFactor = Math.max(0.5, scale);
        double clampedScale = boundaryPointSizeScale * (previewSizingEnabled ? PREVIEW_BOUNDARY_MARKER_SCALE : 1.0d);
        if (!Double.isFinite(clampedScale) || clampedScale <= 0.0d) {
        if (!isFinite(clampedScale) || clampedScale <= 0.0d) {
            clampedScale = 1.0d;
        }
        double minimumDiameter = clampedScale < 1.0 ? 0.5 : 1.0;
@@ -2552,7 +2565,7 @@
            }
            double x = coord.getX();
            double y = coord.getY();
            if (!Double.isFinite(x) || !Double.isFinite(y)) {
            if (!isFinite(x) || !isFinite(y)) {
                continue;
            }
            copy.add(new Obstacledge.XYCoordinate(x, y));
@@ -2890,7 +2903,7 @@
    }
    public void setBoundaryPointSizeScale(double sizeScale) {
        double normalized = (Double.isFinite(sizeScale) && sizeScale > 0.0d) ? sizeScale : 1.0d;
        double normalized = (isFinite(sizeScale) && sizeScale > 0.0d) ? sizeScale : 1.0d;
        if (Math.abs(boundaryPointSizeScale - normalized) < 1e-6) {
            return;
        }
@@ -2918,7 +2931,7 @@
    }
    public void setBoundaryPreviewMarkerScale(double markerScale) {
        double normalized = Double.isFinite(markerScale) && markerScale > 0.0d ? markerScale : 1.0d;
        double normalized = isFinite(markerScale) && markerScale > 0.0d ? markerScale : 1.0d;
        if (Math.abs(boundaryPreviewMarkerScale - normalized) < 1e-6) {
            return;
        }
@@ -2955,7 +2968,7 @@
    }
    public void addHandheldBoundaryPoint(double x, double y) {
        if (!Double.isFinite(x) || !Double.isFinite(y)) {
        if (!isFinite(x) || !isFinite(y)) {
            return;
        }
        if (!handheldBoundaryPreviewActive) {
@@ -3067,8 +3080,8 @@
        Point2D.Double mowerPosition = mower.getPosition();
        if (mowerPosition == null
            || !Double.isFinite(mowerPosition.x)
            || !Double.isFinite(mowerPosition.y)) {
            || !isFinite(mowerPosition.x)
            || !isFinite(mowerPosition.y)) {
            return expanded;
        }
@@ -3512,9 +3525,9 @@
    /**
     * è®¾ç½®è¾¹ç•Œé¢„览更新回调
     */
    private java.util.function.Consumer<String> boundaryPreviewUpdateCallback;
    private Consumer<String> boundaryPreviewUpdateCallback;
    
    public void setBoundaryPreviewUpdateCallback(java.util.function.Consumer<String> callback) {
    public void setBoundaryPreviewUpdateCallback(Consumer<String> callback) {
        this.boundaryPreviewUpdateCallback = callback;
    }
@@ -3531,4 +3544,12 @@
            fitBoundsToView(bounds);
        }
    }
}
    /**
     * æ£€æŸ¥double值是否有限(不是NaN或无穷大)
     * å…¼å®¹ä½Žç‰ˆæœ¬Java
     */
    private static boolean isFinite(double value) {
        return !Double.isNaN(value) && !Double.isInfinite(value);
    }
}
src/zhuye/ShouyeLauncher.java
@@ -7,7 +7,6 @@
public class ShouyeLauncher {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            System.out.println("Starting Shouye via Launcher...");
            JFrame frame = new JFrame("AutoMow - é¦–页");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(400, 800);
src/zhuye/WangfanDraw.java
@@ -208,13 +208,13 @@
        double lat = helper.parseDMToDecimal(latest.getLatitude(), latest.getLatDirection());
        double lon = helper.parseDMToDecimal(latest.getLongitude(), latest.getLonDirection());
        if (!Double.isFinite(lat) || !Double.isFinite(lon)) {
        if (!isFinite(lat) || !isFinite(lon)) {
            return;
        }
        double[] local = helper.convertLatLonToLocal(lat, lon, baseLatLon[0], baseLatLon[1]);
        Point2D.Double candidate = new Point2D.Double(local[0], local[1]);
        if (!Double.isFinite(candidate.x) || !Double.isFinite(candidate.y)) {
        if (!isFinite(candidate.x) || !isFinite(candidate.y)) {
            return;
        }
@@ -427,5 +427,12 @@
        g2d.setStroke(new BasicStroke(dashWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 10.0f, dashPattern, 0.0f));
        g2d.draw(path);
    }
    /**
     * æ£€æŸ¥double值是否有限(不是NaN或无穷大)
     * å…¼å®¹ä½Žç‰ˆæœ¬Java
     */
    private static boolean isFinite(double value) {
        return !Double.isNaN(value) && !Double.isInfinite(value);
    }
}
src/zhuye/adddikuaiyulan.java
@@ -41,7 +41,7 @@
        // è¿‡æ»¤æœ‰æ•ˆç‚¹
        List<Point2D.Double> validPoints = new java.util.ArrayList<>();
        for (Point2D.Double point : previewPoints) {
            if (point != null && Double.isFinite(point.x) && Double.isFinite(point.y)) {
            if (point != null && isFinite(point.x) && isFinite(point.y)) {
                validPoints.add(point);
            }
        }
@@ -125,12 +125,12 @@
    double effectiveScale = Math.max(0.01d, scale);
    double markerSize = cachedMarkerPixelDiameter / effectiveScale;
    double normalizedScale = Double.isFinite(diameterScale) && diameterScale > 0.0d ? diameterScale : 1.0d;
    double normalizedScale = isFinite(diameterScale) && diameterScale > 0.0d ? diameterScale : 1.0d;
    markerSize *= normalizedScale;
    double markerRadius = markerSize / 2.0d;
        for (Point2D.Double point : previewPoints) {
            if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) {
            if (point == null || !isFinite(point.x) || !isFinite(point.y)) {
                continue;
            }
            Shape marker = new Ellipse2D.Double(point.x - markerRadius, point.y - markerRadius, markerSize, markerSize);
@@ -141,4 +141,12 @@
        g2d.setStroke(originalStroke);
        g2d.setColor(originalColor);
    }
    /**
     * æ£€æŸ¥double值是否有限(不是NaN或无穷大)
     * å…¼å®¹ä½Žç‰ˆæœ¬Java
     */
    private static boolean isFinite(double value) {
        return !Double.isNaN(value) && !Double.isInfinite(value);
    }
}
src/zhuye/pointandnumber.java
@@ -39,7 +39,7 @@
    double boundaryLineWidth = 3.0 / scaleFactor; // è¾¹ç•Œçº¿å®½åº¦
    double markerDiameter = boundaryLineWidth * 2.0; // æç‚¹ç›´å¾„(边界线宽度的2倍)
    // åº”用直径缩放因子
    if (diameterScale > 0.0 && Double.isFinite(diameterScale)) {
    if (diameterScale > 0.0 && isFinite(diameterScale)) {
        markerDiameter *= diameterScale;
    }
        double markerRadius = markerDiameter / 2.0; // åŠå¾„
@@ -63,4 +63,12 @@
        double dy = a.y - b.y; // Y差值
        return Math.hypot(dx, dy) <= threshold; // è·ç¦»åˆ¤æ–­
    }
    /**
     * æ£€æŸ¥double值是否有限(不是NaN或无穷大)
     * å…¼å®¹ä½Žç‰ˆæœ¬Java
     */
    private static boolean isFinite(double value) {
        return !Double.isNaN(value) && !Double.isInfinite(value);
    }
}
src/zhuye/tuowei.java
@@ -36,7 +36,7 @@
                continue;
            }
            Point2D.Double point = sample.getPoint();
            if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) {
            if (point == null || !isFinite(point.x) || !isFinite(point.y)) {
                continue;
            }
            if (!started) {
@@ -83,4 +83,12 @@
            return point;
        }
    }
    /**
     * æ£€æŸ¥double值是否有限(不是NaN或无穷大)
     * å…¼å®¹ä½Žç‰ˆæœ¬Java
     */
    private static boolean isFinite(double value) {
        return !Double.isNaN(value) && !Double.isInfinite(value);
    }
}
user.properties
@@ -1,11 +1,11 @@
#Updated User Properties
#Fri Dec 26 19:12:46 CST 2025
email=981894274@qq.com
language=zh
#Sat Dec 27 20:42:59 GMT+08:00 2025
registrationTime=-1
lastLoginTime=1766747566698
password=123456
registrationTime=-1
rememberPassword=1
status=-1
userId=-1
rememberPassword=0
language=zh
userName=981894274@qq.com
userId=-1
email=981894274@qq.com
status=-1