/********************************* (C) ROTEK ***********************************
 * @module  trap_api
 * @file    trap_api.c
 * @version 1.0.0
 * @date    XX.XX.XXXX
 * $brief   trap_api
 *******************************************************************************
 * @history     Version  Author         Comment
 * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
 *******************************************************************************
 */

#include "stm32f4xx.h"  
#include "trap_api.h"
#include "parameters.h"
#include "settings_api.h"

#include "snmp_trap_pdu2.h"

#include "lwip/apps/snmp.h"
#include "lwip/snmp.h"
#include "lwip/sys.h"

/*
#include "lwip/snmp.h"
#include "lwip/snmp_msg.h"
#include "lwip/snmp_asn1.h"
#include "lwip/snmp_structs.h"
*/
#ifdef PRINTF_STDLIB
#include <stdio.h>
#endif
#ifdef PRINTF_CUSTOM
#include "tinystdio.h"
#endif
#include <string.h>
#include <stdbool.h>

/**
  * @brief  Общая структура настроек
  */
extern SETTINGS_t sSettings;

/**
  * @brief  Пул всех возможных трапов устройства
  */
TRAP_t traps[ALL_TRAPS];

#ifdef HARDWARE_BT6709
const char* name_traps[] =
{
  "",
	"Начало обновл. ПО",
  "Успешное обновл. ПО",
  "Сброс настроек",
  "Перезагрузка",
  "Норм. темп. АКБ по верх. границы",
  "Авария темп. АКБ по верх. границы",
  "Авария на линии",
  "Нормализация линии",
  "Низкий заряд АКБ",
  "Нормализация заряда АКБ",
  "Нагрузка в норме",
  "Авария нагрузки",
  "Авария соединения с ИБП",
  "Норм. соединения с ИБП",
  "Отключение АКБ",
  "Подключение АКБ",
  "Норм. темп. АКБ по ниж. границы",
  "Авария темп. АКБ по ниж. границы",
  "Предупр. о замене АКБ",
  "Норм. предупрежд. о замене АКБ",
};
#endif
/**
  * @brief  Инициализация базы трапов
  * @retval 
  */
