| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <classpath> |
| | | <classpathentry kind="src" path="src"/> |
| | | <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"> |
| | | <attributes> |
| | | <attribute name="module" value="true"/> |
| | | </attributes> |
| | | </classpathentry> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jackson-annotations-2.15.2.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jackson-core-2.15.2.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jackson-databind-2.15.2.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jSerialComm-2.10.4.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/jts-core-1.19.0.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/lombok-1.18.36.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/MQTT-1.0-SNAPSHOT.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/org.eclipse.paho.client.mqttv3-1.2.2.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/slf4j-api-1.7.30.jar"/> |
| | | <classpathentry kind="lib" path="D:/eclipseworkspace/GIT/GeCaoAPP/lib/slf4j-simple-1.7.30.jar"/> |
| | | <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jackson-annotations-2.15.2.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jackson-core-2.15.2.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jackson-databind-2.15.2.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jSerialComm-2.10.4.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/jts-core-1.19.0.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/lombok-1.18.36.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/MQTT-1.0-SNAPSHOT.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/org.eclipse.paho.client.mqttv3-1.2.2.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/slf4j-api-1.7.30.jar"/> |
| | | <classpathentry kind="lib" path="E:/Users/hxzk/eclipse-workspace/GeCaoAPP/lib/slf4j-simple-1.7.30.jar"/> |
| | | <classpathentry kind="output" path="bin"/> |
| | | </classpath> |
| | |
| | | #Mower Configuration Properties - Updated |
| | | #Sun Dec 28 20:35:53 GMT+08:00 2025 |
| | | #Current work land selection updated |
| | | #Mon Dec 29 14:26:39 CST 2025 |
| | | appVersion=-1 |
| | | simCardNumber=-1 |
| | | currentWorkLandNumber=LAND1 |
| | | serialBaudRate=115200 |
| | | boundaryLengthVisible=false |
| | | idleTrailDurationSeconds=60 |
| | | handheldMarkerId=1872 |
| | | viewCenterX=-60.00 |
| | | viewCenterY=-34.94 |
| | | manualBoundaryDrawingMode=false |
| | | mowerId=6258 |
| | | serialPortName=COM15 |
| | | serialAutoConnect=true |
| | | mapScale=8.60 |
| | | measurementModeEnabled=false |
| | | firmwareVersion=-1 |
| | | currentWorkLandNumber=LAND1 |
| | | cuttingWidth=200 |
| | | firmwareVersion=-1 |
| | | handheldMarkerId=1872 |
| | | idleTrailDurationSeconds=60 |
| | | manualBoundaryDrawingMode=false |
| | | mapScale=12.32 |
| | | measurementModeEnabled=false |
| | | mowerId=6258 |
| | | serialAutoConnect=true |
| | | serialBaudRate=115200 |
| | | serialPortName=COM15 |
| | | simCardNumber=-1 |
| | | viewCenterX=-53.78 |
| | | viewCenterY=-35.02 |
| | |
| | | } |
| | | |
| | | // 徿 é»è®¤æä¸ï¼270度ï¼ï¼éè¦è®¡ç®æè½¬è§åº¦ä½¿è½¦å¤´æåè¡é©¶æ¹å |
| | | // 妿è¿å¨æ¹ååä¸ï¼90度ï¼â éè¦æè½¬180度ï¼270 - 90 = 180ï¼ |
| | | // 妿è¿å¨æ¹ååå³ï¼0度ï¼â éè¦æè½¬270度ï¼270 - 0 = 270ï¼ |
| | | // 妿è¿å¨æ¹ååå·¦ï¼180度ï¼â éè¦æè½¬90度ï¼270 - 180 = 90ï¼ |
| | | // 妿è¿å¨æ¹ååä¸ï¼270度ï¼â éè¦æè½¬0度ï¼270 - 270 = 0ï¼ |
| | | // å
¬å¼ï¼heading = (270 - atan2Angle + 360) % 360 |
| | | double heading = (270.0 - atan2Angle + 360.0) % 360.0; |
| | | // åæ ç³»ï¼North(+Y) -> Screen Down(90). East(+X) -> Screen Right(0). |
| | | // atan2: North(90), East(0). |
| | | // ç®æ ï¼North -> Icon Down(0 rot). East -> Icon Right(270 rot). |
| | | // 90 -> 0. |
| | | // 0 -> 270. |
| | | // å
¬å¼ï¼heading = (atan2Angle + 270) % 360 |
| | | double heading = (atan2Angle + 270.0) % 360.0; |
| | | |
| | | return heading; |
| | | } |
| | |
| | | // 宿¶é度 |
| | | private String heading; |
| | | // èªåè§ |
| | | private String pitch; |
| | | // ä¿¯ä»°è§ |
| | | private String roll; // 横æ»è§ è§åº¦ |
| | | private String yaw; // åèªè§ è§åº¦ |
| | | private String battery_level; // çµæ± çµéç¾åæ¯ |
| | |
| | | if (realtimeY != null) properties.setProperty("realtimeY", realtimeY); |
| | | if (realtimeSpeed != null) properties.setProperty("realtimeSpeed", realtimeSpeed); |
| | | if (heading != null) properties.setProperty("heading", heading); |
| | | if (pitch != null) properties.setProperty("pitch", pitch); |
| | | if (roll != null) properties.setProperty("roll", roll); |
| | | if (yaw != null) properties.setProperty("yaw", yaw); |
| | | if (battery_level != null) properties.setProperty("battery_level", battery_level); |
| | |
| | | target.realtimeY = properties.getProperty("realtimeY", "-1"); |
| | | target.realtimeSpeed = properties.getProperty("realtimeSpeed", "-1"); |
| | | target.heading = properties.getProperty("heading", "-1"); |
| | | target.pitch = properties.getProperty("pitch", "-1"); |
| | | target.roll = properties.getProperty("roll", "-1"); |
| | | target.yaw = properties.getProperty("yaw", "-1"); |
| | | target.battery_level = properties.getProperty("battery_level", "-1"); |
| | |
| | | target.realtimeY = "-1"; |
| | | target.realtimeSpeed = "-1"; |
| | | target.heading = "-1"; |
| | | target.pitch = "-1"; |
| | | target.roll = "-1"; |
| | | target.yaw = "-1"; |
| | | target.battery_level = "-1"; |
| | |
| | | case "heading": |
| | | this.heading = value; |
| | | return true; |
| | | case "pitch": |
| | | this.pitch = value; |
| | | return true; |
| | | case "roll": |
| | | this.roll = value; |
| | | return true; |
| | |
| | | satelliteCount = defaultIfEmpty(sanitizeField(fields, 7)); |
| | | differentialAge = defaultIfEmpty(sanitizeField(fields, 13)); |
| | | battery_level = defaultIfEmpty(sanitizeField(fields, 16)); |
| | | pitch = defaultIfEmpty(sanitizeField(fields, 17)); |
| | | yaw = defaultIfEmpty(sanitizeField(fields, 17)); |
| | | realtimeSpeed = defaultIfEmpty(sanitizeField(fields, 18)); |
| | | GupdateTime = String.valueOf(System.currentTimeMillis()); |
| | | } |
| | |
| | | this.heading = heading; |
| | | } |
| | | |
| | | public String getPitch() { // è·åä¿¯ä»°è§ |
| | | return pitch; |
| | | } |
| | | |
| | | public void setPitch(String pitch) { // è®¾ç½®ä¿¯ä»°è§ |
| | | this.pitch = pitch; |
| | | } |
| | | |
| | | public String getRoll() { |
| | | return roll; |
| | | } |
| | |
| | | ", realtimeY='" + realtimeY + '\'' + |
| | | ", realtimeSpeed='" + realtimeSpeed + '\'' + |
| | | ", heading='" + heading + '\'' + |
| | | ", pitch='" + pitch + '\'' + |
| | | ", roll='" + roll + '\'' + |
| | | ", yaw='" + yaw + '\'' + |
| | | ", battery_level='" + battery_level + '\'' + |
| | |
| | | private JLabel errorCodeLabel; |
| | | private JLabel errorMessageLabel; |
| | | private JLabel rollLabel; |
| | | private JLabel pitchLabel; |
| | | private JLabel yawLabel; |
| | | |
| | | private JLabel updateTimeLabel; |
| | |
| | | // 横æ»è§ |
| | | addLabelRow(grid, gbc, currentRow++, "横æ»è§ï¼", rollLabel = createValueLabel(), titleFont, valueFont); |
| | | |
| | | // ä¿¯ä»°è§ |
| | | addLabelRow(grid, gbc, currentRow++, "俯仰è§ï¼", pitchLabel = createValueLabel(), titleFont, valueFont); |
| | | |
| | | // åèªè§ |
| | | addLabelRow(grid, gbc, currentRow++, "åèªè§ï¼", yawLabel = createValueLabel(), titleFont, valueFont); |
| | | |
| | |
| | | errorCodeLabel = null; |
| | | errorMessageLabel = null; |
| | | rollLabel = null; |
| | | pitchLabel = null; |
| | | yawLabel = null; |
| | | |
| | | updateTimeLabel = null; |
| | |
| | | errorCodeLabel.setText(formatDeviceValue(device.getError_code())); |
| | | errorMessageLabel.setText(formatDeviceValue(device.getError_message())); |
| | | rollLabel.setText(formatDeviceValue(device.getRoll())); |
| | | pitchLabel.setText(formatDeviceValue(device.getPitch())); |
| | | yawLabel.setText(formatDeviceValue(device.getYaw())); |
| | | |
| | | updateTimeLabel.setText(formatTimestamp(device.getGupdateTime())); |
| | |
| | | if (errorCodeLabel != null) errorCodeLabel.setText(value); |
| | | if (errorMessageLabel != null) errorMessageLabel.setText(value); |
| | | if (rollLabel != null) rollLabel.setText(value); |
| | | if (pitchLabel != null) pitchLabel.setText(value); |
| | | if (yawLabel != null) yawLabel.setText(value); |
| | | |
| | | if (updateTimeLabel != null) updateTimeLabel.setText(value); |
| | |
| | | return; |
| | | } |
| | | |
| | | if (status.getPitch() != null) { |
| | | device.setPitch(String.valueOf(status.getPitch())); |
| | | } |
| | | if (status.getRoll() != null) { |
| | | device.setRoll(String.valueOf(status.getRoll())); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package sendMQTT; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import sendMQTT.HTTPUtils.ControlCommand; |
| | | import set.Setsys; |
| | | import user.Usrdell; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | |
| | | import org.eclipse.paho.client.mqttv3.MqttClient; |
| | | import org.eclipse.paho.client.mqttv3.MqttConnectOptions; |
| | | import org.eclipse.paho.client.mqttv3.MqttException; |
| | | import org.eclipse.paho.client.mqttv3.MqttMessage; |
| | | |
| | | /** |
| | | * è®¾å¤æ§å¶æä»¤MQTTåéå·¥å
·ç±» |
| | | * ç¨äºå设å¤å鿧嶿令ï¼å¯å¨ã忢ãæåãæ¢å¤ãç´§æ¥åæ¢çï¼ |
| | | */ |
| | | public class ControlCommandSender { |
| | | |
| | | private static final String DEFAULT_HOST = "tcp://39.99.43.227:1883"; |
| | | private static final String DEFAULT_CLIENT_ID_PREFIX = "control_"; |
| | | |
| | | private final String host; |
| | | private final String clientId; |
| | | |
| | | /** |
| | | * æé 彿° |
| | | * @param host MQTT brokerå°åï¼ä¾å¦ "tcp://39.99.43.227:1883" |
| | | * @param clientId MQTT客æ·ç«¯ID |
| | | */ |
| | | public ControlCommandSender(String host, String clientId) { |
| | | this.host = host != null ? host : DEFAULT_HOST; |
| | | this.clientId = clientId != null ? clientId : (DEFAULT_CLIENT_ID_PREFIX + System.currentTimeMillis()); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é»è®¤é
ç½®å建åéå¨ |
| | | * @return ControlCommandSenderå®ä¾ |
| | | */ |
| | | public static ControlCommandSender createDefault() { |
| | | return new ControlCommandSender(DEFAULT_HOST, DEFAULT_CLIENT_ID_PREFIX + System.currentTimeMillis()); |
| | | } |
| | | |
| | | /** |
| | | * å鿧嶿令 |
| | | * |
| | | * @param msgId æ¶æ¯å¯ä¸æ è¯ |
| | | * @param userId ç¨æ·ID |
| | | * @param deviceId 设å¤ç¼å· |
| | | * @param command æ§å¶å½ä»¤ï¼start(å¯å¨), stop(忢), pause(æå), resume(æ¢å¤), emergency_stop(ç´§æ¥åæ¢) |
| | | * @param value1 åæ°1ï¼å¯éï¼Doubleç±»åï¼ |
| | | * @param value2 åæ°2ï¼å¯éï¼Stringç±»åï¼ |
| | | * @param value3 åæ°3ï¼å¯éï¼Integerç±»åï¼ |
| | | * @return æ¯å¦åéæå |
| | | * @throws MqttException MQTTåéå¼å¸¸ |
| | | */ |
| | | public boolean sendControlCommand(String msgId, String userId, String deviceId, |
| | | String command, Double value1, String value2, Integer value3) |
| | | throws MqttException { |
| | | // æå»ºåæ°å¯¹è±¡ |
| | | ControlCommand.ControlParameters parameters = new ControlCommand.ControlParameters( |
| | | value1, value2, value3 |
| | | ); |
| | | |
| | | // æå»ºæ§å¶æä»¤å¯¹è±¡ |
| | | long timestamp = System.currentTimeMillis(); |
| | | ControlCommand controlCommand = new ControlCommand( |
| | | msgId, |
| | | timestamp, |
| | | userId, |
| | | deviceId, |
| | | command, |
| | | parameters |
| | | ); |
| | | |
| | | // 转æ¢ä¸ºJSONå符串 |
| | | String jsonString = toJsonString(controlCommand); |
| | | if (jsonString == null) { |
| | | throw new MqttException(new Exception("JSONåºåå失败")); |
| | | } |
| | | |
| | | // åéMQTTæ¶æ¯ |
| | | return sendMQTT(jsonString, userId, deviceId); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * å°ControlCommand对象转æ¢ä¸ºJSONå符串 |
| | | */ |
| | | private String toJsonString(ControlCommand command) { |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | try { |
| | | return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(command); |
| | | } catch (JsonProcessingException e) { |
| | | e.printStackTrace(); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åéMQTTæ¶æ¯ |
| | | * |
| | | * @param messageJson JSONæ¶æ¯å
容 |
| | | * @param userId ç¨æ·ID |
| | | * @param deviceId 设å¤ç¼å· |
| | | * @return æ¯å¦åéæå |
| | | * @throws MqttException MQTTåéå¼å¸¸ |
| | | */ |
| | | private boolean sendMQTT(String messageJson, String userId, String deviceId) throws MqttException { |
| | | MqttClient client = null; |
| | | try { |
| | | // æå»ºä¸»é¢ï¼app/{user_id}/mower/{device_id}/control |
| | | String topic = String.format("app/%s/mower/%s/control", userId, deviceId); |
| | | |
| | | // å建MQTTè¿æ¥é项 |
| | | MqttConnectOptions options = new MqttConnectOptions(); |
| | | options.setCleanSession(true); |
| | | |
| | | // å建MQTT客æ·ç«¯å¹¶è¿æ¥ |
| | | client = new MqttClient(host, clientId); |
| | | client.connect(options); |
| | | |
| | | // åå»ºæ¶æ¯å¹¶åé |
| | | MqttMessage message = new MqttMessage(); |
| | | message.setPayload(messageJson.getBytes("UTF-8")); |
| | | client.publish(topic, message); |
| | | |
| | | return true; |
| | | |
| | | } catch (UnsupportedEncodingException e) { |
| | | throw new MqttException(e); |
| | | } finally { |
| | | // æå¼è¿æ¥ |
| | | if (client != null && client.isConnected()) { |
| | | try { |
| | | client.disconnect(); |
| | | client.close(); |
| | | } catch (MqttException e) { |
| | | // å¿½ç¥æå¼è¿æ¥æ¶çå¼å¸¸ |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | static String msgId = "hxzkcontrol_hxzkcontrol_20151104" ; |
| | | String userId=Usrdell.getUserEmail();//ç¨æ·ID |
| | | String deviceId=Setsys.getMowerIdValue();//设å¤ID |
| | | private static double battery = 90.0; |
| | | private static String token = "abcd123ds"; |
| | | private static int type = 0; |
| | | /** |
| | | * å¯å¨å½ä»¤ï¼startï¼ |
| | | * âåè½ï¼å¼å§æ§è¡é¢è®¾çè·¯å¾è§å任塿仿åç¶æç»§ç»è¿è¡ |
| | | * âåºç¨åºæ¯ï¼å¼å§å²èä½ä¸ãç»§ç»è¢«æåçä»»å¡ |
| | | * |
| | | * @param userId ç¨æ·ID |
| | | * @param deviceId 设å¤ID |
| | | * @return åéç»æï¼true表示æåï¼false表示失败 |
| | | */ |
| | | public static boolean sendStartCommand(String userId, String deviceId) { |
| | | try { |
| | | ControlCommandSender sender = ControlCommandSender.createDefault(); |
| | | boolean result = sender.sendControlCommand(msgId, userId, deviceId, "start", battery, token, type); |
| | | return result; |
| | | } catch (Exception e) { |
| | | System.err.println("å¯å¨å½ä»¤åé失败: " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 忢å½ä»¤ï¼stopï¼ |
| | | * âåè½ï¼æ£å¸¸åæ¢å²èæºè¿è¡ï¼ä¿åå½åç¶æ |
| | | * âåºç¨åºæ¯ï¼å®æä½ä¸åçæ£å¸¸åæ¢ãç¨æ·ä¸»å¨åæ¢ |
| | | * âç¹ç¹ï¼å¹³ç¨³åé忢ï¼è®°å½åæ¢ä½ç½® |
| | | * |
| | | * @param userId ç¨æ·ID |
| | | * @param deviceId 设å¤ID |
| | | * @return åéç»æï¼true表示æåï¼false表示失败 |
| | | */ |
| | | public static boolean sendStopCommand(String userId, String deviceId) { |
| | | try { |
| | | ControlCommandSender sender = ControlCommandSender.createDefault(); |
| | | boolean result = sender.sendControlCommand(msgId, userId, deviceId, "stop", battery, token, type); |
| | | return result; |
| | | } catch (Exception e) { |
| | | System.err.println("忢å½ä»¤åé失败: " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æåå½ä»¤ï¼pauseï¼ |
| | | * âåè½ï¼ä¸´æ¶æåå½åè¿è¡ï¼ä¿æè®¾å¤å°±ç»ªç¶æ |
| | | * âåºç¨åºæ¯ï¼ä¸´æ¶æ£æ¥ãé¿è®©éç¢ç©ãç¨æ·ä¸´æ¶ä¸æ |
| | | * âç¹ç¹ï¼å¯å¿«éæ¢å¤ï¼æ ééæ°åå§å |
| | | * |
| | | * @param userId ç¨æ·ID |
| | | * @param deviceId 设å¤ID |
| | | * @return åéç»æï¼true表示æåï¼false表示失败 |
| | | */ |
| | | public static boolean sendPauseCommand(String userId, String deviceId) { |
| | | try { |
| | | ControlCommandSender sender = ControlCommandSender.createDefault(); |
| | | boolean result = sender.sendControlCommand(msgId, userId, deviceId, "pause", battery, token, type); |
| | | |
| | | return result; |
| | | } catch (Exception e) { |
| | | System.err.println("æåå½ä»¤åé失败: " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¢å¤å½ä»¤ï¼resumeï¼ |
| | | * âåè½ï¼ä»æåç¶ææ¢å¤ä¹åçè¿è¡ |
| | | * âåºç¨åºæ¯ï¼æååç»§ç»ä½ä¸ |
| | | * âç¹ç¹ï¼ä»æåç¹ç»§ç»æ§è¡ï¼ä¿æè·¯å¾è¿ç»æ§ |
| | | * |
| | | * @param userId ç¨æ·ID |
| | | * @param deviceId 设å¤ID |
| | | * @return åéç»æï¼true表示æåï¼false表示失败 |
| | | */ |
| | | public static boolean sendResumeCommand(String userId, String deviceId) { |
| | | try { |
| | | ControlCommandSender sender = ControlCommandSender.createDefault(); |
| | | boolean result = sender.sendControlCommand(msgId, userId, deviceId, "resume", battery, token, type); |
| | | return result; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * ç´§æ¥åæ¢å½ä»¤ï¼emergency_stopï¼ |
| | | * âåè½ï¼ç«å³åæ¢ææå¨ä½ï¼åæå¨åè¾åº |
| | | * âåºç¨åºæ¯ï¼ç´§æ¥æ
åµãå®å
¨å¨èã设å¤å¼å¸¸ |
| | | * âç¹ç¹ï¼æé«ä¼å
级ï¼éè¦æå¨å¤ä½æè½éæ°å¯å¨ |
| | | * |
| | | * @param userId ç¨æ·ID |
| | | * @param deviceId 设å¤ID |
| | | * @return åéç»æï¼true表示æåï¼false表示失败 |
| | | */ |
| | | public static boolean sendEmergencyStopCommand(String userId, String deviceId) { |
| | | try { |
| | | ControlCommandSender sender = ControlCommandSender.createDefault(); |
| | | boolean result = sender.sendControlCommand(msgId, userId, deviceId, "emergency_stop", battery, token, type); |
| | | return result; |
| | | } catch (Exception e) { |
| | | System.err.println("ç´§æ¥åæ¢å½ä»¤åé失败: " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package sendMQTT.HTTPUtils; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * è®¾å¤æ§å¶æä»¤JSONç»æ |
| | | * 主é¢ï¼app/{user_id}/mower/{device_id}/control |
| | | */ |
| | | |
| | | public class ControlCommand { |
| | | |
| | | @JsonProperty("msg_id") |
| | | private String msgId; |
| | | |
| | | private long timestamp; |
| | | |
| | | @JsonProperty("user_id") |
| | | private String userId; |
| | | |
| | | @JsonProperty("device_id") |
| | | private String deviceId; |
| | | |
| | | private String command; // start, stop, pause, resume, emergency_stop |
| | | |
| | | private ControlParameters parameters; |
| | | |
| | | public ControlCommand() { |
| | | } |
| | | |
| | | |
| | | |
| | | public ControlCommand(String msgId, long timestamp, String userId, String deviceId, |
| | | String command, ControlParameters parameters) { |
| | | this.msgId = msgId; |
| | | this.timestamp = timestamp; |
| | | this.userId = userId; |
| | | this.deviceId = deviceId; |
| | | this.command = command; |
| | | this.parameters = parameters; |
| | | } |
| | | |
| | | public String getMsgId() { |
| | | return msgId; |
| | | } |
| | | |
| | | public void setMsgId(String msgId) { |
| | | this.msgId = msgId; |
| | | } |
| | | |
| | | public long getTimestamp() { |
| | | return timestamp; |
| | | } |
| | | |
| | | public void setTimestamp(long timestamp) { |
| | | this.timestamp = timestamp; |
| | | } |
| | | |
| | | public String getUserId() { |
| | | return userId; |
| | | } |
| | | |
| | | public void setUserId(String userId) { |
| | | this.userId = userId; |
| | | } |
| | | |
| | | public String getDeviceId() { |
| | | return deviceId; |
| | | } |
| | | |
| | | public void setDeviceId(String deviceId) { |
| | | this.deviceId = deviceId; |
| | | } |
| | | |
| | | public String getCommand() { |
| | | return command; |
| | | } |
| | | |
| | | public void setCommand(String command) { |
| | | this.command = command; |
| | | } |
| | | |
| | | public ControlParameters getParameters() { |
| | | return parameters; |
| | | } |
| | | |
| | | public void setParameters(ControlParameters parameters) { |
| | | this.parameters = parameters; |
| | | } |
| | | |
| | | /** |
| | | * æ§å¶åæ°å
é¨ç±» |
| | | */ |
| | | |
| | | public static class ControlParameters { |
| | | private Double value1; |
| | | private String value2; |
| | | private Integer value3; |
| | | |
| | | public ControlParameters() { |
| | | } |
| | | |
| | | public ControlParameters(Double value1, String value2, Integer value3) { |
| | | this.value1 = value1; |
| | | this.value2 = value2; |
| | | this.value3 = value3; |
| | | } |
| | | |
| | | public Double getValue1() { |
| | | return value1; |
| | | } |
| | | |
| | | public void setValue1(Double value1) { |
| | | this.value1 = value1; |
| | | } |
| | | |
| | | public String getValue2() { |
| | | return value2; |
| | | } |
| | | |
| | | public void setValue2(String value2) { |
| | | this.value2 = value2; |
| | | } |
| | | |
| | | public Integer getValue3() { |
| | | return value3; |
| | | } |
| | | |
| | | public void setValue3(Integer value3) { |
| | | this.value3 = value3; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | public class Server { |
| | | static String host="tcp://39.99.43.227:1883"; |
| | | static String clientId="1231@qq.com"; |
| | | static String host="tcp://39.99.43.227:1883"; |
| | | static String clientId="1231@qq.com"; |
| | | |
| | | /** |
| | | * è·åå½åç³»ç»æ¶é´ |
| | | * @return æ ¼å¼åçæ¶é´åç¬¦ä¸²ï¼æ ¼å¼ä¸º "yyyy-MM-dd HH:mm:ss" |
| | | */ |
| | | public static String getCurrentSystemTime() { |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | return now.format(formatter); |
| | | } |
| | | /** |
| | | * è·åå½åç³»ç»æ¶é´ |
| | | * @return æ ¼å¼åçæ¶é´åç¬¦ä¸²ï¼æ ¼å¼ä¸º "yyyy-MM-dd HH:mm:ss" |
| | | */ |
| | | public static String getCurrentSystemTime() { |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | return now.format(formatter); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åç³»ç»æ¶é´ï¼èªå®ä¹æ ¼å¼ï¼ |
| | | * @param pattern æ¶é´æ ¼å¼æ¨¡å¼ï¼ä¾å¦ "yyyy-MM-dd HH:mm:ss"ã"yyyy/MM/dd HH:mm:ss" ç |
| | | * @return æ ¼å¼åçæ¶é´å符串 |
| | | */ |
| | | public static String getCurrentSystemTime(String pattern) { |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); |
| | | return now.format(formatter); |
| | | } |
| | | /** |
| | | * è·åå½åç³»ç»æ¶é´ï¼èªå®ä¹æ ¼å¼ï¼ |
| | | * @param pattern æ¶é´æ ¼å¼æ¨¡å¼ï¼ä¾å¦ "yyyy-MM-dd HH:mm:ss"ã"yyyy/MM/dd HH:mm:ss" ç |
| | | * @return æ ¼å¼åçæ¶é´å符串 |
| | | */ |
| | | public static String getCurrentSystemTime(String pattern) { |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); |
| | | return now.format(formatter); |
| | | } |
| | | |
| | | |
| | | |
| | | private static void testCode() { |
| | | String mes_id="hxzkcontrol_20151104";//æ¶æ¯ID |
| | | String userId=Usrdell.getUserEmail();//ç¨æ·ID |
| | | String deviceID=Setsys.getMowerIdValue();//设å¤ID |
| | | String protiesFilePath="./dikuai.properties";//å°åä¿¡æ¯é
ç½®æä»¶ |
| | | String json = PropertiesFileUploader.movePathSend(mes_id,userId, deviceID, protiesFilePath);//çæç»è®¾å¤ä¸åçJSON |
| | | sendMQTT(json, host, clientId,deviceID); |
| | | } |
| | | /**åéå²èè·¯å¾*/ |
| | | public static void sendMowingPath() { |
| | | String mes_id="hxzkcontrol_20151104";//æ¶æ¯ID |
| | | String userId=Usrdell.getUserEmail();//ç¨æ·ID |
| | | String deviceID=Setsys.getMowerIdValue();//设å¤ID |
| | | String protiesFilePath="./dikuai.properties";//å°åä¿¡æ¯é
ç½®æä»¶ |
| | | String json = PropertiesFileUploader.movePathSend(mes_id,userId, deviceID, protiesFilePath);//çæç»è®¾å¤ä¸åçJSON |
| | | sendMQTT(json, host, clientId,deviceID); |
| | | } |
| | | |
| | | private static void sendMQTT(String messageJson, String host, String clientId,String deviceID) { |
| | | try { |
| | | String topic="app/p/mower/"+deviceID+"/path"; |
| | | MqttConnectOptions options = new MqttConnectOptions(); |
| | | options.setCleanSession(true); |
| | | MqttClient client = new MqttClient(host, clientId); |
| | | client.connect(options); |
| | | // æ·»å å
³éé©åï¼ç¨åºéåºæ¶å
³éè¿æ¥ |
| | | Runtime.getRuntime().addShutdownHook(new Thread(() -> { |
| | | try { |
| | | if (client.isConnected()) { |
| | | client.disconnect(); |
| | | client.close(); |
| | | } |
| | | } catch (Exception e) { |
| | | } |
| | | })); |
| | | MqttMessage message = new MqttMessage(); |
| | | message.setPayload(messageJson.getBytes("UTF-8")); |
| | | client.publish(topic, message); |
| | | } catch (MqttException e) { |
| | | throw new RuntimeException(e); |
| | | } catch (UnsupportedEncodingException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | private static void sendMQTT(String messageJson, String host, String clientId,String deviceID) { |
| | | try { |
| | | String topic="app/p/mower/"+deviceID+"/path"; |
| | | MqttConnectOptions options = new MqttConnectOptions(); |
| | | options.setCleanSession(true); |
| | | MqttClient client = new MqttClient(host, clientId); |
| | | client.connect(options); |
| | | // æ·»å å
³éé©åï¼ç¨åºéåºæ¶å
³éè¿æ¥ |
| | | Runtime.getRuntime().addShutdownHook(new Thread(() -> { |
| | | try { |
| | | if (client.isConnected()) { |
| | | client.disconnect(); |
| | | client.close(); |
| | | } |
| | | } catch (Exception e) { |
| | | } |
| | | })); |
| | | MqttMessage message = new MqttMessage(); |
| | | message.setPayload(messageJson.getBytes("UTF-8")); |
| | | client.publish(topic, message); |
| | | } catch (MqttException e) { |
| | | throw new RuntimeException(e); |
| | | } catch (UnsupportedEncodingException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | import java.awt.*; |
| | | import java.awt.event.*; |
| | | import java.awt.geom.Point2D; |
| | | |
| | | import chuankou.dellmessage; |
| | | import chuankou.sendmessage; |
| | | import chuankou.DataListener; |
| | | import chuankou.SerialPortService; |
| | | import dikuai.Dikuai; |
| | | import dikuai.Dikuaiguanli; |
| | |
| | | import java.util.Locale; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | // import java.util.function.Consumer; |
| | | import chuankou.DataListener; |
| | | import java.awt.geom.Point2D; |
| | | |
| | | import publicway.Gpstoxuzuobiao; |
| | | import sendMQTT.ControlCommandSender; |
| | | import sendMQTT.Server; |
| | | import user.Usrdell; |
| | | import dikuai.Dikuaiguanli; |
| | | import publicway.Fanhuibutton; |
| | | import publicway.Gpstoxuzuobiao; |
| | | |
| | | /** |
| | | * é¦é¡µçé¢ - éé
6.5寸ç«å±ï¼ä½¿ç¨ç¬ç«çMapRendererè¿è¡ç»å¶ |
| | |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥è·¯å¾IDæ¯å¦å¹é
|
| | | if (!checkPathIdMatch()) { |
| | | startButtonShowingPause = true; |
| | | statusLabel.setText("å¾
æº"); |
| | | updateStartButtonAppearance(); |
| | | return; |
| | | } |
| | | |
| | | // åéå¼å§æä»¤ |
| | | sendControlCommand("start"); |
| | | |
| | | statusLabel.setText("ä½ä¸ä¸"); |
| | | if (stopButtonActive) { |
| | | stopButtonActive = false; |
| | |
| | | return; |
| | | } |
| | | } else { |
| | | // åéæåæä»¤ |
| | | sendControlCommand("pause"); |
| | | statusLabel.setText("æåä¸"); |
| | | pauseMowingSession(); |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥è·¯å¾IDæ¯å¦å¹é
|
| | | * @return 妿å¹é
è¿åtrueï¼å¦åè¿åfalse |
| | | */ |
| | | private boolean checkPathIdMatch() { |
| | | Device device = Device.getGecaoji(); |
| | | if (device == null) { |
| | | showCustomMessageDialog("æ æ³è·åå²èæºä¿¡æ¯ï¼è¯·æ£æ¥è®¾å¤è¿æ¥", "æç¤º"); |
| | | return false; |
| | | } |
| | | |
| | | String savedPathId = device.getPath_id_saved(); |
| | | String currentLandNumber = Dikuaiguanli.getCurrentWorkLandNumber(); |
| | | |
| | | if (currentLandNumber == null) { |
| | | showCustomMessageDialog("请å
éæ©ä½ä¸å°å", "æç¤º"); |
| | | return false; |
| | | } |
| | | |
| | | // å¦æè·¯å¾IDä¸å¹é
ï¼æ³¨æå¤çnullå-1çæ
åµï¼ |
| | | boolean isMatch = savedPathId != null && savedPathId.equals(currentLandNumber); |
| | | |
| | | if (!isMatch) { |
| | | showPathMismatchDialog(currentLandNumber); |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * æ¾ç¤ºè·¯å¾ä¸å¹é
å¯¹è¯æ¡ |
| | | */ |
| | | private void showPathMismatchDialog(String landNumber) { |
| | | Window parentWindow = SwingUtilities.getWindowAncestor(this); |
| | | JDialog dialog = new JDialog(parentWindow, "è·¯å¾ä¸å¹é
", Dialog.ModalityType.APPLICATION_MODAL); |
| | | dialog.setLayout(new BorderLayout(20, 20)); |
| | | dialog.setResizable(false); |
| | | |
| | | JPanel contentPanel = new JPanel(new BorderLayout(0, 15)); |
| | | contentPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20)); |
| | | contentPanel.setBackground(Color.WHITE); |
| | | |
| | | JLabel messageLabel = new JLabel("<html><div style='text-align: center;'>å½åå²èæºè·¯å¾ä¸éä¸å°åä¸ä¸è´<br>æ¯å¦ç«å³åéå°å " + landNumber + " çè·¯å¾ä¿¡æ¯ï¼</div></html>"); |
| | | messageLabel.setFont(new Font("微软é
é»", Font.PLAIN, 14)); |
| | | messageLabel.setHorizontalAlignment(SwingConstants.CENTER); |
| | | contentPanel.add(messageLabel, BorderLayout.CENTER); |
| | | |
| | | JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0)); |
| | | buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); |
| | | buttonPanel.setOpaque(false); |
| | | |
| | | JButton sendButton = buttonset.createStyledButton("ç«å³åé", THEME_COLOR); |
| | | JButton cancelButton = buttonset.createStyledButton("åæ¶", new Color(150, 150, 150)); |
| | | |
| | | sendButton.addActionListener(e -> { |
| | | dialog.dispose(); |
| | | sendMowingPathAndCheck(landNumber); |
| | | }); |
| | | |
| | | cancelButton.addActionListener(e -> dialog.dispose()); |
| | | |
| | | buttonPanel.add(sendButton); |
| | | buttonPanel.add(cancelButton); |
| | | |
| | | contentPanel.add(buttonPanel, BorderLayout.SOUTH); |
| | | dialog.add(contentPanel, BorderLayout.CENTER); |
| | | |
| | | dialog.pack(); |
| | | dialog.setLocationRelativeTo(this); |
| | | dialog.setVisible(true); |
| | | } |
| | | |
| | | /** |
| | | * åéå²èè·¯å¾å¹¶æ£æ¥ç»æ |
| | | */ |
| | | private void sendMowingPathAndCheck(String expectedLandNumber) { |
| | | // æ¾ç¤ºåéä¸æç¤º |
| | | JDialog progressDialog = new JDialog(SwingUtilities.getWindowAncestor(this), "åéä¸", Dialog.ModalityType.MODELESS); |
| | | progressDialog.setLayout(new BorderLayout()); |
| | | JLabel label = new JLabel("æ£å¨åéè·¯å¾ä¿¡æ¯...", SwingConstants.CENTER); |
| | | label.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 40)); |
| | | progressDialog.add(label); |
| | | progressDialog.pack(); |
| | | progressDialog.setLocationRelativeTo(this); |
| | | progressDialog.setVisible(true); |
| | | |
| | | // 弿¥åé |
| | | new Thread(() -> { |
| | | try { |
| | | Server.sendMowingPath(); |
| | | |
| | | // è½®è¯¢æ£æ¥è·¯å¾IDæ¯å¦æ´æ° |
| | | int maxRetries = 10; // æå¤çå¾
10ç§ |
| | | boolean success = false; |
| | | |
| | | for (int i = 0; i < maxRetries; i++) { |
| | | Thread.sleep(1000); |
| | | Device device = Device.getGecaoji(); |
| | | if (device != null) { |
| | | // å·æ°è®¾å¤æ°æ® |
| | | device.initFromProperties(); |
| | | String currentPathId = device.getPath_id_saved(); |
| | | if (expectedLandNumber.equals(currentPathId)) { |
| | | success = true; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | final boolean finalSuccess = success; |
| | | SwingUtilities.invokeLater(() -> { |
| | | progressDialog.dispose(); |
| | | if (finalSuccess) { |
| | | showCustomMessageDialog("è·¯å¾åéæåï¼", "æç¤º"); |
| | | } else { |
| | | // å³ä½¿è¶
æ¶ä¹æç¤ºåé宿ï¼è®©ç¨æ·å次å°è¯å¼å§ |
| | | showCustomMessageDialog("è·¯å¾åéæä»¤å·²ååºï¼è¯·ç¨åéè¯å¼å§ä½ä¸", "æç¤º"); |
| | | } |
| | | }); |
| | | |
| | | } catch (Exception e) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | progressDialog.dispose(); |
| | | showCustomMessageDialog("åé失败: " + e.getMessage(), "é误"); |
| | | }); |
| | | } |
| | | }).start(); |
| | | } |
| | | |
| | | /** |
| | | * å鿧嶿令 |
| | | * @param command start/stop/pause/resume |
| | | */ |
| | | private void sendControlCommand(String command) { |
| | | new Thread(() -> { |
| | | try { |
| | | String userId = Usrdell.getUserEmail(); |
| | | String deviceId = Setsys.getMowerIdValue(); |
| | | String msgId = "hxzkcontrol_" + System.currentTimeMillis(); |
| | | |
| | | if (userId == null || deviceId == null) { |
| | | System.err.println("æ æ³åéæä»¤ï¼ç¨æ·IDæè®¾å¤ID为空"); |
| | | return; |
| | | } |
| | | |
| | | // ç¹æ®å¤çï¼å¦ææ¯resumeæä»¤ï¼å³ä»æåç¶æåæ¬¡ç¹å»å¼å§ï¼ |
| | | String finalCommand = command; |
| | | if ("start".equals(command) && "æåä¸".equals(statusLabel.getText())) { |
| | | finalCommand = "resume"; |
| | | } |
| | | |
| | | ControlCommandSender sender = ControlCommandSender.createDefault(); |
| | | sender.sendControlCommand(msgId, userId, deviceId, finalCommand, 0.0, "", 0); |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | SwingUtilities.invokeLater(() -> |
| | | showCustomMessageDialog("æä»¤åé失败: " + e.getMessage(), "é误")); |
| | | } |
| | | }).start(); |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥å²èæºæ¯å¦å¨å½åéä¸çä½ä¸å°åè¾¹çèå´å
|
| | | * @return 妿å²èæºå¨è¾¹çå
è¿åtrueï¼å¦åè¿åfalseå¹¶æ¾ç¤ºæç¤º |
| | | */ |
| | |
| | | stopButtonActive = !stopButtonActive; |
| | | updateStopButtonIcon(); |
| | | if (stopButtonActive) { |
| | | // åé忢æä»¤ |
| | | sendControlCommand("stop"); |
| | | statusLabel.setText("å·²ç»æ"); |
| | | startButtonShowingPause = false; |
| | | stopMowingSession(); |