#include "stm32f4xx.h"  

#include "private_mib.h"
#include "lwip/snmp.h"
#include "lwip/snmp_msg.h"
#include "lwip/snmp_asn1.h"
#include "lwip/snmp_structs.h"

#include "settings_api.h"
#include "parameters.h"
#include "web_params_api.h"
#include "snmp_api.h"
#include "trap_api.h"
#include "common_config.h"
#include "log.h"
#include "megatec.h"

#include "FreeRTOS.h"

#ifdef PRINTF_STDLIB
#include <stdio.h>
#endif
#ifdef PRINTF_CUSTOM
#include "tinystdio.h"
#endif
#include <stdlib.h>

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

extern float TimeParamFloat;

extern void ocstrncpy(u8_t *dst, u8_t *src, u16_t n);

char paramStr[255];
uint8_t paramLength = 0;
uint32_t paramInt = 0;

static void system_get_object_def_ee( u8_t ident_len, s32_t *ident, struct obj_def *od );
static void system_get_value_ee(struct obj_def *od, u16_t len, void *value);
static u8_t system_set_test_ee(struct obj_def *od, u16_t len, void *value);
static void system_set_value_ee(struct obj_def *od, u16_t len, void *value);

/* Функции для узла Signals */
static void signals_get_object_def (u8_t ident_len, s32_t *ident, struct obj_def *od);
static void signals_get_value (struct obj_def *od, u16_t len, void *value);
static u8_t signals_set_test (struct obj_def *od, u16_t len, void *value);
static void signals_set_value (struct obj_def *od, u16_t len, void *value);

/*------------------------------------------------------------------------------
 Описание узлов 
------------------------------------------------------------------------------*/
/* узел SYSTEM (операции с EEPROM) */
/*             0 1 2 3 4 5 6 */
/* system .1.3.6.1.2.1.1 */
const mib_scalar_node system_scalar_ee = {
  &system_get_object_def_ee,
  &system_get_value_ee,
  &system_set_test_ee,
  &system_set_value_ee,
  MIB_NODE_SC,
  0
};

// переменные узла SIGNALS ------------------------------------------

const mib_scalar_node signals_var = 
{
  &signals_get_object_def,
  &signals_get_value,
  &signals_set_test,
  &signals_set_value,
  MIB_NODE_SC,
  0
};

// узел SIGNALS -----------------------------------------------------

const s32_t signals_ids[18] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };

struct mib_node* const signals_nodes[18] =
{
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
  (struct mib_node* const)&signals_var,
};

const struct mib_array_node signals = 
{
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  18,
  signals_ids,
  signals_nodes
};


// узел BT-6701 ------------------------------------------------------------

const s32_t bt6701_ids[1] = { 1 };

struct mib_node* const bt6701_nodes[1] = 
{
  (struct mib_node* const)&signals,
};

const struct mib_array_node bt6701 = 
{
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  1,
  bt6701_ids,
  bt6701_nodes
};

// узел swt ------------------------------------------------------------
const s32_t swt_ids[1] = { 
3
};

struct mib_node* const swt_nodes[1] = 
{
  (struct mib_node* const)&bt6701,
};

const struct mib_array_node swt = 
{
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  1,
  swt_ids,
  swt_nodes
};

// узел ROTEK ------------------------------------------------------------

const s32_t rotek_ids[1] = { 911 };

struct mib_node* const rotek_nodes[1] = 
{
  (struct mib_node* const)&swt,
};

const struct mib_array_node rotek = 
{
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  1,
  rotek_ids,
  rotek_nodes
};

// узел ENTERPRISES -------------------------------------------------------

const s32_t enterprises_ids[1] = { 41752 };

struct mib_node* const enterprises_nodes[1] = 
{
  (struct mib_node* const)&rotek
};

const struct mib_array_node enterprises = 
{
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  1,
  enterprises_ids,
  enterprises_nodes
};

// узел PRIVATE -----------------------------------------------------------

const s32_t mib_private_ids[1] = { 1 };

struct mib_node* const mib_pivate_nodes[1] = 
{
  (struct mib_node* const)&enterprises
};

const struct mib_array_node mib_private = 
{
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  1,
  mib_private_ids,
  mib_pivate_nodes
};


/*------------------------------------------------------------------------------
 Функции
------------------------------------------------------------------------------*/

