/********************************* (C) РОТЕК *********************************** * @module ups_monitor * @file ups_monitor.c * @version 1.0.0 * @date XX.XX.XXXX * $brief Template ******************************************************************************* * @history Version Author Comment * XX.XX.XXXX 1.0.0 Telenkov D.A. First release. ******************************************************************************* */ #include "stm32f4xx.h" #include "ups_monitor.h" #include "parameters.h" #include "settings_api.h" #include "megatec.h" #include "led.h" #include "log.h" #include "FreeRTOS.h" #include "task.h" #include "trap_api.h" #include "snmp_api.h" #include #define UPS_LOAD 70.0 // Нагрука (граница) #define UPS_LOAD_HIST 1.0 // Гистерезис нагрузки #define UPS_TEMPERATURE 40.0 // Температура (граница) #define UPS_TEMPERATURE_HIST 1.0 // Гистерезис температуры #define UPS_VAC_OUTPUT 150.0 // Выходного напряжения (граница) #define UPS_VAC_OUTPUT_HIST 20.0 // Гистерезис Выходного напряжения bool flCriticalAlarm = false; bool flNonCriticalAlarm = false; /** * @brief Общая структура настроек */ extern SETTINGS_t sSettings; extern bool flUpdateLog; /** * @brief Задача мониторинга параметров UPS */ void UPS_Monitor(void *params) { vTaskDelay(5000); for (;;) { flCriticalAlarm = false; flNonCriticalAlarm = false; // Проверяем флаг подключения UPS if (UPS.Present) { UPS_LineFailMonitor(); #ifdef HARDWARE_BT6706 UPS_VACoutputMonitor(); #endif UPS_LowBatMonitor(); UPS_PowerMonitor(); UPS_TemperatureMonitor(); UPS_BatteryConnectMonitor(); } UPS_ConnectMonitor(); UPS_DI0Monitor(); #ifdef HARDWARE_BT6702 UPS_CriticalAlarmMonitor(); UPS_NonCriticalAlarmMonitor(); #endif vTaskDelay(1000); } } /** * @brief Мониторинг бита DI0 state */ void UPS_DI0Monitor(void) { static bool isValueRecv = false; static uint8_t DI0OldState = 0; uint8_t DI0StateCurrent; DI0StateCurrent = get_state_din_outs(DIN1) ^ sSettings.sInOuts.din_type_act[0]; UPS.Alarm = (UPS.Alarm & 0x0f) | (DI0StateCurrent << 4); if (!isValueRecv) { isValueRecv = true; DI0OldState = DI0StateCurrent; if (DI0StateCurrent){ log_event_data(LOG_ALARM_DIO, "Авария"); SNMP_SendUserTrap(DI0_ALARM); flUpdateLog = true; } return; } /*if (DI0StateCurrent) flCriticalAlarm = true;*/ // Значение параметра изменилось if (DI0StateCurrent != DI0OldState) { if (!DI0StateCurrent){ log_event_data(LOG_ALARM_DIO, "Норма"); SNMP_SendUserTrap(DI0_NORM); flUpdateLog = true; } else{ log_event_data(LOG_ALARM_DIO, "Авария"); SNMP_SendUserTrap(DI0_ALARM); flUpdateLog = true; } } DI0OldState = DI0StateCurrent; } void relay_setup_log(uint8_t *curr_source, ro_type_source_t src_act_ro, uint8_t state_relay) { uint8_t i = 0; flUpdateLog = true; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ if(curr_source[i] == src_act_ro){ SetROInt(state_relay, i); SNMP_SendUserTrap((DO0_TOGGLED+i)); if(state_relay){ #ifdef HARDWARE_BT6706 log_event_data((LOG_DO0_STATE + i), "Разомкнуто"); #elif HARDWARE_BT6702 log_event_data((LOG_DO0_STATE + i), "Замкнуто"); #endif } else{ #ifdef HARDWARE_BT6706 log_event_data((LOG_DO0_STATE + i), "Замкнуто"); #elif HARDWARE_BT6702 log_event_data((LOG_DO0_STATE + i), "Разомкнуто"); #endif } } } } void relay_setup_log_change(uint8_t *curr_source, uint8_t *prev_source, ro_type_source_t src_act_ro, uint8_t state_relay) { uint8_t i = 0; flUpdateLog = true; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ if(get_state_din_outs(DOUT1 + i)){ if(curr_source[i] != prev_source[i] && (prev_source[i] == src_act_ro || curr_source[i] == src_act_ro)){ SetROInt(state_relay, i); SNMP_SendUserTrap((DO0_TOGGLED+i)); if(state_relay){ #ifdef HARDWARE_BT6706 log_event_data((LOG_DO0_STATE + i), "Разомкнуто"); #elif HARDWARE_BT6702 log_event_data((LOG_DO0_STATE + i), "Замкнуто"); #endif } else{ #ifdef HARDWARE_BT6706 log_event_data((LOG_DO0_STATE + i), "Замкнуто"); #elif HARDWARE_BT6702 log_event_data((LOG_DO0_STATE + i), "Разомкнуто"); #endif } } } } } #ifdef HARDWARE_BT6702 /** * @brief Мониторинг бита CriticalAlarm */ void UPS_CriticalAlarmMonitor(void) { static bool isValueRecv = false; static uint8_t CriticalAlarmOldState = 0; uint8_t CriticalAlarmCurrent; uint8_t i = 0; static uint8_t OldROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; uint8_t CurrROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++) CurrROtype_Sourse[i] = sSettings.sInOuts.ro_type_source[i]; CriticalAlarmCurrent = flCriticalAlarm; if (!isValueRecv) { isValueRecv = true; CriticalAlarmOldState = CriticalAlarmCurrent; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++) OldROtype_Sourse[i] = CurrROtype_Sourse[i]; if(CriticalAlarmCurrent){ relay_setup_log(CurrROtype_Sourse, CRITICAL, 1); } return; } if(CriticalAlarmCurrent){ if (UPS.Present) LED_On(LED_MAJOR_R); else LED_Toggle(LED_MAJOR_R); } else{ LED_Off(LED_MAJOR_R); } // Значение параметра изменилось if (CriticalAlarmCurrent != CriticalAlarmOldState) { if(CriticalAlarmCurrent){ relay_setup_log(CurrROtype_Sourse, CRITICAL, 1); } else{ relay_setup_log(CurrROtype_Sourse, CRITICAL, 0); } } else { if(CriticalAlarmCurrent) relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, CRITICAL, 1); else relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, CRITICAL, 0); } for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } CriticalAlarmOldState = CriticalAlarmCurrent; } /** * @brief Мониторинг бита NonCriticalAlarm */ void UPS_NonCriticalAlarmMonitor(void) { static bool isValueRecv = false; static uint8_t NonCriticalAlarmOldState = 0; uint8_t NonCriticalAlarmCurrent; uint8_t i = 0; static uint8_t OldROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; uint8_t CurrROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++) CurrROtype_Sourse[i] = sSettings.sInOuts.ro_type_source[i]; NonCriticalAlarmCurrent = flNonCriticalAlarm; if (!isValueRecv) { isValueRecv = true; NonCriticalAlarmOldState = NonCriticalAlarmCurrent; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++) OldROtype_Sourse[i] = CurrROtype_Sourse[i]; if(NonCriticalAlarmCurrent) relay_setup_log(CurrROtype_Sourse, NON_CRITICAL, 1); return; } // Значение параметра изменилось if (NonCriticalAlarmCurrent != NonCriticalAlarmOldState) { if(NonCriticalAlarmCurrent){ relay_setup_log(CurrROtype_Sourse, NON_CRITICAL, 1); } else{ relay_setup_log(CurrROtype_Sourse, NON_CRITICAL, 0); } } else { if(NonCriticalAlarmCurrent) relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, CRITICAL, 1); else relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, CRITICAL, 0); } for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } NonCriticalAlarmOldState = NonCriticalAlarmCurrent; } #endif /** * @brief Мониторинг бита LainFail */ void UPS_LineFailMonitor(void) { static bool isValueRecv = false; static uint8_t lineFailOldState = 0; uint8_t lineFailCurrent; #ifdef HARDWARE_BT6706 uint8_t i = 0; static uint8_t OldROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; uint8_t CurrROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++) CurrROtype_Sourse[i] = sSettings.sInOuts.ro_type_source[i]; #endif lineFailCurrent = (UPS.Status >> 7) & 0x01; if (!isValueRecv) { isValueRecv = true; lineFailOldState = lineFailCurrent; if (lineFailCurrent){ log_event_data(LOG_ALARM_LINE, "Авария"); SNMP_SendUserTrap(LINE_ALARM); flUpdateLog = true; #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 1); #endif } return; } if (lineFailCurrent) flCriticalAlarm = true; // Значение параметра изменилось if (lineFailCurrent != lineFailOldState) { if (lineFailCurrent){ #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 1); #endif log_event_data(LOG_ALARM_LINE, "Авария"); SNMP_SendUserTrap(LINE_ALARM); flUpdateLog = true; } else{ #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 0); #endif log_event_data(LOG_ALARM_LINE, "Норма"); SNMP_SendUserTrap(LINE_NORM); flUpdateLog = true; } } #ifdef HARDWARE_BT6706 else{ if (lineFailCurrent) relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, AC_PRESENT, 1); else relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, AC_PRESENT, 0); } for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } #endif lineFailOldState = lineFailCurrent; } #ifdef HARDWARE_BT6706 /** * @brief Мониторинг аварии выходного напряжения */ void UPS_VACoutputMonitor(void) { static uint8_t stateCurrentVACoutput = HYST_IDLE; uint8_t VACoutputCurrent; uint8_t i = 0; static bool isValueRecv = false; static uint8_t OldROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; uint8_t CurrROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ CurrROtype_Sourse[i] = sSettings.sInOuts.ro_type_source[i]; if(!isValueRecv) OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } VACoutputCurrent = UPS.VAC_out; /* Отслеживается переход через нижнию границу */ if (VACoutputCurrent < UPS_VAC_OUTPUT) { if (stateCurrentVACoutput == HYST_IDLE) { LED_On(LED_MINOR_R); LED_On(LED_MINOR_G); stateCurrentVACoutput = HYST_UP; relay_setup_log(CurrROtype_Sourse, DC_PRESENT, 1); log_event_data(LOG_ALARM_VAC_OUTPUT, "Авария"); // Отправка трапа о завышении // SNMP_SendUserTrap(POWER_ALARM); flUpdateLog = true; } else{ relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, DC_PRESENT, 1); } } /* Отслеживается нормализация */ else if (VACoutputCurrent > (UPS_VAC_OUTPUT + UPS_VAC_OUTPUT_HIST)) { if (stateCurrentVACoutput == HYST_UP) { LED_Off(LED_MINOR_R); LED_Off(LED_MINOR_G); stateCurrentVACoutput = HYST_IDLE; relay_setup_log(CurrROtype_Sourse, DC_PRESENT, 0); log_event_data(LOG_ALARM_VAC_OUTPUT, "Норма"); // Отправка трапа о нормализации // SNMP_SendUserTrap(POWER_NORM); flUpdateLog = true; } else{ relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, DC_PRESENT, 0); } } for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } } #endif /** * @brief Мониторинг бита LowBat */ void UPS_LowBatMonitor(void) { static bool isValueRecv = false; static uint8_t lowBatOldState = 0; uint8_t lowBatCurrent; #ifdef HARDWARE_BT6706 uint8_t i = 0; static uint8_t OldROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; uint8_t CurrROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++) CurrROtype_Sourse[i] = sSettings.sInOuts.ro_type_source[i]; #endif if((UPS.Status >> 7) & 0x01) lowBatCurrent = (UPS.Status >> 6) & 0x01; else lowBatCurrent = 0; if (!isValueRecv) { isValueRecv = true; lowBatOldState = lowBatCurrent; if (lowBatCurrent){ log_event_data(LOG_ALARM_LOW_BAT, "Авария"); SNMP_SendUserTrap(LOW_BAT_ALARM); flUpdateLog = true; #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 1); #endif } return; } if (lowBatCurrent) flNonCriticalAlarm = true; // Значение параметра изменилось if (lowBatCurrent != lowBatOldState) { if (lowBatCurrent){ SNMP_SendUserTrap(LOW_BAT_ALARM); log_event_data(LOG_ALARM_LOW_BAT, "Авария"); flUpdateLog = true; #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 1); #endif } else{ SNMP_SendUserTrap(LOW_BAT_NORM); log_event_data(LOG_ALARM_LOW_BAT, "Норма"); flUpdateLog = true; #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 0); #endif } } #ifdef HARDWARE_BT6706 else{ if (lowBatCurrent) relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, CHARGE_AKB, 1); else relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, CHARGE_AKB, 0); } for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } #endif lowBatOldState = lowBatCurrent; } /** * @brief Мониторинг нагрузки */ void UPS_PowerMonitor(void) { float load; static uint8_t stateCurrent = HYST_IDLE; load = UPS.Load; /* Отслеживается переход через верхнюю границу */ if (load > UPS_LOAD) { flCriticalAlarm = true; UPS.Alarm = (UPS.Alarm & 0x0e) | (1 << 0); if (stateCurrent == HYST_IDLE) { LED_On(LED_MINOR_R); LED_On(LED_MINOR_G); stateCurrent = HYST_UP; log_event_data(LOG_ALARM_POWER, "Авария"); // Отправка трапа о завышении SNMP_SendUserTrap(POWER_ALARM); flUpdateLog = true; } } /* Отслеживается нормализация */ else if (load < (UPS_LOAD - UPS_LOAD_HIST)) { UPS.Alarm = (UPS.Alarm & 0x0e); if (stateCurrent == HYST_UP) { LED_Off(LED_MINOR_R); LED_Off(LED_MINOR_G); stateCurrent = HYST_IDLE; log_event_data(LOG_ALARM_POWER, "Норма"); // Отправка трапа о нормализации SNMP_SendUserTrap(POWER_NORM); flUpdateLog = true; } } } /** * @brief Мониторинг температуры */ void UPS_TemperatureMonitor(void) { float temperature; static uint8_t stateCurrent = HYST_IDLE; temperature = UPS.Temp; /* Отслеживается переход через верхнюю границу */ if (temperature > UPS_TEMPERATURE) { flCriticalAlarm = true; UPS.Alarm = (UPS.Alarm & 0x0d) | (1 << 1); if (stateCurrent == HYST_IDLE) { stateCurrent = HYST_UP; log_event_data(LOG_ALARM_TEMP, "Авария"); // Отправка трапа о завышении SNMP_SendUserTrap(BATTERY_TEMPERATURE_ALARM); flUpdateLog = true; } } /* Отслеживается нормализация */ else if (temperature < (UPS_TEMPERATURE - UPS_TEMPERATURE_HIST)) { UPS.Alarm = (UPS.Alarm & 0x0d); if (stateCurrent == HYST_UP) { stateCurrent = HYST_IDLE; log_event_data(LOG_ALARM_TEMP, "Норма"); // Отправка трапа о нормализации SNMP_SendUserTrap(BATTERY_TEMPERATURE_NORM); flUpdateLog = true; } } } /** * @brief Мониторинг параметра upsParams.connect */ void UPS_ConnectMonitor(void) { static bool isValueRecv = false; static uint8_t connectOldState = 0; uint8_t connectCurrent; connectCurrent = UPS.Present; UPS.Alarm = (UPS.Alarm & 0x0b) | ((connectCurrent^1) << 2); if (!isValueRecv) { isValueRecv = true; connectOldState = connectCurrent; if (!connectCurrent){ log_event_data(LOG_ALARM_UPS, "Авария"); SNMP_SendUserTrap(CONNECT_MONITOR_ALARM); flUpdateLog = true; } return; } if (!connectCurrent) flCriticalAlarm = true; // Значение параметра изменилось if (connectCurrent != connectOldState) { if (connectCurrent){ log_event_data(LOG_ALARM_UPS, "Норма"); SNMP_SendUserTrap(CONNECT_MONITOR_NORM); flUpdateLog = true; } else{ log_event_data(LOG_ALARM_UPS, "Авария"); SNMP_SendUserTrap(CONNECT_MONITOR_ALARM); flUpdateLog = true; } } connectOldState = connectCurrent; } /** * @brief Мониторинг параметра upsParams.connect */ void UPS_BatteryConnectMonitor(void) { static bool isValueRecv = false; static uint8_t AKBconnectOldState = 0; uint8_t AKBconnectCurrent; #ifdef HARDWARE_BT6706 uint8_t i = 0; static uint8_t OldROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; uint8_t CurrROtype_Sourse[OUTPUTS_TOTAL_COUNT] = {0}; for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++) CurrROtype_Sourse[i] = sSettings.sInOuts.ro_type_source[i]; #endif if(((UPS.Status >> 7) & 0x01) == 0) AKBconnectCurrent = (UPS.Status >> 6) & 0x01; else{ AKBconnectCurrent = 0; } UPS.Alarm = (UPS.Alarm & 0x07) | (AKBconnectCurrent << 3); if (!isValueRecv) { isValueRecv = true; AKBconnectOldState = AKBconnectCurrent; if (AKBconnectCurrent){ log_event_data(LOG_ALARM_AKB, "Авария"); SNMP_SendUserTrap(BATTERY_CONNECT_ALARM); flUpdateLog = true; #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, OFF_AKB, 1); #endif } return; } if (AKBconnectCurrent) flCriticalAlarm = true; // Значение параметра изменилось if (AKBconnectCurrent != AKBconnectOldState) { if (!AKBconnectCurrent){ log_event_data(LOG_ALARM_AKB, "Норма"); SNMP_SendUserTrap(BATTERY_CONNECT_NORM); flUpdateLog = true; #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, OFF_AKB, 0); #endif } else{ log_event_data(LOG_ALARM_AKB, "Авария"); SNMP_SendUserTrap(BATTERY_CONNECT_ALARM); flUpdateLog = true; #ifdef HARDWARE_BT6706 relay_setup_log(CurrROtype_Sourse, OFF_AKB, 1); #endif } } #ifdef HARDWARE_BT6706 else{ if (AKBconnectCurrent) relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, OFF_AKB, 1); else relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, OFF_AKB, 0); } for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){ OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } #endif AKBconnectOldState = AKBconnectCurrent; } /********************************* (C) РОТЕК **********************************/