1
zhanghua
2024-09-26 c775c6953d9759e70f08acbfa8f6d7490aaae3d1
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
package com.netsdk.demo.customize.JordanPSD;
 
import com.netsdk.demo.customize.JordanPSD.module.ConfigModule;
import com.netsdk.demo.customize.JordanPSD.module.DeviceControlModule;
import com.netsdk.demo.customize.JordanPSD.module.LogonModule;
import com.netsdk.demo.customize.JordanPSD.module.SdkUtilModule;
import com.netsdk.demo.util.CaseMenu;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.ToolKits;
import com.netsdk.lib.Utils;
import com.netsdk.lib.enumeration.*;
import com.netsdk.lib.structure.*;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
 
import java.nio.charset.Charset;
import java.util.Scanner;
 
import static com.netsdk.lib.enumeration.NET_EM_CFG_OPERATE_TYPE.NET_EM_CFG_ENCODE_VIDEO;
 
/**
 * @author 47040
 * @since Created at 2021/5/25 10:52
 */
public class DemoMPT {
 
    // 设备信息
    NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
 
    // 登录句柄
    NetSDKLib.LLong m_hLoginHandle = new NetSDKLib.LLong(0);
 
    // 跨平台编码
    private final Charset encode = Charset.forName(Utils.getPlatformEncode());
 
    // 当前通道
    int channel = 0;
 
    public void setCurrChannel() {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入通道号");
        channel = sc.nextInt();
        System.out.println("当前通道为:" + channel);
    }
 
    ////////////////////////////////////////////////////////////////////////////////////////
    // 需求点一:平台远程设置设备的参数,包括分辨率,帧率,码率
    ////////////////////////////////////////////////////////////////////////////////////////
 
