#include "main.h"
#include "ethernetif.h"
#include "lwip/netif.h"
#include "lwip/tcpip.h"
#include "lwip/dns.h"
#include "app_ethernet.h"
#include "log.h"
#include "bsp_fsmc_sram.h"
#include "bsp_fsmc_nandflash.h"
#include "nandflash.h"
#include "myFile.h"
#include "string.h"
#include "data_task.h"
#include "tcp_server.h"
#include "usart_server.h"
#include "timer.h"
#include "usart.h"
#include "sys_http.h"
#include "sys_mqtt.h"
#include "data_task.h"
#include "mmodbus.h"
#include "led.h"
#include "lte.h"
#include "iwdg.h"
#include "CJT188.h"
#include "sys_ping.h"
#include "reset.h"
#include "lwip/dhcp.h"
#include "master_example.h"
#include "slave_example.h"
#include "simple_server.h"



/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
struct netif gnetif; /* network interface structure */
/* Semaphore to signal Ethernet Link state update */
osSemaphoreId Netif_LinkSemaphore = NULL;
/* Ethernet link thread Argument */
struct link_str link_arg;

/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void StartThread(void const * argument);
static void ToggleLed4(void const * argument);
static void BSP_Config(void);
static void Netif_Config(void);
void EC800M_taskFuntcion(void const*arg);
void write_config(void const * argument);

void load_unique(void);

/* Private functions ---------------------------------------------------------*/
char gatewayId[11];
char ETH_flag = 1; //  1,启用网线，0 启用LTE
uint16_t data[2];
/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
	int status;
  /* STM32F2xx HAL library initialization:
       - Configure the Flash prefetch, instruction and Data caches
       - Configure the Systick to generate an interrupt each 1 msec
       - Set NVIC Group Priority to 4
       - Global MSP (MCU Support Package) initialization
     */
  HAL_Init();  
	load_unique();	
	sprintf(gatewayId,"DTtest0001");//DT8pd3ac6h  DTbma5ac6h  DTtest0001  DTrzts0001
  /* Configure the system clock to 120 MHz */
  SystemClock_Config();
	MX_FSMC_SRAM_Init();
	status = NAND_Init();
	while(status){
		NAND_Format();
		status = NAND_Init();
	}

	TIMER_config();
	my_mem_init(SRAMEX);
	my_mem_init(SRAMIN);

	USART_232_config();
	USART_485_config();
	USART_485_DE_TX();
	printf("hello\n");
//	IWDG_Configuration();
	
	LED_GPIO_Config();	// 339 loraRX
	
//	NET_STATUS_LED_Config();// 339 设备指示灯
	
	resetConfig();// 339 loraTX
//	uint8_t args;
//	void const* arg = &args;
//	iec_master_test(arg);
//	iec_client_test();
	
//	osThreadDef(master, iec_master_test, osPriorityNormal, 0, 1024);
//	osThreadCreate (osThread(master), NULL);
	osThreadDef(client, iec_client_test, osPriorityNormal, 0, 1024);
	osThreadCreate (osThread(client), NULL);

	read_file("ETH.txt", &ETH_flag);
	DeleteDirFile("ETH.txt");
//	if(ETH_flag == 1)// 网线启动
//	{
//		/* Init task */
//		osThreadDef(Start, StartThread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 4);
//		osThreadCreate (osThread(Start), NULL);
//	}
//	else // LTE启动
//	{
//		DEBUG_USART_Config();
//		USART_DMA_Config();	
//		/* LTE task */
//		osThreadDef(LTE_task, EC800M_taskFuntcion, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 4);
//		osThreadCreate (osThread(LTE_task), NULL);
//	}
  
  /* Start scheduler */
  osKernelStart();
  
  /* We should never get here as control is now taken by the scheduler */
  for( ;; );
}

/**
  * @brief  Start Thread
  * @param  argument not used
  * @retval None
  */
static void StartThread(void const * argument)
{
  /* Initialize LCD and LEDs */
  BSP_Config();
  log_init();
  /* Create tcp_ip stack thread */
  tcpip_init(NULL, NULL);
  
  /* Initialize the LwIP stack */
  Netif_Config();
   
  /* Notify user about the network interface config */
  User_notification(&gnetif);
	
	reset_task_creat();
	tcp_server_init();
	
//#ifdef USE_DHCP
  /* Start DHCPClient */
  osThreadDef(DHCP, DHCP_thread, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 2);
  osThreadCreate (osThread(DHCP), &gnetif);
//#endif
  
  /* Start toogleLed4 task : Toggle LED4  every 250ms */
//  osThreadDef(LED4, ToggleLed4, osPriorityNormal, 0, configMINIMAL_STACK_SIZE*8);
//  osThreadCreate(osThread(LED4), NULL);

#ifdef USE_DHCP
	// 确保dhcp配置完成
	while(dhcp_done != 1)	
	{
		feedDog();
		vTaskDelay(100);
	}
#endif
	
//	http_getDemo();
//	mqtt_task_creat();	
//	
//	osThreadDef(DataTask, data_task, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 8);
//	osThreadCreate (osThread(DataTask), NULL);
//	
//	ETH_PingWork("192.168.0.2");
//		osThreadDef(client, cs104_server, osPriorityNormal, 0, 1024);
//		osThreadCreate (osThread(client), NULL);
	for( ;; )
	{
		/* Delete the Init Thread */ 
		osThreadTerminate(NULL);
	}
}

