/********************************* (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 "rtc.h"

#include "FreeRTOS.h"
#include "task.h"

#include "trap_api.h"
#include "snmp_api.h"

#include <stdbool.h>


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_TestFinishMonitor();
      UPS_LineFailMonitor();
#if	defined HARDWARE_BT6707 || HARDWARE_BT6709
      UPS_VACoutputLowRangeMonitor();
      UPS_VACoutputHighRangeMonitor();
#endif
      UPS_LowBatMonitor();  
      UPS_PowerMonitor();
      UPS_TemperatureHighRangeMonitor();
      UPS_TemperatureLowRangeMonitor();
      UPS_BatteryConnectMonitor();
    }
    UPS_ConnectMonitor();
#ifndef HARDWARE_BT6709
    UPS_DI0Monitor();
#endif
#ifdef HARDWARE_BT6709
    AKB_Change_Monitor();
#endif
#ifdef HARDWARE_BT6703
    UPS_CriticalAlarmMonitor();
    UPS_NonCriticalAlarmMonitor();
#endif
#if	defined HARDWARE_BT6707 || HARDWARE_BT6709
      if(flCriticalAlarm){
    	  if (UPS.Present)
    		  LED_On(LED_MAJOR_R);
    	  else
    		  LED_Toggle(LED_MAJOR_R);
      }
      else{
    	  LED_Off(LED_MAJOR_R);
      }
#endif

    vTaskDelay(1000);
  }
}
#ifndef HARDWARE_BT6709
/**
  * @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 & 0xef) | (DI0StateCurrent << 4);

  	if (!isValueRecv) {
	  isValueRecv = true;
	  DI0OldState = DI0StateCurrent;
	  if (DI0StateCurrent){
		  log_event_data(LOG_ALARM_DIO, "Авария");
		  SNMP_SendUserTrap(DI0_ALARM);
		  flUpdateLog = true;
	  }
	  else{
		  log_event_data(LOG_ALARM_DIO, "Норма");
		  SNMP_SendUserTrap(DI0_NORM);
		  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;

	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){
				  flUpdateLog = true;
#if	defined HARDWARE_BT6707
				  log_event_data((LOG_DO0_STATE + i), "Разомкнуто");
#elif HARDWARE_BT6703
				  log_event_data((LOG_DO0_STATE + i), "Замкнуто");
#endif

			  }
			  else{
				  flUpdateLog = true;
#if	defined HARDWARE_BT6707
				  log_event_data((LOG_DO0_STATE + i), "Замкнуто");
#elif HARDWARE_BT6703
				  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 i = 0;

	for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){
		if(curr_source[i] != prev_source[i] && (prev_source[i] == src_act_ro || curr_source[i] == src_act_ro)){
#if	defined HARDWARE_BT6707
			if(curr_source[i] != src_act_ro){
				flUpdateLog = true;
				 SetROInt(0, i);
				 SNMP_SendUserTrap((DO0_TOGGLED+i));
				 log_event_data((LOG_DO0_STATE + i), "Замкнуто");
			  }
			  else{
				  flUpdateLog = true;
				  SetROInt(1, i);
				  SNMP_SendUserTrap((DO0_TOGGLED+i));
				  log_event_data((LOG_DO0_STATE + i), "Разомкнуто");
			  }
#elif HARDWARE_BT6703
			  if(curr_source[i] != src_act_ro){
				  flUpdateLog = true;
				  SetROInt(0, i);
				  SNMP_SendUserTrap((DO0_TOGGLED+i));
				  log_event_data((LOG_DO0_STATE + i), "Разомкнуто");
			  }
			  else{
				  flUpdateLog = true;
				  SetROInt(1, i);
				 SNMP_SendUserTrap((DO0_TOGGLED+i));
				  log_event_data((LOG_DO0_STATE + i), "Замкнуто");
			  }
#endif

		}
	}
}
#endif


#ifdef HARDWARE_BT6703
/**
  * @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);
	}
	else{
		relay_setup_log(CurrROtype_Sourse, CRITICAL, 0);
	}
	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);

  }

	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);
	  else
		  relay_setup_log(CurrROtype_Sourse, NON_CRITICAL, 0);

	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, NON_CRITICAL);
  }

  for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){
  	  OldROtype_Sourse[i] = CurrROtype_Sourse[i];
  }
  NonCriticalAlarmOldState = NonCriticalAlarmCurrent;
}
#endif

/**
  * @brief  Мониторинг бита Test in progress
  */
