以http协议实现onvif协议并完成对IPC摄像头的监控

2023-11-13


前言

因为工作上的原因,需要接入IPC摄像头,实现监控功能,因而开始了对于IPC摄像头的学习之路。因为要做到通用,所以目光直接锁定了onvif协议,因为这是一个通用的协议,各大摄像头厂家都适配于这个协议。在网上搜索后,发现有关onvif协议的实现大部分博主都是通过gsoap这个工具来实现的,但经过查看后,发现gsoap的框架在编译后生成的可执行文件动不动就是10几M,而我工作所用到的板子flash才16M,实际可用的也就12 13M,因而走这条路肯定是行不通了,于是开始研究其他方向,最终找到可以利用http协议实现onvif协议,因为onvif协议在与以IPC摄像头为服务器,自身终端为客户端,在两者进行通信时,使用的是http协议,只不过其命令比较复杂,不像gsoap工具已经集成好了,但为了节省内存空间,只能使用这种方式来实现一些控制。

1实现http连接

        因为我实现监控功能的前提是能获得该IPC摄像头的IP地址,因而设备查找这一块就省略了(其实是比较简单的)。首先我们基于已经知道的IPC摄像头的ip地址来实现http连接,以下是连接时的关键函数:

      

int SendHttpCmdAndReceiveMessage(char*IpAdress,char*sndBuf,int sndLen,char*recvBuf,int recvLen)
{
    int sock;  
    struct sockaddr_in remote;
    if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0){  
        perror("Can't create TCP socket!\n");  
    }
    bzero(&remote,sizeof(remote));
    remote.sin_family = AF_INET;
    if(inet_aton(IpAdress,&remote.sin_addr) == 0) //服务器的IP地址来自程序的参数
    {
        printf("Server IP Address Error!\n");
		return 0;
    }
    remote.sin_port = htons(80);
    int addr_len = sizeof(remote);
    //向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接
    if(connect(sock,(struct sockaddr*)&remote, addr_len) < 0)
    {
        printf("Can Not Connect To %s!\n",IpAdress);
        return 0;
    }  
    send(sock,sndBuf,sndLen,0);
	usleep(500);
    recvLen = recv(sock,recvBuf,recvLen,0);
	close(sock);
	return 1;
}

  该函数就实现了与IPC的http连接,IP地址是摄像头的地址,端口默认是80,并且该函数是发送与接收同步的。有这个基础,我们就能通过这个函数,发出一些指令,从而控制摄像头。

2 获取设备编码参数

        在这里,我们需要获取摄像头的一些参数,因为我们最终是要将视频播放出来,因而我们要知道摄像头的分辨率,帧率等信息,下面是发送获取编码命令的相关代码片段:

/*获取设备编码*/
int ONVIF_IPC_GetVideoEnc_API()
{
    int DataStrlen = 0;
	int ReturnData = 0;
	char cfgStr[2048] = { 0 };
	//char * rcvData = (char *)malloc(RCV_BUFF_SIZE);
	char rcvData[20480];
    assert(rcvData);
	
	DataStrlen = sprintf(cfgStr,"%s","POST /onvif/Media HTTP/1.1\r\n");
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s", "Host: ",gHttpMessage.IPAdress,"\r\n");    
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s", "Content-Type: application/soap+xml; charset=utf-8\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s", "Content-Length: ",289,"\r\n\r\n");
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<?xml version=\"1.0\" encoding=\"utf-8\"?>");
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s", "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"><s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><GetProfiles xmlns=\"http://www.onvif.org/ver10/media/wsdl\"/></s:Body></s:Envelope>\r\n");    
	
	SendHttpCmdAndReceiveMessage(gHttpMessage.IPAdress,cfgStr,strlen(cfgStr),rcvData,RCV_BUFF_SIZE);
	ReturnData = GetRealm(rcvData);
	GetNonce(rcvData);
	ProduceResponceHttp();
	DataStrlen = 0;
	DataStrlen = sprintf(cfgStr,"%s",         "POST /onvif/Media HTTP/1.1\r\n");
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s", "Host:",gHttpMessage.IPAdress,"\r\n");   
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s", "Content-Type: application/soap+xml; charset=utf-8\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\",","Authorization: Digest username=","admin");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," realm=",gHttpMessage.realm);
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," qop=","auth");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," algorithm=","MD5");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," uri=","/onvif/Media");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," nonce=",gHttpMessage.nonce);
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s"," nc=","00000001",",");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," cnonce=","9C6FD4D2CE6E99424E1DDD37312C0A24");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\"\r\n"," response=",gHttpMessage.responce);

	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s","Content-Length: ",289,"\r\n\r\n");
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<?xml version=\"1.0\" encoding=\"utf-8\"?>");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s", "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"><s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><GetProfiles xmlns=\"http://www.onvif.org/ver10/media/wsdl\"/></s:Body></s:Envelope>\r\n");
	
	SendHttpCmdAndReceiveMessage(gHttpMessage.IPAdress,cfgStr,strlen(cfgStr),rcvData,RCV_BUFF_SIZE);

	printf("The rcv data =%s\r\n",rcvData);
	GetResolution(rcvData);
	GetToken(rcvData);
	
	
	GetVideoCoderName(rcvData);
	GetTtlAndUserConutAndPort(rcvData);
	GetH264ProfileAndSessionTimeout(rcvData);
	GetVideoCoderToken(rcvData);
	
	// if(rcvData != NULL)
	// {
	// 	free(rcvData);
	// }
	printf("This is test 2\r\n");
    return 0;
}

