/**
  ******************************************************************************
  * @file    net.c
  * @author  BLW RCU  development Team
  * @version 
  * @date    2022年04月21日
  * @brief  
	*    网络服务函数
	* @log SongHan 202204211130   TCP Disconnect TCP Timout   应MQTT重新连接
				 SongHan 202204211412   打印MQTT接收数据
				 SongHan 202204231150   将MQTT接收到的数据存储到日志
				 SongHan 202205091800   网络中断 关于MQTT的处理 增加 0x01 == mqtt_info.init_flag 的判断
				 SongHan 202205091800   MQTT连接失败  也不要free(mqtt_info.domain_name)
				 SongHan 202205131055   MQTT域名IP变了之后，会产生TCP超时中断。如果网络状态机不变，MQTT会离线。
				                        6分钟后，小概率会产生网络拔出事件。整个网络重新初始化。
																在MQTT TCP超时和断开连接增加 server_info.init_flag = 0   保证域名重新解析				 
  ******************************************************************************
  */
#include "includes.h"
#include "Udp_Internal_Protocol.h"   

#include <ctype.h>

/* 下面的缓冲区和全局变量必须要定义，库中调用 */
__align(16)UINT8    CH57xMACRxDesBuf[(RX_QUEUE_ENTRIES )*16] = {0};                   /* MAC接收描述符缓冲区，16字节对齐 */
__align(4) UINT8    CH57xMACRxBuf[RX_QUEUE_ENTRIES*RX_BUF_SIZE]= {0};                /* MAC接收缓冲区，4字节对齐 */
__align(4) SOCK_INF SocketInf[CH57xNET_MAX_SOCKET_NUM]= {0};                         /* Socket信息表，4字节对齐 */

UINT16 MemNum[8] = {CH57xNET_NUM_IPRAW,
                    CH57xNET_NUM_UDP,
                    CH57xNET_NUM_TCP,
                    CH57xNET_NUM_TCP_LISTEN,
                    CH57xNET_NUM_TCP_SEG,
                    CH57xNET_NUM_IP_REASSDATA,
                    CH57xNET_NUM_PBUF,
                    CH57xNET_NUM_POOL_BUF
                    };
 UINT16 MemSize[8] = {CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IPRAW_PCB),
                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_UDP_PCB),
                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB),
                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_PCB_LISTEN),
                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_TCP_SEG),
                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_IP_REASSDATA),
                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(0),
                    CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_PBUF) + CH57xNET_MEM_ALIGN_SIZE(CH57xNET_SIZE_POOL_BUF)
                    };
__align(4)UINT8 Memp_Memory[CH57xNET_MEMP_SIZE] = {0};
__align(4)UINT8 Mem_Heap_Memory[CH57xNET_RAM_HEAP_SIZE] = {0};
__align(4)UINT8 Mem_ArpTable[CH57xNET_RAM_ARP_TABLE_SIZE] = {0};
						  
/* CH57xNET库TCP的MSS长度为536字节，即一个TCP包里的数据部分最长为536字节 
	TCP协议栈采用滑动窗口进行流控，窗口最大值为socket的接收缓冲区长度。在设定 
	RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系，例如窗口值为4*MSS，则远端一次会发送 
	4个TCP包，如果RX_QUEUE_ENTRIES小于4，则必然会导致数据包丢失，从而导致通讯效率降低 
	建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据，则  
	建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 
	为了节约RAM，请将接收缓冲区的长度设置为MSS */
	
/* 网口灯定义 PB口低十六位有效 */
#if (USE_CORE_TYPE == 1)    //使用C1F核心板
UINT16 CH57xNET_LEDCONN=0x0020;                                                 /* 连接指示灯 PB5*/
UINT16 CH57xNET_LEDDATA=0x0400;                                                 /* 通讯指示灯 PB10 */ 
#elif (USE_CORE_TYPE == 2)   //使用C1核心板
UINT16 CH57xNET_LEDCONN=0x0020;                                                 /* 连接指示灯 PB5*/
UINT16 CH57xNET_LEDDATA=0x0040;                                                 /* 通讯指示灯 PB6*/ 
#endif  //USE_CORE_TYPE == CORE_TYPE_C1F		

					
/* CH579相关定义 */
//UINT8 MACAddr[6] = {0x34,0xD0,0xB8,0x10,0xA3,0x1E};                             /* CH579MAC地址 - 默认MAC地址*/
//UINT8 MACAddr[6] = {0x34,0xD0,0xB8,0x10,0xE0,0xF6};                             /* CH579MAC地址 - 样机MAC地址*/
UINT8 MACAddr[6] = {0x34,0xD0,0xB8,0x10,0xE0,0xF9};                             /* CH579MAC地址 - 样机2MAC地址*/

UINT8 SocketRecvBuf[RECE_BUF_LEN] = {0};                                            	/* socket接收缓冲区 */
uint32_t SysTick_10ms = 0;

uint8_t Global_Large_Buff[1100] = {0};			//用于套接字通讯组包、读写外部SRAM映射寄存器

NET_INFO  net_info ={

	.local_ip   = {192,168,1,200},                           	/* CH579IP地址 */
	.gwip_addr  = {192,168,1,1},                         		/* CH579网关 */
	.mask       = {255,255,255,0},                  			/* CH579子网掩码 */
	.SocketId 	= {0,0,0,0},									/* 套接字索引 */
	.ServerDename = SERVER_NAME_DNS,							/* 服务器域名 2025-10-11 */
	
};

/*网络服务信息*/
NET_SERVER_INFO  server_info = {
	
	.init_flag	   		= 0,									/* 网络初始化标志位，用于套接字创建使用*/
	.register_flag		= 0,									/* 网络注册标志位*/
	.search_ack_flag	= 0,									/* 搜索命令应答ACK*/
	.dhcp_en			= 1,									/* DHCP使能 */
	.dns_sta       		= 0,                                	/* DNS状态机当前状态 */ 
	
	.dhcp_flg      		= 0,                                 	/* DHCP成功时在回调中置位*/
	.dns_flg       		= 0,                                 	/* DNS成功时在回调中置位*/
	.Udp_Internal_sta	= 0,									/* UDP状态机当前状态 */ 
	.PHY_State			= 0,									/* NET PHY状态 */
	
	.register_num		= 0,									/* 注册计数 */ 		
	.dns_fail			= 0,									/*  */ 
	
	.server_dns_flag	= 0,									/* DNS解析服务器域名标志位 */ 
	.tftp_dns_flag		= 0,									/* DNS解析TFTP服务器域名标志位 */ 
	.mqtt_dns_flag		= 0,									/* DNS解析MQTT服务器域名标志位 */ 
 	.online_state 		= 0,
	.sync_tick			= 0,
	
	.udp_dns_flag		= 0,									/* udp服务器解析域名标志位	 */ 
	.server_select		= 0,									/* 服务器选择, 0x00:使用云端服务器,0x01:使用本地服务器*/
	.net_retry_flag 	= 0,									/* 网络重试标志位*/
	.net_retry_num		= 0,									/* 网络重试次数 - 比如DHCP重试次数，DNS重试次数*/
	
	.con_flag 			= 0,									/* 网络直连标志位 */ 
	.rcu_reboot_flag 	= 1,									/* RCU启动标志位 - 用于上报启动原因使用 */ 
	.udp_scan_cnt 		= 0,
	
	.active_cmd_flag 	= 0,
	
	.net_sta       		= 0,                                 	/* 网络状态机当前状态 */
	
	.dis_ip        		= {106,75,37,225},                  	/* 云端服务器IP地址 */
	.tftp_ip			= {116,25,116,27},						/* TFTP服务器IP地址 */ 
	.udp_ip				= {0,0,0,0},							/* 用于搜索命令的回复 IP地址 */ 
	.goal_ip			= {192,168,101,31},						/* 发送数据的目标ip 用于云端升级使用*/
	.local_port    		= 8000,                             	/* 用于搜索命令的回复 端口号 */
	.goal_port     		= 8080,                             	/* 发送数据的目标port */
	.dis_port      		= 3339,                             	/* 云端服务器端口号 */
	.frame_no	   		= 0x8000,								/* 云端服务器发送的帧号 */
	
	.wait_cot      		= 0,                                  	/* 等待计数值赋0 */

	.register_tick 	 	= 0,									/* 注册等待回复计时 */ 
	.search_ack_tick 	= 0,									/* 搜索命令应答ACK时间戳 */
	
	.udp_sta 			= 1,
	.udp_send_flag 		= 0,
	.udp_retry_cnt 		= 0,
	.udp_retry_num 		= 0,
	.ack_frame 			= 0,
	
	.udp_timesync_cnt 	= 0,
	.udp_periodic_cnt 	= 0,
	
	.udp_retry_tick 	= 0,
	.udp_retry_time 	= 2000,
	
	.con_tick 			= 0,
	
	#if TFTP_GET_IP
	.tftpip_gflag = 0,
	#endif
	
	.udp_idle_tick 		= 0,
	.udp_online_tick 	= 0,
	.udp_online_time 	= 0,

};