void SNMP_InitTrapsBase(void)
{
  /* 1. FWVersionUpdate */ // +
  traps[FW_VERSION_UPDATE].trapId = FW_VERSION_UPDATE;
  traps[FW_VERSION_UPDATE].varbindId = 1;
  traps[FW_VERSION_UPDATE].trapEnable = true;
  traps[FW_VERSION_UPDATE].handle = GetVersionStr; /* FWVersion */
  
  /* 2. FWVersionUpdated */ // +
  traps[FW_VERSION_UPDATED].trapId = FW_VERSION_UPDATED;
  traps[FW_VERSION_UPDATED].varbindId = 1;
  traps[FW_VERSION_UPDATED].trapEnable = true;
  traps[FW_VERSION_UPDATED].handle = GetVersionStr; /* FWVersion */
  
  /* 3. DeviceRestored */ // +
  traps[DEVICE_RESTORED].trapId = DEVICE_RESTORED;
  traps[DEVICE_RESTORED].varbindId = 1;
  traps[DEVICE_RESTORED].trapEnable = true;
  traps[DEVICE_RESTORED].handle = GetVersionStr;//GetRestore; /* RestoreSignal */
  
  /* 4. DeviceRebooted */ // +
  traps[DEVICE_REBOOTED].trapId = DEVICE_REBOOTED;
  traps[DEVICE_REBOOTED].varbindId = 1;
  traps[DEVICE_REBOOTED].trapEnable = true;
  traps[DEVICE_REBOOTED].handle = GetVersionStr;//GetReboot; /* RebootSignal */
  
#ifndef HARDWARE_BT6709
  /* 5. DI0Norm */ // +
   traps[DI0_NORM].trapId = DI0_NORM;
#ifdef HARDWARE_BT6703
  traps[DI0_NORM].varbindId = 9;
#elif defined HARDWARE_BT6707
  traps[DI0_NORM].varbindId = 10;
#endif
   traps[DI0_NORM].trapEnable = true;
   traps[DI0_NORM].handle = GetDIN0StatusStr; /* State DIN */

   /* 6. DI0Alarm */ // +
   traps[DI0_ALARM].trapId = DI0_ALARM;
#ifdef HARDWARE_BT6703
  traps[DI0_ALARM].varbindId = 9;
#elif defined HARDWARE_BT6707
  traps[DI0_ALARM].varbindId = 10;
#endif
   traps[DI0_ALARM].trapEnable = true;
   traps[DI0_ALARM].handle = GetDIN0StatusStr; /* State DIN */

   /* 7. DO0Toggle */ // +
    traps[DO0_TOGGLED].trapId = DO0_TOGGLED;
    traps[DO0_TOGGLED].varbindId = 5;
    traps[DO0_TOGGLED].trapEnable = true;
    traps[DO0_TOGGLED].handle = GetDOUT0StatusStr; /* State DO0 */

    /* 8. DO1Toggle */ // +
    traps[DO1_TOGGLED].trapId = DO1_TOGGLED;
    traps[DO1_TOGGLED].varbindId = 6;
    traps[DO1_TOGGLED].trapEnable = true;
    traps[DO1_TOGGLED].handle = GetDOUT1StatusStr; /* State DO1 */

#if	defined HARDWARE_BT6707
    /* 8. DO1Toggle */ // +
    traps[DO2_TOGGLED].trapId = DO2_TOGGLED;
    traps[DO2_TOGGLED].varbindId = 7;
    traps[DO2_TOGGLED].trapEnable = true;
    traps[DO2_TOGGLED].handle = GetDOUT2StatusStr; /* State DO2 */
#endif
#endif

  /* 9. BatteryTemperatureNorm */ // +
  traps[BATTERY_HIGH_TEMPERATURE_NORM].trapId = BATTERY_HIGH_TEMPERATURE_NORM;
#ifdef HARDWARE_BT6703
  traps[BATTERY_HIGH_TEMPERATURE_NORM].varbindId = 10;
#elif defined HARDWARE_BT6707
  traps[BATTERY_HIGH_TEMPERATURE_NORM].varbindId = 11;
#elif defined HARDWARE_BT6709
  traps[BATTERY_HIGH_TEMPERATURE_NORM].varbindId = 9;
#endif
  traps[BATTERY_HIGH_TEMPERATURE_NORM].trapEnable = true;
  traps[BATTERY_HIGH_TEMPERATURE_NORM].handle = GetInternalTempStr; /* BatteryTemperature */
  
  /* 10. BatteryTemperatureAlarm */ // +
  traps[BATTERY_HIGH_TEMPERATURE_ALARM].trapId = BATTERY_HIGH_TEMPERATURE_ALARM;
#ifdef HARDWARE_BT6703
  traps[BATTERY_HIGH_TEMPERATURE_ALARM].varbindId = 10;
#elif defined HARDWARE_BT6707
  traps[BATTERY_HIGH_TEMPERATURE_ALARM].varbindId = 11;
#elif defined HARDWARE_BT608
  traps[BATTERY_HIGH_TEMPERATURE_ALARM].varbindId = 9;
#endif
  traps[BATTERY_HIGH_TEMPERATURE_ALARM].trapEnable = true;
  traps[BATTERY_HIGH_TEMPERATURE_ALARM].handle = GetInternalTempStr; /* BatteryTemperature */
  
  /* 11. LineAlarm */ // +
  traps[LINE_ALARM].trapId = LINE_ALARM;
#ifdef HARDWARE_BT6703
  traps[LINE_ALARM].varbindId = 12;
#elif defined HARDWARE_BT6707
  traps[LINE_ALARM].varbindId = 13;
#elif defined HARDWARE_BT6709
  traps[LINE_ALARM].varbindId = 11;
#endif
  traps[LINE_ALARM].trapEnable = true;
  traps[LINE_ALARM].handle = GetInputVoltageStr; /* LineAlarm */
  
  /* 12. LineNorm */ // +
  traps[LINE_NORM].trapId = LINE_NORM;
#ifdef HARDWARE_BT6703
  traps[LINE_NORM].varbindId = 12;
#elif defined HARDWARE_BT6707
  traps[LINE_NORM].varbindId = 13;
#elif defined HARDWARE_BT6709
  traps[LINE_NORM].varbindId = 11;
#endif
  traps[LINE_NORM].trapEnable = true;
  traps[LINE_NORM].handle = GetInputVoltageStr; /* LineNorm */
  
  /* 13. LowBatAlarm */ // +
  traps[LOW_BAT_ALARM].trapId = LOW_BAT_ALARM;
#ifdef HARDWARE_BT6703
  traps[LOW_BAT_ALARM].varbindId = 15;
#elif defined HARDWARE_BT6707
  traps[LOW_BAT_ALARM].varbindId = 16;
#elif defined HARDWARE_BT6709
  traps[LOW_BAT_ALARM].varbindId = 14;
#endif
  traps[LOW_BAT_ALARM].trapEnable = true;
  traps[LOW_BAT_ALARM].handle = GetBatCapacityStr; /* LowBatAlarm */
  
  /* 14. LowBatNorm */ // +
  traps[LOW_BAT_NORM].trapId = LOW_BAT_NORM;
#ifdef HARDWARE_BT6703
  traps[LOW_BAT_NORM].varbindId = 15;
#elif defined HARDWARE_BT6707
  traps[LOW_BAT_NORM].varbindId = 16;
#elif defined HARDWARE_BT6709
  traps[LOW_BAT_NORM].varbindId = 14;
#endif
  traps[LOW_BAT_NORM].trapEnable = true;
  traps[LOW_BAT_NORM].handle = GetBatCapacityStr; /* LowBatNorm */
  
  /* 15. PowerAlarm */ // +
  traps[POWER_ALARM].trapId = POWER_ALARM;
#ifdef HARDWARE_BT6703
  traps[POWER_ALARM].varbindId = 14;
#elif defined HARDWARE_BT6707
  traps[POWER_ALARM].varbindId = 15;
#elif defined HARDWARE_BT6709
  traps[POWER_ALARM].varbindId = 13;
#endif
  traps[POWER_ALARM].trapEnable = true;
  traps[POWER_ALARM].handle = GetPowerStr; /* PowerAlarm */
  
  /* 16. PowerNorm */ // +
  traps[POWER_NORM].trapId = POWER_NORM;
#ifdef HARDWARE_BT6703
  traps[POWER_NORM].varbindId = 14;
#elif defined HARDWARE_BT6707
  traps[POWER_NORM].varbindId = 15;
#elif defined HARDWARE_BT6709
  traps[POWER_NORM].varbindId = 13;
#endif
  traps[POWER_NORM].trapEnable = true;
  traps[POWER_NORM].handle = GetPowerStr; /* PowerNorm */
  
  /* 17. ConnectMonitorAlarm */ //
  traps[CONNECT_MONITOR_ALARM].trapId = CONNECT_MONITOR_ALARM;
#ifdef HARDWARE_BT6703
  traps[CONNECT_MONITOR_ALARM].varbindId = 17;
#elif defined HARDWARE_BT6707
  traps[CONNECT_MONITOR_ALARM].varbindId = 18;
#elif defined HARDWARE_BT6709
  traps[CONNECT_MONITOR_ALARM].varbindId = 16;
#endif
  traps[CONNECT_MONITOR_ALARM].trapEnable = true;
  traps[CONNECT_MONITOR_ALARM].handle = GetConnectMonitorStr;//GetConnectMonitorStr; /* ConnectMonitor */
  
  /* 18. ConnectMonitorNorm */ //
  traps[CONNECT_MONITOR_NORM].trapId = CONNECT_MONITOR_NORM;
#ifdef HARDWARE_BT6703
  traps[CONNECT_MONITOR_NORM].varbindId = 17;
#elif defined HARDWARE_BT6707
  traps[CONNECT_MONITOR_NORM].varbindId = 18;
#elif defined HARDWARE_BT6709
  traps[CONNECT_MONITOR_NORM].varbindId = 16;
#endif
  traps[CONNECT_MONITOR_NORM].trapEnable = true;
  traps[CONNECT_MONITOR_NORM].handle = GetConnectMonitorStr;//GetConnectMonitorStr; /* ConnectMonitor */

  /* 19. BatteryConnectAlarm */ // +
  traps[BATTERY_CONNECT_ALARM].trapId = BATTERY_CONNECT_ALARM;
#ifdef HARDWARE_BT6703
  traps[BATTERY_CONNECT_ALARM].varbindId = 15;
#elif defined HARDWARE_BT6707
  traps[BATTERY_CONNECT_ALARM].varbindId = 16;
#elif defined HARDWARE_BT6709
  traps[BATTERY_CONNECT_ALARM].varbindId = 14;
#endif
  traps[BATTERY_CONNECT_ALARM].trapEnable = true;
  traps[BATTERY_CONNECT_ALARM].handle = GetBatCapacityStr; /* LowBatAlarm */

  /* 20. BatteryConnectNorm */ // +
  traps[BATTERY_CONNECT_NORM].trapId = BATTERY_CONNECT_NORM;
#ifdef HARDWARE_BT6703
  traps[BATTERY_CONNECT_NORM].varbindId = 15;
#elif defined HARDWARE_BT6707
  traps[BATTERY_CONNECT_NORM].varbindId = 16;
#elif defined HARDWARE_BT6709
  traps[BATTERY_CONNECT_NORM].varbindId = 14;
#endif
  traps[BATTERY_CONNECT_NORM].trapEnable = true;
  traps[BATTERY_CONNECT_NORM].handle = GetBatCapacityStr; /* LowBatNorm */

  /* 21. BatteryTemperatureNorm */ // +
  traps[BATTERY_LOW_TEMPERATURE_NORM].trapId = BATTERY_LOW_TEMPERATURE_NORM;
#ifdef HARDWARE_BT6703
  traps[BATTERY_LOW_TEMPERATURE_NORM].varbindId = 10;
#elif defined HARDWARE_BT6707
  traps[BATTERY_HIGH_TEMPERATURE_NORM].varbindId = 11;
#elif defined HARDWARE_BT6709
  traps[BATTERY_HIGH_TEMPERATURE_NORM].varbindId = 9;
#endif
  traps[BATTERY_LOW_TEMPERATURE_NORM].trapEnable = true;
  traps[BATTERY_LOW_TEMPERATURE_NORM].handle = GetInternalTempStr; /* BatteryTemperature */

  /* 22. BatteryTemperatureAlarm */ // +
  traps[BATTERY_LOW_TEMPERATURE_ALARM].trapId = BATTERY_HIGH_TEMPERATURE_ALARM;
#ifdef HARDWARE_BT6703
  traps[BATTERY_LOW_TEMPERATURE_ALARM].varbindId = 10;
#elif defined HARDWARE_BT6707
  traps[BATTERY_LOW_TEMPERATURE_ALARM].varbindId = 11;
#elif defined HARDWARE_BT609
  traps[BATTERY_LOW_TEMPERATURE_ALARM].varbindId = 9;
#endif
  traps[BATTERY_LOW_TEMPERATURE_ALARM].trapEnable = true;
  traps[BATTERY_LOW_TEMPERATURE_ALARM].handle = GetInternalTempStr; /* BatteryTemperature */

#ifdef HARDWARE_BT6709
 /* 23. AKBChangeAlarm */ // +
    traps[BATTERY_CHANGE_ALARM].trapId = BATTERY_CHANGE_ALARM;
    traps[BATTERY_CHANGE_ALARM].varbindId = 49;
    traps[BATTERY_CHANGE_ALARM].trapEnable = true;
    traps[BATTERY_CHANGE_ALARM].handle = GetDataNextChangeAKBStr; /* data next change AKB */

 /* 24. AKBChangeNorm */ // +
    traps[BATTERY_CHANGE_MORM].trapId = BATTERY_CHANGE_MORM;
    traps[BATTERY_CHANGE_MORM].varbindId = 49;
    traps[BATTERY_CHANGE_MORM].trapEnable = true;
    traps[BATTERY_CHANGE_MORM].handle = GetDataNextChangeAKBStr; /* data next change AKB */
#endif
}