在这里就可以看出,用http协议的不方便了,因为我们需要发送非常多的东西,而且摄像头需要鉴权,也就等同于我们在网页上登录。因为用的是摘要认证方式,所以同样的命令我们要发送两次,第二次才能获得摄像头真正的设备信息。并且我们得到的消息也是一堆复杂的xml文本内容,还需要在这里面去获得我们想要的东西。

HTTP/1.1 200 OK
Date: Thu, 28 Jul 2022 17:54:42 GMT
Server: webserver
X-Frame-Options: SAMEORIGIN
Content-Length: 3319
Connection: close
Content-Type: application/soap+xml; charset=utf-8

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl" xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12" xmlns:http="http://schemas.xmlsoap.org/wsdl/http" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2" xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:trc="http://www.onvif.org/ver10/recording/wsdl" xmlns:tse="http://www.onvif.org/ver10/search/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tnshik="http://www.hikvision.com/2011/event/topics" xmlns:hikwsd="http://www.onvifext.com/onvif/ext/ver10/wsdl" xmlns:hikxsd="http://www.onvifext.com/onvif/ext/ver10/schema" xmlns:tas="http://www.onvif.org/ver10/advancedsecurity/wsdl"><env:Body><trt:GetVideoEncoderConfigurationOptionsResponse><trt:Options><tt:QualityRange><tt:Min>0</tt:Min>
<tt:Max>5</tt:Max>
</tt:QualityRange>
<tt:H264><tt:ResolutionsAvailable><tt:Width>1280</tt:Width>
<tt:Height>720</tt:Height>
</tt:ResolutionsAvailable>
<tt:GovLengthRange><tt:Min>1</tt:Min>
<tt:Max>400</tt:Max>
</tt:GovLengthRange>
<tt:FrameRateRange><tt:Min>1</tt:Min>
<tt:Max>25</tt:Max>
</tt:FrameRateRange>
<tt:EncodingIntervalRange><tt:Min>1</tt:Min>
<tt:Max>1</tt:Max>
</tt:EncodingIntervalRange>
<tt:H264ProfilesSupported>Baseline</tt:H264ProfilesSupported>
<tt:H264ProfilesSupported>Main</tt:H264ProfilesSupported>
</tt:H264>
<tt:Extension><tt:H264><tt:ResolutionsAvailable><tt:Width>1280</tt:Width>
<tt:Height>720</tt:Height>
</tt:ResolutionsAvailable>
<tt:GovLengthRange><tt:Min>1</tt:Min>
<tt:Max>400</tt:Max>
</tt:GovLengthRange>
<tt:FrameRateRange><tt:Min>1</tt:Min>
<tt:Max>25</tt:Max>
</tt:FrameRateRange>
<tt:EncodingIntervalRange><tt:Min>1</tt:Min>
<tt:Max>1</tt:Max>
</tt:EncodingIntervalRange>
<tt:H264ProfilesSupported>Baseline</tt:H264ProfilesSupported>
<tt:H264ProfilesSupported>Main</tt:H264ProfilesSupported>
<tt:BitrateRange><tt:Min>32</tt:Min>
<tt:Max>2048</tt:Max>
</tt:BitrateRange>
</tt:H264>
</tt:Extension>
</trt:Options>
</trt:GetVideoEncoderConfigurationOptionsResponse>
</env:Body>
</env:Envelope>

