好久没写博客了,最近做一个项目,需要直接对接海康摄像头,调用海康的SDK。这个项目原来是C/S模式单机版,改版后是B/S模式,调用SDK就比较麻烦了。

首先,还看的SDK分了好几个版本,至少常用服务器来说有windows或者linux(centos),甚至可能是麒麟。那么问题来了,从官网提供的例子来看,调用的库在不同操作系统上不一样,不能一套代码发布在2个平台上。另外就是很多时候大家开发的环境是windows,而正式部署一般是linux的服务器,这就导致windows调好的代码在正式环境不一定能正常。

官网提供的例子来看,首先,linux版本没有c#的例子,用java,部署很麻烦,主要是库文件的存放路径配置,写了一堆说明。然后,c#用的是winform,要改成B/S模式有些还是不太适用的。

讲了这么多,相信很多程序员还是想一套代码能够搞定一切,免得windows来一个版本,linux来一个版本,维护也麻烦。现在.net core也是支持跨平台的,而且部署起来也很简单,不管是windows还是linux服务器,所以,基于.net core3.1的基础上将海康的例子改了下,变成网络可以调用的api接口,给大家提供一个解决方案。

第一步,自己去官网下载海康的sdk包,windows和linux的都要下载,这里我就不多说啥了;

第二步,创建一个webapi项目,基于.net core3.1平台;

第三步,海康的CHCNetSDK.cs类,复制到自己项目里,然后多复制2个,把复制的2个类分别改名为WindowsCHCNetSDK和LinuxCHCNetSDK,当然,代码也需要改造下:

(1)把WindowsCHCNetSDK和LinuxCHCNetSDK里的常量、结构体、委托的定义全部删掉,只留API申明,就比如这样:

(2)删除代码后,API申明有些就会报错,把这个对象引用指向CHCNetSDK类,也就是像这么改:

[DllImport(HCNetSDK)]
public static extern bool NET_DVR_SetExceptionCallBack_V30(uint nMessage, IntPtr hWnd, CHCNetSDK.EXCEPYIONCALLBACK fExceptionCallBack, IntPtr pUser);

(3)CHCNetSDK类加一句代码,用来识别当前的系统类型(OSPlatform里还有个FreeBSD和OSX就不考虑了,应该没人会用苹果系统做服务器吧!!):

private static bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

(4)CHCNetSDK类里的API申明全部按如下改法改一遍:

public static bool NET_DVR_Init()
{if (isWindows){return WindowsCHCNetSDK.NET_DVR_Init();}return LinuxCHCNetSDK.NET_DVR_Init();
}

这样,直接调用NET_DVR_Init()方法,程序就可以自动按平台来选择引用的类库了。

SDK改好了,还需要再改一些结构体,不然你程序运行,可能就会有像是下面这个错误:加载类型“WIFI_AUTH_PARAM”,因为它在 0 偏移位置处包含一个对象字段,该字段已由一个非对象字段不正确地对齐或重叠。

这个错误也比较好解决,只需要把接口体头部的LayoutKind.Explicit改为LayoutKind.Auto就好了,就像是这样:

[StructLayoutAttribute(LayoutKind.Auto)]
public struct WIFI_AUTH_PARAM
{public UNION_EAP_TTLS EAP_TTLS;//WPA-enterprise/WPA2-enterpris模式适用public UNION_EAP_PEAP EAP_PEAP; //WPA-enterprise/WPA2-enterpris模式适用public UNION_EAP_TLS EAP_TLS;
}

当然,不止这一处,全文搜下LayoutKind.Explicit,全部改了就好了。

都改好了,那么这个SDK的方法就可以通用了。下面我们就写个API接口来试试,我这里用按时间下载文件的接口来测试:

新建一个controller,然后编写接口如下:

