| | |
| | | |
| | | 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(); |