
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/dhcp.h"
#include "ethernetif.h"
#include "common_config.h"
#include "netconf.h"
#include "tcpip.h"
#include "main.h"
#include "settings_api.h"
#include "parameters.h"
#include "web_params_api.h"
#include "snmp_api.h"
#include "trap_api.h"
#include "hal.h"

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


#define MAX_DHCP_TRIES 3

#define TIME_COUNTER_10_MIN   600
#define TIME_COUNTER_1_MIN    60

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

/**
  * @brief  Флаг подтверждения новых сетевых параметров пользователем
  */  
extern bool fConfirmWebParams;

/**
  * @brief  Network interface structure
  */
struct netif xnetif; 

/**
  * @brief  Задача получения сетевый параметров по DHCP протоколу
  */
TaskHandle_t xHandleDHCP = NULL;

/**
  * @brief  Задача переинициализации сети
  */
TaskHandle_t xHandleWebReinit = NULL;

bool dhcp = false;	

void LwIP_Init(void)
{
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;
  char str[20];

  tcpip_init( NULL, NULL );	

  /* Если настройки изменили, то используем временные параметры */
  if (sSettings.sFlags.netsettingsChanged == true)
  {
    if (sSettings.sWebTempParams.dhcpEnable)
    {	
      ipaddr.addr = 0;
      netmask.addr = 0;
      gw.addr = 0;
	
	  netif_add(&xnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
      netif_set_default(&xnetif);
      netif_set_up(&xnetif); 
    }	
    else
    {	
	  ipaddr.addr = ipaddr_addr(sSettings.sWebTempParams.ip);
	  netmask.addr = ipaddr_addr(sSettings.sWebTempParams.mask);
	  gw.addr = ipaddr_addr(sSettings.sWebTempParams.gate);
  
      sprintf(str, " %s\n\r", sSettings.sWebTempParams.ip);
      PRINT_USART("\n\rStatic IP address   \n\r");
      PRINT_USART(str);

      netif_add(&xnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
      netif_set_default(&xnetif);
      netif_set_up(&xnetif); 
    }
  
	if (sSettings.sWebTempParams.dhcpEnable) {
      xTaskCreate(LwIP_DHCP_task, "DHCPClient", configMINIMAL_STACK_SIZE * 2, NULL,
                  tskIDLE_PRIORITY + 2, &xHandleDHCP);
	  dhcp = true;
	}  
  }
  /* Настройки не менялись, используем обычне настройки из флеш памяти */
  else
  {
    if (sSettings.sWebParams.dhcpEnable)
    {	
      ipaddr.addr = 0;
      netmask.addr = 0;
      gw.addr = 0;
	
	  netif_add(&xnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
      netif_set_default(&xnetif);
      netif_set_up(&xnetif); 
    }	
    else
    {	
	  ipaddr.addr = ipaddr_addr(sSettings.sWebParams.ip);
	  netmask.addr = ipaddr_addr(sSettings.sWebParams.mask);
	  gw.addr = ipaddr_addr(sSettings.sWebParams.gate);
  	  
	  /* Обновляем временные настройки */
	  sSettings.sWebTempParams.dhcpEnable = sSettings.sWebParams.dhcpEnable;
	  strcpy(sSettings.sWebTempParams.ip, sSettings.sWebParams.ip);
	  strcpy(sSettings.sWebTempParams.mask, sSettings.sWebParams.mask);
	  strcpy(sSettings.sWebTempParams.gate, sSettings.sWebParams.gate);
	  
      sprintf(str, " %s\n\r", sSettings.sWebParams.ip);
      PRINT_USART("\n\rStatic IP address   \n\r");
      PRINT_USART(str);

      netif_add(&xnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
      netif_set_default(&xnetif);
      netif_set_up(&xnetif); 
    }
  
	if (sSettings.sWebParams.dhcpEnable) {
      xTaskCreate(LwIP_DHCP_task, "DHCPClient", configMINIMAL_STACK_SIZE * 2, NULL,
                  tskIDLE_PRIORITY + 2, &xHandleDHCP);
	  dhcp = true;
	}  
  }
  
  /* Если настройки изменились, запускаем задачу по отсчету времени реакции пользователя*/
  if (sSettings.sFlags.netsettingsChanged == true)
    xTaskCreate(vTaskWebReinit, "webReinit", configMINIMAL_STACK_SIZE, NULL,
              tskIDLE_PRIORITY, &xHandleWebReinit);
}

/**
  * @brief  LwIP_DHCP_Process_Handle
  * @param  None
  * @retval None
  */
void LwIP_DHCP_task(void * pvParameters)
{
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;
  uint8_t DHCP_state;  
  DHCP_state = DHCP_START;

  for (;;)
  {
    switch (DHCP_state)
    {
      case DHCP_START:
      {
        dhcp_start(&xnetif);
        DHCP_state = DHCP_WAIT_ADDRESS;
        //PRINT_USART("\n\rLooking for DHCP server please wait...\n\r");
      }
      break;

      case DHCP_WAIT_ADDRESS:
      {
        /* Read the new IP address */
        ipaddr = xnetif.ip_addr;
        netmask = xnetif.netmask;
        gw = xnetif.gw;
        	
        if (ipaddr.addr != 0) 
        {
          DHCP_state = DHCP_ADDRESS_ASSIGNED;	
          dhcp_stop(&xnetif);
          
		  /* Сохранение полученных сетевый параметров */
		  /* Если настройки изменили, то сохраняем во временные настройки */
          if (sSettings.sFlags.netsettingsChanged == true)
		  {
		    sprintf(sSettings.sWebTempParams.ip,   "%s", ipaddr_ntoa(&ipaddr));
		    sprintf(sSettings.sWebTempParams.mask, "%s", ipaddr_ntoa(&netmask));
		    sprintf(sSettings.sWebTempParams.gate, "%s", ipaddr_ntoa(&gw));
		  }
		  else
		  {
		    sprintf(sSettings.sWebParams.ip,   "%s", ipaddr_ntoa(&ipaddr));
		    sprintf(sSettings.sWebParams.mask, "%s", ipaddr_ntoa(&netmask));
		    sprintf(sSettings.sWebParams.gate, "%s", ipaddr_ntoa(&gw));
			
			/* Обновляем временные настройки */
			sSettings.sWebTempParams.dhcpEnable = sSettings.sWebParams.dhcpEnable;
			sprintf(sSettings.sWebTempParams.ip,   "%s", ipaddr_ntoa(&ipaddr));
		    sprintf(sSettings.sWebTempParams.mask, "%s", ipaddr_ntoa(&netmask));
		    sprintf(sSettings.sWebTempParams.gate, "%s", ipaddr_ntoa(&gw));
			
		  }
		  
		  PRINT_USART("Parameters assigned by a DHCP server:\n\r     IP:   ");
          PRINT_USART(ipaddr_ntoa(&ipaddr));
		  PRINT_USART("\n\r");
          
		  PRINT_USART("Netmask:   ");
		  PRINT_USART(ipaddr_ntoa(&netmask));
		  PRINT_USART("\n\r");
		  
		  PRINT_USART("Gateway:   ");
		  PRINT_USART(ipaddr_ntoa(&gw));
		  PRINT_USART("\n\r");
          
		  vTaskDelay(50);
		  /* Установлен динамический IP, можно отправить трап о перезагрузке устройства */
		  SNMP_SendUserTrap(DEVICE_REBOOTED);
		  
          vTaskDelete(xHandleDHCP);
        }
        else
        {
          /* DHCP timeout */
          if (xnetif.dhcp->tries > MAX_DHCP_TRIES)
          {
            DHCP_state = DHCP_TIMEOUT;

            /* Stop DHCP */
            dhcp_stop(&xnetif);
			
			if (sSettings.sFlags.netsettingsChanged == true)
		    {
			  ipaddr.addr = ipaddr_addr(sSettings.sWebTempParams.ip);
	          netmask.addr = ipaddr_addr(sSettings.sWebTempParams.mask);
	          gw.addr = ipaddr_addr(sSettings.sWebTempParams.gate);
			}  
			else
			{  
			  ipaddr.addr = ipaddr_addr(sSettings.sWebParams.ip);
	          netmask.addr = ipaddr_addr(sSettings.sWebParams.mask);
	          gw.addr = ipaddr_addr(sSettings.sWebParams.gate);
			}
			  
            /* Static address used */
            netif_set_addr(&xnetif, &ipaddr , &netmask, &gw);
 
            PRINT_USART("DHCP timeout\n\r");
            PRINT_USART("\n\rStatic IP address\n\r");
			PRINT_USART(ipaddr_ntoa(&ipaddr));
		    PRINT_USART("\n\r");

			vTaskDelay(50);
			/* Установлен статический IP, можно отправить трап о перезагрузке устройства */
		    SNMP_SendUserTrap(DEVICE_REBOOTED);
			
			vTaskDelete(xHandleDHCP);
          }
        }
      }
      break;

      default: break;
    }

    vTaskDelay(250);
  }   
}

/**
  * @brief  Запуск задачи переинициализации WEB
  */
void WEB_StartReinitTask(void)
{
  xTaskCreate(vTaskWebReinit, "ReinitWeb", 2*configMINIMAL_STACK_SIZE, NULL,
              tskIDLE_PRIORITY, &xHandleWebReinit);
}

/**
  * @brief  Переинициализация WEB. Задача положенное время отслеживает флаг
  *         fConfirmWebParams. 
  *           Если флаг устанавливается в положенное время,
  *         временные настройки web перезаписываются в постоянные, сбрасывается 
  *         флаг sSettings.sFlags.netsettingsChanged и вся структура настроек 
  *         сохраняется в памяти. 
  *           Если флаг не устанавливается в положенное время, то сбрасывается
  *         флаг sSettings.sFlags.netsettingsChanged, сохраняется вся структура
  *         настроек в памяти и контроллер перезагружается.
  */
void vTaskWebReinit(void * pvParameters)
{
  static uint16_t timeCounter = 0;
  
  for (;;)
  {
	/* Контроль времени работы задачи */
	if (timeCounter++ > TIME_COUNTER_10_MIN)
	{
	  SetWebReinitFlag(false);
	  HTTP_SaveSettings();
      vTaskDelay(1010);
      Reboot();
	}
	
	if (fConfirmWebParams)
	{
	  fConfirmWebParams = false;
		
	  /* Сохраняем временные сетевые настройки в постоянные */
	  sSettings.sWebParams.dhcpEnable = sSettings.sWebTempParams.dhcpEnable;
	  strcpy(sSettings.sWebParams.ip,   sSettings.sWebTempParams.ip);
	  strcpy(sSettings.sWebParams.gate, sSettings.sWebTempParams.gate);
	  strcpy(sSettings.sWebParams.mask, sSettings.sWebTempParams.mask);
	  
	  HTTP_SaveSettings();
	  
	  vTaskDelete(xHandleWebReinit);
	}	
	  
	vTaskDelay(1000);
  }	
}	

void SaveWEBparam(void)
{
  sSettings.sWebParams.dhcpEnable = sSettings.sWebTempParams.dhcpEnable;
  strcpy(sSettings.sWebParams.ip,   sSettings.sWebTempParams.ip);
  strcpy(sSettings.sWebParams.gate, sSettings.sWebTempParams.gate);
  strcpy(sSettings.sWebParams.mask, sSettings.sWebTempParams.mask);
}

/**
  * @brief  Возвращает true если сетевые параметры изменились
  */
bool GetStateWebReinit(void)
{
  /* Статус dhcp изменился? */
  if (sSettings.sWebParams.dhcpEnable != sSettings.sWebTempParams.dhcpEnable)
  {
	/* Включили dhcp */
    if (sSettings.sWebTempParams.dhcpEnable == 1)
	{
	  /* Устанавилваем флаг */
	  SetWebReinitFlag(true);
	  return true;
	}
	/* Выключили dhcp */
	else
	{
	  /* Устанавилваем флаг */
      SetWebReinitFlag(true);
	  return true;
	}  
  }
  
  /* Изменился IP? */
  if (strstr(sSettings.sWebParams.ip, sSettings.sWebTempParams.ip) == 0)
  {
    /* Устанавилваем флаг */
	SetWebReinitFlag(true);
	return true;
  }
 
  /* Изменился шлюз? */
  if (strstr(sSettings.sWebParams.gate, sSettings.sWebTempParams.gate) == 0)
  {
    /* Устанавилваем флаг */
	SetWebReinitFlag(true);
	return true;
  }
  
  /* Изменилась маска? */
  if (strstr(sSettings.sWebParams.mask, sSettings.sWebTempParams.mask) == 0)
  {
    /* Устанавилваем флаг */
	SetWebReinitFlag(true);
	return true;
  }
  
  return false;
}

/*********** Portions COPYRIGHT 2012 Embest Tech. Co., Ltd.*****END OF FILE****/