// Функции для узла SIGNALS

/**-----------------------------------------------------------------------------
 \fn     static void signals_get_object_def (u8_t ident_len, s32_t *ident, struct obj_def *od)
 \brief  функция получения свойств переменных узла Identification
 \param  ident_len - the address length. длина адреса
 \param  ident - points to objectname.0 (object id trailer) 
 \param  od - points to object definition. указатель на описание переменной
 \return нет
------------------------------------------------------------------------------*/
static void signals_get_object_def (u8_t ident_len, s32_t *ident, struct obj_def *od)
{
  u8_t id;
  
  /* return to object name, adding index depth (1) */
  ident_len += 1;
  ident -= 1;
  if (ident_len == 2)
  {
    od->id_inst_len = ident_len;
    od->id_inst_ptr = ident;

    id = ident[0];
    
    switch (id)
    {
      case 1: /* FWVersion */
		GetVersionStr(paramStr, &paramLength);
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
        break;
	 case 2: /* RestoreSignal */

        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_WRITE_ONLY;
        od->asn_type = SNMP_ASN1_INTEG;
        od->v_len = sizeof(s32_t);
        break;
	  case 3: /* RebootSignal */

		od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_WRITE_ONLY;
        od->asn_type = SNMP_ASN1_INTEG;
        od->v_len = sizeof(s32_t);
        break;
	  case 4: /* UPSModel*/
		GetUPSModelStr(paramStr, &paramLength);
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
        break;
	  case 5: /* DO1*/
		GetDOUTStatusStr(paramStr, &paramLength, 0);
		od->instance = MIB_OBJECT_SCALAR;
		od->access = MIB_OBJECT_READ_WRITE;
		od->asn_type = SNMP_ASN1_OC_STR;
		od->v_len = paramLength;
		break;
	  case 6: /* DO2*/
		GetDOUTStatusStr(paramStr, &paramLength, 1);
		od->instance = MIB_OBJECT_SCALAR;
		od->access = MIB_OBJECT_READ_WRITE;
		od->asn_type = SNMP_ASN1_OC_STR;
		od->v_len = paramLength;
		break;
	  case 7: /* BatTest*/

		od->instance = MIB_OBJECT_SCALAR;
		od->access = MIB_OBJECT_WRITE_ONLY;
		od->asn_type = SNMP_ASN1_INTEG;
		od->v_len = sizeof(s32_t);
		break;
	  case 8: /* Shutdown UPS*/

		od->instance = MIB_OBJECT_SCALAR;
		od->access = MIB_OBJECT_WRITE_ONLY;
		od->asn_type = SNMP_ASN1_OC_STR;
		od->v_len = paramLength;
		break;
	  case 9: /* DIO*/
		GetDINStatusStr(paramStr, &paramLength, 0);
		od->instance = MIB_OBJECT_SCALAR;
		od->access = MIB_OBJECT_READ_ONLY;
		od->asn_type = SNMP_ASN1_OC_STR;
		od->v_len = paramLength;
		break;
	  case 10: /* IntTemp */
		GetInternalTempStr(paramStr, &paramLength);
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
        break;
	  case 11: /* InFreq */
		GetInputFreqStr(paramStr, &paramLength);
		od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
		break;
	  case 12: /* InVoltVAC */
		GetInputVoltageStr(paramStr, &paramLength);
		od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
		break;
	  case 13: /* OutVoltVAC */
		GetOutputVoltageStr(paramStr, &paramLength);
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
        break;
	  case 14: /* Power */
		GetPowerStr(paramStr, &paramLength);
		od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
		break;
	  case 15: /* BatCap */
		GetBatCapacityStr(paramStr, &paramLength);
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
        break;
	  case 16: /* BatTime */
		GetRuntimeStr(paramStr, &paramLength);
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
        break;	
      case 17: /* ConnectMonitor */
		GetConnectMonitorStr(paramStr, &paramLength);
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
        break;
      case 18: /* Alarms */
    	GetAlarmStr(paramStr, &paramLength);
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = SNMP_ASN1_OC_STR;
        od->v_len = paramLength;
        break;
      default:
        //LWIP_DEBUGF(SNMP_MIB_DEBUG,("planar_get_object_def: no such object\n"));
        od->instance = MIB_OBJECT_NONE;
        break;
    };
  }
  else
  {
    LWIP_DEBUGF(SNMP_MIB_DEBUG,("planar_get_object_def: no scalar\n"));
    od->instance = MIB_OBJECT_NONE;
  }
}

