张世豪
昨天 ef78717c5b956a26b360de44f774fc2b804296c2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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);
    }
}