TFTP_LOG tftp_log;      //2024-04-08



#if INTERRUPT_RECV_EN
UINT8 MyBuf[RECE_BUF_LEN] = {0};    /* 定义一个临时缓冲区 */
#endif
//UINT8 Status;			//当前网络状态 -- DNS

/*******************************************************************************
* Function Name  : Timer0Init
* Description    : 定时器0初始化
* Input          : time 定时时间
* Output         : None
* Return         : None
*******************************************************************************/
void Timer0Init(UINT32 time)
{
	R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;	                                    /* 清除所有计数值 */
	R8_TMR0_CTRL_MOD = 0;					                                	/* 设置定时器模式 */
	R32_TMR0_CNT_END = FREQ_SYS/1000000*time;	                                /* 设置定时时间 */
	R8_TMR0_INT_FLAG = R8_TMR0_INT_FLAG;		                                /* 清除标志 */
	R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END;	                                 	/* 定时中断 */
	R8_TMR0_CTRL_MOD |= RB_TMR_COUNT_EN;
	NVIC_EnableIRQ(TMR0_IRQn);
}

/*******************************************************************************
* Function Name  : IRQ_Handler
* Description    : IRQ中断服务函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void ETH_IRQHandler( void )						                           	/* 以太网中断 */
{
	CH57xNET_ETHIsr();								                       	/* 以太网中断中断服务函数 */
}

void TMR0_IRQHandler( void ) 						                        /* 定时器中断 */
{
	CH57xNET_TimeIsr(CH57xNETTIMEPERIOD);                               	/* 定时器中断服务函数 */
	R8_TMR0_INT_FLAG |= 0xff;												/* 清除定时器中断标志 */
	SysTick_10ms++;
}



/*******************************************************************************
* Function Name  : mStopIfError
* Description    : 调试使用，显示错误代码
* Input          : iError 错误代码
* Output         : None
* Return         : None
*******************************************************************************/
void mStopIfError(UINT8 iError)
{
    if (iError == CH57xNET_ERR_SUCCESS) return;                                 /* 操作成功 */
    Dbg_Println(DBG_BIT_NET_STATUS_bit,"mStopIfError: %02X", (UINT16)iError);	/* 显示错误 */
}


/*******************************************************************************
* Function Name  : CH57xNET_CreatTcpSocket
* Description    : 创建TCP Client socket
* Input          : socket索引保存地址
* Output         : None
* Return         : None
*******************************************************************************/
void CH57xNET_CreatTcpSocket_2(UINT8* S)
{
   UINT8 i;                                                             
   SOCK_INF TmpSocketInf;                                                       /* 创建临时socket变量 */

   memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));                            /* 库内部会将此变量复制，所以最好将临时变量先全部清零 */
   memcpy((void *)TmpSocketInf.IPAddr, server_info.dis_ip, 4);                	/* 设置目的IP地址 */
   TmpSocketInf.DesPort = 1000;                     
   TmpSocketInf.SourPort = 2000;                                                /* 设置源端口 */
   TmpSocketInf.ProtoType = PROTO_TYPE_TCP;                                     /* 设置socekt类型 */
   TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;                         /* 设置接收缓冲区的接收缓冲区 */
   TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;                                     /* 设置接收缓冲区的接收长度 */
   i = CH57xNET_SocketCreat(S,&TmpSocketInf);                           		/* 创建socket，将返回的socket索引保存在SocketId中 */
   mStopIfError(i);                                                             /* 检查错误 */
#ifdef  KEEPLIVE_ENABLE
   CH57xNET_SocketSetKeepLive(*S, 1 );                                   		/* 开启socket的KEEPLIVE功能（V06版本支持） */
#endif

   i = CH57xNET_SocketConnect(*S);                                        		/* TCP连接 */
   mStopIfError(i);                                                             /* 检查错误 */
   i = CH57xNET_SetSocketTTL(*S,128 );
   mStopIfError(i);                                                             /* 检查错误 */
}


/*******************************************************************************
* Function Name  : net_initkeeplive
* Description    : keeplive初始化
* Input          : None      
* Output         : None
* Return         : None
*******************************************************************************/
#ifdef  KEEPLIVE_ENABLE
void net_initkeeplive(void)
{
    struct _KEEP_CFG  klcfg;

    klcfg.KLIdle = 20000;                                                       /* 空闲 */
    klcfg.KLIntvl = 10000;                                                      /* 间隔 */
    klcfg.KLCount = 5;                                                          /* 次数 */
    CH57xNET_ConfigKeepLive(&klcfg);
}
#endif

/*******************************************************************************
* Function Name  : CH57xNET_LibInit
* Description    : 库初始化操作
* Input          : ip      ip地址指针
*                ：gwip    网关ip地址指针
*                : mask    掩码指针
*                : macaddr MAC地址指针 
* Output         : None
* Return         : 执行状态
*******************************************************************************/
UINT8 CH57xNET_LibInit(/*const*/ UINT8 *ip,/*const*/ UINT8 *gwip,/*const*/ UINT8 *mask,/*const*/ UINT8 *macaddr)
{
    UINT8 i;
    struct _CH57x_CFG cfg;

    if(CH57xNET_GetVer() != CH57xNET_LIB_VER)return 0xfc;                       /* 获取库的版本号，检查是否和头文件一致 */
    CH57xNETConfig = LIB_CFG_VALUE;                                             /* 将配置信息传递给库的配置变量 */
    cfg.RxBufSize = RX_BUF_SIZE; 
    cfg.TCPMss   = CH57xNET_TCP_MSS;
    cfg.HeapSize = CH57x_MEM_HEAP_SIZE;
    cfg.ARPTableNum = CH57xNET_NUM_ARP_TABLE;
    cfg.MiscConfig0 = CH57xNET_MISC_CONFIG0;
    CH57xNET_ConfigLIB(&cfg);
    i = CH57xNET_Init(ip,gwip,mask,macaddr);
#ifdef  KEEPLIVE_ENABLE
    net_initkeeplive( );
#endif
    return (i);                      
}