/**-----------------------------------------------------------------------------
 \fn     static void Identification_get_value(struct obj_def *od, u16_t len, void *value)
 \brief  функция получения значения переменных узла Identification
 \param  obj_def - указатель на описание переменной
 \param  len - длина переменной в байтах 
 \param  value - указатель на значение переменной
 \return нет
------------------------------------------------------------------------------*/
static void signals_get_value (struct obj_def *od, u16_t len, void *value)
{
  u8_t id;
  
  id = od->id_inst_ptr[0];
  
  switch (id)
  {
    case 1: /* FWVersion */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
	case 2: /* RestoreSignal */
	  *((s32_t*)value) = 0;
      break;
	case 3: /* RebootSignal */
	  *((s32_t*)value) = 0;
      break;
	case 4: /* UPSModel */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
	  break;
	case 5: /* DO1 */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
	  break;
	case 6: /* DO2 */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
	  break;
	case 7: /* BatTest */
	  *((s32_t*)value) = 0;
	  break;
	case 8: /* Shutdown UPS */
	  *((s32_t*)value) = 0;
	  break;
	case 9: /* DIO */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
	  break;
	case 10: /* IntTemp */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;  
	case 11: /* InFreq */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
	case 12: /* InVoltVAC */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
	case 13: /* OutVoltVAC */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
	case 14: /* Power */
      ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
	case 15: /* BatCap */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
    case 16: /* BatTime */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
    case 17: /* ConnectMonitor */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
    case 18: /* Alarms */
	  ocstrncpy((u8_t*)value, (u8_t*)paramStr, len);
      break;
    default :
	  break;
  };
}

/**-----------------------------------------------------------------------------
 \fn     static void Identification_set_value (struct obj_def *od, u16_t len, void *value)
 \brief  функция записи значений переменных узла Identification
 \param  obj_def - указатель на описание переменной
 \param  len - длина переменной в байтах 
 \param  value - указатель на значение переменной
 \return нет
------------------------------------------------------------------------------*/
static void signals_set_value (struct obj_def *od, u16_t len, void *value)
{
  u8_t id;
  uint32_t val;
  char *val_string;
  char str[20];
  int8_t res = 0;

  memset(str, 0, 20);
  
  id = od->id_inst_ptr[0];
  
  switch (id)
  {
    case 2: /* RestoreSignal */
      val = *((s32_t*)value);
      if (val == 1) {
        HTTP_ResetSettings();
      }
    break;
    case 3: /* RebootSignal */
      val = *((s32_t*)value);
      if (val == 1)
        HTTP_StartResetTask(false);
    break;
	case 5: /* DO1 */
	  if(sSettings.sInOuts.ro_type_source[0] == SNMP_SET){
		  val_string = (char*)value;
		  SetROStr(val_string, 0);
		  if(val_string[0] == 0x31)
			  strcat(str, "Замкнуто");
		  else
			  strcat(str, "Разомкнуто");
		  SNMP_SendUserTrap(DO0_TOGGLED);
		  log_event_data(LOG_DO0_STATE, str);
	  }
	  break;
	case 6: /* DO2 */
	  if(sSettings.sInOuts.ro_type_source[1] == SNMP_SET){
		  val_string = (char*)value;
		  SetROStr(val_string, 1);
		  if(val_string[0] == 0x31)
			  strcat(str, "Замкнуто");
		  else
			  strcat(str, "Разомкнуто");
		  SNMP_SendUserTrap(DO1_TOGGLED);
		  log_event_data(LOG_DO1_STATE, str);
	  }
	  break;
	case 7: /* BatTest */
	  val =*((s32_t*)value);
	  if(val == 0){
		  res = ups_metac_service_pdu(ups_cancel_test);
		  if(res == 1){
			  log_event_data(LOG_TEST_UPS, "Администратор(Останов)");
		  }
	  }
	  else if(val > 0 && val < 100){
		  TimeParam = val;
		  res = ups_metac_service_pdu(ups_test_time);
		  if(res == 1){
			  log_event_data(LOG_TEST_UPS, "Администратор (Запущен)");
		  }
	  }
	  else if(val == 100){
		  res = ups_metac_service_pdu(ups_test_10sec);
		  if(res == 1){
			  log_event_data(LOG_TEST_UPS, "Администратор (Запущен)");
		  }
	  }
	  else if(val == 999){
		  res = ups_metac_service_pdu(ups_test_low_bat);
		  if(res == 1){
			  log_event_data(LOG_TEST_UPS, "Администратор (Запущен)");
		  }
	  }
	  break;
	case 8: /* Shutdown UPS */
	  val_string = (char*)value;
	  float shtdn_val = atof(val_string);
	  if(shtdn_val == 0){
		  res = ups_metac_service_pdu(ups_cancel_shut_down);
		 	if(res == 1)
		 		log_event_data(LOG_SHUTDOWN_UPS, "Администратор(Останов)");
	  }
	  else{
		TimeParamFloat = shtdn_val;
		res = ups_metac_service_pdu(ups_shutdown);
		if(res == 1)
			log_event_data(LOG_SHUTDOWN_UPS, "Администратор");
	  }
	  break;
    default :
    break;
  };
  
}