/**
  * @brief  Отправка обычного трапа с сообщением, зарегистрированного в базе.
  * @retval 
  */
bool SNMP_SendMessageTrap(TRAP_t trap, char* str, uint8_t len)
{
/*  
  const uint8_t maxMsgLen = 30;
  char msg[30];
  struct snmp_varbind *vb;
  struct snmp_obj_id trapObjId = {11, {1, 3, 6, 1, 4, 1, 41752, 911, 3, 2, 1}};

  if (len <= maxMsgLen)
  {
    trapObjId.id[trapObjId.len - 1] = trap.trapId;
	
	strcpy(msg, str);
	
    vb = snmp_varbind_alloc(&trapObjId, SNMP_ASN1_OPAQUE, strlen(msg));
	
	vb->value = msg;
	            
    trap_msg.outvb.head = vb;
    trap_msg.outvb.tail = vb;
    trap_msg.outvb.count = 1;
	
    snmp_send_trap(SNMP_GENTRAP_ENTERPRISESPC, &trapObjId, 0);
     
    trap_msg.outvb.head = NULL;
    trap_msg.outvb.tail = NULL;
    trap_msg.outvb.count = 0;
     
	snmp_varbind_list_free(&trap_msg.outvb);
    snmp_varbind_free(vb);  
	
	return true;
  }
  else
	return false;
*/  
}

