ESP8266学习笔记(11)——SNTP接口使用

一、SNTP简介

简单网络时间协议(Simple Network Time Protocol),由 NTP 改编而来,主要用来同步因特网中的计算机时钟

二、SNTP接口

SNTP 接口位于 ESP8266_NONOS_SDK/include/sntp.h


三、初始化SNTP

设置三个时间服务器域名并初始化。

/**
 @brief 初始化SNTP服务
 @param 无
 @return 无
*/
void ICACHE_FLASH_ATTR
SNTP_Init(void)
{
	sntp_setservername(0,"0.cn.pool.ntp.org");
	sntp_setservername(1,"1.cn.pool.ntp.org");
	sntp_setservername(2,"2.cn.pool.ntp.org");
	sntp_init();
}

四、获取SNTP时间

4.1 获取时间字符串

/**
 @brief 获取SNTP时间
 @param pRealTime -[in&out] 实时时间
 @return 无
*/
void ICACHE_FLASH_ATTR
GetSntpTime(char *pRealTime)
{
	uint32_t time = sntp_get_current_timestamp();
	os_sprintf(pRealTime, "%s", sntp_get_real_time(time));
	os_sprintf(pRealTime, "%s", sntpTimeChangeToSimpleDateFormat(pRealTime));
}

由于通过 sntp_get_real_time()函数 获取出来的时间字符串格式为Thu Dec 27 22:40:21 2018,不是我想要的格式,所以需要重新转换格式。

4.2 SNTP时间转化为简单日期格式

typedef struct sntpData_t
{
	uint8 week;
	uint8 month;
	uint8 day;
	uint8 hour;
	uint8 minute;
	uint8 second;
	uint8 year;
} SntpData_t;

/**
 @brief SNTP时间转化为简单日期格式
 @param pSntpRealTime -[in] 实时时间
 @return 简单日期格式时间字符串
*/
static char *ICACHE_FLASH_ATTR
sntpTimeChangeToSimpleDateFormat(char *pSntpRealTime)
{
	if(!pSntpRealTime)
	{
		return "";
	}

	pSntpRealTime[24] = '\0';						// 不要年份后面的数据
	SntpData_t sntpData;
	uint8 dateType[7] = {3, 3, 2, 2, 2, 2, 4};		// 3-Fri 3-May 2-31 2-11: 2-21: 2-42 4-2019
	uint8 temp[5];
	uint8 i = 0, j = 0;

	while(*pSntpRealTime != '\0')
	{
		if(*pSntpRealTime == ' ' || *pSntpRealTime == ':')
		{
			pSntpRealTime++;
			i++;
		}
		else
		{
			os_memset(temp, '\0', 5);
			for(j = 0; j < dateType[i]; j++)
			{
				temp[j] = *pSntpRealTime;
				pSntpRealTime++;
			}
			switch(i)
			{
			case 0: // 周
				sntpData.week = checkWahtWeek(temp);
				break;
			case 1: // 月
				sntpData.month = checkWahtMonth(temp);
				break;
			case 2: // 日
				sntpData.day = checkWahtDay(temp);
				break;
			case 3: // 时
				sntpData.hour = checkWahtHour(temp);
				break;
			case 4: // 分
				sntpData.minute = checkWahtMinute(temp);
				break;
			case 5: // 秒
				sntpData.second = checkWahtSecond(temp);
				break;
			case 6: // 年
				sntpData.year = checkWahtYear(temp);
				break;
			default:
				break;
			}
		}
	}

	os_memset(pSntpRealTime, 0, 24);
	os_sprintf(pSntpRealTime, "20%x-%02x-%02x %02x:%02x:%02x",
								sntpData.year, sntpData.month,
								sntpData.day, sntpData.hour,
								sntpData.minute, sntpData.second);
	return pSntpRealTime;
}

4.3 解析年月日时分秒

/**
 @brief 检查星期几
 @param pWeek -[in] 待检测字符串
 @return 星期几
*/
static uint8 ICACHE_FLASH_ATTR
checkWahtWeek(char *pWeek)
{
	if(!pWeek)
	{
		return 0;
	}

	uint8 week;
	if(strcmp(pWeek, "Mon") == 0)
	{
		week = 1;									// 星期一
	}
	else if(strcmp(pWeek, "Tue") == 0)
	{
		week = 2;									// 星期二
	}
	else if(strcmp(pWeek, "Wed") == 0)
	{
		week = 3;									// 星期三
	}
	else if(strcmp(pWeek, "Thu") == 0)
	{
		week = 4;									// 星期四
	}
	else if(strcmp(pWeek, "Fri") == 0)
	{
		week = 5;									// 星期五
	}
	else if(strcmp(pWeek, "Sat") == 0)
	{
		week = 6;									// 星期六
	}
	else if(strcmp(pWeek, "Sun") == 0)
	{
		week = 7;									// 星期天
	}
	return week;
}

