From c57cb0cd9feb4495c89246b2faec6d5e45c23c30 Mon Sep 17 00:00:00 2001
From: 张世豪 <979909237@qq.com>
Date: 星期一, 15 十二月 2025 15:46:49 +0800
Subject: [PATCH] 新增了控制指令
---
image/dengoff.png | 0
src/gecaoji/Device.java | 107 ++++
device.properties | 3
image/starton.png | 0
image/xia2.png | 0
src/yaokong/Control05.java | 199 ++++++++
set.properties | 6
src/yaokong/RemoteControlDialog.java | 563 ++++++++++++++++++++++++
image/onanddown.png | 0
image/xia20.png | 0
src/yaokong/Control07.java | 198 ++++++++
image/xia10.png | 0
image/off.png | 0
image/xia1.png | 0
src/yaokong/Control06.java | 245 ++++++++++
image/dengon.png | 0
src/yaokong/Control03.java | 10
17 files changed, 1,316 insertions(+), 15 deletions(-)
diff --git a/device.properties b/device.properties
index f23bf1d..542d7ea 100644
--- a/device.properties
+++ b/device.properties
@@ -24,3 +24,6 @@
positioningStatus=-1
satelliteCount=-1
differentialAge=-1
+mowerStartStatus=-1
+mowerLightStatus=-1
+mowerBladeHeight=-1
diff --git a/image/dengoff.png b/image/dengoff.png
new file mode 100644
index 0000000..66aa325
--- /dev/null
+++ b/image/dengoff.png
Binary files differ
diff --git a/image/dengon.png b/image/dengon.png
new file mode 100644
index 0000000..742b5b0
--- /dev/null
+++ b/image/dengon.png
Binary files differ
diff --git a/image/off.png b/image/off.png
new file mode 100644
index 0000000..0b358be
--- /dev/null
+++ b/image/off.png
Binary files differ
diff --git a/image/onanddown.png b/image/onanddown.png
new file mode 100644
index 0000000..5981fef
--- /dev/null
+++ b/image/onanddown.png
Binary files differ
diff --git a/image/starton.png b/image/starton.png
new file mode 100644
index 0000000..f5d581e
--- /dev/null
+++ b/image/starton.png
Binary files differ
diff --git a/image/xia1.png b/image/xia1.png
new file mode 100644
index 0000000..300bfad
--- /dev/null
+++ b/image/xia1.png
Binary files differ
diff --git a/image/xia10.png b/image/xia10.png
new file mode 100644
index 0000000..f0d4eaa
--- /dev/null
+++ b/image/xia10.png
Binary files differ
diff --git a/image/xia2.png b/image/xia2.png
new file mode 100644
index 0000000..9b26e37
--- /dev/null
+++ b/image/xia2.png
Binary files differ
diff --git a/image/xia20.png b/image/xia20.png
new file mode 100644
index 0000000..7da633b
--- /dev/null
+++ b/image/xia20.png
Binary files differ
diff --git a/set.properties b/set.properties
index c823fc5..432da08 100644
--- a/set.properties
+++ b/set.properties
@@ -1,5 +1,5 @@
-#Current work land selection updated
-#Fri Dec 12 17:21:33 CST 2025
+#Serial Port Preferences Updated
+#Mon Dec 15 15:45:14 CST 2025
appVersion=-1
currentWorkLandNumber=LAND1
cuttingWidth=200
@@ -9,5 +9,5 @@
mowerId=1234
serialAutoConnect=true
serialBaudRate=115200
-serialPortName=COM13
+serialPortName=COM15
simCardNumber=-1
diff --git a/src/gecaoji/Device.java b/src/gecaoji/Device.java
index ee13487..aa4b77d 100644
--- a/src/gecaoji/Device.java
+++ b/src/gecaoji/Device.java
@@ -2,7 +2,10 @@
import baseStation.BaseStation;
import set.Setsys;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Properties;
@@ -74,6 +77,12 @@
// 宸垎鏃堕棿
private String selfCheckStatus = "-1";
// 鍓茶崏鏈鸿嚜妫�鐘舵��
+ private String mowerStartStatus = "-1";
+ // 鍓茶崏鏈哄惎鍔ㄧ姸鎬侊細1寮�鍚紝0鐔勭伀锛�-1鏈煡
+ private String mowerLightStatus = "-1";
+ // 鍓茶崏鏈虹伅寮�鍏崇姸鎬侊細1寮�鍚紝0鍏抽棴锛�-1鏈煡
+ private String mowerBladeHeight = "-1";
+ // 鍓茶崏鏈哄垁鐩橀珮搴︼細-1鏈煡
private static final double METERS_PER_DEGREE_LAT = 111320.0d;
@@ -104,6 +113,58 @@
applyDefaults(gecaoji);
}
+ /**
+ * 淇濆瓨鎵�鏈夊睘鎬у埌device.properties鏂囦欢
+ */
+ public void saveToProperties() {
+ Properties properties = new Properties();
+
+ // 鍔犺浇鐜版湁灞炴�э紙淇濈暀鍏朵粬灞炴�э級
+ try (FileInputStream input = new FileInputStream("device.properties")) {
+ properties.load(input);
+ } catch (IOException e) {
+ // 濡傛灉鏂囦欢涓嶅瓨鍦紝缁х画鍒涘缓鏂版枃浠�
+ }
+
+ // 璁剧疆鎵�鏈夎澶囧睘鎬�
+ if (mowerName != null) properties.setProperty("mowerName", mowerName);
+ if (mowerModel != null) properties.setProperty("mowerModel", mowerModel);
+ if (mowerNumber != null) properties.setProperty("mowerNumber", mowerNumber);
+ if (mowingWidth != null) properties.setProperty("mowingWidth", mowingWidth);
+ if (mowingHeight != null) properties.setProperty("mowingHeight", mowingHeight);
+ if (baseStationNumber != null) properties.setProperty("baseStationNumber", baseStationNumber);
+ if (baseStationCardNumber != null) properties.setProperty("baseStationCardNumber", baseStationCardNumber);
+ if (baseStationCoordinates != null) properties.setProperty("baseStationCoordinates", baseStationCoordinates);
+ if (deviceCardnumber != null) properties.setProperty("deviceCardnumber", deviceCardnumber);
+ if (createTime != null) properties.setProperty("createTime", createTime);
+ if (GupdateTime != null) properties.setProperty("GupdateTime", GupdateTime);
+ if (BupdateTime != null) properties.setProperty("BupdateTime", BupdateTime);
+ if (realtimeLatitude != null) properties.setProperty("realtimeLatitude", realtimeLatitude);
+ if (realtimeLongitude != null) properties.setProperty("realtimeLongitude", realtimeLongitude);
+ if (realtimeAltitude != null) properties.setProperty("realtimeAltitude", realtimeAltitude);
+ if (realtimeX != null) properties.setProperty("realtimeX", realtimeX);
+ 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 (battery != null) properties.setProperty("battery", battery);
+ if (positioningStatus != null) properties.setProperty("positioningStatus", positioningStatus);
+ if (satelliteCount != null) properties.setProperty("satelliteCount", satelliteCount);
+ if (differentialAge != null) properties.setProperty("differentialAge", differentialAge);
+ if (selfCheckStatus != null) properties.setProperty("selfCheckStatus", selfCheckStatus);
+ if (mowerStartStatus != null) properties.setProperty("mowerStartStatus", mowerStartStatus);
+ if (mowerLightStatus != null) properties.setProperty("mowerLightStatus", mowerLightStatus);
+ if (mowerBladeHeight != null) properties.setProperty("mowerBladeHeight", mowerBladeHeight);
+
+ // 淇濆瓨鍒版枃浠�
+ try (FileOutputStream output = new FileOutputStream("device.properties");
+ OutputStreamWriter writer = new OutputStreamWriter(output, StandardCharsets.UTF_8)) {
+ properties.store(writer, "Updated device properties");
+ } catch (IOException ex) {
+ System.err.println("鏃犳硶淇濆瓨 device.properties: " + ex.getMessage());
+ }
+ }
+
private void loadPropertiesInto(Device target, Properties properties) {
if (target == null) {
return;
@@ -133,7 +194,10 @@
target.positioningStatus = properties.getProperty("positioningStatus", "-1");
target.satelliteCount = properties.getProperty("satelliteCount", "-1");
target.differentialAge = properties.getProperty("differentialAge", "-1");
- target.selfCheckStatus = properties.getProperty("selfCheckStatus", "-1");
+ target.selfCheckStatus = properties.getProperty("selfCheckStatus", "-1");
+ target.mowerStartStatus = properties.getProperty("mowerStartStatus", "-1");
+ target.mowerLightStatus = properties.getProperty("mowerLightStatus", "-1");
+ target.mowerBladeHeight = properties.getProperty("mowerBladeHeight", "-1");
}
private void applyDefaults(Device target) {
@@ -165,7 +229,10 @@
target.positioningStatus = "-1";
target.satelliteCount = "-1";
target.differentialAge = "-1";
- target.selfCheckStatus = "-1";
+ target.selfCheckStatus = "-1";
+ target.mowerStartStatus = "-1";
+ target.mowerLightStatus = "-1";
+ target.mowerBladeHeight = "-1";
}
public static synchronized Device initializeActiveDevice(String mowerId) { // 鏍规嵁璁惧ID鍒濆鍖栨椿璺冭澶�
@@ -267,6 +334,15 @@
case "selfCheckStatus":
this.selfCheckStatus = value;
return true;
+ case "mowerStartStatus":
+ this.mowerStartStatus = value;
+ return true;
+ case "mowerLightStatus":
+ this.mowerLightStatus = value;
+ return true;
+ case "mowerBladeHeight":
+ this.mowerBladeHeight = value;
+ return true;
default:
System.err.println("鏈煡瀛楁: " + fieldName);
return false;
@@ -711,6 +787,30 @@
this.selfCheckStatus = selfCheckStatus;
}
+ public String getMowerStartStatus() { // 鑾峰彇鍓茶崏鏈哄惎鍔ㄧ姸鎬�
+ return mowerStartStatus;
+ }
+
+ public void setMowerStartStatus(String mowerStartStatus) { // 璁剧疆鍓茶崏鏈哄惎鍔ㄧ姸鎬�
+ this.mowerStartStatus = mowerStartStatus;
+ }
+
+ public String getMowerLightStatus() { // 鑾峰彇鍓茶崏鏈虹伅寮�鍏崇姸鎬�
+ return mowerLightStatus;
+ }
+
+ public void setMowerLightStatus(String mowerLightStatus) { // 璁剧疆鍓茶崏鏈虹伅寮�鍏崇姸鎬�
+ this.mowerLightStatus = mowerLightStatus;
+ }
+
+ public String getMowerBladeHeight() { // 鑾峰彇鍓茶崏鏈哄垁鐩橀珮搴�
+ return mowerBladeHeight;
+ }
+
+ public void setMowerBladeHeight(String mowerBladeHeight) { // 璁剧疆鍓茶崏鏈哄垁鐩橀珮搴�
+ this.mowerBladeHeight = mowerBladeHeight;
+ }
+
@Override
public String toString() { // 杈撳嚭瀵硅薄淇℃伅
return "Device{" +
@@ -739,6 +839,9 @@
", satelliteCount='" + satelliteCount + '\'' +
", differentialAge='" + differentialAge + '\'' +
", selfCheckStatus='" + selfCheckStatus + '\'' +
+ ", mowerStartStatus='" + mowerStartStatus + '\'' +
+ ", mowerLightStatus='" + mowerLightStatus + '\'' +
+ ", mowerBladeHeight='" + mowerBladeHeight + '\'' +
'}';
}
}
\ No newline at end of file
diff --git a/src/yaokong/Control03.java b/src/yaokong/Control03.java
index 01c28db..6401d72 100644
--- a/src/yaokong/Control03.java
+++ b/src/yaokong/Control03.java
@@ -198,6 +198,16 @@
return currentSteeringSpeed;
}
+ /**
+ * 鐩存帴璁剧疆骞跺彂閫佽浆鍚戝拰鍓嶈繘閫熷害锛堢敤浜庢寔缁彂閫佹帶鍒舵寚浠わ級
+ * @param steeringSpeed 杞悜閫熷害锛岃寖鍥�-100鍒�100
+ * @param forwardSpeed 鍓嶈繘閫熷害锛岃寖鍥�-100鍒�100
+ * @return 鏄惁鍙戦�佹垚鍔�
+ */
+ public static synchronized boolean setAndSendSpeeds(int steeringSpeed, int forwardSpeed) {
+ return sendSpeedsIfDebugSerialOpen(steeringSpeed, forwardSpeed);
+ }
+
private static boolean sendSpeedsIfDebugSerialOpen(int nextSteering, int nextForward) {
SerialPortService service = sendmessage.getActiveService();
if (service == null || !service.isOpen()) {
diff --git a/src/yaokong/Control05.java b/src/yaokong/Control05.java
new file mode 100644
index 0000000..39e8aa2
--- /dev/null
+++ b/src/yaokong/Control05.java
@@ -0,0 +1,199 @@
+package yaokong;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import chuankou.SerialPortService;
+import chuankou.sendmessage;
+
+/**
+ * Control05.java - 閬ユ帶鏈哄櫒鍚姩鍏抽棴鎸囦护绫�
+ *
+ * 鎸囦护绫诲瀷: 0x05
+ * 鍔熻兘: 鎺у埗鍓茶崏鏈烘暣鏈虹數婧愮殑鍚姩涓庡叧闂�
+ *
+ * 鏁版嵁鏍煎紡:
+ * 鎺у埗鍊�(1瀛楄妭): 0=鍏抽棴锛�1=鍚姩
+ * 淇濈暀瀛楁(3瀛楄妭): 0x00濉厖
+ *
+ * 绀轰緥鐢ㄦ硶:
+ * 1. 鍚姩鏈哄櫒: Control05.buildPowerCommandHex("1") 鎴� Control05.powerOn()
+ * 2. 鍏抽棴鏈哄櫒: Control05.buildPowerCommandHex("0") 鎴� Control05.powerOff()
+ * 3. 鍙戦�佹寚浠�: Control05.sendPowerOnIfDebugSerialOpen()
+ */
+public class Control05 {
+
+ /**
+ * 鏋勫缓閬ユ帶鏈哄櫒鍚姩鍏抽棴鎸囦护锛堟寚浠ょ被鍨�0x05锛夌殑HEX鏍煎紡瀛楃涓�
+ *
+ * @param powerValue 鐢垫簮鎺у埗鍊煎瓧绗︿覆锛�"0"琛ㄧず鍏抽棴锛�"1"琛ㄧず鍚姩
+ * @return 鐢垫簮鎺у埗鎸囦护鐨凥EX鏍煎紡瀛楃涓�
+ */
+ public static String buildPowerCommandHex(String powerValue) {
+ // 瑙f瀽鎺у埗鍊�
+ int power = parsePowerValue(powerValue);
+
+ byte[] commandBytes = buildPowerCommandBytes((byte) power);
+ return bytesToHex(commandBytes);
+ }
+
+ /**
+ * 鏋勫缓閬ユ帶鏈哄櫒鍚姩鍏抽棴鎸囦护鐨勫瓧鑺傛暟缁�
+ *
+ * @param powerValue 鐢垫簮鎺у埗鍊硷細0=鍏抽棴锛�1=鍚姩
+ * @return 鐢垫簮鎺у埗鎸囦护鐨勫瓧鑺傛暟缁�
+ */
+ public static byte[] buildPowerCommandBytes(byte powerValue) {
+ // 楠岃瘉鎺у埗鍊艰寖鍥�
+ if (powerValue != 0 && powerValue != 1) {
+ throw new IllegalArgumentException("鐢垫簮鎺у埗鍊煎繀椤绘槸0鎴�1");
+ }
+
+ int dataLength = 4; // 鎺у埗鍊�1瀛楄妭 + 淇濈暀瀛楁3瀛楄妭
+
+ ByteBuffer buffer = ByteBuffer.allocate(14); // 鎬婚暱搴�14瀛楄妭
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ // 甯уご
+ buffer.put(BluetoothProtocol.FRAME_HEADER);
+
+ // 鎸囦护绫诲瀷 (0x05)
+ buffer.put((byte) 0x05);
+
+ // 鏁版嵁闀垮害
+ buffer.putShort((short) dataLength);
+
+ // 搴忓垪鍙�
+ short sequence = (short) BluetoothProtocol.getNextSequence();
+ buffer.putShort(sequence);
+
+ // 鎺у埗鍊�
+ buffer.put(powerValue);
+
+ // 淇濈暀瀛楁 (3瀛楄妭锛屽叏閮ㄥ~0)
+ buffer.put((byte) 0x00);
+ buffer.put((byte) 0x00);
+ buffer.put((byte) 0x00);
+
+ // 璁$畻CRC16锛堜粠鎸囦护绫诲瀷寮�濮嬪埌鏁版嵁鍐呭缁撴潫锛�
+ byte[] dataForCRC = new byte[9];
+ ByteBuffer tempBuffer = ByteBuffer.allocate(9);
+ tempBuffer.order(ByteOrder.LITTLE_ENDIAN);
+ tempBuffer.put((byte) 0x05); // 鎸囦护绫诲瀷
+ tempBuffer.putShort((short) dataLength); // 鏁版嵁闀垮害
+ tempBuffer.putShort(sequence); // 搴忓垪鍙�
+ tempBuffer.put(powerValue); // 鎺у埗鍊�
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁1
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁2
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁3
+
+ dataForCRC = tempBuffer.array();
+ int crc = CRC16.calculateCRC16(dataForCRC, 0, dataForCRC.length);
+ buffer.putShort((short) crc);
+
+ // 甯у熬
+ buffer.put((byte) 0x0D);
+
+ return buffer.array();
+ }
+
+ /**
+ * 褰撹皟璇曚覆鍙f墦寮�鏃跺彂閫佸惎鍔ㄦ満鍣ㄦ寚浠�
+ *
+ * @return 鍙戦�佹垚鍔熻繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+ */
+ public static boolean sendPowerOnIfDebugSerialOpen() {
+ return sendPowerCommandIfDebugSerialOpen((byte) 1);
+ }
+
+ /**
+ * 褰撹皟璇曚覆鍙f墦寮�鏃跺彂閫佸叧闂満鍣ㄦ寚浠�
+ *
+ * @return 鍙戦�佹垚鍔熻繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+ */
+ public static boolean sendPowerOffIfDebugSerialOpen() {
+ return sendPowerCommandIfDebugSerialOpen((byte) 0);
+ }
+
+ /**
+ * 蹇嵎鏂规硶锛氭瀯寤哄惎鍔ㄦ満鍣ㄦ寚浠�
+ *
+ * @return 鍚姩鎸囦护鐨凥EX瀛楃涓�
+ */
+ public static String powerOn() {
+ return buildPowerCommandHex("1");
+ }
+
+ /**
+ * 蹇嵎鏂规硶锛氭瀯寤哄叧闂満鍣ㄦ寚浠�
+ *
+ * @return 鍏抽棴鎸囦护鐨凥EX瀛楃涓�
+ */
+ public static String powerOff() {
+ return buildPowerCommandHex("0");
+ }
+
+ /**
+ * 瑙f瀽鎺у埗鍊煎瓧绗︿覆
+ */
+ private static int parsePowerValue(String powerStr) {
+ try {
+ int power = Integer.parseInt(powerStr.trim());
+ if (power != 0 && power != 1) {
+ throw new IllegalArgumentException("鐢垫簮鎺у埗鍊煎繀椤绘槸0鎴�1");
+ }
+ return power;
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("鐢垫簮鎺у埗鍊煎繀椤绘槸鏁存暟: " + powerStr);
+ }
+ }
+
+ /**
+ * 鍙戦�佺數婧愭帶鍒舵寚浠わ紙鍐呴儴鏂规硶锛�
+ */
+ private static boolean sendPowerCommandIfDebugSerialOpen(byte powerValue) {
+ SerialPortService service = sendmessage.getActiveService();
+ if (service == null || !service.isOpen()) {
+ return false;
+ }
+ byte[] payload = buildPowerCommandBytes(powerValue);
+
+ // 璋冭瘯锛氭墦鍗板彂閫佺殑鏁版嵁
+ System.out.println("鍙戦�佺數婧愭帶鍒舵寚浠�: " + bytesToHex(payload));
+
+ return sendmessage.sendViaActive(payload);
+ }
+
+ /**
+ * 瀛楄妭鏁扮粍杞崲涓篐EX瀛楃涓�
+ */
+ private static String bytesToHex(byte[] bytes) {
+ StringBuilder hexString = new StringBuilder();
+ for (int i = 0; i < bytes.length; i++) {
+ String hex = Integer.toHexString(bytes[i] & 0xFF);
+ if (hex.length() == 1) {
+ hexString.append('0');
+ }
+ hexString.append(hex);
+ if (i < bytes.length - 1) {
+ hexString.append(' ');
+ }
+ }
+ return hexString.toString().toUpperCase();
+ }
+
+ /**
+ * 娴嬭瘯鍑芥暟锛氶獙璇佺數婧愭帶鍒舵寚浠ゆ瀯寤�
+ */
+ 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));
+ }
+}
\ No newline at end of file
diff --git a/src/yaokong/Control06.java b/src/yaokong/Control06.java
new file mode 100644
index 0000000..5e367ff
--- /dev/null
+++ b/src/yaokong/Control06.java
@@ -0,0 +1,245 @@
+package yaokong;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import chuankou.SerialPortService;
+import chuankou.sendmessage;
+
+/**
+ * Control06.java - 閬ユ帶鍓茶崏鍒�鐩樺崌闄嶆寚浠ょ被
+ *
+ * 鎸囦护绫诲瀷: 0x06
+ * 鍔熻兘: 鎺у埗鍓茶崏鏈哄垁鐩樼殑鍗囬檷楂樺害
+ *
+ * 鏁版嵁鏍煎紡:
+ * 鍗囬檷鍊�(1瀛楄妭): -100~100锛屾鏁拌〃绀哄悜涓婃彁鍗�
+ * 淇濈暀瀛楁(3瀛楄妭): 0x00濉厖
+ *
+ * 绀轰緥鐢ㄦ硶:
+ * 1. 鎻愬崌鍒�鐩�50%: Control06.buildBladeCommandHex("50")
+ * 2. 闄嶄綆鍒�鐩�30%: Control06.buildBladeCommandHex("-30")
+ * 3. 鍙戦�佹彁鍗囨寚浠�: Control06.sendBladeUpIfDebugSerialOpen(50)
+ * 4. 鍙戦�侀檷浣庢寚浠�: Control06.sendBladeDownIfDebugSerialOpen(30)
+ */
+public class Control06 {
+
+ private static final int MAX_BLADE_VALUE = 100;
+ private static final int MIN_BLADE_VALUE = -100;
+ private static final int BLADE_STEP = 10; // 榛樿姝ヨ繘鍊�
+
+ private static int currentBladeHeight = 0; // 褰撳墠鍒�鐩橀珮搴︾櫨鍒嗘瘮
+
+ /**
+ * 鏋勫缓閬ユ帶鍓茶崏鍒�鐩樺崌闄嶆寚浠わ紙鎸囦护绫诲瀷0x06锛夌殑HEX鏍煎紡瀛楃涓�
+ *
+ * @param bladeValueStr 鍒�鐩橀珮搴﹀�煎瓧绗︿覆锛岃寖鍥�-100鍒�100锛屾鏁拌〃绀哄悜涓婃彁鍗�
+ * @return 鍒�鐩樺崌闄嶆寚浠ょ殑HEX鏍煎紡瀛楃涓�
+ */
+ public static String buildBladeCommandHex(String bladeValueStr) {
+ int bladeValue = parseBladeValue(bladeValueStr);
+ byte[] commandBytes = buildBladeCommandBytes((byte) bladeValue);
+ return bytesToHex(commandBytes);
+ }
+
+ /**
+ * 鏋勫缓閬ユ帶鍓茶崏鍒�鐩樺崌闄嶆寚浠ょ殑瀛楄妭鏁扮粍
+ *
+ * @param bladeValue 鍒�鐩橀珮搴﹀�硷細-100~100锛屾鏁拌〃绀哄悜涓婃彁鍗�
+ * @return 鍒�鐩樺崌闄嶆寚浠ょ殑瀛楄妭鏁扮粍
+ */
+ public static byte[] buildBladeCommandBytes(byte bladeValue) {
+ // 楠岃瘉鍒�鐩橀珮搴﹁寖鍥�
+ if (bladeValue < -100 || bladeValue > 100) {
+ throw new IllegalArgumentException("鍒�鐩橀珮搴﹀�煎繀椤诲湪-100鍒�100涔嬮棿");
+ }
+
+ int dataLength = 4; // 鍗囬檷鍊�1瀛楄妭 + 淇濈暀瀛楁3瀛楄妭
+
+ ByteBuffer buffer = ByteBuffer.allocate(14); // 鎬婚暱搴�14瀛楄妭
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ // 甯уご
+ buffer.put(BluetoothProtocol.FRAME_HEADER);
+
+ // 鎸囦护绫诲瀷 (0x06)
+ buffer.put((byte) 0x06);
+
+ // 鏁版嵁闀垮害
+ buffer.putShort((short) dataLength);
+
+ // 搴忓垪鍙�
+ short sequence = (short) BluetoothProtocol.getNextSequence();
+ buffer.putShort(sequence);
+
+ // 鍒�鐩橀珮搴﹀��
+ buffer.put(bladeValue);
+
+ // 淇濈暀瀛楁 (3瀛楄妭锛屽叏閮ㄥ~0)
+ buffer.put((byte) 0x00);
+ buffer.put((byte) 0x00);
+ buffer.put((byte) 0x00);
+
+ // 璁$畻CRC16锛堜粠鎸囦护绫诲瀷寮�濮嬪埌鏁版嵁鍐呭缁撴潫锛�
+ byte[] dataForCRC = new byte[9];
+ ByteBuffer tempBuffer = ByteBuffer.allocate(9);
+ tempBuffer.order(ByteOrder.LITTLE_ENDIAN);
+ tempBuffer.put((byte) 0x06); // 鎸囦护绫诲瀷
+ tempBuffer.putShort((short) dataLength); // 鏁版嵁闀垮害
+ tempBuffer.putShort(sequence); // 搴忓垪鍙�
+ tempBuffer.put(bladeValue); // 鍒�鐩橀珮搴﹀��
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁1
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁2
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁3
+
+ dataForCRC = tempBuffer.array();
+ int crc = CRC16.calculateCRC16(dataForCRC, 0, dataForCRC.length);
+ buffer.putShort((short) crc);
+
+ // 甯у熬
+ buffer.put((byte) 0x0D);
+
+ return buffer.array();
+ }
+
+ /**
+ * 褰撹皟璇曚覆鍙f墦寮�鏃跺彂閫佹彁鍗囧垁鐩樻寚浠�
+ *
+ * @param value 鎻愬崌鐧惧垎姣斿�硷紙0-100锛�
+ * @return 鍙戦�佹垚鍔熻繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+ */
+ public static boolean sendBladeUpIfDebugSerialOpen(int value) {
+ int targetHeight = Math.min(currentBladeHeight + value, MAX_BLADE_VALUE);
+ return sendBladeHeightIfDebugSerialOpen(targetHeight);
+ }
+
+ /**
+ * 褰撹皟璇曚覆鍙f墦寮�鏃跺彂閫侀檷浣庡垁鐩樻寚浠�
+ *
+ * @param value 闄嶄綆鐧惧垎姣斿�硷紙0-100锛�
+ * @return 鍙戦�佹垚鍔熻繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+ */
+ public static boolean sendBladeDownIfDebugSerialOpen(int value) {
+ int targetHeight = Math.max(currentBladeHeight - value, MIN_BLADE_VALUE);
+ return sendBladeHeightIfDebugSerialOpen(targetHeight);
+ }
+
+ /**
+ * 褰撹皟璇曚覆鍙f墦寮�鏃跺彂閫佸垁鐩樺綊闆舵寚浠�
+ *
+ * @return 鍙戦�佹垚鍔熻繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+ */
+ public static boolean sendBladeResetIfDebugSerialOpen() {
+ return sendBladeHeightIfDebugSerialOpen(0);
+ }
+
+ /**
+ * 蹇嵎鏂规硶锛氭瀯寤烘彁鍗囧垁鐩樻寚浠�
+ *
+ * @param value 鎻愬崌鐧惧垎姣斿�硷紙0-100锛�
+ * @return 鎻愬崌鎸囦护鐨凥EX瀛楃涓�
+ */
+ public static String bladeUp(int value) {
+ int targetValue = Math.min(Math.max(value, 0), MAX_BLADE_VALUE);
+ return buildBladeCommandHex(String.valueOf(targetValue));
+ }
+
+ /**
+ * 蹇嵎鏂规硶锛氭瀯寤洪檷浣庡垁鐩樻寚浠�
+ *
+ * @param value 闄嶄綆鐧惧垎姣斿�硷紙0-100锛�
+ * @return 闄嶄綆鎸囦护鐨凥EX瀛楃涓�
+ */
+ public static String bladeDown(int value) {
+ int targetValue = Math.max(Math.min(-value, 0), MIN_BLADE_VALUE);
+ return buildBladeCommandHex(String.valueOf(targetValue));
+ }
+
+ /**
+ * 瑙f瀽鍒�鐩橀珮搴﹀�煎瓧绗︿覆
+ */
+ private static int parseBladeValue(String bladeStr) {
+ try {
+ int value = Integer.parseInt(bladeStr.trim());
+ if (value < MIN_BLADE_VALUE || value > MAX_BLADE_VALUE) {
+ throw new IllegalArgumentException("鍒�鐩橀珮搴﹀�煎繀椤诲湪-100鍒�100涔嬮棿");
+ }
+ return value;
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("鍒�鐩橀珮搴﹀�煎繀椤绘槸鏁存暟: " + bladeStr);
+ }
+ }
+
+ /**
+ * 鍙戦�佸垁鐩橀珮搴︽帶鍒舵寚浠わ紙鍐呴儴鏂规硶锛�
+ */
+ private static boolean sendBladeHeightIfDebugSerialOpen(int targetHeight) {
+ SerialPortService service = sendmessage.getActiveService();
+ if (service == null || !service.isOpen()) {
+ return false;
+ }
+ byte[] payload = buildBladeCommandBytes((byte) targetHeight);
+
+ // 璋冭瘯锛氭墦鍗板彂閫佺殑鏁版嵁
+ System.out.println("鍙戦�佸垁鐩樺崌闄嶆寚浠�: " + bytesToHex(payload));
+
+ boolean success = sendmessage.sendViaActive(payload);
+ if (success) {
+ currentBladeHeight = targetHeight;
+ }
+ return success;
+ }
+
+ /**
+ * 鑾峰彇褰撳墠鍒�鐩橀珮搴�
+ *
+ * @return 褰撳墠鍒�鐩橀珮搴︾櫨鍒嗘瘮锛�-100鍒�100锛�
+ */
+ public static int getCurrentBladeHeight() {
+ return currentBladeHeight;
+ }
+
+ /**
+ * 閲嶇疆鍒�鐩橀珮搴︿负0
+ */
+ public static void resetBladeHeight() {
+ currentBladeHeight = 0;
+ }
+
+ /**
+ * 瀛楄妭鏁扮粍杞崲涓篐EX瀛楃涓�
+ */
+ private static String bytesToHex(byte[] bytes) {
+ StringBuilder hexString = new StringBuilder();
+ for (int i = 0; i < bytes.length; i++) {
+ String hex = Integer.toHexString(bytes[i] & 0xFF);
+ if (hex.length() == 1) {
+ hexString.append('0');
+ }
+ hexString.append(hex);
+ if (i < bytes.length - 1) {
+ hexString.append(' ');
+ }
+ }
+ return hexString.toString().toUpperCase();
+ }
+
+ /**
+ * 娴嬭瘯鍑芥暟锛氶獙璇佸垁鐩樺崌闄嶆寚浠ゆ瀯寤�
+ */
+ 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));
+ }
+}
\ No newline at end of file
diff --git a/src/yaokong/Control07.java b/src/yaokong/Control07.java
new file mode 100644
index 0000000..5c1ab2e
--- /dev/null
+++ b/src/yaokong/Control07.java
@@ -0,0 +1,198 @@
+package yaokong;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import chuankou.SerialPortService;
+import chuankou.sendmessage;
+
+/**
+ * Control07.java - 閬ユ帶澶х伅寮�鍏虫寚浠ょ被
+ *
+ * 鎸囦护绫诲瀷: 0x07
+ * 鍔熻兘: 鎺у埗鍓茶崏鏈哄ぇ鐏殑寮�鍏�
+ *
+ * 鏁版嵁鏍煎紡:
+ * 寮�鍏崇姸鎬�(1瀛楄妭): 0=鍏抽棴锛�1=寮�鍚�
+ * 淇濈暀瀛楁(3瀛楄妭): 0x00濉厖
+ *
+ * 绀轰緥鐢ㄦ硶:
+ * 1. 寮�鍚ぇ鐏�: Control07.buildLightCommandHex("1") 鎴� Control07.lightOn()
+ * 2. 鍏抽棴澶х伅: Control07.buildLightCommandHex("0") 鎴� Control07.lightOff()
+ * 3. 鍙戦�佸紑鐏寚浠�: Control07.sendLightOnIfDebugSerialOpen()
+ * 4. 鍙戦�佸叧鐏寚浠�: Control07.sendLightOffIfDebugSerialOpen()
+ */
+public class Control07 {
+
+ /**
+ * 鏋勫缓閬ユ帶澶х伅寮�鍏虫寚浠わ紙鎸囦护绫诲瀷0x07锛夌殑HEX鏍煎紡瀛楃涓�
+ *
+ * @param lightValueStr 澶х伅寮�鍏崇姸鎬佸瓧绗︿覆锛�"0"琛ㄧず鍏抽棴锛�"1"琛ㄧず寮�鍚�
+ * @return 澶х伅鎺у埗鎸囦护鐨凥EX鏍煎紡瀛楃涓�
+ */
+ public static String buildLightCommandHex(String lightValueStr) {
+ int lightValue = parseLightValue(lightValueStr);
+ byte[] commandBytes = buildLightCommandBytes((byte) lightValue);
+ return bytesToHex(commandBytes);
+ }
+
+ /**
+ * 鏋勫缓閬ユ帶澶х伅寮�鍏虫寚浠ょ殑瀛楄妭鏁扮粍
+ *
+ * @param lightValue 澶х伅寮�鍏崇姸鎬侊細0=鍏抽棴锛�1=寮�鍚�
+ * @return 澶х伅鎺у埗鎸囦护鐨勫瓧鑺傛暟缁�
+ */
+ public static byte[] buildLightCommandBytes(byte lightValue) {
+ // 楠岃瘉寮�鍏崇姸鎬佽寖鍥�
+ if (lightValue != 0 && lightValue != 1) {
+ throw new IllegalArgumentException("澶х伅寮�鍏崇姸鎬佸繀椤绘槸0鎴�1");
+ }
+
+ int dataLength = 4; // 寮�鍏崇姸鎬�1瀛楄妭 + 淇濈暀瀛楁3瀛楄妭
+
+ ByteBuffer buffer = ByteBuffer.allocate(14); // 鎬婚暱搴�14瀛楄妭
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ // 甯уご
+ buffer.put(BluetoothProtocol.FRAME_HEADER);
+
+ // 鎸囦护绫诲瀷 (0x07)
+ buffer.put((byte) 0x07);
+
+ // 鏁版嵁闀垮害
+ buffer.putShort((short) dataLength);
+
+ // 搴忓垪鍙�
+ short sequence = (short) BluetoothProtocol.getNextSequence();
+ buffer.putShort(sequence);
+
+ // 澶х伅寮�鍏崇姸鎬�
+ buffer.put(lightValue);
+
+ // 淇濈暀瀛楁 (3瀛楄妭锛屽叏閮ㄥ~0)
+ buffer.put((byte) 0x00);
+ buffer.put((byte) 0x00);
+ buffer.put((byte) 0x00);
+
+ // 璁$畻CRC16锛堜粠鎸囦护绫诲瀷寮�濮嬪埌鏁版嵁鍐呭缁撴潫锛�
+ byte[] dataForCRC = new byte[9];
+ ByteBuffer tempBuffer = ByteBuffer.allocate(9);
+ tempBuffer.order(ByteOrder.LITTLE_ENDIAN);
+ tempBuffer.put((byte) 0x07); // 鎸囦护绫诲瀷
+ tempBuffer.putShort((short) dataLength); // 鏁版嵁闀垮害
+ tempBuffer.putShort(sequence); // 搴忓垪鍙�
+ tempBuffer.put(lightValue); // 澶х伅寮�鍏崇姸鎬�
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁1
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁2
+ tempBuffer.put((byte) 0x00); // 淇濈暀瀛楁3
+
+ dataForCRC = tempBuffer.array();
+ int crc = CRC16.calculateCRC16(dataForCRC, 0, dataForCRC.length);
+ buffer.putShort((short) crc);
+
+ // 甯у熬
+ buffer.put((byte) 0x0D);
+
+ return buffer.array();
+ }
+
+ /**
+ * 褰撹皟璇曚覆鍙f墦寮�鏃跺彂閫佸紑鍚ぇ鐏寚浠�
+ *
+ * @return 鍙戦�佹垚鍔熻繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+ */
+ public static boolean sendLightOnIfDebugSerialOpen() {
+ return sendLightCommandIfDebugSerialOpen((byte) 1);
+ }
+
+ /**
+ * 褰撹皟璇曚覆鍙f墦寮�鏃跺彂閫佸叧闂ぇ鐏寚浠�
+ *
+ * @return 鍙戦�佹垚鍔熻繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+ */
+ public static boolean sendLightOffIfDebugSerialOpen() {
+ return sendLightCommandIfDebugSerialOpen((byte) 0);
+ }
+
+ /**
+ * 蹇嵎鏂规硶锛氭瀯寤哄紑鍚ぇ鐏寚浠�
+ *
+ * @return 寮�鐏寚浠ょ殑HEX瀛楃涓�
+ */
+ public static String lightOn() {
+ return buildLightCommandHex("1");
+ }
+
+ /**
+ * 蹇嵎鏂规硶锛氭瀯寤哄叧闂ぇ鐏寚浠�
+ *
+ * @return 鍏崇伅鎸囦护鐨凥EX瀛楃涓�
+ */
+ public static String lightOff() {
+ return buildLightCommandHex("0");
+ }
+
+ /**
+ * 瑙f瀽澶х伅寮�鍏崇姸鎬佸瓧绗︿覆
+ */
+ private static int parseLightValue(String lightStr) {
+ try {
+ int light = Integer.parseInt(lightStr.trim());
+ if (light != 0 && light != 1) {
+ throw new IllegalArgumentException("澶х伅寮�鍏崇姸鎬佸繀椤绘槸0鎴�1");
+ }
+ return light;
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("澶х伅寮�鍏崇姸鎬佸繀椤绘槸鏁存暟: " + lightStr);
+ }
+ }
+
+ /**
+ * 鍙戦�佸ぇ鐏帶鍒舵寚浠わ紙鍐呴儴鏂规硶锛�
+ */
+ private static boolean sendLightCommandIfDebugSerialOpen(byte lightValue) {
+ SerialPortService service = sendmessage.getActiveService();
+ if (service == null || !service.isOpen()) {
+ return false;
+ }
+ byte[] payload = buildLightCommandBytes(lightValue);
+
+ // 璋冭瘯锛氭墦鍗板彂閫佺殑鏁版嵁
+ System.out.println("鍙戦�佸ぇ鐏帶鍒舵寚浠�: " + bytesToHex(payload));
+
+ return sendmessage.sendViaActive(payload);
+ }
+
+ /**
+ * 瀛楄妭鏁扮粍杞崲涓篐EX瀛楃涓�
+ */
+ private static String bytesToHex(byte[] bytes) {
+ StringBuilder hexString = new StringBuilder();
+ for (int i = 0; i < bytes.length; i++) {
+ String hex = Integer.toHexString(bytes[i] & 0xFF);
+ if (hex.length() == 1) {
+ hexString.append('0');
+ }
+ hexString.append(hex);
+ if (i < bytes.length - 1) {
+ hexString.append(' ');
+ }
+ }
+ return hexString.toString().toUpperCase();
+ }
+
+ /**
+ * 娴嬭瘯鍑芥暟锛氶獙璇佸ぇ鐏帶鍒舵寚浠ゆ瀯寤�
+ */
+ 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));
+ }
+}
\ No newline at end of file
diff --git a/src/yaokong/RemoteControlDialog.java b/src/yaokong/RemoteControlDialog.java
index af45f17..850a14c 100644
--- a/src/yaokong/RemoteControlDialog.java
+++ b/src/yaokong/RemoteControlDialog.java
@@ -20,6 +20,14 @@
private JLabel moveJoystickValueLabel;
private JLabel turnJoystickValueLabel;
private Timer speedUpdateTimer; // 閫熷害鏇存柊瀹氭椂鍣�
+ // 鎽囨潌鎺у埗瀹氭椂鍣細鎸佺画鍙戦�佹帶鍒舵寚浠�
+ private Timer forwardControlTimer; // 鍓嶈繘/鍚庨��鎺у埗瀹氭椂鍣�
+ private Timer steeringControlTimer; // 杞悜鎺у埗瀹氭椂鍣�
+ private int targetForwardSpeed = 0; // 鐩爣鍓嶈繘/鍚庨��閫熷害
+ private int targetSteeringSpeed = 0; // 鐩爣杞悜閫熷害
+ private List<JButton> bladeButtons = new ArrayList<>(); // 瀛樺偍鍒�鐩樻帶鍒舵寜閽紝鐢ㄤ簬娓呯悊瀹氭椂鍣�
+ private String bladeUpDefaultText = "鍒�鐩樺崌"; // 鍒�鐩樺崌鎸夐挳榛樿鏂囧瓧
+ private String bladeDownDefaultText = "鍒�鐩橀檷"; // 鍒�鐩橀檷鎸夐挳榛樿鏂囧瓧
public RemoteControlDialog(Component parent, Color themeColor, JLabel speedLabel) {
super(parent != null ? (JFrame) SwingUtilities.getWindowAncestor(parent) : null,
@@ -31,7 +39,7 @@
Control03.resetSpeeds();
Control03.sendNeutralCommandIfDebugSerialOpen();
int dialogWidth = UIConfig.DIALOG_WIDTH; // 涓庨椤靛搴︿竴鑷�
- int dialogHeight = (int) (UIConfig.DIALOG_HEIGHT / 3.0 * 0.7) + 50 + 40; // 澧炲姞40鍍忕礌
+ int dialogHeight = (int) (UIConfig.DIALOG_HEIGHT / 3.0 * 0.7) +150; // 澧炲姞90鍍忕礌锛堝師40+鏂板40+鍐嶅10锛�
initializeDialog(dialogWidth, dialogHeight);
initializeRemoteContent();
startSpeedUpdateTimer(); // 鍚姩閫熷害鏇存柊瀹氭椂鍣�
@@ -54,13 +62,69 @@
setSize(width, height);
setLocationRelativeTo(getOwner());
setResizable(false);
- getContentPane().setBackground(new Color(26, 26, 46)); // 娣辫壊鑳屾櫙
+ Container contentPane = getContentPane();
+ if (contentPane instanceof JComponent) {
+ JComponent jContentPane = (JComponent) contentPane;
+ jContentPane.setBackground(new Color(0, 0, 0, 0)); // 閫忔槑鑳屾櫙
+ jContentPane.setOpaque(false);
+ }
}
private void initializeRemoteContent() {
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.setBorder(BorderFactory.createEmptyBorder(16, 16, 16, 16));
- contentPanel.setBackground(Color.WHITE);
+ contentPanel.setOpaque(false); // 璁剧疆涓洪�忔槑
+
+ // 鍒涘缓椤堕儴闈㈡澘锛屽寘鍚寜閽拰鏁板�兼樉绀�
+ JPanel topPanel = new JPanel(new BorderLayout());
+ topPanel.setOpaque(false);
+
+ // 鍒涘缓鎸夐挳闈㈡澘锛�4涓寜閽紝闂撮殧30鍍忕礌锛�
+ JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 30, 0));
+ buttonPanel.setOpaque(false);
+ buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0)); // 搴曢儴闂磋窛8鍍忕礌
+
+ // 鎸夐挳1锛歰ff.png <-> starton.png锛屾枃瀛楋細鍚姩 <-> 鐔勭伀
+ JLabel label1 = new JLabel("鍚姩", SwingConstants.CENTER);
+ label1.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+ label1.setForeground(new Color(40, 40, 40));
+ JButton button1 = createIconButtonWithLabel("image/off.png", "image/starton.png", 27, 27,
+ label1, "鍚姩", "鐔勭伀", "POWER");
+ JPanel panel1 = createButtonWithLabel(button1, label1);
+ buttonPanel.add(panel1);
+
+ // 鎸夐挳2锛歞engoff.png <-> dengon.png锛屾枃瀛楋細寮�鐏� <-> 鍏崇伅
+ JLabel label2 = new JLabel("寮�鐏�", SwingConstants.CENTER);
+ label2.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+ label2.setForeground(new Color(40, 40, 40));
+ JButton button2 = createIconButtonWithLabel("image/dengoff.png", "image/dengon.png", 30, 30,
+ label2, "寮�鐏�", "鍏崇伅", "LIGHT");
+ JPanel panel2 = createButtonWithLabel(button2, label2);
+ buttonPanel.add(panel2);
+
+ // 鎸夐挳3锛歺ia1.png锛堝浐瀹氬浘鏍囷級锛屾枃瀛楋細鍒�鐩樺崌
+ JButton button3 = createBladeControlButton("image/xia1.png", "image/xia20.png", 30, 30, true);
+ JLabel label3 = new JLabel("鍒�鐩樺崌", SwingConstants.CENTER);
+ label3.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+ label3.setForeground(new Color(40, 40, 40));
+ button3.putClientProperty("label", label3);
+ button3.putClientProperty("defaultText", bladeUpDefaultText);
+ bladeButtons.add(button3); // 娣诲姞鍒板垪琛ㄤ互渚挎竻鐞�
+ JPanel panel3 = createButtonWithLabel(button3, label3);
+ buttonPanel.add(panel3);
+
+ // 鎸夐挳4锛歺ia2.png锛堝浐瀹氬浘鏍囷級锛屾枃瀛楋細鍒�鐩橀檷
+ JButton button4 = createBladeControlButton("image/xia2.png", "image/xia10.png", 30, 30, false);
+ JLabel label4 = new JLabel("鍒�鐩橀檷", SwingConstants.CENTER);
+ label4.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+ label4.setForeground(new Color(40, 40, 40));
+ button4.putClientProperty("label", label4);
+ button4.putClientProperty("defaultText", bladeDownDefaultText);
+ bladeButtons.add(button4); // 娣诲姞鍒板垪琛ㄤ互渚挎竻鐞�
+ JPanel panel4 = createButtonWithLabel(button4, label4);
+ buttonPanel.add(panel4);
+
+ topPanel.add(buttonPanel, BorderLayout.NORTH);
// 鍦ㄦ瘡涓憞鏉嗕笂鏂瑰垎鍒樉绀哄叾鐘舵��/鏁板�硷紙鍒嗕袱鍒楋級
JPanel valuesPanel = new JPanel(new GridLayout(1, 2, 20, 0));
@@ -80,14 +144,16 @@
valuesPanel.add(moveJoystickValueLabel);
valuesPanel.add(turnJoystickValueLabel);
- contentPanel.add(valuesPanel, BorderLayout.NORTH);
+ topPanel.add(valuesPanel, BorderLayout.CENTER);
+
+ contentPanel.add(topPanel, BorderLayout.NORTH);
// 鍒涘缓鎽囨潌闈㈡澘
JPanel joystickPanel = new JPanel(new GridLayout(1, 2, 20, 0));
joystickPanel.setOpaque(false);
// 绉诲姩鎽囨潌锛堢豢鑹蹭富棰橈級
- moveJoystick = new ModernJoystickComponent("鍓嶈繘/鍚庨��",
+ moveJoystick = new ModernJoystickComponent(" ",
new Color(46, 204, 113), true); // 缁胯壊涓婚
moveJoystick.setJoystickListener(new JoystickListener() {
@Override
@@ -98,10 +164,15 @@
// 闄愬埗鍦� [-100, 100]
forwardVal = Math.max(-100, Math.min(100, forwardVal));
+ // 鏇存柊鐩爣閫熷害
+ targetForwardSpeed = forwardVal;
+
if (Math.abs(y) > 0.1) {
- applyForwardSpeed(forwardVal);
+ // 鎽囨潌涓嶅湪涓績浣嶇疆锛屽惎鍔ㄦ寔缁彂閫佸畾鏃跺櫒
+ startForwardControlTimer();
} else {
- // 鍓嶅悗
+ // 鎽囨潌鍥炲埌涓績浣嶇疆锛屽仠姝㈠彂閫�
+ stopForwardControlTimer();
stopForward();
}
@@ -111,7 +182,7 @@
}
});
// 杞悜鎽囨潌锛堣摑鑹蹭富棰橈級
- turnJoystick = new ModernJoystickComponent("宸﹁浆/鍙宠浆",
+ turnJoystick = new ModernJoystickComponent("",
new Color(52, 152, 219), false); // 钃濊壊涓婚
turnJoystick.setJoystickListener(new JoystickListener() {
@Override
@@ -121,10 +192,15 @@
int steeringVal = (int) Math.round(x * 100.0);
steeringVal = Math.max(-100, Math.min(100, steeringVal));
+ // 鏇存柊鐩爣閫熷害
+ targetSteeringSpeed = steeringVal;
+
if (Math.abs(x) > 0.1) {
- applySteeringSpeed(steeringVal);
+ // 鎽囨潌涓嶅湪涓績浣嶇疆锛屽惎鍔ㄦ寔缁彂閫佸畾鏃跺櫒
+ startSteeringControlTimer();
} else {
- // 宸﹀彸
+ // 鎽囨潌鍥炲埌涓績浣嶇疆锛屽仠姝㈠彂閫�
+ stopSteeringControlTimer();
stopSteering();
}
@@ -142,6 +218,360 @@
getContentPane().add(contentPanel);
}
+ /**
+ * 鍒涘缓甯︽爣绛剧殑鎸夐挳闈㈡澘锛堝瀭鐩村竷灞�锛氭寜閽湪涓婏紝鏍囩鍦ㄤ笅锛�
+ * @param button 鎸夐挳
+ * @param label 鏍囩
+ * @return 鍖呭惈鎸夐挳鍜屾爣绛剧殑闈㈡澘
+ */
+ private JPanel createButtonWithLabel(JButton button, JLabel label) {
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.setOpaque(false);
+ panel.add(button, BorderLayout.CENTER);
+ panel.add(label, BorderLayout.SOUTH);
+ panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ return panel;
+ }
+
+ /**
+ * 鍒涘缓鍙垏鎹㈠浘鏍囩殑鎸夐挳锛堝甫鏍囩鏂囧瓧鍒囨崲锛�
+ * @param defaultIconPath 榛樿鍥炬爣璺緞
+ * @param clickedIconPath 鐐瑰嚮鍚庣殑鍥炬爣璺緞
+ * @param width 鍥炬爣瀹藉害
+ * @param height 鍥炬爣楂樺害
+ * @param label 鏍囩缁勪欢
+ * @param defaultText 榛樿鏂囧瓧
+ * @param clickedText 鐐瑰嚮鍚庣殑鏂囧瓧
+ * @param controlType 鎺у埗鎸囦护绫诲瀷锛�"POWER"琛ㄧず鍚姩/鐔勭伀锛�"LIGHT"琛ㄧず寮�鐏�/鍏崇伅锛宯ull琛ㄧず鏃犳帶鍒舵寚浠�
+ * @return 閰嶇疆濂界殑鎸夐挳
+ */
+ private JButton createIconButtonWithLabel(String defaultIconPath, String clickedIconPath,
+ int width, int height, JLabel label,
+ String defaultText, String clickedText, String controlType) {
+ JButton button = new JButton();
+ button.setPreferredSize(new Dimension(width, height));
+ button.setMinimumSize(new Dimension(width, height));
+ button.setMaximumSize(new Dimension(width, height));
+ button.setContentAreaFilled(false);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+
+ // 鍔犺浇榛樿鍥炬爣鍜岀偣鍑诲浘鏍�
+ ImageIcon defaultIcon = loadIcon(defaultIconPath, width, height);
+ ImageIcon clickedIcon = loadIcon(clickedIconPath, width, height);
+
+ if (defaultIcon != null) {
+ button.setIcon(defaultIcon);
+ }
+
+ // 浣跨敤 clientProperty 鏉ヨ窡韪寜閽姸鎬侊紙false=榛樿鍥炬爣锛宼rue=鐐瑰嚮鍥炬爣锛�
+ button.putClientProperty("isClicked", false);
+ button.putClientProperty("defaultIcon", defaultIcon);
+ button.putClientProperty("clickedIcon", clickedIcon);
+ button.putClientProperty("label", label);
+ button.putClientProperty("defaultText", defaultText);
+ button.putClientProperty("clickedText", clickedText);
+ button.putClientProperty("controlType", controlType);
+
+ // 娣诲姞鐐瑰嚮浜嬩欢锛屽垏鎹㈠浘鏍囧拰鏂囧瓧锛屽苟鍙戦�佹帶鍒舵寚浠�
+ button.addActionListener(e -> {
+ Boolean isClicked = (Boolean) button.getClientProperty("isClicked");
+ ImageIcon defaultIconRef = (ImageIcon) button.getClientProperty("defaultIcon");
+ ImageIcon clickedIconRef = (ImageIcon) button.getClientProperty("clickedIcon");
+ JLabel labelRef = (JLabel) button.getClientProperty("label");
+ String defaultTextRef = (String) button.getClientProperty("defaultText");
+ String clickedTextRef = (String) button.getClientProperty("clickedText");
+ String controlTypeRef = (String) button.getClientProperty("controlType");
+
+ if (isClicked == null || !isClicked) {
+ // 褰撳墠鏄粯璁ゅ浘鏍囷紝鍒囨崲鍒扮偣鍑诲浘鏍�
+ if (clickedIconRef != null) {
+ button.setIcon(clickedIconRef);
+ button.putClientProperty("isClicked", true);
+ }
+ // 鏇存柊鏍囩鏂囧瓧
+ if (labelRef != null && clickedTextRef != null) {
+ labelRef.setText(clickedTextRef);
+ }
+ // 鍙戦�佹帶鍒舵寚浠わ紙寮�鍚級
+ if ("POWER".equals(controlTypeRef)) {
+ boolean success = Control05.sendPowerOnIfDebugSerialOpen();
+ if (!success) {
+ showSerialClosedWarning();
+ }
+ } else if ("LIGHT".equals(controlTypeRef)) {
+ boolean success = Control07.sendLightOnIfDebugSerialOpen();
+ if (!success) {
+ showSerialClosedWarning();
+ }
+ }
+ } else {
+ // 褰撳墠鏄偣鍑诲浘鏍囷紝鍒囨崲鍥為粯璁ゅ浘鏍�
+ if (defaultIconRef != null) {
+ button.setIcon(defaultIconRef);
+ button.putClientProperty("isClicked", false);
+ }
+ // 鏇存柊鏍囩鏂囧瓧
+ if (labelRef != null && defaultTextRef != null) {
+ labelRef.setText(defaultTextRef);
+ }
+ // 鍙戦�佹帶鍒舵寚浠わ紙鍏抽棴锛�
+ if ("POWER".equals(controlTypeRef)) {
+ boolean success = Control05.sendPowerOffIfDebugSerialOpen();
+ if (!success) {
+ showSerialClosedWarning();
+ }
+ } else if ("LIGHT".equals(controlTypeRef)) {
+ boolean success = Control07.sendLightOffIfDebugSerialOpen();
+ if (!success) {
+ showSerialClosedWarning();
+ }
+ }
+ }
+ });
+
+ return button;
+ }
+
+ /**
+ * 鍒涘缓鍙垏鎹㈠浘鏍囩殑鎸夐挳
+ * @param defaultIconPath 榛樿鍥炬爣璺緞
+ * @param clickedIconPath 鐐瑰嚮鍚庣殑鍥炬爣璺緞
+ * @param width 鍥炬爣瀹藉害
+ * @param height 鍥炬爣楂樺害
+ * @return 閰嶇疆濂界殑鎸夐挳
+ */
+ private JButton createIconButton(String defaultIconPath, String clickedIconPath, int width, int height) {
+ JButton button = new JButton();
+ button.setPreferredSize(new Dimension(width, height));
+ button.setMinimumSize(new Dimension(width, height));
+ button.setMaximumSize(new Dimension(width, height));
+ button.setContentAreaFilled(false);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+
+ // 鍔犺浇榛樿鍥炬爣鍜岀偣鍑诲浘鏍�
+ ImageIcon defaultIcon = loadIcon(defaultIconPath, width, height);
+ ImageIcon clickedIcon = loadIcon(clickedIconPath, width, height);
+
+ if (defaultIcon != null) {
+ button.setIcon(defaultIcon);
+ }
+
+ // 浣跨敤 clientProperty 鏉ヨ窡韪寜閽姸鎬侊紙false=榛樿鍥炬爣锛宼rue=鐐瑰嚮鍥炬爣锛�
+ button.putClientProperty("isClicked", false);
+ button.putClientProperty("defaultIcon", defaultIcon);
+ button.putClientProperty("clickedIcon", clickedIcon);
+
+ // 娣诲姞鐐瑰嚮浜嬩欢锛屽垏鎹㈠浘鏍�
+ button.addActionListener(e -> {
+ Boolean isClicked = (Boolean) button.getClientProperty("isClicked");
+ ImageIcon defaultIconRef = (ImageIcon) button.getClientProperty("defaultIcon");
+ ImageIcon clickedIconRef = (ImageIcon) button.getClientProperty("clickedIcon");
+
+ if (isClicked == null || !isClicked) {
+ // 褰撳墠鏄粯璁ゅ浘鏍囷紝鍒囨崲鍒扮偣鍑诲浘鏍�
+ if (clickedIconRef != null) {
+ button.setIcon(clickedIconRef);
+ button.putClientProperty("isClicked", true);
+ }
+ } else {
+ // 褰撳墠鏄偣鍑诲浘鏍囷紝鍒囨崲鍥為粯璁ゅ浘鏍�
+ if (defaultIconRef != null) {
+ button.setIcon(defaultIconRef);
+ button.putClientProperty("isClicked", false);
+ }
+ }
+ });
+
+ return button;
+ }
+
+ /**
+ * 鍒涘缓鍥哄畾鍥炬爣鐨勬寜閽�
+ * @param iconPath 鍥炬爣璺緞
+ * @param width 鍥炬爣瀹藉害
+ * @param height 鍥炬爣楂樺害
+ * @return 閰嶇疆濂界殑鎸夐挳
+ */
+ private JButton createFixedIconButton(String iconPath, int width, int height) {
+ JButton button = new JButton();
+ button.setPreferredSize(new Dimension(width, height));
+ button.setMinimumSize(new Dimension(width, height));
+ button.setMaximumSize(new Dimension(width, height));
+ button.setContentAreaFilled(false);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+
+ ImageIcon icon = loadIcon(iconPath, width, height);
+ if (icon != null) {
+ button.setIcon(icon);
+ }
+
+ return button;
+ }
+
+ /**
+ * 鍒涘缓鍒�鐩樺崌闄嶆帶鍒舵寜閽紙鏀寔鐐瑰嚮鍜岄暱鎸夛級
+ * @param defaultIconPath 榛樿鍥炬爣璺緞
+ * @param clickedIconPath 鐐瑰嚮/闀挎寜鏃剁殑鍥炬爣璺緞
+ * @param width 鍥炬爣瀹藉害
+ * @param height 鍥炬爣楂樺害
+ * @param isUp true琛ㄧず鍒�鐩樺崌锛宖alse琛ㄧず鍒�鐩橀檷
+ * @return 閰嶇疆濂界殑鎸夐挳
+ */
+ private JButton createBladeControlButton(String defaultIconPath, String clickedIconPath,
+ int width, int height, boolean isUp) {
+ JButton button = new JButton();
+ button.setPreferredSize(new Dimension(width, height));
+ button.setMinimumSize(new Dimension(width, height));
+ button.setMaximumSize(new Dimension(width, height));
+ button.setContentAreaFilled(false);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+
+ // 鍔犺浇鍥炬爣
+ ImageIcon defaultIcon = loadIcon(defaultIconPath, width, height);
+ ImageIcon clickedIcon = loadIcon(clickedIconPath, width, height);
+
+ if (defaultIcon != null) {
+ button.setIcon(defaultIcon);
+ }
+
+ button.putClientProperty("defaultIcon", defaultIcon);
+ button.putClientProperty("clickedIcon", clickedIcon);
+ button.putClientProperty("isUp", isUp);
+ button.putClientProperty("isPressed", false);
+
+ // 闀挎寜瀹氭椂鍣�
+ Timer longPressTimer = new Timer(100, e -> { // 姣�100ms鎵ц涓�娆�
+ if (button.getClientProperty("isPressed") == Boolean.TRUE) {
+ boolean isUpButton = (Boolean) button.getClientProperty("isUp");
+ int currentHeight = Control06.getCurrentBladeHeight();
+
+ // 浣跨敤Control06鐨勬柟娉曞彂閫佹寚浠�
+ boolean success;
+ if (isUpButton) {
+ success = Control06.sendBladeUpIfDebugSerialOpen(1);
+ } else {
+ success = Control06.sendBladeDownIfDebugSerialOpen(1);
+ }
+
+ if (!success) {
+ showSerialClosedWarning();
+ } else {
+ // 鏇存柊鎸夐挳鏍囩鏄剧ず褰撳墠鏁板��
+ updateBladeButtonLabel(button);
+ }
+ }
+ });
+ longPressTimer.setInitialDelay(500); // 闀挎寜500ms鍚庡紑濮嬭繛缁彉鍖�
+ button.putClientProperty("longPressTimer", longPressTimer); // 瀛樺偍瀹氭椂鍣ㄥ紩鐢�
+
+ // 榧犳爣鎸変笅浜嬩欢
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ button.putClientProperty("isPressed", true);
+
+ // 绔嬪嵆鍒囨崲鍥炬爣
+ ImageIcon clickedIconRef = (ImageIcon) button.getClientProperty("clickedIcon");
+ if (clickedIconRef != null) {
+ button.setIcon(clickedIconRef);
+ }
+
+ // 鐐瑰嚮鏃剁珛鍗冲鍔�/鍑忓皯10锛屼娇鐢–ontrol06鐨勬柟娉曞彂閫佹寚浠�
+ boolean isUpButton = (Boolean) button.getClientProperty("isUp");
+ boolean success;
+ if (isUpButton) {
+ success = Control06.sendBladeUpIfDebugSerialOpen(10);
+ } else {
+ success = Control06.sendBladeDownIfDebugSerialOpen(10);
+ }
+
+ if (!success) {
+ showSerialClosedWarning();
+ } else {
+ // 鏇存柊鎸夐挳鏍囩鏄剧ず褰撳墠鏁板��
+ updateBladeButtonLabel(button);
+ }
+
+ // 鍚姩闀挎寜瀹氭椂鍣�
+ longPressTimer.start();
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ button.putClientProperty("isPressed", false);
+
+ // 鍋滄闀挎寜瀹氭椂鍣�
+ longPressTimer.stop();
+
+ // 鎭㈠榛樿鍥炬爣
+ ImageIcon defaultIconRef = (ImageIcon) button.getClientProperty("defaultIcon");
+ if (defaultIconRef != null) {
+ button.setIcon(defaultIconRef);
+ }
+
+ // 鎭㈠榛樿鏂囧瓧
+ JLabel labelRef = (JLabel) button.getClientProperty("label");
+ String defaultTextRef = (String) button.getClientProperty("defaultText");
+ if (labelRef != null && defaultTextRef != null) {
+ labelRef.setText(defaultTextRef);
+ }
+ }
+ });
+
+ return button;
+ }
+
+ /**
+ * 鏇存柊鍒�鐩樻寜閽爣绛炬樉绀哄綋鍓嶆暟鍊�
+ * @param button 鎸夐挳
+ */
+ private void updateBladeButtonLabel(JButton button) {
+ JLabel labelRef = (JLabel) button.getClientProperty("label");
+ if (labelRef != null) {
+ String defaultTextRef = (String) button.getClientProperty("defaultText");
+ int currentHeight = Control06.getCurrentBladeHeight();
+ String displayText = defaultTextRef + " " + currentHeight;
+ labelRef.setText(displayText);
+ }
+ }
+
+ /**
+ * 鍔犺浇骞剁缉鏀惧浘鏍�
+ * @param iconPath 鍥炬爣璺緞
+ * @param width 鐩爣瀹藉害
+ * @param height 鐩爣楂樺害
+ * @return 缂╂斁鍚庣殑鍥炬爣
+ */
+ private ImageIcon loadIcon(String iconPath, int width, int height) {
+ try {
+ java.net.URL imgURL = getClass().getClassLoader().getResource(iconPath);
+ if (imgURL == null) {
+ // 灏濊瘯浠庢枃浠剁郴缁熷姞杞�
+ java.io.File imgFile = new java.io.File(iconPath);
+ if (imgFile.exists()) {
+ ImageIcon originalIcon = new ImageIcon(imgFile.getAbsolutePath());
+ Image scaledImage = originalIcon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
+ ImageIcon scaledIcon = new ImageIcon(scaledImage);
+ scaledIcon.setDescription(iconPath);
+ return scaledIcon;
+ }
+ } else {
+ ImageIcon originalIcon = new ImageIcon(imgURL);
+ Image scaledImage = originalIcon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
+ ImageIcon scaledIcon = new ImageIcon(scaledImage);
+ scaledIcon.setDescription(iconPath);
+ return scaledIcon;
+ }
+ } catch (Exception e) {
+ System.err.println("鏃犳硶鍔犺浇鍥炬爣: " + iconPath + " - " + e.getMessage());
+ }
+ return null;
+ }
+
private JPanel createStatusPanel(String label, String value, Color color) {
JPanel panel = new JPanel(new BorderLayout(0, 5));
panel.setOpaque(false);
@@ -235,6 +665,102 @@
}
}
+ /**
+ * 鍚姩鍓嶈繘/鍚庨��鎺у埗瀹氭椂鍣紝鎸佺画鍙戦�佹帶鍒舵寚浠�
+ */
+ private void startForwardControlTimer() {
+ // 濡傛灉瀹氭椂鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄瀹�
+ if (forwardControlTimer != null && forwardControlTimer.isRunning()) {
+ forwardControlTimer.stop();
+ }
+
+ // 鍒涘缓鏂扮殑瀹氭椂鍣紝姣�100ms鍙戦�佷竴娆℃寚浠�
+ forwardControlTimer = new Timer(100, new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // 鎸佺画鍙戦�佺洰鏍囬�熷害鐨勬寚浠�
+ applyForwardSpeedContinuously(targetForwardSpeed);
+ }
+ });
+ forwardControlTimer.setInitialDelay(0);
+ forwardControlTimer.start();
+ }
+
+ /**
+ * 鍋滄鍓嶈繘/鍚庨��鎺у埗瀹氭椂鍣�
+ */
+ private void stopForwardControlTimer() {
+ if (forwardControlTimer != null && forwardControlTimer.isRunning()) {
+ forwardControlTimer.stop();
+ }
+ }
+
+ /**
+ * 鍚姩杞悜鎺у埗瀹氭椂鍣紝鎸佺画鍙戦�佹帶鍒舵寚浠�
+ */
+ private void startSteeringControlTimer() {
+ // 濡傛灉瀹氭椂鍣ㄥ凡缁忓湪杩愯锛屽厛鍋滄瀹�
+ if (steeringControlTimer != null && steeringControlTimer.isRunning()) {
+ steeringControlTimer.stop();
+ }
+
+ // 鍒涘缓鏂扮殑瀹氭椂鍣紝姣�100ms鍙戦�佷竴娆℃寚浠�
+ steeringControlTimer = new Timer(100, new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // 鎸佺画鍙戦�佺洰鏍囬�熷害鐨勬寚浠�
+ applySteeringSpeedContinuously(targetSteeringSpeed);
+ }
+ });
+ steeringControlTimer.setInitialDelay(0);
+ steeringControlTimer.start();
+ }
+
+ /**
+ * 鍋滄杞悜鎺у埗瀹氭椂鍣�
+ */
+ private void stopSteeringControlTimer() {
+ if (steeringControlTimer != null && steeringControlTimer.isRunning()) {
+ steeringControlTimer.stop();
+ }
+ }
+
+ /**
+ * 鎸佺画鍙戦�佸墠杩�/鍚庨��閫熷害鎸囦护
+ */
+ private void applyForwardSpeedContinuously(int targetSpeed) {
+ int currentSpeed = Control03.getCurrentForwardSpeed();
+ int currentSteeringSpeed = Control03.getCurrentSteeringSpeed();
+
+ // 濡傛灉宸茬粡杈惧埌鐩爣閫熷害锛岀洿鎺ュ彂閫佷竴娆′互淇濇寔鐘舵��
+ if (currentSpeed == targetSpeed) {
+ // 鐩存帴鍙戦�佺洰鏍囬�熷害鎸囦护浠ヤ繚鎸佺姸鎬侊紙鍗充娇閫熷害鐩稿悓涔熻鍙戦�侊級
+ Control03.setAndSendSpeeds(currentSteeringSpeed, targetSpeed);
+ } else {
+ // 閫愭璋冩暣鍒扮洰鏍囬�熷害
+ int delta = targetSpeed > currentSpeed ? 10 : -10;
+ Control03.adjustForwardSpeed(delta);
+ }
+ }
+
+ /**
+ * 鎸佺画鍙戦�佽浆鍚戦�熷害鎸囦护
+ */
+ private void applySteeringSpeedContinuously(int targetSpeed) {
+ int currentSpeed = Control03.getCurrentSteeringSpeed();
+ int currentForwardSpeed = Control03.getCurrentForwardSpeed();
+
+ // 濡傛灉宸茬粡杈惧埌鐩爣閫熷害锛岀洿鎺ュ彂閫佷竴娆′互淇濇寔鐘舵��
+ if (currentSpeed == targetSpeed) {
+ // 鐩存帴鍙戦�佺洰鏍囬�熷害鎸囦护浠ヤ繚鎸佺姸鎬侊紙鍗充娇閫熷害鐩稿悓涔熻鍙戦�侊級
+ Control03.setAndSendSpeeds(targetSpeed, currentForwardSpeed);
+ } else {
+ // 閫愭璋冩暣鍒扮洰鏍囬�熷害
+ int delta = targetSpeed > currentSpeed ? 15 : -15;
+ Control03.adjustSteeringSpeed(delta);
+ }
+ }
+
// 鏇存柊椤堕儴鏄剧ず鐨勬憞鏉嗘暟鍊硷紙鍦� EDT 涓婅皟鐢級锛屾枃瀛楁牴鎹暟鍊兼槧灏勪负鏂瑰悜鎻忚堪
private void updateJoystickValues(int forwardVal, int steeringVal) {
// 璁$畻绉诲姩/杞悜鎻忚堪鏂囨湰
@@ -330,6 +856,15 @@
@Override
public void dispose() {
+ // 鍋滄骞舵竻鐞嗘帶鍒跺畾鏃跺櫒
+ stopForwardControlTimer();
+ stopSteeringControlTimer();
+ if (forwardControlTimer != null) {
+ forwardControlTimer = null;
+ }
+ if (steeringControlTimer != null) {
+ steeringControlTimer = null;
+ }
// 鍓嶅悗閫熷害鏇存柊瀹氭椂鍣�
if (speedUpdateTimer != null) {
speedUpdateTimer.stop();
@@ -349,6 +884,14 @@
if (turnJoystick != null) {
turnJoystick.dispose();
}
+ // 鍋滄骞舵竻鐞嗗垁鐩樻寜閽殑瀹氭椂鍣�
+ for (JButton bladeButton : bladeButtons) {
+ Timer timer = (Timer) bladeButton.getClientProperty("longPressTimer");
+ if (timer != null && timer.isRunning()) {
+ timer.stop();
+ }
+ }
+ bladeButtons.clear();
super.dispose();
}
--
Gitblit v1.10.0