struct snmp_varbind vb1, vb2, vb;
char msg[50];
uint32_t snmp_time = 0;

struct snmp_obj_id  mib2_base_oid_systime ={ 9, { 1, 3, 6, 1, 2, 1, 1, 3, 0 }};
struct snmp_obj_id  trap_oid = {11, {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0}};
#ifdef HARDWARE_BT6703
struct snmp_obj_id trapObjId = {11, {1, 3, 6, 1, 4, 1, 41752, 911, 6, 2, 1}};
struct snmp_obj_id varObjId  = {11, {1, 3, 6, 1, 4, 1, 41752, 911, 6, 1, 1}};
#elif defined HARDWARE_BT6707
struct snmp_obj_id trapObjId = {11, {1, 3, 6, 1, 4, 1, 41752, 911, 7, 2, 1}};
struct snmp_obj_id varObjId  = {11, {1, 3, 6, 1, 4, 1, 41752, 911, 7, 1, 1}};
#elif defined HARDWARE_BT6709
struct snmp_obj_id trapObjId = {11, {1, 3, 6, 1, 4, 1, 41752, 911, 8, 2, 1}};
struct snmp_obj_id varObjId  = {11, {1, 3, 6, 1, 4, 1, 41752, 911, 8, 1, 1}};
#endif
/**
  * @brief  Отправка трапа с переменной, зарегистрированного в базе.
  * @retval 
  */
