package yaokong; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; public class Control01 { /** * 构建路径坐标指令(指令类型0x01)的HEX格式字符串 * * @param coordinates 坐标字符串,格式:"X1,Y1;X2,Y2;X3,Y3"(分号分隔,逗号分隔XY) * @return 路径坐标指令的HEX格式字符串 */ public static String buildPathCommandHex(String coordinates) { List points = parseCoordinates(coordinates); byte[] commandBytes = buildPathCommandBytes(points); return bytesToHex(commandBytes); } /** * 构建路径坐标指令的字节数组 */ public static byte[] buildPathCommandBytes(List points) { if (points == null || points.isEmpty() || points.size() > 255) { throw new IllegalArgumentException("路径点数量必须在1-255之间"); } int pointCount = points.size(); int dataLength = 1 + pointCount * 16; // 1字节点数 + 每个点16字节(两个double) ByteBuffer buffer = ByteBuffer.allocate(2 + 1 + 2 + 2 + dataLength + 2 + 1); buffer.order(ByteOrder.LITTLE_ENDIAN); // 帧头 buffer.put(BluetoothProtocol.FRAME_HEADER); // 指令类型 buffer.put((byte) 0x01); // 数据长度 buffer.putShort((short) dataLength); // 序列号 buffer.putShort((short) BluetoothProtocol.getNextSequence()); // 路径点数量 buffer.put((byte) pointCount); // 路径点数据 for (Point point : points) { buffer.putDouble(point.x); buffer.putDouble(point.y); } // 计算CRC16 byte[] dataForCRC = new byte[1 + 2 + 2 + dataLength]; System.arraycopy(buffer.array(), 2, dataForCRC, 0, dataForCRC.length); int crc = CRC16.calculateCRC16(dataForCRC, 0, dataForCRC.length); buffer.putShort((short) crc); // 帧尾 buffer.put((byte) 0x0D); return buffer.array(); } /** * 解析坐标字符串 */ private static List parseCoordinates(String coordinates) { if (coordinates == null || coordinates.trim().isEmpty()) { throw new IllegalArgumentException("坐标字符串不能为空"); } List points = new ArrayList<>(); String[] pointStrings = coordinates.split(";"); for (String pointStr : pointStrings) { String[] xy = pointStr.split(","); if (xy.length != 2) { throw new IllegalArgumentException("坐标格式错误,应为X,Y格式"); } try { double x = Double.parseDouble(xy[0].trim()); double y = Double.parseDouble(xy[1].trim()); points.add(new Point(x, y)); } catch (NumberFormatException e) { throw new IllegalArgumentException("坐标必须是数字: " + pointStr); } } return points; } public static class Point { public double x; public double y; public Point(double x, double y) { this.x = x; this.y = y; } } 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(); } }