/**
 @brief 检查几月份
 @param pMonth -[in] 待检测字符串
 @return 几月份
*/
static uint8 ICACHE_FLASH_ATTR
checkWahtMonth(char *pMonth)
{
	if(!pMonth)
	{
		return 0;
	}

	uint8 month;
	if(strcmp(pMonth, "Jan") == 0)
	{
		month = 1;									// 一月
	}
	else if(strcmp(pMonth, "Feb") == 0)
	{
		month = 2;									// 二月
	}
	else if(strcmp(pMonth, "Mar") == 0)
	{
		month = 3;									// 三月
	}
	else if(strcmp(pMonth, "Apr") == 0)
	{
		month = 4;									// 四月
	}
	else if(strcmp(pMonth, "May") == 0)
	{
		month = 5;									// 五月
	}
	else if(strcmp(pMonth, "Jun") == 0)
	{
		month = 6;									// 六月
	}
	else if(strcmp(pMonth, "Jul") == 0)
	{
		month = 7;									// 七月
	}
	else if(strcmp(pMonth, "Aug") == 0)
	{
		month = 8;									// 八月
	}
	else if(strcmp(pMonth, "Sep") == 0)
	{
		month = 9;									// 九月
	}
	else if(strcmp(pMonth, "Oct") == 0)
	{
		month = 10;									// 十月
	}
	else if(strcmp(pMonth, "Nov") == 0)
	{
		month = 11;									// 十一月
	}
	else if(strcmp(pMonth, "Dec") == 0)
	{
		month = 12;									// 十二月
	}
	return month;
}

/**
 @brief 检查几日
 @param pDay -[in] 待检测字符串
 @return 几日
*/
static uint8 ICACHE_FLASH_ATTR
checkWahtDay(char *pDay)
{
	if(!pDay)
	{
		return 0;
	}

	uint8 day = (*pDay & 0x0f) << 4;
	day = day | (*(pDay+1) & 0x0f);

	return day;
}

/**
 @brief 检查几时
 @param pHour -[in] 待检测字符串
 @return 几时
*/
static uint8 ICACHE_FLASH_ATTR
checkWahtHour(char *pHour)
{
	if(!pHour)
	{
		return 0;
	}

	uint8 hour = (*pHour & 0x0f) << 4;
	hour = hour | (*(pHour+1) & 0x0f);

	return hour;
}

/**
 @brief 检查几分
 @param pMinute -[in] 待检测字符串
 @return 几分
*/
static uint8 ICACHE_FLASH_ATTR
checkWahtMinute(char *pMinute)
{
	if(!pMinute)
	{
		return 0;
	}

	uint8 minute = (*pMinute & 0x0f) << 4;
	minute = minute | (*(pMinute+1) & 0x0f);

	return minute;
}

/**
 @brief 检查几秒
 @param pSecond -[in] 待检测字符串
 @return 几秒
*/
static uint8 ICACHE_FLASH_ATTR
checkWahtSecond(char *pSecond)
{
	if(!pSecond)
	{
		return 0;
	}

	uint8 second = (*pSecond & 0x0f) << 4;
	second = second | (*(pSecond+1) & 0x0f);

	return second;
}

/**
 @brief 检查几年
 @param pYear -[in] 待检测字符串
 @return 几年
*/
static uint8 ICACHE_FLASH_ATTR
checkWahtYear(char *pYear)
{
	if(!pYear)
	{
		return 0;
	}

	uint8 year = (*(pYear+2) & 0x0f) << 4;
	year = year | (*(pYear+3) & 0x0f);

	return year;
}

五、使用方法

首先,在 user_main.cuser_init() 中调用 SNTP_Init() 初始化。

void ICACHE_FLASH_ATTR
user_init(void)
{
  ···
  SNTP_Init();														// SNTP服务初始化
  ···
}

在其他地方调用 GetSntpTime() 获取时间

uint8 time[25];
GetSntpTime(time);
os_printf("%s\n", time);

获取到时间格式为:
2019-07-31 17:01:01


• 由 Leung 写于 2019 年 7 月 31日

• 参考:esp8266_SNTP时间获取处理成BCD码
    ESP8266 Non-OS SDK API参考[7qq6]