上面就是我们得到的编码信息,通过字符串相关操作函数我们可以得到该摄像头的编码方式为h264,分辨率为1280x720,帧率为25帧。

3.设置摄像头相关参数

当我们能获得摄像头相关信息后,并不意味之就能实现显示了,有时候受解码器的限制,我们还需要去修改摄像头的参数,这样才能满足我们某个时刻的需求:

void ONVIF_IPC_SetVideoEnc_API()
{
   	int DataStrlen = 0;
	char cfgStr[2048] = { 0 };
	char * rcvData = (char *)malloc(RCV_BUFF_SIZE);

	DataStrlen = 0;
	DataStrlen = sprintf(cfgStr,"%s","POST /onvif/Media HTTP/1.1\r\n");
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s", "Host: ",gHttpMessage.IPAdress,"\r\n");    
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s", "Content-Type: application/soap+xml; charset=utf-8\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s", "Content-Length: ",1180,"\r\n\r\n");
	
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<soap:Body xmlns:trt=\"http://www.onvif.org/ver10/media/wsdl\" xmlns:tt=\"http://www.onvif.org/ver10/schema\">\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<trt:SetVideoEncoderConfiguration>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\"%s","<trt:Configuration token=",gHttpMessage.VideoEncoderToken,">\r\n");
	
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s","<tt:Name>",gHttpMessage.VideoEncoderName,"</tt:Name>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s","<tt:UseCount>",gHttpMessage.UserConut,"</tt:UseCount>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Encoding>H264</tt:Encoding>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Resolution>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Width>1280</tt:Width>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Height>720</tt:Height>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</tt:Resolution>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Quality>2</tt:Quality>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:RateControl>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:FrameRateLimit>20</tt:FrameRateLimit>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:EncodingInterval>1</tt:EncodingInterval>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:BitrateLimit>1024</tt:BitrateLimit>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</tt:RateControl>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:H264>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:GovLength>30</tt:GovLength>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s","<tt:H264Profile>",gHttpMessage.H264Profile,"</tt:H264Profile>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s"," </tt:H264>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Multicast>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Address>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Type>IPv4</tt:Type>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:IPv4Address>0.0.0.0</tt:IPv4Address>\r\n");;
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</tt:Address>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s","<tt:Port>",gHttpMessage.port,"</tt:Port>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s","<tt:TTL>",gHttpMessage.TTL,"</tt:TTL>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:AutoStart>false</tt:AutoStart>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s"," </tt:Multicast>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s","<tt:SessionTimeout>",gHttpMessage.SessionTimeout,"</tt:SessionTimeout>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</trt:Configuration>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<trt:ForcePersistence>true</trt:ForcePersistence>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</trt:SetVideoEncoderConfiguration>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</soap:Body>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</soap:Envelope>\r\n");


	//printf("The digest send data =%s\r\n",cfgStr);
	SendHttpCmdAndReceiveMessage(gHttpMessage.IPAdress,cfgStr,strlen(cfgStr),rcvData,RCV_BUFF_SIZE);
	//printf("The digest recv data  =%s\r\n",rcvData);

	GetRealm(rcvData);
	GetNonce(rcvData);
	ProduceResponceHttp();

	DataStrlen = 0;
	DataStrlen = sprintf(cfgStr,"%s",         "POST /onvif/Media HTTP/1.1\r\n");
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s", "Host:",gHttpMessage.IPAdress,"\r\n");   
    DataStrlen += sprintf(cfgStr+DataStrlen,"%s", "Content-Type: application/soap+xml; charset=utf-8\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\",","Authorization: Digest username=","admin");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," realm=",gHttpMessage.realm);
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," qop=","auth");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," algorithm=","MD5");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," uri=","/onvif/Media");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," nonce=",gHttpMessage.nonce);
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s"," nc=","00000001",",");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\","," cnonce=","9C6FD4D2CE6E99424E1DDD37312C0A24");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\"\r\n"," response=",gHttpMessage.responce);
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s", "Content-Length: ",1180,"\r\n\r\n");
	printf("len1=%d\r\n",DataStrlen);
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<soap:Body xmlns:trt=\"http://www.onvif.org/ver10/media/wsdl\" xmlns:tt=\"http://www.onvif.org/ver10/schema\">\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<trt:SetVideoEncoderConfiguration>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s\"%s\"%s","<trt:Configuration token=",gHttpMessage.VideoEncoderToken,">\r\n");
	
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s","<tt:Name>",gHttpMessage.VideoEncoderName,"</tt:Name>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s","<tt:UseCount>",gHttpMessage.UserConut,"</tt:UseCount>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Encoding>H264</tt:Encoding>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Resolution>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Width>1280</tt:Width>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Height>720</tt:Height>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</tt:Resolution>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Quality>2</tt:Quality>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:RateControl>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:FrameRateLimit>15</tt:FrameRateLimit>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:EncodingInterval>1</tt:EncodingInterval>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:BitrateLimit>1024</tt:BitrateLimit>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</tt:RateControl>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:H264>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:GovLength>30</tt:GovLength>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s","<tt:H264Profile>",gHttpMessage.H264Profile,"</tt:H264Profile>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s"," </tt:H264>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Multicast>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Address>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:Type>IPv4</tt:Type>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:IPv4Address>0.0.0.0</tt:IPv4Address>\r\n");;
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</tt:Address>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s","<tt:Port>",gHttpMessage.port,"</tt:Port>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%d%s","<tt:TTL>",gHttpMessage.TTL,"</tt:TTL>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<tt:AutoStart>false</tt:AutoStart>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s"," </tt:Multicast>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s%s%s","<tt:SessionTimeout>",gHttpMessage.SessionTimeout,"</tt:SessionTimeout>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</trt:Configuration>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","<trt:ForcePersistence>true</trt:ForcePersistence>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</trt:SetVideoEncoderConfiguration>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</soap:Body>\r\n");
	DataStrlen += sprintf(cfgStr+DataStrlen,"%s","</soap:Envelope>\r\n");

	//printf("len2=%d\r\n",DataStrlen);
	//printf("The digest send data =%s\r\n",cfgStr);
	SendHttpCmdAndReceiveMessage(gHttpMessage.IPAdress,cfgStr,strlen(cfgStr),rcvData,RCV_BUFF_SIZE);
	//printf("The recv data =%s\r\n",rcvData);

	free(rcvData);
}