/**-----------------------------------------------------------------------------
 \fn     static u8_t Identification_set_test (struct obj_def *od, u16_t len, void *value)
 \brief  функция проверки записываемых значений переменных узла Identification
 \param  obj_def - указатель на описание переменной
 \param  len - длина переменной в байтах 
 \param  value - указатель на значение переменной
 \return 0 - некорректное значение
         1 - корректное значение
------------------------------------------------------------------------------*/
static u8_t signals_set_test (struct obj_def *od, u16_t len, void *value)
{
  u8_t id, set_ok;
  char *val_string;
  int32_t val;

  LWIP_UNUSED_ARG(value);
  set_ok = 0;
  id = od->id_inst_ptr[0];
  
  switch (id)
  {
    case 2: 
      if ( len == sizeof(s32_t) )
      {
        set_ok = 1;
      }
      break;  
	  
    case 3: 
      if ( len == sizeof(s32_t) )
      {
        set_ok = 1;
      }
      break; 
	case 5: /* DO1 */
		if ( len <= 1 )
	    {
		   val_string = (char*)value;
		   if(atoi(val_string) <= 1){
			   if(sSettings.sInOuts.ro_type_source[0] == SNMP_SET)
				   set_ok = 1;
		   }
	    }
	  break;
	case 6: /* DO2 */
		if ( len <= 1 )
		{
		   val_string = (char*)value;
		   if(atoi(val_string) <= 1){
			   if(sSettings.sInOuts.ro_type_source[1] == SNMP_SET)
				   set_ok = 1;
		   }
		}
	  break;
	case 7: /* BatTest */
	   val = *((s32_t*)value);
	   if((val >= 0 && val <= 100) || val == 999){
		   set_ok = 1;
	   }
	  break;
	case 8: /* Shutdown UPS */
		if ( len <= 3 )
		{
		   val_string = (char*)value;
		   if(atof(val_string) <= 10){
			set_ok = 1;
		   }
		}
	  break;
  };
  
  return set_ok;
}

/**
 * Returns systems object definitions (eeprom).
 *
 * @param ident_len the address length (2)
 * @param ident points to objectname.0 (object id trailer)
 * @param od points to object definition.
 */
static void
system_get_object_def_ee(u8_t ident_len, s32_t *ident, struct obj_def *od)
{
  u8_t id;

  /* return to object name, adding index depth (1) */
  ident_len += 1;
  ident -= 1;
  if (ident_len == 2)
  {
    od->id_inst_len = ident_len;
    od->id_inst_ptr = ident;

    id = ident[0];
    //LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def_ee system.%"U16_F".0\n",(u16_t)id));
    switch (id)
    {
      case 4: /* sysContact */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = 1 /*GetSnmpStringLen(SNMP_SYSCONTACT_TYPE)*/;
        break;
      case 5: /* sysName */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = 1 /*GetSnmpStringLen(SNMP_SYSNAME_TYPE)*/;
        break;
      case 6: /* sysLocation */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = 1 /*GetSnmpStringLen(SNMP_SYSLOCATION_TYPE)*/;
        break;
      default:
        //LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def_ee: no such object\n"));
        od->instance = MIB_OBJECT_NONE;
        break;
    };
  }
  else
  {
    LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def_ee: no scalar\n"));
    od->instance = MIB_OBJECT_NONE;
  }
}
// ----------------------------------------------------------------------------


