From 142fca3dd02593773270f7c88e87bcd44237af5d Mon Sep 17 00:00:00 2001 From: Matthew Date: Mon, 28 Apr 2025 21:32:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=B5=B7=E5=BA=B7=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/cpp/PhoneDevice.cpp | 49 +----- app/src/main/cpp/netcamera/HikonCtrl.cpp | 204 +++++++++++++++++++++++ app/src/main/cpp/netcamera/HikonCtrl.h | 34 ++++ app/src/main/cpp/netcamera/YuShiCtrl.cpp | 12 +- 4 files changed, 252 insertions(+), 47 deletions(-) create mode 100644 app/src/main/cpp/netcamera/HikonCtrl.cpp create mode 100644 app/src/main/cpp/netcamera/HikonCtrl.h diff --git a/app/src/main/cpp/PhoneDevice.cpp b/app/src/main/cpp/PhoneDevice.cpp index f2527d78..607d154e 100644 --- a/app/src/main/cpp/PhoneDevice.cpp +++ b/app/src/main/cpp/PhoneDevice.cpp @@ -14,6 +14,7 @@ #include "netcamera/VendorCtrl.h" #include "netcamera/YuShiCtrl.h" #include "netcamera/HangYuCtrl.h" +#include "netcamera/HikonCtrl.h" #include "media/RTSPRecorder.h" @@ -1673,56 +1674,14 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c std::unique_ptr vendorCtrl(MakeVendorCtrl(localPhotoInfo.vendor, localPhotoInfo.channel, ip, localPhotoInfo.userName, localPhotoInfo.password, netHandle, false)); NET_PHOTO_INFO netPhotoInfo = { netHandle, 0 }; - if (localPhotoInfo.vendor == 1) - { - // 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 + if (!vendorCtrl) { 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); return false; } - struct in_addr addr; - addr.s_addr = localPhotoInfo.ip; - strcpy(netPhotoInfo.ip, inet_ntoa(addr)); strcpy(netPhotoInfo.outputPath, path.c_str()); - if (!localPhotoInfo.userName.empty()) - { - size_t len = std::min(sizeof(netPhotoInfo.userName) - 1, localPhotoInfo.userName.size()); - strncpy(netPhotoInfo.userName, localPhotoInfo.userName.c_str(), len); - } - if (!localPhotoInfo.password.empty()) - { - size_t len = std::min(sizeof(netPhotoInfo.password) - 1, localPhotoInfo.password.size()); - strncpy(netPhotoInfo.password, localPhotoInfo.password.c_str(), len); - } - // strcpy(netPhotoInfo.interface, "eth0"); std::vector img; cv::Mat rgb; @@ -1730,6 +1689,7 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c bool netCaptureResult = false; std::string lastError; int idx = 0; + vendorCtrl->SetResolution(localPhotoInfo.channel, localPhotoInfo.cameraId, localPhotoInfo.width, localPhotoInfo.height); for (; idx < 128; idx++) { 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); +#if 0 if(localPhotoInfo.vendor == 3) { UniviewResolutionSet(netPhotoInfo, localPhotoInfo.cameraId,localPhotoInfo.resolution); } +#endif img.clear(); netCaptureResult = vendorCtrl->TakePhoto(localPhotoInfo.cameraId, img); @@ -5205,6 +5167,7 @@ VendorCtrl* CPhoneDevice::MakeVendorCtrl(int vendor, uint8_t channel, const std: { case 1: // Hai Kang + vendorCtrl = new HikonCtrl(ip, userName, password, channel, netHandle, syncTime); break; case 2: break; diff --git a/app/src/main/cpp/netcamera/HikonCtrl.cpp b/app/src/main/cpp/netcamera/HikonCtrl.cpp new file mode 100644 index 00000000..591fb67a --- /dev/null +++ b/app/src/main/cpp/netcamera/HikonCtrl.cpp @@ -0,0 +1,204 @@ +// +// Created by Matthew on 2025/3/4. +// + +#include "HikonCtrl.h" +#include "netcamera.h" +#include "httpclient.h" +#include + +#include + +#include +#include + +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 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(""); + size_t widthEnd = xmlString.find(""); + if (widthStart != std::string::npos && widthEnd != std::string::npos) { + widthStart += std::string("").length(); + xmlString.replace(widthStart, widthEnd - widthStart, std::to_string(resX)); + } + + size_t heightStart = xmlString.find(""); + size_t heightEnd = xmlString.find(""); + if (heightStart != std::string::npos && heightEnd != std::string::npos) { + heightStart += std::string("").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//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 resData; + std::replace(osdstring.begin(), osdstring.end(), '\n', '^'); + string xmlString = "" + string(hasDateTime ? "true" : "false") + "801false"+ osdstring+ "8" + string(hasDateTime ? "24" : "0") + ""; + 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 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 = ""; + std::string enableEndTag = ""; + + 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//Media/Video/Streams//LiveStreamURL?TransType=&TransProtocol= + char url[128] = { 0 }; + snprintf(url, sizeof(url), "http://%s/Streams/%u/1/Transport", m_ip.c_str(), (uint32_t)channel); + + std::vector 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], ""); + if (start == NULL) + { + return ""; + } + start += 9; + const char* end = strstr(start, ""); + if (end == NULL) + { + return ""; + } + + return std::string(start, end); +} + +bool HikonCtrl::UpdateTime(time_t ts) +{ + // /LAPI/V1.0/System/Time + + // + // + + std::string reqData = ""; + + std::string url = "http://" + m_ip + "/System/Time"; + std::vector 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& 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; +} \ No newline at end of file diff --git a/app/src/main/cpp/netcamera/HikonCtrl.h b/app/src/main/cpp/netcamera/HikonCtrl.h new file mode 100644 index 00000000..0acb9d15 --- /dev/null +++ b/app/src/main/cpp/netcamera/HikonCtrl.h @@ -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& 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__ diff --git a/app/src/main/cpp/netcamera/YuShiCtrl.cpp b/app/src/main/cpp/netcamera/YuShiCtrl.cpp index 3e336e2a..61aac1a3 100644 --- a/app/src/main/cpp/netcamera/YuShiCtrl.cpp +++ b/app/src/main/cpp/netcamera/YuShiCtrl.cpp @@ -145,7 +145,7 @@ bool YuShiCtrl::UpdateTime(time_t ts) std::string url = "http://" + m_ip + "/LAPI/V1.0/System/Time"; std::vector 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) { @@ -157,16 +157,20 @@ bool YuShiCtrl::UpdateTime(time_t ts) bool YuShiCtrl::TakePhoto(uint8_t streamID, std::vector& 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) { return false; } - void YuShiCtrl::OSDJson(int id, bool enabled, std::string osdString, int x, int y, bool timeOn, std::string& jsonString) { Json::Value root;