实现海康接口

lowmem
Matthew 2 months ago
parent ed35d74c94
commit 142fca3dd0

@ -14,6 +14,7 @@
#include "netcamera/VendorCtrl.h" #include "netcamera/VendorCtrl.h"
#include "netcamera/YuShiCtrl.h" #include "netcamera/YuShiCtrl.h"
#include "netcamera/HangYuCtrl.h" #include "netcamera/HangYuCtrl.h"
#include "netcamera/HikonCtrl.h"
#include "media/RTSPRecorder.h" #include "media/RTSPRecorder.h"
@ -1673,56 +1674,14 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c
std::unique_ptr<VendorCtrl> vendorCtrl(MakeVendorCtrl(localPhotoInfo.vendor, localPhotoInfo.channel, ip, localPhotoInfo.userName, localPhotoInfo.password, netHandle, false)); std::unique_ptr<VendorCtrl> vendorCtrl(MakeVendorCtrl(localPhotoInfo.vendor, localPhotoInfo.channel, ip, localPhotoInfo.userName, localPhotoInfo.password, netHandle, false));
NET_PHOTO_INFO netPhotoInfo = { netHandle, 0 }; NET_PHOTO_INFO netPhotoInfo = { netHandle, 0 };
if (localPhotoInfo.vendor == 1) if (!vendorCtrl)
{
// Hai Kang
netPhotoInfo.authType = HTTP_AUTH_TYPE_DIGEST;
snprintf(netPhotoInfo.url, sizeof(netPhotoInfo.url), "/ISAPI/Streaming/channels/1/picture?");
}
else if (localPhotoInfo.vendor == 2)
{
// Hang Yu
strcpy(netPhotoInfo.url, "/cgi-bin/snapshot.cgi");
}
else if (localPhotoInfo.vendor == 3)
{
// Yu Shi
netPhotoInfo.authType = HTTP_AUTH_TYPE_DIGEST;
int streamSid = 0; // should put into config
snprintf(netPhotoInfo.url, sizeof(netPhotoInfo.url), "/LAPI/V1.0/Channels/%u/Media/Video/Streams/%d/Snapshot", (uint32_t)localPhotoInfo.cameraId, streamSid);
}
else if (localPhotoInfo.vendor == 5)
{
// Hang Yu - New
netPhotoInfo.authType = HTTP_AUTH_TYPE_BASIC;
// http://192.168.1.46/Snapshot/%u/RemoteImageCapture?ImageFormat=2&HorizontalPixel=1920&VerticalPixel=1080
// http://192.168.1.101/Snapshot/1/2/RemoteImageCaptureV2?ImageFormat=jpg
// http://192.168.1.101/Snapshot/1/1/RemoteImageCaptureV2?ImageFormat=jpg
snprintf(netPhotoInfo.url, sizeof(netPhotoInfo.url), "/Snapshot/%u/1/RemoteImageCaptureV2?ImageFormat=jpg", (uint32_t)localPhotoInfo.cameraId);
// vendorCtrl->EnableOsd(false, localPhotoInfo.cameraId);
}
else
{ {
XYLOG(XYLOG_SEVERITY_ERROR, "Vendor(%u) not Supported CH=%u PR=%X PHOTOID=%u", (uint32_t)localPhotoInfo.vendor, (uint32_t)localPhotoInfo.channel, (unsigned int)localPhotoInfo.preset, localPhotoInfo.photoId); XYLOG(XYLOG_SEVERITY_ERROR, "Vendor(%u) not Supported CH=%u PR=%X PHOTOID=%u", (uint32_t)localPhotoInfo.vendor, (uint32_t)localPhotoInfo.channel, (unsigned int)localPhotoInfo.preset, localPhotoInfo.photoId);
TakePhotoCb(0, localPhotoInfo, "", 0); TakePhotoCb(0, localPhotoInfo, "", 0);
return false; return false;
} }
struct in_addr addr;
addr.s_addr = localPhotoInfo.ip;
strcpy(netPhotoInfo.ip, inet_ntoa(addr));
strcpy(netPhotoInfo.outputPath, path.c_str()); strcpy(netPhotoInfo.outputPath, path.c_str());
if (!localPhotoInfo.userName.empty())
{
size_t len = std::min<size_t>(sizeof(netPhotoInfo.userName) - 1, localPhotoInfo.userName.size());
strncpy(netPhotoInfo.userName, localPhotoInfo.userName.c_str(), len);
}
if (!localPhotoInfo.password.empty())
{
size_t len = std::min<size_t>(sizeof(netPhotoInfo.password) - 1, localPhotoInfo.password.size());
strncpy(netPhotoInfo.password, localPhotoInfo.password.c_str(), len);
}
// strcpy(netPhotoInfo.interface, "eth0");
std::vector<uint8_t> img; std::vector<uint8_t> img;
cv::Mat rgb; cv::Mat rgb;
@ -1730,6 +1689,7 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c
bool netCaptureResult = false; bool netCaptureResult = false;
std::string lastError; std::string lastError;
int idx = 0; int idx = 0;
vendorCtrl->SetResolution(localPhotoInfo.channel, localPhotoInfo.cameraId, localPhotoInfo.width, localPhotoInfo.height);
for (; idx < 128; idx++) for (; idx < 128; idx++)
{ {
netHandle = GetEthnetHandle(); netHandle = GetEthnetHandle();
@ -1737,10 +1697,12 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c
XYLOG(XYLOG_SEVERITY_INFO, "NetCapture %d NetHandle=%lld PHOTOID=%u", idx, netHandle, localPhotoInfo.photoId); XYLOG(XYLOG_SEVERITY_INFO, "NetCapture %d NetHandle=%lld PHOTOID=%u", idx, netHandle, localPhotoInfo.photoId);
#if 0
if(localPhotoInfo.vendor == 3) if(localPhotoInfo.vendor == 3)
{ {
UniviewResolutionSet(netPhotoInfo, localPhotoInfo.cameraId,localPhotoInfo.resolution); UniviewResolutionSet(netPhotoInfo, localPhotoInfo.cameraId,localPhotoInfo.resolution);
} }
#endif
img.clear(); img.clear();
netCaptureResult = vendorCtrl->TakePhoto(localPhotoInfo.cameraId, img); netCaptureResult = vendorCtrl->TakePhoto(localPhotoInfo.cameraId, img);
@ -5205,6 +5167,7 @@ VendorCtrl* CPhoneDevice::MakeVendorCtrl(int vendor, uint8_t channel, const std:
{ {
case 1: case 1:
// Hai Kang // Hai Kang
vendorCtrl = new HikonCtrl(ip, userName, password, channel, netHandle, syncTime);
break; break;
case 2: case 2:
break; break;

@ -0,0 +1,204 @@
//
// Created by Matthew on 2025/3/4.
//
#include "HikonCtrl.h"
#include "netcamera.h"
#include "httpclient.h"
#include <LogThread.h>
#include <SpecData_JSON.h>
#include <cstring>
#include <algorithm>
HikonCtrl::~HikonCtrl()
{
}
bool HikonCtrl::SetResolution(uint8_t channel, uint8_t streamID, uint32_t resX, uint32_t resY)
{
//流类型范围1-4,1为主流
char url[128] = { 0 };
snprintf(url, sizeof(url), "http://%s/Streams/%u/1", m_ip.c_str(), (uint32_t)channel);
std::vector<uint8_t> resData;
int res = DoGetRequest(url, HTTP_AUTH_TYPE_BASIC, m_userName.c_str(), m_password.c_str(), m_netHandle, resData);
if (res != 0 || resData.empty())
{
return 0;
}
std::string xmlString(resData.begin(), resData.end());
size_t widthStart = xmlString.find("<ResolutionWidth>");
size_t widthEnd = xmlString.find("</ResolutionWidth>");
if (widthStart != std::string::npos && widthEnd != std::string::npos) {
widthStart += std::string("<ResolutionWidth>").length();
xmlString.replace(widthStart, widthEnd - widthStart, std::to_string(resX));
}
size_t heightStart = xmlString.find("<ResolutionHeigth>");
size_t heightEnd = xmlString.find("</ResolutionHeigth>");
if (heightStart != std::string::npos && heightEnd != std::string::npos) {
heightStart += std::string("<ResolutionHeigth>").length();
xmlString.replace(heightStart, heightEnd - heightStart, std::to_string(resY));
}
res = DoPutRequest(url, HTTP_AUTH_TYPE_BASIC, m_userName.c_str(), m_password.c_str(), m_netHandle, xmlString.c_str(), resData);
if (res != 0)
{
return 0;
}
return true;
}
bool HikonCtrl::SetOsd(uint8_t channel, std::string osdstring, uint8_t pos)
{
// /LAPI/V1.0/Channels/<ID>/Media/OSDs/Contents
//左上OSD
bool hasDateTime = (osdstring.find("$$DATETIME$$") != std::string::npos);
size_t posi = osdstring.find("$$DATETIME$$");
if (posi != std::string::npos) {
size_t endPos = posi + 12;
while (endPos < osdstring.size() && (osdstring[endPos] == ' ' || osdstring[endPos] == '\n')) {
endPos++;
}
osdstring.erase(posi, endPos - posi);
}
char url[128] = { 0 };
snprintf(url, sizeof(url), "http://%s/Pictures/%u/MultiOSDV2", m_ip.c_str(), (uint32_t)channel);
std::vector<uint8_t> resData;
std::replace(osdstring.begin(), osdstring.end(), '\n', '^');
string xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><MultiLineOSD><DisplayTime><Enable>" + string(hasDateTime ? "true" : "false") + "</Enable><PosX>8</PosX><PosY>0</PosY></DisplayTime><OSD><ID>1</ID><Enable>false</Enable><Text>"+ osdstring+ "</Text><x>8</x><y>" + string(hasDateTime ? "24" : "0") + "</y></MultiLineOSD>";
int res = DoPutRequest(url, HTTP_AUTH_TYPE_BASIC, m_userName.c_str(), m_password.c_str(), m_netHandle, xmlString.c_str(), resData);
return res;
}
void HikonCtrl::EnableOsd(bool enable, uint8_t channel)
{
//航煜 只能显示时间和一个OSD
char url[128] = { 0 };
snprintf(url, sizeof(url), "http://%s/Pictures/%u/MultiOSDV2", m_ip.c_str(), (uint32_t)channel);
std::vector<uint8_t> resData;
int res = DoGetRequest(url, HTTP_AUTH_TYPE_BASIC, m_userName.c_str(), m_password.c_str(), m_netHandle, resData);
if (res != 0 || resData.empty())
{
return;
}
std::string xmlString(resData.begin(), resData.end());
std::string enableStartTag = "<Enable>";
std::string enableEndTag = "</Enable>";
size_t pos = 0;
while ((pos = xmlString.find(enableStartTag, pos)) != std::string::npos) {
size_t startPos = pos + enableStartTag.length();
size_t endPos = xmlString.find(enableEndTag, startPos);
if (endPos == std::string::npos) {
break;
}
std::string newValue = enable ? "true" : "false";
xmlString.replace(startPos, endPos - startPos, newValue);
pos = endPos + enableEndTag.length();
}
res = DoPutRequest(url, HTTP_AUTH_TYPE_BASIC, m_userName.c_str(), m_password.c_str(), m_netHandle, xmlString.c_str(), resData);
if (res != 0)
{
// return;
}
}
std::string HikonCtrl::GetStreamingUrl(uint8_t channel)
{
// /LAPI/V1.0/Channels/<ID>/Media/Video/Streams/<ID>/LiveStreamURL?TransType=<Tran
// sType>&TransProtocol=<TransProtocol>
char url[128] = { 0 };
snprintf(url, sizeof(url), "http://%s/Streams/%u/1/Transport", m_ip.c_str(), (uint32_t)channel);
std::vector<uint8_t> resData;
int res = 0;
for (int idx = 0; idx < 10; idx++)
{
res = DoGetRequest(url, HTTP_AUTH_TYPE_BASIC, m_userName.c_str(), m_password.c_str(), m_netHandle, resData);
if (res == 0 && !resData.empty())
{
break;
}
}
if (res != 0 || resData.empty())
{
return "";
}
resData.push_back(0);
const char* start = strstr((const char*)&resData[0], "<RTSPURI>");
if (start == NULL)
{
return "";
}
start += 9;
const char* end = strstr(start, "</RTSPURI>");
if (end == NULL)
{
return "";
}
return std::string(start, end);
}
bool HikonCtrl::UpdateTime(time_t ts)
{
// /LAPI/V1.0/System/Time
// <?xml version="1.0" encoding="utf-8"?>
//<Time>
//<DateTimeFormat>
//<!--req,string,YYYYMMDDWhhmmss,YYYYMMDDhhmmss,MMDDYYYYWhhmmss,MMD
// DYYYYhhmmss,DDMMYYYYWhhmmss,DDMMYYYYhhmmss-->
//</DateTimeFormat>
//<TimeFormat><!--req,xs:string,12hour,24hour--></TimeFormat>
//<SystemTime><!--req,xs:datetime,” 20040503T173008+08”--></SystemTime>
//<SyncNTPFlag><!--req,xs:string,"Sync,NoSync"--></SyncNTPFlag>
//</Time>
std::string reqData = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Time><SystemTime>"
+ FormatLocalDateTime("%d%02d%02dT%02d%02d%02d") + "+08</SystemTime></Time>";
std::string url = "http://" + m_ip + "/System/Time";
std::vector<uint8_t> resData;
int res = DoPutRequest(url.c_str(), HTTP_AUTH_TYPE_BASIC, m_userName.c_str(), m_password.c_str(), m_netHandle, reqData.c_str(), resData);
if (res != 0)
{
return false;
}
return true;
}
bool HikonCtrl::TakePhoto(uint8_t streamID, std::vector<uint8_t>& img)
{
char url[128] = { 0 };
snprintf(url, sizeof(url), "http://%s/ISAPI/Streaming/channels/1/picture?", m_ip.c_str());
int nRet = DoGetRequest(url, HTTP_AUTH_TYPE_DIGEST, m_userName.c_str(), m_password.c_str(), m_netHandle, img);
return nRet == 0;
}
bool HikonCtrl::TakeVideo(uint8_t streamID, uint32_t duration, std::string path)
{
return false;
}

@ -0,0 +1,34 @@
//
// Created by Matthew on 2025/3/4.
//
#ifndef __MICROPHOTO_HIKONCTRL_H__
#define __MICROPHOTO_HIKONCTRL_H__
#include "VendorCtrl.h"
class HikonCtrl : public VendorCtrl
{
public:
using VendorCtrl::VendorCtrl;
virtual ~HikonCtrl();
virtual bool SetOsd(uint8_t channel, std::string osd, uint8_t pos);
virtual void EnableOsd(bool enable, uint8_t channel);
virtual std::string GetStreamingUrl(uint8_t channel);
virtual bool UpdateTime(time_t ts);
virtual bool TakePhoto(uint8_t streamID, std::vector<uint8_t>& img);
virtual bool TakeVideo(uint8_t streamID, uint32_t duration, std::string path);
virtual bool HasAuthOnStreaming() const { return true; }
virtual bool SetResolution(uint8_t channel, uint8_t streamID, uint32_t resX, uint32_t resY);
private:
bool QueryQuality(std::string& qualityContents);
bool DowngradeQuality(std::string& originalConfig);
bool UpdateQuality(const std::string& originalConfig);
bool UpgradeQuality();
};
#endif //__MICROPHOTO_HIKONCTRL_H__

@ -145,7 +145,7 @@ bool YuShiCtrl::UpdateTime(time_t ts)
std::string url = "http://" + m_ip + "/LAPI/V1.0/System/Time"; std::string url = "http://" + m_ip + "/LAPI/V1.0/System/Time";
std::vector<uint8_t> resData; std::vector<uint8_t> resData;
int res = DoPutRequest(url.c_str(), HTTP_AUTH_TYPE_BASIC, m_userName.c_str(), m_password.c_str(), m_netHandle, contents.c_str(), resData); int res = DoPutRequest(url.c_str(), HTTP_AUTH_TYPE_DIGEST, m_userName.c_str(), m_password.c_str(), m_netHandle, contents.c_str(), resData);
if (res != 0) if (res != 0)
{ {
@ -157,16 +157,20 @@ bool YuShiCtrl::UpdateTime(time_t ts)
bool YuShiCtrl::TakePhoto(uint8_t streamID, std::vector<uint8_t>& img) bool YuShiCtrl::TakePhoto(uint8_t streamID, std::vector<uint8_t>& img)
{ {
return false; // Yu Shi
} char url[128] = { 0 };
int streamSid = 0; // should put into config
snprintf(url, sizeof(url), "/LAPI/V1.0/Channels/%u/Media/Video/Streams/%d/Snapshot", (uint32_t)streamID, streamSid);
int nRet = DoGetRequest(url, HTTP_AUTH_TYPE_DIGEST, m_userName.c_str(), m_password.c_str(), m_netHandle, img);
return nRet == 0;
}
bool YuShiCtrl::TakeVideo(uint8_t streamID, uint32_t duration, std::string path) { bool YuShiCtrl::TakeVideo(uint8_t streamID, uint32_t duration, std::string path) {
return false; return false;
} }
void YuShiCtrl::OSDJson(int id, bool enabled, std::string osdString, int x, int y, bool timeOn, std::string& jsonString) void YuShiCtrl::OSDJson(int id, bool enabled, std::string osdString, int x, int y, bool timeOn, std::string& jsonString)
{ {
Json::Value root; Json::Value root;

Loading…
Cancel
Save