/**
 * Returns system object value.
 *
 * @param ident_len the address length (2)
 * @param ident points to objectname.0 (object id trailer)
 * @param len return value space (in bytes)
 * @param value points to (varbind) space to copy value into.
 */
static void
system_get_value_ee(struct obj_def *od, u16_t len, void *value)
{
  u8_t id;

  id = od->id_inst_ptr[0];
  switch (id)
  {
    case 4: /* sysContact */
      //GetSnmpString(SNMP_SYSCONTACT_TYPE, value, len );
      break;
    case 5: /* sysName */
      //GetSnmpString(SNMP_SYSNAME_TYPE, value, len );
      break;
    case 6: /* sysLocation */
      //GetSnmpString(SNMP_SYSLOCATION_TYPE, value, len );
      break;
  };
}
// ----------------------------------------------------------------------------


static u8_t
system_set_test_ee(struct obj_def *od, u16_t len, void *value)
{
  u8_t id, set_ok;

  LWIP_UNUSED_ARG(value);
  set_ok = 0;
  id = od->id_inst_ptr[0];
  switch (id)
  {
    case 4: /* sysContact */
      if ( len <= 255 )
      {
        set_ok = 1;
      }
      break;
    case 5: /* sysName */
      if ( len <= 255 )
      {
        set_ok = 1;
      }
      break;
    case 6: /* sysLocation */
      if ( len <= 255 )
      {
        set_ok = 1;
      }
      break;
  };
  return set_ok;
}
// ----------------------------------------------------------------------------


static void
system_set_value_ee(struct obj_def *od, u16_t len, void *value)
{
  u8_t id;

  id = od->id_inst_ptr[0];
  switch (id)
  {
    case 4: /* sysContact */
      //SetSnmpString(SNMP_SYSCONTACT_TYPE, value, len );
      //*syscontact_len_ptr = len;
    break;
    case 5: /* sysName */
      //SetSnmpString(SNMP_SYSNAME_TYPE, value, len );
      //*sysname_len_ptr = len;
    break;
    case 6: /* sysLocation */
      //SetSnmpString(SNMP_SYSLOCATION_TYPE, value, len );
      //*syslocation_len_ptr = len;
    break;
  };
}
// ----------------------------------------------------------------------------

/**-----------------------------------------------------------------------------
 \fn     err_t snmp_send_trap_ex (s8_t generic_trap, 
                         struct snmp_obj_id *eoid, 
                         s32_t specific_trap, 
                         struct snmp_obj_id* varbinds, 
                         u8_t varbinds_num)
 \brief  функция посылки трапа с возможностью пристыковывать переменные
 \param  generic_trap  - код трапа
 \param  eoid          - указатель на enterprise object identifier
 \param  specific_trap - used for enterprise traps when generic_trap == 6
 \param  varbinds      - указатель на переменные
 \param  varbinds_num  - число переменных
 \return код ошибки
------------------------------------------------------------------------------*/
err_t snmp_send_trap_ex (s8_t generic_trap, 
                         struct snmp_obj_id *eoid, 
                         s32_t specific_trap, 
                         struct snmp_obj_id* varbinds, 
                         u8_t varbinds_num)
{
	uint8_t bSnmpActive = 1;
	
	struct snmp_varbind** vb_list;
	struct mib_node* node;
	struct obj_def obj;
	err_t tResult;
	s32_t* VarNum;
    struct snmp_name_ptr np;
	

	/* SNMP не готово - ничего не отправляем */
	if( !bSnmpActive )
	{
		return ERR_MEM;
	}
	
	/* создаем таблицу указателей переменных */
	pvPortMalloc( varbinds_num * sizeof(struct snmp_varbind*) );
	/*
	if(vb_list == NULL)
	{
		return ERR_MEM;
	}
	*/
	/* создаем сами переменные */
	for(u8_t i = 0; i < varbinds_num; i++)
	{
		/* ищем узел в дереве*/
		node = snmp_search_tree( (struct mib_node*)&internet, varbinds[i].len - 3, 
										 &varbinds[i].id[4], &np );
		
		//node = snmp_search_tree( (struct mib_node*)&internet, varbinds[i].len, 
		//								 &varbinds[i].id[0], &np );
		
		if(node != NULL)
		{
			/* получаем информацию о переменной узла */
			VarNum = &varbinds[i].id[ varbinds[i].len - 1 ];
			
			if( node->node_type == MIB_NODE_EX)
			{
				struct mib_external_node* node_ex;
				node_ex = (struct mib_external_node*)node;
				/* TODO: подставить правильный rid вместо 0 */
				node_ex->get_object_def_a(0, 1, VarNum, &obj);
			}
			else
			{
				node->get_object_def(1, VarNum, &obj);
			}
			
			/* создаем переменную */
			vb_list[i] = snmp_varbind_alloc(&varbinds[i], obj.asn_type, obj.v_len);
			if( vb_list[i] != NULL )
			{
				{
					/* получаем значение переменной */
					if( node->node_type == MIB_NODE_EX)
					{
						struct mib_external_node* node_ex;
						node_ex = (struct mib_external_node*)node;
						/* TODO: подставить правильный rid вместо 0 */
						node_ex->get_value_a(0, &obj, obj.v_len, vb_list[i]->value);
					}
					else
					{
						node->get_value(&obj, obj.v_len, vb_list[i]->value);
					}
					/* добавляем переменную в ловушку */
					snmp_varbind_tail_add(&trap_msg.outvb, vb_list[i]);
				}
			}
		}
	}

	/* посылаем ловушку */
	tResult = snmp_send_trap(generic_trap, eoid, specific_trap);
	
	/* удаляем переменные из списка */
	snmp_varbind_list_free(&trap_msg.outvb);
	
	/* удаляем указатели переменных */
	vPortFree(vb_list);
	
	return tResult;
}