void UPS_TestFinishMonitor(void)
{
  static uint8_t TestFinishState = 0;
  uint8_t TestFinishStateCurrent;

  TestFinishStateCurrent = (UPS.Status >> 2) & 0x01;

  // Значение параметра изменилось
  if (TestFinishStateCurrent != TestFinishState)
  {
    if (!TestFinishStateCurrent){
      log_event_data(LOG_TEST_UPS, "Завершен");
      flUpdateLog = true;
    }
  }

  TestFinishState = TestFinishStateCurrent;
}
/**
  * @brief  Мониторинг бита LainFail
  */
void UPS_LineFailMonitor(void)
{

  static bool isValueRecv = false;
  static uint8_t lineFailOldState = 0;
  uint8_t lineFailCurrent;

#if defined HARDWARE_BT6707
  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;
#if	defined HARDWARE_BT6707
    	relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 1);
#endif
    }
    else{
#if	defined HARDWARE_BT6707
      relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 0);
#endif
      log_event_data(LOG_ALARM_LINE, "Норма");
      SNMP_SendUserTrap(LINE_NORM);
      flUpdateLog = true;
    }

    return;
  }


  if (lineFailCurrent)
	  flCriticalAlarm = true;
    
  // Значение параметра изменилось
  if (lineFailCurrent != lineFailOldState)
  {
    if (lineFailCurrent){
#if	defined HARDWARE_BT6707
    	relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 1);
#endif

    	log_event_data(LOG_ALARM_LINE, "Авария");
    	SNMP_SendUserTrap(LINE_ALARM);
#ifdef HARDWARE_BT6709
      if(UPS.Alarm & 0x40) {
        log_event_data(LOG_ALARM_CHANGE_AKB, "Авария");
    	  SNMP_SendUserTrap(BATTERY_CHANGE_ALARM);
      }   
#endif
    	flUpdateLog = true;
    }
    else{
#if	defined HARDWARE_BT6707
      relay_setup_log(CurrROtype_Sourse, AC_PRESENT, 0);
#endif
      log_event_data(LOG_ALARM_LINE, "Норма");
      SNMP_SendUserTrap(LINE_NORM);
      flUpdateLog = true;
    }
  }

#if defined HARDWARE_BT6707
  else{
	  if (lineFailCurrent)
		  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;
}

#if defined HARDWARE_BT6707 || HARDWARE_BT6709
/**
  * @brief  Мониторинг аварии выходного напряжения по нижней границе
  */
void UPS_VACoutputLowRangeMonitor(void)
{

  static uint8_t stateCurrentVACoutput = HYST_IDLE;
  uint8_t VACoutputCurrent;
#if	defined HARDWARE_BT6707
  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];
  }
#endif

  VACoutputCurrent = UPS.VAC_out;

  /* Отслеживается переход через нижнию границу */
  if (VACoutputCurrent < sSettings.sAlarmManager.ac_output_range.low)
  {
	    flCriticalAlarm = true;
      if (stateCurrentVACoutput == HYST_IDLE)
	    {
          UPS.Alarm |= (1 << 7);
          stateCurrentVACoutput = HYST_DOWN;
#if	defined HARDWARE_BT6707
          relay_setup_log(CurrROtype_Sourse, DC_PRESENT, 1);
#endif
	        log_event_data(LOG_ALARM_VAC_LOW_OUTPUT, "Авария");
	  // Отправка трапа о завышении
	//  SNMP_SendUserTrap(POWER_ALARM);
	        flUpdateLog = true;
	    } else {
#if	defined HARDWARE_BT6707
    	    relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, DC_PRESENT);
#endif
      }
  }
  /* Отслеживается нормализация */
  else if (VACoutputCurrent > (sSettings.sAlarmManager.ac_output_range.low + sSettings.sAlarmManager.ac_output_range.hyst))
  {
      if (stateCurrentVACoutput == HYST_DOWN)
	    {
          UPS.Alarm &= 0x7f;
    	    stateCurrentVACoutput = HYST_IDLE;
#if	defined HARDWARE_BT6707
	        relay_setup_log(CurrROtype_Sourse, DC_PRESENT, 0);
#endif
	        log_event_data(LOG_ALARM_VAC_LOW_OUTPUT, "Норма");
	  // Отправка трапа о нормализации
	 // SNMP_SendUserTrap(POWER_NORM);
	        flUpdateLog = true;
	    }
  }
