#define NOMINMAX #include "./date/date.h" #include "HIKNvr.h" #include #include #include HIKNvr::HIKNvr(){ } /** * @brief Initializes the NVR with the given login information and channel. * * @param ip The IP address of the NVR. * @param port The port number of the NVR. * @param username The username for logging into the NVR. * @param password The password for logging into the NVR. * @param channel The channel number to set for the NVR. */ bool HIKNvr::InitNvr(std::string ip, std::string port, std::string username, std::string password, int channel) { if (Login(ip, port, username, password) == 0){ m_Channel = channel + 32; return true; } return false; } int HIKNvr::GetNvrUTCDiff(){ NET_DVR_NETAPPCFG struNAC = {0}; DWORD ZoneSize = 0; NET_DVR_GetDVRConfig(LoginID, NET_DVR_GET_NETAPPCFG, 0, &struNAC, sizeof(NET_DVR_NETAPPCFG), &ZoneSize); int nDiffHour = struNAC.struNtpClientParam.cTimeDifferenceH; int nDiffMin = struNAC.struNtpClientParam.cTimeDifferenceM; nDiffTotalMin = (nDiffHour < 0 ? -1 : 1) * (abs(nDiffHour) * 60 + nDiffMin); return (nDiffHour < 0 ? -1 : 1) * (abs(nDiffHour) * 60 + nDiffMin); } /** * @brief 用年和月查询日 * * @param select_time The selected time. * @param available_date_vec The available date vector. * @return true if the time region is found, false otherwise. */ int HIKNvr::CheckTimeRegionWithMonth(DateTime select_time,std::vector& available_date_vec) { DateTime DateNow(select_time); // 查当月 NET_DVR_MRD_SEARCH_PARAM struSearchParam = {0}; NET_DVR_MRD_SEARCH_RESULT struSearchResult = {0}; struSearchParam.dwSize = sizeof(NET_DVR_MRD_SEARCH_PARAM); struSearchParam.wYear = DateNow.year(); struSearchParam.byMonth = DateNow.month(); struSearchParam.struStreamInfo.dwChannel = m_Channel; // channel struSearchParam.byLocalOrUTC = true; // 0:local time, 1:UTC time (时区) struSearchParam.byDrawFrame = 0; // 0:不抽帧,1:抽帧 struSearchParam.byStreamType = 0;// 0:主码流,1:子码流 // 查记录 if (!NET_DVR_GetDeviceConfig(this->LoginID, NET_DVR_GET_MONTHLY_RECORD_DISTRIBUTION, 0, &struSearchParam, sizeof(struSearchParam), NULL, &struSearchResult, sizeof(struSearchResult))) { int n = NET_DVR_GetLastError(); return n == NET_DVR_NETWORK_FAIL_CONNECT ? NVR_ERR_CONNECT_7 : NVR_ERR_HIK; } for (int i = 0; i < 32; i++) { if (struSearchResult.byRecordDistribution[i]) { available_date_vec.push_back(i + 1); } } return NVR_SUC; } /** * @brief Check if a given time falls within the available time range for the current day. * * @param select_time The time to check. * @param available_time_vec A vector of available time ranges for the current day. * @return true if the given time falls within the available time range, false otherwise. */ int HIKNvr::CheckTimeRegionWithDay(DateTime select_time, std::vector &available_time_vec) { int nRet = NVR_SUC; GetNvrUTCDiff(); DateTime DateNow(select_time); int nYear = DateNow.year(); int nMonth = DateNow.month(); int nDay = DateNow.day(); NET_DVR_FILECOND FileCond; FileCond.dwFileType = 0xff;// 0xff:所有文件 FileCond.dwIsLocked = 0xff;// 0xff:所有文件 FileCond.dwUseCardNo = 0; //不使用卡号 FileCond.lChannel = m_Channel;//通道号 FileCond.struStartTime.dwYear = DateNow.year(); FileCond.struStartTime.dwMonth = DateNow.month(); FileCond.struStartTime.dwDay = DateNow.day(); FileCond.struStartTime.dwHour = 0; FileCond.struStartTime.dwMinute = 0; FileCond.struStartTime.dwSecond = 0; FileCond.struStopTime.dwYear = DateNow.year(); FileCond.struStopTime.dwMonth = DateNow.month(); FileCond.struStopTime.dwDay = DateNow.day(); FileCond.struStopTime.dwHour = 23; FileCond.struStopTime.dwMinute = 59; FileCond.struStopTime.dwSecond = 59; available_time_vec.clear(); LONG hFindHandle = NET_DVR_FindFile_V30(LoginID, &FileCond); if (-1 == hFindHandle) { nRet = NET_DVR_GetLastError(); return nRet == NET_DVR_NETWORK_FAIL_CONNECT?NVR_ERR_CONNECT_7:NVR_ERR_HIK; } else { NET_DVR_FINDDATA_V30 FindData; // 查找到的文件信息 nRet = NET_DVR_FindNextFile_V30(hFindHandle, &FindData); int ItemIndex = 0; while (nRet > 0) { if (NET_DVR_FILE_EXCEPTION == nRet)//查找文件时异常 { break; } else if (NET_DVR_FILE_NOFIND == nRet)//没有文件 { break; } else if (NET_DVR_NOMOREFILE == nRet) // 查找结束 { break; } else if (NET_DVR_ISFINDING == nRet) // 正在查找 { nRet = NET_DVR_FindNextFile_V30(hFindHandle, &FindData); //请求过快,会出读错误。同时也是参考海康sdk写法。 std::this_thread::sleep_for(std::chrono::milliseconds(5)); } else if (NET_DVR_FILE_SUCCESS == nRet) // 获取文件信息成功 { // 保存文件信息 TimeRecord tR; if (nDay != FindData.struStartTime.dwDay)//起始不在今日 { tR.TimeStart.SetDateTime(FindData.struStartTime.dwYear, FindData.struStartTime.dwMonth, nDay, 0, 0, 0); } else//起始在今日 { tR.TimeStart.SetDateTime(FindData.struStartTime.dwYear, FindData.struStartTime.dwMonth, FindData.struStartTime.dwDay, FindData.struStartTime.dwHour, FindData.struStartTime.dwMinute, FindData.struStartTime.dwSecond); } if (nDay != FindData.struStopTime.dwDay)//结束不在今日 { tR.TimeEnd.SetDateTime(FindData.struStartTime.dwYear, FindData.struStartTime.dwMonth, FindData.struStartTime.dwDay, 23, 59, 59); } else//结束在今日 { tR.TimeEnd.SetDateTime(FindData.struStopTime.dwYear, FindData.struStopTime.dwMonth, FindData.struStopTime.dwDay, FindData.struStopTime.dwHour, FindData.struStopTime.dwMinute, FindData.struStopTime.dwSecond); } date::sys_days original_date_start{date::year{tR.TimeStart.year()} / date::month{static_cast(tR.TimeStart.month())} / date::day{static_cast(tR.TimeStart.day())}}; date::sys_time original_time_start{date::sys_days{original_date_start} + std::chrono::hours{tR.TimeStart.hour()} + std::chrono::minutes{tR.TimeStart.minute()} + std::chrono::seconds{tR.TimeStart.minute()}}; date::sys_time utc_plus_8_time_start = original_time_start - std::chrono::minutes{nDiffTotalMin}; date::sys_days original_date_end{date::year{tR.TimeEnd.year()} / date::month{static_cast(tR.TimeEnd.month())} / date::day{static_cast(tR.TimeEnd.day())}}; date::sys_time original_time_end{date::sys_days{original_date_end} + std::chrono::hours{tR.TimeEnd.hour()} + std::chrono::minutes{tR.TimeEnd.minute()} + std::chrono::seconds{tR.TimeEnd.minute()}}; date::sys_time utc_plus_8_time_end = original_time_end - std::chrono::minutes{nDiffTotalMin}; // 计算时间点到1970-01-01 00:00:00 UTC的时间间隔,即时间戳 std::chrono::seconds timestamp = std::chrono::duration_cast(utc_plus_8_time_start.time_since_epoch()); tR.tmTimeStart = timestamp.count(); timestamp = std::chrono::duration_cast(utc_plus_8_time_end.time_since_epoch()); tR.tmTimeEnd = timestamp.count(); available_time_vec.emplace_back(tR); nRet = NET_DVR_FindNextFile_V30(hFindHandle, &FindData); } } // 关闭查找,释放句柄 NET_DVR_FindClose_V30(hFindHandle); } return NVR_SUC; } /** * @brief Get the time region based on the selected time and value. * * @param SelectTime The selected time. * @param Value The value used to calculate the time region. * @param TimeStart The start time of the time region. * @param TimeEnd The end time of the time region. * @return true if the time region is found, false otherwise. */ bool HIKNvr::GetTimeRegion(DateTime SelectTime, int Value, DateTime &TimeStart, DateTime &TimeEnd) { int nYear = SelectTime.year(); int nMonth = SelectTime.month(); int nDay = SelectTime.day(); // 时间格式 转换,找时间区间 int nHour = Value / 3600; int nMinute = Value / 60 - 60 * nHour; int nSecond = Value - (nMinute + 60 * nHour) * 60; TimeStart = SelectTime; TimeStart.hour() = nHour; TimeStart.minute() = nMinute; TimeStart.second() = nSecond; bool bHave = false; for (auto it : m_TimeRecords) { if (it.IsInRecord(TimeStart)) { bHave = true; TimeEnd = it.TimeEnd; break; } } return bHave; } /** * @brief Turn the time to json. * * @param Time The time to be turned to json. * @param pAvailableDateVec The available date vector. * @return nlohmann::json& The json object. */ nlohmann::json HIKNvr::TimeToJson(DateTime Time, std::vector *pAvailableDateVec) { nlohmann::json Message; //year and month Message["year"] = Time.year(); Message["month"] = Time.month(); //date if (pAvailableDateVec != nullptr) { nlohmann::json data; for (auto date : *pAvailableDateVec) { data.push_back(date); } Message["day"] = data; } return Message; } /** * @brief Converts available time slots in a day to JSON format. * * @param Time The date and time of the day. * @param pAvailableTimeVec A pointer to a vector of available time slots. * @return nlohmann::json& A reference to the JSON object containing the converted time slots. */ nlohmann::json HIKNvr::TimeToJsonInDay(DateTime Time, std::vector *pAvailableTimeVec) { nlohmann::json Message; if(pAvailableTimeVec != nullptr) { for(auto time : *pAvailableTimeVec) { nlohmann::json data; data["begin"] = time.tmTimeStart; data["end"] = time.tmTimeEnd; Message.push_back(data); } } return Message; }