생각보다 onvif 쪽 게시글에 방문하시는 분들이 많은 것 같아 여러가지 지식을 공유하려 한다.
물론 안드로이드 jni 기준이다!
나는 안드로이드에 onvif 라이브러리를 아래 github에 있는 코드를 포팅했다. 아래 코드는 c코드로 되어있다.
https://github.com/As772309423/onvif-server-with-rtsp/tree/a1545162ff9e12efcf303cf403cdc4e4ab90ecc8
나는 onvif client가 아닌 onvif server가 필요했기 때문!
구글에 onvif device manager 를 검색해서 맨 위에 뜨는 사이트에 들어가 프로그램을 다운 받으면, 내가 onvif server앱을 올린 단말 ip가 뜨게 된다. 해당 프로그램으로 ptz control이나 network setting 등.. 많은 기능을 컨트롤 할 수 있었다.
근데... 문제는 많은 기능들을 컨트롤 하기 위해 각 메세지가 단말로 들어올 때마다 일일이 처리를 해줘야 한다는 것이다 ㅠ.ㅠ
우선, PTZ 기능을 어떻게 컨트롤 하고, 어떻게 처리를 했는지 다뤄보려고 한다.
onvif device manager를 실행하면 아래 사진과 같이 내가 onvif server 앱을 올린 단말들이 뜨게 된다
이 중에 하나를 클릭하면 아래 사진과 같이 많은 기능들이 뜬다.!
여기서 NVT에 있는 PTZ control을 클릭해보면!! 아래 사진과 같이 RTSP가 실행되면서 그 위에 컨트롤 할 수 있는 여러 버튼들이 보인다.
사생활 보호를 위해.. 카메라를 손바닥으로 가렸다.
내가 설명할 기능은 위 사진에 빨간색 동그라미가 쳐진 PTZ 기능들이다.
위 라이브러리를 사용한다는 전제 하에 설명을 해보겠다.
//soapServer.cc
SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap) {
...
...
if (!soap_match_tag(soap, soap->tag, "tptz:ContinuousMove"))
return soap_serve___tptz__ContinuousMove(soap);
if (!soap_match_tag(soap, soap->tag, "tptz:Stop"))
return soap_serve___tptz__Stop(soap);
...
}
위와 같이 "tptz:ContinuousMove", "tptz:Stop" 을 추가해준다.
내가 갖고 있는 카메라 기준, Zoom 기능을 컨트롤 시 ContinuousMove 메세지, PT 기능을 컨트롤 시 ContinuousMove, Stop 메세지가 들어온다.
자 이제, soap_serve___tptz__ContinuousMove(), soap_serve___tptz__Stop() 함수를 정의해보겠다.
//soapServer.cc
...
...
SOAP_FMAC5 int SOAP_FMAC6 soap_serve___tptz__ContinuousMove(struct soap *soap) {
struct __tptz__ContinuousMove soap_tmp___tptz__ContinuousMove;
struct _tptz__ContinuousMoveResponse tptz__ContinuousMoveResponse;
soap_default__tptz__ContinuousMoveResponse(soap, &tptz__ContinuousMoveResponse);
soap_default___tptz__ContinuousMove(soap, &soap_tmp___tptz__ContinuousMove);
soap->encodingStyle = NULL;
if (!soap_get___tptz__ContinuousMove(soap, &soap_tmp___tptz__ContinuousMove, "-tptz:ContinuousMove", NULL))
return soap->error;
if (soap_body_end_in(soap)
|| soap_envelope_end_in(soap)
|| soap_end_recv(soap))
return soap->error;
soap->error = __tptz__ContinuousMove(soap, soap_tmp___tptz__ContinuousMove.tptz__ContinuousMove, &tptz__ContinuousMoveResponse);
if (soap->error)
return soap->error;
soap_serializeheader(soap);
soap_serialize__tptz__ContinuousMoveResponse(soap, &tptz__ContinuousMoveResponse);
if (soap_begin_count(soap))
return soap->error;
if (soap->mode & SOAP_IO_LENGTH)
{ if (soap_envelope_begin_out(soap)
|| soap_putheader(soap)
|| soap_body_begin_out(soap)
|| soap_put__tptz__ContinuousMoveResponse(soap, &tptz__ContinuousMoveResponse, "tptz:ContinuousMoveResponse", NULL)
|| soap_body_end_out(soap)
|| soap_envelope_end_out(soap))
return soap->error;
};
if (soap_end_count(soap)
|| soap_response(soap, SOAP_OK)
|| soap_envelope_begin_out(soap)
|| soap_putheader(soap)
|| soap_body_begin_out(soap)
|| soap_put__tptz__ContinuousMoveResponse(soap, &tptz__ContinuousMoveResponse, "tptz:ContinuousMoveResponse", NULL)
|| soap_body_end_out(soap)
|| soap_envelope_end_out(soap)
|| soap_end_send(soap))
return soap->error;
return soap_closesock(soap);
}
SOAP_FMAC5 int SOAP_FMAC6 soap_serve___tptz__Stop(struct soap *soap) {
struct __tptz__Stop soap_tmp___tptz__Stop;
struct _tptz__StopResponse tptz__StopResponse;
soap_default__tptz__StopResponse(soap, &tptz__StopResponse);
soap_default___tptz__Stop(soap, &soap_tmp___tptz__Stop);
soap->encodingStyle = NULL;
if (!soap_get___tptz__Stop(soap, &soap_tmp___tptz__Stop, "-tptz:Stop", NULL))
return soap->error;
if (soap_body_end_in(soap)
|| soap_envelope_end_in(soap)
|| soap_end_recv(soap))
return soap->error;
soap->error = __tptz__Stop(soap, soap_tmp___tptz__Stop.tptz__Stop, &tptz__StopResponse);
if (soap->error)
return soap->error;
soap_serializeheader(soap);
soap_serialize__tptz__StopResponse(soap, &tptz__StopResponse);
if (soap_begin_count(soap))
return soap->error;
if (soap->mode & SOAP_IO_LENGTH)
{ if (soap_envelope_begin_out(soap)
|| soap_putheader(soap)
|| soap_body_begin_out(soap)
|| soap_put__tptz__StopResponse(soap, &tptz__StopResponse, "tptz:StopResponse", NULL)
|| soap_body_end_out(soap)
|| soap_envelope_end_out(soap))
return soap->error;
};
if (soap_end_count(soap)
|| soap_response(soap, SOAP_OK)
|| soap_envelope_begin_out(soap)
|| soap_putheader(soap)
|| soap_body_begin_out(soap)
|| soap_put__tptz__StopResponse(soap, &tptz__StopResponse, "tptz:StopResponse", NULL)
|| soap_body_end_out(soap)
|| soap_envelope_end_out(soap)
|| soap_end_send(soap))
return soap->error;
return soap_closesock(soap);
}
위에 정의되어있는 다른 함수들과 똑같이 정의를 해줬다.
여기서 중요한건... 아래와 같은 __tptz__ContinuousMove, _tptz__ContinuousMoveResponse 구조체가 없을 수도 있고...
struct __tptz__ContinuousMove soap_tmp___tptz__ContinuousMove;
struct _tptz__ContinuousMoveResponse tptz__ContinuousMoveResponse;
또 아래와 같은 soap_default__tptz__ContinuousMoveResponse(..), soap_default___tptz__ContinuousMove 함수 등..이 없을 수도 있을 것이다.
soap_default__tptz__ContinuousMoveResponse(soap, &tptz__ContinuousMoveResponse);
soap_default___tptz__ContinuousMove(soap, &soap_tmp___tptz__ContinuousMove);
위와 같은 정보들은 github에 검색해보면 정말 많이 나온다!! 하지만 난 친절하게 코드를 공유해 주려 한다
//soapStub.h
#ifndef SOAP_TYPE__tptz__ContinuousMove
#define SOAP_TYPE__tptz__ContinuousMove (2047)
/* tptz:ContinuousMove */
struct _tptz__ContinuousMove
{
char *ProfileToken; /* required element of type tt:ReferenceToken */
struct tt__PTZSpeed *Velocity; /* required element of type tt:PTZSpeed */
LONG64 *Timeout; /* optional element of type xsd:duration */
};
#endif
#ifndef SOAP_TYPE__tptz__ContinuousMoveResponse
#define SOAP_TYPE__tptz__ContinuousMoveResponse (2048)
/* tptz:ContinuousMoveResponse */
struct _tptz__ContinuousMoveResponse
{
#ifdef WITH_NOEMPTYSTRUCT
char dummy; /* empty struct is a GNU extension */
#endif
};
#endif
#ifndef SOAP_TYPE___tptz__ContinuousMove
#define SOAP_TYPE___tptz__ContinuousMove (2164)
/* Operation wrapper: */
struct __tptz__ContinuousMove
{
struct _tptz__ContinuousMove *tptz__ContinuousMove; /* optional element of type tptz:ContinuousMove */
};
#endif
#ifndef SOAP_TYPE__tptz__Stop
#define SOAP_TYPE__tptz__Stop (1570)
/* tptz:Stop */
struct _tptz__Stop
{
char *ProfileToken; /* required element of type tt:ReferenceToken */
enum xsd__boolean *PanTilt; /* optional element of type xsd:boolean */
enum xsd__boolean *Zoom; /* optional element of type xsd:boolean */
};
#endif
#ifndef SOAP_TYPE__tptz__StopResponse
#define SOAP_TYPE__tptz__StopResponse (1571)
/* tptz:StopResponse */
struct _tptz__StopResponse
{
#ifdef WITH_NOEMPTYSTRUCT
char dummy; /* dummy member to enable compilation */
#endif
};
#endif
#ifndef SOAP_TYPE___tptz__Stop
#define SOAP_TYPE___tptz__Stop (2180)
/* Operation wrapper: */
struct __tptz__Stop
{
struct _tptz__Stop *tptz__Stop; /* optional element of type tptz:Stop */
};
#endif
//soapC.cc
...
...
SOAP_FMAC3 void SOAP_FMAC4 soap_default___tptz__ContinuousMove(struct soap *soap, struct __tptz__ContinuousMove *a)
{
(void)soap; (void)a; /* appease -Wall -Werror */
a->tptz__ContinuousMove = NULL;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize___tptz__ContinuousMove(struct soap *soap, const struct __tptz__ContinuousMove *a)
{
#ifndef WITH_NOIDREF
(void)soap; (void)a; /* appease -Wall -Werror */
soap_serialize_PointerTo_tptz__ContinuousMove(soap, &a->tptz__ContinuousMove);
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out___tptz__ContinuousMove(struct soap *soap, const char *tag, int id, const struct __tptz__ContinuousMove *a, const char *type)
{
(void)soap; (void)tag; (void)id; (void)type;
if (soap_out_PointerTo_tptz__ContinuousMove(soap, "tptz:ContinuousMove", -1, &a->tptz__ContinuousMove, ""))
return soap->error;
return SOAP_OK;
}
SOAP_FMAC3 struct __tptz__ContinuousMove * SOAP_FMAC4 soap_in___tptz__ContinuousMove(struct soap *soap, const char *tag, struct __tptz__ContinuousMove *a, const char *type)
{
size_t soap_flag_tptz__ContinuousMove = 1;
short soap_flag;
a = (struct __tptz__ContinuousMove *)soap_id_enter(soap, "", a, SOAP_TYPE___tptz__ContinuousMove, sizeof(struct __tptz__ContinuousMove), 0, NULL, NULL, NULL);
if (!a)
return NULL;
soap_default___tptz__ContinuousMove(soap, a);
for (soap_flag = 0;; soap_flag = 1)
{ soap->error = SOAP_TAG_MISMATCH;
if (soap_flag_tptz__ContinuousMove && soap->error == SOAP_TAG_MISMATCH)
if (soap_in_PointerTo_tptz__ContinuousMove(soap, "tptz:ContinuousMove", &a->tptz__ContinuousMove, ""))
{ soap_flag_tptz__ContinuousMove--;
continue;
}
if (soap->error == SOAP_TAG_MISMATCH)
if (soap_flag)
{ soap->error = SOAP_OK;
break;
}
if (soap_flag && soap->error == SOAP_NO_TAG)
break;
if (soap->error)
return NULL;
}
return a;
}
SOAP_FMAC3 int SOAP_FMAC4 soap_put___tptz__ContinuousMove(struct soap *soap, const struct __tptz__ContinuousMove *a, const char *tag, const char *type)
{
register int id = 0;
if (soap_out___tptz__ContinuousMove(soap, tag?tag:"-tptz:ContinuousMove", id, a, type))
return soap->error;
return SOAP_OK;
}
SOAP_FMAC3 struct __tptz__ContinuousMove * SOAP_FMAC4 soap_get___tptz__ContinuousMove(struct soap *soap, struct __tptz__ContinuousMove *p, const char *tag, const char *type)
{
if ((p = soap_in___tptz__ContinuousMove(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_default__tptz__ContinuousMoveResponse(struct soap *soap, struct _tptz__ContinuousMoveResponse *a)
{
(void)soap; (void)a; /* appease -Wall -Werror */
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize__tptz__ContinuousMoveResponse(struct soap *soap, const struct _tptz__ContinuousMoveResponse *a)
{
(void)soap; (void)a; /* appease -Wall -Werror */
#ifndef WITH_NOIDREF
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out__tptz__ContinuousMoveResponse(struct soap *soap, const char *tag, int id, const struct _tptz__ContinuousMoveResponse *a, const char *type)
{
(void)soap; (void)tag; (void)id; (void)a; (void)type; /* appease -Wall -Werror */
if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE__tptz__ContinuousMoveResponse), type))
return soap->error;
return soap_element_end_out(soap, tag);
}
SOAP_FMAC3 struct _tptz__ContinuousMoveResponse * SOAP_FMAC4 soap_in__tptz__ContinuousMoveResponse(struct soap *soap, const char *tag, struct _tptz__ContinuousMoveResponse *a, const char *type)
{
if (soap_element_begin_in(soap, tag, 0, type))
return NULL;
a = (struct _tptz__ContinuousMoveResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE__tptz__ContinuousMoveResponse, sizeof(struct _tptz__ContinuousMoveResponse), NULL, NULL, NULL, NULL);
if (!a)
return NULL;
soap_default__tptz__ContinuousMoveResponse(soap, a);
if (soap->body && !*soap->href)
{
for (;;)
{ soap->error = SOAP_TAG_MISMATCH;
if (soap->error == SOAP_TAG_MISMATCH)
soap->error = soap_ignore_element(soap);
if (soap->error == SOAP_NO_TAG)
break;
if (soap->error)
return NULL;
}
if (soap_element_end_in(soap, tag))
return NULL;
}
else
{ a = (struct _tptz__ContinuousMoveResponse *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE__tptz__ContinuousMoveResponse, SOAP_TYPE__tptz__ContinuousMoveResponse, sizeof(struct _tptz__ContinuousMoveResponse), 0, NULL, NULL);
if (soap->body && soap_element_end_in(soap, tag))
return NULL;
}
return a;
}
SOAP_FMAC3 struct _tptz__ContinuousMoveResponse * SOAP_FMAC4 soap_new__tptz__ContinuousMoveResponse(struct soap *soap, int n)
{
struct _tptz__ContinuousMoveResponse *p;
struct _tptz__ContinuousMoveResponse *a = (struct _tptz__ContinuousMoveResponse*)soap_malloc((soap), (n = (n < 0 ? 1 : n)) * sizeof(struct _tptz__ContinuousMoveResponse));
for (p = a; p && n--; p++)
soap_default__tptz__ContinuousMoveResponse(soap, p);
return a;
}
SOAP_FMAC3 int SOAP_FMAC4 soap_put__tptz__ContinuousMoveResponse(struct soap *soap, const struct _tptz__ContinuousMoveResponse *a, const char *tag, const char *type)
{
if (soap_out__tptz__ContinuousMoveResponse(soap, tag ? tag : "tptz:ContinuousMoveResponse", -2, a, type))
return soap->error;
return soap_putindependent(soap);
}
SOAP_FMAC3 struct _tptz__ContinuousMoveResponse * SOAP_FMAC4 soap_get__tptz__ContinuousMoveResponse(struct soap *soap, struct _tptz__ContinuousMoveResponse *p, const char *tag, const char *type)
{
if ((p = soap_in__tptz__ContinuousMoveResponse(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTo_tptz__ContinuousMove(struct soap *soap, struct _tptz__ContinuousMove *const*a)
{
#ifndef WITH_NOIDREF
if (!soap_reference(soap, *a, SOAP_TYPE__tptz__ContinuousMove))
soap_serialize__tptz__ContinuousMove(soap, *a);
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTo_tptz__ContinuousMoveResponse(struct soap *soap, const char *tag, int id, struct _tptz__ContinuousMoveResponse *const*a, const char *type)
{
id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE__tptz__ContinuousMoveResponse, NULL);
if (id < 0)
return soap->error;
return soap_out__tptz__ContinuousMoveResponse(soap, tag, id, *a, type);
}
SOAP_FMAC3 struct _tptz__ContinuousMoveResponse ** SOAP_FMAC4 soap_in_PointerTo_tptz__ContinuousMoveResponse(struct soap *soap, const char *tag, struct _tptz__ContinuousMoveResponse **a, const char *type)
{
if (soap_element_begin_in(soap, tag, 1, NULL))
return NULL;
if (!a)
if (!(a = (struct _tptz__ContinuousMoveResponse **)soap_malloc(soap, sizeof(struct _tptz__ContinuousMoveResponse *))))
return NULL;
*a = NULL;
if (!soap->null && *soap->href != '#')
{ soap_revert(soap);
if (!(*a = soap_in__tptz__ContinuousMoveResponse(soap, tag, *a, type)))
return NULL;
}
else
{
a = (struct _tptz__ContinuousMoveResponse **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE__tptz__ContinuousMoveResponse, sizeof(struct _tptz__ContinuousMoveResponse), 0, NULL);
if (soap->body && soap_element_end_in(soap, tag))
return NULL;
}
return a;
}
/*SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTo_tptz__ContinuousMoveResponse(struct soap *soap, struct _tptz__ContinuousMoveResponse *const*a, const char *tag, const char *type)
{
register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerTo_tptz__ContinuousMoveResponse);
if (soap_out_PointerTo_tptz__ContinuousMoveResponse(soap, tag?tag:"tptz:ContinuousMoveResponse", id, a, type))
return soap->error;
return soap_putindependent(soap);
}*/
SOAP_FMAC3 struct _tptz__ContinuousMoveResponse ** SOAP_FMAC4 soap_get_PointerTo_tptz__ContinuousMoveResponse(struct soap *soap, struct _tptz__ContinuousMoveResponse **p, const char *tag, const char *type)
{
if ((p = soap_in_PointerTo_tptz__ContinuousMoveResponse(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTo_tptz__ContinuousMove(struct soap *soap, const char *tag, int id, struct _tptz__ContinuousMove *const*a, const char *type)
{
id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE__tptz__ContinuousMove, NULL);
if (id < 0)
return soap->error;
return soap_out__tptz__ContinuousMove(soap, tag, id, *a, type);
}
SOAP_FMAC3 struct _tptz__ContinuousMove ** SOAP_FMAC4 soap_in_PointerTo_tptz__ContinuousMove(struct soap *soap, const char *tag, struct _tptz__ContinuousMove **a, const char *type)
{
if (soap_element_begin_in(soap, tag, 1, NULL))
return NULL;
if (!a)
if (!(a = (struct _tptz__ContinuousMove **)soap_malloc(soap, sizeof(struct _tptz__ContinuousMove *))))
return NULL;
*a = NULL;
if (!soap->null && *soap->href != '#')
{ soap_revert(soap);
if (!(*a = soap_in__tptz__ContinuousMove(soap, tag, *a, type)))
return NULL;
}
else
{ a = (struct _tptz__ContinuousMove **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE__tptz__ContinuousMove, sizeof(struct _tptz__ContinuousMove), 0, NULL);
if (soap->body && soap_element_end_in(soap, tag))
return NULL;
}
return a;
}
/*SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTo_tptz__ContinuousMove(struct soap *soap, struct _tptz__ContinuousMove *const*a, const char *tag, const char *type)
{
register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE_PointerTo_tptz__ContinuousMove);
if (soap_out_PointerTo_tptz__ContinuousMove(soap, tag?tag:"tptz:ContinuousMove", id, a, type))
return soap->error;
return soap_putindependent(soap);
}*/
SOAP_FMAC3 struct _tptz__ContinuousMove ** SOAP_FMAC4 soap_get_PointerTo_tptz__ContinuousMove(struct soap *soap, struct _tptz__ContinuousMove **p, const char *tag, const char *type)
{
if ((p = soap_in_PointerTo_tptz__ContinuousMove(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_default__tptz__ContinuousMove(struct soap *soap, struct _tptz__ContinuousMove *a)
{
(void)soap; (void)a; /* appease -Wall -Werror */
soap_default_tt__ReferenceToken(soap, &a->ProfileToken);
a->Velocity = NULL;
a->Timeout = NULL;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize__tptz__ContinuousMove(struct soap *soap, const struct _tptz__ContinuousMove *a)
{
#ifndef WITH_NOIDREF
(void)soap; (void)a; /* appease -Wall -Werror */
soap_serialize_tt__ReferenceToken(soap, &a->ProfileToken);
soap_serialize_PointerTott__PTZSpeed(soap, &a->Velocity);
soap_serialize_PointerToxsd__duration(soap, &a->Timeout);
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out__tptz__ContinuousMove(struct soap *soap, const char *tag, int id, const struct _tptz__ContinuousMove *a, const char *type)
{
(void)soap; (void)tag; (void)id; (void)type;
if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE__tptz__ContinuousMove), type))
return soap->error;
if (a->ProfileToken)
{ if (soap_out_tt__ReferenceToken(soap, "tptz:ProfileToken", -1, &a->ProfileToken, ""))
return soap->error;
}
else if (soap_element_nil(soap, "tptz:ProfileToken"))
return soap->error;
if (a->Velocity)
{ if (soap_out_PointerTott__PTZSpeed(soap, "tptz:Velocity", -1, &a->Velocity, ""))
return soap->error;
}
else if (soap_element_nil(soap, "tptz:Velocity"))
return soap->error;
if (soap_out_PointerToxsd__duration(soap, "tptz:Timeout", -1, &a->Timeout, ""))
return soap->error;
return soap_element_end_out(soap, tag);
}
SOAP_FMAC3 struct _tptz__ContinuousMove * SOAP_FMAC4 soap_in__tptz__ContinuousMove(struct soap *soap, const char *tag, struct _tptz__ContinuousMove *a, const char *type)
{
size_t soap_flag_ProfileToken = 1;
size_t soap_flag_Velocity = 1;
size_t soap_flag_Timeout = 1;
if (soap_element_begin_in(soap, tag, 0, type))
return NULL;
a = (struct _tptz__ContinuousMove *)soap_id_enter(soap, soap->id, a, SOAP_TYPE__tptz__ContinuousMove, sizeof(struct _tptz__ContinuousMove), 0, NULL, NULL, NULL);
if (!a)
return NULL;
soap_default__tptz__ContinuousMove(soap, a);
if (soap->body && !*soap->href)
{
for (;;)
{ soap->error = SOAP_TAG_MISMATCH;
if (soap_flag_ProfileToken && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
if (soap_in_tt__ReferenceToken(soap, "tptz:ProfileToken", &a->ProfileToken, "tt:ReferenceToken"))
{ soap_flag_ProfileToken--;
continue;
}
if (soap_flag_Velocity && soap->error == SOAP_TAG_MISMATCH)
if (soap_in_PointerTott__PTZSpeed(soap, "tptz:Velocity", &a->Velocity, "tt:PTZSpeed"))
{ soap_flag_Velocity--;
continue;
}
if (soap_flag_Timeout && soap->error == SOAP_TAG_MISMATCH)
if (soap_in_PointerToxsd__duration(soap, "tptz:Timeout", &a->Timeout, "xsd:duration"))
{ soap_flag_Timeout--;
continue;
}
if (soap->error == SOAP_TAG_MISMATCH)
soap->error = soap_ignore_element(soap);
if (soap->error == SOAP_NO_TAG)
break;
if (soap->error)
return NULL;
}
if (soap_element_end_in(soap, tag))
return NULL;
}
else
{ a = (struct _tptz__ContinuousMove *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE__tptz__ContinuousMove, 0, sizeof(struct _tptz__ContinuousMove), 0, NULL, NULL);
if (soap->body && soap_element_end_in(soap, tag))
return NULL;
}
if ((soap->mode & SOAP_XML_STRICT) && (soap_flag_ProfileToken > 0 || soap_flag_Velocity > 0))
{ soap->error = SOAP_OCCURS;
return NULL;
}
return a;
}
/*SOAP_FMAC3 int SOAP_FMAC4 soap_put__tptz__ContinuousMove(struct soap *soap, const struct _tptz__ContinuousMove *a, const char *tag, const char *type)
{
register int id = soap_embed(soap, (void*)a, NULL, 0, tag, SOAP_TYPE__tptz__ContinuousMove);
if (soap_out__tptz__ContinuousMove(soap, tag?tag:"tptz:ContinuousMove", id, a, type))
return soap->error;
return soap_putindependent(soap);
}*/
SOAP_FMAC3 struct _tptz__ContinuousMove * SOAP_FMAC4 soap_get__tptz__ContinuousMove(struct soap *soap, struct _tptz__ContinuousMove *p, const char *tag, const char *type)
{
if ((p = soap_in__tptz__ContinuousMove(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_default__tptz__StopResponse(struct soap *soap, struct _tptz__StopResponse *a)
{
(void)soap; (void)a; /* appease -Wall -Werror */
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize__tptz__StopResponse(struct soap *soap, const struct _tptz__StopResponse *a)
{
#ifndef WITH_NOIDREF
(void)soap; (void)a; /* appease -Wall -Werror */
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out__tptz__StopResponse(struct soap *soap, const char *tag, int id, const struct _tptz__StopResponse *a, const char *type)
{
(void)soap; (void)tag; (void)id; (void)type;
if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE__tptz__StopResponse), type))
return soap->error;
return soap_element_end_out(soap, tag);
}
SOAP_FMAC3 struct _tptz__StopResponse * SOAP_FMAC4 soap_in__tptz__StopResponse(struct soap *soap, const char *tag, struct _tptz__StopResponse *a, const char *type)
{
if (soap_element_begin_in(soap, tag, 0, type))
return NULL;
a = (struct _tptz__StopResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE__tptz__StopResponse, sizeof(struct _tptz__StopResponse), 0, NULL, NULL, NULL);
if (!a)
return NULL;
soap_default__tptz__StopResponse(soap, a);
if (soap->body && !*soap->href)
{
for (;;)
{ soap->error = SOAP_TAG_MISMATCH;
if (soap->error == SOAP_TAG_MISMATCH)
soap->error = soap_ignore_element(soap);
if (soap->error == SOAP_NO_TAG)
break;
if (soap->error)
return NULL;
}
if (soap_element_end_in(soap, tag))
return NULL;
}
else
{ a = (struct _tptz__StopResponse *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE__tptz__StopResponse, 0, sizeof(struct _tptz__StopResponse), 0, NULL, NULL);
if (soap->body && soap_element_end_in(soap, tag))
return NULL;
}
return a;
}
SOAP_FMAC3 int SOAP_FMAC4 soap_put__tptz__StopResponse(struct soap *soap, const struct _tptz__StopResponse *a, const char *tag, const char *type)
{
register int id = 0;
if (soap_out__tptz__StopResponse(soap, tag?tag:"tptz:StopResponse", id, a, type))
return soap->error;
return soap_putindependent(soap);
}
SOAP_FMAC3 struct _tptz__StopResponse * SOAP_FMAC4 soap_get__tptz__StopResponse(struct soap *soap, struct _tptz__StopResponse *p, const char *tag, const char *type)
{
if ((p = soap_in__tptz__StopResponse(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_default__tptz__Stop(struct soap *soap, struct _tptz__Stop *a)
{
(void)soap; (void)a; /* appease -Wall -Werror */
soap_default_tt__ReferenceToken(soap, &a->ProfileToken);
a->PanTilt = NULL;
a->Zoom = NULL;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize__tptz__Stop(struct soap *soap, const struct _tptz__Stop *a)
{
#ifndef WITH_NOIDREF
(void)soap; (void)a; /* appease -Wall -Werror */
soap_serialize_tt__ReferenceToken(soap, &a->ProfileToken);
soap_serialize_PointerToxsd__boolean(soap, &a->PanTilt);
soap_serialize_PointerToxsd__boolean(soap, &a->Zoom);
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out__tptz__Stop(struct soap *soap, const char *tag, int id, const struct _tptz__Stop *a, const char *type)
{
(void)soap; (void)tag; (void)id; (void)type;
if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE__tptz__Stop), type))
return soap->error;
if (a->ProfileToken)
{ if (soap_out_tt__ReferenceToken(soap, "tptz:ProfileToken", -1, &a->ProfileToken, ""))
return soap->error;
}
else if (soap_element_nil(soap, "tptz:ProfileToken"))
return soap->error;
if (soap_out_PointerToxsd__boolean(soap, "tptz:PanTilt", -1, &a->PanTilt, ""))
return soap->error;
if (soap_out_PointerToxsd__boolean(soap, "tptz:Zoom", -1, &a->Zoom, ""))
return soap->error;
return soap_element_end_out(soap, tag);
}
SOAP_FMAC3 struct _tptz__Stop * SOAP_FMAC4 soap_in__tptz__Stop(struct soap *soap, const char *tag, struct _tptz__Stop *a, const char *type)
{
size_t soap_flag_ProfileToken = 1;
size_t soap_flag_PanTilt = 1;
size_t soap_flag_Zoom = 1;
if (soap_element_begin_in(soap, tag, 0, type))
return NULL;
a = (struct _tptz__Stop *)soap_id_enter(soap, soap->id, a, SOAP_TYPE__tptz__Stop, sizeof(struct _tptz__Stop), 0, NULL, NULL, NULL);
if (!a)
return NULL;
soap_default__tptz__Stop(soap, a);
if (soap->body && !*soap->href)
{
for (;;)
{ soap->error = SOAP_TAG_MISMATCH;
if (soap_flag_ProfileToken && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG))
if (soap_in_tt__ReferenceToken(soap, "tptz:ProfileToken", &a->ProfileToken, "tt:ReferenceToken"))
{ soap_flag_ProfileToken--;
continue;
}
if (soap_flag_PanTilt && soap->error == SOAP_TAG_MISMATCH)
if (soap_in_PointerToxsd__boolean(soap, "tptz:PanTilt", &a->PanTilt, "xsd:boolean"))
{ soap_flag_PanTilt--;
continue;
}
if (soap_flag_Zoom && soap->error == SOAP_TAG_MISMATCH)
if (soap_in_PointerToxsd__boolean(soap, "tptz:Zoom", &a->Zoom, "xsd:boolean"))
{ soap_flag_Zoom--;
continue;
}
if (soap->error == SOAP_TAG_MISMATCH)
soap->error = soap_ignore_element(soap);
if (soap->error == SOAP_NO_TAG)
break;
if (soap->error)
return NULL;
}
if (soap_element_end_in(soap, tag))
return NULL;
}
else
{ a = (struct _tptz__Stop *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE__tptz__Stop, 0, sizeof(struct _tptz__Stop), 0, NULL, NULL);
if (soap->body && soap_element_end_in(soap, tag))
return NULL;
}
if ((soap->mode & SOAP_XML_STRICT) && (soap_flag_ProfileToken > 0))
{ soap->error = SOAP_OCCURS;
return NULL;
}
return a;
}
SOAP_FMAC3 int SOAP_FMAC4 soap_put__tptz__Stop(struct soap *soap, const struct _tptz__Stop *a, const char *tag, const char *type)
{
register int id = 0;
if (soap_out__tptz__Stop(soap, tag?tag:"tptz:Stop", id, a, type))
return soap->error;
return soap_putindependent(soap);
}
SOAP_FMAC3 struct _tptz__Stop * SOAP_FMAC4 soap_get__tptz__Stop(struct soap *soap, struct _tptz__Stop *p, const char *tag, const char *type)
{
if ((p = soap_in__tptz__Stop(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_default___tptz__Stop(struct soap *soap, struct __tptz__Stop *a)
{
(void)soap; (void)a; /* appease -Wall -Werror */
a->tptz__Stop = NULL;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize___tptz__Stop(struct soap *soap, const struct __tptz__Stop *a)
{
#ifndef WITH_NOIDREF
(void)soap; (void)a; /* appease -Wall -Werror */
soap_serialize_PointerTo_tptz__Stop(soap, &a->tptz__Stop);
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out___tptz__Stop(struct soap *soap, const char *tag, int id, const struct __tptz__Stop *a, const char *type)
{
(void)soap; (void)tag; (void)id; (void)type;
if (soap_out_PointerTo_tptz__Stop(soap, "tptz:Stop", -1, &a->tptz__Stop, ""))
return soap->error;
return SOAP_OK;
}
SOAP_FMAC3 struct __tptz__Stop * SOAP_FMAC4 soap_in___tptz__Stop(struct soap *soap, const char *tag, struct __tptz__Stop *a, const char *type)
{
size_t soap_flag_tptz__Stop = 1;
short soap_flag;
a = (struct __tptz__Stop *)soap_id_enter(soap, "", a, SOAP_TYPE___tptz__Stop, sizeof(struct __tptz__Stop), 0, NULL, NULL, NULL);
if (!a)
return NULL;
soap_default___tptz__Stop(soap, a);
for (soap_flag = 0;; soap_flag = 1)
{ soap->error = SOAP_TAG_MISMATCH;
if (soap_flag_tptz__Stop && soap->error == SOAP_TAG_MISMATCH)
if (soap_in_PointerTo_tptz__Stop(soap, "tptz:Stop", &a->tptz__Stop, ""))
{ soap_flag_tptz__Stop--;
continue;
}
if (soap->error == SOAP_TAG_MISMATCH)
if (soap_flag)
{ soap->error = SOAP_OK;
break;
}
if (soap_flag && soap->error == SOAP_NO_TAG)
break;
if (soap->error)
return NULL;
}
return a;
}
SOAP_FMAC3 int SOAP_FMAC4 soap_put___tptz__Stop(struct soap *soap, const struct __tptz__Stop *a, const char *tag, const char *type)
{
register int id = 0;
if (soap_out___tptz__Stop(soap, tag?tag:"-tptz:Stop", id, a, type))
return soap->error;
return SOAP_OK;
}
SOAP_FMAC3 struct __tptz__Stop * SOAP_FMAC4 soap_get___tptz__Stop(struct soap *soap, struct __tptz__Stop *p, const char *tag, const char *type)
{
if ((p = soap_in___tptz__Stop(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTo_tptz__StopResponse(struct soap *soap, struct _tptz__StopResponse *const*a)
{
#ifndef WITH_NOIDREF
if (!soap_reference(soap, *a, SOAP_TYPE__tptz__StopResponse))
soap_serialize__tptz__StopResponse(soap, *a);
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTo_tptz__StopResponse(struct soap *soap, const char *tag, int id, struct _tptz__StopResponse *const*a, const char *type)
{
id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE__tptz__StopResponse, NULL);
if (id < 0)
return soap->error;
return soap_out__tptz__StopResponse(soap, tag, id, *a, type);
}
SOAP_FMAC3 struct _tptz__StopResponse ** SOAP_FMAC4 soap_in_PointerTo_tptz__StopResponse(struct soap *soap, const char *tag, struct _tptz__StopResponse **a, const char *type)
{
if (soap_element_begin_in(soap, tag, 1, NULL))
return NULL;
if (!a)
if (!(a = (struct _tptz__StopResponse **)soap_malloc(soap, sizeof(struct _tptz__StopResponse *))))
return NULL;
*a = NULL;
if (!soap->null && *soap->href != '#')
{ soap_revert(soap);
if (!(*a = soap_in__tptz__StopResponse(soap, tag, *a, type)))
return NULL;
}
else
{ a = (struct _tptz__StopResponse **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE__tptz__StopResponse, sizeof(struct _tptz__StopResponse), 0, NULL);
if (soap->body && soap_element_end_in(soap, tag))
return NULL;
}
return a;
}
SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTo_tptz__StopResponse(struct soap *soap, struct _tptz__StopResponse *const*a, const char *tag, const char *type)
{
register int id = 0;
if (soap_out_PointerTo_tptz__StopResponse(soap, tag?tag:"tptz:StopResponse", id, a, type))
return soap->error;
return soap_putindependent(soap);
}
SOAP_FMAC3 struct _tptz__StopResponse ** SOAP_FMAC4 soap_get_PointerTo_tptz__StopResponse(struct soap *soap, struct _tptz__StopResponse **p, const char *tag, const char *type)
{
if ((p = soap_in_PointerTo_tptz__StopResponse(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTo_tptz__Stop(struct soap *soap, struct _tptz__Stop *const*a)
{
#ifndef WITH_NOIDREF
if (!soap_reference(soap, *a, SOAP_TYPE__tptz__Stop))
soap_serialize__tptz__Stop(soap, *a);
#endif
}
SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTo_tptz__Stop(struct soap *soap, const char *tag, int id, struct _tptz__Stop *const*a, const char *type)
{
id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE__tptz__Stop, NULL);
if (id < 0)
return soap->error;
return soap_out__tptz__Stop(soap, tag, id, *a, type);
}
SOAP_FMAC3 struct _tptz__Stop ** SOAP_FMAC4 soap_in_PointerTo_tptz__Stop(struct soap *soap, const char *tag, struct _tptz__Stop **a, const char *type)
{
if (soap_element_begin_in(soap, tag, 1, NULL))
return NULL;
if (!a)
if (!(a = (struct _tptz__Stop **)soap_malloc(soap, sizeof(struct _tptz__Stop *))))
return NULL;
*a = NULL;
if (!soap->null && *soap->href != '#')
{ soap_revert(soap);
if (!(*a = soap_in__tptz__Stop(soap, tag, *a, type)))
return NULL;
}
else
{ a = (struct _tptz__Stop **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE__tptz__Stop, sizeof(struct _tptz__Stop), 0, NULL);
if (soap->body && soap_element_end_in(soap, tag))
return NULL;
}
return a;
}
SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTo_tptz__Stop(struct soap *soap, struct _tptz__Stop *const*a, const char *tag, const char *type)
{
register int id = 0;
if (soap_out_PointerTo_tptz__Stop(soap, tag?tag:"tptz:Stop", id, a, type))
return soap->error;
return soap_putindependent(soap);
}
SOAP_FMAC3 struct _tptz__Stop ** SOAP_FMAC4 soap_get_PointerTo_tptz__Stop(struct soap *soap, struct _tptz__Stop **p, const char *tag, const char *type)
{
if ((p = soap_in_PointerTo_tptz__Stop(soap, tag, p, type)))
if (soap_getindependent(soap))
return NULL;
return p;
}
위에 soapC.cc에 추가해준 함수들은 모두 soapH.h에 정의를 해주면 된다.!
그리고 PTZ 메세지를 받아 처리하는 부분은 아래와 같다.
//onvif_server_interface.cc
SOAP_FMAC5 int SOAP_FMAC6
__tptz__ContinuousMove(struct soap *soap, struct _tptz__ContinuousMove *tptz__ContinuousMove,
struct _tptz__ContinuousMoveResponse *tptz__ContinuousMoveResponse) {
if (NULL != tptz__ContinuousMove->Velocity->PanTilt) {
if (NULL != tptz__ContinuousMove->Velocity->PanTilt->space) {
__android_log_print(ANDROID_LOG_ERROR, "cylog",
"###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ __tptz__ContinuousMove pantilt x:%f y:%f space:%s",
tptz__ContinuousMove->Velocity->PanTilt->x,
tptz__ContinuousMove->Velocity->PanTilt->y,
tptz__ContinuousMove->Velocity->PanTilt->space);
} else {
__android_log_print(ANDROID_LOG_ERROR, "cylog",
"###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ __tptz__ContinuousMove pantilt x:%f y:%f",
tptz__ContinuousMove->Velocity->PanTilt->x,
tptz__ContinuousMove->Velocity->PanTilt->y);
if (tptz__ContinuousMove->Velocity->PanTilt->x < 0) {
//left
} else if (tptz__ContinuousMove->Velocity->PanTilt->x > 0) {
//right
}
if (tptz__ContinuousMove->Velocity->PanTilt->y < 0) {
//bottom
} else if (tptz__ContinuousMove->Velocity->PanTilt->y > 0) {
//top
}
}
}
if (NULL != tptz__ContinuousMove->Velocity->Zoom) {
if (NULL != tptz__ContinuousMove->Velocity->Zoom->space) {
__android_log_print(ANDROID_LOG_ERROR, "cylog",
"###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ __tptz__ContinuousMove Zoom x:%f space:%s",
tptz__ContinuousMove->Velocity->Zoom->x,
tptz__ContinuousMove->Velocity->Zoom->space);
} else {
__android_log_print(ANDROID_LOG_ERROR, "cylog",
"###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ __tptz__ContinuousMove Zoom x:%f",
tptz__ContinuousMove->Velocity->Zoom->x);
if (tptz__ContinuousMove->Velocity->Zoom->x > 0) {
//zoom in
} else if (tptz__ContinuousMove->Velocity->Zoom->x < 0) {
//zoom out
}
}
}
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 __tptz__Stop(struct soap *soap, struct _tptz__Stop *tptz__Stop,
struct _tptz__StopResponse *tptz__StopResponse) {
return SOAP_OK;
}
이제 각각 원하는 이벤트 처리를 해주면 된다.
혹시, 더 알고싶은 정보가 있다면 편하게 댓글 남겨주길 바란다!
댓글