/**
  * @brief  Initializes the lwIP stack
  * @param  None
  * @retval None
  */
static void Netif_Config(void)
{
  ip_addr_t ipaddr;
  ip_addr_t netmask;
  ip_addr_t gw;
	ip_addr_t dns_server;
	
#ifdef USE_DHCP
  ip_addr_set_zero_ip4(&ipaddr);
  ip_addr_set_zero_ip4(&netmask);
  ip_addr_set_zero_ip4(&gw);
#else
  IP_ADDR4(&ipaddr,IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3);
  IP_ADDR4(&netmask,NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3);
  IP_ADDR4(&gw,GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3);
	// 设置DNS服务器地址
  IP4_ADDR(&dns_server, DNS_SERVER_ADDR0, DNS_SERVER_ADDR1, DNS_SERVER_ADDR2, DNS_SERVER_ADDR3);
  dns_setserver(0, &dns_server); // 设置第一个DNS服务器地址
#endif /* USE_DHCP */
    
  netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
  
  /*  Registers the default network interface. */
  netif_set_default(&gnetif);
  
  if (netif_is_link_up(&gnetif))
  {
    /* When the netif is fully configured this function must be called.*/
    netif_set_up(&gnetif);
  }
  else
  {
    /* When the netif link is down this function must be called */
    netif_set_down(&gnetif);
  }
	dhcp_stop(&gnetif);
	netif_set_link_callback(&gnetif,ethernetif_update_config);
	
	  /* create a binary semaphore used for informing ethernetif of frame reception */
  osSemaphoreDef(Netif_SEM); 
  Netif_LinkSemaphore = osSemaphoreCreate(osSemaphore(Netif_SEM) , 1 );

  link_arg.netif = &gnetif;
  link_arg.semaphore = Netif_LinkSemaphore;
	
	osThreadDef(LinkThr, ethernetif_set_link, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE * 2);
  osThreadCreate (osThread(LinkThr), &link_arg);
	
}

void set_ipaddr(char* buf)
{
		ip_addr_t ipaddr;
		ip_addr_t netmask;
		ip_addr_t gw;
	
		int ipaddr0,ipaddr1,ipaddr2,ipaddr3;
		int maskaddr0,maskaddr1,maskaddr2,maskaddr3;
		int gwaddr0,gwaddr1,gwaddr2,gwaddr3;
	
		ipaddr0 = parseIntField(buf,"\"ipv4\":\"" );
		ipaddr1 = parseIntField(strstr(buf,"\"ipv4\":\"") + 1,"." );
		ipaddr2 = parseIntField(strstr(strstr(buf,"\"ipv4\":\"") + 1,"." ) + 1,".");
		ipaddr3 = parseIntField(strstr(strstr(strstr(buf,"\"ipv4\":\"") + 1,"." ) + 1,".") + 1 ,".");

		maskaddr0 = parseIntField(buf,"\"subnetMask\":\"" );
		maskaddr1 = parseIntField(strstr(buf,"\"subnetMask\":\"") + 1,"." );
		maskaddr2 = parseIntField(strstr(strstr(buf,"\"subnetMask\":\"") + 1,"." ) + 1,".");
		maskaddr3 = parseIntField(strstr(strstr(strstr(buf,"\"subnetMask\":\"") + 1,"." ) + 1,".") + 1 ,".");
		
		gwaddr0 = parseIntField(buf,"\"defaultGateway\":\"" );
		gwaddr1 = parseIntField(strstr(buf,"\"defaultGateway\":\"") + 1,"." );
		gwaddr2 = parseIntField(strstr(strstr(buf,"\"defaultGateway\":\"") + 1,"." ) + 1,".");
		gwaddr3 = parseIntField(strstr(strstr(strstr(buf,"\"defaultGateway\":\"") + 1,"." ) + 1,".") + 1 ,".");	
	
		IP4_ADDR(&ipaddr, ipaddr0 ,ipaddr1 , ipaddr2 , ipaddr3 );
    IP4_ADDR(&netmask, maskaddr0, maskaddr1, maskaddr2, maskaddr3);
    IP4_ADDR(&gw, gwaddr0, gwaddr1, gwaddr2,gwaddr3);
//#ifdef USE_DHCP
		// 停止DHCP客户端
		DHCP_close();
//#endif
		// 禁用网口
		 netif_set_down(&gnetif);
		// 设置网络接口的IP地址
//		netif_set_gw(&gnetif, &gw);
//		netif_set_netmask(&gnetif, &netmask);
//		netif_set_ipaddr(&gnetif, &ipaddr);
    netif_set_addr(&gnetif, &ipaddr , &netmask, &gw);

		// 重启网络接口以使更改生效
    netif_set_up(&gnetif);

}
/**
  * @brief  Initializes the LCD and LEDs resources.
  * @param  None
  * @retval None
  */