#if	defined HARDWARE_BT6707
  for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){
  	  OldROtype_Sourse[i] = CurrROtype_Sourse[i];
    }
#endif
}

/**
  * @brief  Мониторинг аварии выходного напряжения по верхней границе
  */
void UPS_VACoutputHighRangeMonitor(void)
{

  static uint8_t stateCurrentVACoutput = HYST_IDLE;
  uint8_t VACoutputCurrent;
#if	defined HARDWARE_BT6707
  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];
  }
#endif

  VACoutputCurrent = UPS.VAC_out;

  /* Отслеживается переход через верхнюю границу */
  if (VACoutputCurrent > sSettings.sAlarmManager.ac_output_range.high)
  {
	    flCriticalAlarm = true;
      if (stateCurrentVACoutput == HYST_IDLE) {
          UPS.Alarm |= (1 << 7);
          stateCurrentVACoutput = HYST_UP;
#if	defined HARDWARE_BT6707
          relay_setup_log(CurrROtype_Sourse, DC_PRESENT, 1);
#endif
	        log_event_data(LOG_ALARM_VAC_HIGH_OUTPUT, "Авария");
	  // Отправка трапа о завышении
	//  SNMP_SendUserTrap(POWER_ALARM);
	        flUpdateLog = true;
	    } else {
#if	defined HARDWARE_BT6707
    	    relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, DC_PRESENT);
#endif
      }
  }
  /* Отслеживается нормализация */
  else if (VACoutputCurrent < (sSettings.sAlarmManager.ac_output_range.high - sSettings.sAlarmManager.ac_output_range.hyst))
  {
      if (stateCurrentVACoutput == HYST_UP) {
          UPS.Alarm &= 0x7f;
    	    stateCurrentVACoutput = HYST_IDLE;
#if	defined HARDWARE_BT6707
	        relay_setup_log(CurrROtype_Sourse, DC_PRESENT, 0);
#endif
	        log_event_data(LOG_ALARM_VAC_HIGH_OUTPUT, "Норма");
	  // Отправка трапа о нормализации
	 // SNMP_SendUserTrap(POWER_NORM);
	        flUpdateLog = true;
	    }
  }
#if	defined HARDWARE_BT6707
  for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){
  	  OldROtype_Sourse[i] = CurrROtype_Sourse[i];
    }
#endif
}

#endif

/**
  * @brief  Мониторинг бита LowBat  
  */
void UPS_LowBatMonitor(void)
{
  static bool isValueRecv = false;
  static uint8_t lowBatOldState = 0;
  static bool flag_alarm_time = false;
  uint8_t lowBatCurrent;

#if defined HARDWARE_BT6707
  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;
#if defined HARDWARE_BT6707
      relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 1);
#endif
    }
    else{
	  SNMP_SendUserTrap(LOW_BAT_NORM);
	  log_event_data(LOG_ALARM_LOW_BAT, "Норма");
	  flUpdateLog = true;
#if defined HARDWARE_BT6707
	  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);
		  log_event_data(LOG_ALARM_LOW_BAT, "Авария");
		  flUpdateLog = true;
#ifdef HARDWARE_BT6707
		  relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 1);
#endif
		}
		else{
		  SNMP_SendUserTrap(LOW_BAT_NORM);
		  log_event_data(LOG_ALARM_LOW_BAT, "Норма");
		  flUpdateLog = true;
#if defined HARDWARE_BT6707
		  relay_setup_log(CurrROtype_Sourse, CHARGE_AKB, 0);
#endif
		}
	}
	else{
		flag_alarm_time = true;
	}
  }
#if defined HARDWARE_BT6707
  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;
	  }
	  lowBatOldState = lowBatCurrent;
  }
  else{
	  if (lowBatOldState){
		  flNonCriticalAlarm = true;
	  }
  }
}

/**
  * @brief  Мониторинг нагрузки 
  */