/*******************************************************************************
* Function Name  : CH57xNET_HandleSockInt
* Description    : Socket中断处理函数
* Input          : sockeid  socket索引
*                ：initstat 中断状态
* Output         : None
* Return         : None
*******************************************************************************/
void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat)
{
    UINT32 len;
    UINT8 i;

    if(initstat & SINT_STAT_RECV)                                               /* 接收中断 */
    {
        len = CH57xNET_SocketRecvLen(sockeid,NULL);                             /* 查询长度 */
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"Receive Len = %ld,sockeid : %d",len,sockeid);                          
		if (len > 0)
		{    
			if(server_info.dns_sta == DNS_WAIT_RECV)
			{
				CH57xNET_SocketRecv(sockeid,dns_buf,&len);
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS ReceiveLen = %ld",len);
				server_info.dns_flg = 1;                                        //标记DNS获取服务器ip成功
				i = CH57xNET_SocketClose( sockeid,TCP_CLOSE_NORMAL );
				mStopIfError(i);
				memset(SocketRecvBuf, 0, len);   //此处不清0将导致后面的套接字接收数据出错
			}
			else
			{
				#if  MQTT_EN
					if((0x01 == mqtt_info.init_flag) && (mqtt_info.mqtt_socket == sockeid))  //MQTT参数已初始化   mqtt套接字
					{
						uint8_t* data = malloc(len);
						if(data == NULL)   return;
						CH57xNET_SocketRecv(sockeid, data, &len);          /* 将接收缓冲区的数据读到MyBuf中*/
						Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"mqtt rec data:",data,len);
						LOG_NET_COMM_Recv_Record(mqtt_info.mqtt_socket,mqtt_info.des_ip,1883,data,len);

						switch(data[0]>>4)
						{
							case FLAG_CONNACK:
								Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT connack");
								mqtt_info.con_flag=1;
												MQTT_Subscribe(sockeid, mqtt_info.sub_topic);    //连接成功，发起订阅
								break;

							case FLAG_PUBLISH:   //接收到数据
							{
								unsigned char dup;
								unsigned short packetid;

								int qos;
								unsigned char retained;
								MQTTString topicName;
								unsigned char* payload;
								int payloadlen;
								
								MQTTDeserialize_publish(&dup,&qos,&retained,&packetid,&topicName,&payload,&payloadlen,data,len);
								Dbg_Println(DBG_BIT_NET_STATUS_bit,"payloadlen=%d",(UINT16)payloadlen);
								
								if((payloadlen + 2) > SRAM_MQTT_RECEIVE_LEN)
								{
									Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT Receive too long:%d", payloadlen);
								}
								else
								{
									Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT Receive DataLen:%d", payloadlen);
									
									SRAM_Write_Word(payloadlen, mqtt_info.Sram_write_addr);    //接收长度
									SRAM_Write_Buff(payload, payloadlen, mqtt_info.Sram_write_addr +2);   //数据内容
									
									mqtt_info.Sram_write_addr += SRAM_MQTT_RECEIVE_LEN;
									if(mqtt_info.Sram_write_addr >= SRAM_MQTT_RECEIVE_END)
									{
										mqtt_info.Sram_write_addr = SRAM_MQTT_RECEIVE_START;
									}
								}
								
//								MQTT_Publish(sockeid, NET485_PUBLISH, (uint8_t*)payload, payloadlen, 0);
//								if(payloadlen > SIMPLEPROFILE_CHAR4_LEN)  peripheralChar4Notify(payload, SIMPLEPROFILE_CHAR4_LEN);    //发给主机的数据固定使用 特征4的NOTIFY
//								else                 							 peripheralChar4Notify(payload, payloadlen);    //发给主机的数据固定使用 特征4的NOTIFY
							}
								
								break;
								
							case FLAG_SUBACK:    //订阅成功
								mqtt_info.sub_flag=1;
#if 0							
								if(mqtt_info.domain_name)
								{
									free(mqtt_info.domain_name);
									mqtt_info.domain_name = NULL;
								}
								if(mqtt_info.clientID)
								{
									free(mqtt_info.clientID);
									mqtt_info.clientID = NULL;
								}
								if(mqtt_info.username)
								{
									free(mqtt_info.username);
									mqtt_info.username = NULL;
								}
								if(mqtt_info.password)
								{
									free(mqtt_info.password);
									mqtt_info.password = NULL;
								}
								if(mqtt_info.sub_topic)
								{
									free(mqtt_info.sub_topic);
									mqtt_info.sub_topic = NULL;
								}
								if(mqtt_info.pub_topic)
								{
									free(mqtt_info.pub_topic);
									mqtt_info.pub_topic = NULL;
								}
#endif
								Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT suback");
								break;

							default:
								Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT MyBuf:%02X %02X", data[0], data[1]);
								break;
						}
						free(data);
					}
					
				 #endif
			}
		}
    }
    if(initstat & SINT_STAT_CONNECT)                                            	/* TCP连接中断 */
    {                                                                           	/* 产生此中断表示TCP已经连接，可以进行收发数据 */
        Dbg_Println(DBG_BIT_NET_STATUS_bit,"TCP Connect Success");    
				#if /*INTERRUPT_RECV_EN ||*/ MQTT_EN
				if((0x01 == mqtt_info.init_flag) && (mqtt_info.mqtt_socket == sockeid))  //MQTT参数已初始化   mqtt套接字
				{
					MQTT_Connect(sockeid, mqtt_info.clientID, mqtt_info.username, mqtt_info.password, mqtt_info.keepAliveInterval);
				}
					
				#endif	
    }
    if(initstat & SINT_STAT_DISCONNECT)                                         	/* TCP断开中断 */
    {                                                                           	/* 产生此中断，CH579库内部会将此socket清除，置为关闭*/
        Dbg_Println(DBG_BIT_NET_STATUS_bit,"TCP Disconnect");                    /* 应用曾需可以重新创建连接 */
				#if /*INTERRUPT_RECV_EN ||*/ MQTT_EN
				if((0x01 == mqtt_info.init_flag) && (mqtt_info.mqtt_socket == sockeid))  //MQTT参数已初始化   mqtt套接字
				{
					//CH57xNET_CreatTcpSocket();
					mqtt_info.con_flag = 0;    //连接断开
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT Disconnect MQTT Need Reconnect");	
//						server_info.init_flag = 0;		//网络环境变化 MQTT连接断开 需重新初始化网络  //Song
						mqtt_info.mqtt_sta = MQTT_RCON;       //2023-03-17
						mqtt_info.wait_cot = SysTick_10ms;    //2023-03-17
						LOG_SYS_PHY_Change_Record(0x03);  //网络环境变化 MQTT TCP断开
				}
					
				#endif	
		}
    if(initstat & SINT_STAT_TIM_OUT)                                            	/* TCP超时中断 */
    {                                                                           	/* 产生此中断，CH579库内部会将此socket清除，置为关闭*/
        Dbg_Println(DBG_BIT_NET_STATUS_bit,"sockeid %d TCP Timout",sockeid);                                                  	/* 应用曾需可以重新创建连接 */
		
				#if /*INTERRUPT_RECV_EN ||*/ MQTT_EN
				if((0x01 == mqtt_info.init_flag) && (mqtt_info.mqtt_socket == sockeid))  //MQTT参数已初始化   mqtt套接字
				{
					mqtt_info.con_flag = 0;    //连接断开
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT Timout MQTT Need Reconnect");
//						server_info.init_flag = 0;		//网络环境变化 MQTT连接超时 需重新初始化网络   //Song
						mqtt_info.mqtt_sta = MQTT_RCON;        //2023-03-17
						mqtt_info.wait_cot = SysTick_10ms;     //2023-03-17
						LOG_SYS_PHY_Change_Record(0x02);  //网络环境变化 MQTT TCP超时
				}
					
				#endif	
    }
}


/*******************************************************************************
* Function Name  : CH57xNET_HandleGloableInt
* Description    : 全局中断处理函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH57xNET_HandleGlobalInt(void)
{
	UINT8 initstat;
	UINT8 i;
	UINT8 socketinit;
	initstat = CH57xNET_GetGlobalInt();                                         	/* 读全局中断状态并清除 */
	if(initstat & GINT_STAT_UNREACH)                                            	/* 不可达中断 */
	{
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"UnreachCode ：%ld",CH57xInf.UnreachCode);                       /* 查看不可达代码 */
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"UnreachProto ：%ld",CH57xInf.UnreachProto);                     /* 查看不可达协议类型 */
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"UnreachPort ：%ld",CH57xInf.UnreachPort);                       /* 查询不可达端口 */   

	}
	if(initstat & GINT_STAT_IP_CONFLI)                                           	/* IP冲突中断 */
	{
		server_info.init_flag = 0;		//重新初始化网络
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"IP冲突中断",i);
	}
	if(initstat & GINT_STAT_PHY_CHANGE)                                          	/* PHY改变中断 */
	{	
		i = CH57xNET_GetPHYStatus();                                             	/* 获取PHY状态 */

		if(i == PHY_DISCONN)	
		{
			Dbg_Println(DBG_BIT_NET_STATUS_bit,"PHY断开,需重新初始化网络");
			server_info.init_flag = 0;		//PHY断开,需重新初始化网络
			LOG_SYS_PHY_Change_Record(0x00);	//网线拔出
		}

		Dbg_Println(DBG_BIT_NET_STATUS_bit,"GINT_STAT_PHY_CHANGE %02x",i);
	}
	if(initstat & GINT_STAT_SOCKET)                                              	/* Socket中断 */
	{
//	Dbg_Print(DBG_BIT_NET_STATUS_bit,"GINT_STAT_SOCKET\n");
		for(i = 0; i < CH57xNET_MAX_SOCKET_NUM; i ++)                     
		{
			socketinit = CH57xNET_GetSocketInt(i);                               	/* 读socket中断并清零 */
			if(socketinit)
			{
				//Dbg_Print(DBG_BIT_NET_STATUS_bit,"GINT_STAT_SOCKET, SOCKET_num:%d, socketinit:%d\n", i, socketinit);
				CH57xNET_HandleSockInt(i,socketinit);                  	/* 如果有中断则清零 */
			}
		}
	}
}

