ESP8266_SNTP(Simple Network Time Protocol)

1、SNTP 简单网络时间协议

SNTP协议采用客户端/服务器的工作方式,以UDP方式通信,SNTP服务器通过接收GPS信号或自带的原子钟作为系统的时间基准。

网络中存在很多台SNTP服务器,客户端会选择几台SNTP服务器使用。如果一台SNTP服务器在工作过程中失去了外部时间源,此时SNTP服务器会告诉SNTP客户端“我失去了外部时间”。当SNTP客户端收到这个信息时,会选择其他的SNTP服务器。

  • 单播模式下,SNTP客户端定期访问SNTP服务器获得准确的时间信息,用于调整客户端自身所在系统的时间,达到同步时间的目的。
  • 广播模式下,SNTP服务器周期性地发送消息给指定的IP广播地址或者IP多播地址。SNTP客户端通过监听这些地址来获得时间信息。

2、参考SDK编程手册的SNTP例程

  • 使能SNTP
    • 设置SNTP服务器,最多可设置3个SNTP服务器,可通过域名或IP地址设置;
    • 初始化SNTP,sntp_init();
  • 设置定时器,检查SNTP时间戳,例程100ms测一次有正确时间则停定时器,我用的是1s循环check;
  • 定时器回调
    • 如果时间戳不为0,则获取当前时间;

 

3、代码、结果

        默认是时间格式:“星期 月 日 时间 年”,比如“Mon Jun 25 23:13:15 2018”,不符合习惯,重新调整格式为“年 月 日 星期 时间”,没有这个需求直接向上面例程一样直接打印也可以;

//SNTP---------------BEGIN------------------------
//	 -----------------------------------------------			 -----------------------------------------------
//	|	  月份		|	英文简写	|	英文全称	|			|	  星期X		|	英文简写	|	英文全称	|
//	 -----------------------------------------------			 -----------------------------------------------
//	| 	  一月		|	  Jan		|	January		|			|	  周一		|	  Mon		|	Monday		|
//	 -----------------------------------------------			 -----------------------------------------------
//	|	  二月		|	  Feb		|	February	|			|	  周二		|	  Tue		|	Tuesday		|
//	 -----------------------------------------------			 -----------------------------------------------
//	| 	  三月		|	  Mar		|	March		|			|	  周三		|	  Wed		|	Wednesday	|
//	 -----------------------------------------------			 -----------------------------------------------
//	| 	  四月		|	  Apr		|	April		|			|	  周四		|	  Thu		|	Thursday	|
//	 -----------------------------------------------			 -----------------------------------------------
//	|  	  五月		|	  May		|	May			|			|	  周五		|	  Fri		|	Friday		|
//	 -----------------------------------------------			 -----------------------------------------------
//	|  	  六月		|	  June		|	June		|			|	  周六		|	  Sat		|	Saturday	|
//	 -----------------------------------------------			 -----------------------------------------------
//	|  	  七月		|	  July		|	July		|			|	  周日		|	  Sun		|	Sunday		|
//	 -----------------------------------------------			 -----------------------------------------------
//	|  	  八月		|	  Aug		|	Aguest		|
//	 -----------------------------------------------
//	|  	  九月		|	  Sept		|	September	|
//	 -----------------------------------------------
//	|  	  十月		|	  Oct		|	October		|
//	 -----------------------------------------------
//	|  	 十一月	    |	  Nov		|	November	|
//	 -----------------------------------------------
//	|  	 十二月	    |	  Dec		|	December	|
//	 -----------------------------------------------

os_timer_t timer_SNTP_check;					//检测SNTP的定时器