[HttpGet("SaveByTime")]
public IActionResult SaveByTime(string ip, string userName, string password, int port = 8000, DateTime? startTime = null, DateTime? endTime = null, int recSecond = 20, int channelNum = 1)
{if (!CHCNetSDK.NET_DVR_Init()){return Ok(new { code = 998, msg = "NET_DVR_Init error!" });}DateTime now = DateTime.Now;DateTime start, end;end = endTime ?? DateTime.Now;if (!startTime.HasValue){start = end.AddSeconds(recSecond * -1);}else{start = startTime.Value;}Device device = HKHelper.GetDevice(ip, userName, password, port);if (device == null){return Ok(new { code = 999, msg = "NET_DVR_Login_V30 failed" });}if (device.DownHandle >= 0){return Ok(new { code = 8022, msg = "Downloading, please stop firstly!" });//正在下载,请先停止下载}CHCNetSDK.NET_DVR_PLAYCOND struDownPara = new CHCNetSDK.NET_DVR_PLAYCOND();struDownPara.dwChannel = (uint)channelNum; //通道号 Channel number  //设置下载的开始时间 Set the starting timestruDownPara.struStartTime.dwYear = (uint)start.Year;struDownPara.struStartTime.dwMonth = (uint)start.Month;struDownPara.struStartTime.dwDay = (uint)start.Day;struDownPara.struStartTime.dwHour = (uint)start.Hour;struDownPara.struStartTime.dwMinute = (uint)start.Minute;struDownPara.struStartTime.dwSecond = (uint)start.Second;//设置下载的结束时间 Set the stopping timestruDownPara.struStopTime.dwYear = (uint)end.Year;struDownPara.struStopTime.dwMonth = (uint)end.Month;struDownPara.struStopTime.dwDay = (uint)end.Day;struDownPara.struStopTime.dwHour = (uint)end.Hour;struDownPara.struStopTime.dwMinute = (uint)end.Minute;struDownPara.struStopTime.dwSecond = (uint)end.Second;string sVideoFileName = Guid.NewGuid().ToString("n");  //录像文件保存路径和文件名 the path and file name to save      sVideoFileName = Path.Combine("路径", sVideoFileName + ".mp4");device.DownHandle = CHCNetSDK.NET_DVR_GetFileByTime_V40(device.UserID, sVideoFileName, ref struDownPara);if (device.DownHandle < 0){uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();return Ok(new { code = iLastErr, msg = "NET_DVR_GetFileByTime_V40 failed" });}uint iOutValue = 0;if (!CHCNetSDK.NET_DVR_PlayBackControl_V40(device.DownHandle, CHCNetSDK.NET_DVR_PLAYSTART, IntPtr.Zero, 0, IntPtr.Zero, ref iOutValue)){uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();return Ok(new { code = iLastErr, msg = "NET_DVR_PLAYSTART failed" }); //下载控制失败,输出错误号}device.DownHandle = -1;return Ok(new { code = 0, data = sVideoFileName });
}

写好了,不要急着运行,把下载的海康开发文档的相关dll拷贝到运行目录下(正常来说是bin\Debug\netcoreapp3.1),这下可以运行了,启动后,你可以调用SaveByTime接口试下,有没发现成功了(前提当然是摄像头需要能够通过ip被访问到)。

如果成功,我们再把这个代码发布到linux服务器上试下(同理,摄像头需要能够通过ip被访问到),提醒下,你的保存路径别忘了改,linux可是没有cdef盘的说法!这里我使用的是docker部署,先来写个dockerfile文件:

# 基于.net core3.1镜像
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim
# 设置工作目录
WORKDIR /app
# 端口号
EXPOSE 80
# 复制文件
COPY . .
# 入口点
ENTRYPOINT ["dotnet", "HKSuo.dll"]

将发布的程序上传到服务器,还有这个dockerfile,再加上各种海康的sdk文件(so文件),像这样:

运行打包命令 "docker build -t hksdk:1.0.0 ."

成功后再运行"docker run -i -d -t --name=hksdk -p 80:80 --restart=always hksdk:1.0.0"启动这个容器。

这下你可以通过服务器地址再次访问刚才的接口,有没发现也是成功的!

好拉,这样就可以做到一套代码跨平台支持了,就是一开始要整理这个代码,确实是繁!!

另外,应该还有很多朋友,想实现实时预览视频把,这个百度下有一篇文章是这样的:

C# 实现海康摄像头在任意浏览器中预览_qq_31753779的博客-CSDN博客_c#海康摄像头两周以来一直研究海康视频在谷歌、火狐等浏览器中的显示问题。在今天终于有了一点小心得。发表出来,希望有问题或者其他建议的老师积极给我建议。在海康浏览器的平台中,因为他本身只支持在IE或者IE内核中显示,这种问题不能根本性的解决在多浏览器里面的问题,我在网上查找了IE-Tab在谷歌浏览器中显示,但是由于需要用户手动切换浏览模式,所以说用起来不是特别方便。后面研究了一下,可以通过海康PlantFor...https://blog.csdn.net/qq_31753779/article/details/82023916这个做法可以参考,这样就不用装插件了,我把也写成了API接口:

就是调用后,启动一个线程,按设定频率定时抓图,然后用websoket方法,定时将这张图推送给客户端就可以了。小伙伴们,可以不用考虑抓图和推送的延迟率,websocket你只管把图片读取出来推送给客户端就好,如果图片太长时间没更新,那就是摄像头断了,画面也就是卡住的感觉。

我用java写个websocket,主要代码就像这样:

@OnOpen
public void onOpen(@PathParam("deviceId") String deviceId, Session session) {deviceInfoService = applicationContext.getBean(TbDeviceInfoService.class);exceptionService = applicationContext.getBean(TbExceptionService.class);this.session = session;TbDeviceInfoVo device = deviceInfoService.getById(deviceId);if (device == null) {return;}try {String body = HttpRequest.get(String.format(SystemConfig.CameraUrl() + "camera/LiveView?ip=%s&userName=%s&password=%s",device.getIpaddr(), device.getLoginId(), device.getLoginPwd())).keepAlive(true).execute().body();if (StringUtils.isNotBlank(body)) {JSONObject jsonObject = JSON.parseObject(body);if(jsonObject.getInteger("code") == CodeEnum.SUCCESS){CameraSocketUtil.put(session.getId(), this, device.getIpaddr());}}}catch (Exception e){exceptionService.saveException("LiveViewHandle", "onOpen", e);}
}

CameraSocketUtil类里启动了一个线程,做定时推送:

public static void put(String key, LiveViewHandle liveViewHandle, String ip) {CameraSocketObject obj = new CameraSocketObject();obj.setSocket(liveViewHandle);obj.setIp(ip);if(!ipList.contains(ip)){ipList.add(ip);//创建图像输出线程Runner run = new Runner(ip);run.start();}webSocketMap.put(key, obj);
}
class Runner extends Thread {String ip;public Runner(String ip) {this.ip = ip;}@Overridepublic void run() {while (true) {try {String imgBase64Str = convertFileToBase64(SystemConfig.FilePath() + ip.replace(".", "") + ".jpg");List<LiveViewHandle> handles = CameraSocketUtil.getHandleByIp(ip);if(handles != null && handles.size() > 0){for(LiveViewHandle handle : handles){try {handle.sendMessage(imgBase64Str);}catch (Exception e){e.printStackTrace();}}}else{//没有需要推送的客户端,将线程结束break;}} catch (Exception e) {e.printStackTrace();}finally {sleep(500);}}}private void sleep(int millis) {try {Thread.sleep(millis);} catch (Exception e) {}}/*** 本地文件(图片、excel等)转换成Base64字符串** @param imgPath*/private static String convertFileToBase64(String imgPath) {byte[] data = null;// 读取图片字节数组try {InputStream in = new FileInputStream(imgPath);data = new byte[in.available()];in.read(data);in.close();} catch (IOException e) {e.printStackTrace();}// 对字节数组进行Base64编码,得到Base64编码的字符串BASE64Encoder encoder = new BASE64Encoder();String base64Str = encoder.encode(data);return base64Str;}
}

最后,我已经把整理好的代码上传了,有兴趣的朋友可以下载参考,地址是:

.netcore实现海康SDK跨平台兼容-C#文档类资源-CSDN下载.netcore实现对海康SDK的跨平台兼容,支持windows和linux平台,实现海康摄像头在更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/ziyouli/84996531注意,appSettings.json里有个SavePath,可以配置文件保存路径,windows和linux路径不同,只需要调整配置文件就可以啦。

在linux(CentOS7)下使用docker部署的时候,可能会出现SDK报错误29,大概提示为:“海康SDK注册失败,userId:-1,错误号:29”,这是因为so库调取失败造成的。但是这个错误并不是必然出现的,我在测试的时候就出现了一台可以,一台报错的情况。

如果报错,按以下步骤处理一次即可:

1. 将库文件拷贝到/usr/lib64/hklib(32位的拷贝到lib目录)下,然后在/etc/profile文件下增加该路径的环境变量,然后通过命令source /etc/profile让环境变量生效;

2. /etc/ld.so.conf 加上/hklib和子文件夹目录,再用ldconfig命令使配置生效;

这2步骤可以看参考下海康官网的使用说明进行操作,完成后修改下dockerfile,加上ENV LD_LIBRARY_PATH /usr/lib64/hklib这句;

最后用docker run启动的时候增加物理磁盘挂载:-v /usr/lib64/hklib:/usr/lib64/hklib即可。

海康摄像头SDK跨平台通用解决方案相关推荐

  1. 【海康摄像头】海康摄像头SDK下载与使用

    文章目录 一.海康摄像头SDK官网下载 二.海康摄像头SDK在WinForm/WPF中使用 三.常用接口函数,封装调用函数 一.海康摄像头SDK官网下载 1.进入海康ws官网,下载官网SDK和相关文档 ...

  2. 海康摄像头SDK开机启动第一个摄像头不显示问题

    问题描述: 采用Qt调用海康摄像头SDK显示视频,开机软件自启动后第一个摄像头不显示. 原因分析: 第一个摄像头首次启动的时候,不显示视频.软件关闭然后重新打开,所有摄像头都正常显示.尝试发现采用bB ...

  3. [转载]海康摄像头sdk与web教程

    [转载]海康摄像头sdk与web教程 原文地址:https://blog.csdn.net/qq_35583089/article/details/80631069 查看原文 感谢大佬的分享,以下为原 ...

  4. Java版基于springboot+maven海康摄像头sdk抓拍功能的二次开发

    相信在用Java开发海康摄像头的小袁袁都很苦恼官网给的SDK,官方的SDK中有demo,有文档,可那大多都是基于C写的文档,找了半天终于找到一个java版本的,进去一看还是用Jfream写的C/S版的 ...

  5. 海康摄像头Sdk的使用 java Demo(idea 车牌识别,报警监听)

    最近用到海康摄像头,起初遇到许多问题,发现网上没有比较直观的java demo,现在将其总结下,希望可以帮助大家 初步使用sdk 首先去官方下sdk:http://www.hikvision.com/ ...

  6. 海康摄像头SDK二次开发错误问题解决方案(一):2. 错误号64:NET_DVR_LOADPLAYERSDKFAILED 64 载入当前目录下 Player Sdk 出错

    错误号64:NET_DVR_LOADPLAYERSDKFAILED 64  载入当前目录下 Player Sdk 出错 分析: 该问题为解决错误107时间引出,问题应该在文件放置目录不对或者库文件内容 ...

  7. 海康摄像头SDK二次开发错误问题解决方案(三):3. 错误:提示如“HCNetSDK.dll”组件缺失,无法加载问题

    错误: 提示如"HCNetSDK.dll"组件缺失,无法加载问题 分析: MFC平台可能有bug,有时不能读取出"HCNetSDK.dll"文件: 解决: 可将 ...

  8. 数字摄像头java sdk_java海康摄像头SDK集成

    1.从官方下载SDK包 按照自己的环境下载 2.按照readme 将相关dll文件和HCNetSDK.java文件放入自己的项目 我这是把全部的dll文件都搬过来了 放到了自己项目根目录下面 3.ja ...

  9. 【目标识别】--【截图程序】海康摄像头sdk二次开发自动多摄像头截图程序

    目录 背景: 1.问题 2.截图程序自动化和多通道实现 3.摄像头参数灵活化 至此已经全部结束,运行程序可以看到 背景: 目标识别需要对每一帧图像进行检测,因此我们需要将摄像头获取的视频流转换成单帧图 ...

  10. 海康摄像头二次开发详解,包含海康摄像头登录、海康云台控制、视频下载等功能

    海康摄像头二次开发详解 准备 海康摄像头SDK开发下载路径: 开发过程中遇到的问题记录: 添加maven依赖 下面代码中会出现的实体类 CameraManage实体类: ControlDto实体类: ...

最新文章

  1. 电力巡检智能管控主站平台性能优化(一):数据采集及用户行为分析
  2. 2020 北京智源大会“云上”开幕, 中外顶尖学者畅想AI的下一个十年
  3. HTML中常用字符实体
  4. java中表示根号三_Java命名规范
  5. 漫画:程序员的社会地位
  6. linux df -h卡成狗
  7. android 无限旋转动画,android ——不停旋转动画
  8. antd权限管理_推荐6款超好看实用的管理后台模版
  9. realme Q5 Pro Vans联名版曝光:经典棋盘格图案设计 辨识度拉满
  10. LeetCode刷题——75. 颜色分类
  11. 【渝粤教育】电大中专职业应用写作 (2)_1作业 题库
  12. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 10 章 类型转换_10.5. UNION、CASE和相关结构...
  13. 自然语言处理(NLP)学习路线总结
  14. java基于springboot教学评价管理系统附源码
  15. 分区桌面 壁纸(正在做,常用,之后在做,临时存)
  16. qq空间进入游戏显示服务器拒绝,打开QQ空间出现ptlogin2.qq.com的解决方法大全
  17. 倒立摆控制系统matlab,单轴倒立摆控制系统设计及Matlab仿真毕业设计论文(资料4)...
  18. CleanMyMac X免费的c盘清理工具
  19. 手写深度学习之优化器(SGD、Momentum、Nesterov、AdaGrad、RMSProp、Adam)
  20. Linux系统之复制粘贴命令

热门文章

  1. 疯狂的程序员_《戴蓓会客厅》第13期|疯狂的程序员 三维家蔡志森的野心
  2. 灵悟礼品网上专卖店——分析类似项目的布局和商品的分类模式
  3. QT D:\Program Files (x86)\SogouInput\Components\
  4. APP开发流程,移动应用开发流程
  5. python在屏幕上画画,屏幕上的Python绘图
  6. jep 使用方法与简介
  7. 二叉树的四种遍历算法
  8. 关于Session过期和失效
  9. MATLAB显示中文乱码问题 MATLAB2016
  10. Talib技术因子详解(一)