~={green}Замечания от заказчика=~ 1. В логе фигурируют аварии, которых не может быть. "Срабатывание EPO", "Ош. подкл. вх. напряжения" ~={yellow}Question.=~ Отключить функции. ~={green}Fixed.=~ Событие "Срабатывание EPO" формируется в модуле ups_monitor.c В отдельной функции UPS_EPOMonitor. Нужно ли ее отключить? ```c #define EPO_MONITOR ``` Событие "Ош подкл вх напр" формируется в модуле ups_monitor.c В отдельной функции UPS_PhaseFailMonitor. Нужно ли ее отключить? ```c #define PHASE_FAIL_MONITOR ``` 2. При запуске теста АКБ в логе информация о смене режима работы, но не о тесте. В syslog правильно. ~={yellow}Question.=~ В логе в событиях контроллера не отображается режим работы "тест АКБ" (Вход в тест, выход из теста.) 3. В веб-интерфейсе отображается входная частота, в случае оффлайн ИБП особого смысла не имеет. Логичнее указывать только частоту выходного напряжения. ~={yellow}Question.=~ ~={green}Fixed.=~ Существует множество режимов работы контроллера ИБП. - Power on - Standby - Bypass - OnLine - Battery - Battery test - Fault - ECO - Converter - Shutdown Необходимо уточнить в каких режимах показывать входную частоту и какое значение выводить? Во всех режимах кроме Bypass выводить 0 в параметре "входная частота". За вывод этого параметра в WEB и SNMP отвечает функция: ```c void GetInputFreqStr(char *str, uint8_t *len) {     sprintf(str, "%0.1f", UPS.Freq_in);     *len = strlen(str); } UPS.Mode != 'B' ``` Добавил анализ режима работы из параметра UPS.Mode ```c void GetInputFreqStr(char *str, uint8_t *len) {     if (UPS.Mode == 'Y')       sprintf(str, "%0.1f", UPS.Freq_in);     else       sprintf(str, "%0.1f", 0.0);     *len = strlen(str); } ``` 4. Проблема IAP. ~={red}Open.=~ 5. Полная мощность ИБП 400, а не 500. ~={green}Fixed.=~ ```c RoTeK-swt-BT-BT-6721-signals-MIB::upsFullPower.0 = STRING: "400" // Этот параметр формируется в функции: /**   * @brief Полная мощность АКБ   */ void GetUPSPowerStr(char *str, uint8_t *len) {     sprintf(str, "%d", (int32_t)sSettings.UPS_Setting.ups_power);     *len = strlen(str); } // Решение. Изменил значение параметра sSettings.UPS_Setting.ups_power в settings_api_bt6721.c /**   * @brief  Настройки ИБП по умолчанию   */ void SETTINGS_SetUPSSettingsDef(void) {   sSettings.UPS_Setting.Ucellmin = 1.89;   sSettings.UPS_Setting.Ucellmax = 2.36;   sSettings.UPS_Setting.Uakb = 12;   sSettings.UPS_Setting.common_capacity = 15;   sSettings.UPS_Setting.ups_power = 400;   sSettings.UPS_Setting.set_data = 0;   sSettings.UPS_Setting.life_time = 5;   sSettings.UPS_Setting.type_ups = ups_kestar; } ``` 6. Убрать отправку fault в конце разряда АКБ. ~={yellow}Question.=~ Не понял. Отправку куда? Это трап. Trap ID - 20 - это оно? ~={yellow}Question.=~ ```c /**   * @brief  Мониторинг бита LowBat     */ void UPS_LowBatMonitor(void) { #ifdef LOW_BAT_MONITOR static bool isValueRecv = false; static uint8_t lowBatOldState = 0; static bool flag_alarm_time = false; uint8_t lowBatCurrent; #if defined RELAY_CHARGE_AKB 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.sRelays[i].ro_type_source; #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); syslog(SYSLOG_ERROR, "Низкий заряд АКБ (%d%%)", UPS.SOC);     flUpdateLog = true; #if defined RELAY_CHARGE_AKB     relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 1); #endif     }     else{     SNMP_SendUserTrap(LOW_BAT_NORM);     log_event_data(LOG_ALARM_LOW_BAT, "Норма");     syslog(SYSLOG_NOTICE, "Заряд АКБ в норме (%d%%)", UPS.SOC);     flUpdateLog = true; #if defined RELAY_CHARGE_AKB     relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 0); #endif }     return; } // Значение параметра изменилось if (lowBatCurrent != lowBatOldState) { if(flag_alarm_time){     flag_alarm_time = false;     if (lowBatCurrent){     SNMP_SendUserTrap(LOW_BAT_ALARM);     syslog(SYSLOG_ERROR, "Низкий заряд АКБ (%d%%)", UPS.SOC);     log_event_data(LOG_ALARM_LOW_BAT, "Авария");     flUpdateLog = true; #ifdef RELAY_CHARGE_AKB       relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 1); #endif     }     else{     SNMP_SendUserTrap(LOW_BAT_NORM);     syslog(SYSLOG_NOTICE, "Заряд АКБ в норме (%d%%)", UPS.SOC);     log_event_data(LOG_ALARM_LOW_BAT, "Норма");     flUpdateLog = true; #if defined RELAY_CHARGE_AKB     relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 0); #endif     } } else{     flag_alarm_time = true; } } #if defined RELAY_CHARGE_AKB else{     flag_alarm_time = false;     if (lowBatCurrent)     relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, CHARGE_AKB); } for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){     OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } #endif if(!flag_alarm_time){     if (lowBatCurrent){ flNonCriticalAlarm = true;     flLedAlarm = true;     }     lowBatOldState = lowBatCurrent; } else{     if (lowBatOldState){     flNonCriticalAlarm = true;     flLedAlarm = true;     } } #endif } ``` 7. Сообщение в лог "авария входного напряжения 220В авария" при возобновлении питания. ~={red}Open.=~ Поправил логику вызова функций записи в лог. ~={green}Fixed.=~ ```c // Запись в журнал формируется в функции: /**   * @brief  Мониторинг бита LainFail   */ void UPS_LineFailMonitor(void) { #ifdef LINE_FAIL_MONITOR static bool isValueRecv = false; static uint8_t lineFailOldState = 0; uint8_t lineFailCurrent; char log_string[50]; uint8_t len; #if defined RELAY_AC_PRESENT 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.sRelays[i].ro_type_source; #endif #ifdef VAC_IN_MONITOR lineFailCurrent = ((UPS.Status >> 7) & 0x01); lineFailCurrent |= UPS_VACinputRangeAlarm(); #else lineFailCurrent = (UPS.Status >> 7) & 0x01; #endif if (!isValueRecv) { isValueRecv = true; lineFailOldState = lineFailCurrent;     if (lineFailCurrent != 0) {     memset(log_string, 0, sizeof(log_string));     strcat(log_string, "Авария");     len = strlen(log_string);     sprintf(&log_string[len], " (%0.1f В)", UPS.VAC_in);       log_event_data(LOG_ALARM_LINE, log_string);     SNMP_SendUserTrap(LINE_ALARM);     syslog(SYSLOG_ERROR, "Авария сети (%0.1f В)", UPS.VAC_in);     flUpdateLog = true; #if defined RELAY_AC_PRESENT relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 1); #endif }     else { #if defined RELAY_AC_PRESENT     relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 0); #endif     log_event_data(LOG_ALARM_LINE, "Норма");     SNMP_SendUserTrap(LINE_NORM);     syslog(SYSLOG_NOTICE, "Сеть в норме (%0.1f В)", UPS.VAC_in);     flUpdateLog = true;     }     return; } if (lineFailCurrent != 0) {     flCriticalAlarm = true;     flLedAlarm = true; } // Значение параметра изменилось if (lineFailCurrent != lineFailOldState) {     if (lineFailCurrent != 0){ #if defined RELAY_AC_PRESENT     relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 1); #endif     memset(log_string, 0, sizeof(log_string));     strcat(log_string, "Авария");    len = strlen(log_string);        sprintf(&log_string[len], " (%0.1f В)", UPS.VAC_in);         log_event_data(LOG_ALARM_LINE, log_string);       SNMP_SendUserTrap(LINE_ALARM);        syslog(SYSLOG_ERROR, "Авария сети (%0.1f В)", UPS.VAC_in); #ifdef AKB_CHANGE_MONITOR       if(UPS.Alarm & 0x40) {         log_event_data(LOG_ALARM_CHANGE_AKB, "Авария");         SNMP_SendUserTrap(BATTERY_CHANGE_ALARM);     }   #endif     flUpdateLog = true;     }     else{     if (UPS.VAC_in == 0) {         return;     } #if defined RELAY_AC_PRESENT       relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 0); #endif     log_event_data(LOG_ALARM_LINE, "Норма");     SNMP_SendUserTrap(LINE_NORM);     syslog(SYSLOG_NOTICE, "Сеть в норме (%0.1f В)", UPS.VAC_in);     flUpdateLog = true;     } } #if defined RELAY_AC_PRESENT else{     if (lineFailCurrent != 0)     relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, AC_PRESENT); } for (i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){     OldROtype_Sourse[i] = CurrROtype_Sourse[i]; } #endif lineFailOldState = lineFailCurrent; #endif ``` 8. В syslog именует выходное напряжение входным. ~={green}Fixed.=~ ```c // ups_monitor.c // Поменял "входное" на "выходное" SNMP_SendUserTrap(VAC_HIGH_OUTPUT_ALARM); syslog(SYSLOG_ERROR, "Высокое выходное напряжение (%0.1f В)", VACoutputCurrent); ``` 9. При отказе флешки контроллер виснет - хочется чтобы продолжал работать пусть и без журнала. ~={green}Fixed.=~ 10. Сброс ИБП командой "C" (кнопка отмены отключения) если состояние Fault длится более 15-и секунд. ~={green}Fixed.=~ Добавил анализ состояния в функцию void kstar_mode(void) ```c     if (UPS.Mode == 'F') {         fault_mode_cnt++;     }     else {         fault_mode_cnt = 0;     }     if (fault_mode_cnt == UPA_CANSEL_DELAY) {         send_MegaTec_cmd(ups_cancel_shut_down);         fault_mode_cnt = 0;     } ```