void UDPSocket1_AppCallBack(struct _SCOK_INF * SocketInf,UINT32 ipaddr,UINT16 port,UINT8 *buff,UINT32 len)
{

	UINT8 ip[4];
	ip[0] = ipaddr;
	ip[1] = ipaddr>>8;
	ip[2] = ipaddr>>16;
	ip[3] = ipaddr>>24;

	Dbg_Println(DBG_BIT_NET_STATUS_bit,"ip:%d.%d.%d.%d, port:%d",ip[0], ip[1], ip[2], ip[3], port);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"Socket1 len:%ld",len);

	Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"data :",buff,len);
	//Udp_Internal_Analysis(buff, len, ip, port);
	
	if(buff[0] == 0xAA)
	{
		switch(buff[1])
		{
			case 0x55:	//旧的服务器协议
				Udp_Internal_Analysis(buff, len, ip, port);
				break;
			case 0x66:	//UDP服务协议 - 2022-05-31
				//UDP_NetServer_Data_Analysis(buff, len, ip, port);
				break;
		}
		
	}
	
}

void UDPSocket2_AppCallBack(struct _SCOK_INF * SocketInf,UINT32 ipaddr,UINT16 port,UINT8 *buff,UINT32 len)
{
	//printf("UDPSocket_AppCallBack %08lX,%d,",ipaddr, port);
	UINT8 ip[4];
	ip[0] = ipaddr;
	ip[1] = ipaddr>>8;
	ip[2] = ipaddr>>16;
	ip[3] = ipaddr>>24;

	Dbg_Println(DBG_BIT_NET_STATUS_bit,"ip:%d.%d.%d.%d, port:%d",ip[0], ip[1], ip[2], ip[3], port);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"Socket2 len:%ld",len);

	TFTP_CMD_Analysis(buff, len, ip, port);
}

void UDPSocket3_AppCallBack(struct _SCOK_INF * SocketInf,UINT32 ipaddr,UINT16 port,UINT8 *buff,UINT32 len)
{

	UINT8 ip[4];
	ip[0] = ipaddr;
	ip[1] = ipaddr>>8;
	ip[2] = ipaddr>>16;
	ip[3] = ipaddr>>24;

	Dbg_Println(DBG_BIT_NET_STATUS_bit,"ip:%d.%d.%d.%d, port:%d",ip[0], ip[1], ip[2], ip[3], port);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"Socket3 len:%ld",len);

	TFTP_FILE_Analysis(buff, len, ip, port);
}

void UDPSocket4_AppCallBack(struct _SCOK_INF * SocketInf,UINT32 ipaddr,UINT16 port,UINT8 *buff,UINT32 len)
{
	UINT8 temp[4];
	temp[0] = ipaddr;
	temp[1] = ipaddr>>8;
	temp[2] = ipaddr>>16;
	temp[3] = ipaddr>>24;

	Dbg_Println(DBG_BIT_NET_STATUS_bit,"ip:%d.%d.%d.%d, port:%d",temp[0], temp[1], temp[2], temp[3], port);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"Socket4 Recive: %s",buff);
}


/*******************************************************************************
* Function Name  : UDPSocketParamInit
* Description    : 创建UDP socket
* Input          : socket索引值，源端口，
* Output         : None
* Return         : None
*******************************************************************************/
void UDPSocketParamInit2(UINT8* S, UINT16 SourPort, AppCallBack cb)
{
   UINT8 i;                                                             
   SOCK_INF TmpSocketInf;                                         	/* 创建临时socket变量 */

   memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));                	/* 库内部会将此变量复制，所以最好将临时变量先全部清零 */
  //memcpy((void *)TmpSocketInf.IPAddr,addr,4);                      	/* 设置目的IP地址 */
	TmpSocketInf.IPAddr[0] = 255;
	TmpSocketInf.IPAddr[1] = 255;
	TmpSocketInf.IPAddr[2] = 255;
	TmpSocketInf.IPAddr[3] = 255;
   TmpSocketInf.DesPort = SourPort;                                 /* 设置目的端口 */
   TmpSocketInf.SourPort = SourPort;                               	/* 设置源端口 */
   TmpSocketInf.ProtoType = PROTO_TYPE_UDP;                        	/* 设置socekt类型 */
   TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;            	/* 设置接收缓冲区的接收缓冲区 */
   TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;                        	/* 设置接收缓冲区的接收长度 */
#if APPCALLBACK_RECV_EN
	TmpSocketInf.AppCallBack = cb;									/* 设置接收回调函数 */
#endif
	 i = CH57xNET_SocketCreat(S,&TmpSocketInf);                     	/* 创建socket，将返回的socket索引保存在SocketId中 */
   mStopIfError(i);                                               	/* 检查错误 */
}




/*******************************************************************************
* Function Name  : DNS_SocketParamInit
* Description    : 创建UDP socket
* Input          : socket索引值，源端口，目的端口及目的IP
* Output         : None
* Return         : None
*******************************************************************************/
UINT8 DNS_SocketParamInit(UINT8* S,UINT8 *addr,UINT16 SourPort,UINT16 DesPort )
{
   UINT8 i;                                                             
   SOCK_INF TmpSocketInf;                                         	/* 创建临时socket变量 */

   memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF));                	/* 库内部会将此变量复制，所以最好将临时变量先全部清零 */
   memcpy((void *)TmpSocketInf.IPAddr,addr,4);                      	/* 设置目的IP地址 */
 
   TmpSocketInf.DesPort = DesPort;                                 	/* 设置目的端口 */
   TmpSocketInf.SourPort = SourPort;                               	/* 设置源端口 */
   TmpSocketInf.ProtoType = PROTO_TYPE_UDP;                        	/* 设置socekt类型 */
   TmpSocketInf.RecvStartPoint = (UINT32)SocketRecvBuf;            	/* 设置接收缓冲区的接收缓冲区 */
   TmpSocketInf.RecvBufLen = RECE_BUF_LEN ;                        	/* 设置接收缓冲区的接收长度 */
   //TmpSocketInf.AppCallBack = UDPSocket_AppCallBack;						  /* 设置接收回调函数 */
	 i = CH57xNET_SocketCreat(S, &TmpSocketInf);                     	/* 创建socket，将返回的socket索引保存在SocketId中 */
   mStopIfError(i);                                               	/* 检查错误 */
	 return i;
}


/*******************************************************************************
* Function Name  : CH57xNET_DHCPCallBack
* Description    : DHCP回调函数
* Input          : None
* Output         : None
* Return         : 执行状态
*******************************************************************************/
UINT8 CH57xNET_DHCPCallBack(UINT8 status,void *arg)
{
   UINT8 *p;
   
	if(!status){                                                                  /* 成功*/
		p = arg;                                                                  /* 产生此中断，CH57xNET库内部会将此socket清除，置为关闭*/
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP Success");
		memcpy(net_info.local_ip, p, 4);
		memcpy(net_info.gwip_addr, &p[4], 4);
		memcpy(net_info.mask, &p[8], 4);                                                   /* 产生此中断，CH57xNET库内部会将此socket清除，置为关闭*/
		//memcpy(DNS_SERVER_IP, &p[12], 4); 			//2022-03-02 DNS服务器IP采用DHCP分配的 , 2022-08-09 取消使用DHCP分配的DNS服务器
		
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"IPAddr = %d.%d.%d.%d",(UINT16)net_info.local_ip[0], (UINT16)net_info.local_ip[1],
			  (UINT16)net_info.local_ip[2], (UINT16)net_info.local_ip[3]);
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"GWIPAddr = %d.%d.%d.%d",(UINT16)net_info.gwip_addr[0], (UINT16)net_info.gwip_addr[1],
			  (UINT16)net_info.gwip_addr[2], (UINT16)net_info.gwip_addr[3]);
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"IPAddr = %d.%d.%d.%d",(UINT16)net_info.mask[0], (UINT16)net_info.mask[1],
			  (UINT16)net_info.mask[2], (UINT16)net_info.mask[3]);
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS1: %d.%d.%d.%d",DNS_SERVER_IP[0],DNS_SERVER_IP[1],DNS_SERVER_IP[2],DNS_SERVER_IP[3]);
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS2: %d.%d.%d.%d",p[16],p[17],p[18],p[19]);

		CH57xNET_DHCPStop();
		
		server_info.net_retry_num = 0;
		CH57xNET_SocketClose(net_info.SocketId[0],0x00);       //2023-05-27
		
		server_info.net_sta = NET_SOCKET_WAIT;
		
		server_info.wait_cot = SysTick_1ms;
		
		return SUCCESS;		
		
	}
	else{ 
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP Fail %02x",status);
		 return FAILED;
	}
	
}