void SNMP_SendTestTrap(void)
{
/*  
  struct snmp_varbind *vb;
  struct snmp_obj_id objid = {11, {1, 3, 6, 1, 4, 1, 41752, 5, 16, 2, 1}};
  unsigned char msg[] = "Sex, drugs and LwIP";
  unsigned char msglen = 19;
  
  vb = snmp_varbind_alloc(&objid, SNMP_ASN1_OPAQUE, msglen);
  
  vb->value = &msg;
           
  trap_msg.outvb.head = vb;
  trap_msg.outvb.tail = vb;
  trap_msg.outvb.count = 1;
  
  snmp_send_trap(SNMP_GENTRAP_ENTERPRISESPC, &objid, 0);
     
  trap_msg.outvb.head = NULL;
  trap_msg.outvb.tail = NULL;
  trap_msg.outvb.count = 0;
  //vb->value = NULL;
     
  snmp_varbind_free(vb);
*/  
  static struct snmp_obj_id trapObjId = {11, {1, 3, 6, 1, 4, 1, 41752, 5, 16, 2, 1}};
  static struct snmp_obj_id varObjId  = {11, {1, 3, 6, 1, 4, 1, 41752, 5, 16, 1, 1}};
  
  struct snmp_varbind* vb;
  u32_t *u32ptr;
  
  vb = snmp_varbind_alloc(&varObjId, MIB_NODE_SC, 4);
  
  vb->value_len = 4;
  vb->value_type = 0x02;
  u32ptr = vb->value; 	
  *u32ptr = 23;
  
  if( vb != NULL )
	snmp_varbind_tail_add(&trap_msg.outvb, vb);
			
  snmp_send_trap(SNMP_GENTRAP_ENTERPRISESPC, &trapObjId, 0);
	
  /* удаляем переменные из списка */
  snmp_varbind_list_free(&trap_msg.outvb);
  
  //snmp_send_trap_ex(SNMP_GENTRAP_ENTERPRISESPC, &trapObjId, 0, &varObjId, 1);
  
  
#if 0	
	struct snmp_varbind** vb_list;
	struct mib_node* node;
	struct obj_def obj;
	err_t tResult;
	s32_t* VarNum;
    struct snmp_name_ptr np;
	

	/* создаем указатель на переменную */
	pvPortMalloc(sizeof(struct snmp_varbind*) );

	/* создаем сами переменные */
	for(u8_t i = 0; i < varbinds_num; i++)
	{
		/* ищем узел в дереве*/
		node = snmp_search_tree( (struct mib_node*)&internet, varbinds[i].len - 4, 
										 &varbinds[i].id[4], &np );
		
		//node = snmp_search_tree( (struct mib_node*)&internet, varbinds[i].len, 
		//								 &varbinds[i].id[0], &np );
		
		if(node != NULL)
		{
			/* получаем информацию о переменной узла */
			VarNum = &varbinds[i].id[ varbinds[i].len - 1 ];
			
			if( node->node_type == MIB_NODE_EX)
			{
				struct mib_external_node* node_ex;
				node_ex = (struct mib_external_node*)node;
				/* TODO: подставить правильный rid вместо 0 */
				node_ex->get_object_def_a(0, 1, VarNum, &obj);
			}
			else
			{
				node->get_object_def(1, VarNum, &obj);
			}
			
			/* создаем переменную */
			vb_list[i] = snmp_varbind_alloc(&varbinds[i], obj.asn_type, obj.v_len);
			if( vb_list[i] != NULL )
			{
				{
					/* получаем значение переменной */
					if( node->node_type == MIB_NODE_EX)
					{
						struct mib_external_node* node_ex;
						node_ex = (struct mib_external_node*)node;
						/* TODO: подставить правильный rid вместо 0 */
						node_ex->get_value_a(0, &obj, obj.v_len, vb_list[i]->value);
					}
					else
					{
						node->get_value(&obj, obj.v_len, vb_list[i]->value);
					}
					/* добавляем переменную в ловушку */
					snmp_varbind_tail_add(&trap_msg.outvb, vb_list[i]);
				}
			}
		}
	}

	/* посылаем ловушку */
	tResult = snmp_send_trap(generic_trap, eoid, specific_trap);
	
	/* удаляем переменные из списка */
	snmp_varbind_list_free(&trap_msg.outvb);
	
	/* удаляем указатели переменных */
	vPortFree(vb_list);
	
	return tResult;
#endif	
}

