package com.netsdk.demo.example.analyseTaskDemo; import com.netsdk.demo.example.analyseTaskDemo.callback.DefaultAnalyseTaskResultCallBack; import com.netsdk.demo.example.analyseTaskDemo.callback.DefaultDisconnectCallBack; import com.netsdk.demo.example.analyseTaskDemo.callback.DefaultHaveReconnectCallBack; import com.netsdk.demo.util.CaseMenu; import com.netsdk.lib.NetSDKLib; import com.netsdk.lib.ToolKits; import com.sun.jna.Memory; import com.sun.jna.ptr.IntByReference; import java.io.File; import java.util.Scanner; import static com.netsdk.lib.Enum.EM_EVENT_IVS.EVENT_IVS_FEATURE_ABSTRACT; /** * @author : 47040 * @since : Created in 2020/7/17 14:37 */ public class AnalyseTask { /****************************** static ************************************* * ************************************************************************* * *************************************************************************/ // The constant net sdk public static final NetSDKLib netsdk = NetSDKLib.NETSDK_INSTANCE; // The constant config sdk. public static NetSDKLib configsdk = NetSDKLib.CONFIG_INSTANCE; private static boolean bInit = false; // 判断是否初始化 private static boolean bLogOpen = false; // 判断log是否打开 // 回调函数需要是静态的,防止被系统回收 private static NetSDKLib.fDisConnect disConnectCB = DefaultDisconnectCallBack.getSingleInstance(); // 断线回调 private static NetSDKLib.fHaveReConnect haveReConnectCB = DefaultHaveReconnectCallBack.getInstance(); // 重连回调 private static NetSDKLib.fAnalyseTaskResultCallBack analyseTaskResultCB = DefaultAnalyseTaskResultCallBack.getSingleInstance(); // 智能分析回调 /** * Init boolean. sdk 初始化 * * @return the boolean */ public static boolean Init() { bInit = netsdk.CLIENT_Init(disConnectCB, null); if (!bInit) { System.out.println("Initialize SDK failed"); return false; } AnalyseTask.enableLog(); // 配置日志 // 设置断线重连回调接口, 此操作为可选操作,但建议用户进行设置 netsdk.CLIENT_SetAutoReconnect(haveReConnectCB, null); //设置登录超时时间和尝试次数,可选 int waitTime = 3000; //登录请求响应超时时间设置为3S int tryTimes = 1; //登录时尝试建立链接 1 次 netsdk.CLIENT_SetConnectTime(waitTime, tryTimes); // 设置更多网络参数, NET_PARAM 的nWaittime , nConnectTryNum 成员与 CLIENT_SetConnectTime // 接口设置的登录设备超时时间和尝试次数意义相同,可选 NetSDKLib.NET_PARAM netParam = new NetSDKLib.NET_PARAM(); netParam.nConnectTime = 10000; // 登录时尝试建立链接的超时时间 netParam.nGetConnInfoTime = 3000; // 设置子连接的超时时间 netsdk.CLIENT_SetNetworkParam(netParam); return true; } /** * 打开 sdk log */ private static void enableLog() { NetSDKLib.LOG_SET_PRINT_INFO setLog = new NetSDKLib.LOG_SET_PRINT_INFO(); File path = new File("sdklog/"); if (!path.exists()) path.mkdir(); // 这里的log保存地址依据实际情况自己调整 String logPath = path.getAbsoluteFile().getParent() + "\\sdklog\\" + "sdklog" + Utils.getDate() + ".log"; setLog.nPrintStrategy = 0; setLog.bSetFilePath = 1; System.arraycopy(logPath.getBytes(), 0, setLog.szLogFilePath, 0, logPath.getBytes().length); System.out.println(logPath); setLog.bSetPrintStrategy = 1; bLogOpen = netsdk.CLIENT_LogOpen(setLog); if (!bLogOpen) System.err.println("Failed to open NetSDK log"); } /** * Cleanup. 清除 sdk 环境 */ public static void cleanup() { if (bLogOpen) { netsdk.CLIENT_LogClose(); } if (bInit) { netsdk.CLIENT_Cleanup(); } } /** * 清理并退出 */ public static void cleanAndExit() { netsdk.CLIENT_Cleanup(); System.exit(0); } /************************************ 登录信息 ********************************************* ****************************************************************************************** ******************************************************************************************/ public void setLogonInfo(String addr, String port, String username, String pwd) { m_strIpAddr = addr.trim(); m_nPort = Integer.parseInt(port.trim()); m_strUser = username; m_strPassword = pwd; } private NetSDKLib.NET_DEVICEINFO_Ex deviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex(); // 设备信息 private NetSDKLib.LLong m_hLoginHandle = new NetSDKLib.LLong(0); // 登录句柄 private NetSDKLib.LLong m_attachHandle = new NetSDKLib.LLong(0); // 订阅句柄 /** * login. TCP 登录 */ public void login() { int nSpecCap = NetSDKLib.EM_LOGIN_SPAC_CAP_TYPE.EM_LOGIN_SPEC_CAP_TCP; // TCP登录 IntByReference nError = new IntByReference(0); m_hLoginHandle = netsdk.CLIENT_LoginEx2(m_strIpAddr, m_nPort, m_strUser, m_strPassword, nSpecCap, null, deviceInfo, nError); if (m_hLoginHandle.longValue() != 0) { System.out.printf("login Device[%s] Success!\n", m_strIpAddr); } else { System.err.printf("login Device[%s] Fail.Error[%s]\n", m_strIpAddr, "Test Error Code."); logOut(); } } /** * login with high level 高安全级别登陆 */ public void loginWithHighLevel() { NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY pstlnParam = new NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY() {{ szIP = m_strIpAddr.getBytes(); nPort = m_nPort; szUserName = m_strUser.getBytes(); szPassword = m_strPassword.getBytes(); }}; // 输入结构体参数 NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY pstOutParam = new NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY(); // 输结构体参数 // 写入sdk m_hLoginHandle = netsdk.CLIENT_LoginWithHighLevelSecurity(pstlnParam, pstOutParam); if (m_hLoginHandle.longValue() == 0) { System.err.printf("Login Device[%s] Port[%d]Failed. %s\n", m_strIpAddr, m_nPort, netsdk.CLIENT_GetLastError()); } else { System.out.println("Login Success"); System.out.println("Device Address:" + m_strIpAddr); } } /** * logout 退出 */ public void logOut() { if (m_hLoginHandle.longValue() != 0) { netsdk.CLIENT_Logout(m_hLoginHandle); System.out.println("LogOut Success"); } } /******************************************** 获取设备能力集 ******************************************** ****************************************************************************************************** ******************************************************************************************************/ /** * 设备智能分析服务能力集查询 */ public void GetAnalyseCaps() { // 查询结构体入参 NetSDKLib.NET_ANALYSE_CAPS_ALGORITHM stuCapsOutParam = new NetSDKLib.NET_ANALYSE_CAPS_ALGORITHM(); int emCapsType = NetSDKLib.EM_ANALYSE_CAPS_TYPE.EM_ANALYSE_CAPS_ALGORITHM; // 智能分析服务能力类型 1 stuCapsOutParam.write(); // 写入内存 boolean ret = netsdk.CLIENT_GetAnalyseCaps(m_hLoginHandle, emCapsType, stuCapsOutParam.getPointer(), 3000); stuCapsOutParam.read(); // 从内存重新读取 if (!ret) { System.err.printf("failed to get analyse caps. ErrorCode=%s\n", ToolKits.getErrorCode()); return; } System.out.println("当前设备支持特征向量个数:" + stuCapsOutParam.nAlgorithmNum); for (int i = 0; i < stuCapsOutParam.nAlgorithmNum; i++) { String info = "第" + (i + 1) + "个\n" + "场景类型:" + stuCapsOutParam.stuAlgorithmInfos[i].emClassType + "\n" + // 枚举,参考 EM_SCENE_CLASS_TYPE "特征向量版本号:" + new String(stuCapsOutParam.stuAlgorithmInfos[i].szVersion) + "\n" + "算法商:" + stuCapsOutParam.stuAlgorithmInfos[i].emAlgorithmVendor; System.out.println(info); } } /******************************************** 添加、查询、删除智能事件 ******************************************** ****************************************************************************************************** ******************************************************************************************************/ // 任务ID private int myTaskID = 0; /** * 添加智能分析任务测试 */ public void AddAnalyseTask() { // 图片智能分析入参 NetSDKLib.NET_PUSH_PICFILE_INFO stuPushPicFileInfo = new NetSDKLib.NET_PUSH_PICFILE_INFO(); stuPushPicFileInfo.emStartRule = NetSDKLib.EM_ANALYSE_TASK_START_RULE.EM_ANALYSE_TASK_START_NOW; // 立刻启动 // 设置图片分析规则 NetSDKLib.NET_ANALYSE_RULE stuRule = new NetSDKLib.NET_ANALYSE_RULE(); stuRule.nRuleCount = 1; // 以一条规则为例 stuRule.stuRuleInfos[0].emClassType = NetSDKLib.EM_SCENE_CLASS_TYPE.EM_SCENE_CLASS_FEATURE_ABSTRACT; // 特征提取大类 stuRule.stuRuleInfos[0].dwRuleType = EVENT_IVS_FEATURE_ABSTRACT.getId(); // 特征提取 /* 特征提取事件 (对应 DEV_EVENT_FEATURE_ABSTRACT_INFO) */ NetSDKLib.NET_FEATURE_ABSTRACT_RULE_INFO sRuleInfo = new NetSDKLib.NET_FEATURE_ABSTRACT_RULE_INFO(); sRuleInfo.emAbstractType = NetSDKLib.EM_FEATURE_ABSTRACT_TYPE.EM_FEATURE_ABSTRACT_FACE; // 特征提取的类型:人脸 sRuleInfo.nFeature = 1; // 提取数量 /* 设定提取版本号 */ byte[] version001 = "1003001002002".getBytes(); // 这里使用的是能力集获取时得到的版本号 // byte[] version001 = "1003001003002".getBytes(); System.arraycopy(version001, 0, sRuleInfo.szFeatureVersions[0].szFeatureVersion, 0, version001.length); // 存入指针 stuRule.stuRuleInfos[0].pReserved = sRuleInfo.getPointer(); sRuleInfo.write(); // 结构体写入内存 stuPushPicFileInfo.stuRuleInfo = stuRule; // 赋规则 stuPushPicFileInfo.write(); // 结构体写入内存 // 出参 NetSDKLib.NET_OUT_ADD_ANALYSE_TASK stuOutParam = new NetSDKLib.NET_OUT_ADD_ANALYSE_TASK(); boolean success = netsdk.CLIENT_AddAnalyseTask(m_hLoginHandle, NetSDKLib.EM_DATA_SOURCE_TYPE.EM_DATA_SOURCE_PUSH_PICFILE, stuPushPicFileInfo.getPointer(), stuOutParam, 15000); // 超时时间设长一点 if (!success) { System.err.printf("Failed to add task! ErrorCode=%s\n", ToolKits.getErrorCode()); } else { System.out.println("添加任务成功, 任务ID:" + stuOutParam.nTaskID); this.myTaskID = stuOutParam.nTaskID; } } /** * 查询智能分析任务 */ public void FindAnalyseTask() { // 入参 NetSDKLib.NET_IN_FIND_ANALYSE_TASK stuInParam = new NetSDKLib.NET_IN_FIND_ANALYSE_TASK(); // 出参 NetSDKLib.NET_OUT_FIND_ANALYSE_TASK stuOutParam = new NetSDKLib.NET_OUT_FIND_ANALYSE_TASK(); if (netsdk.CLIENT_FindAnalyseTask(m_hLoginHandle, stuInParam, stuOutParam, 5000)) { System.out.println("FindAnalyseTask Succeed!" + "智能分析任务个数" + stuOutParam.nTaskNum); // ID和状态 可以从 stuTaskInfos 中获取 for (int i = 0; i < stuOutParam.nTaskNum; i++) { // 状态值参考 EM_ANALYSE_STATE System.out.printf("任务%d: %d, 状态:%d\n", (i + 1), stuOutParam.stuTaskInfos[i].nTaskID, stuOutParam.stuTaskInfos[i].emAnalyseState); } } else { System.err.printf("FindAnalyseTask Failed!Last Error:%s\n", ToolKits.getErrorCode()); } } /** * 删除智能分析任务 */ public void RemoveAnalyseTask() { // 入参 NetSDKLib.NET_IN_REMOVE_ANALYSE_TASK pInParam = new NetSDKLib.NET_IN_REMOVE_ANALYSE_TASK(); pInParam.nTaskID = this.myTaskID; // demo里删除的是刚刚创建的任务,正常应该是查询后获取任务列表再选择需要删除的ID // 出参 NetSDKLib.NET_OUT_REMOVE_ANALYSE_TASK pOutParam = new NetSDKLib.NET_OUT_REMOVE_ANALYSE_TASK(); if (netsdk.CLIENT_RemoveAnalyseTask(m_hLoginHandle, pInParam, pOutParam, 5000)) { System.out.println("RemoveAnalyseTask Succeed! "); } else { System.err.printf("RemoveAnalyseTask Failed!Last Error: %s\n", ToolKits.getErrorCode()); } // 删除后再查询一下看看是否删除 } /******************************************** 任务订阅与退订 ******************************************** ****************************************************************************************************** ******************************************************************************************************/ public void SetDemoTaskID() { System.out.println("请输入TaskID"); Scanner sc = new Scanner(System.in); this.myTaskID = sc.nextInt(); } /** * 订阅智能事件 */ public void AttachAnalyseTaskResult() { this.DetachAnalyseTaskResult(); // 安全起见,先执行一次退订 // 入参 NetSDKLib.NET_IN_ATTACH_ANALYSE_RESULT stuInAttach = new NetSDKLib.NET_IN_ATTACH_ANALYSE_RESULT(); stuInAttach.cbAnalyseTaskResult = AnalyseTask.analyseTaskResultCB; stuInAttach.nTaskIdNum = 1; // 目前设备只支持按一个任务订阅 stuInAttach.nTaskIDs[0] = myTaskID; // 必须指定一个有效的 TaskID 才能订阅成功 stuInAttach.stuFilter.nEventNum = 1; // 只获取 EVENT_IVS_FEATURE_ABSTRACT 特征提取事件 stuInAttach.stuFilter.dwAlarmTypes[0] = EVENT_IVS_FEATURE_ABSTRACT.getId(); m_attachHandle = netsdk.CLIENT_AttachAnalyseTaskResult(m_hLoginHandle, stuInAttach, 5000); System.out.println(m_attachHandle.longValue()); if (m_attachHandle.longValue() != 0) { System.out.println("AttachAnalyseTaskResult Succeed!"); } else { System.err.printf("AttachAnalyseTaskResult Failed!Last Error: %s\n", ToolKits.getErrorCode()); } } /** * 退订智能事件 */ public void DetachAnalyseTaskResult() { if (0 != m_attachHandle.longValue()) { boolean ret = netsdk.CLIENT_DetachAnalyseTaskResult(m_attachHandle); if (!ret) { System.err.printf("DetachAnalyseTaskResult Failed!Last Error: %s\n", ToolKits.getErrorCode()); } else { System.out.println("DetachAnalyseTaskResult Succeed!"); m_attachHandle.setValue(0); } } } /******************************************** 主动推送图片 ******************************************** ****************************************************************************************************** ******************************************************************************************************/ // 测试用的图片 private final String testPicPath1 = "testPic/test1.jpg"; private final String testPicPath2 = "testPic/test2.jpg"; /** * 主动推送图片 */ public void PushAnalysePictureFile() { //入参 NetSDKLib.NET_IN_PUSH_ANALYSE_PICTURE_FILE stuInParam = new NetSDKLib.NET_IN_PUSH_ANALYSE_PICTURE_FILE(); stuInParam.nTaskID = myTaskID; stuInParam.nPicNum = 2; // 以两张图为例 // ftp://用户名:密码@hostname:端口号/文件路径 // byte[] fileUrl = "ftp://username:password@hostname:port/filepath".getBytes(); // System.arraycopy(fileUrl, 0, stuInParam.stuPushPicInfos[0].szUrl, 0, fileUrl.length); // 加载本地图片到缓冲区, 这里以两张图为例 int totalLen = 0; // 这是总的图片缓冲区长度 byte[] testFileBuffer1 = ToolKits.readPictureToByteArray(testPicPath1); byte[] testFileBuffer2 = ToolKits.readPictureToByteArray(testPicPath2); // 文件id byte[] fileId1 = "file001".getBytes(); // 这个ID是图片的标识符,设备分析完毕返回的数据也以这个ID区分 System.arraycopy(fileId1, 0, stuInParam.stuPushPicInfos[0].szFileID, 0, fileId1.length); if (testFileBuffer1 != null) { stuInParam.stuPushPicInfos[0].nLength = testFileBuffer1.length; stuInParam.stuPushPicInfos[0].nOffset = totalLen; // 偏移量,有多张图时这里要特别注意 totalLen = totalLen + stuInParam.stuPushPicInfos[0].nLength; // 总的长度是各个图的累加 } byte[] fileId2 = "file002".getBytes(); // 这个ID是图片的标识符,设备分析完毕返回的数据也以这个ID区分 System.arraycopy(fileId2, 0, stuInParam.stuPushPicInfos[1].szFileID, 0, fileId2.length); if (testFileBuffer2 != null) { stuInParam.stuPushPicInfos[1].nLength = testFileBuffer2.length; stuInParam.stuPushPicInfos[1].nOffset = totalLen; // 偏移量,有多张图时这里要特别注意 totalLen = totalLen + stuInParam.stuPushPicInfos[1].nLength; // 总的长度是各个图的累加 } stuInParam.nBinBufLen = totalLen; stuInParam.pBinBuf = new Memory(totalLen); // 分配内存 stuInParam.pBinBuf.clear(totalLen); // 清理内存 if (testFileBuffer1 != null) // 第一张图写入缓存 stuInParam.pBinBuf.write(stuInParam.stuPushPicInfos[0].nOffset, testFileBuffer1, 0, stuInParam.stuPushPicInfos[0].nLength); if (testFileBuffer2 != null) // 第二张图写入缓存 stuInParam.pBinBuf.write(stuInParam.stuPushPicInfos[1].nOffset, testFileBuffer2, 0, stuInParam.stuPushPicInfos[1].nLength); // 出参 NetSDKLib.NET_OUT_PUSH_ANALYSE_PICTURE_FILE stuOutParam = new NetSDKLib.NET_OUT_PUSH_ANALYSE_PICTURE_FILE(); if (netsdk.CLIENT_PushAnalysePictureFile(m_hLoginHandle, stuInParam, stuOutParam, 5000)) { System.out.println("PushAnalysePictureFile Succeed!"); } else { System.err.printf("PushAnalysePictureFile Failed!Last Error: %s\n", ToolKits.getErrorCode()); } } /******************************************** 简易控制台 *********************************************** ****************************************************************************************************** ******************************************************************************************************/ // 初始化测试 public void InitTest() { AnalyseTask.Init(); // 初始化SDK库 this.loginWithHighLevel(); // 高安全登录 if (m_hLoginHandle.longValue() != 0) { System.out.printf("Login Device [%s:%d] Success. \n", m_strIpAddr, m_nPort); } else { System.err.printf("Login Device [%s:%d] Failed ! Last Error[%x]\n", m_strIpAddr, m_nPort, netsdk.CLIENT_GetLastError()); EndTest(); } } // 加载测试内容 public void RunTest() { CaseMenu menu = new CaseMenu(); menu.addItem(new CaseMenu.Item(this, "分析能力查询", "GetAnalyseCaps")); menu.addItem(new CaseMenu.Item(this, "添加分析任务", "AddAnalyseTask")); menu.addItem(new CaseMenu.Item(this, "查询分析任务", "FindAnalyseTask")); menu.addItem(new CaseMenu.Item(this, "删除分析任务", "RemoveAnalyseTask")); menu.addItem(new CaseMenu.Item(this, "选择TaskID", "SetDemoTaskID")); menu.addItem(new CaseMenu.Item(this, "订阅分析事件", "AttachAnalyseTaskResult")); menu.addItem(new CaseMenu.Item(this, "退订分析事件", "DetachAnalyseTaskResult")); menu.addItem(new CaseMenu.Item(this, "主动推送图片", "PushAnalysePictureFile")); menu.run(); } // 结束测试 public void EndTest() { System.out.println("End Test"); this.DetachAnalyseTaskResult(); // 退订 this.logOut(); // 退出 System.out.println("See You..."); AnalyseTask.cleanAndExit(); // 清理资源并退出 } /////////////// 配置登陆地址,端口,用户名,密码 //////////////////////// private String m_strIpAddr = "172.12.245.68"; private int m_nPort = 37777; private String m_strUser = "admin"; private String m_strPassword = "admin123"; ////////////////////////////////////////////////////////////////////// public static void main(String[] args) { /** * Demo 的使用逻辑: * 1) 先填写设备登录信息: addr, port, username, password。 Demo启动后会先初始化SDK然后登录 * 2) 获取设备分析能力:得到设备现在的特征比对版本号 * * 3) 查询一下设备现存的任务,设备会返回现存任务的 TaskId * 4) 如果没有任务,则添加分析任务,设备会返回新添加任务的 TaskId * 5) 如果任务不需要了,可以删除任务(指定 TaskId) * * 6) 选择 TaskID 这个选项是为了方便 demo 使用,手动指定 TaskId * * 7) 准备好任务后即可订阅任务,相对应的可以退订任务,注意订阅和退订必须一一对应。 * 8) 订阅时用到的 “特征比对版本号” 就是获取设备分析能力时拿到的内容。 * * 9) 订阅任务后,即可推送图片,图片可以一次推送多张,demo里以两张作示例 * 10)推送后设备回很快返回分析结果,包括角度、质量等信息 * * 11) 退出时,Demo 会退订、登出并清理资源。 * 12) 具体的配置内容请参看 demo内的函数注释 */ AnalyseTask demo = new AnalyseTask(); demo.InitTest(); demo.RunTest(); demo.EndTest(); } }