package yaokong; import java.nio.ByteBuffer; import java.nio.ByteOrder; import chuankou.SerialPortService; import chuankou.sendmessage; public class Control04 { /** * 构建开始/停止割草指令(指令类型0x04)的HEX格式字符串 * * @param action 控制动作:0-停止, 1-开始, 2-暂停, 3-急停 * @param emergencyLevel 紧急等级:0-正常, 1-警告, 2-紧急 * @return 控制指令的HEX格式字符串(空格分隔) */ public static String buildControlCommandHex(int action, int emergencyLevel) { // 验证参数范围 if (action < 0 || action > 3) { throw new IllegalArgumentException("控制动作参数无效,必须是0-3之间的整数"); } if (emergencyLevel < 0 || emergencyLevel > 2) { throw new IllegalArgumentException("紧急等级参数无效,必须是0-2之间的整数"); } // 创建缓冲区:帧头2 + 指令类型1 + 数据长度2 + 序列号2 + 数据内容2 + CRC16 2 + 帧尾1 = 12字节 ByteBuffer buffer = ByteBuffer.allocate(12); buffer.order(ByteOrder.LITTLE_ENDIAN); // 帧头 (0xAA, 0x55) buffer.put(BluetoothProtocol.FRAME_HEADER); // 指令类型 (0x04) buffer.put(BluetoothProtocol.CMD_CONTROL); // 数据长度 (固定为2) buffer.putShort((short) 2); // 序列号 (使用协议中的递增序列号) buffer.putShort((short) BluetoothProtocol.getNextSequence()); // 数据内容 buffer.put((byte) action); // 控制动作 buffer.put((byte) emergencyLevel); // 紧急等级 // 计算CRC16校验 byte[] dataForCRC = new byte[7]; // 指令类型1 + 数据长度2 + 序列号2 + 控制动作1 + 紧急等级1 System.arraycopy(buffer.array(), 2, dataForCRC, 0, dataForCRC.length); int crc = CRC16.calculateCRC16(dataForCRC, 0, dataForCRC.length); buffer.putShort((short) crc); // 帧尾 (0x0D) buffer.put(BluetoothProtocol.FRAME_FOOTER); // 转换为HEX字符串(空格分隔) byte[] commandBytes = buffer.array(); return bytesToHex(commandBytes); } /** * 构建开始/停止割草指令(指令类型0x04)的字节数组 * * @param action 控制动作:0-停止, 1-开始, 2-暂停, 3-急停 * @param emergencyLevel 紧急等级:0-正常, 1-警告, 2-紧急 * @return 控制指令的字节数组 */ public static byte[] buildControlCommandBytes(int action, int emergencyLevel) { // 验证参数范围 if (action < 0 || action > 3) { throw new IllegalArgumentException("控制动作参数无效,必须是0-3之间的整数"); } if (emergencyLevel < 0 || emergencyLevel > 2) { throw new IllegalArgumentException("紧急等级参数无效,必须是0-2之间的整数"); } // 创建缓冲区:帧头2 + 指令类型1 + 数据长度2 + 序列号2 + 数据内容2 + CRC16 2 + 帧尾1 = 12字节 ByteBuffer buffer = ByteBuffer.allocate(12); buffer.order(ByteOrder.LITTLE_ENDIAN); // 帧头 (0xAA, 0x55) buffer.put(BluetoothProtocol.FRAME_HEADER); // 指令类型 (0x04) buffer.put(BluetoothProtocol.CMD_CONTROL); // 数据长度 (固定为2) buffer.putShort((short) 2); // 序列号 (使用协议中的递增序列号) buffer.putShort((short) BluetoothProtocol.getNextSequence()); // 数据内容 buffer.put((byte) action); // 控制动作 buffer.put((byte) emergencyLevel); // 紧急等级 // 计算CRC16校验 byte[] dataForCRC = new byte[7]; // 指令类型1 + 数据长度2 + 序列号2 + 控制动作1 + 紧急等级1 System.arraycopy(buffer.array(), 2, dataForCRC, 0, dataForCRC.length); int crc = CRC16.calculateCRC16(dataForCRC, 0, dataForCRC.length); buffer.putShort((short) crc); // 帧尾 (0x0D) buffer.put(BluetoothProtocol.FRAME_FOOTER); return buffer.array(); } /** * 当系统调试串口处于打开状态时发送开始割草指令。 */ public static boolean sendStartCommandIfDebugSerialOpen() { return sendControlCommandIfDebugSerialOpen(1, 0); } /** * 当系统调试串口处于打开状态时发送暂停割草指令。 */ public static boolean sendPauseCommandIfDebugSerialOpen() { return sendControlCommandIfDebugSerialOpen(2, 0); } /** * 当系统调试串口处于打开状态时发送停止割草指令。 */ public static boolean sendStopCommandIfDebugSerialOpen() { return sendControlCommandIfDebugSerialOpen(0, 0); } private static boolean sendControlCommandIfDebugSerialOpen(int action, int emergencyLevel) { SerialPortService service = sendmessage.getActiveService(); if (service == null || !service.isOpen()) { return false; } byte[] payload = buildControlCommandBytes(action, emergencyLevel); return sendmessage.sendViaActive(payload); } /** * 构建常用控制指令的快捷方法 */ // 开始割草(正常) public static String startMowing() { return buildControlCommandHex(1, 0); } // 停止割草(正常) public static String stopMowing() { return buildControlCommandHex(0, 0); } // 暂停割草(正常) public static String pauseMowing() { return buildControlCommandHex(2, 0); } // 紧急停止(紧急) public static String emergencyStop() { return buildControlCommandHex(3, 2); } /** * 字节数组转换为HEX字符串 */ 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(); } /** * 解析控制指令的HEX字符串(反向解析,用于调试) */ public static String parseControlCommandHex(String hexString) { String[] hexParts = hexString.trim().split("\\s+"); if (hexParts.length != 12) { return "无效的HEX格式:需要12个字节"; } try { // 解析帧头 if (!hexParts[0].equals("AA") || !hexParts[1].equals("55")) { return "错误的帧头"; } // 解析指令类型 if (!hexParts[2].equals("04")) { return "非控制指令(0x04)"; } // 解析数据长度 int dataLength = Integer.parseInt(hexParts[4] + hexParts[3], 16); // 小端序 if (dataLength != 2) { return "数据长度错误:" + dataLength; } // 解析序列号 int sequence = Integer.parseInt(hexParts[6] + hexParts[5], 16); // 解析控制动作 int action = Integer.parseInt(hexParts[7], 16); String actionStr; switch (action) { case 0: actionStr = "停止"; break; case 1: actionStr = "开始"; break; case 2: actionStr = "暂停"; break; case 3: actionStr = "急停"; break; default: actionStr = "未知(" + action + ")"; break; } // 解析紧急等级 int emergencyLevel = Integer.parseInt(hexParts[8], 16); String levelStr; switch (emergencyLevel) { case 0: levelStr = "正常"; break; case 1: levelStr = "警告"; break; case 2: levelStr = "紧急"; break; default: levelStr = "未知(" + emergencyLevel + ")"; break; } // 解析CRC int receivedCRC = Integer.parseInt(hexParts[10] + hexParts[9], 16); // 解析帧尾 if (!hexParts[11].equals("0D")) { return "错误的帧尾"; } return String.format("控制指令解析:动作=%s(%d), 紧急等级=%s(%d), 序列号=%d", actionStr, action, levelStr, emergencyLevel, sequence); } catch (Exception e) { return "解析错误:" + e.getMessage(); } } }