static void BSP_Config(void)
{
}

///**
//  * @brief  Toggle LED4 thread
//  * @param  pvParameters not used
//  * @retval None
//  */
//static void ToggleLed4(void const * argument)
//{
//  for( ;; )
//  {
//    /* Toggle LED4 each 250ms */

//		LOG_PRINT(LOG_INFO,"udp");
//    osDelay(100);
//  }
//}

///**
//  * @brief  EXTI line detection callbacks
//  * @param  GPIO_Pin: Specifies the pins connected EXTI line
//  * @retval None
//  */
//void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
//{
//  if (GPIO_Pin == GPIO_PIN_14)
//  {
//    osSemaphoreRelease(Netif_LinkSemaphore);
//  }
//}

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 120000000
  *            HCLK(Hz)                       = 120000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 4
  *            APB2 Prescaler                 = 2
  *            HSE Frequency(Hz)              = 25000000
  *            PLL_M                          = 25
  *            PLL_N                          = 240
  *            PLL_P                          = 2
  *            PLL_Q                          = 5
  *            VDD(V)                         = 3.3
  *            Flash Latency(WS)              = 3
  * @param  None
  * @retval None
  */
static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 240;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* User may add here some code to deal with this error */
  while(1)
  {
  }
}



void vApplicationMallocFailedHook( void )
{
	LOG_PRINT(LOG_ERROR,"malloc error");
}

void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
{
		LogPrint(LOG_ERROR,__FILE__,__FUNCTION__,__LINE__,"task :%s 栈溢出\r\n",pcTaskName);
}


//int fputc(int ch, FILE *stream)
//{
// return ch;
//}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  
  /* Infinite loop */
  while (1)
  {
  }
}
#endif

void ethernetif_notify_conn_changed(struct netif *netif)
{
  if (netif_is_link_up(netif))
  {
    LOG_PRINT(LOG_INFO,"link up");
  }
  else
  {
    LOG_PRINT(LOG_INFO,"link down");
  }
  
}

void load_unique(void)
{
	char *hex_table = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN";
	uint32_t CpuID1, CpuID2, CpuID3;
	HAL_GetUIDw0();
	CpuID1 = *(volatile uint32_t *)(UID_BASE);
	CpuID2 = *(volatile uint32_t *)(UID_BASE+8);
	CpuID3 = *(volatile uint32_t *)(UID_BASE+16);
	char strId[11];

	for (uint8_t i = 0, j = 0; i < 8; i += 2)
	{
		uint32_t sum1 = (CpuID1 >> ((j % 4) * 8)) & 0xFF; // 按字节取出
		uint8_t index1 = sum1 / 16;
		uint8_t remainder1 = sum1 % 16;

		uint32_t sum2 = (CpuID2 >> ((j % 4) * 8)) & 0xFF; // 按字节取出
		uint8_t index2 = sum2 / 16;
		uint8_t remainder2 = sum2 % 16;

		uint32_t sum3 = (CpuID3 >> ((j % 4) * 8)) & 0xFF; // 按字节取出
		uint8_t index3 = sum3 / 16;
		uint8_t remainder3 = sum3 % 16;

		strId[i + 2] = hex_table[index1 + index2 + index3];
		strId[i + 1 + 2] = hex_table[remainder1 + remainder2 + remainder3];

		j++;
	}
	strId[10] = '\0';
	strId[0]='L';
	strId[1]='R';
	strcpy(gatewayId,strId);
}

/*
 *  函数名：void EC800M_taskFuntcion(void *arg)
 *  输入参数：无
 *  输出参数：无
 *  返回值：无
 *  函数作用：开启EC800M模块任务
 */
void EC800M_taskFuntcion(void const*arg)
{
	
//	 /* Create tcp_ip stack thread */
//  tcpip_init(NULL, NULL);
//  
//  /* Initialize the LwIP stack */
//  Netif_Config();
	
	EC800M_open();
	ec800_init();
	
	ec800_TCP();
	char *http=mymalloc(SRAMEX,80); // 根据要访问的 URL修改分配的大小
	sprintf(http,"http://gpu.ringzle.com:8082/iot/transmit/getTransmitConfig/%s",gatewayId);
//	sprintf(http,"http://gpu.ringzle.com:8082/witcarbon-admin/profile/2024/03/25/7935dfd8-b398-41ba-85a3-8f04a6f1625e.bin");
	http_set_url(http);
	myfree(SRAMEX,http);
	LTE_HTTP_get();
	MQ_threadCreate();
	
	osThreadDef(DataTask, data_task, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 8);
	osThreadCreate (osThread(DataTask), NULL);
	
	for( ;; )
  {
    /* Delete the LTE Thread */ 
    osThreadTerminate(NULL);
  }
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
