华为sdc摄像机python调用c++sdk记录
大致流程就是:在c++先开发调用sdk的对应内容,正确返回结果之后,用vc编写dll库,将需要的功能封装成1个dll库中的函数,最后在python中用ctypes调用这个函数,输入对应参数,实现在python中调用sdk的功能。
写在前头:这个华为sdk他不更新了,只是维护,所以可能有的功能不是很对,技术支持那边推荐用restful接口去调用,具体怎么调用可以参见我的其他文章。
目录
摘要
大致流程就是:在c++先开发调用sdk的对应内容,正确返回结果之后,用vc编写dll库,将需要的功能封装成1个dll库中的函数,最后在python中用ctypes调用这个函数,输入对应参数,实现在python中调用sdk的功能。
在c++中的准备
第一步,把华为sdk的库和依赖的dll放好。
我用的是vs2017
主要是以下几个步骤
1、把相关文件放到该放的位置
首先,创建新项目,我是在这个hwsdk文件夹下创建的
创建完成后点进去应该是这个界面,我的解决方案名字也是hwsdk
然后点进hwsdk文件夹,把从官网下载的32位的华为dll依赖全部放进去,要用32位的
注意这个里面还有HWPuSDK.h和HWPuSDK.lib,我们后面要用到,也要放进去
2、在vc里设置依赖
项目->属性->链接器->输入,在附加依赖项里面添加
3、加入头文件
我试着导入了几次都不行,我就自己新建了一个头文件,名字还叫HWPuSDK.h把里面内容拷贝过来。会出现几个问题:
一个是预编译头报错,直接删掉导入的include
一个是要导入#include <wtypes.h>这个头文件
4、设置合规
项目->属性->c/c++语言->是否合规选否,2017就可以了,2022最后输入参数char 和const char要强制类型转换
第二步、开发c++代码
c++写这个不难
#include <string>
#include <stdio.h>
#include "HWPuSDK.h"
#include <Windows.h>
//初始化函数--返回值0代表失败1代表成功
BOOL CamInit()
{
// 初始化标记1为成功0为失败
BOOL INIT_FLAG = IVS_PU_Init(3, NULL, 6060);
//判断初始化是否成功
if (INIT_FLAG)
{
printf("%s\n", "初始化sdk成功");
}
else
{
printf("%s\n", "初始化sdk失败");
//输出错误码
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "一般错误");
break;
case 5:
printf("%s\n", "SDK已被初始化");
break;
case 101:
printf("%s\n", "SDK初始化连接模式出错");
break;
case 102:
printf("%s\n", "SDK初始化本地IP出错");
break;
default:
printf("%s\n", "未知错误");
break;
}
}
return INIT_FLAG;
}
// 登录返回函数--返回正整数代表获得id返回其他代表失败
ULONG CamLogin(CHAR *ip, CHAR *user, CHAR *password)
{
//返回正整数id
ULONG login_id = IVS_PU_Login(ip, 6060, user, password);
if (login_id > 0)
{
printf("%s\n", "获得登录id成功");
}
else
{
printf("%s\n", "获得登录id失败");
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "一般错误");
break;
case 2:
printf("%s\n", "用户名或密码错误");
break;
case 4:
printf("%s\n", "SDK未初始化");
break;
case 6:
printf("%s\n", "SDK与设备版本不匹配");
break;
case 7:
printf("%s\n", "入参为空");
break;
case 10106:
printf("%s\n", "SDK仍为初始密码,建议尽快修改");
break;
default:
printf("%s\n", "未知错误");
break;
}
}
return login_id;
}
void procMetaData(PU_META_DATA *pstMetaData)
{
UINT SpeopleNum = 0;
UINT peopleNum = 0;
LONGLONG time_offset = 0;
printf("%s%d%s\n", "共有", pstMetaData->usValidNumber, "个有效数目");
for (UINT uIndex = 0; uIndex < pstMetaData->usValidNumber; ++uIndex)
{
//printf("%d\n", pstMetaData->pstMetaUserData[uIndex].eType);
// 标记数据类型
switch (pstMetaData->pstMetaUserData[uIndex].eType)
{
case TARGET_TYPE: //target类型,当前用于区分人脸后处理抠图和人脸识别以及人脸识别多机协同
printf("数据类型为target类型\n");
break;
case 0x07000904: //离岗监测--岗位人数
SpeopleNum = pstMetaData->pstMetaUserData[uIndex].unMetaData.uIntValue;
printf("离岗监测--应有岗位人数%d\n", SpeopleNum);
break;
case 0x07000905: //离岗监测--在岗人数
peopleNum = pstMetaData->pstMetaUserData[uIndex].unMetaData.uIntValue;
printf("离岗监测--在岗人数%d\n", peopleNum);
break;
//case 0x08000085: //夏令时偏移时间
// time_offset = pstMetaData->pstMetaUserData[uIndex].unMetaData.longlongValue;
// printf("夏令时偏移时间%l64d\n", time_offset);
default:
break;
}
}
}
//实况回调函数
void CALLBACK fRealDataCallBack(CHAR *szBuffer, LONG lSize, VOID *pUsrData)
{
BOOL bRet = PU_FALSE;
//第二层元数据TYPE
PU_META_DATA *pstMetaTargetData = NULL;
bRet = IVS_User_GetMetaData(szBuffer, lSize, TARGET, &pstMetaTargetData);
if ((PU_TRUE == bRet) && (NULL != pstMetaTargetData))
{
//printf("%s%d%s\n", "数据长度为", lSize, "字节");
procMetaData(pstMetaTargetData);
IVS_User_FreeMetaData(&pstMetaTargetData);
}
}
//实况函数
ULONG Real(ULONG id)
{
//结构体赋值
PU_REAL_PLAY_INFO_S stRealPlayInfo = {0};
//通道号
stRealPlayInfo.ulChannelId = 101;
//传输类型
stRealPlayInfo.enProtocolType = PU_PROTOCOL_TYPE_TCP;
//码流类型
stRealPlayInfo.enStreamType = PU_VIDEO_MAIN_STREAM;
//保活
stRealPlayInfo.bKeepLive = TRUE;
//码流加密方式
stRealPlayInfo.enMediaCryptoType = PU_MEDIA_CRYPTO_NONE;
//数据类型
stRealPlayInfo.enVideoType = PU_VIDEO_TYPE_META;
//媒体回调类型
stRealPlayInfo.enMediaCallbackType = PU_MEDIA_CALLBACK_TYPE_META_FRAME;
//元数据返回标记位置
stRealPlayInfo.szReserved[22] = 1;
//只返回检测框内容
stRealPlayInfo.szReserved[23] = PU_METADATA_REQUEST_REST;
//返回元数据时句柄为空
stRealPlayInfo.hPlayWnd = NULL;
//调用实时预览函数
ULONG real_id = IVS_PU_RealPlay(id, &stRealPlayInfo, fRealDataCallBack, NULL);
if (real_id > 0)
{
printf("%s\n", "获得实时播放id成功");
}
else
{
printf("%s\n", "获得实时播放id失败");
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "一般错误");
break;
case 4:
printf("%s\n", "SDK未初始化");
break;
case 9:
printf("%s\n", "网络连接错误");
break;
case 10:
printf("%s\n", "发送消息超时");
break;
case 11:
printf("%s\n", "接收消息超时");
case 15:
printf("%s\n", "接收消息超时");
break;
case 106:
printf("%s\n", "错误的用户ID号");
break;
case 137:
printf("%s\n", "播放库函数调用出错");
break;
default:
printf("%s\n", "未知错误");
break;
}
}
return real_id;
}
//程序入口
int main()
{
//初始化变量
CHAR *ip = "ip";
CHAR *user = "user";
CHAR *password = "password";
//初始化sdk
CamInit();
//获得登录id
ULONG id = CamLogin(ip, user, password);
//实时数据返回
Real(id);
while (1)
{
Sleep(1 * 60000);
printf("%s\n", "程序运行");
}
}
以离岗监测为例子,就是这样写的内容。返回的回调函数的内容需要对着sdk的文档去获得回调函数返回的数据类型,具体返回的含义要对着TLV全网数据格式对照文档去看。
新建dll项目
新建一个hwdll解决项目,项目类型是dll库类型啊,别选错了
然后还是把哪些dll和lib放到对应的跟目录下
这次把这个函数功能当做导出函数
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <string>
#include <stdio.h>
#include "HWPuSDK.h"
#include <Windows.h>
//初始化函数--返回值0代表失败1代表成功
BOOL CamInit()
{
// 初始化标记1为成功0为失败
BOOL INIT_FLAG = IVS_PU_Init(3, NULL, 6060);
//判断初始化是否成功
if (INIT_FLAG)
{
printf("%s\n", "init sdk success");
}
else
{
printf("%s\n", "init sdk failed");
//输出错误码
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "common error");
break;
case 5:
printf("%s\n", "SDK has been initialed");
break;
case 101:
printf("%s\n", "SDK init connection mode error");
break;
case 102:
printf("%s\n", "SDK init local IP error");
break;
default:
printf("%s\n", "unknown error");
break;
}
}
return INIT_FLAG;
}
// 登录返回函数--返回正整数代表获得id返回其他代表失败
ULONG CamLogin(CHAR *ip, CHAR *user, CHAR *password)
{
//返回正整数id
ULONG login_id = IVS_PU_Login(ip, 6060, user, password);
if (login_id > 0)
{
printf("%s\n", "get login id success");
}
else
{
printf("%s\n", "get login id failed");
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "common error");
break;
case 2:
printf("%s\n", "username or password error");
break;
case 4:
printf("%s\n", "SDK not init");
break;
case 6:
printf("%s\n", "SDK version not match equipment");
break;
case 7:
printf("%s\n", "params is NULL");
break;
case 10106:
printf("%s\n", "SDK password is init,please change");
break;
default:
printf("%s\n", "unknown error");
break;
}
}
return login_id;
}
void procMetaData(PU_META_DATA *pstMetaData)
{
UINT SpeopleNum = 0;
UINT peopleNum = 0;
LONGLONG time_offset = 0;
//printf("%s%d%s\n", "共有", pstMetaData->usValidNumber, "个有效数目");
for (UINT uIndex = 0; uIndex < pstMetaData->usValidNumber; ++uIndex)
{
//printf("%d\n", pstMetaData->pstMetaUserData[uIndex].eType);
// 标记数据类型
switch (pstMetaData->pstMetaUserData[uIndex].eType)
{
case TARGET_TYPE: //target类型,当前用于区分人脸后处理抠图和人脸识别以及人脸识别多机协同
//printf("数据类型为target类型\n");
break;
case 0x07000904: //离岗监测--岗位人数
SpeopleNum = pstMetaData->pstMetaUserData[uIndex].unMetaData.uIntValue;
printf("%s%d%s\n", "should have ", SpeopleNum, " people working");
break;
case 0x07000905: //离岗监测--在岗人数
peopleNum = pstMetaData->pstMetaUserData[uIndex].unMetaData.uIntValue;
printf("%s%d%s\n", "now have ", peopleNum, " people working");
break;
//case 0x08000085: //夏令时偏移时间
// time_offset = pstMetaData->pstMetaUserData[uIndex].unMetaData.longlongValue;
// printf("夏令时偏移时间%l64d\n", time_offset);
default:
break;
}
}
}
//实况回调函数
void CALLBACK fRealDataCallBack(CHAR *szBuffer, LONG lSize, VOID *pUsrData)
{
BOOL bRet = PU_FALSE;
//第二层元数据TYPE
PU_META_DATA *pstMetaTargetData = NULL;
bRet = IVS_User_GetMetaData(szBuffer, lSize, TARGET, &pstMetaTargetData);
if ((PU_TRUE == bRet) && (NULL != pstMetaTargetData))
{
//printf("%s%d%s\n", "数据长度为", lSize, "字节");
procMetaData(pstMetaTargetData);
IVS_User_FreeMetaData(&pstMetaTargetData);
}
}
//实况函数
ULONG Real(ULONG id)
{
//结构体赋值
PU_REAL_PLAY_INFO_S stRealPlayInfo = { 0 };
//通道号
stRealPlayInfo.ulChannelId = 101;
//传输类型
stRealPlayInfo.enProtocolType = PU_PROTOCOL_TYPE_TCP;
//码流类型
stRealPlayInfo.enStreamType = PU_VIDEO_MAIN_STREAM;
//保活
stRealPlayInfo.bKeepLive = TRUE;
//码流加密方式
stRealPlayInfo.enMediaCryptoType = PU_MEDIA_CRYPTO_NONE;
//数据类型
stRealPlayInfo.enVideoType = PU_VIDEO_TYPE_META;
//媒体回调类型
stRealPlayInfo.enMediaCallbackType = PU_MEDIA_CALLBACK_TYPE_META_FRAME;
//元数据返回标记位置
stRealPlayInfo.szReserved[22] = 1;
//只返回检测框内容
stRealPlayInfo.szReserved[23] = PU_METADATA_REQUEST_REST;
//返回元数据时句柄为空
stRealPlayInfo.hPlayWnd = NULL;
//调用实时预览函数
ULONG real_id = IVS_PU_RealPlay(id, &stRealPlayInfo, fRealDataCallBack, NULL);
if (real_id > 0)
{
printf("%s\n", "get realplay id success");
}
else
{
printf("%s\n", "get realplay id failed");
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "common error");
break;
case 4:
printf("%s\n", "SDK not init");
break;
case 9:
printf("%s\n", "connection error");
break;
case 10:
printf("%s\n", "message send timeout");
break;
case 11:
printf("%s\n", "message get timeout");
case 15:
printf("%s\n", "message get timeout");
break;
case 106:
printf("%s\n", "wrong user id");
break;
case 137:
printf("%s\n", "function use error");
break;
default:
printf("%s\n", "unknown error");
break;
}
}
return real_id;
}
extern "C" __declspec(dllexport) int lgjc(CHAR *ip, CHAR *user, CHAR *password)
{
//初始化变量
//CHAR *ip = ip;
//CHAR *user = "admin";
//CHAR *password = "zjkjc123";
//初始化sdk
CamInit();
//获得登录id
ULONG id = CamLogin(ip, user, password);
//实时数据返回
int real_id = Real(id);
return real_id;
//while (1)
//{
// Sleep(1 * 60000);
// printf("%s\n", "程序运行");
//}
}
这就好了,点击生成。就会在项目跟目录下的debug生成对应的dll和lib文件。这个就是我们要的。
pyhon方面的准备
hwsdk只能用32位的sdk,所以python解释器也要是32位的
创建一个32位的环境3.6
设置这个
set CONDA_FORCE_32BIT=1
创建环境
我创建了3.6的环境,据说别的不稳健
改回来
set CONDA_FORCE_32BIT=0
好,接下来用ctypes就行了
import ctypes
import os
import time
from ctypes import wintypes
import struct
import _ctypes
# 加载sdk
# 获得当前目录
cur_path = os.getcwd()
# 定位到lib文件夹
dllPath = os.path.join(cur_path, "lib")
# 更改工作目录到指定目录
os.chdir(dllPath)
# 导入dll 文件夹中其他dll是相关依赖
hw_dll = ctypes.cdll.LoadLibrary('hwdll.dll')
print('get dll success!')
ip = ctypes.c_char_p(b'ip')
acc = ctypes.c_char_p(b'user')
passa = ctypes.c_char_p(b'password')
a = hw_dll.lgjc(ip, acc, passa)
print(a)
while True:
time.sleep(1)
我的工作目录,里面也是添加了所有的dll依赖。
更多推荐
所有评论(0)