#include "stdafx.h" #include "ResistAlarm.h" #include "MonitorObject.h" #include "Device.h" #include #include #include #include #include #include #include #include "AppService.h" #include #include <315ClientManager.h> #include "SkylightMng.h" CResistAlarm::CResistAlarm() { } CResistAlarm::~CResistAlarm() { } CResistAlarmMng::CResistAlarmMng() { } CResistAlarmMng::~CResistAlarmMng() { } BOOL CResistAlarmMng::Start(CString strIniPath) { LoadAlarmSet(); if (FALSE == LoadAlarmID()) return FALSE; LoadUnAck(); m_bWork = true; m_pThreadAlarmSet = new thread(CResistAlarmMng::ThreadProcAlarmSet, (DWORD_PTR)this, strIniPath); if (m_pThreadAlarmSet == nullptr) return FALSE; //离线报警 /*m_pThreadDevice = new thread(CResistAlarmMng::ThreadProcDevice, (DWORD_PTR)this); if (m_pThreadDevice == nullptr) return FALSE;*/ if (g_bExternalData) { m_pThreadMove = new thread(CResistAlarmMng::ThreadProcMoveFromDB, (DWORD_PTR)this); if (m_pThreadMove == nullptr) return FALSE; } else { m_pThreadMove = new thread(CResistAlarmMng::ThreadProcMove, (DWORD_PTR)this); if (m_pThreadMove == nullptr) return FALSE; } return TRUE; } void CResistAlarmMng::Stop() { m_bWork = false; if (m_pThreadAlarmSet) { m_pThreadAlarmSet->join(); delete m_pThreadAlarmSet; m_pThreadAlarmSet = nullptr; } if (m_pThreadDevice) { m_pThreadDevice->join(); delete m_pThreadDevice; m_pThreadDevice = nullptr; } if (m_pThreadMove) { m_pThreadMove->join(); delete m_pThreadMove; m_pThreadMove = nullptr; } for (auto& it : m_alarm_set) { if (it.second) { if (it.second->type == eZL_ALARMTYPE::MAX_OVER_LIMIT) { delete (MAX_OVER_LIMIT_INFO*)it.second; it.second = nullptr; } else if (it.second->type == eZL_ALARMTYPE::FRICTION_OVER_LIMIT) { delete (FRICTION_OVER_LIMIT_INFO*)it.second; it.second = nullptr; } else if (it.second->type == eZL_ALARMTYPE::CONVERT_LIMIT) { delete (CONVERT_RESIST_OVER_LIMIT*)it.second; it.second = nullptr; } else if (it.second->type == eZL_ALARMTYPE::SUOBI_LOCK_LIMIT) { delete (SUOBI_OVER_LIMIT_INFO*)it.second; it.second = nullptr; } else { assert(0); } } } m_alarm_set.clear(); for (auto& it : m_lstUnConfirmAlarm) delete it; m_lstUnConfirmAlarm.clear(); } //BASE_INFO* CResistAlarmMng::Find(string momp, uint8_t no, uint8_t type) //{ // stringstream ss; // ss << momp << '.' << to_string(no) << '.' << to_string(type); // auto it = m_alarm_set.find(ss.str()); // if (it != m_alarm_set.end()) // { // return it->second; // } // return nullptr; //} BASE_INFO* CResistAlarmMng::Find(string mo, string mp, uint8_t no, eZL_ALARMTYPE type) { stringstream ss; ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string((uint8_t)type); auto it = m_alarm_set.find(ss.str()); if (it != m_alarm_set.end()) { return it->second; } return nullptr; } //bool CResistAlarmMng::Insert(const string& momp, uint8_t no, uint8_t type, BASE_INFO* info) //{ // auto it = m_alarm_set.insert(make_pair(momp + '.' + to_string(no) + '.' + to_string(type), info)); // return it.second; //} bool CResistAlarmMng::Insert(string mo, string mp, uint8_t no, uint8_t type, BASE_INFO* info) { auto it = m_alarm_set.insert(make_pair(mo + '.' + mp + '.' + to_string(no) + '.' + to_string(type), info)); return it.second; } //bool CResistAlarmMng::ConfirmAlarm(string mo, string mp, uint8_t no, uint8_t type, const SYSTEMTIME& st) //{ // lock_guard lock(m_mtxAlarm); // auto it = m_lstUnConfirmAlarm.begin(); // for (it; it != m_lstUnConfirmAlarm.end(); ++it) // { // const auto& pInfo = *it; // if (pInfo->mo.compare(mo) == 0 && pInfo->mp.compare(mp) == 0 && pInfo->no == no && pInfo->type == type && pInfo->time.wYear == st.wYear && // pInfo->time.wMonth == st.wMonth && pInfo->time.wDay == st.wDay && pInfo->time.wHour == st.wHour && pInfo->time.wMinute == st.wMinute) // { // m_lstUnConfirmAlarm.erase(it); // return true; // } // } // return false; //} bool CResistAlarmMng::AckAlarm(int alarm_id, string& name, CTime& time) { lock_guard lock(m_mtxAlarm); auto it = m_lstUnConfirmAlarm.begin(); auto pInfo = *it; bool result = false; for (it; it != m_lstUnConfirmAlarm.end(); ++it) { pInfo = *it; if (alarm_id == pInfo->id) { result = true; break; //g_p315ClientManager->GetTcpClient()->SendAlarmData(pInfo->no, 2, CTime(pInfo->time).GetTime(), time.GetTime(), (WORD)pInfo->type, pInfo->val, 0, 0); } } if (!result) return false; auto itNew = m_lstUnConfirmAlarm.begin(); for (itNew;itNew != m_lstUnConfirmAlarm.end();++itNew) { auto& pInfoNew = *itNew; if (pInfo->mo == pInfoNew->mo && pInfo->mp == pInfoNew->mp && pInfo->no == pInfoNew->no && pInfo->type == pInfoNew->type) { pInfoNew->ack_result = 1; pInfoNew->ack_name = name; pInfoNew->ack_time = time; } } return true; } bool CResistAlarmMng::HandleAlarm(int alarm_id) { lock_guard lock(m_mtxAlarm); auto it = m_lstUnConfirmAlarm.begin(); for (it; it != m_lstUnConfirmAlarm.end(); ++it) { const auto& pInfo = *it; if (pInfo->id == alarm_id && pInfo->ack_result == 1 && pInfo->recoveryTime.wYear > 2000) { m_lstUnConfirmAlarm.erase(it); return true; } } return true; } void CResistAlarmMng::GeneralAlarm(string mo, string mp, uint8_t no, eZL_ALARMTYPE type, uint8_t level, SYSTEMTIME& tAlarm) { ALARM_INFO* pAlarmInfo = nullptr; bool bNew = false; { std::lock_guard lock(m_mtxAlarm); for (const auto& alarm : m_lstUnConfirmAlarm) { if (alarm->type == type && alarm->mo.compare(mo) == 0 && alarm->recoveryTime.wYear < 2000 && alarm->mp.compare(mp) == 0 && no == alarm->no) //跟上次报警时间超过1小时,则算新报警 { pAlarmInfo = alarm; break; } } } if (pAlarmInfo == nullptr) { bNew = true; pAlarmInfo = new ALARM_INFO; pAlarmInfo->event_id = hjfunc_GetGUID(); pAlarmInfo->id = ++m_nAlarmID; pAlarmInfo->level = 1; pAlarmInfo->mo = mo; pAlarmInfo->mp = mp; pAlarmInfo->no = no; pAlarmInfo->time = tAlarm; pAlarmInfo->type = type; pAlarmInfo->val = 0; char szInfo[200]; sprintf_s(szInfo, sizeof(szInfo), "传感器异常时间:%04d-%02d-%02d %02d:%02d:%02d", tAlarm.wYear, tAlarm.wMonth, tAlarm.wDay, tAlarm.wHour, tAlarm.wMinute, tAlarm.wSecond); pAlarmInfo->desc = szInfo; lock_guard lock(m_mtxAlarm); m_lstUnConfirmAlarm.push_back(pAlarmInfo); } //send if (bNew) //不再推送 { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pAlarmInfo, buffer); const char* output = buffer.GetString(); //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength()); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); } //save if (bNew) { CTime ctAlarmTime(tAlarm); CString sql; sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, (int)pAlarmInfo->type, (LPCSTR)(ctAlarmTime.Format("%Y-%m-%d %H:%M:%S")), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val, pAlarmInfo->event_id.c_str(), pAlarmInfo->rel_id.c_str(), uint8_t(pAlarmInfo->posi), uint8_t(pAlarmInfo->loworhigh), pAlarmInfo->refer_val, pAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) CSimpleLog::Error("执行语句失败" + sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); //g_p315ClientManager->GetTcpClient()->SendAlarmData(pAlarmInfo->no, 1, ctAlarmTime.GetTime(), 0xFFFFFFFF, (WORD)pAlarmInfo->type, pAlarmInfo->val, 0, 0); delete[] pack; pack = nullptr; } } } //报警恢复, 报警恢复逻辑与受理确认逻辑分开 void CResistAlarmMng::RecoverAlarm(const string mo, const string mp, const uint8_t no, const eZL_ALARMTYPE type, const uint8_t level, const SYSTEMTIME& tAlarm) { vector vctAlarmID; vector vctEventID; //ALARM_INFO tmpalarm; { std::lock_guard lock(m_mtxAlarm); for (auto it = m_lstUnConfirmAlarm.begin(); it != m_lstUnConfirmAlarm.end();) { auto pAlarm = *it; if (pAlarm->type == type && pAlarm->mo.compare(mo) == 0 && pAlarm->mp.compare(mp) == 0 && no == pAlarm->no && level == pAlarm->level && pAlarm->recoveryTime.wYear < 2000) { vctAlarmID.emplace_back(pAlarm->id); vctEventID.emplace_back(pAlarm->event_id); //CopyMemory(&tmpalarm, *it, sizeof(tmpalarm)); 有string 不能拷贝 //tmpalarm = *pAlarm; if (pAlarm->ack_result == 1)//如果已确认则可以删除 { it = m_lstUnConfirmAlarm.erase(it); continue; } else memcpy(&pAlarm->recoveryTime, &tAlarm, sizeof(SYSTEMTIME)); } it++; } } if (vctAlarmID.size() == 0) return; CTime ctAlarm(tAlarm); string recovery_time = ctAlarm.Format("%Y-%m-%d %H:%M:%S"); //g_p315ClientManager->GetTcpClient()->SendAlarmData(tmpalarm.no, 2, CTime(tmpalarm.time).GetTime(), ctAlarm.GetTime(), (WORD)tmpalarm.type, tmpalarm.val, 0, 0); //更新数据库 { CString sql; for (auto& it : vctAlarmID) { sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE ID = %d;", recovery_time.c_str(), it); CDBConnectPool::Instance()->DBExecuteSQL(sql); } //for (auto& it : vctEventID) //{ // sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE [event_id] = '%s';", recovery_time.c_str(), it); // CDBConnectPool::Instance()->DBExecuteSQL(sql); //} } //恢复暂时不通知 //auto doc = yyjson_mut_doc_new(nullptr); //auto root = yyjson_mut_obj(doc); //yyjson_mut_doc_set_root(doc, root); //yyjson_mut_obj_add_str(doc, root, "cmd", "alm_ack"); //yyjson_mut_obj_add_uint(doc, root, "alarm_id", alarm_id); //yyjson_mut_obj_add_strcpy(doc, root, "ack_time", recovery_time.c_str()); //yyjson_mut_obj_add_strcpy(doc, root, "ack_name", ANSItoUTF8("系统").c_str()); //size_t len; //auto json = yyjson_mut_write(doc, 0, &len); //if (json) //{ // CAppService::Instance()->GetMgServer()->SendToAllClient(json, len); // free(json); //} //yyjson_mut_doc_free(doc); } eZL_MP_STAT CResistAlarmMng::GetAlarmStat(string& mo, string& mp, SYSTEMTIME& stAlarm) { eZL_MP_STAT stat = eZL_MP_STAT::MP_STAT_UNKNOW; lock_guard lock(m_mtxAlarm); auto it = m_lstUnConfirmAlarm.rbegin(); for (it; it != m_lstUnConfirmAlarm.rend(); ++it) { const auto& pInfo = *it; if (pInfo->ack_result) continue;//受理了暂时放过 if (pInfo->mo.compare(mo) == 0 && pInfo->mp.compare(mp) == 0 && pInfo->recoveryTime.wYear < 2000) { if (pInfo->type == eZL_ALARMTYPE::EQUIP_OFFLINE || pInfo->type == eZL_ALARMTYPE::SENSOR_ABNORMAL) { stat = eZL_MP_STAT::MP_STAT_OFFLINE_GRAY; break; } else if (pInfo->level == 1) { stAlarm = pInfo->time; stat = eZL_MP_STAT::MP_STAT_ALARM_RED; break; } else if (pInfo->level == 0) { stAlarm = pInfo->time; stat = eZL_MP_STAT::MP_STAT_WARN_ORANGE; break; } } } return stat; } uint32_t CResistAlarmMng::GeneralAlarmSet(uint8_t** pack, int* len) { auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_arr(doc); yyjson_mut_doc_set_root(doc, root); for (const auto& it : m_alarm_set) { auto obj = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(root, obj); auto ss = it.second; auto kk = it.first; int nPos = kk.find('.'); int nPos2 = kk.find('.', nPos + 1); string mo = kk.substr(0, nPos); string mp = kk.substr(nPos + 1, nPos2 - nPos - 1); string momp = kk.substr(0, nPos2); string mmomp_name, station; CMonitorObjectMng::Instance()->GetStationNameByMomP(momp, station, mmomp_name); yyjson_mut_obj_add_strcpy(doc, obj, "mo", mo.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "mp", mp.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "station", station.c_str()); yyjson_mut_obj_add_int(doc, obj, "no", ss->no); yyjson_mut_obj_add_int(doc, obj, "type", uint8_t(ss->type)); switch (ss->type) { case eZL_ALARMTYPE::MAX_OVER_LIMIT: { auto conf = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, obj, "conf", conf); { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); yyjson_mut_obj_add_str(doc, object, "name", "enable"); yyjson_mut_obj_add_str(doc, object, "val", ss->enable ? "true" : "false"); } auto pInfo = (MAX_OVER_LIMIT_INFO*)ss; { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); if (ss->no == 2) yyjson_mut_obj_add_str(doc, object, "name", "d_alarm_high_limit"); else yyjson_mut_obj_add_str(doc, object, "name", "lock_alarm_high_limit"); yyjson_mut_obj_add_strcpy(doc, object, "val", to_string(pInfo->alarm_high_limit).c_str()); } { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); if (ss->no == 2) yyjson_mut_obj_add_str(doc, object, "name", "d_warn_high_limit"); else yyjson_mut_obj_add_str(doc, object, "name", "lock_warn_high_limit"); yyjson_mut_obj_add_strcpy(doc, object, "val", to_string(pInfo->warn_high_limit).c_str()); } { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); if (ss->no == 2) yyjson_mut_obj_add_str(doc, object, "name", "f_alarm_high_limit"); else yyjson_mut_obj_add_str(doc, object, "name", "keep_alarm_high_limit"); yyjson_mut_obj_add_strcpy(doc, object, "val", to_string(pInfo->f_alarm_high_limit).c_str()); } { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); if (ss->no == 2) yyjson_mut_obj_add_str(doc, object, "name", "keep_warn_high_limit"); else yyjson_mut_obj_add_str(doc, object, "name", "f_warn_high_limit"); yyjson_mut_obj_add_strcpy(doc, object, "val", to_string(pInfo->f_warn_high_limit).c_str()); } } break; case eZL_ALARMTYPE::FRICTION_OVER_LIMIT: { auto conf = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, obj, "conf", conf); { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); yyjson_mut_obj_add_str(doc, object, "name", "enable"); yyjson_mut_obj_add_str(doc, object, "val", ss->enable ? "true" : "false"); } auto pInfo = (FRICTION_OVER_LIMIT_INFO*)ss; { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); yyjson_mut_obj_add_str(doc, object, "name", "up_alarm_low_limit"); yyjson_mut_obj_add_strcpy(doc, object, "val", to_string(pInfo->up_alarm_low_limit).c_str()); } { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); yyjson_mut_obj_add_str(doc, object, "name", "up_warn_low_limit"); yyjson_mut_obj_add_strcpy(doc, object, "val", to_string(pInfo->up_warn_low_limit).c_str()); } { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); yyjson_mut_obj_add_str(doc, object, "name", "dw_alarm_high_limit"); yyjson_mut_obj_add_strcpy(doc, object, "val", to_string(pInfo->dw_alarm_high_limit).c_str()); } { auto object = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(conf, object); yyjson_mut_obj_add_str(doc, object, "name", "dw_warn_high_limit"); yyjson_mut_obj_add_strcpy(doc, object, "val", to_string(pInfo->dw_warn_high_limit).c_str()); } } break; case eZL_ALARMTYPE::SUOBI_LOCK_LIMIT: { auto conf = yyjson_mut_obj(doc); yyjson_mut_obj_add_val(doc, obj, "conf", conf); auto pInfo = (SUOBI_OVER_LIMIT_INFO*)ss; yyjson_mut_obj_add_bool(doc, conf, "enable", pInfo->enable); yyjson_mut_obj_add_int(doc, conf, "alarm_low_limit", pInfo->alarm_low_limit); yyjson_mut_obj_add_int(doc, conf, "warn_low_limit", pInfo->warn_low_limit); yyjson_mut_obj_add_int(doc, conf, "alarm_high_limit", pInfo->alarm_high_limit); yyjson_mut_obj_add_int(doc, conf, "warn_high_limit", pInfo->warn_high_limit); } break; case eZL_ALARMTYPE::CONVERT_LIMIT: { auto conf = yyjson_mut_obj(doc); yyjson_mut_obj_add_val(doc, obj, "conf", conf); auto pInfo = (CONVERT_RESIST_OVER_LIMIT*)ss; yyjson_mut_obj_add_bool(doc, conf, "enable", pInfo->enable); yyjson_mut_obj_add_int(doc, conf, "dw_alarm_low_limit", pInfo->dw_alarm_low_limit); yyjson_mut_obj_add_int(doc, conf, "dw_warn_low_limit", pInfo->dw_warn_low_limit); yyjson_mut_obj_add_int(doc, conf, "up_alarm_high_limit", pInfo->up_alarm_high_limit); yyjson_mut_obj_add_int(doc, conf, "up_warn_high_limit", pInfo->up_warn_high_limit); } break; case eZL_ALARMTYPE::RETENSION_FORCE: { auto conf = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, obj, "conf", conf); auto pInfo = (tagRetension_Force_Drop*)ss; yyjson_mut_obj_add_bool(doc, conf, "enable", pInfo->enable); yyjson_mut_obj_add_int(doc, conf, "dw_alarm_low_drop", pInfo->dw_alarm_low_drop); yyjson_mut_obj_add_int(doc, conf, "alarm_low_percent", pInfo->alarm_low_percent); yyjson_mut_obj_add_int(doc, conf, "alarm_high_percent", pInfo->alarm_high_percent); } break; default: ASSERT(0); break; } } size_t json_len; auto json = yyjson_mut_write(doc, 0, &json_len); yyjson_mut_doc_free(doc); *len = json_len + sizeof(HJDATAHEAD2) + 2; *pack = new uint8_t[*len]; auto no = CAppService::Instance()->GetPackNo(); CHjDataConver::conver_sendpack(*pack, (LPBYTE)json, json_len, 0, no, E_ZL_PROTOCAL::ZL_ALARM_SET, OR_DATA_INFO(0, 0, 1, 2, OPT_TYPE::OPT_SYNC)); free(json); return no; } uint32_t CResistAlarmMng::GeneralUnAck(uint8_t** pack, int* len) { auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_arr(doc); yyjson_mut_doc_set_root(doc, root); { //查询数据库近一天的数据 lock_guard lock(m_mtxAlarm); auto it = m_lstUnConfirmAlarm.begin(); for (it; it != m_lstUnConfirmAlarm.end(); ++it) { auto& pInfo = *it; auto obj = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(root, obj); yyjson_mut_obj_add_uint(doc, obj, "id", pInfo->id); yyjson_mut_obj_add_strcpy(doc, obj, "mo", pInfo->mo.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "mp", pInfo->mp.c_str()); yyjson_mut_obj_add_int(doc, obj, "no", pInfo->no); yyjson_mut_obj_add_int(doc, obj, "type", int(pInfo->type)); yyjson_mut_obj_add_int(doc, obj, "level", pInfo->level); yyjson_mut_obj_add_strcpy(doc, obj, "time", fmt::format("{}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", pInfo->time.wYear, pInfo->time.wMonth, pInfo->time.wDay, pInfo->time.wHour, pInfo->time.wMinute, pInfo->time.wSecond).c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "desc", pInfo->desc.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "desc", pInfo->suggest.c_str()); yyjson_mut_obj_add_int(doc, obj, "val", pInfo->val); yyjson_mut_obj_add_int(doc, obj, "ack_result", pInfo->ack_result); yyjson_mut_obj_add_strcpy(doc, obj, "ack_name", pInfo->ack_name.c_str()); yyjson_mut_obj_add_int(doc, obj, "ack_time", pInfo->ack_time.GetTime()); yyjson_mut_obj_add_strcpy(doc, obj, "event_id", pInfo->event_id.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "rel_id", pInfo->rel_id.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "recoverytime", fmt::format("{}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", pInfo->recoveryTime.wYear, pInfo->recoveryTime.wMonth, pInfo->recoveryTime.wDay, pInfo->recoveryTime.wHour, pInfo->recoveryTime.wMinute, pInfo->recoveryTime.wSecond).c_str()); } } size_t json_len; auto json = yyjson_mut_write(doc, 0, &json_len); yyjson_mut_doc_free(doc); *len = json_len + sizeof(HJDATAHEAD2) + 2; *pack = new uint8_t[*len]; auto no = CAppService::Instance()->GetPackNo(); CHjDataConver::conver_sendpack(*pack, (LPBYTE)json, json_len, 0, no, E_ZL_PROTOCAL::ZL_ALARM_UNACK, OR_DATA_INFO(0, 0, 1, 2, OPT_TYPE::OPT_SYNC)); free(json); return no; } uint32_t CResistAlarmMng::GeneralNewAlarmData(ALARM_INFO* pInfo, uint8_t** pack, int* len) { auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_arr(doc); yyjson_mut_doc_set_root(doc, root); auto obj = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(root, obj); yyjson_mut_obj_add_uint(doc, obj, "id", pInfo->id); yyjson_mut_obj_add_strcpy(doc, obj, "mo", pInfo->mo.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "mp", pInfo->mp.c_str()); yyjson_mut_obj_add_int(doc, obj, "no", pInfo->no); yyjson_mut_obj_add_int(doc, obj, "type", int(pInfo->type)); yyjson_mut_obj_add_int(doc, obj, "level", pInfo->level); yyjson_mut_obj_add_strcpy(doc, obj, "time", fmt::format("{}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", pInfo->time.wYear, pInfo->time.wMonth, pInfo->time.wDay, pInfo->time.wHour, pInfo->time.wMinute, pInfo->time.wSecond).c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "desc", pInfo->desc.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "suggest", pInfo->suggest.c_str()); yyjson_mut_obj_add_int(doc, obj, "val", pInfo->val); yyjson_mut_obj_add_int(doc, obj, "ack_result", pInfo->ack_result); yyjson_mut_obj_add_strcpy(doc, obj, "ack_name", pInfo->ack_name.c_str()); yyjson_mut_obj_add_int(doc, obj, "ack_time", pInfo->ack_time.GetTime()); yyjson_mut_obj_add_strcpy(doc, obj, "event_id", pInfo->event_id.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "rel_id", pInfo->rel_id.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "recoverytime", fmt::format("{}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", pInfo->recoveryTime.wYear, pInfo->recoveryTime.wMonth, pInfo->recoveryTime.wDay, pInfo->recoveryTime.wHour, pInfo->recoveryTime.wMinute, pInfo->recoveryTime.wSecond).c_str()); size_t json_len; auto json = yyjson_mut_write(doc, 0, &json_len); yyjson_mut_doc_free(doc); *len = json_len + sizeof(HJDATAHEAD2) + 2; *pack = new uint8_t[*len]; auto no = CAppService::Instance()->GetPackNo(); CHjDataConver::conver_sendpack(*pack, (LPBYTE)json, json_len, 0, no, E_ZL_PROTOCAL::ZL_ALARM_DATA, OR_DATA_INFO(0, 0, 1, 2, OPT_TYPE::OPT_ADD)); free(json); return no; } bool CResistAlarmMng::AlarmInfo2Pack(const ALARM_INFO* pAlarmInfo, rapidjson::StringBuffer& buffer, bool bGb2312 /*= false*/) { char szInfo[200]; char szUtf[200]; using namespace rapidjson; Writer writer(buffer); writer.StartObject(); writer.Key("cmd"); writer.String("new_alarm"); writer.Key("type"); //if (pAlarmInfo->type == MAX_OVER_LIMIT) writer.String("monitor.alarm.max_over_limit"); //else if (pAlarmInfo->type == EQUIP_OFFLINE) writer.String("monitor.alarm.equip_offline"); //else if (pAlarmInfo->type == SENSOR_ABNORMAL) writer.String("monitor.alarm.sensor_abnormal"); //else writer.String(""); writer.Int((int)pAlarmInfo->type); writer.Key("tag"); writer.String((pAlarmInfo->mo + '.' + pAlarmInfo->mp + '.' + to_string(pAlarmInfo->no + 1) + "#").c_str()); string up, momp_name, up_name; string momp = pAlarmInfo->mo + "." + pAlarmInfo->mp; CMonitorObjectMng::Instance()->GetStationNameByMomP(momp, up, momp_name); auto pObject = CMonitorObjectMng::Instance()->GetTreeByID(up); if (pObject) up_name = pObject->name; string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(momp, name1, name2, name3); if (pAlarmInfo->no == 0 && name1.length() == 0) name1 = "1号测力点"; else if (pAlarmInfo->no == 1 && name2.length() == 0) name2 = "2号测力点"; else if (pAlarmInfo->no == 2 && name3.length() == 0) name3 = "3号测力点"; sprintf_s(szInfo, 200, "%s.%s.%s.%s%s", up_name.c_str(), momp_name.c_str(), pAlarmInfo->no == 0 ? name1.c_str() : pAlarmInfo->no == 1 ? name2.c_str() : pAlarmInfo->no == 2 ? name3.c_str() : "", GetAlarmName(pAlarmInfo->type).c_str(), pAlarmInfo->level == 1 ? "报警" : "预警" ); gbk2utf8(szUtf, sizeof(szUtf), szInfo); writer.Key("title"); writer.String(szUtf); gbk2utf8(szUtf, sizeof(szUtf), up.c_str()); writer.Key("up"); writer.String(szUtf); gbk2utf8(szUtf, sizeof(szUtf), up_name.c_str()); writer.Key("up_name"); writer.String(szUtf); writer.Key("alarm_id"); writer.Uint(pAlarmInfo->id); writer.Key("event_id"); writer.String(pAlarmInfo->event_id.c_str()); writer.Key("rel_id"); writer.String(pAlarmInfo->rel_id.c_str()); writer.Key("sunroof"); writer.Int(pAlarmInfo->sunroof); writer.Key("level"); if (pAlarmInfo->level) writer.String("alarm"); else writer.String("warn"); writer.Key("occur_time"); sprintf_s(szInfo, sizeof(szInfo), "%04d-%02d-%02d %02d:%02d:%02d.%03d", pAlarmInfo->time.wYear, pAlarmInfo->time.wMonth, pAlarmInfo->time.wDay, pAlarmInfo->time.wHour, pAlarmInfo->time.wMinute, pAlarmInfo->time.wSecond, pAlarmInfo->time.wMilliseconds); writer.String(szInfo); writer.Key("val"); if (pAlarmInfo->type == eZL_ALARMTYPE::EQUIP_OFFLINE || pAlarmInfo->type == eZL_ALARMTYPE::SENSOR_ABNORMAL) writer.String("-"); else writer.String(to_string(pAlarmInfo->val).c_str()); writer.String("desc"); gbk2utf8(szInfo, sizeof(szInfo), pAlarmInfo->desc.c_str()); writer.String(szInfo); writer.Key("suggest"); writer.String(""); if (pAlarmInfo->ack_result) { //已受理的报警 writer.String("ack_result"); writer.Int(pAlarmInfo->ack_result); writer.Key("ack_name"); writer.String(ANSItoUTF8(pAlarmInfo->ack_name).c_str()); writer.Key("ack_time"); writer.String(pAlarmInfo->ack_time.Format("%Y-%m-%d %H:%M:%S")); } if (pAlarmInfo->recoveryTime.wYear != 1900) { writer.Key("recoverytime"); sprintf_s(szInfo, sizeof(szInfo), "%04d-%02d-%02d %02d:%02d:%02d.%03d", pAlarmInfo->recoveryTime.wYear, pAlarmInfo->recoveryTime.wMonth, pAlarmInfo->recoveryTime.wDay, pAlarmInfo->recoveryTime.wHour, pAlarmInfo->recoveryTime.wMinute, pAlarmInfo->recoveryTime.wSecond, pAlarmInfo->recoveryTime.wMilliseconds); writer.String(szInfo); } writer.EndObject(); return true; } CResistAlarmMng CResistAlarmMng::obj; void CResistAlarmMng::InsertToDBByMove(string mo, string mp, time_t show_time, time_t start_time, time_t end_time, int curr_val, int show_val, uint8_t idx, uint8_t posi, uint8_t type, string mark) { if (show_time == 0) return; CTime ctShowTime(show_time / 1000); uint8_t sunroof = CSkylightMng::GetInstance()->IsSkylight(&ctShowTime); //2024年6月9日 添加天窗 string table_name = fmt::format("rm_move_{:0>4}{:0>2}", ctShowTime.GetYear(), ctShowTime.GetMonth()); auto strShowTime = (LPCSTR)ctShowTime.Format("%Y-%m-%d %H:%M:%S.") + to_string(show_time % 1000); auto strStartTime = start_time ? CTime(start_time).Format("%Y-%m-%d %H:%M:%S") : ""; auto strEndTime = end_time ? CTime(end_time).Format("%Y-%m-%d %H:%M:%S") : ""; CString sql = fmt::format("INSERT INTO {} (mo,mp,show_time,start_time,end_time,curr_val,show_val,idx,posi,type,sunroof,mark) values ('{}', '{}', '{}', '{}','{}', {}, {}, {}, {}, {}, {}, '{}');", table_name, mo, mp, strShowTime, strStartTime, strEndTime, curr_val, show_val, idx, posi, type, sunroof, mark).c_str(); if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE) CSimpleLog::Error(sql); //上送 //组装数据 auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_arr(doc); yyjson_mut_doc_set_root(doc, root); //添加数据 auto obj = yyjson_mut_obj(doc); yyjson_mut_arr_add_val(root, obj); yyjson_mut_obj_add_strcpy(doc, obj, "mo", mo.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "mp", mp.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "show_time", strShowTime.c_str()); yyjson_mut_obj_add_strcpy(doc, obj, "start_time", strStartTime); yyjson_mut_obj_add_strcpy(doc, obj, "end_time", strEndTime); yyjson_mut_obj_add_strcpy(doc, obj, "mark", mark.c_str()); yyjson_mut_obj_add_int(doc, obj, "curr_val", curr_val); yyjson_mut_obj_add_int(doc, obj, "show_val", show_val); yyjson_mut_obj_add_int(doc, obj, "idx", idx); yyjson_mut_obj_add_int(doc, obj, "posi", posi); yyjson_mut_obj_add_int(doc, obj, "sunroof", sunroof); size_t json_len; auto json = yyjson_mut_write(doc, 0, &json_len); auto send_len = json_len + sizeof(HJDATAHEAD2) + 2; auto pack = new uint8_t[send_len]; auto packno = CAppService::Instance()->GetPackNo(); CHjDataConver::conver_sendpack(pack, (LPBYTE)json, json_len, 0, packno, E_ZL_PROTOCAL::ZL_MOVE, OR_DATA_INFO(0, 0, 1, 2, OPT_TYPE::OPT_ADD)); CSuperManager::Instance()->SendPack(pack, send_len, packno, E_ZL_PROTOCAL::ZL_MOVE, true); delete[] pack; pack = nullptr; free(json); yyjson_mut_doc_free(doc); } //判断锁闭力是否超限 void CResistAlarmMng::JudgeAlarm(CResistAlarmMng* pService, SUOBI_OVER_LIMIT_INFO* pSuobiOverInfo, time_t show_time, int show_val, eSuoBiPosi posi, string mo, string mp, uint32_t zzjno) { if (pSuobiOverInfo == nullptr || pSuobiOverInfo->enable == false) return; bool bNew = false; ALARM_INFO* pAlarmInfo = nullptr; bool bAlarm = false, bWarn = false; int alarm_value = 0, alarm_refer; time_t alarm_time = show_time; CTime ctAlarmTime = CTime(alarm_time / 1000); eLowHigh loworhigh = eLowHigh::LH_UNKNOWN; //0:最小值 1:最大值 { if (show_val < pSuobiOverInfo->alarm_low_limit) { bAlarm = true; alarm_refer = pSuobiOverInfo->alarm_low_limit; alarm_value = show_val; loworhigh = eLowHigh::LH_LOW; } else if (show_val < pSuobiOverInfo->warn_low_limit) { bWarn = true; alarm_refer = pSuobiOverInfo->warn_low_limit; alarm_value = show_val; loworhigh = eLowHigh::LH_LOW; } if (show_val > pSuobiOverInfo->alarm_high_limit) { bAlarm = true; alarm_refer = pSuobiOverInfo->alarm_high_limit; alarm_value = show_val; loworhigh = eLowHigh::LH_HIGH; } else if (show_val > pSuobiOverInfo->warn_high_limit) { bWarn = true; alarm_refer = pSuobiOverInfo->warn_high_limit; alarm_value = show_val; loworhigh = eLowHigh::LH_HIGH; } if (bAlarm == false && bWarn == false) { { std::lock_guard lock(pService->m_mtxAlarm); for (auto it = pService->m_lstUnConfirmAlarm.begin(); it != pService->m_lstUnConfirmAlarm.end();) { auto pAlarm = *it; if (pAlarm->no == (uint8_t)posi && pAlarm->type == eZL_ALARMTYPE::SUOBI_LOCK_LIMIT && pAlarm->recoveryTime.wYear < 2000 //预警和报警单独计算 && pAlarm->mo.compare(mo) == 0 && pAlarm->mp.compare(mp) == 0) { pAlarmInfo = pAlarm; if (pAlarmInfo) { //恢复 //1. 更新数据库 //2. 更新内存数据 //3. 上送恢复消息 if (ctAlarmTime.GetTime() == 0) ctAlarmTime = CTime::GetCurrentTime(); string recovery_time = ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE ID = %d;", recovery_time.c_str(), pAlarmInfo->id); CDBConnectPool::Instance()->DBExecuteSQL(sql); if (pAlarmInfo->ack_result == 1) { it = pService->m_lstUnConfirmAlarm.erase(it); continue; } else { ctAlarmTime.GetAsSystemTime(pAlarm->recoveryTime); } g_p315ClientManager->GetTcpClient()->SendAlarmData(zzjno, 2, CTime(pAlarmInfo->time).GetTime(), alarm_time / 1000, pAlarmInfo->type, posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT, pAlarmInfo->level, pAlarm->loworhigh, TIEDA_ACQ_VALUE(pAlarm->val, TIEDA_VAL_STATE::TVS_MOVEING), TIEDA_ACQ_VALUE(pAlarm->refer_val, TIEDA_VAL_STATE::TVS_MOVEING), 0); } } it++; } } return; } //查找是否原有的报警已存在 uint8_t level = 0; if (bAlarm) level = 1; { std::lock_guard lock(pService->m_mtxAlarm); for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarm->no == (uint8_t)posi && alarm->type == eZL_ALARMTYPE::SUOBI_LOCK_LIMIT && level == alarm->level && alarm->recoveryTime.wYear < 2000 //预警和报警单独计算 && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0) { pAlarmInfo = alarm; break; } } } ALARM_INFO *pNewAlarmInfo = nullptr; { bNew = true; pNewAlarmInfo = new ALARM_INFO; pNewAlarmInfo->event_id = hjfunc_GetGUID(); pNewAlarmInfo->rel_id = pAlarmInfo ? pAlarmInfo->event_id : ""; pNewAlarmInfo->id = ++pService->m_nAlarmID; pNewAlarmInfo->level = (bAlarm == 1); pNewAlarmInfo->mo = mo; pNewAlarmInfo->mp = mp; pNewAlarmInfo->no = (uint8_t)posi; ctAlarmTime.GetAsSystemTime(pNewAlarmInfo->time); pNewAlarmInfo->time.wMilliseconds = alarm_time % 1000; pNewAlarmInfo->type = eZL_ALARMTYPE::SUOBI_LOCK_LIMIT; pNewAlarmInfo->val = alarm_value; pNewAlarmInfo->refer_val = alarm_refer; pNewAlarmInfo->posi = (posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT); pNewAlarmInfo->loworhigh = loworhigh; pNewAlarmInfo->zzjno = zzjno; pNewAlarmInfo->sunroof = CSkylightMng::GetInstance()->IsSkylight(&pNewAlarmInfo->time); char szInfo[200] = { 0 }; sprintf_s(szInfo, sizeof(szInfo), "锁闭力超限,位置:%s, 报警值为%dN, 参考值为%dN", posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", alarm_value, alarm_refer); pNewAlarmInfo->desc = szInfo; lock_guard lock(pService->m_mtxAlarm); pService->m_lstUnConfirmAlarm.push_back(pNewAlarmInfo); } //send //if (bNew) //不再推送 { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pNewAlarmInfo, buffer); const char* output = buffer.GetString(); //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength()); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); } //主动推送315 //if (bNew) { g_p315ClientManager->GetTcpClient()->SendAlarmData(pNewAlarmInfo->zzjno, 1, CTime(pNewAlarmInfo->time).GetTime(), 0xFFFFFFFF, pNewAlarmInfo->type, posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT, pNewAlarmInfo->level, loworhigh, TIEDA_ACQ_VALUE(alarm_value, TIEDA_VAL_STATE::TVS_MOVEING), TIEDA_ACQ_VALUE(alarm_refer, TIEDA_VAL_STATE::TVS_MOVEING), 0); } //save //if (bNew) { CString sql; sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pNewAlarmInfo->id, pNewAlarmInfo->mo.c_str(), pNewAlarmInfo->mp.c_str(), pNewAlarmInfo->no, pNewAlarmInfo->type, ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"), pNewAlarmInfo->level, pNewAlarmInfo->desc.c_str(), pNewAlarmInfo->suggest.c_str(), pNewAlarmInfo->val, pNewAlarmInfo->event_id.c_str(), pNewAlarmInfo->rel_id.c_str(), uint8_t(pNewAlarmInfo->posi), uint8_t(pNewAlarmInfo->loworhigh), pNewAlarmInfo->refer_val, pNewAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) CSimpleLog::Error("执行语句失败" + sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pNewAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); //g_p315ClientManager->GetTcpClient()->SendAlarmData(pNewAlarmInfo->no, 1, ctAlarmTime.GetTime(), 0xFFFFFFFF, (WORD)pNewAlarmInfo->type, pNewAlarmInfo->val, 0, 0); delete[] pack; pack = nullptr; } } } } //判断转换阻力是否超限 void CResistAlarmMng::JudgeAlarm(CResistAlarmMng* pService, CONVERT_RESIST_OVER_LIMIT* pConvertOverLimit, time_t show_time, int show_val, eDaoChaPosi posi, string mo, string mp, uint32_t zzjno) { if (pConvertOverLimit == nullptr || pConvertOverLimit->enable == false) return; bool bNew = false; ALARM_INFO* pAlarmInfo = nullptr; bool bAlarm = false, bWarn = false; int alarm_value = show_val, alarm_refer; time_t alarm_time = show_time; CTime ctAlarmTime = CTime(alarm_time / 1000); { if (posi == eDaoChaPosi::DCP_INVERT2FIX) { if (show_val > pConvertOverLimit->up_alarm_high_limit) { bAlarm = true; alarm_refer = pConvertOverLimit->up_alarm_high_limit; } else if (show_val > pConvertOverLimit->up_warn_high_limit) { bWarn = true; alarm_refer = pConvertOverLimit->up_warn_high_limit; } } else if (posi == eDaoChaPosi::DCP_FIX2INVERT) { if (show_val > pConvertOverLimit->dw_alarm_low_limit) { bAlarm = true; alarm_refer = pConvertOverLimit->dw_alarm_low_limit; } else if (show_val > pConvertOverLimit->dw_warn_low_limit) { bWarn = true; alarm_refer = pConvertOverLimit->dw_warn_low_limit; } } if (bAlarm == false && bWarn == false) { { string strPosi= "方向:"; strPosi += (posi == eDaoChaPosi::DCP_FIX2INVERT ? "定扳反" : "反扳定"); std::lock_guard lock(pService->m_mtxAlarm); for (auto it = pService->m_lstUnConfirmAlarm.begin(); it != pService->m_lstUnConfirmAlarm.end();) { auto alarm = *it; if (alarm->no == 2 && alarm->type == eZL_ALARMTYPE::CONVERT_LIMIT //预警和报警单独计算 // && alarm->posi == posi && alarm->recoveryTime.wYear < 2000 && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0) //跟上次报警时间超过1小时,则算新报警 { pAlarmInfo = alarm; if (pAlarmInfo) { //恢复 //1. 更新数据库 //2. 更新内存数据 //3. 上送恢复消息 if (ctAlarmTime.GetTime() == 0) ctAlarmTime = CTime::GetCurrentTime(); string recovery_time = ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE ID = %d;", recovery_time.c_str(), pAlarmInfo->id); CDBConnectPool::Instance()->DBExecuteSQL(sql); if (pAlarmInfo->ack_result == 1) { it = pService->m_lstUnConfirmAlarm.erase(it); continue; } else { ctAlarmTime.GetAsSystemTime(alarm->recoveryTime); } g_p315ClientManager->GetTcpClient()->SendAlarmData(alarm->zzjno, 2, CTime(pAlarmInfo->time).GetTime(), alarm_time / 1000, pAlarmInfo->type, posi, pAlarmInfo->level, eLowHigh::LH_HIGH, TIEDA_ACQ_VALUE(alarm->val, TIEDA_VAL_STATE::TVS_MOVEING), TIEDA_ACQ_VALUE(alarm->refer_val, TIEDA_VAL_STATE::TVS_MOVEING), 0); } } ++it; } } return; } //查找是否原有的报警已存在 uint8_t level = 0; if (bAlarm) level = 1; { std::lock_guard lock(pService->m_mtxAlarm); for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarm->no == 2 && alarm->type == eZL_ALARMTYPE::CONVERT_LIMIT && level == alarm->level && alarm->recoveryTime.wYear < 2000 //预警和报警单独计算 && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0) { pAlarmInfo = alarm; break; } } } ALARM_INFO* pNewAlarmInfo = nullptr; { bNew = true; pNewAlarmInfo = new ALARM_INFO; pNewAlarmInfo->event_id = hjfunc_GetGUID(); pNewAlarmInfo->rel_id = pAlarmInfo ? pAlarmInfo->event_id : ""; pNewAlarmInfo->id = ++pService->m_nAlarmID; pNewAlarmInfo->level = (bAlarm == 1); pNewAlarmInfo->mo = mo; pNewAlarmInfo->mp = mp; pNewAlarmInfo->no = 2; ctAlarmTime.GetAsSystemTime(pNewAlarmInfo->time); pNewAlarmInfo->time.wMilliseconds = alarm_time % 1000; pNewAlarmInfo->type = eZL_ALARMTYPE::CONVERT_LIMIT; pNewAlarmInfo->val = alarm_value; pNewAlarmInfo->refer_val = alarm_refer; pNewAlarmInfo->posi = posi; pNewAlarmInfo->zzjno = zzjno; pNewAlarmInfo->sunroof = CSkylightMng::GetInstance()->IsSkylight(&pNewAlarmInfo->time); char szInfo[200] = { 0 }; sprintf_s(szInfo, sizeof(szInfo), "转换阻力超限,方向:%s, 报警值为%dN, 参考值为%dN", posi == eDaoChaPosi::DCP_FIX2INVERT ? "定扳反" : "反扳定", alarm_value, alarm_refer); pNewAlarmInfo->desc = szInfo; lock_guard lock(pService->m_mtxAlarm); pService->m_lstUnConfirmAlarm.push_back(pNewAlarmInfo); } //send //if (bNew) //不再推送 { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pNewAlarmInfo, buffer); const char* output = buffer.GetString(); //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength()); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); } //主动推送315 //if (bNew) { g_p315ClientManager->GetTcpClient()->SendAlarmData(pNewAlarmInfo->zzjno, 1, CTime(pNewAlarmInfo->time).GetTime(), 0xFFFFFFFF, pNewAlarmInfo->type, posi, pNewAlarmInfo->level, eLowHigh::LH_HIGH, TIEDA_ACQ_VALUE(alarm_value, TIEDA_VAL_STATE::TVS_MOVEING), TIEDA_ACQ_VALUE(alarm_refer, TIEDA_VAL_STATE::TVS_MOVEING), 0); } //save { CString sql; sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pNewAlarmInfo->id, pNewAlarmInfo->mo.c_str(), pNewAlarmInfo->mp.c_str(), pNewAlarmInfo->no, pNewAlarmInfo->type, ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"), pNewAlarmInfo->level, pNewAlarmInfo->desc.c_str(), pNewAlarmInfo->suggest.c_str(), pNewAlarmInfo->val, pNewAlarmInfo->event_id.c_str(), pNewAlarmInfo->rel_id.c_str(), uint8_t(pNewAlarmInfo->posi), uint8_t(pNewAlarmInfo->loworhigh), pNewAlarmInfo->refer_val, pNewAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) CSimpleLog::Error("执行语句失败" + sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pNewAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); //g_p315ClientManager->GetTcpClient()->SendAlarmData(pNewAlarmInfo->no, 1, ctAlarmTime.GetTime(), 0xFFFFFFFF, (WORD)pNewAlarmInfo->type, pNewAlarmInfo->val, 0, 0); delete[] pack; pack = nullptr; } } } } void CResistAlarmMng::JudgeAlarm(CResistAlarmMng* pService, FRICTION_OVER_LIMIT_INFO* pAlarmSet, time_t show_time, int showval, eDaoChaPosi posi, eUpOrDownInfo eUpOrDown, void* pMoMpInfo) { if (pAlarmSet == nullptr || pAlarmSet->enable == false) return; auto pInfo = (ST_MOMP_INFO*)pMoMpInfo; bool bNew = false; ALARM_INFO* pAlarmInfo = nullptr; int show_val = showval < 0 ? -showval : showval; bool bAlarm = false, bWarn = false; int alarm_value = show_val, alarm_refer; time_t alarm_time = show_time; CTime ctAlarmTime = CTime(alarm_time / 1000); eLowHigh loworhigh = eLowHigh::LH_UNKNOWN; //0:最小值 1:最大值 { if (show_val >= pAlarmSet->up_alarm_low_limit) { bAlarm = true; alarm_refer = pAlarmSet->up_alarm_low_limit; alarm_value = show_val; loworhigh = eLowHigh::LH_HIGH; } else if (show_val <= pAlarmSet->dw_alarm_high_limit) { bAlarm = true; alarm_refer = pAlarmSet->dw_alarm_high_limit; alarm_value = show_val; loworhigh = eLowHigh::LH_LOW; } else if (show_val >= pAlarmSet->up_warn_low_limit) { bWarn = true; alarm_refer = pAlarmSet->up_warn_low_limit; alarm_value = show_val; loworhigh = eLowHigh::LH_HIGH; } else if (show_val <= pAlarmSet->dw_warn_high_limit) { bWarn = true; alarm_refer = pAlarmSet->dw_warn_high_limit; alarm_value = show_val; loworhigh = eLowHigh::LH_LOW; } if (bAlarm == false && bWarn == false) { { std::lock_guard lock(pService->m_mtxAlarm); for (auto it = pService->m_lstUnConfirmAlarm.begin(); it != pService->m_lstUnConfirmAlarm.end();) { auto alarm = *it; if (alarm->no == 2 && alarm->type == pAlarmSet->type //预警和报警单独计算 // && alarm->posi == posi && alarm->recoveryTime.wYear < 2000 && alarm->mo.compare(pInfo->mo) == 0 && alarm->mp.compare(pInfo->mp) == 0) //跟上次报警时间超过1小时,则算新报警 { pAlarmInfo = alarm; if (pAlarmInfo) { //恢复 //1. 更新数据库 //2. 更新内存数据 //3. 上送恢复消息 if (ctAlarmTime.GetTime() == 0) ctAlarmTime = CTime::GetCurrentTime(); string recovery_time = ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE rm_alarm SET recovery_time='%s' WHERE ID = %d;", recovery_time.c_str(), pAlarmInfo->id); CDBConnectPool::Instance()->DBExecuteSQL(sql); if (pAlarmInfo->ack_result == 1) { it = pService->m_lstUnConfirmAlarm.erase(it); continue; } else { ctAlarmTime.GetAsSystemTime(alarm->recoveryTime); } g_p315ClientManager->GetTcpClient()->SendAlarmData(alarm->zzjno, 2, CTime(pAlarmInfo->time).GetTime(), alarm_time / 1000, pAlarmInfo->type, posi, pAlarmInfo->level, loworhigh, TIEDA_ACQ_VALUE(alarm->val, TIEDA_VAL_STATE::TVS_MOVEING), TIEDA_ACQ_VALUE(alarm->refer_val, TIEDA_VAL_STATE::TVS_MOVEING), 0); } } ++it; } } return; } //查找是否原有的报警已存在 uint8_t level = 0; if (bAlarm) level = 1; { std::lock_guard lock(pService->m_mtxAlarm); for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarm->no == 2 && alarm->type == pAlarmSet->type && level == alarm->level && alarm->recoveryTime.wYear < 2000 //预警和报警单独计算 && alarm->mo.compare(pInfo->mo) == 0 && alarm->mp.compare(pInfo->mp) == 0) { pAlarmInfo = alarm; break; } } } ALARM_INFO* pNewAlarmInfo = nullptr; { bNew = true; pNewAlarmInfo = new ALARM_INFO; pNewAlarmInfo->event_id = hjfunc_GetGUID(); pNewAlarmInfo->rel_id = pAlarmInfo ? pAlarmInfo->event_id : ""; pNewAlarmInfo->id = ++pService->m_nAlarmID; pNewAlarmInfo->level = (bAlarm == 1); pNewAlarmInfo->mo = pInfo->mo; pNewAlarmInfo->mp = pInfo->mp; pNewAlarmInfo->no = 2; ctAlarmTime.GetAsSystemTime(pNewAlarmInfo->time); pNewAlarmInfo->time.wMilliseconds = alarm_time % 1000; pNewAlarmInfo->type = pAlarmSet->type; pNewAlarmInfo->val = alarm_value; pNewAlarmInfo->refer_val = alarm_refer; pNewAlarmInfo->posi = posi; pNewAlarmInfo->zzjno = pInfo->zzjno; pNewAlarmInfo->sunroof = CSkylightMng::GetInstance()->IsSkylight(&pNewAlarmInfo->time); char szInfo[200] = { 0 }; sprintf_s(szInfo, sizeof(szInfo), "摩擦力稳态值%s超限,报警值为%dN, 参考值为%dN", loworhigh == eLowHigh::LH_LOW ? "下" : "上", alarm_value, alarm_refer); pNewAlarmInfo->desc = szInfo; lock_guard lock(pService->m_mtxAlarm); pService->m_lstUnConfirmAlarm.push_back(pNewAlarmInfo); } //send if (bNew) //不再推送 { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pNewAlarmInfo, buffer); const char* output = buffer.GetString(); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); } //主动推送315 if (bNew) { g_p315ClientManager->GetTcpClient()->SendAlarmData(pNewAlarmInfo->zzjno, 1, CTime(pNewAlarmInfo->time).GetTime(), 0xFFFFFFFF, pNewAlarmInfo->type, posi, pNewAlarmInfo->level, loworhigh, TIEDA_ACQ_VALUE(alarm_value, TIEDA_VAL_STATE::TVS_MOVEING), TIEDA_ACQ_VALUE(alarm_refer, TIEDA_VAL_STATE::TVS_MOVEING), 0); } //save { CString sql; sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pNewAlarmInfo->id, pNewAlarmInfo->mo.c_str(), pNewAlarmInfo->mp.c_str(), pNewAlarmInfo->no, pNewAlarmInfo->type, ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"), pNewAlarmInfo->level, pNewAlarmInfo->desc.c_str(), pNewAlarmInfo->suggest.c_str(), pNewAlarmInfo->val, pNewAlarmInfo->event_id.c_str(), pNewAlarmInfo->rel_id.c_str(), uint8_t(pNewAlarmInfo->posi), uint8_t(pNewAlarmInfo->loworhigh), pNewAlarmInfo->refer_val, pNewAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) CSimpleLog::Error("执行语句失败" + sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pNewAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); delete[] pack; pack = nullptr; } } } } void CResistAlarmMng::JudgeAlarm2(CResistAlarmMng* pService, RETENSION_FORCE_DROP* pRetensionForceDropInfo, time_t show_time, int show_val, eSuoBiPosi posi, string mo, string mp, uint32_t zzjno) { if (pRetensionForceDropInfo == nullptr || pRetensionForceDropInfo->enable == false) return; bool bNew = false; ALARM_INFO* pAlarmInfo = nullptr; bool bAlarm = false, bWarn = false; int alarm_value = 0, alarm_refer; time_t alarm_time = show_time; CTime ctAlarmTime = CTime(alarm_time / 1000); eLowHigh loworhigh = eLowHigh::LH_HIGH; //0:最小值 1:最大值 { if (show_val < pRetensionForceDropInfo->dw_alarm_low_drop) { bWarn = true; alarm_refer = pRetensionForceDropInfo->dw_alarm_low_drop; alarm_value = show_val; //loworhigh = eLowHigh::LH_LOW; } if (bAlarm == false && bWarn == false) { if (g_strMoMp.compare(mo + "." + mp) == 0) SPDLOG_INFO("[保持力下降]{}.{} 未检测到下降. {} ", mo, mp, show_val); { std::lock_guard lock(pService->m_mtxAlarm); for (auto it = pService->m_lstUnConfirmAlarm.begin(); it != pService->m_lstUnConfirmAlarm.end();) { auto pAlarm = *it; if (pAlarm->no == (uint8_t)posi && pAlarm->type == eZL_ALARMTYPE::RETENSION_FORCE && pAlarm->recoveryTime.wYear < 2000 //预警和报警统一恢复 && pAlarm->mo.compare(mo) == 0 && pAlarm->mp.compare(mp) == 0) { pAlarmInfo = pAlarm; if (pAlarmInfo) { //恢复 //1. 更新数据库 //2. 更新内存数据 //3. 上送恢复消息 if (ctAlarmTime.GetTime() == 0) ctAlarmTime = CTime::GetCurrentTime(); string recovery_time = ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE ID = %d;", recovery_time.c_str(), pAlarmInfo->id); CDBConnectPool::Instance()->DBExecuteSQL(sql); if (pAlarmInfo->ack_result == 1) { it = pService->m_lstUnConfirmAlarm.erase(it); continue; } else { ctAlarmTime.GetAsSystemTime(pAlarm->recoveryTime); } g_p315ClientManager->GetTcpClient()->SendAlarmData(zzjno, 2, CTime(pAlarmInfo->time).GetTime(), ctAlarmTime.GetTime(), pAlarmInfo->type, posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT, pAlarmInfo->level, pAlarm->loworhigh, TIEDA_ACQ_VALUE(pAlarm->val, TIEDA_VAL_STATE::TVS_AFTER_MOVE), TIEDA_ACQ_VALUE(pAlarm->refer_val, TIEDA_VAL_STATE::TVS_AFTER_MOVE), 0); } } it++; } } return; } SPDLOG_INFO("[保持力下降]{}.{} 检测到下降. {} ", mo, mp, show_val); //查找是否原有的报警已存在 uint8_t level = 0; if (bAlarm) level = 1; { std::lock_guard lock(pService->m_mtxAlarm); for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarm->no == (uint8_t)posi && alarm->type == eZL_ALARMTYPE::RETENSION_FORCE && level == alarm->level && alarm->recoveryTime.wYear < 2000 //预警和报警单独计算 && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0) { pAlarmInfo = alarm; break; } } } if (pAlarmInfo == nullptr) { bNew = true; pAlarmInfo = new ALARM_INFO; pAlarmInfo->event_id = hjfunc_GetGUID(); pAlarmInfo->id = ++pService->m_nAlarmID; pAlarmInfo->level = (bAlarm == 1); pAlarmInfo->mo = mo; pAlarmInfo->mp = mp; pAlarmInfo->no = (uint8_t)posi; ctAlarmTime.GetAsSystemTime(pAlarmInfo->time); pAlarmInfo->time.wMilliseconds = alarm_time % 1000; pAlarmInfo->type = eZL_ALARMTYPE::RETENSION_FORCE; pAlarmInfo->val = alarm_value; pAlarmInfo->refer_val = alarm_refer; pAlarmInfo->posi = (posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT); pAlarmInfo->loworhigh = loworhigh; pAlarmInfo->zzjno = zzjno; pAlarmInfo->sunroof = CSkylightMng::GetInstance()->IsSkylight(&pAlarmInfo->time); char szInfo[200] = { 0 }; sprintf_s(szInfo, sizeof(szInfo), "保持力下降,位置:%s, 报警值为%dN, 参考值为%dN", posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", alarm_value, alarm_refer); pAlarmInfo->desc = szInfo; lock_guard lock(pService->m_mtxAlarm); pService->m_lstUnConfirmAlarm.push_back(pAlarmInfo); } //send if (bNew) //不再推送 { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pAlarmInfo, buffer); const char* output = buffer.GetString(); //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength()); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); } //主动推送315 if (bNew) { g_p315ClientManager->GetTcpClient()->SendAlarmData(zzjno, 1, CTime(pAlarmInfo->time).GetTime(), 0xFFFFFFFF, pAlarmInfo->type, posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT, pAlarmInfo->level, loworhigh, TIEDA_ACQ_VALUE(alarm_value, TIEDA_VAL_STATE::TVS_AFTER_MOVE), TIEDA_ACQ_VALUE(alarm_refer, TIEDA_VAL_STATE::TVS_AFTER_MOVE), 0); } //save if (bNew) { CString sql; sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, pAlarmInfo->type, ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val, pAlarmInfo->event_id.c_str(), pAlarmInfo->rel_id.c_str(), uint8_t(pAlarmInfo->posi), uint8_t(pAlarmInfo->loworhigh), pAlarmInfo->refer_val, pAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) CSimpleLog::Error("执行语句失败" + sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); delete[] pack; pack = nullptr; } } } } void CResistAlarmMng::JudgeAlarm(CResistAlarmMng* pService, RETENSION_FORCE_DROP* pAlarmSet, time_t show_time, int show_val, eSuoBiPosi posi, string mo, string mp, void* pInfo, int detectToday, eDaoChaPosi posiLast, BOOL isRedAlarm, BOOL alarmStatus) { if (pAlarmSet == nullptr) { return; } if (show_val < 0) { return; } ST_MOMP_INFO* pMoMpInfo = (ST_MOMP_INFO*)pInfo; CTime ctShowTime(show_time / 1000); bool bSkylight = CSkylightMng::GetInstance()->IsSkylight(&ctShowTime); if (pAlarmSet->enable == false) { return; } eLowHigh loworhigh = eLowHigh::LH_UNKNOWN; int alarm_refer = 0, alarm_value = 0; bool bAlarm = false; int level = 0; if (show_val < pAlarmSet->dw_alarm_low_drop && (alarmStatus ==0 || alarmStatus ==1) && std::abs(pAlarmSet->dw_alarm_low_drop) <= 100000) { BOOL judgePass = false; if (isRedAlarm) { judgePass = JudgePass(mo, mp); } if (!isRedAlarm ||(isRedAlarm &&!judgePass)) { bAlarm = true; level = 1; alarm_refer = pAlarmSet->dw_alarm_low_drop; alarm_value = show_val; loworhigh = eLowHigh::LH_LOW; SPDLOG_INFO("[最低值红线保持力报警]:{}.{},发生时间:{},报警值:{},参考值:{},是否红线密贴:{},是否红线密贴过车:{}", mo, mp, (LPCSTR)(CTime(show_time / 1000).Format("%Y-%m-%d %H:%M:%S")), alarm_value, alarm_refer, isRedAlarm==true?"是":"否", judgePass == true ? "是" : "否"); } } if (loworhigh == eLowHigh::LH_UNKNOWN && isRedAlarm!=1 && pAlarmSet->is_page_dyna && (alarmStatus == 0 || alarmStatus == 2)) { int nRatio = show_val * 100 / detectToday; //下降20%或上升40% 进行预警 if (std::abs(nRatio) <= (100 - pAlarmSet->alarm_low_percent)&& detectToday<40000 && detectToday > 3000 && pAlarmSet->alarm_low_percent>=5 && pAlarmSet->alarm_low_percent<=95) { level = 0; loworhigh = eLowHigh::LH_LOW; alarm_value = show_val; alarm_refer = detectToday* (100 - pAlarmSet->alarm_low_percent)/100; SPDLOG_INFO("[动态下降保持力报警]:{}.{},发生时间:{},报警值:{},参考值:{},下降百分比:{}%,当日标定值:{}", mo, mp, (LPCSTR)(CTime(show_time / 1000).Format("%Y-%m-%d %H:%M:%S")), alarm_value, alarm_refer, pAlarmSet->alarm_low_percent, detectToday); } else if (std::abs(nRatio) >= (100 + pAlarmSet->alarm_high_percent) && detectToday < 40000 && detectToday > 3000 && pAlarmSet->alarm_high_percent >= 5 && pAlarmSet->alarm_high_percent <= 95) { level = 0; loworhigh = eLowHigh::LH_HIGH; alarm_value = show_val; alarm_refer = detectToday * (100 + pAlarmSet->alarm_high_percent)/100; SPDLOG_INFO("[动态上升保持力报警]:{}.{},发生时间:{},报警值:{},参考值:{},上升百分比:{}%,当日标定值:{}", mo, mp, (LPCSTR)(CTime(show_time / 1000).Format("%Y-%m-%d %H:%M:%S")), alarm_value, alarm_refer, pAlarmSet->alarm_high_percent, detectToday); } } ALARM_INFO* pAlarmInfo = nullptr; bool bNew = false; //产生预警 if (loworhigh != eLowHigh::LH_UNKNOWN) { //查找是否原有的报警已存在 { std::lock_guard lock(pService->m_mtxAlarm); for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarm->no == (uint8_t)posi && alarm->type == eZL_ALARMTYPE::RETENSION_FORCE && alarm->recoveryTime.wYear < 2000 && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0 && alarm->ack_result==0) { pAlarmInfo = alarm; break; } } } if (pAlarmInfo == nullptr) { pAlarmInfo = new ALARM_INFO; pAlarmInfo->id = ++pService->m_nAlarmID; pAlarmInfo->event_id = hjfunc_GetGUID(); pAlarmInfo->level = level; pAlarmInfo->mo = mo; pAlarmInfo->mp = mp; pAlarmInfo->no = (uint8_t)posi; ctShowTime.GetAsSystemTime(pAlarmInfo->time); pAlarmInfo->time.wMilliseconds = show_time % 1000; pAlarmInfo->type = eZL_ALARMTYPE::RETENSION_FORCE; pAlarmInfo->val = alarm_value; pAlarmInfo->refer_val = alarm_refer; pAlarmInfo->posi = (posi == eSuoBiPosi::SB_FIX? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT); pAlarmInfo->loworhigh = loworhigh; pAlarmInfo->zzjno = pMoMpInfo->zzjno; pAlarmInfo->sunroof = bSkylight; char szInfo[200] = { 0 }; if (level == 1) { sprintf_s(szInfo, sizeof(szInfo), "保持力超最低值报警,位置:%s, 报警值为%dN, 参考值为%dN", posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", show_val, alarm_refer); } else if (level == 0 && loworhigh == eLowHigh::LH_LOW) { sprintf_s(szInfo, sizeof(szInfo), "保持力下降超%d%%预警,位置:%s, 报警值为%dN, 参考值为%dN", pAlarmSet->alarm_low_percent, posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", show_val, alarm_refer); } else if (level == 0 && loworhigh == eLowHigh::LH_HIGH) { sprintf_s(szInfo, sizeof(szInfo), "保持力上升超%d%%预警,位置:%s, 报警值为%dN, 参考值为%dN", pAlarmSet->alarm_high_percent, posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", show_val, alarm_refer); } pAlarmInfo->desc = szInfo; if (!bSkylight) { bNew = true; lock_guard lock(pService->m_mtxAlarm); pService->m_lstUnConfirmAlarm.push_back(pAlarmInfo); } SPDLOG_INFO("[保持力产生新报警]:{}.{},描述:{},目前队列报警数:{},是否天窗:{}",mo, mp,pAlarmInfo->desc, pService->m_lstUnConfirmAlarm.size(),bSkylight==true?"是":"否"); }else{ pAlarmInfo->id = ++pService->m_nAlarmID; ctShowTime.GetAsSystemTime(pAlarmInfo->time); pAlarmInfo->time.wMilliseconds = show_time % 1000; pAlarmInfo->val = alarm_value; pAlarmInfo->level = level; pAlarmInfo->refer_val = alarm_refer; pAlarmInfo->posi = (posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT); pAlarmInfo->loworhigh = loworhigh; pAlarmInfo->zzjno = pMoMpInfo->zzjno; pAlarmInfo->sunroof = bSkylight; pAlarmInfo->event_id = hjfunc_GetGUID(); char szInfo[200] = { 0 }; if (level == 1) { sprintf_s(szInfo, sizeof(szInfo), "保持力超最低值报警,位置:%s, 报警值为%dN, 参考值为%dN", posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", show_val, alarm_refer); } else if (level == 0 && loworhigh == eLowHigh::LH_LOW) { sprintf_s(szInfo, sizeof(szInfo), "保持力下降超%d%%预警,位置:%s, 报警值为%dN, 参考值为%dN", pAlarmSet->alarm_low_percent, posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", show_val, alarm_refer); } else if (level == 0 && loworhigh == eLowHigh::LH_HIGH) { sprintf_s(szInfo, sizeof(szInfo), "保持力上升超%d%%预警,位置:%s, 报警值为%dN, 参考值为%dN", pAlarmSet->alarm_high_percent, posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", show_val, alarm_refer); } pAlarmInfo->desc = szInfo; SPDLOG_INFO("[保持力存在相同报警]:{}.{},描述:{},目前队列报警数:{},是否天窗:{}", mo, mp, pAlarmInfo->desc, pService->m_lstUnConfirmAlarm.size(), bSkylight == true ? "是" : "否"); } //send if (bNew) { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pAlarmInfo, buffer); const char* output = buffer.GetString(); //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength()); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); SPDLOG_INFO("[保持力报警发送页面]:{}.{},是否红线:{},发送内容:{}", mo, mp,level==1?"红线报警":"动态保持力报警", output); } //主动推送315 if (bNew && level==1){ g_p315ClientManager->GetTcpClient()->SendAlarmData(pAlarmInfo->zzjno, 1, CTime(pAlarmInfo->time).GetTime(), 0xFFFFFFFF, pAlarmInfo->type, posiLast, pAlarmInfo->level, loworhigh, TIEDA_ACQ_VALUE(pAlarmInfo->val, TIEDA_VAL_STATE::TVS_AFTER_MOVE), TIEDA_ACQ_VALUE(pAlarmInfo->refer_val, TIEDA_VAL_STATE::TVS_AFTER_MOVE), 0); SPDLOG_INFO("[保持力报警发送315]:{}.{}", mo, mp); } CString sql; if (bNew) { sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, pAlarmInfo->type, ctShowTime.Format("%Y-%m-%d %H:%M:%S"), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val, pAlarmInfo->event_id.c_str(), pAlarmInfo->rel_id.c_str(), uint8_t(pAlarmInfo->posi), uint8_t(pAlarmInfo->loworhigh), pAlarmInfo->refer_val, pAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) SPDLOG_INFO("[保持力报警执行语句失败,sql]:{}", sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); delete[] pack; pack = nullptr; } } } else{//恢复 { std::lock_guard lock(pService->m_mtxAlarm); if (alarmStatus == 31) { level = 1; } if (alarmStatus == 30) { level = 0; } for (auto it = pService->m_lstUnConfirmAlarm.begin(); it != pService->m_lstUnConfirmAlarm.end();){ auto pAlarm = *it; if (pAlarm->no == (uint8_t)posi && pAlarm->type == eZL_ALARMTYPE::RETENSION_FORCE && pAlarm->recoveryTime.wYear < 2000 && pAlarm->mo.compare(mo) == 0 && pAlarm->mp.compare(mp) == 0 && pAlarm->level ==level){ pAlarmInfo = pAlarm; if (pAlarmInfo){ //恢复 //1. 更新数据库 //2. 更新内存数据 //3. 上送恢复消息 if (ctShowTime.GetTime() == 0) ctShowTime = CTime::GetCurrentTime(); string recovery_time = ctShowTime.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE mo = '%s' and mp = '%s' and no = %d and type = %d and level = %d and recovery_time< '2000';", recovery_time.c_str(), pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, pAlarmInfo->type,pAlarmInfo->level); CDBConnectPool::Instance()->DBExecuteSQL(sql); if (pAlarmInfo->ack_result == 1){ it = pService->m_lstUnConfirmAlarm.erase(it); continue; } else{ ctShowTime.GetAsSystemTime(pAlarm->recoveryTime); } if (pAlarmInfo->level == 1) { g_p315ClientManager->GetTcpClient()->SendAlarmData(pAlarmInfo->zzjno, 2, CTime(pAlarmInfo->time).GetTime(), ctShowTime.GetTime(), pAlarmInfo->type, pAlarmInfo->posi, pAlarmInfo->level, pAlarm->loworhigh, TIEDA_ACQ_VALUE(pAlarm->val, TIEDA_VAL_STATE::TVS_AFTER_MOVE), TIEDA_ACQ_VALUE(pAlarm->refer_val, TIEDA_VAL_STATE::TVS_AFTER_MOVE), 0); } SPDLOG_INFO("[保持力恢复]:{}.{},恢复sql:{},确认结果:{},等级:{}",mo, mp, sql, pAlarmInfo->ack_result == 1?"确认":"未确认",level==0?"预警":"报警"); } } it++; } } return; } } void CResistAlarmMng::JudgeAlarm3(CResistAlarmMng* pService, RETENSION_FORCE_DROP* pRetensionForceDropInfo, time_t show_time, int show_val, eSuoBiPosi posi, string mo, string mp, uint32_t zzjno) { if (pRetensionForceDropInfo == nullptr || pRetensionForceDropInfo->enable == false) return; bool bNew = false; ALARM_INFO* pAlarmInfo = nullptr; bool bAlarm = false, bWarn = false; int alarm_value = 0, alarm_refer; time_t alarm_time = show_time; CTime ctAlarmTime = CTime(alarm_time / 1000); eLowHigh loworhigh = eLowHigh::LH_HIGH; //0:最小值 1:最大值 { if (show_val < pRetensionForceDropInfo->dw_alarm_low_drop) { bAlarm = true; alarm_refer = pRetensionForceDropInfo->dw_alarm_low_drop; alarm_value = show_val; //loworhigh = eLowHigh::LH_LOW; } if (bAlarm == false && bWarn == false) { { std::lock_guard lock(pService->m_mtxAlarm); for (auto it = pService->m_lstUnConfirmAlarm.begin(); it != pService->m_lstUnConfirmAlarm.end();) { auto pAlarm = *it; if (pAlarm->no == (uint8_t)posi && pAlarm->type == eZL_ALARMTYPE::RETENSION_FORCE && pAlarm->recoveryTime.wYear < 2000 //预警和报警统一恢复 && pAlarm->mo.compare(mo) == 0 && pAlarm->mp.compare(mp) == 0) { pAlarmInfo = pAlarm; if (pAlarmInfo) { //恢复 //1. 更新数据库 //2. 更新内存数据 //3. 上送恢复消息 if (ctAlarmTime.GetTime() == 0) ctAlarmTime = CTime::GetCurrentTime(); string recovery_time = ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE ID = %d;", recovery_time.c_str(), pAlarmInfo->id); CDBConnectPool::Instance()->DBExecuteSQL(sql); if (pAlarmInfo->ack_result == 1) { it = pService->m_lstUnConfirmAlarm.erase(it); continue; } else { ctAlarmTime.GetAsSystemTime(pAlarm->recoveryTime); } g_p315ClientManager->GetTcpClient()->SendAlarmData(zzjno, 2, CTime(pAlarmInfo->time).GetTime(), alarm_time / 1000, pAlarmInfo->type, posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT, pAlarmInfo->level, pAlarm->loworhigh, TIEDA_ACQ_VALUE(pAlarm->val, TIEDA_VAL_STATE::TVS_AFTER_MOVE), TIEDA_ACQ_VALUE(pAlarm->refer_val, TIEDA_VAL_STATE::TVS_AFTER_MOVE), 0); } } it++; } } return; } //查找是否原有的报警已存在 uint8_t level = 0; if (bAlarm) level = 1; { std::lock_guard lock(pService->m_mtxAlarm); for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarm->no == (uint8_t)posi && alarm->type == eZL_ALARMTYPE::RETENSION_FORCE && level == alarm->level && alarm->recoveryTime.wYear < 2000 //预警和报警单独计算 && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0) { pAlarmInfo = alarm; break; } } } ALARM_INFO* pNewAlarmInfo = nullptr; { bNew = true; pNewAlarmInfo = new ALARM_INFO; pNewAlarmInfo->event_id = hjfunc_GetGUID(); pNewAlarmInfo->rel_id = pAlarmInfo ? pAlarmInfo->event_id : ""; pNewAlarmInfo->id = ++pService->m_nAlarmID; pNewAlarmInfo->level = (bAlarm == 1); pNewAlarmInfo->mo = mo; pNewAlarmInfo->mp = mp; pNewAlarmInfo->no = (uint8_t)posi; ctAlarmTime.GetAsSystemTime(pNewAlarmInfo->time); pNewAlarmInfo->time.wMilliseconds = alarm_time % 1000; pNewAlarmInfo->type = eZL_ALARMTYPE::RETENSION_FORCE; pNewAlarmInfo->val = alarm_value; pNewAlarmInfo->refer_val = alarm_refer; pNewAlarmInfo->posi = (posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT); pNewAlarmInfo->loworhigh = loworhigh; pNewAlarmInfo->zzjno = zzjno; pNewAlarmInfo->sunroof = CSkylightMng::GetInstance()->IsSkylight(&pNewAlarmInfo->time); char szInfo[200] = { 0 }; sprintf_s(szInfo, sizeof(szInfo), "保持力下降,位置:%s, 报警值为%dN, 参考值为%dN", posi == eSuoBiPosi::SB_FIX ? "定位" : "反位", alarm_value, alarm_refer); pNewAlarmInfo->desc = szInfo; lock_guard lock(pService->m_mtxAlarm); pService->m_lstUnConfirmAlarm.push_back(pNewAlarmInfo); } //send //if (bNew) //不再推送 { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pNewAlarmInfo, buffer); const char* output = buffer.GetString(); //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength()); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); } //主动推送315 //if (bNew) { g_p315ClientManager->GetTcpClient()->SendAlarmData(zzjno, 1, CTime(pNewAlarmInfo->time).GetTime(), 0xFFFFFFFF, pNewAlarmInfo->type, posi == eSuoBiPosi::SB_FIX ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT, pNewAlarmInfo->level, loworhigh, TIEDA_ACQ_VALUE(alarm_value, TIEDA_VAL_STATE::TVS_AFTER_MOVE), TIEDA_ACQ_VALUE(alarm_refer, TIEDA_VAL_STATE::TVS_AFTER_MOVE), 0); } //save //if (bNew) { CString sql; sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pNewAlarmInfo->id, pNewAlarmInfo->mo.c_str(), pNewAlarmInfo->mp.c_str(), pNewAlarmInfo->no, pNewAlarmInfo->type, ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"), pNewAlarmInfo->level, pNewAlarmInfo->desc.c_str(), pNewAlarmInfo->suggest.c_str(), pNewAlarmInfo->val, pNewAlarmInfo->event_id.c_str(), pNewAlarmInfo->rel_id.c_str(), uint8_t(pNewAlarmInfo->posi), uint8_t(pNewAlarmInfo->loworhigh), pNewAlarmInfo->refer_val, pNewAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) CSimpleLog::Error("执行语句失败" + sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pNewAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); //g_p315ClientManager->GetTcpClient()->SendAlarmData(pNewAlarmInfo->no, 1, ctAlarmTime.GetTime(), 0xFFFFFFFF, (WORD)pNewAlarmInfo->type, pNewAlarmInfo->val, 0, 0); delete[] pack; pack = nullptr; } } } } BOOL ConmpareValue(std::map::const_iterator i, std::map::const_iterator j, int refer_value, int& hight_num, int& low_num) { int start_value = 0; for (; i != j; i++) { if (i->second > refer_value) { if (start_value == 1) { //原来大于,现在也是大于 continue; } else { //原来小于或者无效,现在大于 start_value = 1; hight_num++; } } else { if (start_value == -1) { //原来小于,现在小于等于 continue; } else { //原来大于或者无效,现在小于 start_value = -1; low_num++; } } } return TRUE; } void CResistAlarmMng::ThreadProcAlarmSet(DWORD_PTR param,CString strIniPath) { auto pService = (CResistAlarmMng*)param; Sleep(2000); time_t tmNow; bool bLock = false; char szTemp[100] = { 0 }; int detectTimeByna = ::GetPrivateProfileInt("SET", "retension_dynamic", 600, strIniPath);//动态保持力检测时间为10分钟 600 int detectTimeRed = ::GetPrivateProfileInt("SET", "retension_red", 30, strIniPath);//红线保持力检测时间为30秒 30 int detectFourAlarm = ::GetPrivateProfileInt("SET", "retension_alarm", 14400, strIniPath);//四个小时重复报警,4 * 60 * 60 time_t detectTimeBynaTime = 0; time_t detectFourAlarmTime = 0; int detectToday0 = 3000;//定位保持力参考值 time_t detectTodayTime0=0; int detectToday1 = 3000;//反位保持力参考值 time_t detectTodayTime1=0; int detectToday01 = 3000;//保持力参考值 eDaoChaPosi posiToday = eDaoChaPosi::DCP_FIX; //当日位置 eDaoChaPosi posiLast = eDaoChaPosi::DCP_FIX; //最近一次过车位置 int alarmStatus = 1;// 0:板动报警;1:红线报警;2:动态报警; 3:报警恢复 int test = 0; do { if (bLock) { g_lockSync.Unlock(); bLock = false; } Sleep(1000); time(&tmNow); if (tmNow == pService->m_lastDetectTime) continue; pService->m_lastDetectTime = tmNow; bLock = true; g_lockSync.ReadLock(); //1秒判断一次 for (const auto& item : pService->m_alarm_set) { if (item.second == nullptr) continue; if (item.second->enable == false) continue; if (item.second->type != eZL_ALARMTYPE::MAX_OVER_LIMIT) //这个逻辑里面只支持这两种 continue; if (item.second->no < 0 || item.second->no > 2) continue; int nPos = item.first.find('.'); if (nPos == -1) continue; int nPos2 = item.first.find('.', nPos + 1); if (nPos2 == -1) continue; string mo = item.first.substr(0, nPos); string mp = item.first.substr(nPos + 1, nPos2 - nPos - 1); string momp = item.first.substr(0, nPos2); bool bNew = false; ALARM_INFO *pAlarmInfo = nullptr; CTime ctAlarmTime; string imei; int idx; auto ret = CMonitorObjectMng::Instance()->MOMP2IMEI(momp, imei, idx); if (ret == false) continue; #ifdef _DEBUG if (strcmp("860588048955283", imei.c_str()) != 0) continue; #endif auto pDevice = CDeviceMng::Instance()->Find(imei); if (pDevice == nullptr) { CSimpleLog::Error(("找不到imei(" + imei + ")" + std::to_string(__LINE__)).c_str()); continue; } int desc_type = 0; bool bAlarm = false, bWarn = false; int alarm_value = 0; time_t alarm_time = 0; eDaoChaPosi posi = eDaoChaPosi::DCP_UNKNOWN; int high_alarm_limit = INT_MAX, high_warn_limit = INT_MAX, low_alarm_limit = INT_MIN, low_warn_limit = INT_MIN, alarm_refer = INT_MAX; time_t tmNow; time(&tmNow); BASE_INFO* pAlarmSet = item.second; do{ Sleep(0); lock_guard lock(pDevice->m_mtx); std::map* pData = pDevice->GetMapData(idx, item.second->no); assert(pData); if (pData == nullptr) continue; if (pData->size() == 0) continue; if (item.second == 0) continue; if (item.second->type == eZL_ALARMTYPE::MAX_OVER_LIMIT) { auto pInfo = (MAX_OVER_LIMIT_INFO*)pAlarmSet; #ifdef _DEBUG if (pInfo->tmLastCheckTime > pData->rbegin()->first) pInfo->tmLastCheckTime = pData->rbegin()->first; #endif auto it = pData->cbegin(); if (pInfo->tmLastCheckTime == 0) pInfo->tmLastCheckTime = pData->rbegin()->first; else if (pInfo->tmLastCheckTime != 0) it = pData->find(pInfo->tmLastCheckTime); if (it == pData->cend()) { it = pData->find(pInfo->tmLastCheckTime / 1000 * 1000); if (it == pData->cend()) { pInfo->tmLastCheckTime = pData->rbegin()->first; continue; } } if (pInfo->tmLastCheckTime == pData->rbegin()->first) //没有新的数据 continue; #ifdef _DEBUG TRACE("%s.%s.%d.%d lastcheck:%s now:%s\r\n", mo.c_str(), mp.c_str(), pInfo->no, (int)eZL_ALARMTYPE::MAX_OVER_LIMIT, CTime(pInfo->tmLastCheckTime / 1000).Format("%Y-%m-%d %H:%M:%S"), CTime(pData->rbegin()->first / 1000).Format("%Y-%m-%d %H:%M:%S")); #endif // _DEBUG time_t tmStartSteady = pInfo->tmLastCheckTime / 1000 - 3; //稳态报警检测开始, 从上次3秒前到当前秒 if (item.second->no == 2) { if (pInfo->alarm_high_limit > pInfo->f_alarm_high_limit) {//定板反 high_alarm_limit = pInfo->alarm_high_limit; high_warn_limit = pInfo->warn_high_limit; low_alarm_limit = pInfo->f_alarm_high_limit; low_warn_limit = pInfo->f_warn_high_limit; posi = eDaoChaPosi::DCP_FIX2INVERT; } else {//反板定 low_alarm_limit = pInfo->alarm_high_limit; low_warn_limit = pInfo->warn_high_limit; high_alarm_limit = pInfo->f_alarm_high_limit; high_warn_limit = pInfo->f_warn_high_limit; posi = eDaoChaPosi::DCP_FIX2INVERT; } } for (++it; it != pData->cend(); ++it) { //CString str = CTime(it->first / 1000).Format("%Y-%m-%d %H:%M:%S"); if (it->second == INVLID_VAL) { pInfo->tmLastCheckTime = it->first; continue; } if (item.second->no < 2) { //1,2 锁闭力报警 if (it->second > pInfo->alarm_high_limit) { bAlarm = true; alarm_refer = pInfo->alarm_high_limit; alarm_value = it->second; alarm_time = it->first; pInfo->tmLastCheckTime = pData->rbegin()->first; desc_type = 1; break; } //else if (it->second > pInfo->warn_high_limit) //稳态报警单独判断 //{ // bWarn = true; // alarm_refer = pInfo->warn_high_limit; // alarm_value = it->second; // alarm_time = it->first; // pInfo->tmLastCheckTime = pData->rbegin()->first; //} } else { assert(item.second->no == 2); if (pInfo->alarm_high_limit == INT_MAX || pInfo->f_alarm_high_limit == INT_MAX || pInfo->alarm_high_limit == pInfo->f_alarm_high_limit) break; desc_type = 3; if (it->second > high_alarm_limit) { bAlarm = true; alarm_refer = high_alarm_limit; alarm_value = it->second; alarm_time = it->first; pInfo->tmLastCheckTime = pData->rbegin()->first; break; } else if (it->second < low_alarm_limit) { bAlarm = true; alarm_refer = low_alarm_limit; alarm_value = it->second; alarm_time = it->first; pInfo->tmLastCheckTime = pData->rbegin()->first; break; } else if (low_warn_limit == INT_MIN || high_warn_limit == INT_MIN) { //未设置预警值 } else if (it->second > high_warn_limit) { bWarn = true; alarm_refer = high_warn_limit; alarm_value = it->second; alarm_time = it->first; pInfo->tmLastCheckTime = pData->rbegin()->first; } else if (it->second < low_warn_limit) { bWarn = true; alarm_refer = low_warn_limit; alarm_value = it->second; alarm_time = it->first; pInfo->tmLastCheckTime = pData->rbegin()->first; } } pInfo->tmLastCheckTime = it->first; } //稳态报警判断 if (item.second->no < 2 && bAlarm == false) { time_t tmEnd = pInfo->tmLastCheckTime / 1000; int dif = tmEnd - tmStartSteady; for (time_t i = tmStartSteady; i < tmEnd - 3; i++) { #ifdef _DEBUG COleDateTime t(i); TRACE("%s\r\n", t.Format("%Y-%m-%d %H:%M:%S")); #endif // _DEBUG auto j = pData->find(i * 1000); if (j == pData->end()) continue; time_t t2 = (i + 1) * 1000; auto k = pData->find(t2); if (k == pData->end()) continue; t2 = (i + 2) * 1000; k = pData->find(t2); if (k == pData->end()) continue; //连续3秒在线,继续找下一个结束点 t2 = (i + 3) * 1000; auto g = pData->find(t2); if (g == pData->end()) { for (++k; k != pData->end(); k++) { if (k->first >= t2) { g = k; break; } } } if (g == pData->end()) continue; int high_num = 0, low_num = 0; ConmpareValue(j, g, pInfo->warn_high_limit, high_num, low_num); if (high_num > 0 && high_num <= 2) { bWarn = true; desc_type = 2; alarm_refer = pInfo->warn_high_limit; alarm_value = high_num; alarm_time = i * 1000; //报警时间 pInfo->tmLastCheckTime = pData->rbegin()->first; break; } } } } /* 2024年8月24日 放在move中判断 else if (item.second->type == eZL_ALARMTYPE::FRICTION_OVER_LIMIT) { auto pInfo = (FRICTION_OVER_LIMIT_INFO*)item.second; #ifdef _DEBUG if (pInfo->tmLastCheckTime > pData->rbegin()->first) pInfo->tmLastCheckTime = pData->rbegin()->first; #endif auto it = pData->cbegin(); if (pInfo->tmLastCheckTime == 0) pInfo->tmLastCheckTime = pData->rbegin()->first; else if (pInfo->tmLastCheckTime != 0) it = pData->find(pInfo->tmLastCheckTime); if (it == pData->cend()) { it = pData->find(pInfo->tmLastCheckTime / 1000 * 1000); if (it == pData->cend()) { pInfo->tmLastCheckTime = pData->rbegin()->first; continue; } } if (pInfo->tmLastCheckTime == pData->rbegin()->first) //没有新的数据 continue; if (tmNow * 1000 - pInfo->tmLastCheckTime < 5000) //5秒检测一次 continue; #ifdef _DEBUG TRACE("%s.%s.%d.%d lastcheck:%s now:%s\r\n", mo.c_str(), mp.c_str(), pInfo->no, (int)eZL_ALARMTYPE::FRICTION_OVER_LIMIT, CTime(pInfo->tmLastCheckTime / 1000).Format("%Y-%m-%d %H:%M:%S"), CTime(pData->rbegin()->first / 1000).Format("%Y-%m-%d %H:%M:%S")); #endif // _DEBUG if (item.second->no != 2) continue; //从检测时间往前取30秒的数据 static const int dif_resist = 200; //稳定期判定差值 int up_max_resist = INT_MIN; //上最大值 time_t up_max_time = 0; int up_avg_resist = INT_MIN; //上稳定期平均值 uint64_t up_stable_sum = 0; //上稳定期的和 int up_stable_time = 0; //上稳定期的数值个数 int up_start_resist_stabel = INT_MIN; //上稳定期开始值 time_t up_start_stable_time = 0; //规定是最大值之后的2秒 time_t up_end_stable_time = 0;//稳定结束的时间 int up_dif_time_stable = 0; //上稳定期的时长 int down_max_resist = INT_MAX; //上最大值 time_t down_max_time = 0; int down_avg_resist = INT_MAX; //上稳定期平均值 uint64_t down_stable_sum = 0; //上稳定期的和 int down_stable_time = 0; //上稳定期的数值个数 int down_start_resist_stabel = INT_MAX; //上稳定期开始值 time_t down_start_stable_time = 0; //规定是最大值之后的2秒 int down_dif_time_stable = 0; //上稳定期的时长 time_t tmEnd = pData->rbegin()->first / 1000 + 1; //结束时间 time_t tmStart = tmEnd - 36;//开始时间是从上次35秒到当前秒 std::map::const_iterator it_start, it_up_max, it_down_min, it_up_stable_start, it_down_stable_start, it_up_stable_end, it_down_stable_end; //寻找起始时间 for (time_t i = tmStart; i < tmEnd; i++) { #ifdef _DEBUG COleDateTime t(i); TRACE("%s\r\n", t.Format("%Y-%m-%d %H:%M:%S")); #endif // _DEBUG it_start = pData->find(i * 1000); if (it_start != pData->cend()) break; } pInfo->tmLastCheckTime = pData->rbegin()->first; //赋值最后的时间 if (it_start == pData->cend()) break; bool bUp = true, bDown = true; //先找最大值 for (auto i = it_start; i != pData->cend(); i++) { //寻找最大的点 if (i->second > up_max_resist) { up_max_resist = i->second; it_up_max = i; } //寻找最小的点 if (i->second < down_max_resist) { down_max_resist = i->second; it_down_min = i; } } if (pInfo->tmLastCheckTime - it_up_max->first < 17000) bUp = false; //小于17秒 if (pInfo->tmLastCheckTime - it_down_min->first < 1700) bDown = false; //小于17秒 if(bUp == false && bDown == false) break; //再找稳定开始 if (bUp) { it_up_stable_start = it_up_max; for (auto i = it_up_max; i != pData->cend(); i++) { if (i->first - it_up_max->first < 2000) continue; else { it_up_stable_start = i; break; } } if (it_up_stable_start == it_up_max) bUp = false; } if (bDown) { it_down_stable_start = it_down_min; for (auto i = it_down_min; i != pData->cend(); i++) { if (i->first - it_down_min->first < 2000) continue; else { it_down_stable_start = i; break; } } if (it_down_stable_start == it_down_min) bDown = false; } if (bUp == false && bDown == false) break; if (bUp) { up_start_resist_stabel = it_up_stable_start->second;//稳定期开始的值 it_up_stable_end = it_up_stable_start; for (auto i = it_up_stable_start; i != pData->cend(); i++) { if (abs(up_start_resist_stabel - i->second) < dif_resist) { up_stable_sum += i->second; up_start_stable_time++; it_up_stable_end = i; continue; } else { break; } } //时间条件限定在 15s-30s 之间 auto dif = it_up_stable_end->first - it_up_stable_start->first; if (dif > 15000 && dif < 30000) { //平均值 up_avg_resist = up_stable_sum / up_start_stable_time; if (up_avg_resist < pInfo->up_alarm_low_limit) { bAlarm = true; alarm_value = up_avg_resist; alarm_time = it_up_stable_start->first; alarm_refer = pInfo->up_alarm_low_limit; desc_type = 4; } else if (up_avg_resist < pInfo->up_warn_low_limit) { bWarn = true; alarm_value = up_avg_resist; alarm_time = it_up_stable_start->first; alarm_refer = pInfo->up_warn_low_limit; desc_type = 4; } } } if (bDown) { down_start_resist_stabel = it_down_stable_start->second;//稳定期开始的值 it_down_stable_end = it_down_stable_start; for (auto i = it_down_stable_start; i != pData->cend(); i++) { if (abs(down_start_resist_stabel - i->second) < dif_resist) { down_stable_sum += i->second; down_start_stable_time++; it_down_stable_end = i; continue; } else { break; } } //时间条件限定在 15s-30s 之间 auto dif = it_down_stable_end->first - it_down_stable_start->first; if (dif > 15000 && dif < 30000) { //平均值 down_avg_resist = down_stable_sum / down_start_stable_time; if (down_avg_resist > pInfo->dw_alarm_high_limit) { bAlarm = true; alarm_value = down_avg_resist; alarm_time = it_down_stable_start->first; alarm_refer = pInfo->dw_alarm_high_limit; desc_type = 5; } else if (down_avg_resist > pInfo->dw_warn_high_limit) { bWarn = true; alarm_value = down_avg_resist; alarm_time = it_down_stable_start->first; alarm_refer = pInfo->dw_warn_high_limit; desc_type = 5; } } } }*/ else { //其他未实现 //TODO assert(0); continue; } }while (false); //update CString sql; sql.Format("update rm_alarm_set SET time = %I64u WHERE mo = '%s' and mp = '%s' and no = %d and type = %d", pAlarmSet->tmLastCheckTime, mo.c_str(), mp.c_str(), pAlarmSet->no, pAlarmSet->type); if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE) { assert(0); CSimpleLog::Error("语句执行失败" + sql); } string name1, name2, name3, out_name, in_name; CMonitorObjectMng::Instance()->GetNameByMoMp(momp, name1, name2, name3, out_name, in_name); auto pMoMpInfo = CMonitorObjectMng::Instance()->GetMoMpInfo(momp); if (item.second->no == 0 || item.second->no == 1) { if (name1.find("定位") != -1) { posi = item.second->no == 0 ? eDaoChaPosi::DCP_FIX : eDaoChaPosi::DCP_INVERT; } else if (name1.find("反位") != -1) { posi = item.second->no == 0 ? eDaoChaPosi::DCP_INVERT : eDaoChaPosi::DCP_FIX; } else if (pMoMpInfo) SPDLOG_WARN("{} 未配置定位位关系 {}, {}, {}, {}", momp, name1, name2, pMoMpInfo->name1, pMoMpInfo->name2); } else if (item.second->no == 2) { //TODO if (posi == eDaoChaPosi::DCP_UNKNOWN) posi = eDaoChaPosi::DCP_FIX2INVERT; } else ASSERT(FALSE); if (bAlarm == false && bWarn == false) //没有报警 { //恢复报警 std::lock_guard lock(pService->m_mtxAlarm); for (auto it = pService->m_lstUnConfirmAlarm.begin(); it != pService->m_lstUnConfirmAlarm.end();) { auto& alarm = *it; if (alarm->no == item.second->no && alarm->type == pAlarmSet->type && alarm->recoveryTime.wYear < 2000 && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0) { auto pAlarmInfo = alarm; //1. 更新数据库 //2. 更新内存数据 //3. 上送恢复消息 if (ctAlarmTime.GetTime() == 0) ctAlarmTime = CTime::GetCurrentTime(); string recovery_time = ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE ID = %d;", recovery_time.c_str(), pAlarmInfo->id); CDBConnectPool::Instance()->DBExecuteSQL(sql); if (pAlarmInfo->ack_result == 1) { it = pService->m_lstUnConfirmAlarm.erase(it); continue; } else { ctAlarmTime.GetAsSystemTime(alarm->recoveryTime); } g_p315ClientManager->GetTcpClient()->SendAlarmData(CMonitorObjectMng::Instance()->GetZZJNO(mo + '.' + mp), 2, CTime(pAlarmInfo->time).GetTime(), ctAlarmTime.GetTime(), pAlarmInfo->type, posi, pAlarmInfo->level, eLowHigh::LH_HIGH, TIEDA_ACQ_VALUE(alarm->val, TIEDA_VAL_STATE::TVS_MOVEING), TIEDA_ACQ_VALUE(alarm->refer_val, TIEDA_VAL_STATE::TVS_MOVEING), 0); } ++it; } continue; //误报警继续下一个循环 } //查找是否原有的报警已存在 uint8_t level = 0; if (bAlarm) level = 1; ctAlarmTime = CTime(alarm_time / 1000); { std::lock_guard lock(pService->m_mtxAlarm); for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarm->no == item.second->no && alarm->type == pAlarmSet->type && level == alarm->level && alarm->recoveryTime.wYear < 2000 //预警和报警单独计算 && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0) { pAlarmInfo = alarm; break; } } } if (pAlarmInfo == nullptr) { bNew = true; pAlarmInfo = new ALARM_INFO; pAlarmInfo->event_id = hjfunc_GetGUID(); pAlarmInfo->id = ++pService->m_nAlarmID; pAlarmInfo->level = (bAlarm == 1); pAlarmInfo->mo = mo; pAlarmInfo->mp = mp; pAlarmInfo->no = item.second->no; ctAlarmTime.GetAsSystemTime(pAlarmInfo->time); pAlarmInfo->time.wMilliseconds = alarm_time % 1000; pAlarmInfo->type = item.second->type; pAlarmInfo->val = alarm_value; pAlarmInfo->refer_val = alarm_refer; pAlarmInfo->posi = posi; pAlarmInfo->zzjno = CMonitorObjectMng::Instance()->GetZZJNO(momp); pAlarmInfo->sunroof = CSkylightMng::GetInstance()->IsSkylight(&pAlarmInfo->time); char szInfo[200]; if (desc_type == 1) { sprintf_s(szInfo, sizeof(szInfo), "瞬时冲击力超限报警,报警值为%dN, 参考值为%dN", alarm_value, alarm_refer);//101 102 if (pAlarmInfo->type == eZL_ALARMTYPE::MAX_OVER_LIMIT) { g_p315ClientManager->GetTcpClient()->SendAlarmData(pAlarmInfo->zzjno, 1, CTime(pAlarmInfo->time).GetTime(), 0xFFFFFFFF, pAlarmInfo->type, pAlarmInfo->posi, pAlarmInfo->level, eLowHigh::LH_HIGH, TIEDA_ACQ_VALUE(alarm_value, TIEDA_VAL_STATE::TVS_POLL), TIEDA_ACQ_VALUE(alarm_refer, TIEDA_VAL_STATE::TVS_POLL), 0); } } else if (desc_type == 2) sprintf_s(szInfo, sizeof(szInfo), "稳态值超限预警, 超限次数为%d次, 参考值为%dN", alarm_value, alarm_refer); else if (desc_type == 3) sprintf_s(szInfo, sizeof(szInfo), "转换阻力值超限报警, 报警值为%dN, 参考值为%dN", alarm_value, alarm_refer); else if (desc_type == 4) { sprintf_s(szInfo, sizeof(szInfo), "摩擦力超限%s, 缩进位报警值为%dN, 参考值为:%dN", bAlarm == 1 ? "告警" : "预警", alarm_value, alarm_refer); string direct1, direct2; CMonitorObjectMng::Instance()->GetDirectByMoMp(mo + '.' + mp, direct1, direct2); } else if (desc_type == 5) { sprintf_s(szInfo, sizeof(szInfo), "摩擦力超限%s, 伸出位报警值为%dN, 参考值为:%dN", bAlarm == 1 ? "告警" : "预警", alarm_value, alarm_refer); string direct1, direct2; CMonitorObjectMng::Instance()->GetDirectByMoMp(mo + '.' + mp, direct1, direct2); } else assert(0); pAlarmInfo->desc = szInfo; lock_guard lock(pService->m_mtxAlarm); pService->m_lstUnConfirmAlarm.push_back(pAlarmInfo); } //send if (bNew) //不再推送 { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pAlarmInfo, buffer); const char* output = buffer.GetString(); //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength()); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); } //save if (bNew) { CString sql; sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, pAlarmInfo->type, ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val, pAlarmInfo->event_id.c_str(), pAlarmInfo->rel_id.c_str(), uint8_t(pAlarmInfo->posi), uint8_t(pAlarmInfo->loworhigh), pAlarmInfo->refer_val, pAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) CSimpleLog::Error("执行语句失败" + sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); //g_p315ClientManager->GetTcpClient()->SendAlarmData(pAlarmInfo->no, 1, ctAlarmTime.GetTime(), 0xFFFFFFFF, (WORD)pAlarmInfo->type, pAlarmInfo->val, 0, 0); delete[] pack; pack = nullptr; } } } //保持力下降检测 if (tmNow - pService->m_lastDetectDrop > detectTimeRed) { pService->m_lastDetectDrop = tmNow; time_t tt; time(&tt); for (auto it = (&pService->m_alarm_set)->cbegin(); it != (&pService->m_alarm_set)->cend(); it++) { auto item = *it; if (item.second == nullptr) continue; if (item.second->enable == false) continue; if (item.second->type != eZL_ALARMTYPE::RETENSION_FORCE) //这个逻辑里面只支持保持力 continue; auto pAlarmSet = (RETENSION_FORCE_DROP*)item.second; if ((eSuoBiPosi)item.second->no != eSuoBiPosi::SB_FIX && (eSuoBiPosi)item.second->no != eSuoBiPosi::SB_INVERT) continue; BOOL isRedAlarm = false; string momp = item.second->momp; if (momp.empty()) { int nPos = item.first.find('.'); if (nPos == -1) continue; int nPos2 = item.first.find('.', nPos + 1); if (nPos2 == -1) continue; string mo = item.first.substr(0, nPos); string mp = item.first.substr(nPos + 1, nPos2 - nPos - 1); momp = item.first.substr(0, nPos2); } auto pInfo = CMonitorObjectMng::Instance()->GetMoMpInfo(momp); if (pInfo == nullptr) continue; if (pInfo->pDeivce == nullptr) continue; if (isBetweenFiveAndFiveTen()) { //获取当天保持力值 LoadMoveData(momp, &detectTodayTime0, &detectToday0, 1); LoadMoveData(momp, &detectTodayTime1, &detectToday1, 2); if (detectToday0 != 3000) { SPDLOG_INFO("[动态保持力数据判定]:{},定位保持力:{},定位保持力时间:{},目前道岔位置:{}", momp, detectToday0, (LPCSTR)(CTime(detectTodayTime0 / 1000).Format("%Y-%m-%d %H:%M:%S")), posiLast == eDaoChaPosi::DCP_FIX ? "定位" : "反位"); } if (detectToday1 != 3000) { SPDLOG_INFO("[动态保持力数据判定]:{},反位保持力:{},反位保持力时间:{},目前道岔位置:{}", momp, detectToday1, (LPCSTR)(CTime(detectTodayTime1 / 1000).Format("%Y-%m-%d %H:%M:%S")), posiLast == eDaoChaPosi::DCP_FIX ? "定位" : "反位"); } } auto pMap0 = pInfo->pDeivce->GetStatInfo(pInfo->idx, 0); auto pMap1 = pInfo->pDeivce->GetStatInfo(pInfo->idx, 1); std::map* pMap = nullptr; std::map* mapRedAll = nullptr; std::map* mapDynaAll = nullptr; DAOCHA_POSITION posiLastDaocha = CMonitorObjectMng::Instance()->GetZZJEPOS(momp);//上一次道岔位置 if (posiLastDaocha == DAOCHA_POSITION::MP_FIX) { posiLast = eDaoChaPosi::DCP_FIX; } else if (posiLastDaocha == DAOCHA_POSITION::MP_INVERT) { posiLast = eDaoChaPosi::DCP_INVERT; } else { posiLast = eDaoChaPosi::DCP_UNKNOWN; SPDLOG_INFO("[道岔位置未知,无法进行保持力报警]:{}.{}",pInfo->mo, pInfo->mp); } if ((eSuoBiPosi)pAlarmSet->no == eSuoBiPosi::SB_FIX && posiLast == eDaoChaPosi::DCP_FIX) { if (pInfo->name1.find("定位") != -1) { pMap = pMap0; } if (pInfo->name1.find("反位") != -1) { pMap = pMap1; } } else if ((eSuoBiPosi)pAlarmSet->no == eSuoBiPosi::SB_FIX && posiLast == eDaoChaPosi::DCP_INVERT) { isRedAlarm = true;//只对红线生效 if (pInfo->name1.find("定位") != -1) { pMap = pMap0; } if (pInfo->name1.find("反位") != -1) { pMap = pMap1; } } else if ((eSuoBiPosi)pAlarmSet->no == eSuoBiPosi::SB_INVERT && posiLast == eDaoChaPosi::DCP_INVERT) { if (pInfo->name1.find("反位") != -1) { pMap = pMap0; } if (pInfo->name1.find("定位") != -1) { pMap = pMap1; } } else if ((eSuoBiPosi)pAlarmSet->no == eSuoBiPosi::SB_INVERT && posiLast == eDaoChaPosi::DCP_FIX) { isRedAlarm = true;//只对红线生效 if (pInfo->name1.find("反位") != -1) { pMap = pMap0; } if (pInfo->name1.find("定位") != -1) { pMap = pMap1; } } else { continue; } if (pMap == nullptr || pMap->size() < 3) { if (tmNow - detectTimeBynaTime >= detectTimeByna) { if (std::next(it) == (&pService->m_alarm_set)->cend()) { detectTimeBynaTime = tmNow; } } continue; } if (pAlarmSet->tmLastCheckTime >= pMap->rbegin()->first) { if (tmNow - detectTimeBynaTime >= detectTimeByna) { if (std::next(it) == (&pService->m_alarm_set)->cend()) { detectTimeBynaTime = tmNow; } } continue;//不重复检测 } pAlarmSet->tmLastCheckTime = pMap->rbegin()->first; time_t tStartRed = pService->m_lastDetectDrop - detectTimeRed; for (auto it = pMap->crbegin(); it != pMap->crend(); it++) { if (it->first <= tStartRed) { if (it == pMap->crbegin()) { //没有新数据 break; } if (++it != pMap->crend()) { tStartRed = (it)->first; } else { tStartRed = (--it)->first; } break; } } if (tStartRed == (pService->m_lastDetectDrop - detectTimeRed) && tStartRed <= pMap->begin()->first) { tStartRed = pMap->begin()->first; } mapRedAll = new std::map((*pMap).find(tStartRed), (*pMap).end()); if (mapRedAll == nullptr) { break; } time_t redAlarmAll = 0; time_t redAlarmRecoveryAll = 0; for (auto itR = mapRedAll->cbegin(); itR != mapRedAll->cend(); itR++) { if (std::abs(pAlarmSet->dw_alarm_low_drop) > 100000) { break; } auto it0 = itR; auto it1 = ++itR; if (it1 == mapRedAll->cend()) { break; } auto it2 = ++itR; if (it2 == mapRedAll->cend()) { break; } int nMinVal = it2->second.min_val; time_t tMinTime = it2->second.min_time; if (it0->second.min_val < pAlarmSet->dw_alarm_low_drop && it1->second.min_val < pAlarmSet->dw_alarm_low_drop && it2->second.min_val < pAlarmSet->dw_alarm_low_drop) { if (redAlarmAll ==0) { alarmStatus = 1; redAlarmAll = tMinTime; SPDLOG_INFO("[最低值红线保持力报警2]:{}.{},上一包发生时间:{},报警值:{},上两包发生时间:{},报警值:{},参考值:{}", pInfo->mo, pInfo->mp, (LPCSTR)(CTime(it1->second.min_time / 1000).Format("%Y-%m-%d %H:%M:%S")), it1->second.min_val, (LPCSTR)(CTime(it0->second.min_time / 1000).Format("%Y-%m-%d %H:%M:%S")), it0->second.min_val, detectToday01); JudgeAlarm(pService, pAlarmSet, tMinTime, nMinVal, (eSuoBiPosi)pAlarmSet->no, pInfo->mo, pInfo->mp, pInfo, detectToday01, posiLast, isRedAlarm, alarmStatus); } }else { if((redAlarmAll > redAlarmRecoveryAll) || redAlarmRecoveryAll==0){ alarmStatus = 31; redAlarmRecoveryAll = tMinTime; JudgeAlarm(pService, pAlarmSet, tMinTime, nMinVal, (eSuoBiPosi)pAlarmSet->no, pInfo->mo, pInfo->mp, pInfo, detectToday01, posiLast, isRedAlarm, alarmStatus); } if (redAlarmAll < redAlarmRecoveryAll && redAlarmRecoveryAll != 0 && redAlarmAll != 0) { break; } } itR--; itR--; } //动态保持力判定 if (pAlarmSet->is_page_dyna && tmNow - detectTimeBynaTime > detectTimeByna) { if (!(pAlarmSet->alarm_low_percent >= 5 && pAlarmSet->alarm_low_percent <= 95)) { break; } if (!(pAlarmSet->alarm_high_percent >= 5 && pAlarmSet->alarm_high_percent <= 95)) { break; } if (std::next(it)== (&pService->m_alarm_set)->cend()) { detectTimeBynaTime = tmNow; } time_t tStartByna = detectTimeBynaTime - detectTimeByna; for (auto it = pMap->crbegin(); it != pMap->crend(); it++) { if (it->first <= tStartByna) { if (it == pMap->crbegin()) { //没有新数据 break; } if (++it != pMap->crend()) { tStartByna = (it)->first; } else { tStartByna = (--it)->first; } break; } } if (tStartByna == (detectTimeBynaTime - detectTimeByna) && tStartByna < pMap->begin()->first) { tStartByna = pMap->begin()->first; } mapDynaAll = new std::map((*pMap).find(tStartByna), (*pMap).end()); if (mapDynaAll == nullptr) { break; } auto pMompInfo = CMonitorObjectMng::Instance()->GetMoMpInfo(momp); pMompInfo->detectToday0 = detectToday0; pMompInfo->detectTodayTime0 = detectTodayTime0; pMompInfo->detectToday1 = detectToday1; pMompInfo->detectTodayTime1 = detectTodayTime1; alarmStatus = 2; if (posiLast == eDaoChaPosi::DCP_FIX) { detectToday01 = detectToday0; } else if (posiLast == eDaoChaPosi::DCP_INVERT) { detectToday01 = detectToday1; } if (!(detectToday01 < 40000 && detectToday01 > 3000)) { break; } int redAlarmRecovery = false; time_t bynaAlarmAll = 0; time_t bynaAlarmRecoveryAll = 0; for (auto itD = mapDynaAll->cbegin(); itD != mapDynaAll->cend(); itD++) { auto it0 = itD; auto it1 = ++itD; if (it1 == mapDynaAll->cend()) { break; } auto it2 = ++itD; if (it2 == mapDynaAll->cend()) { break; } int nMinVal = it0->second.min_val; time_t tMinTime = it0->second.min_time; int nRatio0 = nMinVal * 100 / detectToday01; int nRatio1 = it1->second.min_val * 100 / detectToday01; int nRatio2 = it2->second.min_val * 100 / detectToday01; if (it0->second.min_val < pAlarmSet->dw_alarm_low_drop && it1->second.min_val < pAlarmSet->dw_alarm_low_drop && it2->second.min_val < pAlarmSet->dw_alarm_low_drop) { break; } //下降20%或上升40% 进行预警 if ((std::abs(nRatio0) <= (100 - pAlarmSet->alarm_low_percent) && std::abs(nRatio1) <= (100 - pAlarmSet->alarm_low_percent) && std::abs(nRatio2) <= (100 - pAlarmSet->alarm_low_percent))|| (std::abs(nRatio0) >= (100 + pAlarmSet->alarm_high_percent) && std::abs(nRatio1) >= (100 + pAlarmSet->alarm_high_percent) && std::abs(nRatio2) >= (100 + pAlarmSet->alarm_high_percent))) { if (bynaAlarmAll==0 && !isRedAlarm) { alarmStatus = 2; SPDLOG_INFO("[动态保持力报警]:{}.{},上一包发生时间:{},报警值:{},上两包发生时间:{},报警值:{}", pInfo->mo, pInfo->mp, (LPCSTR)(CTime(it1->second.min_time / 1000).Format("%Y-%m-%d %H:%M:%S")), it1->second.min_val, (LPCSTR)(CTime(it2->second.min_time / 1000).Format("%Y-%m-%d %H:%M:%S")), it2->second.min_val); JudgeAlarm(pService, pAlarmSet, tMinTime, nMinVal, (eSuoBiPosi)pAlarmSet->no, pInfo->mo, pInfo->mp, pInfo, detectToday01, posiLast, isRedAlarm, alarmStatus); bynaAlarmAll = tMinTime; } } else { if (((bynaAlarmAll > bynaAlarmRecoveryAll) || bynaAlarmRecoveryAll == 0)&& !isRedAlarm) { alarmStatus = 30; bynaAlarmRecoveryAll = tMinTime; JudgeAlarm(pService, pAlarmSet, tMinTime, nMinVal, (eSuoBiPosi)pAlarmSet->no, pInfo->mo, pInfo->mp, pInfo, detectToday01, posiLast, isRedAlarm, alarmStatus); } if (bynaAlarmAll < bynaAlarmRecoveryAll && bynaAlarmRecoveryAll!=0 && bynaAlarmAll !=0) { break; } } itD--; itD--; } } delete mapRedAll; delete mapDynaAll; } //清理无效位置 CMonitorObjectMng::Instance()->ClearZZJHistroyEPOS(tt); //四个小时未确认的保持力报警需要再次推送 std::map m_lstUnConfirmAlarmTemp; if ((tmNow - detectFourAlarmTime) >= detectFourAlarm && detectFourAlarm>0) { detectFourAlarmTime = tmNow; for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarm->type == eZL_ALARMTYPE::RETENSION_FORCE && alarm->ack_result == 0 && alarm->level == 1 &&((tmNow - SystemTimeToTimeT(alarm->time)) >= detectFourAlarm)) { auto find = m_lstUnConfirmAlarmTemp.find(alarm->id); if (find == m_lstUnConfirmAlarmTemp.end()) { m_lstUnConfirmAlarmTemp[alarm->id] = 1; } else { find->second++; } } } for (const auto& alarmTemp : m_lstUnConfirmAlarmTemp) { for (const auto& alarm : pService->m_lstUnConfirmAlarm) { if (alarmTemp.first==alarm->id && alarmTemp.second<5) { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(alarm, buffer); const char* output = buffer.GetString(); CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); pService->m_lstUnConfirmAlarm.push_back(alarm); break; } } } } } } while (pService->m_bWork); if (bLock) { g_lockSync.Unlock(); bLock = false; } } typedef struct tagMoMp { string mo; string mp; uint8_t no; //传感器的序号 tagMoMp(string a, string b) { mo = a; mp = b; } tagMoMp(uint8_t a) { no = a; } }; typedef struct offline_info { string imei; CTime time; uint8_t idx = 0; std::vector vct; offline_info(string a, CTime b) { imei = a; time = b; } offline_info(string a, CTime b, uint8_t c, uint8_t d) { imei = a; time = b; idx = c; vct.push_back(tagMoMp(d)); } }; void CResistAlarmMng::ThreadProcDevice(DWORD_PTR param) { auto pService = (CResistAlarmMng*)param; this_thread::sleep_for(chrono::seconds(2)); static CTimeSpan offline_time(0, 0, 5, 0); //设备离线时间暂定5分钟 static CTimeSpan offline_limit(30, 0, 0, 0); bool bLock = false; do { if (bLock) { g_lockSync.Unlock(); bLock = false; } for (int i = 0; i < 30; i++) { if (false == pService->m_bWork) break; Sleep(1000); } g_lockSync.ReadLock(); bLock = true; CTime ctNow = CTime::GetCurrentTime(); //离线设备 { auto& pMap = CMonitorObjectMng::Instance()->m_mapMoMpInfo; for (auto& it : pMap) { auto& pInfo = it.second; if (pInfo == nullptr) continue; bool bAlarm = false; if (!pInfo->pDeivce) continue; const auto pDevice = pInfo->pDeivce; if (pDevice->m_ctUpdateTime.GetTime() == 0) continue; if (ctNow - pDevice->m_ctUpdateTime > offline_time) bAlarm = true; else if (pInfo->bFirstOnline) {//第一次上线发送一次315离线报警恢复 因铁大未作报警同步 pInfo->bFirstOnline = false; g_p315ClientManager->GetTcpClient()->SendAlarmData(pInfo->zzjno, 2, pDevice->m_ctUpdateTime.GetTime(), pDevice->m_ctUpdateTime.GetTime(), eZL_ALARMTYPE::EQUIP_OFFLINE, eDaoChaPosi::DCP_UNKNOWN, 1, eLowHigh::LH_UNKNOWN, TIEDA_ACQ_VALUE(INT_MIN), TIEDA_ACQ_VALUE(INT_MIN), 0); SPDLOG_INFO("{}第一次上线发送一次315离线报警恢复", it.first); } ALARM_INFO* pAlarmInfo = nullptr; bool bNew = false; auto ctAlarmTime = ctNow; { std::lock_guard lock(pService->m_mtxAlarm); for (auto it = pService->m_lstUnConfirmAlarm.begin(); it != pService->m_lstUnConfirmAlarm.end();) { auto pAlarm = *it; if (pAlarm->type == eZL_ALARMTYPE::EQUIP_OFFLINE && pAlarm->recoveryTime.wYear < 2000 && pAlarm->mo.compare(pInfo->mo) == 0 && pAlarm->mp.compare(pInfo->mp) == 0) { pAlarmInfo = pAlarm; if (bAlarm) //连续报警 { break; } else { //恢复报警 //更新数据库 if (ctAlarmTime.GetTime() == 0) ctAlarmTime = CTime::GetCurrentTime(); string recovery_time = ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET [recovery_time]='%s' WHERE ID = %d;", recovery_time.c_str(), pAlarmInfo->id); CDBConnectPool::Instance()->DBExecuteSQL(sql); //315上送 g_p315ClientManager->GetTcpClient()->SendAlarmData(pInfo->zzjno, 2, CTime(pAlarm->time).GetTime(), ctAlarmTime.GetTime(), pAlarm->type, eDaoChaPosi::DCP_UNKNOWN, pAlarm->level, eLowHigh::LH_UNKNOWN, TIEDA_ACQ_VALUE(INT_MIN), TIEDA_ACQ_VALUE(INT_MIN), 0); it = pService->m_lstUnConfirmAlarm.erase(it); continue; /*if (pAlarm->ack_result == 1) { it = pService->m_lstUnConfirmAlarm.erase(it); continue; } else { ctAlarmTime.GetAsSystemTime(pAlarm->recoveryTime); }*/ } } ++it; } } if (bAlarm == false) continue; if (pAlarmInfo == nullptr) { bNew = true; pAlarmInfo = new ALARM_INFO; pAlarmInfo->event_id = hjfunc_GetGUID(); pAlarmInfo->id = ++pService->m_nAlarmID; pAlarmInfo->level = 1; pAlarmInfo->mo = pInfo->mo; pAlarmInfo->mp = pInfo->mp; pAlarmInfo->no = -1; ctAlarmTime.GetAsSystemTime(pAlarmInfo->time); //pAlarmInfo->time.wMilliseconds = alarm_time % 1000; pAlarmInfo->type = eZL_ALARMTYPE::EQUIP_OFFLINE; pAlarmInfo->val = 0; pAlarmInfo->zzjno = pInfo->zzjno; char szInfo[200]; sprintf_s(szInfo, sizeof(szInfo), "设备离线时间:%s", (LPCSTR)(pDevice->m_ctUpdateTime.Format("%Y-%m-%d %H:%M:%S"))); pAlarmInfo->desc = szInfo; pAlarmInfo->sunroof = CSkylightMng::GetInstance()->IsSkylight(&pAlarmInfo->time); lock_guard lock(pService->m_mtxAlarm); pService->m_lstUnConfirmAlarm.push_back(pAlarmInfo); } //send if (bNew) //不再推送 { rapidjson::StringBuffer buffer; auto ret = AlarmInfo2Pack(pAlarmInfo, buffer); const char* output = buffer.GetString(); //CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength()); } //save if (bNew) { CString sql; sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],posi,loworhigh,referval,[sunroof]) "\ "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d, '%s', '%s',%d,%d,%d,%d);", pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, pAlarmInfo->type, (LPCSTR)(ctAlarmTime.Format("%Y-%m-%d %H:%M:%S")), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val, pAlarmInfo->event_id.c_str(), pAlarmInfo->rel_id.c_str(), uint8_t(pAlarmInfo->posi), uint8_t(pAlarmInfo->loworhigh), pAlarmInfo->refer_val, pAlarmInfo->sunroof); if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql)) CSimpleLog::Error("执行语句失败" + sql); else { uint8_t* pack = nullptr; int len = 0; auto packno = CResistAlarmMng::GeneralNewAlarmData(pAlarmInfo, &pack, &len); if (packno) CSuperManager::Instance()->SendPack(pack, len, packno, E_ZL_PROTOCAL::ZL_ALARM_DATA, true); g_p315ClientManager->GetTcpClient()->SendAlarmData(pAlarmInfo->zzjno, 1, ctAlarmTime.GetTime(), 0xFFFFFFFF, pAlarmInfo->type, eDaoChaPosi::DCP_UNKNOWN, 1, eLowHigh::LH_UNKNOWN, TIEDA_ACQ_VALUE(INT_MIN), TIEDA_ACQ_VALUE(INT_MIN), 0); delete[] pack; pack = nullptr; } } } } } while (pService->m_bWork); if (bLock) { g_lockSync.Unlock(); bLock = false; } } void CResistAlarmMng::ThreadProcMove(DWORD_PTR param) { auto pService = (CResistAlarmMng*)param; Sleep(2000); time_t tmNow; auto strIniPath = CSimpleLog::GetAppDir() + "DataServices.ini"; bool bLock = false; do { if (bLock) { g_lockSync.Unlock(); bLock = false; } Sleep(800); time(&tmNow); if (pService->m_lastDetectMove > tmNow) { SPDLOG_INFO("时间有跳变"); pService->m_lastDetectMove = tmNow; } //10秒归档一次 扳动判断 if (tmNow - pService->m_lastDetectMove < 10) continue; g_lockSync.ReadLock(); bLock = true; pService->m_lastDetectMove = tmNow; char szTemp[100] = { 0 }; ::GetPrivateProfileString("SET", "momp", "", szTemp, sizeof(szTemp), strIniPath); g_strMoMp = szTemp; //SPDLOG_INFO("扳动判断:{}", g_strMoMp); auto& mapDevice = CDeviceMng::Instance()->m_map_devices; for (auto& it : mapDevice) { auto pDevice = it.second; for (auto i = 0; i < 3; i++) { string mo, mp; if (FALSE == CMonitorObjectMng::Instance()->IMEI2MOMP(pDevice->imei, i, mo, mp)) { //CSimpleLog::Error(fmt::format("IMEI2MOMP fail. imei:{}, idx:{}, {}:{}", pDevice->imei, i, __FILE__, __LINE__).c_str()); continue; //没有绑定返回 } std::map map0, map1, map2; std::map* mapData[3] = { 0 }; if (i == 0) { if (tmNow - pDevice->GetUpdateTime(0) < 3) continue; //3秒钟 无数据上送 开始判断 else if (tmNow - pDevice->m_tmMoveDetectTime0 < 10) continue; //距离上次应大于10秒 else if (pDevice->m_mapSecondStatInfo00.size() == 0) continue; const auto tCheck = pDevice->m_tmMoveDetectTime0; lock_guard lock(pDevice->m_mtx); for (auto it = pDevice->m_mapSecondStatInfo00.rbegin(); it != pDevice->m_mapSecondStatInfo00.rend(); it++) { if (it->first < tCheck) break; map0.insert(*it); } for (auto it = pDevice->m_mapSecondStatInfo01.rbegin(); it != pDevice->m_mapSecondStatInfo01.rend(); it++) { if (it->first < tCheck) break; map1.insert(*it); } for (auto it = pDevice->m_mapSecondStatInfo02.rbegin(); it != pDevice->m_mapSecondStatInfo02.rend(); it++) { if (it->first < tCheck) break; map2.insert(*it); } if (map2.size() > 2) { //拷贝原始数据 time_t tStart = 0; std::map::iterator itStart2; if (tCheck) { for (auto ii = tCheck; ii < tmNow; ii++) { itStart2 = pDevice->map_resist_idx02.find(ii*1000); if (itStart2 != pDevice->map_resist_idx02.end()) { tStart = ii*1000; break; } } } else { itStart2 = pDevice->map_resist_idx02.begin(); tStart = itStart2->first; } if (tStart) { mapData[0] = new std::map(pDevice->map_resist_idx00.find(tStart), pDevice->map_resist_idx00.end()); mapData[1] = new std::map(pDevice->map_resist_idx01.find(tStart), pDevice->map_resist_idx01.end()); mapData[2] = new std::map(itStart2, pDevice->map_resist_idx02.end()); } else ASSERT(0); } pDevice->m_tmMoveDetectTime0 = tmNow; } else if (i == 1) { if (tmNow - pDevice->GetUpdateTime(1) < 3) continue; //3秒钟 无数据上送 开始判断 else if (tmNow - pDevice->m_tmMoveDetectTime1 < 10) continue; //距离上次应大于10秒 else if (pDevice->m_mapSecondStatInfo10.size() == 0) continue; const auto tCheck = pDevice->m_tmMoveDetectTime1; lock_guard lock(pDevice->m_mtx); for (auto it = pDevice->m_mapSecondStatInfo10.rbegin(); it != pDevice->m_mapSecondStatInfo10.rend(); it++) { if (it->first < tCheck) break; map0.insert(*it); } for (auto it = pDevice->m_mapSecondStatInfo11.rbegin(); it != pDevice->m_mapSecondStatInfo11.rend(); it++) { if (it->first < tCheck) break; map1.insert(*it); } for (auto it = pDevice->m_mapSecondStatInfo12.rbegin(); it != pDevice->m_mapSecondStatInfo12.rend(); it++) { if (it->first < tCheck) break; map2.insert(*it); } if (map2.size() > 2) { //拷贝原始数据 time_t tStart = 0; std::map::iterator itStart2; if (tCheck) { for (auto ii = tCheck; ii < tmNow; ii++) { itStart2 = pDevice->map_resist_idx12.find(ii*1000); if (itStart2 != pDevice->map_resist_idx12.end()) { tStart = ii*1000; break; } } } else { itStart2 = pDevice->map_resist_idx12.begin(); tStart = itStart2->first; } if (tStart) { mapData[0] = new std::map(pDevice->map_resist_idx10.find(tStart), pDevice->map_resist_idx10.end()); mapData[1] = new std::map(pDevice->map_resist_idx11.find(tStart), pDevice->map_resist_idx11.end()); mapData[2] = new std::map(itStart2, pDevice->map_resist_idx12.end()); } else ASSERT(0); } pDevice->m_tmMoveDetectTime1 = tmNow; } else { if (tmNow - pDevice->GetUpdateTime(2) < 3) continue; //3秒钟 无数据上送 开始判断 else if (tmNow - pDevice->m_tmMoveDetectTime2 < 10) continue; //距离上次应大于10秒 else if (pDevice->m_mapSecondStatInfo20.size() == 0) continue; //else if (pDevice->m_mapSecondStatInfo20.rbegin()->second.dif_val > 100) continue; //最后值需要稳定 2024年5月31日移除 //else if (pDevice->m_mapSecondStatInfo21.rbegin()->second.dif_val > 100) continue; //else if (pDevice->m_mapSecondStatInfo22.rbegin()->second.dif_val > 100) continue; const auto tCheck = pDevice->m_tmMoveDetectTime2; lock_guard lock(pDevice->m_mtx); for (auto it = pDevice->m_mapSecondStatInfo20.rbegin(); it != pDevice->m_mapSecondStatInfo20.rend(); it++) { //RACE("20: first:%s check:%s\r\n", CTime(it->first).Format("%Y-%m-%d %H:%M:%S"), CTime(tCheck).Format("%Y-%m-%d %H:%M:%S")); if (it->first < tCheck) break; map0.insert(*it); } for (auto it = pDevice->m_mapSecondStatInfo21.rbegin(); it != pDevice->m_mapSecondStatInfo21.rend(); it++) { //TRACE("21: first:%s check:%s\r\n", CTime(it->first).Format("%Y-%m-%d %H:%M:%S"), CTime(tCheck).Format("%Y-%m-%d %H:%M:%S")); if (it->first < tCheck) break; map1.insert(*it); } for (auto it = pDevice->m_mapSecondStatInfo22.rbegin(); it != pDevice->m_mapSecondStatInfo22.rend(); it++) { //TRACE("22: first:%s check:%s\r\n", CTime(it->first).Format("%Y-%m-%d %H:%M:%S"), CTime(tCheck).Format("%Y-%m-%d %H:%M:%S")); if (it->first < tCheck) break; map2.insert(*it); } if (map2.size() > 2) { //拷贝原始数据 time_t tStart = 0; std::map::iterator itStart2; if (tCheck) { for (auto ii = tCheck; ii < tmNow; ii++) { itStart2 = pDevice->map_resist_idx22.find(ii*1000); if (itStart2 != pDevice->map_resist_idx22.end()) { tStart = ii*1000; break; } } } else { itStart2 = pDevice->map_resist_idx22.begin(); tStart = itStart2->first; } if (tStart) { mapData[0] = new std::map(pDevice->map_resist_idx20.find(tStart), pDevice->map_resist_idx20.end()); mapData[1] = new std::map(pDevice->map_resist_idx21.find(tStart), pDevice->map_resist_idx21.end()); mapData[2] = new std::map(itStart2, pDevice->map_resist_idx22.end()); } else assert(0); } TRACE("update: m_tmMoveDetectTime2:%s tmNow:%s size:%d\r\n", CTime(pDevice->m_tmMoveDetectTime2).Format("%Y-%m-%d %H:%M:%S"), CTime(tmNow).Format("%Y-%m-%d %H:%M:%S"), map2.size()); pDevice->m_tmMoveDetectTime2 = tmNow; } if (map2.size() <= 2) continue; if (!mapData[0] && !mapData[1] && !mapData[2]) continue; if (mapData[0]->size() != mapData[1]->size() || mapData[1]->size() != mapData[2]->size()) continue; SPDLOG_INFO("扳动判断数据{}.{} map:{} 0:{} 1:{} 2:{}", mo, mp, map2.size(), mapData[0]->size(), mapData[1]->size(), mapData[2]->size()); list lstResit2; //转换力数据 list lstPass; //过车数据 list lstFriction; //摩擦力数据 std::map maxlock0, maxlock1;//锁闭力 前面时间戳, 后面 高4位显示值, 低4位报警值 std::map retentionforce0, retentionforce1; //保持力 时间戳, 高4位显示值, 低4位报警值 mg_per_session_data::GetMaxResistNew(map2, lstResit2, mo, mp); if (g_bDataCompression) { SPDLOG_INFO("[过车判断]{}.{} 开始过车判断 size:{}", mo, mp, map0.size()); mg_per_session_data::GetPassNew(map0, mapData[0], map1, mapData[1], mo, mp, &lstPass); SPDLOG_INFO("[过车判断]{}.{} 结束过车判断 size:{} pass:{}", mo, mp, map0.size(), lstPass.size()); //过车过滤 for (auto& item : lstPass) { for (auto it = lstResit2.begin(); it != lstResit2.end();) { if (it->tmStart * 1000 <= item.show_time && item.show_time <= (it->tmEnd + 1) * 1000) { it = lstResit2.erase(it); break; } ++it; } } } //摩擦力过滤 for (auto it = lstResit2.begin(); it != lstResit2.end();) { int first_value = 0, last_value = 0; auto ii = map2.find(it->tmStart); ASSERT(ii != map2.end()); first_value = ii->second.first_val; ii = map2.find(it->tmEnd); if (ii == map2.end()) ii = map2.find(it->tmEnd - 1); ASSERT(ii != map2.end()); last_value = ii->second.end_val; auto dif = last_value - first_value; auto strLog = fmt::format("[摩擦力判断]{} first:{} last:{} dif:{}", CTime(it->time / 1000).Format("%Y-%m-%d %H:%M:%S"), first_value, last_value, dif); if (dif > 1000 || dif < -1000) { SPDLOG_INFO(strLog); if (it->tmEnd - it->tmStart >= 4) { FRICTION_RESIST info; info.peak_time = it->time; info.peak_val = it->val; info.show_time = ii->first * 1000; info.show_val = dif; //稳态值显示差值 info.curr_val = last_value; //显示的位置 info.tmStart = it->tmStart; info.tmEnd = it->tmEnd; info.t = strLog; info.bUpOrDown = it->bUpOrDown; lstFriction.emplace_back(info); } it = lstResit2.erase(it); } else ++it; } if (lstResit2.size()) { mg_per_session_data::GetMaxLockNew(map0, lstResit2, maxlock0, retentionforce0); mg_per_session_data::GetMaxLockNew(map1, lstResit2, maxlock1, retentionforce1); SPDLOG_INFO("[转换阻力][{}:{}] lock0:{} lock1:{}, resist2:{}", mo, mp, maxlock0.size(), maxlock1.size(), lstResit2.size()); } auto pMompInfo = CMonitorObjectMng::Instance()->GetMoMpInfo(mo + "." + mp); ASSERT(pMompInfo); //扳动处理逻辑 if (lstResit2.size()) { //获取报警设置 //转换阻力报警设置项 auto pConvertResistOverLimitInfo = (CONVERT_RESIST_OVER_LIMIT*)pService->Find(mo, mp, 2, eZL_ALARMTYPE::CONVERT_LIMIT); //定位锁闭力报警设置项 auto pFixSuobiOverInfo = (SUOBI_OVER_LIMIT_INFO*)pService->Find(mo, mp, (uint8_t)eSuoBiPosi::SB_FIX, eZL_ALARMTYPE::SUOBI_LOCK_LIMIT); //反位 auto pInvertSuobiOverInfo = (SUOBI_OVER_LIMIT_INFO*)pService->Find(mo, mp, (uint8_t)eSuoBiPosi::SB_INVERT, eZL_ALARMTYPE::SUOBI_LOCK_LIMIT); //定位保持力报警设置项 auto pFixConstRetensionForceWaveInfo = (RETENSION_FORCE_DROP*)pService->Find(mo, mp, (uint8_t)eSuoBiPosi::SB_FIX, eZL_ALARMTYPE::RETENSION_FORCE); if (pFixConstRetensionForceWaveInfo == nullptr)//默认开启 { //ASSERT(FALSE); //pFixConstRetensionForceWaveInfo = new RETENSION_FORCE_DROP; ///pService->Insert(mo, mp, (uint8_t)eSuoBiPosi::SB_FIX, (uint8_t)eZL_ALARMTYPE::RETENSION_FORCE, pFixConstRetensionForceWaveInfo); } //反位 auto pInvertConstRetensionForceWaveInfo = (RETENSION_FORCE_DROP*)pService->Find(mo, mp, (uint8_t)eSuoBiPosi::SB_INVERT, eZL_ALARMTYPE::RETENSION_FORCE); if (pInvertConstRetensionForceWaveInfo == nullptr)//默认开启 { //ASSERT(FALSE); //pInvertConstRetensionForceWaveInfo = new RETENSION_FORCE_DROP; //pService->Insert(mo, mp, (uint8_t)eSuoBiPosi::SB_INVERT, (uint8_t)eZL_ALARMTYPE::RETENSION_FORCE, pInvertConstRetensionForceWaveInfo); } //获取报警设置 end eDaoChaPosi posiLock0; if (pMompInfo->name1.find("定位") != -1) { posiLock0 = eDaoChaPosi::DCP_FIX; for (auto& it : maxlock0) { int show_val = (it.second >> 32); CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, show_val, i, (uint8_t)eDaoChaPosi::DCP_FIX, (uint8_t)ePowerName::PN_LOCK, fmt::format("锁闭力:{}", show_val)); JudgeAlarm(pService, pFixSuobiOverInfo, it.first, show_val, eSuoBiPosi::SB_FIX, mo, mp, pMompInfo->zzjno); } for (auto& it : retentionforce0) { int show_val = (int)it.second; CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, show_val, i, (uint8_t)eDaoChaPosi::DCP_FIX, (uint8_t)ePowerName::PN_RETENTION, fmt::format("保持力:{}", show_val)); JudgeAlarm(pService, pFixConstRetensionForceWaveInfo, it.first, show_val, eSuoBiPosi::SB_FIX, mo, mp, pMompInfo,pMompInfo->detectToday0, posiLock0, false, false); } for (auto& it : maxlock1) { int show_val = (it.second >> 32); CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, show_val, i, (uint8_t)eDaoChaPosi::DCP_INVERT, (uint8_t)ePowerName::PN_LOCK, fmt::format("锁闭力:{}", show_val)); JudgeAlarm(pService, pInvertSuobiOverInfo, it.first, show_val, eSuoBiPosi::SB_INVERT, mo, mp, pMompInfo->zzjno); } for (auto& it : retentionforce1) { int show_val = (int)it.second; CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, show_val, i, (uint8_t)eDaoChaPosi::DCP_INVERT, (uint8_t)ePowerName::PN_RETENTION, fmt::format("保持力:{}", show_val)); JudgeAlarm(pService, pInvertConstRetensionForceWaveInfo, it.first, show_val, eSuoBiPosi::SB_FIX, mo, mp, pMompInfo, pMompInfo->detectToday1, posiLock0, false, false); } } else { posiLock0 = eDaoChaPosi::DCP_INVERT; for (auto& it : maxlock0) { int show_val = (it.second >> 32); CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, show_val, i, (uint8_t)eDaoChaPosi::DCP_INVERT, (uint8_t)ePowerName::PN_LOCK, fmt::format("锁闭力:{}", show_val)); JudgeAlarm(pService, pInvertSuobiOverInfo, it.first, show_val, eSuoBiPosi::SB_INVERT, mo, mp, pMompInfo->zzjno); } for (auto& it : retentionforce0) { int show_val = (int)it.second; CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, show_val, i, (uint8_t)eDaoChaPosi::DCP_INVERT, (uint8_t)ePowerName::PN_RETENTION, fmt::format("保持力:{}", show_val)); JudgeAlarm(pService, pInvertConstRetensionForceWaveInfo, it.first, show_val, eSuoBiPosi::SB_INVERT, mo, mp, pMompInfo, pMompInfo->detectToday0, posiLock0, false, false); } for (auto& it : maxlock1) { int show_val = (it.second >> 32); CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, show_val, i, (uint8_t)eDaoChaPosi::DCP_FIX, (uint8_t)ePowerName::PN_LOCK, fmt::format("锁闭力:{}", show_val)); JudgeAlarm(pService, pFixSuobiOverInfo, it.first, show_val, eSuoBiPosi::SB_FIX, mo, mp, pMompInfo->zzjno); } for (auto& it : retentionforce1) { int show_val = (int)it.second; CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, show_val, i, (uint8_t)eDaoChaPosi::DCP_FIX, (uint8_t)ePowerName::PN_RETENTION, fmt::format("保持力:{}", show_val)); JudgeAlarm(pService, pFixConstRetensionForceWaveInfo, it.first, show_val, eSuoBiPosi::SB_FIX, mo, mp, pMompInfo,pMompInfo->detectToday1, posiLock0, false, false); } } auto mg_315_server = g_p315ClientManager->GetTcpClient(); //SPDLOG_INFO("扳动判断数据{}.{} 转换力", mo, mp); auto eqpno = CMonitorObjectMng::Instance()->GetZZJNO(mo + "." + mp); for (auto& it : lstResit2) { //auto it_start0 = mapData[0]->find(it.tmStart * 1000); //auto it_end0 = mapData[0]->find(it.tmEnd * 1000); //auto it_start1 = mapData[1]->find(it.tmStart * 1000); //auto it_end1 = mapData[1]->find(it.tmEnd * 1000); //auto it_start2 = mapData[2]->find(it.tmStart * 1000); //auto it_end2 = mapData[2]->find(it.tmEnd * 1000); eDaoChaPosi posi = eDaoChaPosi::DCP_UNKNOWN; if (posi == eDaoChaPosi::DCP_FIX2INVERT) { if (pMompInfo->in_name.find("定扳反") != -1) { CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.tmEnd, it.val, it.fluctuation_val, i, (uint8_t)eDaoChaPosi::DCP_FIX2INVERT, (uint8_t)ePowerName::PN_MOVE, fmt::format("{}:{}", pMompInfo->in_name, it.fluctuation_val)); posi = eDaoChaPosi::DCP_FIX2INVERT; CMonitorObjectMng::Instance()->UpdateZZJEPOS(mo + "." + mp, DAOCHA_POSITION::MP_INVERT); JudgeAlarm(pService, pConvertResistOverLimitInfo, it.time, it.fluctuation_val, posi, mo, mp, pMompInfo->zzjno); } } else if(posi == eDaoChaPosi::DCP_INVERT2FIX) { CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.tmEnd, it.val, it.fluctuation_val, i, (uint8_t)eDaoChaPosi::DCP_INVERT2FIX, (uint8_t)ePowerName::PN_MOVE, fmt::format("{}:{}", pMompInfo->out_name, it.fluctuation_val)); posi = eDaoChaPosi::DCP_INVERT2FIX; CMonitorObjectMng::Instance()->UpdateZZJEPOS(mo + "." + mp, DAOCHA_POSITION::MP_FIX); JudgeAlarm(pService, pConvertResistOverLimitInfo, it.time, it.fluctuation_val, posi, mo, mp, pMompInfo->zzjno); } SPDLOG_INFO("扳动判断数据{}.{} 315 上送", mo, mp); if(mapData[0]) mg_315_server->SendCurveData(pMompInfo->zzjno, posi, 1, true, mapData, it.tmStart, it.tmEnd); SPDLOG_INFO("扳动判断数据结束{}.{} 315 上送", mo, mp); } } //过车处理逻辑 if (lstPass.size()) { //TODO //SPDLOG_INFO("扳动判断数据{}.{} 315 上送", mo, mp); //mg_315_server->SendCurveData(pMompInfo->zzjno, posi, 1, true, mapData, it.tmStart, it.tmEnd); //SPDLOG_INFO("扳动判断数据结束{}.{} 315 上送", mo, mp); } //摩檫力逻辑 if (lstFriction.size()) { pMompInfo; auto pAlarmSet = (FRICTION_OVER_LIMIT_INFO*)pService->Find(mo, mp, 2, eZL_ALARMTYPE::FRICTION_OVER_LIMIT); auto mg_315_server = g_p315ClientManager->GetTcpClient(); for (auto& it : lstFriction) { CResistAlarmMng::InsertToDBByMove(mo, mp, it.show_time, it.tmStart, it.tmEnd, it.curr_val, it.show_val, 2, (uint8_t)eDaoChaPosi::DCP_UNKNOWN, (uint8_t)ePowerName::PN_FRICTION, fmt::format("稳态值:{}", it.show_val)); //CMonitorObjectMng::Instance()->UpdateZZJEPOS(mo + "." + mp, DAOCHA_POSITION::MP_QUARTO); //四开 JudgeAlarm(pService, pAlarmSet, it.show_time, it.show_val, eDaoChaPosi::DCP_UNKNOWN, it.bUpOrDown, (void*)pMompInfo); //发送315曲线数据 //if (mapData[0]) // mg_315_server->SendCurveData(pMompInfo->zzjno, eDaoChaPosi::DCP_UNKNOWN, 1, true, mapData, it.tmStart, it.tmEnd); } } delete mapData[0]; delete mapData[1]; delete mapData[2]; } } } while (pService->m_bWork); if (bLock) { g_lockSync.Unlock(); bLock = false; } } TIMESTAMP_STRUCT GetLastMoveTimeStamp(COdbcConnect* pDBConn) { SYSTEMTIME ss; GetLocalTime(&ss); string table_today = fmt::format("rm_move_{:0>4}{:0>2}", ss.wYear, ss.wMonth); TIMESTAMP_STRUCT ts; CString sql = ("SELECT MAX(show_time) FROM " + table_today).c_str(); bool bSucc = false; do { COdbcStatement stmt; stmt.SetOdbcConnect(pDBConn); int r = stmt.ExecDirect(sql); if (!ISODBCSUCCESS(r)) break; stmt.BindTimeStampCol(1, &ts); if (stmt.FetchNext() != 0) break; bSucc = true; } while (false); if (!bSucc) { //如果查询失败就以今天0点开始 ts.year = ss.wYear; ts.month = ss.wMonth; ts.day = 1; ts.hour = 0; ts.minute = 0; ts.second = 0; ts.fraction = 0; } return ts; } void CResistAlarmMng::ThreadProcMoveFromDB(DWORD_PTR param) { auto pService = (CResistAlarmMng*)param; auto pDBConn = CDBConnectPool::Instance()->GetConnection(); TIMESTAMP_STRUCT tsLast = GetLastMoveTimeStamp(pDBConn); Sleep(2000); do { Sleep(200); //每100ms 获取一次 string table_today = fmt::format("rm_move_{:0>4}{:0>2}", tsLast.year, tsLast.month); //加载数据 CString sql = fmt::format("SELECT mo,mp,show_time,start_time,end_time,curr_val,show_val,\ idx,posi,mark,type,sunroof FROM {} WHERE sunroof = 0 and show_time > '{:0>4}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}.{}' ORDER BY show_time ASC;", table_today, tsLast.year, tsLast.month, tsLast.day, tsLast.hour, tsLast.minute, tsLast.second, tsLast.fraction / 1000000).c_str(); //用大于号不包含关系 dataservice 不运行时候, 数据不存储外部也就不会产生数据 COdbcStatement stmt; stmt.SetOdbcConnect(pDBConn); int r = stmt.ExecDirect(sql); if (!ISODBCSUCCESS(r)) { ASSERT(0); continue; } //绑定数据 int nCol = 1; char mo[51], mp[51]; TIMESTAMP_STRUCT show_time, start_time, end_time; int curr_val, show_val; uint8_t idx, posi, type, sunroof; char mark[100]; stmt.BindCharCol(nCol++, mo, sizeof(mo)); stmt.BindCharCol(nCol++, mp, sizeof(mp)); stmt.BindTimeStampCol(nCol++, &show_time); stmt.BindTimeStampCol(nCol++, &start_time); stmt.BindTimeStampCol(nCol++, &end_time); stmt.BindIntCol(nCol++, &curr_val); stmt.BindIntCol(nCol++, &show_val); stmt.BindTinyIntCol(nCol++, &idx); stmt.BindTinyIntCol(nCol++, &posi); stmt.BindCharCol(nCol++, mark, sizeof(mark)); stmt.BindTinyIntCol(nCol++, &type); stmt.BindTinyIntCol(nCol++, &sunroof); ST_MOMP_INFO* pMompInfo = nullptr; auto mg_315_server = g_p315ClientManager->GetTcpClient(); int nCount = 0; //获取数据 do { if (stmt.FetchNext() != 0) break; //类型条件语句 auto ePosi = (eDaoChaPosi)posi; auto eType = (ePowerName)type; if (pMompInfo == nullptr || pMompInfo->mo.compare(mo) != 0 || pMompInfo->mp.compare(mp) != 0) pMompInfo = CMonitorObjectMng::Instance()->GetMoMpInfo(string(mo) + "." + mp); if (pMompInfo == nullptr) continue; CTime ctAlarm = CTime(show_time.year, show_time.month, show_time.day, show_time.hour, show_time.minute, show_time.second); memcpy(&tsLast, &show_time, sizeof(TIMESTAMP_STRUCT)); //赋值最新的时间, 区分查询后面的数据 time_t show_time_t = ctAlarm.GetTime() * 1000 + show_time.fraction / 1000000; nCount++; SPDLOG_INFO("[MOVE]查询到新的数据 {}.{} {:0>2}:{:0>2}:{:0>2}", mo, mp, tsLast.hour, tsLast.minute, tsLast.second); switch (eType) { case ePowerName::PN_LOCK: { //报警判断 if (ePosi == eDaoChaPosi::DCP_FIX) { auto pFixSuobiOverInfo = (SUOBI_OVER_LIMIT_INFO*)pService->Find(mo, mp, (uint8_t)eSuoBiPosi::SB_FIX, eZL_ALARMTYPE::SUOBI_LOCK_LIMIT); JudgeAlarm(pService, pFixSuobiOverInfo, show_time_t, show_val, eSuoBiPosi::SB_FIX, mo, mp, pMompInfo->zzjno); } else if (ePosi == eDaoChaPosi::DCP_INVERT) { auto pInvertSuobiOverInfo = (SUOBI_OVER_LIMIT_INFO*)pService->Find(mo, mp, (uint8_t)eSuoBiPosi::SB_INVERT, eZL_ALARMTYPE::SUOBI_LOCK_LIMIT); JudgeAlarm(pService, pInvertSuobiOverInfo, show_time_t, show_val, eSuoBiPosi::SB_INVERT, mo, mp, pMompInfo->zzjno); } } break; case ePowerName::PN_RETENTION: { if (ePosi == eDaoChaPosi::DCP_FIX) { auto pFixConstRetensionForceWaveInfo = (RETENSION_FORCE_DROP*)pService->Find(mo, mp, (uint8_t)eSuoBiPosi::SB_FIX, eZL_ALARMTYPE::RETENSION_FORCE); JudgeAlarm(pService, pFixConstRetensionForceWaveInfo, show_time_t, show_val, eSuoBiPosi::SB_FIX, mo, mp, pMompInfo, pMompInfo->detectToday0, ePosi, false,false); } else if (ePosi == eDaoChaPosi::DCP_INVERT) { auto pInvertConstRetensionForceWaveInfo = (RETENSION_FORCE_DROP*)pService->Find(mo, mp, (uint8_t)eSuoBiPosi::SB_INVERT, eZL_ALARMTYPE::RETENSION_FORCE); JudgeAlarm(pService, pInvertConstRetensionForceWaveInfo, show_time_t, show_val, eSuoBiPosi::SB_INVERT, mo, mp, pMompInfo, pMompInfo->detectToday1, ePosi, false, false); } } break; case ePowerName::PN_MOVE: { //转换阻力报警设置项 auto pConvertResistOverLimitInfo = (CONVERT_RESIST_OVER_LIMIT*)pService->Find(mo, mp, 2, eZL_ALARMTYPE::CONVERT_LIMIT); if (ePosi == eDaoChaPosi::DCP_FIX2INVERT) { //更新状态 CMonitorObjectMng::Instance()->UpdateZZJEPOS(string(mo) + "." + mp, DAOCHA_POSITION::MP_INVERT); SPDLOG_INFO("[MOVE]{}:{} 更新到反位", mo, mp); JudgeAlarm(pService, pConvertResistOverLimitInfo, show_time_t, show_val, ePosi, mo, mp, pMompInfo->zzjno); } else if (ePosi == eDaoChaPosi::DCP_INVERT2FIX) { //更新状态 CMonitorObjectMng::Instance()->UpdateZZJEPOS(string(mo) + "." + mp, DAOCHA_POSITION::MP_FIX); SPDLOG_INFO("[MOVE]{}:{} 更新到定位", mo, mp); JudgeAlarm(pService, pConvertResistOverLimitInfo, show_time_t, show_val, ePosi, mo, mp, pMompInfo->zzjno); } //TODO发送315曲线 // mg_315_server->SendCurveData(pMompInfo->zzjno, posi, 1, true, mapData, it.tmStart, it.tmEnd); } break; case ePowerName::PN_FRICTION: { //摩擦力 auto pAlarmSet = (FRICTION_OVER_LIMIT_INFO*)pService->Find(mo, mp, 2, eZL_ALARMTYPE::FRICTION_OVER_LIMIT); JudgeAlarm(pService, pAlarmSet, show_time_t, show_val, eDaoChaPosi::DCP_UNKNOWN, show_val < 0 ? eUpOrDownInfo::UOD_DOWN : eUpOrDownInfo::UOD_UP, pMompInfo); //TODO发送315曲线 //mg_315_server->SendCurveData(pMompInfo->zzjno, posi, 1, true, mapData, it.tmStart, it.tmEnd); } break; default: SPDLOG_WARN("[MOVE][扳动数据有误]{}:{} type:{}", mo, mp, type); ASSERT(0); break; } } while (true); stmt.Close(); if (nCount>0) { SPDLOG_INFO("[MOVE]外部加载扳动数据:{}条 语句:{}", nCount, sql); } else { //考虑到跨月的情况 SYSTEMTIME ss; GetLocalTime(&ss); if (ss.wMonth != tsLast.month) { tsLast.year = ss.wYear; tsLast.month = ss.wMonth; tsLast.day = ss.wDay; tsLast.hour = 0; tsLast.minute = 0; tsLast.second = 0; tsLast.fraction = 0; SPDLOG_INFO("[MOVE]外部加载扳动数据: 月份不同,重新加载"); } } } while (pService->m_bWork); SPDLOG_WARN("[MOVE]ThreadProcMoveFromDB 线程退出."); CDBConnectPool::Instance()->FreeConnection(pDBConn); } BOOL CResistAlarmMng::LoadAlarmSet() { CString sql = "SELECT [mo],[mp],[no],[type],[conf],[time] FROM [rm_alarm_set]"; COdbcStatement stmt; if (!CDBConnectPool::Instance()->DBQuery(stmt, sql)) { CSimpleLog::Error("执行语句失败" + sql); return FALSE; } for (auto& it : m_alarm_set) { //delete it.second; //暂时不释放 it.second = nullptr; } m_alarm_set.clear(); char mo[51], mp[51], conf[501]; uint8_t no, type; __time64_t time; int nCol = 1; stmt.BindCharCol(nCol++, mo, sizeof(mo)); stmt.BindCharCol(nCol++, mp, sizeof(mp)); stmt.BindTinyIntCol(nCol++, &no); stmt.BindTinyIntCol(nCol++, &type); stmt.BindCharCol(nCol++, conf, sizeof(conf)); stmt.BindBigIntCol(nCol++, &time); do { if (stmt.FetchNext() != 0) break; using namespace rapidjson; int len = strlen(conf); if (len == 0) continue; Document doc; if (doc.Parse(conf, len).HasParseError()) { CSimpleLog::Error(CString("解析数据出错") + conf); continue; } const auto eType = (eZL_ALARMTYPE)type; if (eType == eZL_ALARMTYPE::MAX_OVER_LIMIT) { if (doc.IsArray() == false) { CSimpleLog::Error(CString("conf是非数组") + conf); continue; } SizeType n = doc.Size(); bool enable = false; int alarm_high_limit = INT_MAX; int warn_high_limit = INT_MAX; int f_alarm_high_limit = INT_MAX; int f_warn_high_limit = INT_MAX; for (SizeType i = 0; i < n; i++) { if (doc[i].HasMember("name") == false || doc[i].HasMember("val") == false || doc[i]["name"].IsString() == false || doc[i]["val"].IsString() == false) { assert(false); continue; } string key = doc[i]["name"].GetString(); string value = doc[i]["val"].GetString(); if (key.compare("enable") == 0) { enable = (value.compare("true") == 0); } else if (key.compare("lock_alarm_high_limit") == 0) { alarm_high_limit = atoi(value.c_str()); } else if (key.compare("lock_warn_high_limit") == 0) { warn_high_limit = atoi(value.c_str()); } else if (key.compare("d_alarm_high_limit") == 0) { alarm_high_limit = atoi(value.c_str()); } else if (key.compare("d_warn_high_limit") == 0) { warn_high_limit = atoi(value.c_str()); } else if (key.compare("f_alarm_high_limit") == 0) { f_alarm_high_limit = atoi(value.c_str()); } else if (key.compare("f_warn_high_limit") == 0) { f_warn_high_limit = atoi(value.c_str()); } else if (key.compare("keep_alarm_high_limit") == 0) { f_alarm_high_limit = atoi(value.c_str()); } else if (key.compare("keep_warn_high_limit") == 0) { f_warn_high_limit = atoi(value.c_str()); } else { assert(0); } } if (alarm_high_limit == INT_MAX || warn_high_limit == INT_MAX) continue; auto pInfo = new MAX_OVER_LIMIT_INFO; pInfo->enable = enable; pInfo->no = no; pInfo->type = eType; pInfo->alarm_high_limit = alarm_high_limit; pInfo->warn_high_limit = warn_high_limit; pInfo->f_alarm_high_limit = f_alarm_high_limit; pInfo->f_warn_high_limit = f_warn_high_limit; pInfo->tmLastCheckTime = time; sprintf_s(pInfo->momp, 20, "%s.%s", mo, mp); stringstream ss; ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type); m_alarm_set[ss.str()] = pInfo; } else if (eType == eZL_ALARMTYPE::FRICTION_OVER_LIMIT) { if (doc.IsArray() == false) { CSimpleLog::Error(CString("conf是非数组") + conf); continue; } SizeType n = doc.Size(); bool enable = false; int up_alarm_low_limit = INT_MAX; int up_warn_low_limit = INT_MAX; int dw_alarm_high_limit = INT_MIN; int dw_warn_high_limit = INT_MIN; for (SizeType i = 0; i < n; i++) { if (doc[i].HasMember("name") == false || doc[i].HasMember("val") == false || doc[i]["name"].IsString() == false || doc[i]["val"].IsString() == false) { assert(false); continue; } string key = doc[i]["name"].GetString(); string value = doc[i]["val"].GetString(); if (key.compare("enable") == 0) { enable = (value.compare("true") == 0); } else if (key.compare("up_alarm_low_limit") == 0) { up_alarm_low_limit = atoi(value.c_str()); } else if (key.compare("up_warn_low_limit") == 0) { up_warn_low_limit = atoi(value.c_str()); } else if (key.compare("dw_alarm_high_limit") == 0) { dw_alarm_high_limit = atoi(value.c_str()); } else if (key.compare("dw_warn_high_limit") == 0) { dw_warn_high_limit = atoi(value.c_str()); } else { assert(0); } } auto pInfo = new FRICTION_OVER_LIMIT_INFO; pInfo->enable = enable; pInfo->no = no; pInfo->type = eType; pInfo->up_alarm_low_limit = up_alarm_low_limit; pInfo->up_warn_low_limit = up_warn_low_limit; pInfo->dw_alarm_high_limit = dw_alarm_high_limit; pInfo->dw_warn_high_limit = dw_warn_high_limit; pInfo->tmLastCheckTime = time; sprintf_s(pInfo->momp, 20, "%s.%s", mo, mp); stringstream ss; ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type); m_alarm_set[ss.str()] = pInfo; } else if (eType == eZL_ALARMTYPE::SUOBI_LOCK_LIMIT) { auto doc = yyjson_read(conf, len, 0); if (doc == nullptr) continue; auto root = yyjson_doc_get_root(doc); auto pInfo = new SUOBI_OVER_LIMIT_INFO; pInfo->type = eZL_ALARMTYPE::SUOBI_LOCK_LIMIT; pInfo->no = no; pInfo->enable = yyjson_get_bool(yyjson_obj_get(root, "enable")); pInfo->alarm_low_limit = yyjson_get_int(yyjson_obj_get(root, "alarm_low_limit")); pInfo->warn_low_limit = yyjson_get_int(yyjson_obj_get(root, "warn_low_limit")); pInfo->alarm_high_limit = yyjson_get_int(yyjson_obj_get(root, "alarm_high_limit")); pInfo->warn_high_limit = yyjson_get_int(yyjson_obj_get(root, "warn_high_limit")); sprintf_s(pInfo->momp, 20, "%s.%s", mo, mp); stringstream ss; ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type); m_alarm_set[ss.str()] = pInfo; yyjson_doc_free(doc); } else if (eType == eZL_ALARMTYPE::CONVERT_LIMIT) { auto doc = yyjson_read(conf, len, 0); if (doc == nullptr) continue; auto root = yyjson_doc_get_root(doc); auto pInfo = new CONVERT_RESIST_OVER_LIMIT; pInfo->type = eZL_ALARMTYPE::CONVERT_LIMIT; pInfo->no = 2; pInfo->enable = yyjson_get_bool(yyjson_obj_get(root, "enable")); pInfo->dw_alarm_low_limit = yyjson_get_int(yyjson_obj_get(root, "dw_alarm_low_limit")); pInfo->dw_warn_low_limit = yyjson_get_int(yyjson_obj_get(root, "dw_warn_low_limit")); pInfo->up_alarm_high_limit = yyjson_get_int(yyjson_obj_get(root, "up_alarm_high_limit")); pInfo->up_warn_high_limit = yyjson_get_int(yyjson_obj_get(root, "up_warn_high_limit")); sprintf_s(pInfo->momp, 20, "%s.%s", mo, mp); stringstream ss; ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type); m_alarm_set[ss.str()] = pInfo; yyjson_doc_free(doc); } else if (eType == eZL_ALARMTYPE::RETENSION_FORCE) { auto doc = yyjson_read(conf, len, 0); if (doc == nullptr) continue; auto root = yyjson_doc_get_root(doc); auto pInfo = new RETENSION_FORCE_DROP; pInfo->type = eZL_ALARMTYPE::RETENSION_FORCE; pInfo->no = no; pInfo->enable = yyjson_get_bool(yyjson_obj_get(root, "enable")); pInfo->dw_alarm_low_drop = yyjson_get_int(yyjson_obj_get(root, "dw_alarm_low_drop")); pInfo->alarm_high_percent = yyjson_get_int(yyjson_obj_get(root, "alarm_high_percent")); pInfo->alarm_low_percent = yyjson_get_int(yyjson_obj_get(root, "alarm_low_percent")); sprintf_s(pInfo->momp, 20, "%s.%s", mo, mp); stringstream ss; ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type); m_alarm_set[ss.str()] = pInfo; yyjson_doc_free(doc); } else { ASSERT(0); } } while (true); //2024年8月23日 开启默认开启最低3000N报警 const auto& mapInfo = CMonitorObjectMng::Instance()->m_mapMoMpInfo; for (auto& it : mapInfo) { auto pAlarmSetFix = (RETENSION_FORCE_DROP*)Find(it.second->mo, it.second->mp, (uint8_t)eSuoBiPosi::SB_FIX, eZL_ALARMTYPE::RETENSION_FORCE); if (pAlarmSetFix) { if (((pAlarmSetFix->alarm_low_percent <= 95 && pAlarmSetFix->alarm_low_percent >= 5) || (pAlarmSetFix->alarm_high_percent <= 95 && pAlarmSetFix->alarm_high_percent >= 5))) { pAlarmSetFix->is_page_dyna = true; if (!(pAlarmSetFix->dw_alarm_low_drop > 0 && pAlarmSetFix->dw_alarm_low_drop <= 40000)) { pAlarmSetFix->dw_alarm_low_drop = 3000; } } } /*else { auto pInfo = new RETENSION_FORCE_DROP; pInfo->no = (uint8_t)eSuoBiPosi::SB_FIX; pInfo->enable = true; pInfo->dw_alarm_low_drop = 3000; pInfo->is_page_dyna = false; sprintf_s(pInfo->momp, 20, "%s.%s", it.second->mo.c_str(), it.second->mp.c_str()); Insert(it.second->mo, it.second->mp, pInfo->no, (uint8_t)eZL_ALARMTYPE::RETENSION_FORCE, pInfo); }*/ auto pAlarmSetInvert = (RETENSION_FORCE_DROP*)Find(it.second->mo, it.second->mp, (uint8_t)eSuoBiPosi::SB_INVERT, eZL_ALARMTYPE::RETENSION_FORCE); if (pAlarmSetInvert) { if (((pAlarmSetInvert->alarm_low_percent <= 95 && pAlarmSetInvert->alarm_low_percent >= 5) || (pAlarmSetInvert->alarm_high_percent <= 95 && pAlarmSetInvert->alarm_high_percent >= 5))) { pAlarmSetInvert->is_page_dyna = true; if (!(pAlarmSetInvert->dw_alarm_low_drop > 0 && pAlarmSetInvert->dw_alarm_low_drop <= 40000)) { pAlarmSetInvert->dw_alarm_low_drop = 3000; } } } /*else { auto pInfo = new RETENSION_FORCE_DROP; pInfo->no = (uint8_t)eSuoBiPosi::SB_INVERT; pInfo->enable = true; pInfo->dw_alarm_low_drop = 3000; pInfo->is_page_dyna = false; sprintf_s(pInfo->momp, 20, "%s.%s", it.second->mo.c_str(), it.second->mp.c_str()); Insert(it.second->mo, it.second->mp, pInfo->no, (uint8_t)eZL_ALARMTYPE::RETENSION_FORCE, pInfo); }*/ } CSimpleLog::Info(fmt::format("一共加载到{}条报警规则:{}", m_alarm_set.size(), sql).c_str()); return TRUE; } BOOL CResistAlarmMng::LoadAlarmID() { CString sql = "SELECT TOP 1 ID FROM RM_ALARM ORDER BY ID DESC"; COdbcStatement stmt; if (!CDBConnectPool::Instance()->DBQuery(stmt, sql)) { CSimpleLog::Error("执行语句失败" + sql); return FALSE; } int alarm_id; int nCol = 1; stmt.BindIntCol(nCol++, &alarm_id); do { if (stmt.FetchNext() != 0) break; m_nAlarmID = alarm_id; } while (false); stmt.Close(); return TRUE; } BOOL CResistAlarmMng::LoadMoveData(string momp, time_t* showTime,int* showVal, int posi) { SYSTEMTIME tmNow; GetLocalTime(&tmNow); string table_name = fmt::format("rm_move_{:0>4}{:0>2}", tmNow.wYear, tmNow.wMonth); CString sql = fmt::format("SELECT TOP 1 show_time,show_val FROM {} WHERE mo +'.'+ mp = '{}' and type = 2 and posi = {} ORDER BY show_time DESC;", table_name, momp,posi).c_str(); COdbcStatement stmt; if (!CDBConnectPool::Instance()->DBQuery(stmt, sql)) { CSimpleLog::Error("执行语句失败" + sql); return FALSE; } TIMESTAMP_STRUCT showTimeT; int nCol = 1; int showValT; stmt.BindTimeStampCol(nCol++, &showTimeT); stmt.BindIntCol(nCol++, &showValT); int i = 0; do { if (stmt.FetchNext() != 0) { return false; } *showTime = CTime(showTimeT.year, showTimeT.month, showTimeT.day, showTimeT.hour, showTimeT.minute, showTimeT.second).GetTime() * 1000 + showTimeT.fraction / 1000000; *showVal = showValT; } while (false); stmt.Close(); return true; } BOOL CResistAlarmMng::isBetweenFiveAndFiveTen() { int hour = 5; int minuteStart = 0; int minuteEnd = 15; auto now = std::chrono::system_clock::now(); std::time_t now_c = std::chrono::system_clock::to_time_t(now); std::tm* now_tm = std::localtime(&now_c); bool is_between = (now_tm->tm_hour == hour) && (now_tm->tm_min >= minuteStart) && (now_tm->tm_min <= minuteEnd); return is_between; } BOOL CResistAlarmMng::JudgePass(string mo,string mp) { bool is_pass = false; time_t tmNow; std::map* map0 = nullptr; std::map* map1 = nullptr; std::map* mapData[2] = { 0 }; string imei; int idx; auto ret = CMonitorObjectMng::Instance()->MOMP2IMEI(mo,mp, imei, idx); if (ret == false) return is_pass; #ifdef _DEBUG if (strcmp("0000000100000001", imei.c_str()) != 0) return is_pass; #endif auto pDevice = CDeviceMng::Instance()->Find(imei); if (pDevice == nullptr) { CSimpleLog::Error(("找不到imei(" + imei + ")" + std::to_string(__LINE__)).c_str()); return is_pass; } Sleep(30000); // 30*1000 time(&tmNow); if (tmNow - pDevice->GetUpdateTime(idx) < 0) return is_pass; //30秒钟无数据上送说明过车已经结束开始判断 else if (pDevice->m_mapSecondStatInfo00.size() == 0) return is_pass; lock_guard lock(pDevice->m_mtx); //拷贝原始数据,30秒 time_t tStart = (tmNow - 30)*1000; for (auto it = (&(pDevice->map_resist_idx00))->crbegin(); it != (&(pDevice->map_resist_idx00))->crend(); it++) { if (it->first < tStart) { if (it == (&(pDevice->map_resist_idx00))->crbegin()) { break; } tStart = (--it)->first; break; } } if (tStart== (tmNow - 30) * 1000) { tStart = (&(pDevice->map_resist_idx00))->begin()->first; } mapData[0] = new std::map(pDevice->map_resist_idx00.find(tStart), pDevice->map_resist_idx00.end()); mapData[1] = new std::map(pDevice->map_resist_idx01.find(tStart), pDevice->map_resist_idx01.end()); map0 = new std::map(pDevice->m_mapSecondStatInfo00.find(tStart/1000), pDevice->m_mapSecondStatInfo00.end()); map1 = new std::map(pDevice->m_mapSecondStatInfo01.find(tStart/1000), pDevice->m_mapSecondStatInfo01.end()); if (!mapData[0] && !mapData[1]) return is_pass; if (mapData[0]->size() != mapData[1]->size()) return is_pass; if (!map0 && !map1) return is_pass; if ((map0->size() != map1->size())|| map0->size()<=3 || map1->size()<=3) return is_pass; list lstPass; //过车数据 std::map mapStatInfo0; std::map* mapStatInfo1 = nullptr; auto it = (*map0).cbegin(); mapStatInfo0.emplace(it->first, it->second); time_t tLastIt = it->first; BOOL bForContinue = TRUE; do { it++; if (it != (*map0).cend()) { if (it->first - tLastIt < 2) //单位秒 { mapStatInfo0.emplace(it->first, it->second); tLastIt = it->first; continue; } else { tLastIt = it->first; } } else { bForContinue = FALSE;//遍历结束 } } while (bForContinue); if (mapStatInfo0.size() <= 3) //过车不小于3秒 return is_pass; mapStatInfo1 = new std::map((*map1).find(mapStatInfo0.cbegin()->first), ((*map1).find(mapStatInfo0.crbegin()->first))); int nDifCount0 = 0, nDifCount1 = 0; for (auto it = (&mapStatInfo0)->cbegin(); it != (&mapStatInfo0)->cend(); it++){ if (it->second.dif_val > 100) nDifCount0++; } for (auto it = mapStatInfo1->cbegin(); it != mapStatInfo1->cend(); it++){ if (it->second.dif_val > 100) nDifCount1++; } if (std::max(nDifCount0, nDifCount1) <= 3) return is_pass; //波动小于等于3秒 int iUpNum = 0; //上升次数 int iDwNum = 0; //下降次数 int iMaxDif = 0; int nMaxValue = 0; time_t tMaxTime; time_t tsStartTime = (&mapStatInfo0)->begin()->first; time_t tsEndTime = (&mapStatInfo0)->crbegin()->first + 1; //结束时间加1秒,后面判断过车时间[tsStartTime, tsEndTime) auto dif = tsEndTime - tsStartTime; auto sStart = CTime(tsStartTime).Format("%Y-%m-%d %H:%M:%S"); auto sEnd = CTime(tsEndTime).Format("%Y-%m-%d %H:%M:%S"); TRACE("pass: tsStartTime:%s tsEndTime:%s dif:%d \r\n", sStart, sEnd, dif); SPDLOG_INFO("pass: nDifCount0:{} nDifCount1:{} tsStartTime:{} tsEndTime:{} dif:{}", nDifCount0, nDifCount1, sStart, sEnd, dif); if (nDifCount0 > nDifCount1) CompareValuePass(mapData[0], tsStartTime, tsEndTime, iUpNum, iDwNum, 5, iMaxDif, tMaxTime, nMaxValue); else CompareValuePass(mapData[1], tsStartTime, tsEndTime, iUpNum, iDwNum, 5, iMaxDif, tMaxTime, nMaxValue); if ((dif >= 4 && dif < 7 && iUpNum >= 22 && iDwNum >= 22) || (dif == 7 && iUpNum >= 30 && iDwNum >= 30) || (dif >= 8 && iUpNum >= 45 && iDwNum >= 45)) { is_pass = TRUE; } SPDLOG_INFO("[红线保持力过车判断]{}.{} 开始时间 {} 结束时间 {} 经过时间 {}秒 向上波动 {} 向下波动 {} maxdif:{} 是否过车:{}", mo, mp, sStart, sEnd, dif, iUpNum, iDwNum, iMaxDif, is_pass ? "是" : "否"); delete mapStatInfo1; if (mapStatInfo0.size()) mapStatInfo0.clear(); delete map0; delete map1; return is_pass; } time_t CResistAlarmMng::SystemTimeToTimeT(const SYSTEMTIME& st) { struct tm t = { 0 }; t.tm_year = st.wYear - 1900; // 年份减去1900,因为tm结构中的年份是从1900年开始计算的 t.tm_mon = st.wMonth - 1; // 月份从0开始,所以需要减1 t.tm_mday = st.wDay; // 日 t.tm_hour = st.wHour; // 小时 t.tm_min = st.wMinute; // 分钟 t.tm_sec = st.wSecond; // 秒 time_t time = mktime(&t); // mktime会将tm结构转换为自1970年1月1日以来的秒数 return time; } // 格式化时间,精确到毫秒 string CResistAlarmMng::getTimeString() { auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); std::stringstream ss; ss << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S"); auto tNow = std::chrono::system_clock::now(); auto tMilliseconds = std::chrono::duration_cast(tNow.time_since_epoch()); auto tSeconds = std::chrono::duration_cast(tNow.time_since_epoch()); auto ms = tMilliseconds - tSeconds; ss << "." << std::setfill('0') << std::setw(3) << ms.count(); return ss.str(); } BOOL CResistAlarmMng::CompareValuePass(std::map* pData, time_t tsStartTime, time_t tsEndTime, int& hight_num, int& low_num, int threshold, int& iMaxDif, time_t& tMaxTime, int& nMaxValue) { auto it = pData->find(tsStartTime * 1000); if (it == pData->end()) return false; int signal = 0; tMaxTime = 0; int startvalue = it->second / 10; int lastvalue = startvalue; int lastVV = lastvalue; time_t lastTT = it->first; int iMax = startvalue; std::map mapMaxValue; hight_num = 0; low_num = 0; for (it; it != pData->end() && it->first < tsEndTime * 1000; it++) { auto val = it->second / 10; if (val > lastvalue)//上升 { if (signal == 1) { //原来大于,现在也是大于 //continue; } else { //原来小于或者无效,现在大于 signal = 1; startvalue = lastvalue; if (iMax - startvalue > threshold) low_num++; } } else if (val < lastvalue)//下降 { if (signal == -1) { //原来小于,现在小于等于 //continue; } else { //原来大于或者无效,现在小于 signal = -1; iMax = lastvalue; if (iMax - startvalue > threshold) //相差阈值计数 { mapMaxValue[lastTT] = lastVV; hight_num++; } } } lastvalue = val; lastTT = it->first; lastVV = it->second; } iMax = INT_MIN; int iMin = INT_MAX; for (auto& it : mapMaxValue) { if (it.second > iMax) { iMax = it.second; tMaxTime = it.first; } if (it.second < iMin) iMin = it.second; } iMaxDif = iMax - iMin; nMaxValue = iMax; return TRUE; } //加载未受理和未恢复的报警 BOOL CResistAlarmMng::LoadUnAck() { //只加载31天内非天窗期的报警 CString sql = " SELECT [ID],a.[mo],a.[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id],[posi],[loworhigh],[referval],[recovery_time],[sunroof],zzjno,[ack_result] FROM [rm_alarm] as A \ LEFT JOIN(SELECT mo, mp, zzjno FROM rm_map) AS B ON a.mo = b.mo and a.mp = b.mp \ WHERE DATEADD(dd, -31, getdate()) < occur_time and sunroof = 0 and type !=32 and (ack_result = 0 OR [recovery_time] < '2000') \ ORDER BY occur_time ASC; "; COdbcStatement stmt; if (!CDBConnectPool::Instance()->DBQuery(stmt, sql)) { ASSERT(FALSE); CSimpleLog::Error("执行语句失败" + sql); return FALSE; } char mo[51], mp[51], desc[200], suggest[200], event_id[37] = { 0 }, rel_id[37] = { 0 }; uint8_t no, type, level, posi, loworhigh, sunroof; int val; int id; int zzjno; int ackResult; TIMESTAMP_STRUCT ts,tsRecovery; int referval; int nCol = 1; stmt.BindIntCol(nCol++, &id); stmt.BindCharCol(nCol++, mo, sizeof(mo)); stmt.BindCharCol(nCol++, mp, sizeof(mp)); stmt.BindTinyIntCol(nCol++, &no); stmt.BindTinyIntCol(nCol++, &type); stmt.BindTimeStampCol(nCol++, &ts); stmt.BindTinyIntCol(nCol++, &level); stmt.BindCharCol(nCol++, desc, sizeof(desc)); stmt.BindCharCol(nCol++, suggest, sizeof(suggest)); stmt.BindIntCol(nCol++, &val); stmt.BindCharCol(nCol++, event_id, 36); stmt.BindCharCol(nCol++, rel_id, 36); stmt.BindTinyIntCol(nCol++, &posi); stmt.BindTinyIntCol(nCol++, &loworhigh); stmt.BindIntCol(nCol++, &referval); stmt.BindTimeStampCol(nCol++, &tsRecovery); stmt.BindTinyIntCol(nCol++, &sunroof); stmt.BindIntCol(nCol++, &zzjno); stmt.BindIntCol(nCol++, &ackResult); do { if (stmt.FetchNext() != 0) break; ALARM_INFO *pAlarm = new ALARM_INFO; pAlarm->event_id = event_id; if (rel_id[0] != 0x20) pAlarm->rel_id = rel_id; pAlarm->id = id; pAlarm->mo = mo; pAlarm->mp = mp; pAlarm->no = no; pAlarm->type = (eZL_ALARMTYPE)type; ConvertData(ts, pAlarm->time); pAlarm->val = val; pAlarm->level = level; pAlarm->desc = desc; pAlarm->suggest = suggest; pAlarm->posi = (eDaoChaPosi)posi; pAlarm->loworhigh = (eLowHigh)loworhigh; pAlarm->refer_val = referval; ConvertData(tsRecovery, pAlarm->recoveryTime); pAlarm->sunroof = sunroof; pAlarm->zzjno = zzjno; pAlarm->ack_result = ackResult; m_lstUnConfirmAlarm.push_back(pAlarm); } while (true); stmt.Close(); CSimpleLog::Info(("一共加载(" + to_string(m_lstUnConfirmAlarm.size()) + ")条未受理和未恢复的报警").c_str()); return TRUE; }