没有触发智能订阅的回调事件的原因是隐私设置的抓拍功能没有打开
分享一下排查问题的经验
-
大华demo代码的大概思路就是,创建
AnalyzerDataCB
类实现大华sdk的回调接口,然后根据需求重写invoke
函数用来接收回传过来的参数,然后创建AnalyzerDataCB
实例当作大华sdk中CLIENT_RealLoadPictureEx
函数的参数,从而实现智能订阅。private AnalyzerDataCB analyzerCallback = new AnalyzerDataCB(); //监听按钮,点击后智能订阅 @Override public void actionPerformed(ActionEvent arg0) { m_hAttachHandle = GateModule.realLoadPic(chnComboBox.getSelectedIndex(), analyzerCallback); if(m_hAttachHandle.longValue() != 0) { isAttach = true; attachBtn.setEnabled(false); detachBtn.setEnabled(true); } else { JOptionPane.showMessageDialog(null, ToolKits.getErrorCodeShow(), Res.string().getErrorMessage(), JOptionPane.ERROR_MESSAGE); } } //智能订阅的回调事件 private class AnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack { private BufferedImage gateBufferedImage = null; public int invoke(LLong lAnalyzerHandle, int dwAlarmType, Pointer pAlarmInfo, Pointer pBuffer, int dwBufSize, Pointer dwUser, int nSequence, Pointer reserved) { if (lAnalyzerHandle.longValue() == 0 || pAlarmInfo == null) { return -1; } File path = new File("./GateSnapPicture/"); if (!path.exists()) { path.mkdir(); } ///< 门禁事件 if(dwAlarmType == NetSDKLib.EVENT_IVS_ACCESS_CTL) { System.out.println("123"); DEV_EVENT_ACCESS_CTL_INFO msg = new DEV_EVENT_ACCESS_CTL_INFO(); ToolKits.GetPointerData(pAlarmInfo, msg); // 保存图片,获取图片缓存 String snapPicPath = path + "\\" + System.currentTimeMillis() + "GateSnapPicture.jpg"; // 保存图片地址 byte[] buffer = pBuffer.getByteArray(0, dwBufSize); ByteArrayInputStream byteArrInputGlobal = new ByteArrayInputStream(buffer); try { gateBufferedImage = ImageIO.read(byteArrInputGlobal); if(gateBufferedImage != null) { ImageIO.write(gateBufferedImage, "jpg", new File(snapPicPath)); } } catch (IOException e2) { e2.printStackTrace(); } // 图片以及门禁信息界面显示 EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); if (eventQueue != null) { eventQueue.postEvent( new AccessEvent(target, gateBufferedImage, msg)); } SwingUtilities.invokeLater(() -> { VideoPlayerDialog dialog = new VideoPlayerDialog(null); dialog.setVisible(true); }); } return 0; } } //调用大华的netsdk实现智能订阅事件 public static LLong realLoadPic(int ChannelId, NetSDKLib.fAnalyzerDataCallBack m_AnalyzerDataCB) { /** * 说明: * 通道数可以在有登录是返回的信息 m_stDeviceInfo.byChanNum 获取 * 下列仅订阅了0通道的智能事件. */ int bNeedPicture = 1; // 是否需要图片 LLong m_hAttachHandle = LoginModule.netsdk.CLIENT_RealLoadPictureEx(LoginModule.m_hLoginHandle, ChannelId, NetSDKLib.EVENT_IVS_ALL, bNeedPicture , m_AnalyzerDataCB , null , null); if( m_hAttachHandle.longValue() != 0 ) { System.out.println("CLIENT_RealLoadPictureEx Success ChannelId : \n" + ChannelId); } else { System.err.println("CLIENT_RealLoadPictureEx Failed!" + ToolKits.getErrorCodePrint()); return null; } return m_hAttachHandle; }
-
刚开始测试大华的demo,
invoke
一直接受不到回传的参数。通过测试抓拍回调和监控回调事件,确认demo可以正常连通机器。 -
然后排查是否是智能订阅事件的问题,查看代码,发现订阅的所有事件(
NetSDKLib.EVENT_IVS_ALL
),但任然没有触发回调方法。 -
查看后台的日志记录,发现机器是有开门的日志记录的,所以应该是代码或者机器配问题。现在有两个思路,(1)代码问题(2)机器设置问题,先去网上查找源码并询问有经验的人,得到回调是子线程有可能被回收,所以要设置成静态单例,试过之后任然没有效果。
下面是静态单例的回调代码,但是任然没有取到回调参数。
private AnalyzerDataCB analyzerCallback = AnalyzerDataCB.getInstance(); //监听按钮,点击后智能订阅 @Override public void actionPerformed(ActionEvent arg0) { m_hAttachHandle = GateModule.realLoadPic(chnComboBox.getSelectedIndex(), analyzerCallback); if(m_hAttachHandle.longValue() != 0) { isAttach = true; attachBtn.setEnabled(false); detachBtn.setEnabled(true); } else { JOptionPane.showMessageDialog(null, ToolKits.getErrorCodeShow(), Res.string().getErrorMessage(), JOptionPane.ERROR_MESSAGE); } } //智能订阅的回调事件 private static class AnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack { private static AnalyzerDataCB instance; private BufferedImage gateBufferedImage = null; private AnalyzerDataCB(){} public static AnalyzerDataCB getInstance(){ if(instance == null){ synchronized(AnalyzerDataCB.class){ if(instance == null){ instance = new AnalyzerDataCB(); } } } return instace; } public int invoke(LLong lAnalyzerHandle, int dwAlarmType, Pointer pAlarmInfo, Pointer pBuffer, int dwBufSize, Pointer dwUser, int nSequence, Pointer reserved) { if (lAnalyzerHandle.longValue() == 0 || pAlarmInfo == null) { return -1; } File path = new File("./GateSnapPicture/"); if (!path.exists()) { path.mkdir(); } ///< 门禁事件 if(dwAlarmType == NetSDKLib.EVENT_IVS_ACCESS_CTL) { System.out.println("123"); DEV_EVENT_ACCESS_CTL_INFO msg = new DEV_EVENT_ACCESS_CTL_INFO(); ToolKits.GetPointerData(pAlarmInfo, msg); // 保存图片,获取图片缓存 String snapPicPath = path + "\\" + System.currentTimeMillis() + "GateSnapPicture.jpg"; // 保存图片地址 byte[] buffer = pBuffer.getByteArray(0, dwBufSize); ByteArrayInputStream byteArrInputGlobal = new ByteArrayInputStream(buffer); try { gateBufferedImage = ImageIO.read(byteArrInputGlobal); if(gateBufferedImage != null) { ImageIO.write(gateBufferedImage, "jpg", new File(snapPicPath)); } } catch (IOException e2) { e2.printStackTrace(); } // 图片以及门禁信息界面显示 EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); if (eventQueue != null) { eventQueue.postEvent( new AccessEvent(target, gateBufferedImage, msg)); } SwingUtilities.invokeLater(() -> { VideoPlayerDialog dialog = new VideoPlayerDialog(null); dialog.setVisible(true); }); } return 0; } } //调用大华的netsdk实现智能订阅事件 public static LLong realLoadPic(int ChannelId, NetSDKLib.fAnalyzerDataCallBack m_AnalyzerDataCB) { /** * 说明: * 通道数可以在有登录是返回的信息 m_stDeviceInfo.byChanNum 获取 * 下列仅订阅了0通道的智能事件. */ int bNeedPicture = 1; // 是否需要图片 LLong m_hAttachHandle = LoginModule.netsdk.CLIENT_RealLoadPictureEx(LoginModule.m_hLoginHandle, ChannelId, NetSDKLib.EVENT_IVS_ALL, bNeedPicture , m_AnalyzerDataCB , null , null); if( m_hAttachHandle.longValue() != 0 ) { System.out.println("CLIENT_RealLoadPictureEx Success ChannelId : \n" + ChannelId); } else { System.err.println("CLIENT_RealLoadPictureEx Failed!" + ToolKits.getErrorCodePrint()); return null; } return m_hAttachHandle; }
-
然后在网上查找的代码也都差不多。我认为可能是机器配置问题,在网上查找配置也没有得到什么有效的结果,然后就一个一个的设置进行排查,最终在隐私设置打开抓拍功能后,成功接收到回调。