Hi3531 Onvif+Gosap自动搜索IP_Discovery实现
生成ONVIF的框架代码
可以参考这章海思[Hi3531]onvif协议实现基于gsoap和openssl
只是实现IP自动搜索还要添加一个remotediscovery.wsdl文件去生成onvif框架代码
附上关键代码
自动搜索IP
- 主要代码
soap_init(&soap);
char Mediaddr[256] = "";
char profile[256] = "";
char ip[128] = "";
HI_S32 i,j;
HI_S32 client_port,client_port2;
struct _tds__GetCapabilities req;
struct _tds__GetCapabilitiesResponse rep;
struct wsdd__ProbeType wreq;
struct __wsdd__ProbeMatches wresp;
struct wsdd__ScopesType sScope;
struct SOAP_ENV__Header header;
char guid_string[100];
soap.recv_timeout = 5;
soap_default_SOAP_ENV__Header(&soap,&header);
header.wsa__MessageID = guid_string;
header.wsa__To= "urn:schemas-xmlsoap-org:ws:2005:04:discovery";
header.wsa__Action= "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
soap.header = &header;
//先填充头部,一般按我这个填就好
soap_default_wsdd__ScopesType(&soap, &sScope);
sScope.__item = "";
soap_default_wsdd__ProbeType(&soap, &req);
wreq.Scopes = &sScope;
wreq.Types = "";
result = soap_send___wsdd__Probe(&soap, "soap.udp://239.255.255.250:3702", NULL, &req);
do{
result = soap_recv___wsdd__ProbeMatches(&soap, &wresp);
if (soap.error)
{
printf("soap error:%d---%s",soap.error,*soap_faultstring(&soap));
result = soap.error;
break;
}
else
{
printf("wsdd:UriListType:%s\n",wresp.wsdd__ProbeMatches->ProbeMatch->XAddrs);
HI_S8 * camera_ip = wresp.wsdd__ProbeMatches->ProbeMatch->XAddrs + 7;
//地址偏移获取ip地址的起始地址
camera_ip = strtok(camera_ip,"/");
//分割字符串返回准确ip地址
printf("ID-%d ip:%s\n",*vdec_num,camera_ip);
strcpy(stVdecSend[*vdec_num].ip,camera_ip);
//printf("-----------%d----------\n",__LINE__);
if(strstr(wresp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item,"Dahua"))
{
//这里是判断摄像头的厂家是大华还是海康威视
strcpy(stVdecSend[*vdec_num].company,"Dahua");
}
else if(strstr(wresp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item,"HIKVISION"))
{
strcpy(stVdecSend[*vdec_num].company,"HIKVISION");
}
//printf("-----------%d----------\n",__LINE__);
printf("----------ip:%s,company:%s------------\n",stVdecSend[*vdec_num].ip,stVdecSend[*vdec_num].company);
(*vdec_num)++;
}
}while(1);
soap_destroy(&soap); // clean up class instances
soap_end(&soap); // clean up everything and close socket, // userid and passwd were deallocated
soap_done(&soap); // close master socket and detach context
PTZ的实现
- 获取摄像头PTZ功能的操作地址
//这个是设备地址,通过它可以获得ptz和imaging的操作地址
sprintf(endpoint, "http://%s/onvif/device_service", pstVdecSend->ip);
//获取PTZ操作地址
soap_call___tds__GetCapabilities(&soap, endpoint, NULL, &req, &rep);
//req和rep分别是发送结构体,和接受结构体
if (soap.error)
{
printf("[%s][%d]--->>> soap result: %d, %s, %s\n", __func__, __LINE__,
soap.error, *soap_faultcode(&soap),
*soap_faultstring(&soap));
}
else
{
printf("get capability success\n");
printf("PTZ_XAddr====%s\n",rep.Capabilities->PTZ->XAddr);
//获取成功在这里会成功返回
strcpy(PTZaddr, rep.Capabilities->PTZ->XAddr);
}
- 申请鉴权并获取配置文件
soap_wsse_add_UsernameTokenDigest(&soap, NULL, "admin", "jjoe0308");
//申请鉴权输入账号和密码
if (soap_call___ns1__GetProfiles(&soap, Mediaddr, NULL, &getProfiles, &getProfiles_response) == SOAP_OK)
{
printf("get profile succeed \n");
printf("profile:%s\n",getProfiles_response.Profiles[0].token);
strcpy(profile, getProfiles_response.Profiles[0].token);
//在返回的接受的结构体中去获取配置文件
}
else
{
printf("get profile failed \n");
printf("[%s][%d]--->>> soap result: %d, %s, %s\n", __func__, __LINE__,
soap.error, *soap_faultcode(&soap),
*soap_faultstring(&soap));
}
- 填充参数配置摄像头
tptz__RelativeMove.ProfileToken = profile;
//填充配置文件
tptz__RelativeMove.Translation->PanTilt->space = NULL;
tptz__RelativeMove.Translation->Zoom->space = NULL;
tptz__RelativeMove.Speed->PanTilt->space = NULL;
tptz__RelativeMove.Speed->Zoom->space = NULL;
//这四个一般为NULL
tptz__RelativeMove.Speed->PanTilt->x = 1;
tptz__RelativeMove.Speed->PanTilt->y = 1;
tptz__RelativeMove.Speed->Zoom->x = 1;
//上面给x,y,z的速度进行赋值,范围为0~1
tptz__RelativeMove.Translation=(struct tt__PTZVector*)soap_malloc(&soap,sizeof(struct tt__PTZVector));
tptz__RelativeMove.Translation->PanTilt = (struct tt__Vector2D*)soap_malloc(&soap,sizeof(struct tt__Vector2D));
tptz__RelativeMove.Translation->Zoom = (struct tt__Vector1D*)soap_malloc(&soap,sizeof(struct tt__Vector1D));
tptz__RelativeMove.Speed = (struct tt__PTZSpeed*)soap_malloc(&soap,sizeof(struct tt__PTZSpeed));
tptz__RelativeMove.Speed->PanTilt = (struct tt__Vector2D*)soap_malloc(&soap,sizeof(struct tt__Vector2D));
tptz__RelativeMove.Speed->Zoom = (struct tt__Vector1D*)soap_malloc(&soap,sizeof(struct tt__Vector1D));
//在这里我举个例子,设置x旋转(范围好像是-1~1)
//y是上下旋转,Z是焦距
tptz__RelativeMove.Translation->PanTilt->x = 1;
tptz__RelativeMove.Translation->PanTilt->y = 0;
tptz__RelativeMove.Translation->Zoom->x = 0;
//先鉴权,然后通过接口soap_call___tptz__RelativeMove设置摄像头参数,这个接口是相对运动接口,当然也有绝对运动和方向运动等等
soap_wsse_add_UsernameTokenDigest(&soap, NULL, "admin", "jjoe0308");
if (soap_call___tptz__RelativeMove(&soap, PTZaddr, NULL, &tptz__RelativeMove, &tptz__RelativeMoveResponse) == SOAP_OK)
{
printf("set ptz succeed \n");
printf("profile====%s\n", profile);
}
else
{
printf("get profile failed \n");
printf("[%s][%d]--->>> soap result: %d, %s, %s\n", __func__, __LINE__,
soap.error, *soap_faultcode(&soap),
*soap_faultstring(&soap));
}
//没有报错,成功运行一般就设置成功啦