void ICACHE_FLASH_ATTR timer_SNTP_check_callback(void* arg)
{
	 uint32	TimeStamp;		// 时间戳
	 char * Str_RealTime;	// 实际时间的字符串

	char * Str_Head_Week;		// 【"星期"】字符串首地址
	char * Str_Head_Month;		// 【"月份"】字符串首地址
	char * Str_Head_Day;		// 【"日数"】字符串首地址
	char * Str_Head_Clock;		// 【"时钟"】字符串首地址
	char * Str_Head_Year;		// 【"年份"】字符串首地址

	char A_Str_Data[30] = {0};			//调整年月日时间之后的字符串
	char *T_A_Str_Data = A_Str_Data;	// 缓存数组指针

	 // 查询当前距离基准时间(1970.01.01 00:00:00 GMT+8)的时间戳(单位:秒)
	 TimeStamp = sntp_get_current_timestamp();

	 if(TimeStamp == 0){						// 判断是否获取到偏移时间
//		 os_timer_arm(&timer_SNTP_check,100,0);
	 }else{
//		 os_timer_disarm(&timer_SNTP_check);

		 // 查询实际时间(GMT+8):东八区(北京时间)
		 Str_RealTime = sntp_get_real_time(TimeStamp);

		 // 【实际时间】字符串 == "周 月 日 时:分:秒 年"
		 os_printf("SNTP_TimeStamp = %d\n",TimeStamp);		// 时间戳
		 os_printf("SNTP_InternetTime = %s\n",Str_RealTime);	// 实际时间

		 //只有月份的缩写字符个数是不确定的
		 Str_Head_Week 	= Str_RealTime;							// "星期" 字符串的首地址
		 Str_Head_Month = strstr(Str_Head_Week,	" ") + 1;	// "月份" 字符串的首地址
		 Str_Head_Day 	= strstr(Str_Head_Month,	" ") + 1;	// "日数" 字符串的首地址
		 Str_Head_Clock = strstr(Str_Head_Day,	" ") + 1;	// "时钟" 字符串的首地址
		 Str_Head_Year  = Str_Head_Clock + 9;					//年份

		 os_memcpy(T_A_Str_Data, Str_Head_Year, 4);
		 A_Str_Data[4] = ' ';
		 T_A_Str_Data += 5;
		 if(Str_Head_Day - Str_Head_Month == 4){				//月份是3字节
			 os_memcpy(T_A_Str_Data, Str_Head_Month, 4);		//多的1字节是自带的空格
			 T_A_Str_Data += 4;
		 }else{
			 os_memcpy(T_A_Str_Data, Str_Head_Month, 5);		//多的1字节是自带的空格
			 T_A_Str_Data += 5;
		 }
		 if(Str_Head_Clock - Str_Head_Day == 2){				//day是1字节
			 os_memcpy(T_A_Str_Data, Str_Head_Day, 2);		//多的1字节是自带的空格
			 T_A_Str_Data += 2;
		 }else{													//day是2字节
			 os_memcpy(T_A_Str_Data, Str_Head_Day, 3);		//多的1字节是自带的空格
			 T_A_Str_Data += 3;
		 }
		 os_memcpy(T_A_Str_Data, Str_Head_Week, 4);			//
		 T_A_Str_Data += 4;

		 os_memcpy(T_A_Str_Data, Str_Head_Clock, 8);		//00:00:00
		 T_A_Str_Data += 8;
		 *T_A_Str_Data = '\0';								// 【"日期"】字符串后面添加'\0'

		 os_printf("data = %s\n",A_Str_Data);
		 oled_show_string(0,2,A_Str_Data,FONT_8x16);

	 }
}

// 初始化SNTP
void ICACHE_FLASH_ATTR SNTP_initial(void)
{
	ip_addr_t * addr = (ip_addr_t *)os_zalloc(sizeof(ip_addr_t));

//	sntp_setservername(0, "us.pool.ntp.org");	// 服务器_0【域名】
	sntp_setservername(0, "0.cn.pool.ntp.org");	// 服务器_0【域名】
	sntp_setservername(1, "ntp.sjtu.edu.cn");	// 服务器_1【域名】
	ipaddr_aton("210.72.145.44", addr);			// 点分十进制 => 32位二进制
	sntp_setserver(2, addr);					// 服务器_2【IP地址】
	os_free(addr);								// 释放addr

	sntp_init();								// SNTP初始化API

	os_timer_disarm(&timer_SNTP_check);
	os_timer_setfn(&timer_SNTP_check,timer_SNTP_check_callback,NULL);
	os_timer_arm(&timer_SNTP_check,1000,1);		//1000ms
}

//SNTP-------------------END--------------------------------

 

参考链接:

sntp_百度百科 (baidu.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值