package publicway; public class OpenDoor { // 常量定义 private static final String HEADER = "DDCC0008F0"; private static final String FUNCTION_CODE_PREFIX = "515AA55AA5"; // 开门类型常量 public static final int TYPE_ISSUE_CARD = 1; public static final int TYPE_ADMIN = 2; // 参数范围常量 private static final int MIN_SLOT_NUMBER = 0; private static final int MAX_SLOT_NUMBER = 255; // 默认间隔时间(毫秒) private static final int DEFAULT_INTERVAL_MS = 250; /** * 开一个柜门 * * @param slotNumber 柜门编号 (0-255) * @param type 开门类型 (1:发卡开门, 2:管理员开门) * @return 生成的指令字符串 * @throws IllegalArgumentException 当参数超出范围时抛出 * @throws RuntimeException 当生成指令过程中发生错误时抛出 */ public static String openOneDoor(int slotNumber, int type) { // 参数校验 validateParameters(slotNumber, type); try { String functionCode = buildFunctionCode(type); String slotHex = formatSlotNumber(slotNumber); String baseContent = HEADER + slotHex + functionCode; return buildFinalCommand(baseContent); } catch (Exception e) { throw new RuntimeException("生成开门指令时发生错误", e); } } /** * 批量打开多个卡槽(从1到N) * * @param totalSlots 卡槽总数N (1-255) * @param intervalMs 发送指令间隔时间(毫秒),默认250ms * @param type 开门类型 (1:发卡开门, 2:管理员开门) * @return 生成的指令字符串数组 * @throws IllegalArgumentException 当参数超出范围时抛出 */ public static String[] openAllSlots(int totalSlots, Integer intervalMs, int type) { // 参数校验 if (totalSlots < 1 || totalSlots > MAX_SLOT_NUMBER) { throw new IllegalArgumentException( String.format("卡槽总数必须在1-%d范围内", MAX_SLOT_NUMBER)); } validateType(type); // 使用默认间隔时间如果未提供 int actualInterval = intervalMs != null ? intervalMs : DEFAULT_INTERVAL_MS; if (actualInterval < 0) { throw new IllegalArgumentException("间隔时间不能为负数"); } String[] commands = new String[totalSlots]; try { for (int i = 0; i < totalSlots; i++) { int slotNumber = i + 1; // 从1开始 String command = openOneDoor(slotNumber, type); commands[i] = command; // 如果不是最后一个指令,则等待指定间隔 if (i < totalSlots - 1 && actualInterval > 0) { try { Thread.sleep(actualInterval); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("开门指令发送被中断", e); } } } System.out.println(String.format("成功生成 %d 个开门指令,间隔 %d 毫秒", totalSlots, actualInterval)); return commands; } catch (Exception e) { throw new RuntimeException("生成批量开门指令时发生错误", e); } } /** * 批量打开多个卡槽(使用默认间隔时间) * * @param totalSlots 卡槽总数N (1-255) * @param type 开门类型 (1:发卡开门, 2:管理员开门) * @return 生成的指令字符串数组 */ public static String[] openAllSlots(int totalSlots, int type) { return openAllSlots(totalSlots, null, type); } /** * 异步批量打开多个卡槽(不阻塞当前线程) * * @param totalSlots 卡槽总数N (1-255) * @param intervalMs 发送指令间隔时间(毫秒) * @param type 开门类型 (1:发卡开门, 2:管理员开门) * @param callback 回调接口,用于接收生成的指令和处理进度 */ public static void openAllSlotsAsync(int totalSlots, Integer intervalMs, int type, OpenDoorCallback callback) { // 参数校验 if (totalSlots < 1 || totalSlots > MAX_SLOT_NUMBER) { if (callback != null) { callback.onError(new IllegalArgumentException( String.format("卡槽总数必须在1-%d范围内", MAX_SLOT_NUMBER))); } return; } if (callback == null) { throw new IllegalArgumentException("回调接口不能为null"); } validateType(type); // 在新线程中执行批量开门 new Thread(() -> { try { int actualInterval = intervalMs != null ? intervalMs : DEFAULT_INTERVAL_MS; String[] commands = new String[totalSlots]; for (int i = 0; i < totalSlots; i++) { int slotNumber = i + 1; String command = openOneDoor(slotNumber, type); commands[i] = command; // 通知进度 callback.onProgress(slotNumber, totalSlots, command); // 等待间隔 if (i < totalSlots - 1 && actualInterval > 0) { Thread.sleep(actualInterval); } } callback.onComplete(commands); } catch (Exception e) { callback.onError(e); } }).start(); } /** * 验证输入参数 */ private static void validateParameters(int slotNumber, int type) { if (slotNumber < MIN_SLOT_NUMBER || slotNumber > MAX_SLOT_NUMBER) { throw new IllegalArgumentException( String.format("柜门编号必须在%d-%d范围内", MIN_SLOT_NUMBER, MAX_SLOT_NUMBER)); } validateType(type); } /** * 验证开门类型 */ private static void validateType(int type) { if (type != TYPE_ISSUE_CARD && type != TYPE_ADMIN) { throw new IllegalArgumentException("开门类型参数无效,应为1或2"); } } /** * 构建功能码 */ private static String buildFunctionCode(int type) { return FUNCTION_CODE_PREFIX + String.format("%02X", type); } /** * 格式化柜门编号为16进制 */ private static String formatSlotNumber(int slotNumber) { return String.format("%02X", slotNumber); } /** * 构建最终指令(添加CRC校验) */ private static String buildFinalCommand(String baseContent) { byte[] cmdBytes = HexUtil.hexStringToBytes(baseContent); String crc = HexUtil.calculate(cmdBytes); String finalContent = baseContent + crc; System.out.println("生成的开门指令: " + finalContent); return finalContent; } /** * 开门回调接口 */ public interface OpenDoorCallback { /** * 进度回调 * @param currentSlot 当前处理的卡槽编号 * @param totalSlots 总卡槽数量 * @param command 生成的指令 */ void onProgress(int currentSlot, int totalSlots, String command); /** * 完成回调 * @param commands 所有生成的指令数组 */ void onComplete(String[] commands); /** * 错误回调 * @param error 异常信息 */ void onError(Exception error); } }