SNTP协议客户端实现以及数据包格式: LI:跳跃指示器,警告在当月最后一天的最终时刻插入的迫近闺秒(闺秒)。 VN:版本号。 Mode:工作模式。该字段包括以下值:0-预留;1-对称行为;3-客户机;4-服务器;5-广播;6-NTP控制信息。NTP协议具有3种工作模式,分别为主/被动对称模式、客户/服务器模式、广播模式。在主/被动对称模式中,有一对一的连接,双方均可同步对方或被对方同步,先发出申请建立连接的一方工作在主动模式下,另一方工作在被动模式下; 客户/服务器模 式与主/被动模式基本相同,惟一区别在于客户方可被服务器同步,但服务器不能被客户同步;在广播模式中,有一对多的连接,服务器不论客户工作 在何种模式下,都会主动发出时间信息,客户根据此信息调整自己的时间。 Stratum:对本地时钟级别的整体识别。 Poll:有符号整数表示连续信息间的最大间隔。 Precision:有符号整数表示本地时钟精确度。 Root Delay:表示到达主参考源的一次往复的总延迟,它是有15~16位小数部分的符号定点小 数。 Root Dispersion:表示一次到达主参考源的标准误差,它是有15~16位小数部分的无符号 定点小数。 Reference Identifier:识别特殊参考源。 Originate Timestamp:这是向服务器请求分离客户机的时间,采用64位时标格式。 Receive Timestamp:这是向服务器请求到达客户机的时间,采用64位时标格式。 Transmit Timestamp:这是向客户机答复分离服务器的时间,采用64位时标格式。 Authenticator(Optional):当实现了NTP认证模式时,主要标识符和信息数字域就 包括已定义的信息认证代码(MAC)信息。
### 回答1: ESP8266是一种低成本、高性能的Wi-Fi芯片,广泛应用于物联网(IoT)领域。SNTP(Simple Network Time Protocol)是一种基于UDP协议的时间同步协议,在物联网设备中具有重要的应用价值。 ESP8266通过SNTP协议与互联网中的时间服务器通信,获得准确的时间戳。这些时间戳可用于日志记录、事件触发、时间截止等应用场景。 SNTP协议本身非常简单,可以使用ESP8266的标准库集成到程序中。通过WiFi连接到局域网或互联网后,ESP8266可以与指定的时间服务器同步,获取与本地时间的时间差。为了准确,ES8266通常使用多个时间服务器进行同步,并进行平均计算。 值得注意的是,SNTP协议是基于UDP协议的,因此无法保证在传输过程中的可靠性。为了解决这个问题,ESP8266通常会定期进行时间同步,以保证时间准确性。当然,若是在时间同步失败的情况下采用短时间运行,错误也会相应地累积。因此,一些特殊的应用场景需要采用GPS等时间同步手段来确保时间的准确性。 总之,ESP8266通过SNTP协议可以快速、准确地获取互联网上的时间戳,因此在物联网设备的时间同步方面拥有巨大的应用潜力。 ### 回答2: ESP8266是一款低成本的Wi-Fi芯片,可以方便的接入互联网。SNTP(Simple Network Time Protocol)是一种简单的网络时间协议,用于同步网络设备的时间。 在ESP8266中,可以使用SNTP协议来同步设备的时间。通过连接SNTP服务器,ESP8266可以获取世界标准时间,并将其与本地时间进行比较和更新。这非常有用,因为设备的时间通常需要与其他设备同步,以便它们可以协调它们的操作。 ESP8266支持SNTP协议的库如下: • sntp.h • sntp.c 这些库可以在ESP8266的开发环境中进行安装和使用使用这些库,可以轻松地与SNTP服务进行通信,以便同步设备的时间。在使用这些库时,用户需要提供SNTP服务器的IP地址和端口号。然后,ESP8266会连接到服务器并获取当前的时间。 SNTP协议的一个重要特点是具有低带宽和延迟。这使得设备可以在非常低的成本和能耗下同步时间。由于ESP8266的能源需求非常低,因此使用SNTP协议进行时间同步是非常有效的方法。这使得ESP8266成为物联网设备设计的首选芯片之一。 ### 回答3: ESP8266是一款高性能、低功耗、易于开发的Wi-Fi芯片,可以通过SNTP协议进行时间同步。SNTP(Simple Network Time Protocol)是NTP协议的简化版本,用于进行网络时间同步。 在ESP8266使用SNTP进行时间同步,需要先通过WiFi连接到网络。然后,使用SNTP协议向NTP服务器请求时间信息,并将服务器返回的时间设定为ESP8266的系统时间。这个过程可以使用ESP8266自带的API实现,也可以使用第三方库完成。 使用SNTP同步时间有很多好处,其中最主要的就是可以保证设备时间的准确性。在一些需要高精度时间的应用场景,比如金融、物流等领域,时间同步显得尤为关键。 总之,ESP8266虽然是一款小巧的芯片,但它拥有丰富的功能和强大的性能,可以为各种物联网应用提供稳定可靠的支持。SNTP协议则是保证ESP8266时间准确性的重要手段之一。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leung_ManWah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值