#ifndef _DHCP_H_
#define _DHCP_H_

#include <stdio.h>
#include <string.h>
#include "CH57x_common.h"
#include "CH57xNET.H"
#include "DNS.h"
#include "BLV_NET_Function.h"

#define KEEPLIVE_ENABLE					1            	/* 开启KEEPLIVE功能 */
#define RECE_BUF_LEN    				536         	/* 接收缓冲区的大小 */

#define Net_NO_SERVER   				0x00      		//无服务器
#define Net_LOCAL_SERVER   				0x01      		//本地服务器
#define Net_CLOUD_SERVER   				0x02      		//云端服务器

#define INTERRUPT_RECV_EN       		0             	//禁用中断方式接收
#define APPCALLBACK_RECV_EN     		1             	//使能回调方式接收
#define USE_AUTO_OBTAIN_IP      		0          		//DHCP自动获取ip 	0：DHCP自动获取; 1：手动修改
#define USE_BLE_OBTAIN_IP       		1           	//蓝牙获取ip 
#define User_NET_DNS_EN					1				//NET DNS使能

#define SOCKET_TYPE_TCP        			1            	//发送TCP的套接字
#define SOCKET_TYPE_MQTT				2              	//发送MQTT的套接字
#define SOCKET_TYPE_UDP					3              	//发送UDP的套接字

#define NET_RESEND_TIMES        		3            	/*重发次数，最大值7，实际重发次数+1 */

#define USER_NET_Register_Timeout		30				//向服务器注册命令发送超时,单位：S
#define USER_NET_Send_Timeout			20				//发送数据等待回复时间,单位：S
#define USER_NET_Register_Times			10				//向服务器注册命令发送次数
#define USER_NET_Send_Times				10				//发送数据重发次数


typedef void (*AppCallBack)(struct _SCOK_INF *,UINT32 ,UINT16 ,UINT8 *,UINT32 ); /* 接收回调函数*/

typedef enum
{
	NET_INIT = 0,
	NET_PHY_WAIT,
	NET_DHCP,
	NET_DHCP_WAIT,
	NET_TFTP,
	NET_DNS,
	NET_DNS2,
	NET_WAIT,
	NET_COMPLETE,
	NET_MQTT_DNS,
	NET_MQTT_INIT,
	NET_MQTT_WAIT,
	NET_WAIT_MAC_RESTART,
	NET_START_TO_INIT,
	NET_CON_WAIT,
	NET_SOCKET_WAIT,
}NET_STA;

typedef enum
{
	MQTT_DNS = 0,
	MQTT_INIT,
	MQTT_WAIT,
	MQTT_COMPLETE,
	MQTT_RCON,
	MQTT_FAIL,
}MQTT_STA;    //2023-03-17

typedef enum
{
	SOCKET_SEND,
	SOCKET_RESEND,
	SOCKET_COMPLETE,
	
}SOCKET_STA;

typedef enum
{
	NET_STATUS_INIT = 0,       	//未初始化完成
	NET_STATUS_PHY_DISCONN,    	//网线未插入 或 PHY协商失败
	NET_STATUS_IP_CONFLI,      	//IP冲突
	NET_STATUS_UNREACH,        	//不可达错误
	NET_STATUS_NORMAL,         	//网络正常
	
}NET_STATUS;

#pragma pack(1)
typedef struct
{
	UINT8   local_ip[4];                      		//本地ip地址
	UINT8   gwip_addr[4];                        	//网关
	UINT8   mask[4];                         		//子网掩码
	UINT8   SocketId[4];                			//存放创建的套接字索引
	UINT8 	ServerDename[64];						//服务器域名	2025-10-11
}NET_INFO;

