赞
踩
本文基于ESP_IDF5.0 powershell 编译、下载等操作,VS code代码编辑 ,fireTools 串口调试工具打印log ,飞书文档管理和项目沟通等操作。
ESP32S3开发项目是常用的世界协调时间(UTC),那么智能设备同步网络时间是非常必要的,这篇文章将提供两种网络时间校准的方法,一种是通过网络时间服务器(SNTP)上获取的,另一种通过自定义指令同步设备UTC。
SNTP 指简单网络时间协议(Simple Network Time Protocol),使用非常简单,如下,联网判断成功后,
创建一个SNTP 校准时间的任务,代码及其简洁和干净
//创建一个SNTP 校准时间的任务 xTaskCreate(&sntp_task, "sntp_task", 1024 * 4, NULL, 6, NULL); //SNTP 校准时间的任务 void sntp_task(void *pvParameter) { sntp_setoperatingmode(SNTP_OPMODE_POLL); //单播模式 sntp_setservername(0, "ntp1.aliyun.com"); //阿里云ntp1服务 sntp_setservername(1, "ntp2.aliyun.com"); //阿里云ntp2服务 sntp_setservername(2, "ntp3.aliyun.com"); //阿里云ntp3服务 //设置时区 setenv("TZ", "CST-8", 1); //东八区 sntp_init(); //sntp初始化 time_t now = 0; struct tm timeinfo = { 0 }; int sntp_retry_cnt = 0; int sntp_retry_time = 0; while (1) {//直到获取成功,才退出循环 for (int32_t i = 0; (i < (SNTP_RECV_TIMEOUT / 100)) && timeinfo.tm_year < (2019 - 1900); i ++) { vTaskDelay(100 / portTICK_PERIOD_MS); time(&now); localtime_r(&now, &timeinfo);//时间戳转化为本地时间结构 } if (timeinfo.tm_year < (2019 - 1900) && sntp_retry_cnt < (SNTP_RECV_TIMEOUT / 100)) { sntp_retry_time = SNTP_RECV_TIMEOUT << sntp_retry_cnt; if (SNTP_RECV_TIMEOUT << (sntp_retry_cnt + 1) < SNTP_RETRY_TIMEOUT_MAX) { sntp_retry_cnt ++; //sntp尝试次数累加 } ESP_LOGI(TAG,"SNTP get time failed, retry after %d ms\n", sntp_retry_time); vTaskDelay(sntp_retry_time / portTICK_PERIOD_MS);//延时时间 } else { ESP_LOGI(TAG,"SNTP get time success\n"); break; //获取时间成功,退出循环 } } sntp_stop(); long timenow=time(NULL); ESP_LOGI(TAG,"网络时间同步:%ld\r\n",timenow); vTaskDelete(NULL); // 删除任务 }
有了SNTP网络时间同步,为什么还需要考虑指令同步呢?
1:实际测试过程中,SNTP服务获取网络时间不是实时的,需要等待一段时间才能同步。
2:实际测试过程中,ESP32S3的 UTC校时后,运行一段时间后,实际设备里的UTC和网络UTC误差很大,频繁调用SNTP负担很重。
如上UTC时间是大部分系统是定义为long型,也就是4个字节就可以定义UTC,那么我们通过MQTT协议自定义一个指令,服务器向ESP32S3发送携带4个字节UTC指令即可立刻同步时间,非常高效简洁
MQTT的通讯,省略…
void SET_A2_11(unsigned char *data, unsigned char data_len) //UTC对时 { if (data_len == 4) { //4个字节数据组合 devicestation.NOW_UTC=(data[0]<<24)+(data[1]<<16)+(data[2]<<8)+data[3]; struct timeval tv; tv.tv_sec = devicestation.NOW_UTC; tv.tv_usec = 0; // long timenow = time(NULL); if(settimeofday(&tv,NULL)==ESP_OK) { ESP_LOGI(TAG, "A2 11 UTC对时:%lld",tv.tv_sec); } else { ESP_LOGI(TAG, "A2 11 UTC对时失败:%lld",tv.tv_sec); } } }
指令校准更加简单
主要用到函数settimeofday()
int settimeofday(const struct timeval *tv, const struct timezone *tz)
测试完成校验成功。
SNTP校准时间不需要搭建服务器,直接选用免费NTP服务器即可,但是不确定增加,校时效率比较慢。可以结合MQTT指令校时方法,在项目开发上两个都可以使用,实际上非常实用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。