package com.netsdk.demo.customize; import static com.netsdk.lib.Utils.getOsPrefix; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.Objects; import java.util.Scanner; import com.netsdk.demo.util.CaseMenu; import com.netsdk.lib.NetSDKLib; import com.netsdk.lib.NetSDKLib.*; import com.netsdk.lib.enumeration.EM_EVENT_IVS_TYPE; import com.netsdk.lib.structure.CFG_INTELLI_SHELF_INFO; import com.netsdk.lib.structure.CFG_IVS_MAN_NUM_DETECTION_INFO; import com.netsdk.lib.structure.CFG_NUMBERSTAT_INFO; import com.netsdk.lib.structure.DEV_EVENT_INTELLI_SHELF_INFO; import com.netsdk.lib.ToolKits; import com.sun.jna.Memory; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; /** * 视频统计摘要信息 * 进出数量统计 * @author 29779 * */ public class VideoStatistic { static NetSDKLib netsdkApi = NetSDKLib.NETSDK_INSTANCE; static NetSDKLib configApi = NetSDKLib.CONFIG_INSTANCE; private NetSDKLib.NET_DEVICEINFO_Ex deviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex(); // 登录句柄 private static LLong loginHandle = new LLong(0); public static String encode; static { String osPrefix = getOsPrefix(); if (osPrefix.toLowerCase().startsWith("win32")) { encode = "GBK"; } else if (osPrefix.toLowerCase().startsWith("linux")) { encode = "UTF-8"; } } // 智能订阅句柄 private LLong attachHandle = new NetSDKLib.LLong(0); String address = "172.27.1.173"; int port = 37777; String username = "admin"; String password = "admin123"; // private static class DisconnectCallback implements NetSDKLib.fDisConnect { private static DisconnectCallback instance = new DisconnectCallback(); private DisconnectCallback() {} public static DisconnectCallback getInstance() { return instance; } public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser){ System.out.printf("Device[%s:%d] Disconnect!\n" , pchDVRIP , nDVRPort); } } private static class HaveReconnectCallback implements NetSDKLib.fHaveReConnect { private static HaveReconnectCallback instance = new HaveReconnectCallback(); private HaveReconnectCallback() {} public static HaveReconnectCallback getInstance() { return instance; } public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser){ System.out.printf("Device[%s:%d] HaveReconnected!\n" , pchDVRIP , nDVRPort); } } public void EndTest() { System.out.println("End Test"); if( loginHandle.longValue() != 0) { netsdkApi.CLIENT_Logout(loginHandle); } System.out.println("See You..."); netsdkApi.CLIENT_Cleanup(); // 进程关闭时调用一次 System.exit(0); } public void InitTest() { //初始化SDK库 netsdkApi.CLIENT_Init(DisconnectCallback.getInstance(), null); // 进程启动时调用一次 //设置断线自动重练功能 netsdkApi.CLIENT_SetAutoReconnect(HaveReconnectCallback.getInstance(), null); // 向设备登入 final int nSpecCap = 0; /// login device by TCP final IntByReference error = new IntByReference(); loginHandle = netsdkApi.CLIENT_LoginEx2(address, (short)port, username, password, nSpecCap, null, deviceInfo, error); if(loginHandle.longValue() == 0) { System.err.printf("Login Device [%s:%d] Failed ! Last Error[%x]\n", address, port, netsdkApi.CLIENT_GetLastError()); return; } System.out.printf("Login Device [%s:%d] Success. \n", address, port); } private static class VideoStatSumCallback implements NetSDKLib.fVideoStatSumCallBack { private static VideoStatSumCallback instance = new VideoStatSumCallback(); private VideoStatSumCallback() {} public static VideoStatSumCallback getInstance() { return instance; } public void invoke(LLong lAttachHandle, NET_VIDEOSTAT_SUMMARY stVideoState, int dwBufLen, Pointer dwUser){ /** * 回调函数使用注意(防止卡回调) * 1.不能再回调进行耗时操作,建议将数据、图片流、视频流等通过中间件和多线程抛出处理 * 2.不能再回调调用netsdk的其他接口 */ System.out.printf("Channel[%d] GetTime[%s]\n" + "People In Information[Total[%d] Hour[%d] Today[%d]]\n" + "People Out Information[Total[%d] Hour[%d] Today[%d]]\n", stVideoState.nChannelID , stVideoState.stuTime.toStringTime() , stVideoState.stuEnteredSubtotal.nToday , stVideoState.stuEnteredSubtotal.nHour , stVideoState.stuEnteredSubtotal.nTotal , stVideoState.stuExitedSubtotal.nToday , stVideoState.stuExitedSubtotal.nHour , stVideoState.stuExitedSubtotal.nTotal ); try { /** * 方案:通过上报的规则类型名称 和区域ID值 去智能规则配置关系获取自定义的规则名称 * 一.规则类型名称 * 输出字符串 * 1."ManNumDetection" 对应 智能规则配置枚举 EVENT_IVS_MAN_NUM_DETECTION(立体视觉区域内人数统计事件) * 2."NumberStat" 对应 智能规则配置枚举 EVENT_IVS_NUMBERSTAT(数量统计事件)对应的规则配置 * * 二、区域ID * 输出区域ID值 对应智能规则字段nAreaID的值 */ System.out.println("规则类型名称:"+new String(stVideoState.szRuleName,encode)); System.out.println("区域ID:"+stVideoState.nAreaID); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } /** * 查询智能规则配置信息 */ public void getCongigRuleInfo() { int channel = 0; // 通道号 String command = NetSDKLib.CFG_CMD_ANALYSERULE; int ruleCount = 10; // 事件规则个数 CFG_RULE_INFO[] ruleInfo = new CFG_RULE_INFO[ruleCount]; for (int i = 0; i < ruleCount; i++) { ruleInfo[i] = new CFG_RULE_INFO(); } CFG_ANALYSERULES_INFO analyse = new CFG_ANALYSERULES_INFO(); analyse.nRuleLen = 1024 * 1024 * 40; analyse.pRuleBuf = new Memory(1024 * 1024 * 40); // 申请内存 analyse.pRuleBuf.clear(1024 * 1024 * 40); // 查询 if (ToolKits.GetDevConfig(loginHandle, channel, command, analyse)) { int offset = 0; System.out.println("设备返回的事件规则个数:" + analyse.nRuleCount); int count = analyse.nRuleCount < ruleCount ? analyse.nRuleCount : ruleCount; for (int i = 0; i < count; i++) { // 每个视频输入通道对应的所有事件规则:缓冲区pRuleBuf填充多个事件规则信息,每个事件规则信息内容为 CFG_RULE_INFO + 事件类型对应的规则配置结构体。 ToolKits.GetPointerDataToStruct(analyse.pRuleBuf, offset, ruleInfo[i]); offset += ruleInfo[0].size(); // 智能规则偏移量 switch (ruleInfo[i].dwRuleType) { case NetSDKLib.EVENT_IVS_CROSSLINEDETECTION: { //事件类型 EVENT_IVS_CROSSLINEDETECTION (警戒线事件)对应的规则配置CFG_CROSSLINE_INFO //System.out.println("警戒线配置----------------------------"); break; } case NetSDKLib.EVENT_IVS_CROSSREGIONDETECTION: {//事件类型EVENT_IVS_CROSSREGIONDETECTION(警戒区事件)对应的规则配置CFG_CROSSREGION_INFO //System.out.println("警戒区配置-----------------------------"); break; } case NetSDKLib.EVENT_IVS_NUMBERSTAT: { //事件类型EVENT_IVS_NUMBERSTAT(数量统计事件)对应的规则配置 CFG_NUMBERSTAT_INFO // #define EVENT_IVS_NUMBERSTAT = 0x00000010 System.out.println("数量统计-----------------------------"); System.out.println("数量统计的枚举值:"+NetSDKLib.EVENT_IVS_NUMBERSTAT+" 对应规则类型名称字符串'NumberStat'"); CFG_NUMBERSTAT_INFO msg = new CFG_NUMBERSTAT_INFO(); ToolKits.GetPointerDataToStruct(analyse.pRuleBuf, offset, msg); try { System.out.println("自定义规则名称:"+ new String(msg.szRuleName,encode)); // 用户需要的名称 System.out.println("区域ID:"+ msg.nAreaID); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } break; } case NetSDKLib.EVENT_IVS_MAN_NUM_DETECTION: { //事件类型EVENT_IVS_MAN_NUM_DETECTION(立体视觉区域内人数统计事件)对应的规则配置 CFG_IVS_MAN_NUM_DETECTION_INFO //#define EVENT_IVS_MAN_NUM_DETECTION = 0x0000020E System.out.println("区域内人数统计-----------------------------"); System.out.println("区域内人数统计的枚举值:"+NetSDKLib.EVENT_IVS_MAN_NUM_DETECTION+" 对应规则类型名称字符串'ManNumDetection'"); CFG_IVS_MAN_NUM_DETECTION_INFO msg = new CFG_IVS_MAN_NUM_DETECTION_INFO(); ToolKits.GetPointerDataToStruct(analyse.pRuleBuf, offset, msg); try { System.out.println("自定义规则名称:"+ new String(msg.szRuleName,encode)); // 用户需要的名称 System.out.println("区域ID:"+ msg.nAreaID); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } break; } case NetSDKLib.EVENT_IVS_INTELLI_SHELF: { //事件类型EVENT_IVS_INTELLI_SHELF(智能补货事件)对应的规则配置 CFG_INTELLI_SHELF_INFO //#define EVENT_IVS_INTELLI_SHELF = 0x00000277 System.out.println("智能补货事件-----------------------------"); System.out.println("智能补货事件的枚举值:"+NetSDKLib.EVENT_IVS_INTELLI_SHELF+" 对应规则类型名称字符串'IntelliShelf'"); CFG_INTELLI_SHELF_INFO msg = new CFG_INTELLI_SHELF_INFO(); ToolKits.GetPointerDataToStruct(analyse.pRuleBuf, offset, msg); try { System.out.println("自定义规则名称:"+ new String(msg.szRuleName,encode)); // 用户需要的名称 System.out.println("区域ID:"+ msg.nAreaID); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } break; } default: break; } offset += ruleInfo[i].nRuleSize; // 智能事件偏移量 } } else { System.err.println("查询智能事件规则信息失败!" + ToolKits.getErrorCode()); } } /** 订阅视频统计 句柄*/ private LLong videoStatHandle = new LLong(0); /** * 订阅 */ public void attachVideoStatSummary() { if (loginHandle.longValue() == 0) { return; } NET_IN_ATTACH_VIDEOSTAT_SUM videoStatIn = new NET_IN_ATTACH_VIDEOSTAT_SUM(); videoStatIn.nChannel = 0; videoStatIn.cbVideoStatSum = VideoStatSumCallback.getInstance(); NET_OUT_ATTACH_VIDEOSTAT_SUM videoStatOut = new NET_OUT_ATTACH_VIDEOSTAT_SUM(); videoStatHandle = netsdkApi.CLIENT_AttachVideoStatSummary(loginHandle, videoStatIn, videoStatOut, 5000); if( videoStatHandle.longValue() == 0 ) { System.err.printf("Attach Failed!LastError = %x\n", netsdkApi.CLIENT_GetLastError()); return; } System.out.printf("Attach Success!Wait Device Notify Information\n"); } /** * 退订 */ public void detachVideoStatSummary() { if (videoStatHandle.longValue() != 0) { netsdkApi.CLIENT_DetachVideoStatSummary(videoStatHandle); videoStatHandle.setValue(0); } } private LLong findHandle = new LLong(0); // 查询句柄 public void startFindNumberStat() { NetSDKLib.NET_IN_FINDNUMBERSTAT inParam = new NetSDKLib.NET_IN_FINDNUMBERSTAT(); inParam.nChannelID = 0; // 通道号 inParam.stStartTime.dwYear = 2016;// 开始时间 inParam.stStartTime.dwMonth = 6; inParam.stStartTime.dwDay = 20; inParam.stStartTime.dwHour = 0; inParam.stEndTime.dwYear = 2016;// 结束时间 inParam.stEndTime.dwMonth = 6; inParam.stEndTime.dwDay = 21; inParam.stEndTime.dwHour = 23; inParam.nGranularityType = 1;// 颗粒度 inParam.nWaittime = 5000; // 接口超时时间5s NetSDKLib.NET_OUT_FINDNUMBERSTAT outParam = new NetSDKLib.NET_OUT_FINDNUMBERSTAT(); /// 获取查询句柄 findHandle = netsdkApi.CLIENT_StartFindNumberStat(loginHandle, inParam, outParam); if (findHandle.longValue() == 0) { System.err.printf("StartFindNumberStat Failed! LastError = 0x%x\n", netsdkApi.CLIENT_GetLastError() ); return; } System.out.println("dwTotalCount: " + outParam.dwTotalCount); /// 查询 NetSDKLib.NET_IN_DOFINDNUMBERSTAT inDoFind = new NetSDKLib.NET_IN_DOFINDNUMBERSTAT(); inDoFind.nBeginNumber = 0; // 从0开始查询 inDoFind.nCount = 10; // 每次查询10条 inDoFind.nWaittime = 5000; //接口超时时间 5s NetSDKLib.NET_OUT_DOFINDNUMBERSTAT outDofind = new NetSDKLib.NET_OUT_DOFINDNUMBERSTAT(); NetSDKLib.NET_NUMBERSTAT[] numberstat = (NetSDKLib.NET_NUMBERSTAT[])new NetSDKLib.NET_NUMBERSTAT().toArray(inDoFind.nCount); for (int i = 0 ;i < numberstat.length; i ++) { numberstat[i].dwSize = numberstat[0].dwSize; } outDofind.nBufferLen = inDoFind.nCount * numberstat[0].dwSize; outDofind.pstuNumberStat = new Memory(outDofind.nBufferLen); outDofind.pstuNumberStat.clear(outDofind.nBufferLen); // Note: 初始化内存中 dwSize 字段的值,否则查询的结果为空 ToolKits.SetStructArrToPointerData(numberstat, outDofind.pstuNumberStat); int bFound = 0; int index = 1; do { bFound = netsdkApi.CLIENT_DoFindNumberStat(findHandle, inDoFind, outDofind); if (0 == bFound) { System.err.printf("DoFindNumberStat Failed! LastError = 0x%x\n", netsdkApi.CLIENT_GetLastError() ); return; } // 查询结果 ToolKits.GetPointerDataToStructArr(outDofind.pstuNumberStat, numberstat); for(int i = 0; i < outDofind.nCount; i++, index ++) { System.out.println("Index = " + index + " Start Time: " + numberstat[i].stuStartTime.toStringTime() + " Stop Time: " + numberstat[i].stuEndTime.toStringTime() + " Enter Total: " + numberstat[i].nEnteredSubTotal + " Exit Total: " + numberstat[i].nExitedSubtotal + "\n" ); } // 查询下一次 inDoFind.nBeginNumber += inDoFind.nCount; // 从上一次结束地方开始查询 }while(outDofind.nCount >= inDoFind.nCount); } public void stopFindNumberStat() { if (findHandle.longValue() != 0 ) { netsdkApi.CLIENT_StopFindNumberStat(findHandle); System.out.println("stop Find Number Stat Success. "); findHandle.setValue(0); } } /** * 选择通道 */ private int channel = 0; public void setChannelID() { System.out.println("请输入通道,从0开始计数,-1表示全部"); Scanner sc = new Scanner(System.in); this.channel = sc.nextInt(); } /** * 订阅智能事件 */ public void AttachEventRealLoadPic() { // 先退订,设备不会对重复订阅作校验,重复订阅后会有重复的事件返回 this.DetachEventRealLoadPic(); // 需要图片 int bNeedPicture = 1; attachHandle = netsdkApi.CLIENT_RealLoadPictureEx(loginHandle, channel, NetSDKLib.EVENT_IVS_ALL, bNeedPicture, AnalyzerDataCB.getInstance(), null, null); if (attachHandle.longValue() != 0) { System.out.printf("Chn[%d] CLIENT_RealLoadPictureEx Success\n", channel); } else { System.out.printf("Ch[%d] CLIENT_RealLoadPictureEx Failed!LastError = %s\n", channel, ToolKits.getErrorCode()); } } /** * 智能事件回调 */ private static class AnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack { private final File picturePath; private static AnalyzerDataCB instance; private AnalyzerDataCB() { picturePath = new File("./AnalyzerPicture/"); if (!picturePath.exists()) { picturePath.mkdirs(); } } public static AnalyzerDataCB getInstance() { if (instance == null) { synchronized (AnalyzerDataCB.class) { if (instance == null) { instance = new AnalyzerDataCB(); } } } return instance; } public int invoke(LLong lAnalyzerHandle, int dwAlarmType, Pointer pAlarmInfo, Pointer pBuffer, int dwBufSize, Pointer dwUser, int nSequence, Pointer reserved) { if (lAnalyzerHandle == null || lAnalyzerHandle.longValue() == 0) { return -1; } System.out.println("dwAlarmType:"+dwAlarmType); switch (Objects.requireNonNull(EM_EVENT_IVS_TYPE.getEventType(dwAlarmType))) { case EVENT_IVS_INTELLI_SHELF: {// 智能补货事件(对应 DEV_EVENT_INTELLI_SHELF_INFO) DEV_EVENT_INTELLI_SHELF_INFO msg = new DEV_EVENT_INTELLI_SHELF_INFO(); ToolKits.GetPointerData(pAlarmInfo, msg); System.out.println(" 智能补货事件 时间(UTC):" + msg.UTC + " 通道号:" + msg.nChannelID +" 事件ID:" + msg.nEventID +" 事件名称:" +new String(msg.szName).trim() // 规则类型名称 +" 区域ID(从1开始), 0为单区域:" +msg.nAreaID // 区域ID +" 事件触发的预置点号,从1开始:" +msg.nPresetID +" 表示货架上剩余货物的百分比:" +msg.nPercent ); /** * 回调函数使用注意(防止卡回调) * 1.不能再回调进行耗时操作,建议将数据、图片流、视频流等通过中间件和多线程抛出处理 * 2.不能再回调调用netsdk的其他接口 */ // 全图 String Picture = picturePath + "\\" + "EVENT_IVS_INTELLI_SHELF" + System.currentTimeMillis() + ".jpg"; if (dwBufSize > 0) { ToolKits.savePicture(pBuffer, 0, dwBufSize, Picture); } // 全景大图 if (msg.stuSceneImage != null && msg.stuSceneImage.nLength > 0) { String bigPicture = picturePath + "\\" + "big" + System.currentTimeMillis() + ".jpg"; ToolKits.savePicture(pBuffer, msg.stuSceneImage.nOffSet, msg.stuSceneImage.nLength, bigPicture); } break; } default: System.out.println("其他事件--------------------" + dwAlarmType); break; } return 0; } } /** * 停止侦听智能事件 */ public void DetachEventRealLoadPic() { if (attachHandle.longValue() != 0) { netsdkApi.CLIENT_StopLoadPic(attachHandle); } } public void RunTest() { System.out.println("Run Test"); CaseMenu menu = new CaseMenu(); menu.addItem(new CaseMenu.Item(this, "查询智能规则配置信息", "getCongigRuleInfo")); menu.addItem(new CaseMenu.Item(this, "订阅", "attachVideoStatSummary")); menu.addItem(new CaseMenu.Item(this, "退订", "detachVideoStatSummary")); //menu.addItem(new CaseMenu.Item(this, "开始查询", "startFindNumberStat")); //menu.addItem(new CaseMenu.Item(this, "停止查询", "stopFindNumberStat")); menu.addItem(new CaseMenu.Item(this, "选择通道", "setChannelID")); menu.addItem(new CaseMenu.Item(this, "订阅智能事件", "AttachEventRealLoadPic")); menu.addItem(new CaseMenu.Item(this, "停止侦听智能事件", "DetachEventRealLoadPic")); menu.run(); } public static void main(String[]args) { VideoStatistic demo = new VideoStatistic(); demo.InitTest(); demo.RunTest(); demo.EndTest(); } }