/*******************************************************************************
* Function Name  : GetMacAddr
* Description    : 系统获取MAC地址
* Input          : pMAC:指向用来存储Mac地址的缓冲
* Output         : None
* Return         : None
*******************************************************************************/
void GetMacAddr(UINT8 *pMAC)
{
	UINT8 transbuf[6],i;
	
	GetMACAddress(transbuf);
	for(i=0;i<6;i++)
	{
		pMAC[5-i]=transbuf[i];
	
	}
}



/*******************************************************************************
* Function Name  : DNS_Restart
* Description    : 重启DNS,在DNS失败的情况下使用
* Input          : None
* Output         : None
* Return         : 返回1状态机繁忙，返回0成功
* 用  法         : 
*******************************************************************************/
UINT8 DNS_Restart()
{
	if(server_info.net_sta != NET_COMPLETE)   return 1;
	server_info.net_sta = NET_DNS;                //状态置为DNS
	return 0;
}


int is_valid_domain(const char *domain) 
{
    const char *c = domain;
    int parts = 0;
    int dashes = 0;
	
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_0:%s",domain);
 
    // 检查是否有连续的点或连字符
    if (strstr(domain, "..") || strstr(domain, "--")) 
	{
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_1");
        return 0;
    }
 
    // 检查每个字符
    while (*c) 
	{
        if (isalpha(*c) || isdigit(*c) || *c == '-' || *c == '.') 
		{
            if (*c == '-') 
			{
                // 不允许在开头或结尾出现连字符
                if (c == domain || *(c + 1) == '\0' || dashes == 0) 
				{
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_2");
                    return 0;
                }
                dashes = 0;
            } 
			else 
			{
                dashes = 1;
            }
        } 
		else 
		{
            // 非法字符
			Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_3:%c",*c);
            return 0;
        }
		
        if (*c == '.') 
		{
            parts++; // 分隔符计数
            if (c == domain || *(c + 1) == '\0') 
			{
                // 不允许在开头、结尾或者在两个点之间为空
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_4");
                return 0;
            }
        }
        c++;
    }
 
    // 至少需要两个部分（例如 example.com）
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"is_valid_domain_5:%d",parts);
    return parts > 1;
}

/*******************************************************************************
* Function Name  : Data_Conver_To_Uint16
* Description    : 将数组中的两位大端模式的数据转换为uint16_t的数据
* Input          : 
* Return         : None
*******************************************************************************/
uint16_t Data_Conver_To_Uint16(uint8_t *data)
{
	uint16_t temp_data = data[1];
	temp_data <<= 8;
	temp_data |= data[0];
	
	return temp_data;
}

/*******************************************************************************
* Function Name  : NetWork_Parameter_Get
* Description    : 网络任务 获取网络初始化参数以及网络初始化功能
* Input          : None
* Output         : None
* Return         : None
* 用  法         : 初始化调用
*******************************************************************************/
void NetWork_Parameter_Get(void)
{
	uint8_t Arge_Flag = 0;
	uint32_t temp = 0;
	
	/*判断网络是否使用设置参数为默认IP地址*/
	Arge_Flag = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_NetInfo_EN_OFFSET + 1);
	if(Arge_Flag == 0x01)
	{
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"NET 网络参数使用PC设置参数!");
		SRAM_Read_Buff(net_info.local_ip,4,SRAM_Register_Start_ADDRESS + Register_NetIP_OFFSET);
		SRAM_Read_Buff(net_info.gwip_addr,4,SRAM_Register_Start_ADDRESS + Register_NetGateway_OFFSET);
		SRAM_Read_Buff(net_info.mask,4,SRAM_Register_Start_ADDRESS + Register_NetMask_OFFSET);
		SRAM_Read_Buff(DNS_SERVER_IP,4,SRAM_Register_Start_ADDRESS + Register_DNSServerIP_OFFSET);
	}else {
		
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"NET 网络参数使用本机默认参数!");
		//MCU初始化IP
		net_info.local_ip[0] = 192;
		net_info.local_ip[1] = 168;
		net_info.local_ip[2] = MACAddr[4];    //2023-03-17
		net_info.local_ip[3] = MACAddr[5];    //2023-03-17
		//MCU初始网关
		net_info.gwip_addr[0] = 192;
		net_info.gwip_addr[1] = 168;
		net_info.gwip_addr[2] = MACAddr[4];   //2023-03-17
		net_info.gwip_addr[3] = 1;
		//MCU初始子网掩码
		net_info.mask[0] = 255;
		net_info.mask[1] = 255;
		net_info.mask[2] = 0;                 //2023-03-17
		net_info.mask[3] = 0;
		//MCU DNS地址
		DNS_SERVER_IP[0] = 223;
		DNS_SERVER_IP[1] = 5;
		DNS_SERVER_IP[2] = 5;
		DNS_SERVER_IP[3] = 5;
	}
	
	/*启用DHCP*/
	if(SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_NetInfo_EN_OFFSET) != 0x02)		
	{
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP功能使能!");
		server_info.dhcp_en = 0x01;
	}else{	/*不启用*/
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"不启用DHCP功能!");
		server_info.dhcp_en = 0x00;
	}
				
	/*判断当前使用本地服务器还是云端服务器*/
	temp = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_NetInfo_EN_OFFSET + 2);
	
	if(temp == 0x01)	//使用本地端服务器
	{
		server_info.server_select = 0x01;
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"使用本地端服务器");
	}else 	//使用云端端服务器
	{
		server_info.server_select = 0x00;
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"使用云端端服务器");
	}
	
	/*2024-04-08 start*/   
	memset(&tftp_log,0,sizeof(TFTP_LOG));

	SRAM_Read_Buff((uint8_t*)&tftp_log.Time,2,SRAM_Register_Start_ADDRESS + Register_TFTPLOGTime_OFFSET);
	
	SRAM_Read_Buff((uint8_t*)&tftp_log.Port,2,SRAM_Register_Start_ADDRESS + Register_TFTPLOGPort_OFFSET);
	
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp log port:%d time:%dh",tftp_log.Port,tftp_log.Time);
	
	if((tftp_log.Port == 0xFFFF) || (tftp_log.Port == 0x00))
	{
		tftp_log.Port = TFTP_Destination_Port;
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp log default port:%d",tftp_log.Port);
	}
	
	if((tftp_log.Time == 0x00) || (tftp_log.Time > 720))
	{
		tftp_log.Time = 720;   //1个月
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp log default time:%dh",tftp_log.Time);
	}
	
	tftp_log.DN_Lens = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_TFTPDmLens_OFFSET);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp log domain name lens:%d",tftp_log.DN_Lens);
	if(tftp_log.DN_Lens < DOMAINNAME_MAX)
	{
		SRAM_Read_Buff((uint8_t*)tftp_log.DomainName,tftp_log.DN_Lens,SRAM_Register_Start_ADDRESS + Register_TFTPDmName_OFFSET);
		tftp_log.DomainName[tftp_log.DN_Lens] = '\0';
	}

	if((tftp_log.DN_Lens == 0x00) || (is_valid_domain(tftp_log.DomainName) == 0x00))   //域名不合法使用默认
	{
		tftp_log.DN_Lens = sizeof(TFTPSERVER_NAME_DNS);
		if(tftp_log.DN_Lens < DOMAINNAME_MAX)
		{
			memcpy(tftp_log.DomainName,(char*)TFTPSERVER_NAME_DNS,sizeof(TFTPSERVER_NAME_DNS));
			tftp_log.DomainName[tftp_log.DN_Lens] = '\0';
		}
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"tftp domain name err,use default:%s",tftp_log.DomainName);
	}
	/*2024-04-08 end*/  

	//2025-10-11 读取服务器离线判定时间
	server_info.udp_online_time = SRAM_Read_DW(SRAM_Register_Start_ADDRESS + Register_NetOfflineTime_OFFSET);	
	if( (server_info.udp_online_time < 1000) || (server_info.udp_online_time > 7200000) )
	{
		server_info.udp_online_time = 600000;
	}
	
	//2025-10-11 读取UDP 定期上报时间间隔
	temp = SRAM_Read_DW(SRAM_Register_Start_ADDRESS + Register_UDPPeriodicTime_OFFSET);	
	if( (temp < 10000) || (temp > 7200000) )
	{
		server_info.udp_periodic_time = 60;
	}else {
		server_info.udp_periodic_time = temp / 1000;
	}
	
	//2025-10-11 读取服务器域名与端口
	temp = SRAM_Read_DW(SRAM_Register_Start_ADDRESS + Register_WebServerPort_OFFSET);	
	if( (temp == 0x00) || (temp >= 0xFFFF) )
	{
		//服务器端口不合法，使用默认端口 3339
		server_info.dis_port = 3339;
	}else {
		server_info.dis_port = temp & 0xFFFF;
	}
	
	temp = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_BLVServerDmLen_OFFSET);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"BLVServerDmName lens:%d",temp);
	if(temp < 64)
	{
		memset(net_info.ServerDename,0,sizeof(net_info.ServerDename));
		SRAM_Read_Buff((uint8_t*)net_info.ServerDename,temp,SRAM_Register_Start_ADDRESS + Register_BLVServerDmName_OFFSET);
		net_info.ServerDename[temp] = '\0';
	}

	if((temp == 0x00) || (is_valid_domain((char *)net_info.ServerDename) == 0x00))   //域名不合法使用默认
	{
		temp = sizeof(SERVER_NAME_DNS);
		if(temp < 64)
		{
			memcpy(net_info.ServerDename,(char*)SERVER_NAME_DNS,sizeof(SERVER_NAME_DNS));
			net_info.ServerDename[temp] = '\0';
		}
		Dbg_Println(DBG_BIT_NET_STATUS_bit,"BLVServerDmName err,use default:%s",net_info.ServerDename);
	}
	
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"MCU初始IP地址 : %d.%d.%d.%d",net_info.local_ip[0],net_info.local_ip[1],net_info.local_ip[2],net_info.local_ip[3]);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"MCU初始网关 : %d.%d.%d.%d",net_info.gwip_addr[0],net_info.gwip_addr[1],net_info.gwip_addr[2],net_info.gwip_addr[3]);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"MCU初始子网掩码 : %d.%d.%d.%d",net_info.mask[0],net_info.mask[1],net_info.mask[2],net_info.mask[3]);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"MCU DNS地址 : %d.%d.%d.%d",DNS_SERVER_IP[0],DNS_SERVER_IP[1],DNS_SERVER_IP[2],DNS_SERVER_IP[3]);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"TFTP Log Domain name:%s ",tftp_log.DomainName);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"BLVServerDmName : %s:%d ",net_info.ServerDename,server_info.dis_port);
	Dbg_Println(DBG_BIT_NET_STATUS_bit,"online_time:%d periodic_time:%d",server_info.udp_online_time,server_info.udp_periodic_time);
	LOG_SYS_NET_Argc_Init_Record(net_info.local_ip,net_info.gwip_addr,net_info.mask,DNS_SERVER_IP,Arge_Flag,server_info.dhcp_en,server_info.server_select);
}



