1、任务描述:
最近DVR实现了ahd和tvi的UTC功能,现在想在浏览器上面添加使用UTC接口控制云台,之前是默认使用485接口控制云台的。
注:CGI的工作原理是用户在浏览器界面点击按钮,通过局域网或外网把xml信息发给DVR,DVR接收信息之后交给cgi_gw.c解析信息,过程是遍历所有函数,根据name满足条件的就获取xml信息中的各选项的值,然后通过TCP把这些信息发给app,最后在app2cgi_communication.c中根据命令类型执行相对应的命令。
xml信息格式:<juan ver="0" squ="abcdef" dir="0" enc="1"><utcptzctrl usr="admin" pwd="" chn="0" cmd="15" param="0"/></juan>
2、步骤:
1)在cgi_gw.c解析web服务器发过来的xml信息:
static void proc_juan_utcctrl(UniStructNode* root_in, UniStructNode* root_out)
{
UniStructNodesList* tmp_nodes_in;
UniStructNode* tmp_node_in;
UniStructNode* tmp_node_out;
UniStructAttr* tmp_attr_in;
// UniStructAttr* tmp_attr_out;
char *name;
name = "utcctrl";
tmp_nodes_in = UniStruct_find_children(root_in, name);
if(tmp_nodes_in == NULL){
name = "utcmenuctrl";
tmp_nodes_in = UniStruct_find_children(root_in, name);
}
if(tmp_nodes_in != NULL)
{
int i;
for(i = 0; i < tmp_nodes_in->count; i++)
{
tmp_node_in = tmp_nodes_in->nodes[i];
tmp_node_out = UniStruct_append_child(root_out, name, "");
UniStruct_append_attr(tmp_node_out, "errno", _convert_from_enum(JUAN_ERRNO_NO_ERROR));
char* usr = NULL;
char* pwd = NULL;
CHK_USR_PWD(JUAN_ERRNO_USR_OR_PWD_ERROR);
#define PTZCTRL_PROC_START(key) \
{ \
tmp_attr_in = UniStruct_find_attr(tmp_node_in, key); \
if(tmp_attr_in != NULL) \
{ \
#define PTZCTRL_PROC_END(key) \
UniStruct_append_attr(tmp_node_out, key, tmp_attr_in->value); \
} \
}
int chn = -1;
int cmd = -1;
int param = -1;
PTZCTRL_PROC_START("chn");
chn = _convert_from_string(tmp_attr_in->value);
PTZCTRL_PROC_END("chn");
PTZCTRL_PROC_START("cmd");
cmd = _convert_from_string(tmp_attr_in->value);
PTZCTRL_PROC_END("cmd");
PTZCTRL_PROC_START("param");
param = _convert_from_string(tmp_attr_in->value);
PTZCTRL_PROC_END("param");
if(chn == -1 || cmd == -1 || param == -1)
{
UniStruct_modify_attr(tmp_node_out, "errno", _convert_from_enum(JUAN_ERRNO_PARAM_ERROR));
continue;
}
///
DVRCommand_t dvr_cmd;
memset(&dvr_cmd, 0, sizeof(DVRCommand_t));
dvr_cmd.flag = DVR_CMD_FLAG;
dvr_cmd.type = CMD_UTC_CTRL;
dvr_cmd.utc_ctrl.nChn = chn;
dvr_cmd.utc_ctrl.nCmd = cmd;
dvr_cmd.utc_ctrl.u8Val = param;
SEND_CMD_TO_APP(dvr_cmd, SEND_CMD_TO_APP_TIMEOUT);
if(dvr_cmd.type != CMD_UTC_CTRL_ACK)
{
UniStruct_modify_attr(tmp_node_out, "errno", _convert_from_enum(JUAN_ERRNO_APP_RESPONSE_ERROR));
continue;
}
}
UniStruct_free_nodes_list(tmp_nodes_in);
tmp_nodes_in = NULL;
}
}
2)在app2cgi_communication.c中调用app的接口执行命令:
void app2cgi_read_cmd(DVRCommand_t cmd, int _socket_index)
{
// check cmd is legal
if(DVR_CMD_FLAG != cmd.flag)
{
TRACE_DEBUG("cgi connecting. cmd.flag is %u", cmd.flag);
TRACE_DEBUG("cgi connecting. cmd.type is %d", cmd.type);
TRACE_DEBUG("cgi connecting. not DVR_CMD_FLAG");
return;
}
// TRACE_DEBUG("client connecting. cmd.type is %d", cmd.type);
int ret;
switch(cmd.type)
{
case CMD_PTZ_CTRL:
{
TRACE_DEBUG("rcv ptz cmd: chn=%d cmd=%d val=%d", cmd.ptz_ctrl.nChn, cmd.ptz_ctrl.nCmd, cmd.ptz_ctrl.u8Val);
if(PTZ_CMD_TOUR == cmd.ptz_ctrl.nCmd){
if(cmd.ptz_ctrl.u8Val){
PTZTOUR_Start(cmd.ptz_ctrl.nChn);
}else{
PTZTOUR_Stop(cmd.ptz_ctrl.nChn);
}
}else{
PTZ_Send(cmd.ptz_ctrl.nChn, cmd.ptz_ctrl.nCmd, cmd.ptz_ctrl.u8Val);
}
cmd.type = CMD_PTZ_CTRL_ACK;
SEND_DVRCMD_ACK(cmd, _socket_index);
}
break;
case CMD_UTC_CTRL:
{
TRACE_DEBUG("rcv utc cmd: chn=%d cmd=%d val=%d", cmd.utc_ctrl.nChn, cmd.utc_ctrl.nCmd, cmd.utc_ctrl.u8Val);
HDDVR_UTC_Init();
switch(cmd.utc_ctrl.nCmd)
{
case UTC_CMD_LEFT_UP:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_LEFT_UP , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_UP:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_UP , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_RIGHT_UP:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_RIGHT_UP , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_LEFT_DOWN:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_LEFT_DOWN , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_DOWN:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_DOWN , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_RIGHT_DOWN:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_RIGHT_DOWN , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_LEFT:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_LEFT , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_RIGHT:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_RIGHT , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_IRIS_OPEN:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_IRIS_OPEN , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_IRIS_CLOSE:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_IRIS_CLOSE , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_FOCUS_NEAR:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_FOCUS_NEAR , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_FOCUS_FAR:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_FOCUS_FAR , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_ZOOM_WIDE:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_ZOOM_WIDE , cmd.utc_ctrl.u8Val);
break;
case UTC_CMD_ZOOM_TELE:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_ZOOM_TELE , cmd.utc_ctrl.u8Val);
break;
default:
break;
}
HDDVR_UTC_Exit();
cmd.type = CMD_UTC_CTRL_ACK;
SEND_DVRCMD_ACK(cmd, _socket_index);
}
break;
case CMD_UTCMENU_CTRL:
{
TRACE_DEBUG("rcv utc cmd: chn=%d cmd=%d val=%d", cmd.utc_ctrl.nChn, cmd.utc_ctrl.nCmd, cmd.utc_ctrl.u8Val);
HDDVR_UTC_Init();
switch(cmd.utc_ctrl.nCmd)
{
case UTC_MENU_CMD_UP:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_UP , cmd.utc_ctrl.u8Val);
break;
case UTC_MENU_CMD_DOWN:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_DOWN , cmd.utc_ctrl.u8Val);
break;
case UTC_MENU_CMD_LEFT:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_LEFT , cmd.utc_ctrl.u8Val);
break;
case UTC_MENU_CMD_RIGHT:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_RIGHT , cmd.utc_ctrl.u8Val);
break;
case UTC_MENU_ENTER:
HDDVR_UTC_Send(cmd.utc_ctrl.nChn, HDDVR_UTC_CMD_IRIS_OPEN , cmd.utc_ctrl.u8Val);
break;
default:
break;
}
HDDVR_UTC_Exit();
cmd.type = CMD_UTCMENU_CTRL_ACK;
SEND_DVRCMD_ACK(cmd, _socket_index);
}
break;
default:
{
break;
}
}
}
setenv("WEBDIR", "/root/dvr_web/www", false);
HTTPD_init(getenv("WEBDIR"));
HTTPD_add_cgi("/moo", CGI_moo);
HTTPD_add_cgi("/whoami", CGI_whoami);
// HTTPD_add_cgi("/shell", CGI_shell);
// HTTPD_add_cgi("/snapshot", CGI_snapshot);
// HTTPD_add_cgi("/mjpeg", CGI_mjpeg);
// HTTPD_add_cgi("/mjpeg.html", CGI_mjpeg_html);
// HTTPD_add_cgi("/email", CGI_send_email);
// HTTPD_add_cgi("/cgi-bin/view.cgi", CGI_flv_live_view);
// HTTPD_add_cgi("/cgi-bin/flv.cgi", CGI_playback);
// HTTPD_add_cgi("/hls/live.m3u8", CGI_hls_live_m3u8);
// HTTPD_add_cgi("/hls/live.ts", CGI_hls_live_ts);
// HTTPD_add_cgi("/ios/test.mp4", CGI_live_mp4);
HTTPD_add_cgi("/cgi-bin/jscript.cgi", CGI_jscript);
HTTPD_add_cgi("/cgi-bin/gw.cgi", CGI_gw);
// HTTPD_add_cgi("/cgi-bin/sp.cgi", CGI_sp);
HTTPD_add_cgi("/index.cgi", CGI_index);
SPOOK_init(g_pstSysEnv->GetHTTPPort(g_pstSysEnv), "/tmp/spook");
SPOOK_add_session("httpd", HTTPD_probe2, HTTPD_loop2);
//PTZ_INIT();
XENVACT_init_volumn();
#if defined(_NVR) || defined(_HVR) || defined(_DNVR) || defined(_JAMEDIA)
APP_GLIB_init();
#endif
TS_init();
4)使用fiddler工具向DVR发命令请求来测试功能:
Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据,Fiddler包含了一个强大的基于事件脚本的子系统,并且能使用.net语言进行扩展。
因为现在需要向DVR发送XML信息,从而测试UTC-CGI接口是否有效,所以只需要创建HTTP Request并向DVR发送就行。具体操作:
点击右边的Composer,选择GET请求,输入请求的地址,比如:
http://192.168.40.40/cgi-bin/gw.cgi?xml=<juan%20ver="0"%20squ="abcdef"%20dir="0"%20enc="1"><utcctrl%20usr="admin"%20pwd=""%20chn="0"%20cmd="15"%20param="0"/></juan>&_=1450927026027
也可以在左边Web会话列表中拖拽一个已有的Request,最后点击execute按钮发送。