typedef struct
{
	uint8_t 	init_flag:1;						//初始化完成标志位
	uint8_t		register_flag:1;					//注册标志位
	uint8_t		search_ack_flag:1;					//发送标志位
	uint8_t		dhcp_en:1;							//DHCP是否启用
	uint8_t 	dns_sta:4;							//DNS状态
	
	uint8_t   	dhcp_flg:1;                     	//DHCP分配ip成功标志
	uint8_t   	dns_flg:1;                       	//DNS获取ip成功标志
	uint8_t 	Udp_Internal_sta:4;					//UDP状态机状态
	uint8_t   	PHY_State:2;                    	//NET PHY状态 0x00:当前网络未连接，0x01:当前网络已连接DNS状态
	
	uint8_t		register_num:4;						//注册计数
	uint8_t		dns_fail:4;							//DNS失败计数，用于切换DNS服务器使用
	
	uint8_t		server_dns_flag:1;					//DNS成功解析服务器域名
	uint8_t		tftp_dns_flag:1;					//DNS成功解析tftp服务器域名
	uint8_t		mqtt_dns_flag:1;					//MQTT成功解析域名标志位
	uint8_t     online_state:3;                 	//网络连接状态   0:离线 1:局域网在线  2:本地服务器在线 3:云端服务器在线
	uint8_t     sync_tick:2;                      	//同步时间标记
	
	uint8_t		udp_dns_flag:1;						//udp服务器解析域名标志位	
	uint8_t		server_select:1;					//服务器选择	0x00:默认云端服务器,0x01:本地服务器
	uint8_t 	net_retry_flag:1;					//网络重试标志位 - 
	uint8_t		net_retry_num:5;					//网络重试次数 - 比如DHCP重试次数，DNS重试次数
	
	uint8_t 	con_flag:1;      					//直连标记  
	uint8_t 	rcu_reboot_flag:1;					//RCU重启标志位
	uint8_t 	udp_scan_cnt:6;						//udp扫描计数
	
	uint8_t		active_cmd_flag;					//主动发送命令标志位

	uint8_t   	net_sta;                          	//网络状态机当前状态
		
	uint8_t   	dis_ip[4];                        	//云端服务器ip地址
	uint8_t   	tftp_ip[4];							//TFTP服务器
	uint8_t		udp_ip[4];							//额外的UDP服务器
	uint8_t  	goal_ip[4];                       	//目标ip, 
	uint16_t  	local_port;                       	//本地端口
	uint16_t 	goal_port;                        	//目标port
	uint16_t  	dis_port;                        	//云端服务器端口
	uint16_t 	frame_no;							//发送的帧号
	uint32_t 	wait_cot;                     		//等待计数
	
	uint32_t 	register_tick;						//注册计时
	uint32_t 	search_ack_tick;					//发送计时
	
	uint8_t 	udp_sta;        					//UDP任务状态机
	
	uint8_t 	udp_send_flag;  					//发送标记
	uint8_t 	udp_retry_cnt;						//重发次数
	uint8_t 	udp_retry_num;						//重发次数
	uint16_t 	ack_frame;							//ACK帧号
	
	uint16_t 	udp_timesync_cnt;					//时间同步次数 - 1s一次 
	uint16_t 	udp_periodic_cnt;					//定期上报次数 - 1s一次
	uint16_t 	udp_periodic_time;					//定期上报时间间隔 - 单位:S
	
	uint32_t 	udp_retry_tick; 					//重发超时时间戳
	uint32_t 	udp_retry_time;						//重发超时时间

	uint32_t 	con_tick;     						//直连时间戳     2023-05-27
	
	#if TFTP_GET_IP
	uint8_t tftpip_gflag;           //TFTP_IP下发标记
	#endif
	
	uint32_t 	udp_idle_tick;						//UDP空闲时间戳
	uint32_t 	udp_online_tick;					//UDP离线时间戳
	uint32_t 	udp_online_time;					//UDP离线判定时间

	
}__attribute__ ((__packed__)) NET_SERVER_INFO;


#pragma pack()

extern uint32_t SysTick_10ms;
extern NET_INFO  net_info;
extern NET_SERVER_INFO  server_info;
extern UINT8 MACAddr[6];                             		/* CH579MAC地址 */
extern UINT8 SocketRecvBuf[RECE_BUF_LEN];
extern TFTP_LOG tftp_log; 
extern uint8_t Global_Large_Buff[1100];

#if USE_INTERRUPT_RECV
extern UINT8 MyBuf[RECE_BUF_LEN];
#endif

void mStopIfError(UINT8 iError);
void CH57xNET_CreatTcpSocket(void);		

void CH57xNET_CreatTcpSocket_2(UINT8* S);

UINT8 CH57xNET_LibInit(/*const*/ UINT8 *ip,/*const*/ UINT8 *gwip,/*const*/ UINT8 *mask,/*const*/ UINT8 *macaddr);						
void CH57xNET_HandleSockInt(UINT8 sockeid,UINT8 initstat);
void CH57xNET_HandleGlobalInt(void);
//void UDPSocketParamInit(UINT8 S,UINT8 *addr,UINT16 SourPort,UINT16 DesPort );
//void UDPSocketParamInit1(UINT8 S,UINT8 *addr,UINT16 SourPort,UINT16 DesPort );
//void UDPSocketParamInit2(UINT8* S,UINT8 *addr,UINT16 SourPort,UINT16 DesPort );
void UDPSocketParamInit2(UINT8* S, UINT16 SourPort, AppCallBack cb);
UINT8 DNS_SocketParamInit(UINT8* S,UINT8 *addr,UINT16 SourPort,UINT16 DesPort );

void Timer0Init(UINT32 time);
UINT8 CH57xNET_DHCPCallBack(UINT8 status,void *arg);
void SystemClock_UART1_init(void);
void GetMacAddr(UINT8 *pMAC);


UINT8 Ethernet_Send_Start(UINT8 socketid, UINT8* buff, UINT16 len, UINT8* ip, UINT16 port);    //启动指定套接字发送数据
UINT8 DNS_Restart(void);                                               //DNS失败时，重启DNS
UINT8 UDP_Socket_Creat(void);                                          //创建一个UDP套接字，详细属性需要到NetWork_Task状态机的NET_SOCKET设置

void NetWork_Parameter_Get(void);
void NetWork_Task(void);                                               //网络任务状态机，主循环调用

uint16_t Data_Conver_To_Uint16(uint8_t *data);

void UDPSocket1_AppCallBack(struct _SCOK_INF * SocketInf,UINT32 ipaddr,UINT16 port,UINT8 *buff,UINT32 len);
void UDPSocket2_AppCallBack(struct _SCOK_INF * SocketInf,UINT32 ipaddr,UINT16 port,UINT8 *buff,UINT32 len);
void UDPSocket3_AppCallBack(struct _SCOK_INF * SocketInf,UINT32 ipaddr,UINT16 port,UINT8 *buff,UINT32 len);
void UDPSocket4_AppCallBack(struct _SCOK_INF * SocketInf,UINT32 ipaddr,UINT16 port,UINT8 *buff,UINT32 len);
#endif
