ups_monitor.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /********************************* (C) РОТЕК ***********************************
  2. * @module ups_monitor
  3. * @file ups_monitor.c
  4. * @version 1.0.0
  5. * @date XX.XX.XXXX
  6. * $brief Template
  7. *******************************************************************************
  8. * @history Version Author Comment
  9. * XX.XX.XXXX 1.0.0 Telenkov D.A. First release.
  10. *******************************************************************************
  11. */
  12. #include "stm32f4xx.h"
  13. #include "ups_monitor.h"
  14. #include "parameters.h"
  15. #include "settings_api.h"
  16. #include "megatec.h"
  17. #include "led.h"
  18. #include "log.h"
  19. #include "FreeRTOS.h"
  20. #include "task.h"
  21. #include "trap_api.h"
  22. #include "snmp_api.h"
  23. #include <stdbool.h>
  24. #define UPS_LOAD 70.0 // Нагрука (граница)
  25. #define UPS_LOAD_HIST 1.0 // Гистерезис нагрузки
  26. #define UPS_TEMPERATURE 40.0 // Температура (граница)
  27. #define UPS_TEMPERATURE_HIST 1.0 // Гистерезис температуры
  28. bool flCriticalAlarm = false;
  29. bool flNonCriticalAlarm = false;
  30. /**
  31. * @brief Общая структура настроек
  32. */
  33. extern SETTINGS_t sSettings;
  34. extern bool flUpdateLog;
  35. /**
  36. * @brief Задача мониторинга параметров UPS
  37. */
  38. void UPS_Monitor(void *params)
  39. {
  40. vTaskDelay(5000);
  41. for (;;)
  42. {
  43. flCriticalAlarm = false;
  44. flNonCriticalAlarm = false;
  45. // Проверяем флаг подключения UPS
  46. if (UPS.Present)
  47. {
  48. UPS_LineFailMonitor();
  49. UPS_LowBatMonitor();
  50. UPS_PowerMonitor();
  51. UPS_TemperatureMonitor();
  52. UPS_BatteryConnectMonitor();
  53. }
  54. UPS_ConnectMonitor();
  55. UPS_DI0Monitor();
  56. UPS_CriticalAlarmMonitor();
  57. UPS_NonCriticalAlarmMonitor();
  58. vTaskDelay(1000);
  59. }
  60. }
  61. /**
  62. * @brief Мониторинг бита DI0 state
  63. */
  64. void UPS_DI0Monitor(void)
  65. {
  66. static bool isValueRecv = false;
  67. static uint8_t DI0OldState = 0;
  68. uint8_t DI0StateCurrent;
  69. DI0StateCurrent = get_state_din_outs(DIN1) ^ sSettings.sInOuts.din_type_act[0];
  70. UPS.Alarm = (UPS.Alarm & 0x0f) | (DI0StateCurrent << 4);
  71. if (!isValueRecv) {
  72. isValueRecv = true;
  73. DI0OldState = DI0StateCurrent;
  74. if (DI0StateCurrent){
  75. log_event_data(LOG_ALARM_DIO, "Авария");
  76. SNMP_SendUserTrap(DI0_ALARM);
  77. flUpdateLog = true;
  78. }
  79. return;
  80. }
  81. if (DI0StateCurrent)
  82. flCriticalAlarm = true;
  83. // Значение параметра изменилось
  84. if (DI0StateCurrent != DI0OldState)
  85. {
  86. if (!DI0StateCurrent){
  87. log_event_data(LOG_ALARM_DIO, "Норма");
  88. SNMP_SendUserTrap(DI0_NORM);
  89. flUpdateLog = true;
  90. }
  91. else{
  92. log_event_data(LOG_ALARM_DIO, "Авария");
  93. SNMP_SendUserTrap(DI0_ALARM);
  94. flUpdateLog = true;
  95. }
  96. }
  97. DI0OldState = DI0StateCurrent;
  98. }
  99. /**
  100. * @brief Мониторинг бита CriticalAlarm
  101. */
  102. void UPS_CriticalAlarmMonitor(void)
  103. {
  104. static bool isValueRecv = false;
  105. static uint8_t CriticalAlarmOldState = 0;
  106. uint8_t CriticalAlarmCurrent;
  107. static uint8_t OldRO0type_Sourse = 0;
  108. static uint8_t OldRO2type_Sourse = 0;
  109. uint8_t CurrRO2type_Sourse = 0;
  110. uint8_t CurrRO1type_Sourse = 0;
  111. char str[30];
  112. memset(str, 0, 30);
  113. CurrRO1type_Sourse = sSettings.sInOuts.ro_type_source[0];
  114. CurrRO2type_Sourse = sSettings.sInOuts.ro_type_source[1];
  115. CriticalAlarmCurrent = flCriticalAlarm;
  116. if (!isValueRecv) {
  117. isValueRecv = true;
  118. CriticalAlarmOldState = CriticalAlarmCurrent;
  119. OldRO0type_Sourse = CurrRO1type_Sourse;
  120. OldRO2type_Sourse = CurrRO2type_Sourse;
  121. if(OldRO0type_Sourse == CRITICAL){
  122. if(CriticalAlarmCurrent){
  123. SetROInt(1, 0);
  124. SNMP_SendUserTrap(DO0_TOGGLED);
  125. log_event_data(LOG_DO0_STATE, "Замкнуто");
  126. }
  127. }
  128. if(OldRO2type_Sourse == CRITICAL){
  129. if(CriticalAlarmCurrent){
  130. SetROInt(1, 1);
  131. SNMP_SendUserTrap(DO1_TOGGLED);
  132. log_event_data(LOG_DO1_STATE, "Замкнуто");
  133. }
  134. }
  135. return;
  136. }
  137. if(CriticalAlarmCurrent){
  138. if (UPS.Present)
  139. LED_Toggle(LED_MAJOR_R);
  140. else
  141. LED_On(LED_MAJOR_R);
  142. }
  143. else{
  144. LED_Off(LED_MAJOR_R);
  145. }
  146. // Значение параметра изменилось
  147. if (CriticalAlarmCurrent != CriticalAlarmOldState)
  148. {
  149. if(OldRO0type_Sourse == CRITICAL){
  150. memset(str, 0, 30);
  151. if(CriticalAlarmCurrent){
  152. SetROInt(1, 0);
  153. strcat(str, "Замкнуто");
  154. }
  155. else{
  156. SetROInt(0, 0);
  157. strcat(str, "Разомкнуто");
  158. }
  159. SNMP_SendUserTrap(DO0_TOGGLED);
  160. log_event_data(LOG_DO0_STATE, str);
  161. }
  162. if(OldRO2type_Sourse == CRITICAL){
  163. memset(str, 0, 30);
  164. if(CriticalAlarmCurrent){
  165. SetROInt(1, 1);
  166. strcat(str, "Замкнуто");
  167. }
  168. else{
  169. SetROInt(0, 1);
  170. strcat(str, "Разомкнуто");
  171. }
  172. SNMP_SendUserTrap(DO1_TOGGLED);
  173. log_event_data(LOG_DO1_STATE, str);
  174. }
  175. }
  176. else
  177. {
  178. if(OldRO0type_Sourse == CRITICAL && OldRO0type_Sourse != OldRO0type_Sourse){
  179. memset(str, 0, 30);
  180. if(CriticalAlarmCurrent){
  181. SetROInt(1, 0);
  182. strcat(str, "Замкнуто");
  183. }
  184. else{
  185. SetROInt(0, 0);
  186. strcat(str, "Разомкнуто");
  187. }
  188. SNMP_SendUserTrap(DO0_TOGGLED);
  189. log_event_data(LOG_DO0_STATE, str);
  190. }
  191. if(OldRO2type_Sourse == CRITICAL && OldRO2type_Sourse != OldRO2type_Sourse){
  192. memset(str, 0, 30);
  193. if(CriticalAlarmCurrent){
  194. SetROInt(1, 1);
  195. strcat(str, "Замкнуто");
  196. }
  197. else{
  198. SetROInt(0, 1);
  199. strcat(str, "Разомкнуто");
  200. }
  201. SNMP_SendUserTrap(DO1_TOGGLED);
  202. log_event_data(LOG_DO1_STATE, str);
  203. }
  204. }
  205. OldRO0type_Sourse = CurrRO1type_Sourse;
  206. OldRO2type_Sourse = CurrRO2type_Sourse;
  207. CriticalAlarmOldState = CriticalAlarmCurrent;
  208. }
  209. /**
  210. * @brief Мониторинг бита NonCriticalAlarm
  211. */
  212. void UPS_NonCriticalAlarmMonitor(void)
  213. {
  214. static bool isValueRecv = false;
  215. static uint8_t NonCriticalAlarmOldState = 0;
  216. uint8_t NonCriticalAlarmCurrent;
  217. static uint8_t OldRO0type_Sourse = 0;
  218. static uint8_t OldRO2type_Sourse = 0;
  219. uint8_t CurrRO2type_Sourse = 0;
  220. uint8_t CurrRO1type_Sourse = 0;
  221. char str[30];
  222. memset(str, 0, 30);
  223. CurrRO1type_Sourse = sSettings.sInOuts.ro_type_source[0];
  224. CurrRO2type_Sourse = sSettings.sInOuts.ro_type_source[1];
  225. NonCriticalAlarmCurrent = flNonCriticalAlarm;
  226. if (!isValueRecv) {
  227. isValueRecv = true;
  228. NonCriticalAlarmOldState = NonCriticalAlarmCurrent;
  229. OldRO0type_Sourse = CurrRO1type_Sourse;
  230. OldRO2type_Sourse = CurrRO2type_Sourse;
  231. if(OldRO0type_Sourse == NON_CRITICAL){
  232. if(NonCriticalAlarmCurrent){
  233. SetROInt(1, 0);
  234. SNMP_SendUserTrap(DO0_TOGGLED);
  235. log_event_data(LOG_DO0_STATE, "Замкнуто");
  236. }
  237. }
  238. if(OldRO2type_Sourse == NON_CRITICAL){
  239. if(NonCriticalAlarmCurrent){
  240. SetROInt(1, 1);
  241. SNMP_SendUserTrap(DO1_TOGGLED);
  242. log_event_data(LOG_DO1_STATE, "Замкнуто");
  243. }
  244. }
  245. return;
  246. }
  247. // Значение параметра изменилось
  248. if (NonCriticalAlarmCurrent != NonCriticalAlarmOldState)
  249. {
  250. if(OldRO0type_Sourse == NON_CRITICAL){
  251. memset(str, 0, 30);
  252. if(NonCriticalAlarmCurrent){
  253. SetROInt(1, 0);
  254. strcat(str, "Замкнуто");
  255. }
  256. else{
  257. SetROInt(0, 0);
  258. strcat(str, "Разомкнуто");
  259. }
  260. SNMP_SendUserTrap(DO0_TOGGLED);
  261. log_event_data(LOG_DO0_STATE, str);
  262. }
  263. if(OldRO2type_Sourse == NON_CRITICAL){
  264. memset(str, 0, 30);
  265. if(NonCriticalAlarmCurrent){
  266. SetROInt(1, 1);
  267. strcat(str, "Разомкнуто");
  268. }
  269. else{
  270. SetROInt(0, 1);
  271. strcat(str, "Замкнуто");
  272. }
  273. SNMP_SendUserTrap(DO1_TOGGLED);
  274. log_event_data(LOG_DO1_STATE, str);
  275. }
  276. }
  277. else
  278. {
  279. if(OldRO0type_Sourse == NON_CRITICAL && OldRO0type_Sourse != OldRO0type_Sourse){
  280. memset(str, 0, 30);
  281. if(NonCriticalAlarmCurrent){
  282. SetROInt(1, 0);
  283. strcat(str, "Замкнуто");
  284. }
  285. else{
  286. SetROInt(0, 0);
  287. strcat(str, "Разомкнуто");
  288. }
  289. SNMP_SendUserTrap(DO0_TOGGLED);
  290. log_event_data(LOG_DO0_STATE, str);
  291. }
  292. if(OldRO2type_Sourse == NON_CRITICAL && OldRO2type_Sourse != OldRO2type_Sourse){
  293. memset(str, 0, 30);
  294. if(NonCriticalAlarmCurrent){
  295. SetROInt(1, 1);
  296. strcat(str, "Замкнуто");
  297. }
  298. else{
  299. SetROInt(0, 1);
  300. strcat(str, "Разомкнуто");
  301. }
  302. SNMP_SendUserTrap(DO1_TOGGLED);
  303. log_event_data(LOG_DO1_STATE, str);
  304. }
  305. }
  306. OldRO0type_Sourse = CurrRO1type_Sourse;
  307. OldRO2type_Sourse = CurrRO2type_Sourse;
  308. NonCriticalAlarmOldState = NonCriticalAlarmCurrent;
  309. }
  310. /**
  311. * @brief Мониторинг бита LainFail
  312. */
  313. void UPS_LineFailMonitor(void)
  314. {
  315. static bool isValueRecv = false;
  316. static uint8_t lineFailOldState = 0;
  317. uint8_t lineFailCurrent;
  318. lineFailCurrent = (UPS.Status >> 7) & 0x01;
  319. if (!isValueRecv) {
  320. isValueRecv = true;
  321. lineFailOldState = lineFailCurrent;
  322. if (lineFailCurrent){
  323. log_event_data(LOG_ALARM_LINE, "Авария");
  324. SNMP_SendUserTrap(LINE_ALARM);
  325. flUpdateLog = true;
  326. }
  327. return;
  328. }
  329. if (lineFailCurrent)
  330. flCriticalAlarm = true;
  331. // Значение параметра изменилось
  332. if (lineFailCurrent != lineFailOldState)
  333. {
  334. if (lineFailCurrent){
  335. log_event_data(LOG_ALARM_LINE, "Авария");
  336. SNMP_SendUserTrap(LINE_ALARM);
  337. flUpdateLog = true;
  338. }
  339. else{
  340. log_event_data(LOG_ALARM_LINE, "Норма");
  341. SNMP_SendUserTrap(LINE_NORM);
  342. flUpdateLog = true;
  343. }
  344. }
  345. lineFailOldState = lineFailCurrent;
  346. }
  347. /**
  348. * @brief Мониторинг бита LowBat
  349. */
  350. void UPS_LowBatMonitor(void)
  351. {
  352. static bool isValueRecv = false;
  353. static uint8_t lowBatOldState = 0;
  354. uint8_t lowBatCurrent;
  355. if((UPS.Status >> 7) & 0x01)
  356. lowBatCurrent = (UPS.Status >> 6) & 0x01;
  357. else
  358. lowBatCurrent = 0;
  359. if (!isValueRecv) {
  360. isValueRecv = true;
  361. lowBatOldState = lowBatCurrent;
  362. if (lowBatCurrent){
  363. log_event_data(LOG_ALARM_LOW_BAT, "Авария");
  364. SNMP_SendUserTrap(LOW_BAT_ALARM);
  365. flUpdateLog = true;
  366. }
  367. return;
  368. }
  369. if (lowBatCurrent)
  370. flNonCriticalAlarm = true;
  371. // Значение параметра изменилось
  372. if (lowBatCurrent != lowBatOldState)
  373. {
  374. if (lowBatCurrent){
  375. SNMP_SendUserTrap(LOW_BAT_ALARM);
  376. log_event_data(LOG_ALARM_LOW_BAT, "Авария");
  377. flUpdateLog = true;
  378. }
  379. else{
  380. SNMP_SendUserTrap(LOW_BAT_NORM);
  381. log_event_data(LOG_ALARM_LOW_BAT, "Норма");
  382. flUpdateLog = true;
  383. }
  384. }
  385. lowBatOldState = lowBatCurrent;
  386. }
  387. /**
  388. * @brief Мониторинг нагрузки
  389. */
  390. void UPS_PowerMonitor(void)
  391. {
  392. float load;
  393. static uint8_t stateCurrent = HYST_IDLE;
  394. load = UPS.Load;
  395. /* Отслеживается переход через верхнюю границу */
  396. if (load > UPS_LOAD)
  397. {
  398. flCriticalAlarm = true;
  399. UPS.Alarm = (UPS.Alarm & 0x0e) | (1 << 0);
  400. if (stateCurrent == HYST_IDLE)
  401. {
  402. LED_On(LED_MINOR_R);
  403. LED_On(LED_MINOR_G);
  404. stateCurrent = HYST_UP;
  405. log_event_data(LOG_ALARM_POWER, "Авария");
  406. // Отправка трапа о завышении
  407. SNMP_SendUserTrap(POWER_ALARM);
  408. flUpdateLog = true;
  409. }
  410. }
  411. /* Отслеживается нормализация */
  412. else if (load < (UPS_LOAD - UPS_LOAD_HIST))
  413. {
  414. UPS.Alarm = (UPS.Alarm & 0x0e);
  415. if (stateCurrent == HYST_UP)
  416. {
  417. LED_Off(LED_MINOR_R);
  418. LED_Off(LED_MINOR_G);
  419. stateCurrent = HYST_IDLE;
  420. log_event_data(LOG_ALARM_POWER, "Норма");
  421. // Отправка трапа о нормализации
  422. SNMP_SendUserTrap(POWER_NORM);
  423. flUpdateLog = true;
  424. }
  425. }
  426. }
  427. /**
  428. * @brief Мониторинг температуры
  429. */
  430. void UPS_TemperatureMonitor(void)
  431. {
  432. float temperature;
  433. static uint8_t stateCurrent = HYST_IDLE;
  434. temperature = UPS.Temp;
  435. /* Отслеживается переход через верхнюю границу */
  436. if (temperature > UPS_TEMPERATURE)
  437. {
  438. flCriticalAlarm = true;
  439. UPS.Alarm = (UPS.Alarm & 0x0d) | (1 << 1);
  440. if (stateCurrent == HYST_IDLE)
  441. {
  442. stateCurrent = HYST_UP;
  443. log_event_data(LOG_ALARM_TEMP, "Авария");
  444. // Отправка трапа о завышении
  445. SNMP_SendUserTrap(BATTERY_TEMPERATURE_ALARM);
  446. flUpdateLog = true;
  447. }
  448. }
  449. /* Отслеживается нормализация */
  450. else if (temperature < (UPS_TEMPERATURE - UPS_TEMPERATURE_HIST))
  451. {
  452. UPS.Alarm = (UPS.Alarm & 0x0d);
  453. if (stateCurrent == HYST_UP)
  454. {
  455. stateCurrent = HYST_IDLE;
  456. log_event_data(LOG_ALARM_TEMP, "Норма");
  457. // Отправка трапа о нормализации
  458. SNMP_SendUserTrap(BATTERY_TEMPERATURE_NORM);
  459. flUpdateLog = true;
  460. }
  461. }
  462. }
  463. /**
  464. * @brief Мониторинг параметра upsParams.connect
  465. */
  466. void UPS_ConnectMonitor(void)
  467. {
  468. static bool isValueRecv = false;
  469. static uint8_t connectOldState = 0;
  470. uint8_t connectCurrent;
  471. connectCurrent = UPS.Present;
  472. UPS.Alarm = (UPS.Alarm & 0x0b) | ((connectCurrent^1) << 2);
  473. if (!isValueRecv) {
  474. isValueRecv = true;
  475. connectOldState = connectCurrent;
  476. if (!connectCurrent){
  477. log_event_data(LOG_ALARM_UPS, "Авария");
  478. SNMP_SendUserTrap(CONNECT_MONITOR_ALARM);
  479. flUpdateLog = true;
  480. }
  481. return;
  482. }
  483. if (!connectCurrent)
  484. flCriticalAlarm = true;
  485. // Значение параметра изменилось
  486. if (connectCurrent != connectOldState)
  487. {
  488. if (connectCurrent){
  489. log_event_data(LOG_ALARM_UPS, "Норма");
  490. SNMP_SendUserTrap(CONNECT_MONITOR_NORM);
  491. flUpdateLog = true;
  492. }
  493. else{
  494. log_event_data(LOG_ALARM_UPS, "Авария");
  495. SNMP_SendUserTrap(CONNECT_MONITOR_ALARM);
  496. flUpdateLog = true;
  497. }
  498. }
  499. connectOldState = connectCurrent;
  500. }
  501. /**
  502. * @brief Мониторинг параметра upsParams.connect
  503. */
  504. void UPS_BatteryConnectMonitor(void)
  505. {
  506. static bool isValueRecv = false;
  507. static uint8_t AKBconnectOldState = 0;
  508. uint8_t AKBconnectCurrent;
  509. if(((UPS.Status >> 7) & 0x01) == 0)
  510. AKBconnectCurrent = (UPS.Status >> 6) & 0x01;
  511. else{
  512. AKBconnectCurrent = 0;
  513. }
  514. UPS.Alarm = (UPS.Alarm & 0x07) | (AKBconnectCurrent << 3);
  515. if (!isValueRecv) {
  516. isValueRecv = true;
  517. AKBconnectOldState = AKBconnectCurrent;
  518. if (AKBconnectCurrent){
  519. log_event_data(LOG_ALARM_AKB, "Авария");
  520. SNMP_SendUserTrap(BATTERY_CONNECT_ALARM);
  521. flUpdateLog = true;
  522. }
  523. return;
  524. }
  525. if (AKBconnectCurrent)
  526. flCriticalAlarm = true;
  527. // Значение параметра изменилось
  528. if (AKBconnectCurrent != AKBconnectOldState)
  529. {
  530. if (!AKBconnectCurrent){
  531. log_event_data(LOG_ALARM_AKB, "Норма");
  532. SNMP_SendUserTrap(BATTERY_CONNECT_NORM);
  533. flUpdateLog = true;
  534. }
  535. else{
  536. log_event_data(LOG_ALARM_AKB, "Авария");
  537. SNMP_SendUserTrap(BATTERY_CONNECT_ALARM);
  538. flUpdateLog = true;
  539. }
  540. }
  541. AKBconnectOldState = AKBconnectCurrent;
  542. }
  543. /********************************* (C) РОТЕК **********************************/