通过该函数我们能设置摄像头的参数。


总结

这期就写到这里了,后面再更新如何通过rtsp接收IPC摄像头的视频数据,将其写入文件,或者播放到屏幕上。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以http协议实现onvif协议并完成对IPC摄像头的监控 的相关文章

  • pandas用法整理

    处理表格数据的时候经常用到pandas 每次用的时候都要去查函数 每次记不住 每次都查 哈哈哈 自己整理一下 码住 一 Pandas的数据类型 进行数据分析时 如何正确使用数据类型 这非常重要 在pandas中的数据类型和python原生数
  • 6类典型场景的无线AP选型和部署方案

    你们好 我的网工朋友 前段时间刚给你们来了篇解决无线频繁断网的技术文 解决无线频繁断网 这个办法值得收藏 不少朋友私聊 说想再聊聊无线AP的选型和部署方案 这不就安排上了 无线网络覆盖项目中 无线AP的合理选型和部署非常重要 在设计施工中
  • CMAKE_MAKE_PROGRAM is not set 解读

    目录 CMAKE MAKE PROGRAM 未设置 错误原因 解决方案 示例1 GNU Make 示例2 Ninja CMakeLists txt 的结构 示例 CMakeLists txt 文件 总结 CMAKE MAKE PROGRAM
  • 内网穿透的应用-使用Net2FTP轻松部署本地Web网站并公网访问管理内网资源

    文章目录 1 前言 2 Net2FTP网站搭建 2 1 Net2FTP下载和安装 2 2 Net2FTP网页测试 3 cpolar内网穿透 3 1 Cpolar云端设置 3 2 Cpolar本地设置
  • nohup - 后台执行

    nohup no hang up 语法 nohup Command Arg 使用示例 nohup python a py 日志将被保留在 当前文件夹下的 nohup out 将日志放到文件 不输出到终端 echo hello gt 1 tx
  • 服务器集群是如何提高计算性能的?

    服务器集群是一种将多台服务器连接起来协同工作的技术 通过集群配置 可以提高计算性能 可靠性和可扩展性 以下是服务器集群如何提高计算性能的详细解释 一 并行处理能力 服务器集群的核心优势在于其并行处理能力 通过将多个服务器组成一个集群 可以将
  • 5个步骤,教你瞬间明白线程和线程安全

    记得今年3月份刚来杭州面试的时候 有一家公司的技术总监问了我这样一个问题 你来说说有哪些线程安全的类 我心里一想 这我早都背好了 稀里哗啦说了一大堆 他又接着问 那你再来说说什么是线程安全 然后我就GG了 说真的 我们整天说线程安全 但是对
  • 白帽子如何快速挖到人生的第一个漏洞 | 购物站点挖掘商城漏洞

    本文针对人群 很多朋友们接触安全都是通过书籍 网上流传的PDF 亦或是通过论坛里的文章 但可能经过了这样一段时间的学习 了解了一些常见漏洞的原理之后 对于漏洞挖掘还不是很清楚 甚至不明白如何下手 可能你通过 sql labs 初步掌握了sq
  • 通俗易懂,十分钟读懂DES,详解DES加密算法原理,DES攻击手段以及3DES原理

    文章目录 1 什么是DES 2 DES的基本概念 3 DES的加密流程 4 DES算法步骤详解 4 1 初始置换 Initial Permutation IP置换 4 2 加密轮次 4 3 F轮函数 4 3 1 拓展R到48位 4 3 2
  • 【信道估计】【MIMO】【FBMC】未来移动通信的滤波器组多载波调制方案(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码及文章
  • 基于java的物业管理系统设计与实现

    基于java的物业管理系统设计与实现 I 引言 A 研究背景和动机 物业管理系统是指对物业进行管理和服务的系统 该系统需要具备对物业信息 人员信息 财务信息等进行管理的能力 基于Java的物业管理系统设计与实现的研究背景和动机主要体现在以下
  • 网络安全(黑客)自学启蒙

    一 什么是网络安全 网络安全是一种综合性的概念 涵盖了保护计算机系统 网络基础设施和数据免受未经授权的访问 攻击 损害或盗窃的一系列措施和技术 经常听到的 红队 渗透测试 等就是研究攻击技术 而 蓝队 安全运营 安全运维 则研究防御技术 作
  • 揭秘网络世界的幕后密码——Wireshark网络协议分析软件

    在我们日常生活中 计算机和互联网已经成为不可或缺的一部分 然而 很少有人真正了解网络背后复杂的工作原理和通信协议 幸运的是 有一款强大而实用的软件 Wireshark 可以帮助我们深入了解网络世界的幕后密码 Wireshark是一款免费的网
  • 国外拨号VPS指南:开启你的全球网络之旅

    在当今数字化时代 互联网已经成为了我们生活的一部分 而要在全球范围内畅通无阻地访问互联网 拥有一个可靠的国外拨号VPS是非常重要的 无论您是为了工作 学习还是娱乐 国外拨号VPS都可以为您提供更广泛的网络体验 本文将为您提供国外拨号VPS的
  • 服务器VPS是什么意思?一文了解其含义与重要性

    在今天的数字时代 服务器扮演着至关重要的角色 它们是网站 应用程序和在线业务的基石 但是 你是否听说过VPS 本文将深入探讨什么是服务器VPS 以及为什么它在今天的互联网世界中如此重要 什么是服务器VPS 服务器的基本概念 在我们深入探讨V
  • Mysql中设置只允许指定ip能连接访问(可视化工具的方式)

    场景 Mysql中怎样设置指定ip远程访问连接 Mysql中怎样设置指定ip远程访问连接 navicat for mysql 设置只有某个ip可以远程链接 CSDN博客 前面设置root账户指定ip能连接访问是通过命令行的方式 如果通过可视
  • 为什么我强烈推荐大学生打CTF!

    前言 写这个文章是因为我很多粉丝都是学生 经常有人问 感觉大一第一个学期忙忙碌碌的过去了 啥都会一点 但是自己很难系统的学习到整个知识体系 很迷茫 想知道要如何高效学习 这篇文章我主要就围绕两点 减少那些罗里吧嗦的废话 直接上干货 CTF如
  • DSCA190V 57310001-PK

    DSCA190V 57310001 PK DSCA190V 57310001 PK 具有两个可编程继电器功能 并安装在坚固的 XP 外壳中 DSCA190V 57310001 PK 即可使用 只需最少的最终用户校准 DSCA190V 573
  • 网络安全行业热门认证证书合集

    网络安全认证证书 就和学历一样是敲门砖 拿到了可以用不到 但不能没有 技术大牛可以没有证书 但普通人不能没有 1 初级入门 就像学历在职场上展示一个人的基本素养一样 网络安全认证证书可以展示一个人在网络安全领域具备的基本知识和技能 它为初学
  • Onvif - 尝试了解它是如何工作的

    首先 我完全没有使用ONVIF的经验 我在一家公司获得了奖学金 并被要求与它一起工作 控制一些相机并从它们那里获取照片 但他们也不知道它是如何工作的 所以没有人可以帮助我很多 我正在阅读 ONVIF 网页上提供的规范 但我不太明白 我知道我

随机推荐

  • jqGrid 各种参数 详解

    JQGrid JQGrid是一个在jquery基础上做的一个表格控件 以ajax的方式和服务器端通信 JQGrid Demo 是一个在线的演示项目 在这里 可以知道jqgrid可以做什么事情 下面是转自其他人blog的一个学习资料 与其说是
  • SpringCloud-服务配置

    服务配置 Spring Cloud Config分布式配置中心 概述 分布式系统面临的配置问题 微服务意味着要将单体应用中的业务拆分成一个个子服务 每个服务的粒度相对较小 因此系统中会出现大量的服务 由于每个服务都需要必要的配置信息才能运行
  • NAT--静态、动态、NAPT、Easy-ip、NAT server

    静态NAT 静态 NAT Static NAT 一对一 将内部网络的私有IP地址转换为公有IP地址 IP地址对是一对一的 是一直不变的 实验拓扑 PC配置 AR1
  • 5 .A-B 数对-二分查找/模拟(普及-)

    文章目录 问题描述 问题分析 代码实现 运行结果 总结 问题描述 出题是一件痛苦的事情 相同的题目看多了也会有审美疲劳 于是我舍弃了大家所熟悉的 A B Problem 改用 A B 了哈哈 好吧 题目是这样的 给出一串数以及一个数字 C
  • 深度测评

    2021 跨平台开发框架到底哪家强 目前市场上有多个专业做跨平台开发的框架 那么对开发者来说究竟哪一个框架更符合自己的需求呢 笔者特地总结对比了一下不同框架的特性 国内外笔者选择了一共 5 个主流的测评对象 分别是 RN Flutter I
  • Kafka 数据存储形式以及数据清理

    文章目录 Kafka 的存储日志 日志的观察模式 日志写入模式 日志读写模式 删除消息 数据挤压问题 数据清理 日志删除 日志压缩 在Kafka当中数据是以日志的形式存在的 Kafka 的存储日志 在Kafka当中 数据在磁盘当中的存储 K
  • 家用千兆路由器排行榜前十名_路由器哪个牌子好?千兆路由器2019排行

    现在网络宽带已经进入千兆时代 几乎很多的宽带已经免费升级到了100M以上 所以之前的百兆无线路由器已经有点落伍了 市面上也出现了很多的入门级的千兆无线路由器 区别就是如果你家的宽带在100M以内 比如80M 50M 20M 10M等 使用百
  • 取消GL.iNet路由器视频的密码

    每次路由器访问192 168 8 1 8083 action stream时总是无法访问 但是先进入192 168 8 1登录以后再去刷新视频就可以出来 即使取消外网登录验证也还是没效果 最后发现广大网友的意见是重新刷固件 先去GL iNe
  • 计算机专业毕业设计演示视频(论文+系统)_kaic

    https gongkailuxiangdu oss cn beijing aliyuncs com lx jsp 20 70912jspm E6 88 BF E5 B1 8B E9 94 80 E5 94 AE E7 AE A1 E7 9
  • 树莓派命令行显示乱码及异地组网问题

    写了一千多字没保存 很生气 这一条简写 命令行显示异常 首先检查树莓派设置里的地区 时区设置 一律改为中国 随后重要原因就是字库不全问题 命令行输入 sudo apt get install ttf way zenhei 一路确定安装字体
  • 程序的链接的三种方式

    程序的链接有以下三种方式 静态链接 在程序运行之前 先将各目标模块及它们所需的库函数链接成一个完整的可执行程序 以后不再拆开 装入时动态链接 将用户源程序编译后所得到的一组目标模块 在装入内存时 釆用边装入边链接的链接方式 运行时动态链接
  • 使用matlab进行灵敏性分析(附源代码)

    调用单纯形程序 function x z flg sgma simplexfun A A1 b c m n n1 cb xx A b are the matric in Ax b c is the matrix in max z cx A1
  • ChatGPT实现代码生成

    代码生成 就代码生成而言 ChatGPT 是一款卓越的工具 它为开发者提供强大的功能 ChatGPT 可以运用其出色的自然语言处理技术 深入理解和解释开发者的需求 快速生成适合的代码片段 对于那些繁琐的任务或者重复的代码 ChatGPT 能
  • 试题 C: 刷题统计

    题目链接 点击跳转 题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛 他计划周一至周五每天做 a 道题目 周六和周日每天做 b 道题目 请你帮小明计算 按照计划他将在第几天实现做题数大于等于 n 题 输入格式 输入一行包含三个整数 a
  • 系统资源占用高排查手段

    1 cpu高排查思路 1 top d 1每秒打印进程所占cpu资源 然后再按h显示线程占用 2 strace跟踪strace p 线程号 会打印该线程主要做什么操作 2 io高排查思路 lsof是一个展现的是当前系统所有进程 不是线程 打开
  • 端午过后公司面了一个字节来的要求月薪23K,明显感觉他背了很多面试题...

    最近有朋友去字节面试 面试前后进行了20天左右 包含4轮电话面试 1轮笔试 1轮主管视频面试 1轮hr视频面试 据他所说 80 的人都会栽在第一轮面试 要不是他面试前做足准备 估计都坚持不完后面几轮面试 其实 第一轮的电话面试除了一些常规的
  • Redis数据结构——QuickList、SkipList、RedisObjective

    承接上文 本文主要介绍QuickList SkipList RedisObjective 四 Redis数据结构 QuickList 问题1 ZipList虽然节省内存 但申请内存必须是连续空间 如果内存占用较多 申请内存效率很低 怎么办
  • ObjectArx 学习笔记(一)--入口函数acrxEntryPoint

    参考资料 AutoCAD 2000 ARX二次开发实例精粹 1 Arx程序的初始化 新建完工程之后 Arx程序的初始化在acrxEntryPoint 函数的AcRx kInitAppMsg事件中 或该事件调用的函数中进行 例如InitApp
  • 【PS】高低频磨皮

    一 原理 将皮肤纹理的信息储存在高频的图层中 将皮肤颜色的信息储存在低频的图层中 从而分开皮肤的颜色和纹理 达到快速修复皮肤的效果 二 步骤 1 建立高低频图层 2 低频图层 3 高频图层 图像 应用图像 混合模式改为线性光
  • 以http协议实现onvif协议并完成对IPC摄像头的监控

    文章目录 目录 文章目录 前言 1实现http连接 2 获取设备编码参数 3 设置摄像头相关参数 总结 前言 因为工作上的原因 需要接入IPC摄像头 实现监控功能 因而开始了对于IPC摄像头的学习之路 因为要做到通用 所以目光直接锁定了on