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