    /**
     * 获取远程设备编码配置
     * 二代协议
     * Demo 此处以获取主码流配置为例
     */
    public void getVideoEncode() {
        final int cfgCmd = NET_EM_CFG_ENCODE_VIDEO;
 
        NET_ENCODE_VIDEO_INFO stuInfo = new NET_ENCODE_VIDEO_INFO();
        stuInfo.emFormatType = NET_EM_FORMAT_TYPE.EM_FORMAT_MAIN_NORMAL.getValue();     // 主码流
 
        boolean ret = ConfigModule.GetConfig(m_hLoginHandle, cfgCmd, channel, stuInfo, 5000);
        if (!ret) {
            System.err.println("获取远程设备编码配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        // 打印看一下
 
        StringBuilder info = new StringBuilder()
                .append(String.format("SN:%s, Chn:%03d, 主码流配置:\n", new String(m_stDeviceInfo.sSerialNumber, encode).trim(), channel));
        info.append(String.format(
                " bEnable:%d, \n" +
                        " emFormatType:%d, emCompression:%d\n" +
                        " nHeight:%d, nWidth:%d \n" +
                        " emBitRateControl:%d, nBitRate:%d\n" +
                        " nFrameRate:%f, nIFrameInterval:%d\n" +
                        " emImageQuality:%d",
                stuInfo.bVideoEnable,
                stuInfo.emFormatType,
                stuInfo.emCompression,
                stuInfo.nHeight,
                stuInfo.nWidth,
                stuInfo.emBitRateControl,
                stuInfo.nBitRate,
                stuInfo.nFrameRate,
                stuInfo.nIFrameInterval,
                stuInfo.emImageQuality));
        System.out.println(info.toString());
    }
 
    /**
     * 下发远程设备编码配置
     * 二代协议
     * Demo 此处以获取主码流配置为例:
     * 分辨率:1920x1080 码率:2048 帧率:25.0 I帧间隔:50
     * <p>
     * 注意:
     * 1) I帧以 2s 一个为宜 所以 I帧间隔我们建议同步设置为 帧率 x2
     * 2) 修改配置的原则是: 获取->修改->下发 这样可以避免关键字段缺省
     * 3) 并不是任何配置都可以下发成功, 能力集请参考三代协议的接口
     */
    public void setVideoEncode() {
 
        ////////////////////////////// 获取配置 //////////////////////////////
        /////////////////////////////////////////////////////////////////////
 
        final int cfgCmd = NET_EM_CFG_ENCODE_VIDEO;
 
        NET_ENCODE_VIDEO_INFO stuInfo = new NET_ENCODE_VIDEO_INFO();
        stuInfo.emFormatType = NET_EM_FORMAT_TYPE.EM_FORMAT_MAIN_NORMAL.getValue();     // 主码流
 
        boolean ret = ConfigModule.GetConfig(m_hLoginHandle, cfgCmd, channel, stuInfo, 5000);
        if (!ret) {
            System.err.println("获取远程设备编码配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        ////////////////////////////// 修改配置 //////////////////////////////
        /////////////////////////////////////////////////////////////////////
 
        // 分辨率
        stuInfo.nWidth = 1920;
        stuInfo.nHeight = 1080;
        // 码流
        stuInfo.nBitRate = 2048;
        // 帧率和I帧间隔
        stuInfo.nFrameRate = 25.0f;
        stuInfo.nIFrameInterval = 50;
 
        ////////////////////////////// 下发配置 //////////////////////////////
        /////////////////////////////////////////////////////////////////////
 
        ret = ConfigModule.SetConfig(m_hLoginHandle, cfgCmd, channel, stuInfo, 5000);
        if (!ret) {
            System.err.println("下发远程设备编码配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("下发远程设备编码配置成功");
    }
 
 
    /**
     * 获取远程设备编码配置
     * 三代协议
     * 注:
     * 1) 我们建议把主码流配置看成一个整体, 即主码流组统一做相同配置
     * 2) 辅码流在不同设备上能力集差异较大 我们建议只使用辅码流 1, 即只关注辅码流组的第一个配置
     */
    public void getDeviceEncode() {
        final String cfgCmd = EM_NEW_CONFIG.CFG_CMD_ENCODE.getValue();
        NetSDKLib.CFG_ENCODE_INFO encodeInfo = new NetSDKLib.CFG_ENCODE_INFO();
        encodeInfo.nChannelID = channel;
        boolean ret = ToolKits.GetDevConfig(m_hLoginHandle, channel, cfgCmd, encodeInfo);
        if (!ret) {
            System.err.println("获取远程设备编码配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        // 打印下当前的设备参数: 主/辅 码流的分辨率, 帧率和码率
        StringBuilder info = new StringBuilder()
                .append(String.format("SN:%s, Chn:%03d, Encode Config:\n", new String(m_stDeviceInfo.sSerialNumber, encode).trim(), channel));
        // 主码流
        if (encodeInfo.nValidCountMainStream > 0) {
            info.append("Main Stream 主码流:\n")
                    .append("    Resolution 分辨率: ").append(String.format("( %04d x %04d )\n",
                    encodeInfo.stuMainStream[0].stuVideoFormat.nWidth,
                    encodeInfo.stuMainStream[0].stuVideoFormat.nHeight))
                    .append("    BitRate 视频码流(kbps): ").append(encodeInfo.stuMainStream[0].stuVideoFormat.nBitRate).append("\n")
                    .append("    FrameRate 帧率: ").append(encodeInfo.stuMainStream[0].stuVideoFormat.nFrameRate).append("\n")
                    .append("    IFrameInterval I帧间隔: ").append(encodeInfo.stuMainStream[0].stuVideoFormat.nIFrameInterval).append("\n");
        }
 
        // 辅码流
        if (encodeInfo.nValidCountExtraStream > 0) {
            info.append("Sub Stream 辅码流(1):\n")
                    .append("    Resolution 分辨率: ").append(String.format("( %04d x %04d )\n",
                    encodeInfo.stuExtraStream[0].stuVideoFormat.nWidth,
                    encodeInfo.stuExtraStream[0].stuVideoFormat.nHeight))
                    .append("    BitRate 视频码流(kbps): ").append(encodeInfo.stuExtraStream[0].stuVideoFormat.nBitRate).append("\n")
                    .append("    FrameRate 帧率: ").append(encodeInfo.stuExtraStream[0].stuVideoFormat.nFrameRate).append("\n")
                    .append("    IFrameInterval I帧间隔: ").append(encodeInfo.stuExtraStream[0].stuVideoFormat.nIFrameInterval).append("\n");
        }
 
        System.out.println(info.toString());
    }
 
    /**
     * 设置远程设备编码配置
     * 三代协议
     * 注:
     * 1) 我们建议把主码流配置看成一个整体, 即主码流组统一做相同配置
     * 2) 辅码流在不同设备上差异较大 如果对接设备型号来源复杂的话我们建议只使用辅码流 1, 即只关注辅码流组的第一个配置
     * 3) I帧以 2s 一个为宜 所以 I帧间隔我们建议同步设置为 帧率 x2
     * 4) 修改配置的原则是: 获取->修改->下发 这样可以避免关键字段缺省
     * <p>
     * Demo 这里采用以下用例:
     * 主码流 分辨率:1920x1080 码率:2048 帧率:25.0 I帧间隔:50
     * 辅码流(1) 分辨率:704x576 码率:512 帧率:25.0 I帧间隔:50
     * <p>
     * 注:这个数据不是随便填的 设备端会逐一校验 所以简便的办法是照搬网页端的规则
     * 当然 最好的方法是是获取设备的相关能力集 请参考下一个示例
     */
    public void setDeviceEncode() {
 
        ////////////////////////////// 获取配置 ///////////////////////////////
        //////////////////////////////////////////////////////////////////////
 
        String cfgCmd = EM_NEW_CONFIG.CFG_CMD_ENCODE.getValue();
        NetSDKLib.CFG_ENCODE_INFO encodeInfo = new NetSDKLib.CFG_ENCODE_INFO();
        encodeInfo.nChannelID = channel;
        boolean ret = ToolKits.GetDevConfig(m_hLoginHandle, channel, cfgCmd, encodeInfo);
        if (!ret) {
            System.err.println("获取远程设备编码配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
 
        ////////////////////////////// 修改配置 ///////////////////////////////
        //////////////////////////////////////////////////////////////////////
 
        // 主码流组统一做相同配置
        for (int i = 0; i < encodeInfo.nValidCountMainStream; i++) {
            // 分辨率:1920x1080
            encodeInfo.stuMainStream[i].stuVideoFormat.nWidth = 1920;
            encodeInfo.stuMainStream[i].stuVideoFormat.nHeight = 1080;
            // 码流:1280
            encodeInfo.stuMainStream[i].stuVideoFormat.nBitRate = 2048;
            // 帧率:25.0
            encodeInfo.stuMainStream[i].stuVideoFormat.nFrameRate = 25f;
            // I帧间隔 帧率x2
            encodeInfo.stuMainStream[i].stuVideoFormat.nIFrameInterval = 50;
        }
 
        // 辅码流只使用 辅码流1 也只修改它的配置 其他配置保持不变
        if (encodeInfo.nValidCountExtraStream > 0) {
            // 分辨率:1920x1080
            encodeInfo.stuExtraStream[0].stuVideoFormat.nWidth = 704;
            encodeInfo.stuExtraStream[0].stuVideoFormat.nHeight = 576;
            // 码流:512
            encodeInfo.stuExtraStream[0].stuVideoFormat.nBitRate = 512;
            // 帧率:25.0
            encodeInfo.stuExtraStream[0].stuVideoFormat.nFrameRate = 25.0f;
            // I帧间隔 帧率x2
            encodeInfo.stuExtraStream[0].stuVideoFormat.nIFrameInterval = 50;
        }
 
        ////////////////////////////// 下发配置 ///////////////////////////////
        //////////////////////////////////////////////////////////////////////
 
        ret = ToolKits.SetDevConfig(m_hLoginHandle, channel, cfgCmd, encodeInfo);
        if (!ret) {
            System.err.println("下发远程设备编码配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("下发远程设备编码配置成功");
    }
 
    /**
     * 依据当前配置 获取本编码格式下对应的能力集
     * 三代协议
     * Demo 这里以 主码流 为例
     */
    public void getEncodeCapWithConfig() {
 
        //////////////////////// 获取配置 /////////////////////////
        //////////////////////////////////////////////////////////
        String cfgCmd = EM_NEW_CONFIG.CFG_CMD_ENCODE.getValue();
        NetSDKLib.CFG_ENCODE_INFO encodeInfo = new NetSDKLib.CFG_ENCODE_INFO();
        encodeInfo.nChannelID = channel;
        boolean ret = ToolKits.GetDevConfig(m_hLoginHandle, channel, cfgCmd, encodeInfo);
        if (!ret) {
            System.err.println("获取远程设备编码配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        ////////////////// 获取能力集 指定本编码格式///////////////////
        ////////////////////////////////////////////////////////////
 
        int capCmd = GetDevCaps_Type.NET_ENCODE_CFG_CAPS.getType();
        NET_IN_ENCODE_CFG_CAPS stuIn = new NET_IN_ENCODE_CFG_CAPS();
        stuIn.nChannelId = channel;
        stuIn.nStreamType = 0;              // 主码流
        byte[] encodeJson = ConfigModule.PackageData2JsonByte(cfgCmd, 2 * 1024 * 1024, encodeInfo);
        if (encodeJson == null) {
            System.err.println("打包编码配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        Pointer pEncodeJson = new Memory(encodeJson.length);
        pEncodeJson.clear(encodeJson.length);
        pEncodeJson.write(0, encodeJson, 0, encodeJson.length);
        stuIn.pchEncodeJson = pEncodeJson;
 
        NET_OUT_ENCODE_CFG_CAPS stuOut = new NET_OUT_ENCODE_CFG_CAPS();
 
        ret = ConfigModule.GetDeviceCapability(m_hLoginHandle, capCmd, stuIn, stuOut, 5000);
        if (!ret) {
            System.err.println("获取设备编码能力失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        // 打印展示一下 以第一个配置为例
        NET_STREAM_CFG_CAPS mainStreamCaps = stuOut.stuMainFormatCaps[0];
 
        // 指定编码格式后获取能力集时 abIndivResolution = 0
        StringBuilder info = new StringBuilder()
                .append(String.format("SN:%s, Chn:%03d, 主码流能力集:\n", new String(m_stDeviceInfo.sSerialNumber, encode).trim(), channel));
 
        info.append("  当前能力集所属编码: ").append(
                CFG_VIDEO_COMPRESSION.getEnum(encodeInfo.stuMainStream[0].stuVideoFormat.emCompression).getNote()).append("\n");
 
        // 注意: 码流区间并不意味着可以在区间里随便填 必须填 STREAM_RATE_TYPE 内的符合条件的枚举值
        info.append("  码流范围(kbps): ").append(String.format("( %04d ~ %04d )\n",
                mainStreamCaps.nMinBitRateOptions, mainStreamCaps.nMaxBitRateOptions));
 
        // 大部分设备这个字段都是有值的
        if (mainStreamCaps.nFPSMax != 0)
            info.append(" 帧率最大值: ").append(mainStreamCaps.nFPSMax).append("\n");
 
        info.append(" 分辨率支持列表: \n");
        for (int i = 0; i < mainStreamCaps.nResolutionTypeNum; i++) {
            info.append("    分辨率: ").append(String.format("( %04d x %04d )\n",
                    mainStreamCaps.stuResolutionTypes[i].snWidth,
                    mainStreamCaps.stuResolutionTypes[i].snHight));
            if (mainStreamCaps.nFPSMax == 0) {
                info.append("      帧率: ").append(mainStreamCaps.nResolutionFPSMax[i]).append("\n");
            }
        }
        System.out.println(info.toString());
    }
 
    /////////////////////////////////////////////////////////////////////////
    // 需求点二:平台可以远程关闭设备
    /////////////////////////////////////////////////////////////////////////
 
    /**
     * 手动关机
     * <p>
     * 警告: 关机后 sdk 是无法把设备启动起来的
     * <p>
     * 注: 大部分设备对关机命令都有特殊逻辑
     * 比如很多设备需要连续两次关机命令才会真正关机 而且在上电状态下会直接重启 本质和Reboot命令没有区别
     */
    public void deviceShutdown() {
 
        Scanner sc = new Scanner(System.in);
        System.err.println("确定要关闭设备吗(y/n)? 关闭后sdk无法主动启动设备");
        String decision = sc.next().trim().toLowerCase();
        if (!decision.equals("y")) return;
 
        boolean ret = DeviceControlModule.DeviceShutdown(m_hLoginHandle);
        if (!ret) {
            System.err.println("设备关机命令下发失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("设备关机命令下发成功");
    }
 
    /**
     * 手动重启
     */
    public void deviceReboot() {
 
        boolean ret = DeviceControlModule.DeviceReboot(m_hLoginHandle);
        if (!ret) {
            System.err.println("设备重启命令下发失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("设备重启命令下发成功");
    }
 
    /**
     * 远程关机
     */
    public void RemoteShutdown() {
        boolean ret = DeviceControlModule.RemoteShutDown(m_hLoginHandle);
        if (!ret) {
            System.err.println("远程关机失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("远程关机成功");
 
    }
 
    /////////////////////////////////////////////////////////////////////////
    // 需求点二:平台可以远程关闭/开启设备录像
    /////////////////////////////////////////////////////////////////////////
 
    //  Todo 二代协议
 
    /**
     * 获取录像状态
     * 三代协议: "RecordMode"
     * 0-自动录像,1-手动录像,2-关闭录像
     * 需求里的开启即 1-手动录像 关闭即 2-关闭录像
     * 设置为 0 则使用 自动录像的配置规则 见下一个示例
     */
    public void getRecordMode() {
        String szCommand = NetSDKLib.CFG_CMD_RECORDMODE;   // "RecordMode"
        // m_stDeviceInfo.byChanNum为设备通道数
        NetSDKLib.AV_CFG_RecordMode[] recordModes = new NetSDKLib.AV_CFG_RecordMode[m_stDeviceInfo.byChanNum];
        for (int i = 0; i < recordModes.length; ++i) {
            recordModes[i] = new NetSDKLib.AV_CFG_RecordMode();
        }
 
        int retCount = ToolKits.GetDevConfig(m_hLoginHandle, -1, szCommand, recordModes);
        StringBuilder info = new StringBuilder()
                .append(String.format("SN:%s, 录像状态:\n", new String(m_stDeviceInfo.sSerialNumber, encode).trim()));
        for (int i = 0; i < retCount; i++) {
            info.append(" 通道:").append(i).append(" 主码流录像模式:")
                    .append(parseRecodeMode(recordModes[i].nMode)).append("; ")
                    .append(" 辅码流录像模式:").append(parseRecodeMode(recordModes[i].nModeExtra1)).append("\n");
        }
        System.out.println(info.toString());
    }
 
    private String parseRecodeMode(int type) {
        switch (type) {
            case 0:
                return "自动录像";
            case 1:
                return "手动录像";
            case 2:
                return "关闭录像";
            default:
                return "数据错误";
        }
    }
 
 
    /**
     * 设置录像状态 手动 开启/停止 录像
     * 三代协议: "RecordMode"
     * Demo 这里不修改内容 原样下发
     */
    public void setRecordMode() {
 
        //////////////////////// 获取配置 /////////////////////////
        //////////////////////////////////////////////////////////
 
        String szCommand = NetSDKLib.CFG_CMD_RECORDMODE;   // "RecordMode"
        // m_stDeviceInfo.byChanNum为设备通道数
        NetSDKLib.AV_CFG_RecordMode[] recordModes = new NetSDKLib.AV_CFG_RecordMode[m_stDeviceInfo.byChanNum];
        for (int i = 0; i < recordModes.length; ++i) {
            recordModes[i] = new NetSDKLib.AV_CFG_RecordMode();
        }
 
        int retCount = ToolKits.GetDevConfig(m_hLoginHandle, -1, szCommand, recordModes);
        if (retCount == -1) {
            System.err.println("获取录像模式失败: " + ENUMERROR.getErrorMessage());
            return;
        }
 
        //////////////////////// 下发配置 /////////////////////////
        //////////////////////////////////////////////////////////
 
        boolean bRet = ToolKits.SetDevConfig(m_hLoginHandle, -1, szCommand, recordModes);
        if (!bRet) {
            System.err.println("下发录像模式失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("下发录像模式成功");
    }
 
    /**
     * 获取手持设备 IR 开关配置
     */
    public void getInfraredSetConfig() {
        String strCmd = NetSDKLib.CFG_CMD_INFRARED_CONFIG;  // 配置类型枚举
        CFG_INFRARED_INFO config = new CFG_INFRARED_INFO();
 
        boolean bRet = ToolKits.GetDevConfig(m_hLoginHandle, -1, strCmd, config);
        if (!bRet) {
            System.err.println("获取IR开关配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("获取IR开关配置成功");
 
        // 打印出来看一看
        System.out.println(String.format("当前设备 SN:%s IR开关配置:\n" +
                        "    红外功能模式:%s\n" +
                        "    红外亮度(仅模式为开始时有效): %s",
                new String(m_stDeviceInfo.sSerialNumber, encode).trim(),
                EM_INFRARED_FUNC_MODE.getEnum(config.emInfraredMode).getNote(),
                EM_INFRARED_LIGHT_LEVEL.getEnum(config.emLightLevel).getNote()));
    }
 
    /**
     * 配置手持设备 IR 开关配置
     */
    public void setInfraredSetConfig() {
        String strCmd = NetSDKLib.CFG_CMD_INFRARED_CONFIG;  // 配置类型枚举
        CFG_INFRARED_INFO config = new CFG_INFRARED_INFO();
 
        // 先获取配置
        boolean bRet = ToolKits.GetDevConfig(m_hLoginHandle, -1, strCmd, config);
        if (!bRet) {
            System.err.println("获取IR开关配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("获取IR开关配置成功");
 
        // todo 修改
        config.emLightLevel = EM_INFRARED_LIGHT_LEVEL.EM_INFRARED_LIGHT_LEVEL_MEDIUM.getValue();
 
        // 下发配置
        bRet = ToolKits.SetDevConfig(m_hLoginHandle, -1, strCmd, config);
        if (!bRet) {
            System.err.println("下发IR开关配置失败:" + ENUMERROR.getErrorMessage());
            return;
        }
        System.out.println("下发IR开关配置成功");
    }
 
 
    /////////////////////////////////////// 简易控制台 ///////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////////////
 
    /**
     * 初始化测试
     */
    public void InitTest() {
        SdkUtilModule.Init();  // 初始化SDK库
        m_hLoginHandle = LogonModule.TcpLoginWithHighSecurity(m_ipAddr, m_nPort, m_username, m_password, m_stDeviceInfo);  // 高安全登录
        if (m_hLoginHandle.intValue() == 0) {
            SdkUtilModule.cleanup();
        }
    }
 
    /**
     * 加载测试内容
     */
    public void RunTest() {
        CaseMenu menu = new CaseMenu();
        menu.addItem(new CaseMenu.Item(this, "切换Demo选择通道", "setCurrChannel"));
 
        menu.addItem(new CaseMenu.Item(this, "获取设备编码配置(二代协议)", "getVideoEncode"));
        menu.addItem(new CaseMenu.Item(this, "下发设备编码配置(二代协议)", "setVideoEncode"));
 
        menu.addItem(new CaseMenu.Item(this, "获取设备编码配置(三代协议)", "getDeviceEncode"));
        menu.addItem(new CaseMenu.Item(this, "获取当前编码能力集(三代协议)", "getEncodeCapWithConfig"));
        menu.addItem(new CaseMenu.Item(this, "下发设备编码配置(三代协议)", "setDeviceEncode"));
 
        menu.addItem(new CaseMenu.Item(this, "重启当前设备", "deviceReboot"));
        menu.addItem(new CaseMenu.Item(this, "关闭当前设备", "deviceShutdown"));
        menu.addItem(new CaseMenu.Item(this, "远程关机", "RemoteShutdown"));
 
        menu.addItem(new CaseMenu.Item(this, "获取录像模式", "getRecordMode"));
        menu.addItem(new CaseMenu.Item(this, "下发录像模式", "setRecordMode"));
 
        menu.addItem(new CaseMenu.Item(this, "获取手持设备IR(红外)配置", "getInfraredSetConfig"));
        menu.addItem(new CaseMenu.Item(this, "下发手持设备IR(红外)配置", "setInfraredSetConfig"));
 
        menu.run();
    }
 
    /**
     * 结束测试
     */
    public void EndTest() {
        System.out.println("End Test");
        LogonModule.logout(m_hLoginHandle);  // 登出
        System.out.println("See You...");
        SdkUtilModule.cleanup();             // 清理资源
    }
 
    /////////////// 配置登陆地址,端口,用户名,密码  ////////////////////////
    private String m_ipAddr = "172.8.2.99";
    private int m_nPort = 37777;
    private String m_username = "admin";
    private String m_password = "qqqqq1";
    //////////////////////////////////////////////////////////////////////
 
    public static void main(String[] args) {
        DemoMPT demo = new DemoMPT();
        if (args.length == 4) {
            demo.m_ipAddr = args[0];
            demo.m_nPort = Integer.parseInt(args[1]);
            demo.m_username = args[2];
            demo.m_password = args[3];
        }
        demo.InitTest();
        demo.RunTest();
        demo.EndTest();
    }
}