/*******************************************************************************
* Function Name  : NetWork_Task
* Description    : 网络任务，包括库初始化，DHSP, DNS, socket创建, 发送数据
* Input          : None
* Output         : None
* Return         : None
* 用  法         : 主循环调用
*******************************************************************************/
uint8_t DNS_num = 0;
void NetWork_Task(void)
{
	//socket状态机，发送函数
	switch(server_info.net_sta)
	{
		case NET_INIT:                             //网络初始化
			{

				DNS_num = 0;
				server_info.init_flag = 0;					//网络开始初始化
				server_info.register_num = 0;
				
				server_info.dhcp_flg = 0;
				server_info.server_dns_flag = 0;
				server_info.tftp_dns_flag = 0;
				server_info.mqtt_dns_flag = 0;
				server_info.udp_sta = 0x01;
				server_info.Udp_Internal_sta = STA_INIT;	//UDP套接字状态
				server_info.online_state = 0;               //2023-10-07
				
				#if TFTP_GET_IP
				server_info.tftpip_gflag = 0x00;
				#endif
				
				#if MQTT_EN
				{
					mqtt_info.mqtt_sta = MQTT_DNS;       //2023-03-17
				}
				#endif
				
				NetWork_Parameter_Get();
				
				//GetMacAddr(MACAddr);                     	/* 获取自带的MAC地址 */
				CH57xNET_OpenMac();                      	//打开网络时钟
				
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"MACAddr : %02X.%02X.%02X.%02X.%02X.%02X",MACAddr[0],MACAddr[1],MACAddr[2],MACAddr[3],MACAddr[4],MACAddr[5]);
				UINT8 ret = CH57xNET_LibInit(net_info.local_ip, net_info.gwip_addr, net_info.mask, MACAddr);          	/* 库初始化 */
				mStopIfError(ret);                                                		/* 检查错误 */
				if(ret != CH57xNET_ERR_SUCCESS)    break;                          		//网络库初始化失败
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"CH57xNETLibInit Success");
				Timer0Init( 10000 );		                                       		/* 初始化定时器:10ms */
				NVIC_EnableIRQ(ETH_IRQn);	                                      		//开启以太网中断
				
				server_info.wait_cot = SysTick_10ms;
				server_info.net_sta = NET_PHY_WAIT;
				server_info.con_tick = SysTick_1s;        //2023-05-27
				
				server_info.udp_sta = 0x01;
				server_info.register_num = 0x00;
				server_info.udp_timesync_cnt = 0x00;
				server_info.udp_periodic_cnt = 0x00;
				server_info.udp_idle_tick = SysTick_1ms;
				server_info.udp_send_flag = 0x00;    
			}
			break;
		case NET_PHY_WAIT:                                          //等待PHY协商，如果协商不成功，网络将不可用
			if( CH57xInf.PHYStat < 2 )
			{
				if(SysTick_10ms - server_info.wait_cot > 3000)
				{
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"网络PHY协商失败，准备重新初始化网络");
					server_info.net_sta = NET_START_TO_INIT;
				}
				break;
			}else {
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"网线插入已插入，创建直连套接字");
				
				UDPSocketParamInit2(&net_info.SocketId[0], 3341, UDPSocket1_AppCallBack);    //创建套接字,局域网等待接收升级或配置发布等命令
				server_info.online_state = 1;               //2023-10-07
				server_info.wait_cot = SysTick_10ms;
				server_info.net_sta = NET_CON_WAIT;
				LOG_SYS_PHY_Change_Record(0x01);	//网线插入
			}
			break;
		case NET_START_TO_INIT:
			CH57xNET_CloseMac();   //关闭网络时钟
			server_info.wait_cot = SysTick_10ms;
			Dbg_Println(DBG_BIT_NET_STATUS_bit,"关闭MAC,准备重启网络");
			server_info.net_sta = NET_WAIT_MAC_RESTART;
			break;
		case NET_WAIT_MAC_RESTART:
			if(SysTick_10ms - server_info.wait_cot > 100)
			{
				server_info.wait_cot = SysTick_10ms;
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"重启网络中");
				server_info.net_sta = NET_INIT;
			}
			break;
		case NET_CON_WAIT:         //2023-05-26
			if(SysTick_10ms - server_info.wait_cot > 20)
			{
				server_info.wait_cot = SysTick_10ms;
				if(server_info.dhcp_en == 0x01)
				{
					server_info.net_sta = NET_DHCP;
				}else {
					server_info.net_sta = NET_DNS;
//					CH57xNET_SocketClose(net_info.SocketId[0],0x00);         //2023-05-27
				}
			}
			break;
		case NET_DHCP:    	//启动DHCP分配ip
			Dbg_Println(DBG_BIT_NET_STATUS_bit,"启动DHCP分配...");
			CH57xNET_DHCPStart(CH57xNET_DHCPCallBack);      /* 启动DHCP */
		
			server_info.wait_cot = SysTick_1ms;
			server_info.net_sta = NET_DHCP_WAIT;
			break;
		case NET_DHCP_WAIT:
			if(SysTick_1ms - server_info.wait_cot >= 10000)
			{
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP 耗时：%dms", SysTick_1ms - server_info.wait_cot);
				server_info.wait_cot = SysTick_1ms;
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP获取失败!");
				CH57xNET_DHCPStop();
				server_info.net_retry_num++;
				server_info.net_sta = NET_DHCP;	
				
				if(server_info.net_retry_num >= 3)
				{
					server_info.net_retry_num = 0;
					
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP重试次数已达上限!");
					server_info.net_sta = NET_START_TO_INIT;		//DHCP分配失败，直接重新初始化网络;
					
					CH57xNET_SocketClose(net_info.SocketId[0],0x00);     //2023-05-27
				}
			}
			break;
		case NET_SOCKET_WAIT:           //2023-05-29
			if(SysTick_1ms - server_info.wait_cot >= 200)
			{
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"DHCP成功，重新创建通讯套接字");
				UDPSocketParamInit2(&net_info.SocketId[0], 3341, UDPSocket1_AppCallBack);    //创建套接字,局域网等待接收升级或配置发布等命令
				server_info.net_sta = NET_DNS;
			}
			break;
		case NET_DNS:
			if(server_info.server_select == 0x00)
			{
				UINT8 ret = DnsQuery_Task(&net_info.SocketId[3], (UINT8*)net_info.ServerDename, server_info.dis_ip);      /* DNS查询 */
				if(ret == 1)                       							//DNS查询成功
				{
					server_info.dns_sta = DNS_INIT;
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"Domain name:%s", net_info.ServerDename);
					Dbg_Println(DBG_BIT_NET_STATUS_bit," HTTPs_IP=%d.%d.%d.%d",server_info.dis_ip[0], server_info.dis_ip[1], server_info.dis_ip[2], server_info.dis_ip[3]);
					
					if((server_info.dis_ip[0] == 0x00) && (server_info.dis_ip[1] == 0x00))	//无效地址
					{
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS 无效地址");
						server_info.net_sta = NET_DNS;
						DNS_num++;
						if(DNS_num > 5)
						{
							DNS_num = 0;
							server_info.server_dns_flag = 0x00;
							
							server_info.net_sta = NET_DNS2;		
							Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS失败");
							if(dns_buf)//不为空指针则释放DNS空间
							{
								free(dns_buf);     							//释放DNS空间
								dns_buf = NULL;
							}
						}
					}else {
						/*服务器域名解析成功*/
						server_info.server_dns_flag = 0x01;
						server_info.net_sta = NET_DNS2;
						
						if(dns_buf)
						{
							free(dns_buf);     							//释放DNS空间
							dns_buf = NULL;
						}
					}
				}
				else if(ret == 2)               //DNS失败将会使用初始化赋值的服务器ip地址
				{
					server_info.dns_sta = DNS_INIT;
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS超时");
					server_info.net_sta = NET_DNS;
					DNS_num++;
					if(DNS_num > 5)
					{
						DNS_num = 0;
						server_info.net_sta = NET_DNS2;
						
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS失败");
					}
				}
			}else if(server_info.server_select == 0x01)
			{
				/*采用本地服务器 - 直接设置服务器IP地址，跳过解析服务器域名这一步，解析域名标志位暂时没用上*/

				server_info.dis_ip[0] = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_WebServerIP_OFFSET + 0);
				server_info.dis_ip[1] = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_WebServerIP_OFFSET + 1);
				server_info.dis_ip[2] = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_WebServerIP_OFFSET + 2);
				server_info.dis_ip[3] = SRAM_Read_Byte(SRAM_Register_Start_ADDRESS + Register_WebServerIP_OFFSET + 3);
				
				server_info.server_dns_flag = 0x00;		
				server_info.net_sta = NET_DNS2;
				
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"采用本地服务器:%d.%d.%d.%d",server_info.dis_ip[0],server_info.dis_ip[1],server_info.dis_ip[2],server_info.dis_ip[3]);
			}
			break;
		case NET_DNS2:
			/*解析额外的UDP服务器域名*/
			{
				UINT8 ret = DnsQuery_Task(&net_info.SocketId[3], (UINT8*)UDPSERVER_NAME_DNS, server_info.udp_ip);      /* DNS查询 */
				if(ret == 1)                       							//DNS查询成功
				{
					server_info.dns_sta = DNS_INIT;
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"Domain name:%s", UDPSERVER_NAME_DNS);
					Dbg_Println(DBG_BIT_NET_STATUS_bit," HTTPs_IP=%d.%d.%d.%d",server_info.udp_ip[0], server_info.udp_ip[1], server_info.udp_ip[2], server_info.udp_ip[3]);
					
					if((server_info.udp_ip[0] == 0x00) && (server_info.udp_ip[1] == 0x00))	//无效地址
					{
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS 无效地址");
						server_info.net_sta = NET_DNS2;
						DNS_num++;
						if(DNS_num > 5)
						{
							DNS_num = 0;
							server_info.server_dns_flag = 0x00;
							
							server_info.net_sta = NET_TFTP;		
							Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS失败");
							if(dns_buf)
							{
								free(dns_buf);     							//释放DNS空间
								dns_buf = NULL;
							}
						}
					}else {
						/*服务器域名解析成功*/
						server_info.server_dns_flag = 0x01;
						server_info.net_sta = NET_TFTP;
						
						if(dns_buf)
						{
							free(dns_buf);     							//释放DNS空间
							dns_buf = NULL;
						}
					}
				}
				else if(ret == 2)               //DNS失败将会使用初始化赋值的服务器ip地址
				{
					server_info.dns_sta = DNS_INIT;
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS超时");
					server_info.net_sta = NET_DNS2;
					DNS_num++;
					if(DNS_num > 5)
					{
						DNS_num = 0;
						server_info.net_sta = NET_TFTP;
						
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS失败");
					}
				}
			}
			break;
		case NET_TFTP:
			{
				UINT8 ret = DnsQuery_Task(&net_info.SocketId[3], (UINT8*)tftp_log.DomainName, server_info.tftp_ip);      /* DNS查询 */
				if(ret == 1)                       							//DNS查询成功
				{
					server_info.dns_sta = DNS_INIT;
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"Domain name:%s",tftp_log.DomainName);
					Dbg_Println(DBG_BIT_NET_STATUS_bit," HTTPs_IP=%d.%d.%d.%d",server_info.tftp_ip[0], server_info.tftp_ip[1], server_info.tftp_ip[2], server_info.tftp_ip[3]);
					
					if((server_info.tftp_ip[0] == 0x00) && (server_info.tftp_ip[1] == 0x00))	//无效地址
					{
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS 无效地址");
						server_info.net_sta = NET_TFTP;
						DNS_num++;
						if(DNS_num > 5)
						{
							DNS_num = 0;

							server_info.net_sta = NET_COMPLETE;		
							Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS失败");
							if(dns_buf)
							{
								free(dns_buf);     							//释放DNS空间
								dns_buf = NULL;
							}
						}
					}else {
						/*TFTP服务器域名解析成功*/
						server_info.tftp_dns_flag = 0x01;
						server_info.net_sta = NET_COMPLETE;
						
						if(dns_buf)
						{
							free(dns_buf);     							//释放DNS空间
							dns_buf = NULL;
						}
					}
				}
				else if(ret == 2)               //DNS失败将会使用初始化赋值的服务器ip地址
				{
					
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS超时");
					//server_info.net_sta = NET_SOCKET;
					server_info.dns_sta = DNS_INIT;
					server_info.net_sta = NET_TFTP;
					DNS_num++;
					if(DNS_num > 5)
					{
						DNS_num = 0;

						server_info.net_sta = NET_COMPLETE;		
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS失败");
					}
					
				}
			}
			break;
		case NET_COMPLETE:
			
			Udp_Internal_Task();        				//内网处理任务（升级，发布配置）
		
			if(server_info.con_flag==0x01)        //2023-05-27
			{
				if(SysTick_1s - server_info.con_tick > 10)
				{
					server_info.con_flag = 0x00;
					server_info.con_tick = SysTick_1s;
					server_info.init_flag = 0x00;
					Dbg_Println(DBG_BIT_NET_STATUS_bit,"直连超时，重启网络");
				}
			}
			
			if(server_info.init_flag == 0x00)		//网络需要重新初始化
			{
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"网络重新初始化，关闭MAC");
				server_info.net_sta = NET_START_TO_INIT;
				
				server_info.online_state = 0;               //2023-10-07
				DevActionGlobal.TimeSyncFlag = 0x00;        //清除同步网络时间标记    2024-08-02
				
				/*释放套接字*/
				Dbg_Println(DBG_BIT_NET_STATUS_bit,"释放套接字");
				CH57xNET_SocketClose(net_info.SocketId[0],0x00);
				if(IAPVarTypeStruct_Ptr != NULL)
				{
					if(IAPSTART == IAPVarTypeStruct_Ptr->IapState)	
					{
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"TFTP 释放套接字");
						CH57xNET_SocketClose(net_info.SocketId[1],0x00);
						CH57xNET_SocketClose(net_info.SocketId[2],0x00);
						
						CH57xNET_CloseMac();                      //关闭网络时钟
						IAPVarTypeStruct_Ptr->IapState = IAPFINISH;
						free(IAPVarTypeStruct_Ptr);
						IAPVarTypeStruct_Ptr = NULL;
					}
				}
			}
			break;
		
		default: break;
	}
	
}



