由于海康HikVision (Hik)平台摄像机的SDK不支持Arm Linux平台,为了跨平台的兼容性,只能使用ISAPI作为控制或接收相机数据的方式,ISAPI是Hik的一套HTTP通信协议,这里不过多介绍,详细可以查看[1-2]
签名在ISAPI中是一个核心问题,几乎每一次API调用都需要签名,签名机制在Intelligent Security API (General Application)[1] 中3.1章Authentication有充分介绍,这里不赘述,核心代码如下(相对于原代码作了一些简化):
#include
#include
#include "md5.h"
struct http_auth
{
char* httpBuf;//temp buffer 4096
char* user; //user name
char* pass; //password
char* realm; //in WWW-Authenticate header
char* nonce; //in WWW-Authenticate header
char* method; //request method -> strdup("GET")
} ;
std::string generate_auth(http_auth ct,char *uri)
{
char ha1Buf[33];
char ha2Buf[33];
unsigned char tmp[16];
//cnonce 用于生成的字串为8位,可重复4次扩展为32位
int cnonce = rand();
memset(ct->httpBuf,'\0',4096);
sprintf((char*)ct->httpBuf, "%s:%s:%s",ct->user,ct->realm,ct->pass);
md5_hash(ct->httpBuf, strlen(ct->httpBuf), tmp);
hex_from_raw(tmp, 16, ha1Buf);
snprintf((char*)ct->httpBuf, 4096, "%s:%s",ct->method,uri);
md5_hash(ct->httpBuf, strlen(ct->httpBuf), tmp);
hex_from_raw(tmp, 16, ha2Buf);
memset(ct->httpBuf,'\0',4096);
sprintf((char*)ct->httpBuf, "%s:%s:00000001:%08x:auth:%s",\
ha1Buf, ct->nonce, cnonce, ha2Buf);
md5_hash(ct->httpBuf, strlen(ct->httpBuf), tmp);
hex_from_raw(tmp, 16, ha1Buf);
snprintf(ct->httpBuf, 4096, "Digest username=\"%s\", realm=\"%s\", "
"nonce=\"%s\", uri=\"%s\", response=\"%s\", qop=auth, "
"nc=00000001, cnonce=\"%08x\"",
ct->user, ct->realm, ct->nonce, uri, ha1Buf, cnonce);
return std::string(ct->httpBuf);
}
使用任意一个API获取 realm 和 nonce ,这里需要自己解析 WWW-Authenticate,且每次过期都需要请求(一般每次API调用都重新生成签名),在有签名的 API 请求Header中应包含验证信息 Authorization
~$ curl -X GET -i 'http://192.168.0.100:80/ISAPI/Security/users'
HTTP/1.1 401 Unauthorized
Date: Fri, 22 Apr 2022 10:39:44 GMT
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 178
Content-Type: text/html
Connection: close
WWW-Authenticate: Digest qop="auth", realm="IP Camera(F9868)", nonce="323533623a35306462333232633a418b56a32f5c61f15b209459378c035d", stale="FALSE"
<!DOCTYPE html>
<html><head><title>Document Error: Unauthorized</title></head>
<body><h2>Access Error: 401 -- Unauthorized</h2>
<p>Authentication Error</p>
</body>
</html>
双向语音(Two-Way Audio),请求过程如下(一般ID都是1) :
1. Optional: Get parameters, including channel No., encoding mode, and so on, of all two-way audio channels by
the request URL: GET /ISAPI/System/TwoWayAudio/channels .
2. Specify a channel of device to start the two-way audio by
the request URL: PUT /ISAPI/System/TwoWayAudio/channels/<ID>/open
3. Perform the following operations to transmit the audio data between platform and device.
Send Audio Data to Device Request URL: PUT /ISAPI/System/TwoWayAudio/channels/<ID>/audioData
Receive Audio Data from Request URL: GET /ISAPI/System/TwoWayAudio/channels/Device<ID>/audioData
4. Stop two-way audio of the specific channel by
the request URL: PUT /ISAPI/System/TwoWayAudio/channels/<ID>/close .
需要注意的是,发送或接收数据时连接为HTTP长连接即 keep-alive,发送数据时单次只能发送8000个bytes ,不同采样率及位深的音频每秒发送次数不同,公式如下:
每秒字节数 = 采样率 x 位深 x 音频通道数 x 1(秒) ÷ 8
如:采样率为16Khz,位深为16bit的音频,通道为单声道,每秒字节数 = 16000 x 16 x 1 ÷ 8 = 32000B = 32KB,所以在Hik相机上需要每秒传4次8000B的数据,即每250ms传一次8000B的数据
参考:
1 . Hikvision Isapi Core Protocol - Intelligent Security API (General Application)
2 . Intelligent Security API (Display and Control)
3 . hpwang666/httpclient