ResistAlarm.cpp 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865
  1. #include "stdafx.h"
  2. #include "ResistAlarm.h"
  3. #include "MonitorObject.h"
  4. #include "Device.h"
  5. #include <ODBC/DBConnectPool.h>
  6. #include <rapidjson/document.h>
  7. #include <rapidjson/writer.h>
  8. #include <rapidjson/stringbuffer.h>
  9. #include <Simplelog.h>
  10. #include <sstream>
  11. #include <gbk2utf8.h>
  12. #include "AppService.h"
  13. #include <yyjson.h>
  14. CResistAlarm::CResistAlarm()
  15. {
  16. }
  17. CResistAlarm::~CResistAlarm()
  18. {
  19. }
  20. CResistAlarmMng::CResistAlarmMng()
  21. {
  22. }
  23. CResistAlarmMng::~CResistAlarmMng()
  24. {
  25. }
  26. BOOL CResistAlarmMng::Start()
  27. {
  28. LoadAlarmSet();
  29. if (FALSE == LoadAlarmID()) return FALSE;
  30. LoadUnAck();
  31. //无须开启线程检测
  32. /*
  33. m_bWork = true;
  34. m_pThreadAlarmSet = new thread(CResistAlarmMng::ThreadProcAlarmSet, (DWORD_PTR)this);
  35. if (m_pThreadAlarmSet == nullptr) return FALSE;
  36. m_pThreadDevice = new thread(CResistAlarmMng::ThreadProcDevice, (DWORD_PTR)this);
  37. if (m_pThreadDevice == nullptr) return FALSE;
  38. */
  39. return TRUE;
  40. }
  41. void CResistAlarmMng::Stop()
  42. {
  43. m_bWork = false;
  44. if (m_pThreadAlarmSet)
  45. {
  46. m_pThreadAlarmSet->join();
  47. delete m_pThreadAlarmSet;
  48. m_pThreadAlarmSet = nullptr;
  49. }
  50. for (auto& it : m_alarm_set)
  51. {
  52. if (it.second)
  53. {
  54. if (it.second->type == eZL_ALARMTYPE::MAX_OVER_LIMIT)
  55. {
  56. delete (MAX_OVER_LIMIT_INFO*)it.second;
  57. it.second = nullptr;
  58. }
  59. else if (it.second->type == eZL_ALARMTYPE::FRICTION_OVER_LIMIT)
  60. {
  61. delete (FRICTION_OVER_LIMIT_INFO*)it.second;
  62. it.second = nullptr;
  63. }
  64. else
  65. {
  66. assert(0);
  67. }
  68. }
  69. }
  70. m_alarm_set.clear();
  71. for (auto& it : m_lstUnConfirmAlarm) delete it;
  72. m_lstUnConfirmAlarm.clear();
  73. }
  74. //BASE_INFO* CResistAlarmMng::Find(string momp, uint8_t no, uint8_t type)
  75. //{
  76. // stringstream ss;
  77. // ss << momp << '.' << to_string(no) << '.' << to_string(type);
  78. // auto it = m_alarm_set.find(ss.str());
  79. // if (it != m_alarm_set.end())
  80. // {
  81. // return it->second;
  82. // }
  83. // return nullptr;
  84. //}
  85. BASE_INFO* CResistAlarmMng::Find(string mo, string mp, uint8_t no, eZL_ALARMTYPE type)
  86. {
  87. stringstream ss;
  88. ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string((uint8_t)type);
  89. auto it = m_alarm_set.find(ss.str());
  90. if (it != m_alarm_set.end())
  91. {
  92. return it->second;
  93. }
  94. return nullptr;
  95. }
  96. //bool CResistAlarmMng::Insert(const string& momp, uint8_t no, uint8_t type, BASE_INFO* info)
  97. //{
  98. // auto it = m_alarm_set.insert(make_pair(momp + '.' + to_string(no) + '.' + to_string(type), info));
  99. // return it.second;
  100. //}
  101. bool CResistAlarmMng::Insert(string mo, string mp, uint8_t no, uint8_t type, BASE_INFO* info)
  102. {
  103. auto it = m_alarm_set.insert(make_pair(mo + '.' + mp + '.' + to_string(no) + '.' + to_string(type), info));
  104. return it.second;
  105. }
  106. //bool CResistAlarmMng::ConfirmAlarm(string mo, string mp, uint8_t no, uint8_t type, const SYSTEMTIME& st)
  107. //{
  108. // lock_guard<mutex> lock(m_mtxAlarm);
  109. // auto it = m_lstUnConfirmAlarm.begin();
  110. // for (it; it != m_lstUnConfirmAlarm.end(); ++it)
  111. // {
  112. // const auto& pInfo = *it;
  113. // if (pInfo->mo.compare(mo) == 0 && pInfo->mp.compare(mp) == 0 && pInfo->no == no && pInfo->type == type && pInfo->time.wYear == st.wYear &&
  114. // pInfo->time.wMonth == st.wMonth && pInfo->time.wDay == st.wDay && pInfo->time.wHour == st.wHour && pInfo->time.wMinute == st.wMinute)
  115. // {
  116. // m_lstUnConfirmAlarm.erase(it);
  117. // return true;
  118. // }
  119. // }
  120. // return false;
  121. //}
  122. bool CResistAlarmMng::AckAlarm(int alarm_id, string& name, CTime& time)
  123. {
  124. lock_guard<mutex> lock(m_mtxAlarm);
  125. auto it = m_lstUnConfirmAlarm.begin();
  126. for (it; it != m_lstUnConfirmAlarm.end(); ++it)
  127. {
  128. auto& pInfo = *it;
  129. if (alarm_id == pInfo->id)
  130. {
  131. pInfo->ack_result = 1;
  132. pInfo->ack_name = name;
  133. pInfo->ack_time = time;
  134. return true;
  135. }
  136. }
  137. return false;
  138. }
  139. bool CResistAlarmMng::HandleAlarm(int alarm_id)
  140. {
  141. lock_guard<mutex> lock(m_mtxAlarm);
  142. auto it = m_lstUnConfirmAlarm.begin();
  143. for (it; it != m_lstUnConfirmAlarm.end(); ++it)
  144. {
  145. const auto& pInfo = *it;
  146. if (pInfo->id == alarm_id)
  147. {
  148. m_lstUnConfirmAlarm.erase(it);
  149. return true;
  150. }
  151. }
  152. return false;
  153. }
  154. void CResistAlarmMng::GeneralAlarm(string mo, string mp, uint8_t no, eZL_ALARMTYPE type, uint8_t level, SYSTEMTIME& tAlarm)
  155. {
  156. ALARM_INFO* pAlarmInfo = nullptr;
  157. bool bNew = false;
  158. {
  159. std::lock_guard<mutex> lock(m_mtxAlarm);
  160. for (const auto& alarm : m_lstUnConfirmAlarm)
  161. {
  162. if (alarm->type == eZL_ALARMTYPE::SENSOR_ABNORMAL && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0 && no == alarm->no/* && ctAlarmTime - CTime(alarm->time) < cts*/) //跟上次报警时间超过1小时,则算新报警
  163. {
  164. pAlarmInfo = alarm;
  165. break;
  166. }
  167. }
  168. }
  169. if (pAlarmInfo == nullptr)
  170. {
  171. bNew = true;
  172. pAlarmInfo = new ALARM_INFO;
  173. pAlarmInfo->id = ++m_nAlarmID;
  174. pAlarmInfo->level = 1;
  175. pAlarmInfo->mo = mo;
  176. pAlarmInfo->mp = mp;
  177. pAlarmInfo->no = no;
  178. pAlarmInfo->time = tAlarm;
  179. //pAlarmInfo->time.wMilliseconds = alarm_time % 1000;
  180. pAlarmInfo->type = eZL_ALARMTYPE::SENSOR_ABNORMAL;
  181. pAlarmInfo->val = 0;
  182. char szInfo[200];
  183. sprintf_s(szInfo, sizeof(szInfo), "传感器异常时间:%04d-%02d-%02d %02d:%02d:%02d",
  184. tAlarm.wYear, tAlarm.wMonth, tAlarm.wDay, tAlarm.wHour, tAlarm.wMinute, tAlarm.wSecond);
  185. pAlarmInfo->desc = szInfo;
  186. lock_guard<mutex> lock(m_mtxAlarm);
  187. m_lstUnConfirmAlarm.push_back(pAlarmInfo);
  188. }
  189. //send
  190. if (bNew) //不再推送
  191. {
  192. rapidjson::StringBuffer buffer;
  193. auto ret = AlarmInfo2Pack(pAlarmInfo, buffer);
  194. const char* output = buffer.GetString();
  195. //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength());
  196. CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength());
  197. }
  198. //save
  199. if (bNew)
  200. {
  201. CTime ctAlarmTime(tAlarm);
  202. CString sql;
  203. sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val]) "\
  204. "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d);",
  205. pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, (int)pAlarmInfo->type,
  206. (LPCSTR)(ctAlarmTime.Format("%Y-%m-%d %H:%M:%S")), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val);
  207. if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql))
  208. {
  209. CSimpleLog::Error("执行语句失败" + sql);
  210. }
  211. }
  212. }
  213. void CResistAlarmMng::RecoverAlarm(const string mo, const string mp, const uint8_t no, const eZL_ALARMTYPE type, const uint8_t level, const SYSTEMTIME& tAlarm)
  214. {
  215. uint32_t alarm_id = -1;
  216. {
  217. std::lock_guard<mutex> lock(m_mtxAlarm);
  218. for (auto it = m_lstUnConfirmAlarm.begin(); it != m_lstUnConfirmAlarm.end(); it++)
  219. {
  220. auto alarm = *it;
  221. if (alarm->type == type && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0 && no == alarm->no && level == alarm->level/* && ctAlarmTime - CTime(alarm->time) < cts*/) //跟上次报警时间超过1小时,则算新报警
  222. {
  223. alarm_id = alarm->id;
  224. m_lstUnConfirmAlarm.erase(it);
  225. break;
  226. }
  227. }
  228. }
  229. if (alarm_id == -1)
  230. return;
  231. CTime ctAlarm(tAlarm);
  232. string ack_time = ctAlarm.Format("%Y-%m-%d %H:%M:%S");
  233. //更新数据库
  234. {
  235. CString sql;
  236. sql.Format("UPDATE [rm_alarm] SET ack_result = 1, ack_name='%s', ack_time='%s' WHERE ID = %d;",
  237. "系统", ack_time.c_str(), alarm_id);
  238. CDBConnectPool::Instance()->DBExecuteSQL(sql);
  239. }
  240. auto doc = yyjson_mut_doc_new(nullptr);
  241. auto root = yyjson_mut_obj(doc);
  242. yyjson_mut_doc_set_root(doc, root);
  243. yyjson_mut_obj_add_str(doc, root, "cmd", "alm_ack");
  244. yyjson_mut_obj_add_uint(doc, root, "alarm_id", alarm_id);
  245. yyjson_mut_obj_add_strcpy(doc, root, "ack_time", ack_time.c_str());
  246. yyjson_mut_obj_add_strcpy(doc, root, "ack_name", ANSItoUTF8("系统").c_str());
  247. size_t len;
  248. auto json = yyjson_mut_write(doc, 0, &len);
  249. if (json)
  250. {
  251. CAppService::Instance()->GetMgServer()->SendToAllClient(json, len);
  252. free(json);
  253. }
  254. yyjson_mut_doc_free(doc);
  255. }
  256. eZL_MP_STAT CResistAlarmMng::GetAlarmStat(string& mo, string& mp, SYSTEMTIME& stAlarm)
  257. {
  258. eZL_MP_STAT stat = eZL_MP_STAT::MP_STAT_NORMAL_GREEN;
  259. lock_guard<mutex> lock(m_mtxAlarm);
  260. auto it = m_lstUnConfirmAlarm.rbegin();
  261. for (it; it != m_lstUnConfirmAlarm.rend(); ++it)
  262. {
  263. const auto& pInfo = *it;
  264. if (pInfo->ack_result) continue;//受理了暂时放过
  265. if (pInfo->mo.compare(mo) == 0 && pInfo->mp.compare(mp) == 0)
  266. {
  267. if (pInfo->type == eZL_ALARMTYPE::EQUIP_OFFLINE || pInfo->type == eZL_ALARMTYPE::SENSOR_ABNORMAL)
  268. {
  269. stat = eZL_MP_STAT::MP_STAT_OFFLINE_GRAY;
  270. break;
  271. }
  272. else if (pInfo->level == 1)
  273. {
  274. stAlarm = pInfo->time;
  275. stat = eZL_MP_STAT::MP_STAT_ALARM_RED;
  276. break;
  277. }
  278. else if (pInfo->level == 0)
  279. {
  280. stAlarm = pInfo->time;
  281. stat = eZL_MP_STAT::MP_STAT_WARN_ORANGE;
  282. break;
  283. }
  284. }
  285. }
  286. return stat;
  287. }
  288. bool CResistAlarmMng::AlarmInfo2Pack(const ALARM_INFO* pAlarmInfo, rapidjson::StringBuffer& buffer, bool bGb2312 /*= false*/)
  289. {
  290. char szInfo[200];
  291. char szUtf[200];
  292. using namespace rapidjson;
  293. Writer<StringBuffer> writer(buffer);
  294. writer.StartObject();
  295. writer.Key("cmd");
  296. writer.String("new_alarm");
  297. writer.Key("type");
  298. //if (pAlarmInfo->type == MAX_OVER_LIMIT) writer.String("monitor.alarm.max_over_limit");
  299. //else if (pAlarmInfo->type == EQUIP_OFFLINE) writer.String("monitor.alarm.equip_offline");
  300. //else if (pAlarmInfo->type == SENSOR_ABNORMAL) writer.String("monitor.alarm.sensor_abnormal");
  301. //else writer.String("");
  302. writer.Int((int)pAlarmInfo->type);
  303. writer.Key("tag");
  304. writer.String((pAlarmInfo->mo + '.' + pAlarmInfo->mp + '.' + to_string(pAlarmInfo->no + 1) + "#").c_str());
  305. string up, momp_name, up_name;
  306. string momp = pAlarmInfo->mo + "." + pAlarmInfo->mp;
  307. CMonitorObjectMng::Instance()->GetStationNameByMomP(momp, up, momp_name);
  308. auto pObject = CMonitorObjectMng::Instance()->GetTreeByID(up);
  309. if (pObject) up_name = pObject->name;
  310. string name1, name2, name3;
  311. CMonitorObjectMng::Instance()->GetNameByMoMp(momp, name1, name2, name3);
  312. if (pAlarmInfo->no == 0 && name1.length() == 0) name1 = "1号测力点";
  313. else if (pAlarmInfo->no == 1 && name2.length() == 0) name2 = "2号测力点";
  314. else if (pAlarmInfo->no == 2 && name3.length() == 0) name3 = "3号测力点";
  315. sprintf_s(szInfo, 200, "%s.%s.%s.%s%s", up_name.c_str(), momp_name.c_str(),
  316. pAlarmInfo->no == 0 ? name1.c_str() : pAlarmInfo->no == 1 ? name2.c_str() : pAlarmInfo->no == 2 ? name3.c_str() : "",
  317. GetAlarmName(pAlarmInfo->type).c_str(),
  318. pAlarmInfo->level == 1 ? "报警" : "预警"
  319. );
  320. gbk2utf8(szUtf, sizeof(szUtf), szInfo);
  321. writer.Key("title");
  322. writer.String(szUtf);
  323. gbk2utf8(szUtf, sizeof(szUtf), up.c_str());
  324. writer.Key("up");
  325. writer.String(szUtf);
  326. gbk2utf8(szUtf, sizeof(szUtf), up_name.c_str());
  327. writer.Key("up_name");
  328. writer.String(szUtf);
  329. writer.Key("alarm_id");
  330. writer.Uint(pAlarmInfo->id);
  331. writer.Key("level");
  332. if (pAlarmInfo->level)
  333. writer.String("alarm");
  334. else
  335. writer.String("warn");
  336. writer.Key("occur_time");
  337. sprintf_s(szInfo, sizeof(szInfo), "%04d-%02d-%02d %02d:%02d:%02d.%03d",
  338. pAlarmInfo->time.wYear, pAlarmInfo->time.wMonth, pAlarmInfo->time.wDay,
  339. pAlarmInfo->time.wHour, pAlarmInfo->time.wMinute, pAlarmInfo->time.wSecond, pAlarmInfo->time.wMilliseconds);
  340. writer.String(szInfo);
  341. writer.Key("val");
  342. if (pAlarmInfo->type == eZL_ALARMTYPE::EQUIP_OFFLINE || pAlarmInfo->type == eZL_ALARMTYPE::SENSOR_ABNORMAL)
  343. writer.String("-");
  344. else
  345. writer.String(to_string(pAlarmInfo->val).c_str());
  346. writer.String("desc");
  347. gbk2utf8(szInfo, sizeof(szInfo), pAlarmInfo->desc.c_str());
  348. writer.String(szInfo);
  349. writer.Key("suggest");
  350. writer.String("");
  351. if (pAlarmInfo->ack_result)
  352. {
  353. //已受理的报警
  354. writer.String("ack_result");
  355. writer.Int(pAlarmInfo->ack_result);
  356. writer.Key("ack_name");
  357. writer.String(ANSItoUTF8(pAlarmInfo->ack_name).c_str());
  358. writer.Key("ack_time");
  359. writer.String(pAlarmInfo->ack_time.Format("%Y-%m-%d %H:%M:%S"));
  360. }
  361. writer.EndObject();
  362. return true;
  363. }
  364. CResistAlarmMng CResistAlarmMng::obj;
  365. 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, string mark)
  366. {
  367. if (show_time == 0) return;
  368. CTime ctShowTime(show_time / 1000);
  369. string table_name = fmt::format("rm_move_{:0>4}{:0>2}", ctShowTime.GetYear(), ctShowTime.GetMonth());
  370. CString sql = fmt::format("INSERT INTO {} (mo,mp,show_time,start_time,end_time,curr_val,show_val,idx,posi,mark) values ('{}', '{}', '{}', '{}','{}', {}, {}, {}, {}, '{}');",
  371. table_name, mo, mp, (LPCSTR)ctShowTime.Format("%Y-%m-%d %H:%M:%S.") + to_string(show_time % 1000),
  372. start_time ? CTime(start_time).Format("%Y-%m-%d %H:%M:%S") : "", end_time ? CTime(end_time).Format("%Y-%m-%d %H:%M:%S") : "", curr_val, show_val, idx, posi, mark).c_str();
  373. if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE)
  374. SPDLOG_ERROR(sql);
  375. }
  376. BOOL ConmpareValue(std::map<time_t, int>::const_iterator i, std::map<time_t, int>::const_iterator j, short refer_value, int& hight_num, int low_num)
  377. {
  378. int start_value = 0;
  379. for (i; i != j; i++)
  380. {
  381. if (i->second > refer_value)
  382. {
  383. if (start_value == 1)
  384. {
  385. //原来大于,现在也是大于
  386. continue;
  387. }
  388. else
  389. {
  390. //原来小于或者无效,现在大于
  391. start_value = 1;
  392. hight_num++;
  393. }
  394. }
  395. else
  396. {
  397. if (start_value == -1)
  398. {
  399. //原来小于,现在小于等于
  400. continue;
  401. }
  402. else
  403. {
  404. //原来大于或者无效,现在小于
  405. start_value = -1;
  406. low_num++;
  407. }
  408. }
  409. }
  410. return TRUE;
  411. }
  412. void CResistAlarmMng::ThreadProcAlarmSet(DWORD_PTR param)
  413. {
  414. auto pService = (CResistAlarmMng*)param;
  415. Sleep(2000);
  416. time_t tmNow;
  417. do
  418. {
  419. Sleep(100);
  420. time(&tmNow);
  421. if (tmNow == pService->m_lastDetectTime)
  422. continue;
  423. pService->m_lastDetectTime = tmNow;
  424. //1秒判断一次
  425. for (const auto& item : pService->m_alarm_set)
  426. {
  427. if (item.second == nullptr) continue;
  428. if (item.second->enable == false) continue;
  429. if (item.second->type != eZL_ALARMTYPE::MAX_OVER_LIMIT && item.second->type != eZL_ALARMTYPE::FRICTION_OVER_LIMIT) //这个逻辑里面只支持这两种
  430. continue;
  431. if (item.second->no < 0 || item.second->no > 2) continue;
  432. int nPos = item.first.find('.');
  433. if (nPos == -1) continue;
  434. int nPos2 = item.first.find('.', nPos + 1);
  435. if (nPos2 == -1) continue;
  436. string mo = item.first.substr(0, nPos);
  437. string mp = item.first.substr(nPos + 1, nPos2 - nPos - 1);
  438. string momp = item.first.substr(0, nPos2);
  439. bool bNew = false;
  440. ALARM_INFO *pAlarmInfo = nullptr;
  441. CTime ctAlarmTime;
  442. string imei; int idx;
  443. //auto ret = CMonitorObjectMng::Instance()->MOMP2IMEI(momp, imei, idx); //TODO
  444. //if (ret == false) continue;
  445. #ifdef _DEBUG
  446. if (strcmp("860588048955283", imei.c_str()) != 0) continue;
  447. #endif
  448. auto pDevice = CDeviceMng::Instance()->Find(imei);
  449. if (pDevice == nullptr)
  450. {
  451. CSimpleLog::Error(("找不到imei(" + imei + ")" + std::to_string(__LINE__)).c_str());
  452. continue;
  453. }
  454. int desc_type = 0;
  455. bool bAlarm = false, bWarn = false; int alarm_value = 0; time_t alarm_time;
  456. short high_alarm_limit = SHORT_MAX, high_warn_limit = SHORT_MAX, low_alarm_limit = -SHORT_MAX, low_warn_limit = -SHORT_MAX, alarm_refer = SHORT_MAX;
  457. time_t tmNow; time(&tmNow);
  458. BASE_INFO* pAlarmSet = item.second;
  459. do{
  460. Sleep(100);
  461. lock_guard<mutex> lock(pDevice->m_mtx);
  462. std::map<time_t, int>* pData = pDevice->GetMapData(idx, item.second->no);
  463. assert(pData);
  464. if (pData == nullptr) continue;
  465. if (pData->size() == 0) continue;
  466. if (item.second->type == eZL_ALARMTYPE::MAX_OVER_LIMIT)
  467. {
  468. auto pInfo = (MAX_OVER_LIMIT_INFO*)item.second;
  469. #ifdef _DEBUG
  470. if (pInfo->tmLastCheckTime > pData->rbegin()->first)
  471. pInfo->tmLastCheckTime = pData->rbegin()->first;
  472. #endif
  473. auto it = pData->cbegin();
  474. if (pInfo->tmLastCheckTime == 0) pInfo->tmLastCheckTime = pData->rbegin()->first;
  475. else if (pInfo->tmLastCheckTime != 0) it = pData->find(pInfo->tmLastCheckTime);
  476. if (it == pData->cend())
  477. {
  478. it = pData->find(pInfo->tmLastCheckTime / 1000 * 1000);
  479. if (it == pData->cend())
  480. {
  481. pInfo->tmLastCheckTime = pData->rbegin()->first;
  482. continue;
  483. }
  484. }
  485. if (pInfo->tmLastCheckTime == pData->rbegin()->first) //没有新的数据
  486. continue;
  487. #ifdef _DEBUG
  488. 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,
  489. CTime(pInfo->tmLastCheckTime / 1000).Format("%Y-%m-%d %H:%M:%S"), CTime(pData->rbegin()->first / 1000).Format("%Y-%m-%d %H:%M:%S"));
  490. #endif // _DEBUG
  491. time_t tmStartSteady = pInfo->tmLastCheckTime / 1000 - 3; //稳态报警检测开始, 从上次3秒前到当前秒
  492. if (item.second->no == 2)
  493. {
  494. if (pInfo->alarm_high_limit > pInfo->f_alarm_high_limit)
  495. {//定板反
  496. high_alarm_limit = pInfo->alarm_high_limit;
  497. high_warn_limit = pInfo->warn_high_limit;
  498. low_alarm_limit = pInfo->f_alarm_high_limit;
  499. low_warn_limit = pInfo->f_warn_high_limit;
  500. }
  501. else
  502. {//反板定
  503. low_alarm_limit = pInfo->alarm_high_limit;
  504. low_warn_limit = pInfo->warn_high_limit;
  505. high_alarm_limit = pInfo->f_alarm_high_limit;
  506. high_warn_limit = pInfo->f_warn_high_limit;
  507. }
  508. }
  509. for (++it; it != pData->cend(); ++it)
  510. {
  511. //CString str = CTime(it->first / 1000).Format("%Y-%m-%d %H:%M:%S");
  512. if (it->second == INVALID_RESIST)
  513. {
  514. pInfo->tmLastCheckTime = it->first;
  515. continue;
  516. }
  517. if (item.second->no < 2)
  518. {
  519. //1,2 锁闭力报警
  520. if (it->second > pInfo->alarm_high_limit)
  521. {
  522. bAlarm = true;
  523. alarm_refer = pInfo->alarm_high_limit;
  524. alarm_value = it->second;
  525. alarm_time = it->first;
  526. pInfo->tmLastCheckTime = pData->rbegin()->first;
  527. desc_type = 1;
  528. break;
  529. }
  530. //else if (it->second > pInfo->warn_high_limit) //稳态报警单独判断
  531. //{
  532. // bWarn = true;
  533. // alarm_refer = pInfo->warn_high_limit;
  534. // alarm_value = it->second;
  535. // alarm_time = it->first;
  536. // pInfo->tmLastCheckTime = pData->rbegin()->first;
  537. //}
  538. }
  539. else
  540. {
  541. assert(item.second->no == 2);
  542. if (pInfo->alarm_high_limit == SHORT_MAX || pInfo->f_alarm_high_limit == SHORT_MAX || pInfo->alarm_high_limit == pInfo->f_alarm_high_limit)
  543. break;
  544. desc_type = 3;
  545. if (it->second > high_alarm_limit)
  546. {
  547. bAlarm = true;
  548. alarm_refer = high_alarm_limit;
  549. alarm_value = it->second;
  550. alarm_time = it->first;
  551. pInfo->tmLastCheckTime = pData->rbegin()->first;
  552. break;
  553. }
  554. else if (it->second < low_alarm_limit)
  555. {
  556. bAlarm = true;
  557. alarm_refer = low_alarm_limit;
  558. alarm_value = it->second;
  559. alarm_time = it->first;
  560. pInfo->tmLastCheckTime = pData->rbegin()->first;
  561. break;
  562. }
  563. else if (low_warn_limit == SHORT_MAX || high_warn_limit == SHORT_MAX)
  564. {
  565. //未设置预警值
  566. }
  567. else if (it->second > high_warn_limit)
  568. {
  569. bWarn = true;
  570. alarm_refer = high_warn_limit;
  571. alarm_value = it->second;
  572. alarm_time = it->first;
  573. pInfo->tmLastCheckTime = pData->rbegin()->first;
  574. }
  575. else if (it->second < low_warn_limit)
  576. {
  577. bWarn = true;
  578. alarm_refer = low_warn_limit;
  579. alarm_value = it->second;
  580. alarm_time = it->first;
  581. pInfo->tmLastCheckTime = pData->rbegin()->first;
  582. }
  583. }
  584. pInfo->tmLastCheckTime = it->first;
  585. }
  586. //稳态报警判断
  587. if (item.second->no < 2 && bAlarm == false)
  588. {
  589. time_t tmEnd = pInfo->tmLastCheckTime / 1000;
  590. int dif = tmEnd - tmStartSteady;
  591. for (time_t i = tmStartSteady; i < tmEnd - 3; i++)
  592. {
  593. #ifdef _DEBUG
  594. COleDateTime t(i);
  595. TRACE("%s\r\n", t.Format("%Y-%m-%d %H:%M:%S"));
  596. #endif // _DEBUG
  597. auto j = pData->find(i * 1000);
  598. if (j == pData->end()) continue;
  599. time_t t2 = (i + 1) * 1000;
  600. auto k = pData->find(t2);
  601. if (k == pData->end()) continue;
  602. t2 = (i + 2) * 1000;
  603. k = pData->find(t2);
  604. if (k == pData->end()) continue;
  605. //连续3秒在线,继续找下一个结束点
  606. t2 = (i + 3) * 1000;
  607. auto g = pData->find(t2);
  608. if (g == pData->end())
  609. {
  610. for (++k; k != pData->end(); k++)
  611. {
  612. if (k->first >= t2)
  613. {
  614. g = k;
  615. break;
  616. }
  617. }
  618. }
  619. if (g == pData->end())
  620. continue;
  621. int high_num = 0, low_num = 0;
  622. ConmpareValue(j, g, pInfo->warn_high_limit, high_num, low_num);
  623. if (high_num > 0 && high_num <= 2)
  624. {
  625. bWarn = true;
  626. desc_type = 2;
  627. alarm_refer = pInfo->warn_high_limit;
  628. alarm_value = high_num;
  629. alarm_time = i * 1000; //报警时间
  630. pInfo->tmLastCheckTime = pData->rbegin()->first;
  631. break;
  632. }
  633. }
  634. }
  635. }
  636. else if (item.second->type == eZL_ALARMTYPE::FRICTION_OVER_LIMIT)
  637. {
  638. auto pInfo = (FRICTION_OVER_LIMIT_INFO*)item.second;
  639. #ifdef _DEBUG
  640. if (pInfo->tmLastCheckTime > pData->rbegin()->first)
  641. pInfo->tmLastCheckTime = pData->rbegin()->first;
  642. #endif
  643. auto it = pData->cbegin();
  644. if (pInfo->tmLastCheckTime == 0) pInfo->tmLastCheckTime = pData->rbegin()->first;
  645. else if (pInfo->tmLastCheckTime != 0) it = pData->find(pInfo->tmLastCheckTime);
  646. if (it == pData->cend())
  647. {
  648. it = pData->find(pInfo->tmLastCheckTime / 1000 * 1000);
  649. if (it == pData->cend())
  650. {
  651. pInfo->tmLastCheckTime = pData->rbegin()->first;
  652. continue;
  653. }
  654. }
  655. if (pInfo->tmLastCheckTime == pData->rbegin()->first) //没有新的数据
  656. continue;
  657. if (tmNow * 1000 - pInfo->tmLastCheckTime < 5000) //5秒检测一次
  658. continue;
  659. #ifdef _DEBUG
  660. 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,
  661. CTime(pInfo->tmLastCheckTime / 1000).Format("%Y-%m-%d %H:%M:%S"), CTime(pData->rbegin()->first / 1000).Format("%Y-%m-%d %H:%M:%S"));
  662. #endif // _DEBUG
  663. if (item.second->no != 2) continue;
  664. //从检测时间往前取30秒的数据
  665. static const int dif_resist = 200; //稳定期判定差值
  666. int up_max_resist = INT_MIN; //上最大值
  667. time_t up_max_time = 0;
  668. int up_avg_resist = INT_MIN; //上稳定期平均值
  669. uint64_t up_stable_sum = 0; //上稳定期的和
  670. int up_stable_time = 0; //上稳定期的数值个数
  671. int up_start_resist_stabel = INT_MIN; //上稳定期开始值
  672. time_t up_start_stable_time = 0; //规定是最大值之后的2秒
  673. time_t up_end_stable_time = 0;//稳定结束的时间
  674. int up_dif_time_stable = 0; //上稳定期的时长
  675. int down_max_resist = INT_MAX; //上最大值
  676. time_t down_max_time = 0;
  677. int down_avg_resist = INT_MAX; //上稳定期平均值
  678. uint64_t down_stable_sum = 0; //上稳定期的和
  679. int down_stable_time = 0; //上稳定期的数值个数
  680. int down_start_resist_stabel = INT_MAX; //上稳定期开始值
  681. time_t down_start_stable_time = 0; //规定是最大值之后的2秒
  682. int down_dif_time_stable = 0; //上稳定期的时长
  683. time_t tmEnd = pData->rbegin()->first / 1000 + 1; //结束时间
  684. time_t tmStart = tmEnd - 36;//开始时间是从上次35秒到当前秒
  685. std::map<time_t, int>::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;
  686. //寻找起始时间
  687. for (time_t i = tmStart; i < tmEnd; i++)
  688. {
  689. #ifdef _DEBUG
  690. COleDateTime t(i);
  691. TRACE("%s\r\n", t.Format("%Y-%m-%d %H:%M:%S"));
  692. #endif // _DEBUG
  693. it_start = pData->find(i * 1000);
  694. if (it_start != pData->cend()) break;
  695. }
  696. pInfo->tmLastCheckTime = pData->rbegin()->first; //赋值最后的时间
  697. if (it_start == pData->cend()) break;
  698. bool bUp = true, bDown = true;
  699. //先找最大值
  700. for (auto i = it_start; i != pData->cend(); i++)
  701. {
  702. //寻找最大的点
  703. if (i->second > up_max_resist)
  704. {
  705. up_max_resist = i->second;
  706. it_up_max = i;
  707. }
  708. //寻找最小的点
  709. if (i->second < down_max_resist)
  710. {
  711. down_max_resist = i->second;
  712. it_down_min = i;
  713. }
  714. }
  715. if (pInfo->tmLastCheckTime - it_up_max->first < 17000) bUp = false; //小于17秒
  716. if (pInfo->tmLastCheckTime - it_down_min->first < 1700) bDown = false; //小于17秒
  717. if(bUp == false && bDown == false) break;
  718. //再找稳定开始
  719. if (bUp)
  720. {
  721. it_up_stable_start = it_up_max;
  722. for (auto i = it_up_max; i != pData->cend(); i++)
  723. {
  724. if (i->first - it_up_max->first < 2000) continue;
  725. else
  726. {
  727. it_up_stable_start = i;
  728. break;
  729. }
  730. }
  731. if (it_up_stable_start == it_up_max) bUp = false;
  732. }
  733. if (bDown)
  734. {
  735. it_down_stable_start = it_down_min;
  736. for (auto i = it_down_min; i != pData->cend(); i++)
  737. {
  738. if (i->first - it_down_min->first < 2000) continue;
  739. else
  740. {
  741. it_down_stable_start = i;
  742. break;
  743. }
  744. }
  745. if (it_down_stable_start == it_down_min) bDown = false;
  746. }
  747. if (bUp == false && bDown == false) break;
  748. if (bUp)
  749. {
  750. up_start_resist_stabel = it_up_stable_start->second;//稳定期开始的值
  751. it_up_stable_end = it_up_stable_start;
  752. for (auto i = it_up_stable_start; i != pData->cend(); i++)
  753. {
  754. if (abs(up_start_resist_stabel - i->second) < dif_resist)
  755. {
  756. up_stable_sum += i->second;
  757. up_start_stable_time++;
  758. it_up_stable_end = i;
  759. continue;
  760. }
  761. else
  762. {
  763. break;
  764. }
  765. }
  766. //时间条件限定在 15s-30s 之间
  767. auto dif = it_up_stable_end->first - it_up_stable_start->first;
  768. if (dif > 15000 && dif < 30000)
  769. {
  770. //平均值
  771. up_avg_resist = up_stable_sum / up_start_stable_time;
  772. if (up_avg_resist < pInfo->up_alarm_low_limit)
  773. {
  774. bAlarm = true;
  775. alarm_value = up_avg_resist;
  776. alarm_time = it_up_stable_start->first;
  777. alarm_refer = pInfo->up_alarm_low_limit;
  778. desc_type = 4;
  779. }
  780. else if (up_avg_resist < pInfo->up_warn_low_limit)
  781. {
  782. bWarn = true;
  783. alarm_value = up_avg_resist;
  784. alarm_time = it_up_stable_start->first;
  785. alarm_refer = pInfo->up_warn_low_limit;
  786. desc_type = 4;
  787. }
  788. }
  789. }
  790. if (bDown)
  791. {
  792. down_start_resist_stabel = it_down_stable_start->second;//稳定期开始的值
  793. it_down_stable_end = it_down_stable_start;
  794. for (auto i = it_down_stable_start; i != pData->cend(); i++)
  795. {
  796. if (abs(down_start_resist_stabel - i->second) < dif_resist)
  797. {
  798. down_stable_sum += i->second;
  799. down_start_stable_time++;
  800. it_down_stable_end = i;
  801. continue;
  802. }
  803. else
  804. {
  805. break;
  806. }
  807. }
  808. //时间条件限定在 15s-30s 之间
  809. auto dif = it_down_stable_end->first - it_down_stable_start->first;
  810. if (dif > 15000 && dif < 30000)
  811. {
  812. //平均值
  813. down_avg_resist = down_stable_sum / down_start_stable_time;
  814. if (down_avg_resist > pInfo->dw_alarm_high_limit)
  815. {
  816. bAlarm = true;
  817. alarm_value = down_avg_resist;
  818. alarm_time = it_down_stable_start->first;
  819. alarm_refer = pInfo->dw_alarm_high_limit;
  820. desc_type = 5;
  821. }
  822. else if (down_avg_resist > pInfo->dw_warn_high_limit)
  823. {
  824. bWarn = true;
  825. alarm_value = down_avg_resist;
  826. alarm_time = it_down_stable_start->first;
  827. alarm_refer = pInfo->dw_warn_high_limit;
  828. desc_type = 5;
  829. }
  830. }
  831. }
  832. }
  833. else
  834. {
  835. //其他未实现
  836. //TODO
  837. assert(0);
  838. continue;
  839. }
  840. }while (false);
  841. //update
  842. CString sql;
  843. sql.Format("update rm_alarm_set SET time = %I64u WHERE mo = '%s' and mp = '%s' and no = %d and type = %d",
  844. pAlarmSet->tmLastCheckTime, mo.c_str(), mp.c_str(), pAlarmSet->no, pAlarmSet->type);
  845. if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE)
  846. {
  847. assert(0);
  848. CSimpleLog::Error("语句执行失败" + sql);
  849. }
  850. if (bAlarm == false && bWarn == false) continue; //没有报警
  851. //查找是否原有的报警已存在
  852. uint8_t level = 0;
  853. if (bAlarm) level = 1;
  854. ctAlarmTime = CTime(alarm_time / 1000);
  855. {
  856. std::lock_guard<mutex> lock(pService->m_mtxAlarm);
  857. for (const auto& alarm : pService->m_lstUnConfirmAlarm)
  858. {
  859. static CTimeSpan cts(0, 6, 0, 0); //报警间隔6小时重新生成报警
  860. if (alarm->no == item.second->no && alarm->type == pAlarmSet->type && level == alarm->level //预警和报警单独计算
  861. && alarm->mo.compare(mo) == 0 && alarm->mp.compare(mp) == 0 && ctAlarmTime - CTime(alarm->time) < cts) //跟上次报警时间超过1小时,则算新报警
  862. {
  863. pAlarmInfo = alarm;
  864. break;
  865. }
  866. }
  867. }
  868. if (pAlarmInfo == nullptr)
  869. {
  870. bNew = true;
  871. pAlarmInfo = new ALARM_INFO;
  872. pAlarmInfo->id = ++pService->m_nAlarmID;
  873. pAlarmInfo->level = (bAlarm == 1);
  874. pAlarmInfo->mo = mo;
  875. pAlarmInfo->mp = mp;
  876. pAlarmInfo->no = item.second->no;
  877. ctAlarmTime.GetAsSystemTime(pAlarmInfo->time);
  878. pAlarmInfo->time.wMilliseconds = alarm_time % 1000;
  879. pAlarmInfo->type = item.second->type;
  880. pAlarmInfo->val = alarm_value;
  881. char szInfo[200];
  882. if (desc_type == 1)
  883. sprintf_s(szInfo, sizeof(szInfo), "瞬时冲击力超限报警,报警值为%dN, 参考值为%dN", alarm_value, alarm_refer);
  884. else if (desc_type == 2)
  885. sprintf_s(szInfo, sizeof(szInfo), "稳态值超限预警, 超限次数为%d次, 参考值为%dN", alarm_value, alarm_refer);
  886. else if (desc_type == 3)
  887. sprintf_s(szInfo, sizeof(szInfo), "转换阻力值超限报警, 报警值为%dN, 参考值为%dN", alarm_value, alarm_refer);
  888. else if (desc_type == 4)
  889. sprintf_s(szInfo, sizeof(szInfo), "摩擦力超限%s, 缩进位报警值为%dN, 参考值为:%dN", bAlarm == 1 ? "告警" : "预警", alarm_value, alarm_refer);
  890. else if (desc_type == 5)
  891. sprintf_s(szInfo, sizeof(szInfo), "摩擦力超限%s, 伸出位报警值为%dN, 参考值为:%dN", bAlarm == 1 ? "告警" : "预警", alarm_value, alarm_refer);
  892. else
  893. assert(0);
  894. pAlarmInfo->desc = szInfo;
  895. lock_guard<mutex> lock(pService->m_mtxAlarm);
  896. pService->m_lstUnConfirmAlarm.push_back(pAlarmInfo);
  897. }
  898. //send
  899. if (bNew) //不再推送
  900. {
  901. rapidjson::StringBuffer buffer;
  902. auto ret = AlarmInfo2Pack(pAlarmInfo, buffer);
  903. const char* output = buffer.GetString();
  904. //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength());
  905. CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength());
  906. }
  907. //save
  908. if (bNew)
  909. {
  910. CString sql;
  911. sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val]) "\
  912. "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d);",
  913. pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, pAlarmInfo->type,
  914. ctAlarmTime.Format("%Y-%m-%d %H:%M:%S"), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val);
  915. if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql))
  916. {
  917. CSimpleLog::Error("执行语句失败" + sql);
  918. }
  919. }
  920. }
  921. //10秒归档一次
  922. /*采用滑动方式检测.每次检测15秒的数据.每次滑动10秒.
  923. 即0分20秒时 取 0 - 15秒的数据, 下一次检测时间 0分30秒, 取10 - 25秒的数据.
  924. 再下一次检测时间0分40秒, 取20 - 35秒数据.
  925. */
  926. /*
  927. if (tmNow % 10 != 0) continue;
  928. auto& mapDevice = CDeviceMng::Instance()->m_map_devices;
  929. for (auto& it : mapDevice)
  930. {
  931. auto pDevice = it.second;
  932. if (pDevice->m_tmMoveDetectTime == 0)
  933. continue;
  934. time_t tmStart = pDevice->m_tmMoveDetectTime - 20; time_t tmEnd = pDevice->m_tmMoveDetectTime - 2;
  935. #ifdef _DEBUG
  936. string strStart = CTime(tmStart).Format("%Y-%m-%d %H:%M:%S");
  937. string strEnd = CTime(tmEnd).Format("%Y-%m-%d %H:%M:%S");
  938. TRACE("%s-%s\r\n", strStart.c_str(), strEnd.c_str());
  939. #endif // _DEBUG
  940. pDevice->m_tmMoveDetectTime += 10;
  941. for (auto i = 0; i < 3; i++)
  942. {
  943. std::map<time_t, tagSecondStatInfo> map0, map1, map2;
  944. if (pDevice->GetSendStatInfo(tmStart, tmEnd, i, map0, map1, map2) == FALSE) continue;
  945. list<CONVERT_RESIST> lstResit2;
  946. std::map<time_t, int64_t> maxlock0, maxlock1;
  947. mg_per_session_data::GetMaxResist(map2, lstResit2);
  948. if (lstResit2.size())
  949. {
  950. mg_per_session_data::GetMaxLockNew(map0, lstResit2, maxlock0);
  951. mg_per_session_data::GetMaxLockNew(map1, lstResit2, maxlock1);
  952. }
  953. string mo, mp;
  954. if (FALSE == CMonitorObjectMng::Instance()->IMEI2MOMP(pDevice->imei, i, mo, mp))
  955. {
  956. CSimpleLog::Error(fmt::format("IMEI2MOMP fail. imei:{}, idx:{}", pDevice->imei, i).c_str());
  957. continue;
  958. }
  959. string name1, name2, name3, out_name, in_name;
  960. CMonitorObjectMng::Instance()->GetNameByMoMp(mo + "." + mp, name1, name2, name3, out_name, in_name);
  961. for (auto& it : maxlock0)
  962. {
  963. if (name1.find("定位") != -1)
  964. CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, (int)it.second, (it.second >> 32), i,
  965. (uint8_t)eDaoChaPosi::DCP_FIX, fmt::format("定位密贴锁闭力值:{}", (it.second >> 32)));
  966. else
  967. CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, (int)it.second, (it.second >> 32), i,
  968. (uint8_t)eDaoChaPosi::DCP_INVERT, fmt::format("反位密贴锁闭力值:{}", (it.second >> 32)));
  969. }
  970. for (auto& it : maxlock1)
  971. {
  972. if (name2.find("定位") != -1)
  973. CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, (int)it.second, (it.second >> 32), i,
  974. (uint8_t)eDaoChaPosi::DCP_FIX, fmt::format("定位密贴锁闭力值:{}", (it.second >> 32)));
  975. else
  976. CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, (int)it.second, (it.second >> 32), i,
  977. (uint8_t)eDaoChaPosi::DCP_INVERT, fmt::format("反位密贴锁闭力值:{}", (it.second >> 32)));
  978. }
  979. for (auto& it : lstResit2)
  980. {
  981. if (it.bUpOrDown == 1)
  982. {
  983. if (in_name.find("定扳反") != -1)
  984. CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.val, it.fluctuation_val, i,
  985. (uint8_t)eDaoChaPosi::DCP_FIX2INVERT, fmt::format("{}转换值:{}", in_name, it.fluctuation_val));
  986. else
  987. CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.val, it.fluctuation_val, i,
  988. (uint8_t)eDaoChaPosi::DCP_INVERT2FIX, fmt::format("{}转换值:{}", in_name, it.fluctuation_val));
  989. }
  990. else
  991. {
  992. if (out_name.find("定扳反") != -1)
  993. CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.val, it.fluctuation_val, i,
  994. (uint8_t)eDaoChaPosi::DCP_FIX2INVERT, fmt::format("{}转换值:{}", out_name, it.fluctuation_val));
  995. else
  996. CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.val, it.fluctuation_val, i,
  997. (uint8_t)eDaoChaPosi::DCP_INVERT2FIX, fmt::format("{}转换值:{}", out_name, it.fluctuation_val));
  998. }
  999. }
  1000. }
  1001. }
  1002. */
  1003. //10秒归档一次
  1004. if (tmNow % 10 != 0) continue;
  1005. time_t tt;
  1006. time(&tt);
  1007. auto& mapDevice = CDeviceMng::Instance()->m_map_devices;
  1008. for (auto& it : mapDevice)
  1009. {
  1010. auto pDevice = it.second;
  1011. for (auto i = 0; i < 3; i++)
  1012. {
  1013. string mo, mp;
  1014. //if (FALSE == CMonitorObjectMng::Instance()->IMEI2MOMP(pDevice->imei, i, mo, mp)) //TODO
  1015. {
  1016. //CSimpleLog::Error(fmt::format("IMEI2MOMP fail. imei:{}, idx:{}, {}:{}", pDevice->imei, i, __FILE__, __LINE__).c_str());
  1017. continue; //没有绑定返回
  1018. }
  1019. std::map<time_t, tagSecondStatInfo> map0, map1, map2;
  1020. if (i == 0)
  1021. {
  1022. if (pDevice->m_mapSecondStatInfo00.size() == 0) continue;
  1023. else if (tt - pDevice->m_tmMoveDetectTime0 < 20) continue;
  1024. else if (pDevice->m_mapSecondStatInfo00.rbegin()->second.dif_val > 100) continue; //最后值需要稳定
  1025. lock_guard<mutex> lock(pDevice->m_mtx);
  1026. swap(pDevice->m_mapSecondStatInfo00, map0);
  1027. swap(pDevice->m_mapSecondStatInfo01, map1);
  1028. swap(pDevice->m_mapSecondStatInfo02, map2);
  1029. }
  1030. else if (i == 1)
  1031. {
  1032. if (pDevice->m_mapSecondStatInfo10.size() == 0) continue;
  1033. else if (tt - pDevice->m_tmMoveDetectTime1 < 20) continue;
  1034. else if (pDevice->m_mapSecondStatInfo10.rbegin()->second.dif_val > 100) continue; //最后值需要稳定
  1035. lock_guard<mutex> lock(pDevice->m_mtx);
  1036. swap(pDevice->m_mapSecondStatInfo10, map0);
  1037. swap(pDevice->m_mapSecondStatInfo11, map1);
  1038. swap(pDevice->m_mapSecondStatInfo12, map2);
  1039. }
  1040. else
  1041. {
  1042. if (pDevice->m_mapSecondStatInfo20.size() == 0) continue;
  1043. else if (tt - pDevice->m_tmMoveDetectTime2 < 20) continue;
  1044. else if (pDevice->m_mapSecondStatInfo20.rbegin()->second.dif_val > 100) continue; //最后值需要稳定
  1045. lock_guard<mutex> lock(pDevice->m_mtx);
  1046. swap(pDevice->m_mapSecondStatInfo20, map0);
  1047. swap(pDevice->m_mapSecondStatInfo21, map1);
  1048. swap(pDevice->m_mapSecondStatInfo22, map2);
  1049. }
  1050. list<CONVERT_RESIST> lstResit2;
  1051. std::map<time_t, int64_t> maxlock0, maxlock1;
  1052. mg_per_session_data::GetMaxResistNew(map2, lstResit2, mo, mp);
  1053. if (lstResit2.size())
  1054. {
  1055. mg_per_session_data::GetMaxLockNew(map0, lstResit2, maxlock0);
  1056. mg_per_session_data::GetMaxLockNew(map1, lstResit2, maxlock1);
  1057. SPDLOG_INFO("[转换阻力][{}:{}] lock0:{} lock1:{}, resist2:{}",
  1058. mo, mp, maxlock0.size(), maxlock1.size(), lstResit2.size());
  1059. }
  1060. else
  1061. continue; //没有检查到转换阻力
  1062. string name1, name2, name3, out_name, in_name;
  1063. CMonitorObjectMng::Instance()->GetNameByMoMp(mo + "." + mp, name1, name2, name3, out_name, in_name);
  1064. for (auto& it : maxlock0)
  1065. {
  1066. if (name1.find("定位") != -1)
  1067. CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, (it.second >> 32), i,
  1068. (uint8_t)eDaoChaPosi::DCP_FIX, fmt::format("锁闭力:{}", (it.second >> 32)));
  1069. else
  1070. CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, (it.second >> 32), i,
  1071. (uint8_t)eDaoChaPosi::DCP_INVERT, fmt::format("锁闭力:{}", (it.second >> 32)));
  1072. }
  1073. for (auto& it : maxlock1)
  1074. {
  1075. if (name2.find("定位") != -1)
  1076. CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, (it.second >> 32), i,
  1077. (uint8_t)eDaoChaPosi::DCP_FIX, fmt::format("锁闭力:{}", (it.second >> 32)));
  1078. else
  1079. CResistAlarmMng::InsertToDBByMove(mo, mp, it.first, 0, 0, (int)it.second, (it.second >> 32), i,
  1080. (uint8_t)eDaoChaPosi::DCP_INVERT, fmt::format("锁闭力:{}", (it.second >> 32)));
  1081. }
  1082. for (auto& it : lstResit2)
  1083. {
  1084. if (it.bUpOrDown == 1)
  1085. {
  1086. if (in_name.find("定扳反") != -1)
  1087. CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.tmEnd, it.val, it.fluctuation_val, i,
  1088. (uint8_t)eDaoChaPosi::DCP_FIX2INVERT, fmt::format("{}:{}", in_name, it.fluctuation_val));
  1089. else
  1090. CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.tmEnd, it.val, it.fluctuation_val, i,
  1091. (uint8_t)eDaoChaPosi::DCP_INVERT2FIX, fmt::format("{}:{}", in_name, it.fluctuation_val));
  1092. }
  1093. else
  1094. {
  1095. if (out_name.find("定扳反") != -1)
  1096. CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.tmEnd, it.val, it.fluctuation_val, i,
  1097. (uint8_t)eDaoChaPosi::DCP_FIX2INVERT, fmt::format("{}:{}", out_name, it.fluctuation_val));
  1098. else
  1099. CResistAlarmMng::InsertToDBByMove(mo, mp, it.time, it.tmStart, it.tmEnd, it.val, it.fluctuation_val, i,
  1100. (uint8_t)eDaoChaPosi::DCP_INVERT2FIX, fmt::format("{}:{}", out_name, it.fluctuation_val));
  1101. }
  1102. }
  1103. }
  1104. }
  1105. } while (pService->m_bWork);
  1106. }
  1107. typedef struct tagMoMp
  1108. {
  1109. string mo;
  1110. string mp;
  1111. uint8_t no; //传感器的序号
  1112. tagMoMp(string a, string b)
  1113. {
  1114. mo = a;
  1115. mp = b;
  1116. }
  1117. tagMoMp(uint8_t a)
  1118. {
  1119. no = a;
  1120. }
  1121. };
  1122. typedef struct offline_info
  1123. {
  1124. string imei;
  1125. CTime time;
  1126. uint8_t idx = 0;
  1127. std::vector<tagMoMp> vct;
  1128. offline_info(string a, CTime b)
  1129. {
  1130. imei = a;
  1131. time = b;
  1132. }
  1133. offline_info(string a, CTime b, uint8_t c, uint8_t d)
  1134. {
  1135. imei = a;
  1136. time = b;
  1137. idx = c;
  1138. vct.push_back(tagMoMp(d));
  1139. }
  1140. };
  1141. void CResistAlarmMng::ThreadProcDevice(DWORD_PTR param)
  1142. {
  1143. auto pService = (CResistAlarmMng*)param;
  1144. this_thread::sleep_for(chrono::seconds(2));
  1145. static CTimeSpan offline_time(0, 0, 3, 0); //设备离线时间暂定5分钟
  1146. static CTimeSpan offline_limit(30, 0, 0, 0);
  1147. do
  1148. {
  1149. for (int i = 0; i < 30; i++)
  1150. {
  1151. if (false == pService->m_bWork) break;
  1152. this_thread::sleep_for(chrono::seconds(1));
  1153. }
  1154. CTime ctNow = CTime::GetCurrentTime();
  1155. //传感器异常检测
  1156. {
  1157. std::vector<offline_info> vct;
  1158. {
  1159. lock_guard<mutex> lock(CDeviceMng::Instance()->m_mtx);
  1160. const auto& pDevices = CDeviceMng::Instance()->m_map_devices;
  1161. for (const auto& it : pDevices)
  1162. {
  1163. {
  1164. const auto& item = it.second->map_resist_idx00;
  1165. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1166. {
  1167. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 0, 0));
  1168. }
  1169. }
  1170. {
  1171. const auto& item = it.second->map_resist_idx01;
  1172. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1173. {
  1174. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 0, 1));
  1175. }
  1176. }
  1177. {
  1178. const auto& item = it.second->map_resist_idx02;
  1179. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1180. {
  1181. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 0, 2));
  1182. }
  1183. }
  1184. {
  1185. const auto& item = it.second->map_resist_idx10;
  1186. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1187. {
  1188. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 1, 0));
  1189. }
  1190. }
  1191. {
  1192. const auto& item = it.second->map_resist_idx11;
  1193. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1194. {
  1195. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 1, 1));
  1196. }
  1197. }
  1198. {
  1199. const auto& item = it.second->map_resist_idx12;
  1200. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1201. {
  1202. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 1, 2));
  1203. }
  1204. }
  1205. {
  1206. const auto& item = it.second->map_resist_idx20;
  1207. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1208. {
  1209. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 2, 0));
  1210. }
  1211. }
  1212. {
  1213. const auto& item = it.second->map_resist_idx21;
  1214. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1215. {
  1216. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 2, 1));
  1217. }
  1218. }
  1219. {
  1220. const auto& item = it.second->map_resist_idx22;
  1221. if (item.size() && item.rbegin()->second == INVALID_RESIST)
  1222. {
  1223. vct.push_back(offline_info(it.first, (item.rbegin()->first / 1000), 2, 2));
  1224. }
  1225. }
  1226. }
  1227. }
  1228. //转换成momp
  1229. for (auto it = vct.begin(); it != vct.end();)
  1230. {
  1231. string mo, mp;
  1232. //if (CMonitorObjectMng::Instance()->IMEI2MOMP(it->imei, it->idx, mo, mp) && it->vct.size() >= 1) //TODO
  1233. {
  1234. it->vct[0].mo = mo;
  1235. it->vct[0].mp = mp;
  1236. it++;
  1237. }
  1238. //else
  1239. {
  1240. it = vct.erase(it);
  1241. //CString strLog;
  1242. //strLog.Format("imei(%s)(%d) 转换成 mo, mp 失败.请检查是否绑定.size;(%d) %s:%d", it.imei.c_str(), it.idx, (int)it.vct.size(), __FUNCTION__, __LINE__);
  1243. //CSimpleLog::Warn(strLog);
  1244. }
  1245. }
  1246. CTime ctAlarmTime = ctNow;
  1247. for (const auto& it : vct)
  1248. {
  1249. for (const auto& it_mo_mp : it.vct)
  1250. {
  1251. ALARM_INFO* pAlarmInfo = nullptr;
  1252. bool bNew = false;
  1253. {
  1254. std::lock_guard<mutex> lock(pService->m_mtxAlarm);
  1255. for (const auto& alarm : pService->m_lstUnConfirmAlarm)
  1256. {
  1257. if (alarm->type == eZL_ALARMTYPE::SENSOR_ABNORMAL && alarm->mo.compare(it_mo_mp.mo) == 0 && alarm->mp.compare(it_mo_mp.mp) == 0 && it_mo_mp.no == alarm->no/* && ctAlarmTime - CTime(alarm->time) < cts*/) //跟上次报警时间超过1小时,则算新报警
  1258. {
  1259. pAlarmInfo = alarm;
  1260. break;
  1261. }
  1262. }
  1263. }
  1264. if (pAlarmInfo == nullptr)
  1265. {
  1266. bNew = true;
  1267. pAlarmInfo = new ALARM_INFO;
  1268. pAlarmInfo->id = ++pService->m_nAlarmID;
  1269. pAlarmInfo->level = 1;
  1270. pAlarmInfo->mo = it_mo_mp.mo;
  1271. pAlarmInfo->mp = it_mo_mp.mp;
  1272. pAlarmInfo->no = it_mo_mp.no;
  1273. ctAlarmTime.GetAsSystemTime(pAlarmInfo->time);
  1274. //pAlarmInfo->time.wMilliseconds = alarm_time % 1000;
  1275. pAlarmInfo->type = eZL_ALARMTYPE::SENSOR_ABNORMAL;
  1276. pAlarmInfo->val = 0;
  1277. char szInfo[200];
  1278. sprintf_s(szInfo, sizeof(szInfo), "传感器异常时间:%s", (LPCSTR)(it.time.Format("%Y-%m-%d %H:%M:%S")));
  1279. pAlarmInfo->desc = szInfo;
  1280. lock_guard<mutex> lock(pService->m_mtxAlarm);
  1281. pService->m_lstUnConfirmAlarm.push_back(pAlarmInfo);
  1282. }
  1283. //send
  1284. if (bNew) //不再推送
  1285. {
  1286. rapidjson::StringBuffer buffer;
  1287. auto ret = AlarmInfo2Pack(pAlarmInfo, buffer);
  1288. const char* output = buffer.GetString();
  1289. //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength());
  1290. CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength());
  1291. }
  1292. //save
  1293. if (bNew)
  1294. {
  1295. CString sql;
  1296. sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val]) "\
  1297. "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d);",
  1298. pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, (int)pAlarmInfo->type,
  1299. (LPCSTR)(ctAlarmTime.Format("%Y-%m-%d %H:%M:%S")), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val);
  1300. if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql))
  1301. {
  1302. CSimpleLog::Error("执行语句失败" + sql);
  1303. }
  1304. }
  1305. }
  1306. }
  1307. }
  1308. {
  1309. //离线设备
  1310. std::vector<offline_info> vct;
  1311. {
  1312. lock_guard<mutex> lock(CDeviceMng::Instance()->m_mtx);
  1313. const auto& pDevices = CDeviceMng::Instance()->m_map_devices;
  1314. for (const auto& it : pDevices)
  1315. if (it.second->m_ctUpdateTime != 0 && ctNow - it.second->m_ctUpdateTime > offline_time && ctNow - it.second->m_ctUpdateTime < offline_limit)
  1316. {
  1317. vct.push_back(offline_info(it.first, it.second->m_ctUpdateTime));
  1318. }
  1319. }
  1320. for (auto& it : vct)
  1321. {
  1322. for (int i = 0; i < 3; i++)
  1323. {
  1324. string mo, mp;
  1325. //if (CMonitorObjectMng::Instance()->IMEI2MOMP(it.imei, i, mo, mp)) //TODO
  1326. {
  1327. it.vct.push_back(tagMoMp(mo, mp));
  1328. }
  1329. //else
  1330. {
  1331. //CString strLog;
  1332. //strLog.Format("imei(%s)(%d) 转换成 mo, mp 失败.请检查是否绑定. size;(%d) %s:%d", it.imei.c_str(), i, (int)it.vct.size(), __FUNCTION__, __LINE__);
  1333. //CSimpleLog::Warn(strLog);
  1334. }
  1335. }
  1336. }
  1337. CTime ctAlarmTime = ctNow;
  1338. for (const auto& it : vct)
  1339. {
  1340. for (const auto& it_mo_mp : it.vct)
  1341. {
  1342. ALARM_INFO* pAlarmInfo = nullptr;
  1343. bool bNew = false;
  1344. {
  1345. std::lock_guard<mutex> lock(pService->m_mtxAlarm);
  1346. for (const auto& alarm : pService->m_lstUnConfirmAlarm)
  1347. {
  1348. static CTimeSpan cts(0, 6, 0, 0); //报警间隔6小时重新生成报警
  1349. if (alarm->type == eZL_ALARMTYPE::EQUIP_OFFLINE && alarm->mo.compare(it_mo_mp.mo) == 0 && alarm->mp.compare(it_mo_mp.mp) == 0/* && ctAlarmTime - CTime(alarm->time) < cts*/) //跟上次报警时间超过1小时,则算新报警
  1350. {
  1351. pAlarmInfo = alarm;
  1352. break;
  1353. }
  1354. }
  1355. }
  1356. if (pAlarmInfo == nullptr)
  1357. {
  1358. bNew = true;
  1359. pAlarmInfo = new ALARM_INFO;
  1360. pAlarmInfo->id = ++pService->m_nAlarmID;
  1361. pAlarmInfo->level = 1;
  1362. pAlarmInfo->mo = it_mo_mp.mo;
  1363. pAlarmInfo->mp = it_mo_mp.mp;
  1364. pAlarmInfo->no = -1;
  1365. ctAlarmTime.GetAsSystemTime(pAlarmInfo->time);
  1366. //pAlarmInfo->time.wMilliseconds = alarm_time % 1000;
  1367. pAlarmInfo->type = eZL_ALARMTYPE::EQUIP_OFFLINE;
  1368. pAlarmInfo->val = 0;
  1369. char szInfo[200];
  1370. sprintf_s(szInfo, sizeof(szInfo), "设备离线时间:%s", (LPCSTR)(it.time.Format("%Y-%m-%d %H:%M:%S")));
  1371. pAlarmInfo->desc = szInfo;
  1372. lock_guard<mutex> lock(pService->m_mtxAlarm);
  1373. pService->m_lstUnConfirmAlarm.push_back(pAlarmInfo);
  1374. }
  1375. //send
  1376. if (bNew) //不再推送
  1377. {
  1378. rapidjson::StringBuffer buffer;
  1379. auto ret = AlarmInfo2Pack(pAlarmInfo, buffer);
  1380. const char* output = buffer.GetString();
  1381. //CAppService::Instance()->GetLwsServer()->SendPackToALLClient_with_noEncode((uint8_t*)output, buffer.GetLength());
  1382. CAppService::Instance()->GetMgServer()->SendToAllClient(output, buffer.GetLength());
  1383. }
  1384. //save
  1385. if (bNew)
  1386. {
  1387. CString sql;
  1388. sql.Format("INSERT INTO [rm_alarm]([ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val]) "\
  1389. "VALUES(%d, '%s', '%s', %d, %d, '%s', %d, '%s', '%s', %d);",
  1390. pAlarmInfo->id, pAlarmInfo->mo.c_str(), pAlarmInfo->mp.c_str(), pAlarmInfo->no, pAlarmInfo->type,
  1391. (LPCSTR)(ctAlarmTime.Format("%Y-%m-%d %H:%M:%S")), pAlarmInfo->level, pAlarmInfo->desc.c_str(), pAlarmInfo->suggest.c_str(), pAlarmInfo->val);
  1392. if (false == CDBConnectPool::Instance()->DBExecuteSQL(sql))
  1393. {
  1394. CSimpleLog::Error("执行语句失败" + sql);
  1395. }
  1396. }
  1397. }
  1398. }
  1399. }
  1400. } while (pService->m_bWork);
  1401. }
  1402. BOOL CResistAlarmMng::LoadAlarmSet()
  1403. {
  1404. CString sql = "SELECT [mo],[mp],[no],[type],[conf],[time] FROM [rm_alarm_set]";
  1405. COdbcStatement stmt;
  1406. if (!CDBConnectPool::Instance()->DBQuery(stmt, sql))
  1407. {
  1408. CSimpleLog::Error("执行语句失败" + sql);
  1409. return FALSE;
  1410. }
  1411. for (auto& it : m_alarm_set)
  1412. {
  1413. delete it.second;
  1414. it.second = nullptr;
  1415. }
  1416. m_alarm_set.clear();
  1417. char mo[51], mp[51], conf[501];
  1418. uint8_t no, type;
  1419. __time64_t time;
  1420. int nCol = 1;
  1421. stmt.BindCharCol(nCol++, mo, sizeof(mo));
  1422. stmt.BindCharCol(nCol++, mp, sizeof(mp));
  1423. stmt.BindTinyIntCol(nCol++, &no);
  1424. stmt.BindTinyIntCol(nCol++, &type);
  1425. stmt.BindCharCol(nCol++, conf, sizeof(conf));
  1426. stmt.BindBigIntCol(nCol++, &time);
  1427. do
  1428. {
  1429. if (stmt.FetchNext() != 0) break;
  1430. using namespace rapidjson;
  1431. int len = strlen(conf);
  1432. if (len == 0) continue;
  1433. Document doc;
  1434. if (doc.Parse(conf, len).HasParseError())
  1435. {
  1436. CSimpleLog::Error(CString("解析数据出错") + conf);
  1437. continue;
  1438. }
  1439. const auto eType = (eZL_ALARMTYPE)type;
  1440. if (eType == eZL_ALARMTYPE::MAX_OVER_LIMIT)
  1441. {
  1442. if (doc.IsArray() == false)
  1443. {
  1444. CSimpleLog::Error(CString("conf是非数组") + conf);
  1445. continue;
  1446. }
  1447. SizeType n = doc.Size();
  1448. bool enable = false;
  1449. short alarm_high_limit = MAXSHORT;
  1450. short warn_high_limit = MAXSHORT;
  1451. short f_alarm_high_limit = MAXSHORT;
  1452. short f_warn_high_limit = MAXSHORT;
  1453. for (SizeType i = 0; i < n; i++)
  1454. {
  1455. if (doc[i].HasMember("name") == false || doc[i].HasMember("val") == false || doc[i]["name"].IsString() == false || doc[i]["val"].IsString() == false)
  1456. {
  1457. assert(false);
  1458. continue;
  1459. }
  1460. string key = doc[i]["name"].GetString();
  1461. string value = doc[i]["val"].GetString();
  1462. if (key.compare("enable") == 0)
  1463. {
  1464. enable = (value.compare("true") == 0);
  1465. }
  1466. else if (key.compare("lock_alarm_high_limit") == 0)
  1467. {
  1468. alarm_high_limit = atoi(value.c_str());
  1469. }
  1470. else if (key.compare("lock_warn_high_limit") == 0)
  1471. {
  1472. warn_high_limit = atoi(value.c_str());
  1473. }
  1474. else if (key.compare("d_alarm_high_limit") == 0)
  1475. {
  1476. alarm_high_limit = atoi(value.c_str());
  1477. }
  1478. else if (key.compare("d_warn_high_limit") == 0)
  1479. {
  1480. warn_high_limit = atoi(value.c_str());
  1481. }
  1482. else if (key.compare("f_alarm_high_limit") == 0)
  1483. {
  1484. f_alarm_high_limit = atoi(value.c_str());
  1485. }
  1486. else if (key.compare("f_warn_high_limit") == 0)
  1487. {
  1488. f_warn_high_limit = atoi(value.c_str());
  1489. }
  1490. else if (key.compare("keep_alarm_high_limit") == 0)
  1491. {
  1492. f_alarm_high_limit = atoi(value.c_str());
  1493. }
  1494. else if (key.compare("keep_warn_high_limit") == 0)
  1495. {
  1496. f_warn_high_limit = atoi(value.c_str());
  1497. }
  1498. else
  1499. {
  1500. assert(0);
  1501. }
  1502. }
  1503. if (alarm_high_limit == MAXSHORT || warn_high_limit == MAXSHORT) continue;
  1504. auto pInfo = new MAX_OVER_LIMIT_INFO;
  1505. pInfo->enable = enable;
  1506. pInfo->no = no;
  1507. pInfo->type = eType;
  1508. pInfo->alarm_high_limit = alarm_high_limit;
  1509. pInfo->warn_high_limit = warn_high_limit;
  1510. pInfo->f_alarm_high_limit = f_alarm_high_limit;
  1511. pInfo->f_warn_high_limit = f_warn_high_limit;
  1512. pInfo->tmLastCheckTime = time;
  1513. stringstream ss;
  1514. ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type);
  1515. m_alarm_set[ss.str()] = pInfo;
  1516. }
  1517. else if (eType == eZL_ALARMTYPE::FRICTION_OVER_LIMIT)
  1518. {
  1519. if (doc.IsArray() == false)
  1520. {
  1521. CSimpleLog::Error(CString("conf是非数组") + conf);
  1522. continue;
  1523. }
  1524. SizeType n = doc.Size();
  1525. bool enable = false;
  1526. int up_alarm_low_limit = INT_MAX;
  1527. int up_warn_low_limit = INT_MAX;
  1528. int dw_alarm_high_limit = INT_MIN;
  1529. int dw_warn_high_limit = INT_MIN;
  1530. for (SizeType i = 0; i < n; i++)
  1531. {
  1532. if (doc[i].HasMember("name") == false || doc[i].HasMember("val") == false || doc[i]["name"].IsString() == false || doc[i]["val"].IsString() == false)
  1533. {
  1534. assert(false);
  1535. continue;
  1536. }
  1537. string key = doc[i]["name"].GetString();
  1538. string value = doc[i]["val"].GetString();
  1539. if (key.compare("enable") == 0)
  1540. {
  1541. enable = (value.compare("true") == 0);
  1542. }
  1543. else if (key.compare("up_alarm_low_limit") == 0)
  1544. {
  1545. up_alarm_low_limit = atoi(value.c_str());
  1546. }
  1547. else if (key.compare("up_warn_low_limit") == 0)
  1548. {
  1549. up_warn_low_limit = atoi(value.c_str());
  1550. }
  1551. else if (key.compare("dw_alarm_high_limit") == 0)
  1552. {
  1553. dw_alarm_high_limit = atoi(value.c_str());
  1554. }
  1555. else if (key.compare("dw_warn_high_limit") == 0)
  1556. {
  1557. dw_warn_high_limit = atoi(value.c_str());
  1558. }
  1559. else
  1560. {
  1561. assert(0);
  1562. }
  1563. }
  1564. auto pInfo = new FRICTION_OVER_LIMIT_INFO;
  1565. pInfo->enable = enable;
  1566. pInfo->no = no;
  1567. pInfo->type = eType;
  1568. pInfo->up_alarm_low_limit = up_alarm_low_limit;
  1569. pInfo->up_warn_low_limit = up_warn_low_limit;
  1570. pInfo->dw_alarm_high_limit = dw_alarm_high_limit;
  1571. pInfo->dw_warn_high_limit = dw_warn_high_limit;
  1572. pInfo->tmLastCheckTime = time;
  1573. stringstream ss;
  1574. ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type);
  1575. m_alarm_set[ss.str()] = pInfo;
  1576. }
  1577. else if (eType == eZL_ALARMTYPE::SUOBI_LOCK_LIMIT)
  1578. {
  1579. auto doc = yyjson_read(conf, len, 0);
  1580. if (doc == nullptr) continue;
  1581. auto root = yyjson_doc_get_root(doc);
  1582. auto pInfo = new SUOBI_OVER_LIMIT_INFO;
  1583. pInfo->type = eZL_ALARMTYPE::SUOBI_LOCK_LIMIT;
  1584. pInfo->enable = yyjson_get_bool(yyjson_obj_get(root, "enable"));
  1585. pInfo->alarm_low_limit = yyjson_get_int(yyjson_obj_get(root, "alarm_low_limit"));
  1586. pInfo->warn_low_limit = yyjson_get_int(yyjson_obj_get(root, "warn_low_limit"));
  1587. pInfo->alarm_high_limit = yyjson_get_int(yyjson_obj_get(root, "alarm_high_limit"));
  1588. pInfo->warn_high_limit = yyjson_get_int(yyjson_obj_get(root, "warn_high_limit"));
  1589. stringstream ss;
  1590. ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type);
  1591. m_alarm_set[ss.str()] = pInfo;
  1592. yyjson_doc_free(doc);
  1593. }
  1594. else if (eType == eZL_ALARMTYPE::CONVERT_LIMIT)
  1595. {
  1596. auto doc = yyjson_read(conf, len, 0);
  1597. if (doc == nullptr) continue;
  1598. auto root = yyjson_doc_get_root(doc);
  1599. auto pInfo = new CONVERT_RESIST_OVER_LIMIT;
  1600. pInfo->type = eZL_ALARMTYPE::CONVERT_LIMIT;
  1601. pInfo->no = 2;
  1602. pInfo->enable = yyjson_get_bool(yyjson_obj_get(root, "enable"));
  1603. pInfo->dw_alarm_low_limit = yyjson_get_int(yyjson_obj_get(root, "dw_alarm_low_limit"));
  1604. pInfo->dw_warn_low_limit = yyjson_get_int(yyjson_obj_get(root, "dw_warn_low_limit"));
  1605. pInfo->up_alarm_high_limit = yyjson_get_int(yyjson_obj_get(root, "up_alarm_high_limit"));
  1606. pInfo->up_warn_high_limit = yyjson_get_int(yyjson_obj_get(root, "up_warn_high_limit"));
  1607. stringstream ss;
  1608. ss << mo << '.' << mp << '.' << to_string(no) << '.' << to_string(type);
  1609. m_alarm_set[ss.str()] = pInfo;
  1610. }
  1611. else
  1612. {
  1613. ASSERT(0);
  1614. }
  1615. } while (true);
  1616. SPDLOG_INFO("一共加载到{}条报警规则:{}", m_alarm_set.size(), sql);
  1617. return TRUE;
  1618. }
  1619. BOOL CResistAlarmMng::LoadAlarmID()
  1620. {
  1621. CString sql = "SELECT TOP 1 ID FROM RM_ALARM ORDER BY ID DESC";
  1622. COdbcStatement stmt;
  1623. if (!CDBConnectPool::Instance()->DBQuery(stmt, sql))
  1624. {
  1625. CSimpleLog::Error("执行语句失败" + sql);
  1626. return FALSE;
  1627. }
  1628. int alarm_id;
  1629. int nCol = 1;
  1630. stmt.BindIntCol(nCol++, &alarm_id);
  1631. do
  1632. {
  1633. if (stmt.FetchNext() != 0) break;
  1634. m_nAlarmID = alarm_id;
  1635. } while (false);
  1636. stmt.Close();
  1637. return TRUE;
  1638. }
  1639. BOOL CResistAlarmMng::LoadUnAck()
  1640. {
  1641. CString sql = "SELECT [ID],[mo],[mp],[no],[type],[occur_time],[level],[desc],[suggest],[val],[event_id],[rel_id] FROM [rm_alarm] WHERE ack_result = 0 ORDER BY ID;";
  1642. COdbcStatement stmt;
  1643. if (!CDBConnectPool::Instance()->DBQuery(stmt, sql))
  1644. {
  1645. SPDLOG_ERROR("执行语句失败 {}", sql);
  1646. return FALSE;
  1647. }
  1648. char mo[51], mp[51], desc[200], suggest[200], event_id[37] = { 0 }, rel_id[37] = { 0 };;
  1649. uint8_t no, type, level;
  1650. short val;
  1651. int id;
  1652. TIMESTAMP_STRUCT ts;
  1653. int nCol = 1;
  1654. stmt.BindIntCol(nCol++, &id);
  1655. stmt.BindCharCol(nCol++, mo, sizeof(mo));
  1656. stmt.BindCharCol(nCol++, mp, sizeof(mp));
  1657. stmt.BindTinyIntCol(nCol++, &no);
  1658. stmt.BindTinyIntCol(nCol++, &type);
  1659. stmt.BindTimeStampCol(nCol++, &ts);
  1660. stmt.BindTinyIntCol(nCol++, &level);
  1661. stmt.BindCharCol(nCol++, desc, sizeof(desc));
  1662. stmt.BindCharCol(nCol++, suggest, sizeof(suggest));
  1663. stmt.BindSmallIntCol(nCol++, &val);
  1664. stmt.BindCharCol(nCol++, event_id, 36);
  1665. stmt.BindCharCol(nCol++, rel_id, 36);
  1666. do
  1667. {
  1668. if (stmt.FetchNext() != 0) break;
  1669. ALARM_INFO *pAlarm = new ALARM_INFO;
  1670. pAlarm->event_id = event_id;
  1671. if (rel_id[0] != 0x20)
  1672. pAlarm->rel_id = rel_id;
  1673. pAlarm->id = id;
  1674. pAlarm->mo = mo;
  1675. pAlarm->mp = mp;
  1676. pAlarm->no = no;
  1677. pAlarm->type = (eZL_ALARMTYPE)type;
  1678. pAlarm->time.wYear = ts.year;
  1679. pAlarm->time.wMonth = ts.month;
  1680. pAlarm->time.wDay = ts.day;
  1681. pAlarm->time.wHour = ts.hour;
  1682. pAlarm->time.wMinute = ts.minute;
  1683. pAlarm->time.wSecond = ts.second;
  1684. pAlarm->time.wMilliseconds = ts.fraction;
  1685. pAlarm->val = val;
  1686. pAlarm->level = level;
  1687. pAlarm->desc = desc;
  1688. pAlarm->suggest = suggest;
  1689. m_lstUnConfirmAlarm.push_back(pAlarm);
  1690. } while (true);
  1691. stmt.Close();
  1692. SPDLOG_INFO("一共加载({})条未处理报警", m_lstUnConfirmAlarm.size());
  1693. return TRUE;
  1694. }