转载自:https://blog.csdn.net/X_Jiner/article/details/76263771
球机都有自己的能力集,在要对球机发送调用命令前可以先获取设备能力集:
struct _tds__GetCapabilities Capabilities;
struct _tds__GetCapabilitiesResponse CapabilitiesResponse;
soap_wsse_add_UsernameTokenDigest(soap, NULL, username, password);//依然记得要在这之前加上鉴权操作
soap_call___tds__GetCapabilities(soap, DeviceXAddr, NULL, &Capabilities, &CapabilitiesResponse);
简单介绍PTZ表示的是什么:
- P:Pan水平转动角度
- T:Tilt垂直转动角度
- Z:缩放倍数
我用http的80端口传输时用的是PTZ绝对位置,范围是:P:(0,18000)T:(0,9000)z:(0-200)
。
而用onvif控球,其发送的是归一化后的绝对位置,P:(-1,1)T:(-1,1),Z:(0,1)
。在发送之前,将PTZ值先归一化即可。
AbsoluteMove
(绝对移动)命令soap_call___tptz__AbsoluteMove(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct _tptz__AbsoluteMove *tptz__AbsoluteMove, struct _tptz__AbsoluteMoveResponse *tptz__AbsoluteMoveResponse)
ContinuousMove
(沿某方向持续移动)命令soap_call___tptz__ContinuousMove(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct _tptz__ContinuousMove *tptz__ContinuousMove, struct _tptz__ContinuousMoveResponse *tptz__ContinuousMoveResponse);
RelativeMove
(相对移动)命令soap_call___tptz__RelativeMove(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct _tptz__RelativeMove *tptz__RelativeMove, struct _tptz__RelativeMoveResponse *tptz__RelativeMoveResponse);
绝对位置移动结构体SOAP_TYPE__tptz__AbsoluteMove
定义如下:
struct _tptz__AbsoluteMove {
/** Required element 'ProfileToken' of XSD type 'tt:ReferenceToken' */
char *ProfileToken;
/** Required element 'Position' of XSD type 'tt:PTZVector' */
struct tt__PTZVector *Position;//转动位置结构体成员
/** Optional element 'Speed' of XSD type 'tt:PTZSpeed' */
struct tt__PTZSpeed *Speed;//转动速度结构体成员
};
其中ProfileToken
是一个标识。可以用获取配置文件函数soap_call___trt__GetProfiles
获得,函数定义:
soap_call___trt__GetProfiles(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct _trt__GetProfiles *trt__GetProfiles, struct _trt__GetProfilesResponse *trt__GetProfilesResponse)
tt__PTZVector
为转动位置结构体:
struct tt__PTZVector {
/** Optional element 'tt:PanTilt' of XSD type 'tt:Vector2D' */
struct tt__Vector2D *PanTilt;//2维坐标结构体
/** Optional element 'tt:Zoom' of XSD type 'tt:Vector1D' */
struct tt__Vector1D *Zoom;//1维坐标结构体
};
tt__PTZSpeed
为转动速度结构体
struct tt__PTZSpeed {
/** Optional element 'tt:PanTilt' of XSD type 'tt:Vector2D' */
struct tt__Vector2D *PanTilt;
/** Optional element 'tt:Zoom' of XSD type 'tt:Vector1D' */
struct tt__Vector1D *Zoom;
};
tt__Vector2D
2维坐标:
struct tt__Vector2D {
/** Required attribute 'x' of XSD type 'xsd:float' */
float x; //Pan
/** Required attribute 'y' of XSD type 'xsd:float' */
float y; //Tilt
/** Optional attribute 'space' of XSD type 'xsd:anyURI' */
//URI:一般填入"http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace"即可
char *space;
};
tt__Vector1D
1维坐标:
struct tt__Vector1D {
/** Required attribute 'x' of XSD type 'xsd:float' */
float x;
/** Optional attribute 'space' of XSD type 'xsd:anyURI' */
char *space;
};
soap_p = soap_new();
soap_set_namespaces(soap_p, namespaces);
soap_wsse_add_UsernameTokenDigest(soap_p, NULL, "admin", "ADMIN123456");
struct _trt__GetProfiles req;
struct _trt__GetProfilesResponse rep;
soap_call___trt__GetProfiles(soap, MediaXAddr, NULL, &req, &rep);
if (rep.__sizeProfiles > 0)
{
// 分配缓存
(*profiles) = (struct tagProfile *)malloc(rep.__sizeProfiles * sizeof(struct tagProfile));
SOAP_ASSERT(NULL != (*profiles));
memset((*profiles), 0x00, rep.__sizeProfiles * sizeof(struct tagProfile));
}
for(i = 0; i < rep.__sizeProfiles; i++)
{
// 提取所有配置文件信息(我们所关心的)
struct tt__Profile *ttProfile = &rep.Profiles[i];
struct tagProfile *plst = &(*profiles)[i];
if (NULL != ttProfile->token)
{
// 配置文件Token
strncpy(plst->token, ttProfile->token, sizeof(plst->token) - 1);
}
}
在发送命令之前要为结构体_tptz__AbsoluteMove
和_tptz__AbsoluteMoveResponse
申请内存空间,其成员也需要分配内存:
soap_malloc(struct soap *soap, size_t n)
......//为结构体分配内存
然后填充结构体:
soap_default__tptz__AbsoluteMove(soap_p, &AbsoluteMove);//内存清零
soap_default__tptz__AbsoluteMoveResponse(soap_p, &AbsoluteMoveResponse);
AbsoluteMove.ProfileToken = (char*)soap_malloc(soap_p, 128);
strcpy(AbsoluteMove.ProfileToken, "Profile_1");//profiletoken
AbsoluteMove.Position->PanTilt = (tt__Vector2D*)soap_malloc(soap_p, sizeof(struct tt__Vector2D));
AbsoluteMove.Position->PanTilt->x = -0.9798;//P这里是随便写的几个数
AbsoluteMove.Position->PanTilt->y = 0.6768;//T
AbsoluteMove.Position->PanTilt->xmlns = (char*)soap_malloc(soap_p, 128);
strcpy(AbsoluteMove.Position->PanTilt->xmlns, "http://www.onvif.org/ver10/schema");
AbsoluteMove.Speed->PanTilt = (tt__Vector2D*)soap_malloc(soap_p, sizeof(struct tt__Vector2D));;
AbsoluteMove.Speed->PanTilt->x = 1.0;//P方向转速
AbsoluteMove.Speed->PanTilt->y = 1.0;//T方向转速
AbsoluteMove.Speed->PanTilt->xmlns = (char*)soap_malloc(soap_p, 128);
strcpy(AbsoluteMove.Speed->PanTilt->xmlns, "http://www.onvif.org/ver10/schema");
AbsoluteMove.Position->Zoom =(tt__Vector1D*) soap_malloc(soap_p, sizeof(struct tt__Vector1D));
AbsoluteMove.Position->Zoom->x = 0.7646;//Z
AbsoluteMove.Position->Zoom->xmlns = (char*)soap_malloc(soap_p, 128);
strcpy(AbsoluteMove.Position->Zoom->xmlns, "http://www.onvif.org/ver10/schema");
AbsoluteMove.Speed->Zoom = (tt__Vector1D*)soap_malloc(soap_p, sizeof(struct tt__Vector1D));;
AbsoluteMove.Speed->Zoom->x = 1.0;//Z缩放速度
AbsoluteMove.Speed->Zoom->xmlns = (char*)soap_malloc(soap_p, 128);
strcpy(AbsoluteMove.Speed->Zoom->xmlns, "http://www.onvif.org/ver10/schema");
soap_call___tptz__AbsoluteMove(soap_p, ball_onvifserver, NULL, &AbsoluteMove, &AbsoluteMoveResponse);
soap_destroy(soap_p);
soap_end(soap_p);
soap_done(soap_p);