void UPS_PowerMonitor(void)
{
  float load;
  static uint8_t stateCurrent = HYST_IDLE;
    
  load = UPS.Load;

  /* Отслеживается переход через верхнюю границу */
  if (load > sSettings.sAlarmManager.load_range.high)
  {
	flCriticalAlarm = true;
	UPS.Alarm = (UPS.Alarm & 0xfe) | (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 < (sSettings.sAlarmManager.load_range.high - sSettings.sAlarmManager.load_range.hyst))
  {
	UPS.Alarm = (UPS.Alarm & 0xfe);
    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_TemperatureHighRangeMonitor(void)
{
  float temperature;
  static uint8_t stateCurrent = HYST_IDLE;
    
  temperature = UPS.Temp;

  /* Отслеживается переход через верхнюю границу */
  if (temperature > sSettings.sAlarmManager.Temprature_range.high)
  {
	flCriticalAlarm = true;
	UPS.Alarm = (UPS.Alarm & 0xfd) | (1 << 1);
    if (stateCurrent == HYST_IDLE)
	{
	  stateCurrent = HYST_UP;
      

	  log_event_data(LOG_ALARM_HIGH_TEMP, "Авария");
	  // Отправка трапа о завышении 
	  SNMP_SendUserTrap(BATTERY_HIGH_TEMPERATURE_ALARM);
	  flUpdateLog = true;
	}
  }
  /* Отслеживается нормализация */
  else if (temperature < (sSettings.sAlarmManager.Temprature_range.high - sSettings.sAlarmManager.Temprature_range.hyst))
  {
	  UPS.Alarm = (UPS.Alarm & 0xfd);
    if (stateCurrent == HYST_UP)
	{
	  stateCurrent = HYST_IDLE;
      
	  log_event_data(LOG_ALARM_HIGH_TEMP, "Норма");
	  // Отправка трапа о нормализации 
	  SNMP_SendUserTrap(BATTERY_HIGH_TEMPERATURE_NORM);
	  flUpdateLog = true;
	}
  }
}

/**
  * @brief  Мониторинг температуры по нижней границе
  */
void UPS_TemperatureLowRangeMonitor(void)
{
  float temperature;
  static uint8_t stateCurrent = HYST_IDLE;

  temperature = UPS.Temp;

  /* Отслеживается переход через нипжнюю границу */
  if (temperature < sSettings.sAlarmManager.Temprature_range.low)
  {
	flCriticalAlarm = true;
	UPS.Alarm = (UPS.Alarm & 0xdf) | (1 << 5);
    if (stateCurrent == HYST_IDLE)
	{
	  stateCurrent = HYST_DOWN;


	  log_event_data(LOG_ALARM_LOW_TEMP, "Авария");
	  // Отправка трапа о занижении
	  SNMP_SendUserTrap(BATTERY_LOW_TEMPERATURE_ALARM);
	  flUpdateLog = true;
	}
  }
  /* Отслеживается нормализация */
  else if (temperature > (sSettings.sAlarmManager.Temprature_range.low + sSettings.sAlarmManager.Temprature_range.hyst))
  {
	  UPS.Alarm = (UPS.Alarm & 0xdf);
    if (stateCurrent == HYST_DOWN)
	{
	  stateCurrent = HYST_IDLE;

	  log_event_data(LOG_ALARM_LOW_TEMP, "Норма");
	  // Отправка трапа о нормализации
	  SNMP_SendUserTrap(BATTERY_LOW_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 & 0xfb) | ((connectCurrent^1) << 2);

  if (!isValueRecv) {
    isValueRecv = true;
    connectOldState = connectCurrent;
    if (!connectCurrent){
    	log_event_data(LOG_ALARM_UPS, "Авария");
    	SNMP_SendUserTrap(CONNECT_MONITOR_ALARM);
    	flUpdateLog = true;
    }
    else{
    	log_event_data(LOG_ALARM_UPS, "Норма");
		SNMP_SendUserTrap(CONNECT_MONITOR_NORM);
		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 bool flag_alarm_time = false;
  static uint8_t AKBconnectOldState = 0;
  uint8_t AKBconnectCurrent;

#if defined HARDWARE_BT6707
  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 & 0xf7) | (AKBconnectCurrent << 3);

  if (!isValueRecv) {
    isValueRecv = true;
    AKBconnectOldState = AKBconnectCurrent;
    if (AKBconnectCurrent){
      log_event_data(LOG_ALARM_AKB, "Авария");
	  SNMP_SendUserTrap(BATTERY_CONNECT_ALARM);
	  flUpdateLog = true;
#if defined HARDWARE_BT6707
      relay_setup_log(CurrROtype_Sourse, OFF_AKB, 1);
#endif
    }
    else{
    	log_event_data(LOG_ALARM_AKB, "Норма");
		  SNMP_SendUserTrap(BATTERY_CONNECT_NORM);
		  flUpdateLog = true;
#if	defined HARDWARE_BT6707
		  relay_setup_log(CurrROtype_Sourse, OFF_AKB, 0);
#endif
    }
    return;
  }
  // Значение параметра изменилось
  if (AKBconnectCurrent != AKBconnectOldState)
  {
	if(flag_alarm_time){
		flag_alarm_time = false;
		if (!AKBconnectCurrent){
		  log_event_data(LOG_ALARM_AKB, "Норма");
		  SNMP_SendUserTrap(BATTERY_CONNECT_NORM);
		  flUpdateLog = true;
#if defined HARDWARE_BT6707
		  relay_setup_log(CurrROtype_Sourse, OFF_AKB, 0);
#endif
		}
		else{
		  log_event_data(LOG_ALARM_AKB, "Авария");
		  SNMP_SendUserTrap(BATTERY_CONNECT_ALARM);
		  flUpdateLog = true;
#if defined HARDWARE_BT6707
		  relay_setup_log(CurrROtype_Sourse, OFF_AKB, 1);
#endif
		}
	}
	else{
		flag_alarm_time = true;
	}
  }
#if defined HARDWARE_BT6707
  else{
	  flag_alarm_time = false;
	  if (AKBconnectCurrent)
		  relay_setup_log_change(CurrROtype_Sourse, OldROtype_Sourse, OFF_AKB);
  }

  for(i = 0; i < OUTPUTS_TOTAL_COUNT; i ++){
	  OldROtype_Sourse[i] = CurrROtype_Sourse[i];
  }
#endif

  if(!flag_alarm_time){
	  if (AKBconnectCurrent){
		  flCriticalAlarm = true;
	  }
	  AKBconnectOldState = AKBconnectCurrent;
  }
  else{
	  if (AKBconnectOldState){
		  flCriticalAlarm = true;
	  }
  }
}

#ifdef HARDWARE_BT6709
/**
  * @brief  Мониторинг параметра замены АКБ
  */
void AKB_Change_Monitor(void)
{
  uint32_t data_change = sSettings.UPS_Setting.set_data + (31536000*sSettings.UPS_Setting.life_time);
  TM_RTC_t tmp_data;
  static bool isValueRecv = false;
  static uint8_t status_change_akb = 0;
  uint8_t curr_status_change_akb = 0;
  
  TM_RTC_GetDateTime(&tmp_data, TM_RTC_Format_BIN);
  
  if (tmp_data.unix >= data_change) {
    UPS.Alarm |= (1 << 6);
    curr_status_change_akb = 1;
    flCriticalAlarm = true;
  }
  else {
    UPS.Alarm &= 0xbf;
    curr_status_change_akb = 0;
  }

  if (!isValueRecv) {
    isValueRecv = true;
    status_change_akb = curr_status_change_akb;
    if (curr_status_change_akb){
    	log_event_data(LOG_ALARM_CHANGE_AKB, "Авария");
    	SNMP_SendUserTrap(BATTERY_CHANGE_ALARM);
    	flUpdateLog = true;
    }
    else{
    	log_event_data(LOG_ALARM_CHANGE_AKB, "Норма");
      SNMP_SendUserTrap(BATTERY_CHANGE_MORM);
      flUpdateLog = true;
    }
    return;
  }

  // Значение параметра изменилось
  if (status_change_akb != curr_status_change_akb)
  {
    if (curr_status_change_akb){
      log_event_data(LOG_ALARM_CHANGE_AKB, "Авария");
    	SNMP_SendUserTrap(BATTERY_CHANGE_ALARM);
      flUpdateLog = true;
    } else {
      log_event_data(LOG_ALARM_CHANGE_AKB, "Норма");
      SNMP_SendUserTrap(BATTERY_CHANGE_MORM);
      flUpdateLog = true;
    }
  }
  status_change_akb = curr_status_change_akb;
}
#endif


/********************************* (C) РОТЕК **********************************/
