ESP32开发,所以不能用海康SDK,之前用QT开发时也不想用SDK,发现有这种通过HTTP直接获取最新截图的方式,直接一个QNetworkRequest,不要太简单。URL是这样的:http://user:password@192.168.1.64/onvif-http/snapshot?Profile_2
本来还用onvif去获取URL,后发现是固定的,也不用每次去获取XML了。
话不多说,贴代码:
String md5(String str)
{
MD5Builder md;
md.begin();
md.add(str);
md.calculate();
return md.toString();
}
String extractParam(String& authHeader, String param) {
int start = authHeader.indexOf(param + "=\"") + param.length() + 2;
int end = authHeader.indexOf("\"", start);
return authHeader.substring(start, end);
}
int digestAuthRequest(HTTPClient &http) {
const char* keys[] = {"WWW-Authenticate"};
http.collectHeaders(keys, 1);
int httpCode = http.GET();
if(httpCode == HTTP_CODE_UNAUTHORIZED) {
String authHeader = http.header("WWW-Authenticate");
// 解析realm, nonce等参数
String realm = extractParam(authHeader, "realm");
String nonce = extractParam(authHeader, "nonce");
//String opaque = extractParam(authHeader, "opaque");
// 计算响应值
String ha1 = md5("admin:" + realm + ":password");//我这里user是admin直接写死了
String ha2 = md5("GET:/onvif-http/snapshot?Profile_2");
String response = md5(ha1 + ":" + nonce + ":" + ha2);
// 构造Authorization头部
String authHeaderValue = "Digest username=\"admin\", realm=\"" + realm +
"\", nonce=\"" + nonce + "\", uri=\"/onvif-http/snapshot?Profile_2\", " +
"response=\"" + response + "\"";
// 发送认证请求
http.addHeader("Authorization", authHeaderValue);
httpCode = http.GET();
}
return httpCode;
}
注意点:网上有代码缺少collectHeaders过程,导致http.header(...)得不到内容!
以下是使用的代码:
#define USE_SERIAL Serial
//从http获取
HTTPClient http;
USE_SERIAL.print("[HTTP] begin...\n");
// configure traged server and url
//http.begin("http://user:password@192.168.1.64/onvif-http/snapshot?Profile_2");//这种默认是basic认证,新海康摄像头用不了
http.begin("http://192.168.1.64/onvif-http/snapshot?Profile_2");
USE_SERIAL.print("[HTTP] GET...\n");
// start connection and send HTTP header
//int httpCode = http.GET();//这是直接get,会得到401,要求认证
int httpCode = digestAuthRequest(http);//这里会判断401,则去digest认证
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
USE_SERIAL.printf("[HTTP] GET... code: %d,%d\n", httpCode,httpCode2);
// file found at server
if (httpCode == HTTP_CODE_OK) {
// create buffer for read
uint8_t buff[1024] = {0};
int len = http.getSize();
USE_SERIAL.println(len);
// get tcp stream
NetworkClient *stream = http.getStreamPtr();
// read all data from server
while (http.connected() && len > 0) {
if(http.connected() && len>0) {
// get available data size
size_t size = stream->available();
if (size) {
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
// write it to tcp
tcp.write(buff, c);//我这里是转发给服务器,再保存为png文件
if (len > 0) {
len -= c;
}
}
delay(1);
}
}
}
}
使用的代码很平常,arduino的HTTPClient例子很多,我就替换了http.GET()这函数,在返回401的时候加上了认证。其实更应该完善HTTPClient这个库更合理,我找到头文件中有
void setAuthorization(const char *user, const char *password);
void setAuthorization(const char *auth);
void setAuthorizationType(const char *authType);
可惜setAuthorizationType这函数只是会把认证类型直接填上,后面的加密方式还是直接按base64,有这么段代码:
if (_base64Authorization.length()) {
_base64Authorization.replace("\n", "");
header += F("Authorization: ");
header += _authorizationType;
header += " ";
header += _base64Authorization;
header += "\r\n";
}
不深究了,自己的需求是实现了。
附新摄像头配置:
1、配置->高级配置->集成协议中勾选 启用onvif
2、请你为onvif协议设置用户名和密码(admin,password,管理员),这是onvif协议认证时候需要的
3、关闭如下“开启非法登录锁定”设置(可选)



1801

被折叠的 条评论
为什么被折叠?