//2023-03-17
#if MQTT_EN

void Mqtt_Task()
{
	
	switch(mqtt_info.mqtt_sta)
	{
		case MQTT_DNS:
		{
			if((mqtt_info.init_flag == 0x01)&&(server_info.net_sta == NET_COMPLETE))          //2023-06-19
			{
				UINT8 ret = DnsQuery_Task(&net_info.SocketId[3], (UINT8*)mqtt_info.domain_name, mqtt_info.des_ip);      /* DNS查询 */
				if(ret == 1)                       							//DNS查询成功
				{
					server_info.dns_sta = DNS_INIT;
					Dbg_Print(DBG_BIT_NET_STATUS_bit,"Domain name:%s \n", mqtt_info.domain_name);
					Dbg_Print(DBG_BIT_NET_STATUS_bit," HTTPs_IP=%d.%d.%d.%d\n\n",mqtt_info.des_ip[0], mqtt_info.des_ip[1], mqtt_info.des_ip[2], mqtt_info.des_ip[3]);
					
					
					if((mqtt_info.des_ip[0] == 0x00) && (mqtt_info.des_ip[1] == 0x00))	//无效地址
					{
						Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS 无效地址");
						
						mqtt_info.mqtt_sta = MQTT_DNS;
						DNS_num++;
						if(DNS_num > 5)
						{
							DNS_num = 0;

							mqtt_info.mqtt_sta = MQTT_RCON;		
							Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS失败 - \n");
							if(dns_buf)
							{
								free(dns_buf);     							//释放DNS空间
								dns_buf = NULL;
							}
						}
					}else {
						/*服务器域名解析成功*/
						mqtt_info.mqtt_sta = MQTT_INIT;

						if(dns_buf)
						{
							free(dns_buf);     							//释放DNS空间
							dns_buf = NULL;
						}
					}
				}
				else if(ret == 2)               //DNS失败将会使用初始化赋值的服务器ip地址
				{
					
					Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS超时\n");
					server_info.dns_sta = DNS_INIT;
					mqtt_info.mqtt_sta = MQTT_DNS;
					DNS_num++;
					if(DNS_num > 5)
					{
						DNS_num = 0;
						mqtt_info.mqtt_sta = MQTT_RCON;		
						Dbg_Print(DBG_BIT_NET_STATUS_bit,"DNS失败 - \n");
					}
				}
			}
		}
			break;
		case MQTT_INIT:
			
			Dbg_Print(DBG_BIT_NET_STATUS_bit,"mqtt_info.init_flag:%d",mqtt_info.init_flag);
			if(mqtt_info.init_flag)
			{
				mqtt_info.mqtt_socket = Transport_Open(&mqtt_info, mqtt_info.des_ip, 49506);   //49506
				Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT发起连接：%d.%d.%d.%d\n",mqtt_info.des_ip[0], mqtt_info.des_ip[1], mqtt_info.des_ip[2], mqtt_info.des_ip[3]);
				Dbg_Print(DBG_BIT_NET_STATUS_bit,"mqtt_info.mqtt_socket：%d",mqtt_info.mqtt_socket);
								
				mqtt_info.wait_cot = SysTick_10ms;
				mqtt_info.mqtt_sta = MQTT_WAIT;
			}
			break;
			
		case MQTT_WAIT:
			if(mqtt_info.init_flag)
			{
				if(mqtt_info.con_flag == 0)  //未连接
				{
					if(SysTick_10ms - mqtt_info.wait_cot > 500)
					{
						mqtt_info.wait_cot = SysTick_10ms;
						Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT连接超时\n");
						
						if(mqtt_info.reconnect)
						{
							mqtt_info.reconnect--;
							mqtt_info.mqtt_sta = MQTT_INIT;
							CH57xNET_SocketClose(mqtt_info.mqtt_socket,SOCK_STAT_CLOSED );
							Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT等待重连...\n");
						}
						else
						{
							mqtt_info.mqtt_sta = MQTT_RCON;  //停止连接MQTT
						#if 0   //
							if(mqtt_info.domain_name)
							{
								free(mqtt_info.domain_name);
								mqtt_info.domain_name = NULL;
							}
							if(mqtt_info.clientID)
							{
								free(mqtt_info.clientID);
								mqtt_info.clientID = NULL;
							}
							if(mqtt_info.username)
							{
								free(mqtt_info.username);
								mqtt_info.username = NULL;
							}
							if(mqtt_info.password)
							{
								free(mqtt_info.password);
								mqtt_info.password = NULL;
							}
							if(mqtt_info.sub_topic)
							{
								free(mqtt_info.sub_topic);
								mqtt_info.sub_topic = NULL;
							}
							if(mqtt_info.pub_topic)
							{
								free(mqtt_info.pub_topic);
								mqtt_info.pub_topic = NULL;
							}
							#endif
							Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT2连接失败\n");
						}
					}
				}
				else
				{
					mqtt_info.mqtt_sta = MQTT_COMPLETE;  //连接成功
				}
			}
//			else if(mqtt_info2.init_flag)
//			{
//				if(mqtt_info2.con_flag == 0)  //未连接
//				{
//					if(SysTick_10ms - server_info.wait_cot > 500)
//					{
//						server_info.wait_cot = SysTick_10ms;
//						Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT2连接超时\n");
//						
//						if(mqtt_info2.reconnect)
//						{
//							mqtt_info2.reconnect--;
//							server_info.net_sta = NET_MQTT_INIT;
//							CH57xNET_SocketClose(mqtt_info2.mqtt_socket, SOCK_STAT_CLOSED);
//							Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT2等待重连...");
//						}
//						else
//						{
//							server_info.net_sta = NET_COMPLETE;  //停止连接MQTT
//							mqtt_info2.init_flag = 0;
//							Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT2连接失败");
//						}
//					}
//				}
//				else
//				{
//					server_info.net_sta = NET_COMPLETE;  //连接成功
//					mqtt_info2.init_flag = 0;
//				}
//			}
			break;
		case MQTT_COMPLETE:
			MQTT_Receive_Processing();
			break;
		case MQTT_RCON:
			mqtt_info.mqtt_cfail_num++;
//			Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT连接失败%d\n",mqtt_info.mqtt_cfail_num);
			CH57xNET_SocketClose(mqtt_info.mqtt_socket, TCP_CLOSE_RST );
//			Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT连接失败,1准备进入定期重连%d",mqtt_info.mqtt_cfail_num);
			
			
			if(SysTick_10ms - mqtt_info.wait_cot > 1000)
			{
				mqtt_info.wait_cot = SysTick_10ms;
				mqtt_info.mqtt_sta = MQTT_DNS;
			}
			
			if(mqtt_info.mqtt_cfail_num>=4)
			{
				Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT连接失败,准备进入定期重连%d\n",mqtt_info.mqtt_cfail_num);
				mqtt_info.mqtt_sta = MQTT_FAIL;
				mqtt_info.wait_cot = SysTick_1s;
			}
			
			break;
		case MQTT_FAIL:
			if(SysTick_1s - mqtt_info.wait_cot > 600)   //  600 10分钟重新连接
			{
				mqtt_info.wait_cot = SysTick_1s;
				mqtt_info.mqtt_cfail_num = 0;
				mqtt_info.mqtt_sta = MQTT_DNS;
				Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT连接失败,定期重新连接\n");
			}
			break;
		default:
			break;
	}
	
}

#endif






