前言
本文主要介绍图像抓拍功能,通过自研的sip库(mysipsdk.dll)对接真实设备,使用http方式实现图像数据传输,最终达到图像抓拍与保存的目的。
基本要求
- 图像格式宜使用JPEG;
- 图像分辨率宜采用与主码流相同的分辨率;
- 抓拍图像文件命令宜遵循如下格式:
协议接口
- MESSAGE消息头Content-type头域为Content-type:Application/MANSCDP+xml;
- 图像传输方式宜使用http;
- 图像抓拍传输完成中的SessionID应与图像抓拍配置中的SessionID一致;
流程图
流程说明:
- SIP服务器(mysipsdk.dll)向设备端发送图像抓拍配置命令;
- 设备端返回200 OK;
- 设备端返回图像抓拍配置响应;
- SIP服务器(mysipsdk.dll)返回200 OK;
- 设备端将图像数据传输至图片存储服务器;
- 设备端发送图像抓拍传输完成消息;
- SIP服务器(mysipsdk.dll)返回200 OK;
设计
- SIP服务器(mysipsdk.dll)向设备端发送图像抓拍配置命令;
参数说明:
SnapNum:连拍张数,最多10张,当为手动抓拍时取值为1
Interval:单张抓拍间隔时间,单位:秒,最短为1秒
UploadURL:抓拍图像上传路径,例如:http://192.168.1.121/uploadsnapshot?token=xxx
SessionID:会话ID,由平台生成,用于关联抓拍的图像和平台请求,SessionID由大小写英文字母、数字、短划线组成,长度32~128字节
代码示例:
int CGBDeviceConfig::SnapShotConfig_(CMyGBDevice* device, const std::string& deviceID, const std::string& request)
{if (!device || deviceID.empty() || request.empty())return -1;Json::Value value;Json::Reader reader;if (!reader.parse(request.c_str(), value))return -1;std::string sn = GetConfigSN();std::string uploadURL = value["uploadURL"].asString();std::string sessionID = value["sessionID"].asString();int snapNum = value["snapNum"].asInt();int interval = value["interval"].asInt();char snapShotInfo[500] = { 0 };snprintf(snapShotInfo, 500,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n""<Control>\n""<CmdType>DeviceConfig</CmdType>\n""<SN>%s</SN>\n""<DeviceID>%s</DeviceID>\n""<SnapShotConfig>\n""<SnapNum>%d</SnapNum>\n""<Interval>%d</Interval>\n""<UploadURL>%s</UploadURL>\n""<SessionID>%s</SessionID>\n""</SnapShotConfig>\n""</Control>\n", sn.c_str(), deviceID.c_str(), snapNum, interval, uploadURL.c_str(), sessionID.c_str());return CMySipContext::GetInstance().SendSipMessage(device, snapShotInfo);
}
- 设备端发送图像抓拍传输完成消息,SIP服务器(mysipsdk.dll)做解析;
主要流程:
1) 接收响应消息;
2) xml解析;
3) 判断CmdType是否为"UploadSnapShotFinished";
4) 如果3)步骤为是,解析返回消息并回调至应用层;
图像抓拍返回字段说明:
CmdType:固定为字符串"UploadSnapShotFinished"
SessionID:会话ID,由平台生成,用于关联抓拍的图像和平台请求
SnapShotList:抓拍图像标识列表
SnapShotFileID:抓拍图像唯一标识,由前端抓拍设备生成
代码示例:
bool CDeviceConfigMethod::OnRecvMsg(pjsip_rx_data* rdata)
{if (PJSIP_OTHER_METHOD == rdata->msg_info.cseq->method.id){CMyXmlParser xmlParser(CMySipContext::GetInstance().GetMessageBody(rdata));CMyDynamicStruct dynamicStruct;dynamicStruct.Set(xmlParser.GetXml());auto cmd = xmlParser.GetXml()->RootElement()->Value();auto cmdType = dynamicStruct.Get("CmdType");if ("UploadSnapShotFinished" == cmdType){CSnapShotFinishInfo snapShotInfo;snapShotInfo.deviceID = dynamicStruct.Get("DeviceID");snapShotInfo.sessionID = dynamicStruct.Get("SessionID");std::string snapShotList = dynamicStruct.Get("SnapShotList");Json::Reader reader;Json::Value value;reader.parse(snapShotList, value);int size = value.size();for (int i = 0; i < size; i++){Json::Value val = value[i];std::string snapShotfileID = val["SnapShotFileID"].asString();snapShotInfo.snapShotFileIDs.push_back(snapShotfileID);}// 回调至应用层,需注册if (m_dataCB)m_dataCB(m_handleType, m_user, &snapShotInfo);}else{return false;}Response(rdata, PJSIP_SC_OK, NoHead);return true;}return false;
}