#define NUM_PRIVATE_TRAP 10
 
//static unsigned char SNMP_TRAP_0_FLAG = 1;
//static struct ip_addr SNMP_TRAP_0_ADDR;
 
extern struct snmp_msg_trap trap_msg;
 
struct private_trap
{
  /* source enterprise ID (sysObjectID) */
  struct snmp_obj_id *enterprise; 
  /* trap ID */
  struct snmp_obj_id *trap_oid;
 
  /* specific trap code */
  u32_t spc_trap;
 
  /* object value ASN1 type */
  u8_t value_type;
  /* object value length (in u8_t) */
  u8_t value_len;
  /* object value */
  void *value;
  /* indicate that the trap is sent */
  u8_t in_use;
};
 
struct private_trap trap_bank[NUM_PRIVATE_TRAP];
 
struct private_trap * getNextFreePrivateTrap()
{
   u8_t index;
   void * result = NULL;
  
   for(index = 0; index < NUM_PRIVATE_TRAP; index++)
   {
      if(!trap_bank[index].in_use)
      {
         trap_bank[index].in_use = 1;
         result = &trap_bank[index];        
         break;
      }
   }
  
   return result; 
}
 
void freePrivateTrap(struct private_trap * trap)
{
   trap->enterprise = NULL;
   trap->trap_oid = NULL;
   trap->value = NULL;
   trap->in_use = 0;  
}
 
void vSendTrapCallback( void * parameters )
{
   struct private_trap * trapToSend;
   struct snmp_varbind * vb;
  
   if( parameters != NULL )
   {
      trapToSend = (struct private_trap *) parameters;
     
      vb = snmp_varbind_alloc(trapToSend->enterprise,
                              trapToSend->value_type,
                              trapToSend->value_len);
                             
      vb->value = trapToSend->value;
           
      trap_msg.outvb.head = vb;
      trap_msg.outvb.tail = vb;
      trap_msg.outvb.count = 1;
     
      snmp_send_trap(SNMP_GENTRAP_ENTERPRISESPC, trapToSend->trap_oid, trapToSend->spc_trap);
     
      trap_msg.outvb.head = NULL;
      trap_msg.outvb.tail = NULL;
      trap_msg.outvb.count = 0;
     
      vb->value = NULL;
     
      snmp_varbind_free(vb);
     
      freePrivateTrap(trapToSend);
   }  
}
 
 