bool SNMP_SendVarbindTrap(TRAP_t *trap)
{
  uint8_t len = 0;
  
  memset(&vb1, 0, sizeof(struct snmp_varbind));
  memset(&vb2, 0, sizeof(struct snmp_varbind));
  memset(&vb, 0, sizeof(struct snmp_varbind));

  trapObjId.id[trapObjId.len - 1] = trap->trapId;
  varObjId.id[varObjId.len - 1] = trap->varbindId;
  
  trap->handle(msg, &len);
  
  vb.oid = mib2_base_oid_systime;
  vb.type = SNMP_ASN1_TYPE_TIMETICKS;
  MIB2_COPY_SYSUPTIME_TO(&snmp_time);
  vb.value = &snmp_time;
  vb.value_len = sizeof(uint32_t);
  vb.next = &vb1;
  vb.prev = NULL;

  vb1.oid = trap_oid;
  vb1.type = SNMP_ASN1_TYPE_OBJECT_ID;
  vb1.value = trapObjId.id;
  vb1.value_len = 4*trapObjId.len;
  vb1.next = &vb2;
  vb1.prev = &vb;

  vb2.oid = varObjId;
  vb2.type = SNMP_ASN1_TYPE_OCTET_STRING;
  vb2.value = msg;
  vb2.value_len = len;
  vb2.next = NULL;
  vb2.prev = &vb1;
  
  snmp_send_trap_pduv2(&vb);
  //snmp_send_trap(&trapObjId, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, 0, &vb);
  
  return true;
}  


/********************************* (C) ROTEK **********************************/
