package com.netsdk.demo.customize; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.Scanner; import com.netsdk.demo.util.CaseMenu; import com.netsdk.lib.NetSDKLib; import com.netsdk.lib.NetSDKLib.LLong; import com.netsdk.lib.ToolKits; import com.netsdk.lib.structure.NET_RECORD_STATUS; import com.sun.jna.Memory; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import static com.netsdk.lib.Utils.getOsPrefix; /** * 查找文件信息demo */ public class FindFilePictureAndRecord { static NetSDKLib netsdkApi = NetSDKLib.NETSDK_INSTANCE; static NetSDKLib configApi = NetSDKLib.CONFIG_INSTANCE; private final 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-amd64")) { encode = "GBK"; } else if (osPrefix.toLowerCase().startsWith("linux-amd64")) { encode = "UTF-8"; } } // 设备断线回调: 通过 CLIENT_Init 设置该回调函数,当设备出现断线时,SDK会调用该函数 public static class fDisConnectCB implements NetSDKLib.fDisConnect { public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser) { System.out.printf("Device[%s] Port[%d] Disconnect!\n", pchDVRIP, nDVRPort); } } // 网络连接恢复,设备重连成功回调 // 通过 CLIENT_SetAutoReconnect 设置该回调函数,当已断线的设备重连成功时,SDK会调用该函数 public static class HaveReConnect implements NetSDKLib.fHaveReConnect { public void invoke(LLong loginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) { System.out.printf("ReConnect Device[%s] Port[%d]\n", pchDVRIP, nDVRPort); } } private final fDisConnectCB m_DisConnectCB = new fDisConnectCB(); private final HaveReConnect haveReConnect = new HaveReConnect(); /** * 查找录像,需要指定查询录像的最大个数 除非 FindFileEx 无法使用 否则不建议使用这个接口 */ public void QueryRecordFile() { NetSDKLib.NET_TIME stTimeStart = new NetSDKLib.NET_TIME(); stTimeStart.dwYear = 2021; stTimeStart.dwMonth = 1; stTimeStart.dwDay = 1; stTimeStart.dwHour = 0; stTimeStart.dwMinute = 0; stTimeStart.dwSecond = 0; NetSDKLib.NET_TIME stTimeEnd = new NetSDKLib.NET_TIME(); stTimeEnd.dwYear = 2021; stTimeEnd.dwMonth = 1; stTimeEnd.dwDay = 31; stTimeEnd.dwHour = 23; stTimeEnd.dwMinute = 59; stTimeEnd.dwSecond = 59; //**************按时间查找视频文件************** int nFileCount = 50; //每次查询的最大文件个数 NetSDKLib.NET_RECORDFILE_INFO[] numberFile = (NetSDKLib.NET_RECORDFILE_INFO[]) new NetSDKLib.NET_RECORDFILE_INFO().toArray(nFileCount); int maxlen = nFileCount * numberFile[0].size(); IntByReference outFileCoutReference = new IntByReference(0); boolean cRet = netsdkApi.CLIENT_QueryRecordFile(loginHandle, 0, 0, stTimeStart, stTimeEnd, null, numberFile, maxlen, outFileCoutReference, 5000, false); if (cRet) { System.out.println("QueryRecordFile Succeed! \n" + "查询到的视频个数:" + outFileCoutReference.getValue() + "\n" + "码流类型:" + numberFile[0].bRecType); for (int i = 0; i < outFileCoutReference.getValue(); i++) { System.out.println("【" + i + "】:"); System.out.println("开始时间:" + numberFile[i].starttime); System.out.println("结束时间:" + numberFile[i].endtime); System.out.println("通道号:" + numberFile[i].ch); } } else { System.err.println("QueryRecordFile Failed!" + netsdkApi.CLIENT_GetLastError()); } } /** * 查询图片 */ public void QueryPictureByFindFileEx() { System.out.println("查询设备保存的jpg图片"); Scanner sc = new Scanner(System.in); System.out.println("请输入通道号 从0开始 -1表示全部:"); int channel = Integer.parseInt(sc.nextLine()); System.out.println("请输入起始时间 yyyy-MM-dd HH:mm:ss"); String startStr = sc.nextLine().trim(); NetSDKLib.NET_TIME startTime = GetNetTime(startStr); if (startTime == null) return; System.out.println("请输入结束时间 yyyy-MM-dd HH:mm:ss"); String endStr = sc.nextLine().trim(); NetSDKLib.NET_TIME endTime = GetNetTime(endStr); if (endTime == null) return; // 文件类型 1:查询jpg图片,2:查询dav FindFileEx(channel, 1, startTime, endTime); } /** * 查询录像 */ public void QueryRecordByFindFileEx() { System.out.println("查询设备保存的dev录像文件"); Scanner sc = new Scanner(System.in); System.out.println("请输入通道号 从0开始 -1表示全部:"); int channel = Integer.parseInt(sc.nextLine()); System.out.println("请输入起始时间 yyyy-MM-dd HH:mm:ss"); String startStr = sc.nextLine().trim(); NetSDKLib.NET_TIME startTime = GetNetTime(startStr); if (startTime == null) return; System.out.println("请输入结束时间 yyyy-MM-dd HH:mm:ss"); String endStr = sc.nextLine().trim(); NetSDKLib.NET_TIME endTime = GetNetTime(endStr); if (endTime == null) return; // 文件类型 1:查询jpg图片,2:查询dav FindFileEx(channel, 2, startTime, endTime); } private static NetSDKLib.NET_TIME GetNetTime(String dateTime) { NetSDKLib.NET_TIME start = new NetSDKLib.NET_TIME(); try { int[] date = Arrays.stream(dateTime.split("\\s+")[0].split("-")).mapToInt(Integer::valueOf).toArray(); int[] time = Arrays.stream(dateTime.split("\\s+")[1].split(":")).mapToInt(Integer::valueOf).toArray(); start.setTime(date[0], date[1], date[2], time[0], time[1], time[2]); } catch (Exception e) { System.err.println("输入格式错误"); return null; } return start; } /** * 查询 图片/录像 文件 */ public void FindFileEx(int channel, int fileType, NetSDKLib.NET_TIME startTime, NetSDKLib.NET_TIME endTime) { int type = NetSDKLib.EM_FILE_QUERY_TYPE.NET_FILE_QUERY_FILE; // 查询条件 NetSDKLib.NET_IN_MEDIA_QUERY_FILE queryCondition = new NetSDKLib.NET_IN_MEDIA_QUERY_FILE(); // 工作目录列表,一次可查询多个目录,为空表示查询所有目录。 // 目录之间以分号分隔,如“/mnt/dvr/sda0;/mnt/dvr/sda1”,szDirs==null 或"" 表示查询所有 queryCondition.szDirs = ""; // 文件类型 1:查询jpg图片,2:查询dav queryCondition.nMediaType = fileType; // 通道号从0开始,-1表示查询所有通道 queryCondition.nChannelID = channel; // 开始时间 queryCondition.stuStartTime = startTime; // 结束时间 queryCondition.stuEndTime = endTime; queryCondition.write(); LLong lFindHandle = netsdkApi.CLIENT_FindFileEx(loginHandle, type, queryCondition.getPointer(), null, 3000); if (lFindHandle.longValue() == 0) { System.err.println("FindFileEx Failed!" + getErrorCode()); return; } queryCondition.read(); /////////////////////////// int nMaxCount = 10; // 每次查询的个数,循环查询 NetSDKLib.NET_OUT_MEDIA_QUERY_FILE[] pMediaQueryFile = new NetSDKLib.NET_OUT_MEDIA_QUERY_FILE[nMaxCount]; for (int i = 0; i < pMediaQueryFile.length; ++i) { pMediaQueryFile[i] = new NetSDKLib.NET_OUT_MEDIA_QUERY_FILE(); } int MemorySize = pMediaQueryFile[0].size() * nMaxCount; Pointer mediaFileInfo = new Memory(MemorySize); mediaFileInfo.clear(MemorySize); ToolKits.SetStructArrToPointerData(pMediaQueryFile, mediaFileInfo); //循环查询 int nCurCount = 0; int nFindCount = 0; while (true) { int nRet = netsdkApi.CLIENT_FindNextFileEx(lFindHandle, nMaxCount, mediaFileInfo, MemorySize, null, 3000); ToolKits.GetPointerDataToStructArr(mediaFileInfo, pMediaQueryFile); System.out.println("nRet : " + nRet); if (nRet <= 0) { break; } for (int i = 0; i < nRet; i++) { nFindCount = i + nCurCount * nMaxCount; System.out.println("[" + nFindCount + "]通道号 :" + pMediaQueryFile[i].nChannelID); System.out.println("[" + nFindCount + "]开始时间 :" + pMediaQueryFile[i].stuStartTime.toStringTime()); System.out.println("[" + nFindCount + "]结束时间 :" + pMediaQueryFile[i].stuEndTime.toStringTime()); if (pMediaQueryFile[i].byFileType == 1) { System.out.println("[" + nFindCount + "]文件类型 : jpg图片"); } else if ((pMediaQueryFile[i].byFileType == 2)) { System.out.println("[" + nFindCount + "]文件类型 : dav"); } System.out.println("[" + nFindCount + "]文件路径 :" + new String(pMediaQueryFile[i].szFilePath).trim()); } if (nRet < nMaxCount) { break; } else { nCurCount++; } } // 关闭查询 netsdkApi.CLIENT_FindCloseEx(lFindHandle); } /** * 指定月份 查询当月每日的录像状况 录像类型指定: 所有类型 */ public void QueryAllRecordStatusInSpecifiedMonth() { Scanner sc = new Scanner(System.in); System.out.println("请输入通道号 从0开始 -1表示全部:"); int channel = Integer.parseInt(sc.nextLine()); System.out.println("请指定月份 yyyy-MM"); String monthStr = sc.nextLine().trim(); NetSDKLib.NET_TIME month = GetNetMonth(monthStr); if (month == null) return; int recordType = NetSDKLib.EM_QUERY_RECORD_TYPE.EM_RECORD_TYPE_ALL; // 查询所有录像 try { QueryRecordStatus(channel, month, recordType, null); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } /** * 指定月份 查询当月每日的录像状况 录像类型指定: 卡号查询 * 只有部分 HB-U、NVS设备的版本支持 */ public void QueryCardRecordStatusInSpecifiedMonth() { Scanner sc = new Scanner(System.in); System.out.println("请输入通道号 从0开始 -1表示全部:"); int channel = sc.nextInt(); System.out.println("请指定月份 yyyy-MM"); String monthStr = sc.nextLine().trim(); NetSDKLib.NET_TIME month = GetNetMonth(monthStr); if (month == null) return; System.out.println("请输入卡号 最长59个字节"); String cardId = sc.nextLine().trim(); if (cardId.length() > 59) { System.err.println("卡号长度超过59字节"); return; } int recordType = NetSDKLib.EM_QUERY_RECORD_TYPE.EM_RECORD_TYPE_CARD; // 卡号查询 try { QueryRecordStatus(channel, month, recordType, cardId); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } /** * 指定月份 查询当月每日的录像状况 录像类型指定: 按字段查询 * 只有部分 HB-U、NVS设备的版本支持 */ public void QueryFieldRecordStatusInSpecifiedMonth() { Scanner sc = new Scanner(System.in); System.out.println("请输入通道号 从0开始 -1表示全部:"); int channel = sc.nextInt(); System.out.println("请指定月份 yyyy-MM"); String monthStr = sc.nextLine().trim(); NetSDKLib.NET_TIME month = GetNetMonth(monthStr); if (month == null) return; System.out.println("请输入字段 最长256个字节"); String field = sc.nextLine().trim(); if (field.length() > 256) { System.err.println("字段长度超过256字节"); return; } int recordType = NetSDKLib.EM_QUERY_RECORD_TYPE.EM_RECORD_TYPE_FIELD; // 按字段查询 try { QueryRecordStatus(channel, month, recordType, field); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } public void QueryRecordStatus(int channel, NetSDKLib.NET_TIME monthTime, int recordType, String cardId) throws UnsupportedEncodingException { // recordFileType 枚举不为 EM_RECORD_TYPE_CARD 或 EM_RECORD_TYPE_FIELD 时 pCardId 无效 Pointer pCardId = null; if (recordType == NetSDKLib.EM_QUERY_RECORD_TYPE.EM_RECORD_TYPE_CARD) { byte[] bCardId = cardId.getBytes(encode); pCardId = new Memory(59); pCardId.clear(59); pCardId.write(0, bCardId, 0, bCardId.length); } else if (recordType == NetSDKLib.EM_QUERY_RECORD_TYPE.EM_RECORD_TYPE_FIELD) { byte[] bCardId = cardId.getBytes(encode); pCardId = new Memory(256); pCardId.clear(256); pCardId.write(0, bCardId, 0, bCardId.length); } NET_RECORD_STATUS status = new NET_RECORD_STATUS(); monthTime.write(); status.write(); boolean ret = netsdkApi.CLIENT_QueryRecordStatus(loginHandle, channel, recordType, monthTime.getPointer(), pCardId, status.getPointer(), 3000); if (!ret) { System.err.println("查询月录像状态失败:" + getErrorCode()); return; } status.read(); StringBuilder recordStatus = new StringBuilder().append(String.format("%4d年%2d月的录像状态:", monthTime.dwYear, monthTime.dwMonth)).append("\n"); for (int i = 0; i < status.flag.length; i++) { // 请注意 flag[0] 是当月的第1天 recordStatus.append(String.format(" 第%2d天: %s", i + 1, (status.flag[i] == 0 ? "不存在" : "存在"))).append("\n"); } System.out.println(recordStatus.toString()); } private static NetSDKLib.NET_TIME GetNetMonth(String month) { NetSDKLib.NET_TIME start = new NetSDKLib.NET_TIME(); try { int[] date = Arrays.stream(month.split("-")).mapToInt(Integer::valueOf).toArray(); start.setTime(date[0], date[1], 0, 0, 0, 0); } catch (Exception e) { System.err.println("输入格式错误"); return null; } return start; } /** * 获取接口错误码 */ public static String getErrorCode() { return " { error code: ( 0x80000000|" + (netsdkApi.CLIENT_GetLastError() & 0x7fffffff) + " ). 参考 NetSDKLib.java }"; } public void InitTest() { //初始化SDK库 netsdkApi.CLIENT_Init(m_DisConnectCB, null); // 设置断线重连回调接口,设置过断线重连成功回调函数后,当设备出现断线情况,SDK内部会自动进行重连操作 // 此操作为可选操作,但建议用户进行设置 netsdkApi.CLIENT_SetAutoReconnect(haveReConnect, null); //设置登录超时时间和尝试次数,可选 int waitTime = 5000; //登录请求响应超时时间设置为5S int tryTimes = 3; //登录时尝试建立链接3次 netsdkApi.CLIENT_SetConnectTime(waitTime, tryTimes); // 设置更多网络参数,NET_PARAM的nWaittime,nConnectTryNum成员与CLIENT_SetConnectTime // 接口设置的登录设备超时时间和尝试次数意义相同,可选 NetSDKLib.NET_PARAM netParam = new NetSDKLib.NET_PARAM(); netParam.nConnectTime = 10000; //登录时尝试建立链接的超时时间 netsdkApi.CLIENT_SetNetworkParam(netParam); // 打开日志,可选 NetSDKLib.LOG_SET_PRINT_INFO setLog = new NetSDKLib.LOG_SET_PRINT_INFO(); File path = new File("."); String logPath = path.getAbsoluteFile().getParent() + "\\sdk_log\\" + System.currentTimeMillis() + ".log"; setLog.bSetFilePath = 1; System.arraycopy(logPath.getBytes(), 0, setLog.szLogFilePath, 0, logPath.getBytes().length); setLog.bSetPrintStrategy = 1; setLog.nPrintStrategy = 0; boolean bLogopen = netsdkApi.CLIENT_LogOpen(setLog); if (!bLogopen) { System.err.println("Failed to open NetSDK log !!!"); } // 向设备登入 int nSpecCap = 0; Pointer pCapParam = null; IntByReference nError = new IntByReference(0); loginHandle = netsdkApi.CLIENT_LoginEx2(m_strIp, m_nPort, m_strUser, m_strPassword, nSpecCap, pCapParam, deviceinfo, nError); if (loginHandle.longValue() != 0) { System.out.printf("Login Device[%s] Port[%d]Success!\n", m_strIp, m_nPort); } else { System.out.printf("Login Device[%s] Port[%d]Fail.Last Error[0x%x]\n", m_strIp, m_nPort, netsdkApi.CLIENT_GetLastError()); EndTest(); } } public void RunTest() { System.out.println("Run Test"); CaseMenu menu = new CaseMenu(); menu.addItem(new CaseMenu.Item(this, "QueryPictureByFindFileEx 通过FindFileEx接口查询图片", "QueryPictureByFindFileEx")); menu.addItem(new CaseMenu.Item(this, "QueryRecordByFindFileEx 通过FindFileEx接口查询录像", "QueryRecordByFindFileEx")); menu.addItem(new CaseMenu.Item(this, "QueryAllRecordStatusInSpecifiedMonth 查询当月录像状况: 所有录像", "QueryAllRecordStatusInSpecifiedMonth")); menu.run(); } 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); } //////////////////////////////////////////////////////////////// String m_strIp = "172.23.12.29"; int m_nPort = 37777; String m_strUser = "admin"; String m_strPassword = "admin111"; //////////////////////////////////////////////////////////////// public static void main(String[] args) { FindFilePictureAndRecord demo = new FindFilePictureAndRecord(); demo.InitTest(); demo.RunTest(); demo.EndTest(); } }