【NodeMCU实时天气时钟温湿度项目 4】通过NTPClient库获取实时网络时间并显示在TFT屏幕上

        今天是【实时天气时钟温湿度项目】第四专题,主要内容是:学习导入NTPClient库,通过这个库获取实时网络时间,显示在1.3寸TFT液晶屏幕上。此前三个专题,请选择查看以下链接。

        第一专题内容,请参考
        【NodeMCU实时天气时钟温湿度项目 1】连接点亮SPI-TFT屏幕和UI布局设计-CSDN博客
        第二专题内容,请参考
        【NodeMCU实时天气时钟温湿度项目 2】WIFI模式设置及连接-CSDN博客
        第三专题内容,请参考       
【NodeMCU实时天气时钟温湿度项目 3】连接SHT30传感器,获取并显示当前环境温湿度数据(I2C)-CSDN博客
        NTPClient功能库有关内容,请参考
        【Arduino】NTPClient:连接NTP服务器获取实时网络时间_ntpclient.h-CSDN博客

一、添加NTPClient库

        获取实时网络时间,一般通过 NTP (网络时间协议)服务器来实现。在Arduino框架下,我们通过NTPClient库提供的函数功能,连接到NTP服务器,从服务器获取时间,并保持同步。
        添加库的方法:打开 PlatformIO 界面,选择 Libraries 图标,在搜索栏内输入 NTPClient,在查询结果中选择NTPClient库,,添加到本项目中。

二、NTPClient官方示例代码及主要函数

        下面是NTPClient库官方示例 Advanced.info 的代码内容,将其全文复制到主文件 main.cpp 中,添加库,编译上传到NodeMCU开发板,就可以正常运行了。
        提醒:请务必将 ssid 和 password ,变更为您所在环境的 AP访问点名称和密码。       

#include <NTPClient.h>
// change next line to use with another board/shield
#include <ESP8266WiFi.h>
//#include <WiFi.h> // for WiFi shield
//#include <WiFi101.h> // for WiFi 101 shield or MKR1000
#include <WiFiUdp.h>const char *ssid     = "xcb940";
const char *password = "87589940abc";WiFiUDP ntpUDP;// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionally you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);void setup(){Serial.begin(115200);WiFi.begin(ssid, password);while ( WiFi.status() != WL_CONNECTED ) {delay ( 500 );Serial.print ( "." );}timeClient.begin();
}void loop() {timeClient.update();Serial.println(timeClient.getFormattedTime());delay(1000);
}

下图是程序正常运行后的模样。

        特别说明:关于NTPClient库的介绍和应用,我在前期曾发布过一个博文,对这个库作了详细介绍。官方示例中涉及到的功能函数,在博文中都有详细介绍,具体内容请点击下面的链接查看:【Arduino】NTPClient:连接NTP服务器获取实时网络时间_ntpclient.h-CSDN博客

三、本项目关于获取网络时间函数说明       

        通过NTPClient功能库获取网络时间的代码,封装在项目的 ntptime.h 文件中,主要有以下4个功能函数。
        (1)void initNtp(),启动NTPClient,开始客户端与NTP服务器同步、获取UTC时间,填充时日期时间数据结构 struct dt_data;设置时区偏移量(28800 = 60 * 60 * 8 秒)。

void initNtp() {timeClient.begin();//28800 = +8时区(我们的北京时间)timeClient.setTimeOffset(28800);loopNtp();
}
struct dt_data {String localDate = "";String localTime = "";String y;String m;String d;String h;String i;String s;uint16_t year;uint8_t month;uint8_t day;uint8_t hours;uint8_t minutes;uint8_t seconds;
} dt;

        (2)void loopNtp(),获取UTC时间,进行格式转换,填充时日期时间数据结构 struct dt_data;每调用一次,获取一次时间。

void loopNtp() {timeClient.update();Serial.println(timeClient.getFormattedTime());//获取unix时间戳(1970年至今的总秒数)unsigned long epochTime = timeClient.getEpochTime();Serial.print("epochTime: ");Serial.println(epochTime);//格式化得到 时:分:秒dt.localTime = timeClient.getFormattedTime();//重新计算得到 年-月-日time_t rawtime = epochTime;struct tm * ti;ti = localtime (&rawtime);dt.year = ti->tm_year + 1900;dt.y = String(dt.year);dt.month = ti->tm_mon + 1;dt.m = dt.month < 10 ? "0" + String(dt.month) : String(dt.month);dt.day = ti->tm_mday;dt.d = dt.day < 10 ? "0" + String(dt.day) : String(dt.day);dt.hours = ti->tm_hour;dt.h = dt.hours < 10 ? "0" + String(dt.hours) : String(dt.hours);dt.minutes = ti->tm_min;dt.i = dt.minutes < 10 ? "0" + String(dt.minutes) : String(dt.minutes);dt.seconds = ti->tm_sec;dt.s = dt.seconds < 10 ? "0" + String(dt.seconds) : String(dt.seconds);//将得到的年月日写入weather_data 结构体dt.localDate = dt.y + "-" + dt.m + "-" + dt.d;//Serial.println(dt.h + "-" + dt.i + "-" + dt.s);
}

        (3)LunarDate LunarCalendar(int year, int month, int day),将阳历的年月日转换成阴历的年月日,存放到结构体 struct LunarDate 中。

LunarDate LunarCalendar(int year, int month, int day)
{int Spring_NY, Sun_NY, StaticDayCount;int index, flag;//Spring_NY 记录春节离当年元旦的天数。//Sun_NY 记录阳历日离当年元旦的天数。if ( ((LunarCalendarTable[year - 1901] & 0x0060) >> 5) == 1)Spring_NY = (LunarCalendarTable[year - 1901] & 0x001F) - 1;elseSpring_NY = (LunarCalendarTable[year - 1901] & 0x001F) - 1 + 31;Sun_NY = MonthAdd[month - 1] + day - 1;if ( (!(year % 4)) && (month > 2))Sun_NY++;//StaticDayCount记录大小月的天数 29 或30//index 记录从哪个月开始来计算。//flag 是用来对闰月的特殊处理。//判断阳历日在春节前还是春节后if (Sun_NY >= Spring_NY)//阳历日在春节后(含春节那天){Sun_NY -= Spring_NY;month = 1;index = 1;flag = 0;if ( ( LunarCalendarTable[year - 1901] & (0x80000 >> (index - 1)) ) == 0)StaticDayCount = 29;elseStaticDayCount = 30;while (Sun_NY >= StaticDayCount){Sun_NY -= StaticDayCount;index++;if (month == ((LunarCalendarTable[year - 1901] & 0xF00000) >> 20) ){flag = ~flag;if (flag == 0)month++;}elsemonth++;if ( ( LunarCalendarTable[year - 1901] & (0x80000 >> (index - 1)) ) == 0)StaticDayCount = 29;elseStaticDayCount = 30;}day = Sun_NY + 1;}else //阳历日在春节前{Spring_NY -= Sun_NY;year--;month = 12;if ( ((LunarCalendarTable[year - 1901] & 0xF00000) >> 20) == 0)index = 12;elseindex = 13;flag = 0;if ( ( LunarCalendarTable[year - 1901] & (0x80000 >> (index - 1)) ) == 0)StaticDayCount = 29;elseStaticDayCount = 30;while (Spring_NY > StaticDayCount){Spring_NY -= StaticDayCount;index--;if (flag == 0)month--;if (month == ((LunarCalendarTable[year - 1901] & 0xF00000) >> 20))flag = ~flag;if ( ( LunarCalendarTable[year - 1901] & (0x80000 >> (index - 1)) ) == 0)StaticDayCount = 29;elseStaticDayCount = 30;}day = StaticDayCount - Spring_NY + 1;}LunarCalendarDay |= day;LunarCalendarDay |= (month << 6);LunarDate d;d.year = year;d.month = month;d.day = day;if (month == ((LunarCalendarTable[year - 1901] & 0xF00000) >> 20))d.leap =  1;elsed.leap =  0;return d;
}String outputLunarDate(int year, int month, int day) {LunarDate ld = LunarCalendar(year, month, day);String str = "";if (ld.leap) {str += "闰";} else {str += " ";}str += ChMonth[ld.month] + ChDay[ld.day];return str;
}

        (4)String weekOfDate1(int year, int month, int day),将阳历的年月日转换为星期几。

String weekOfDate1(int year, int month, int day)
{int adjustment, mm, yy;if (year < 2000) year += 2000;adjustment = (14 - month) / 12;mm = month + 12 * adjustment - 2;yy = year - adjustment;int week = (day + (13 * mm - 1) / 5 +yy + yy / 4 - yy / 100 + yy / 400) % 7;return weekly[week];
}

        说明:本程序主要内容,来源于网络大神,如有异议,请及时联系作者。

四、项目运行结果视频展示

        本阶段TFT屏幕上部,第一行,可以显示阳历日期、星期几、农历日期;第二行显示实时网络时间(东八东,偏移量28800秒),每秒更新一次;
        中部,实时天气和明天天气预报部分,目前仍显示静态画展,没有加入实时获取天气信息的代码。
        下部,显示当前所在环境实时的温度和湿度数据,每3秒更新一次。        

WeatherClock_exalmpl4

五、项目第四专题代码下载

        百度网盘下载链接:
        https://pan.baidu.com/s/1tBrHF5KNcwBR-2-HXvNQdw?pwd=bw9e,提取码:bw9e

        参考文档
        1. NTPClient 部分源代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/7900.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用wxPython和pandas模块生成Excel文件

介绍&#xff1a; 在Python编程中&#xff0c;有时我们需要根据特定的数据生成Excel文件。本文将介绍如何使用wxPython和pandas模块来实现这个目标。我们将创建一个简单的GUI应用程序&#xff0c;允许用户选择输出文件夹和输入的Excel文件&#xff0c;并根据Excel文件中每个单…

docker jenkins 部署springboot项目

1、创建jenkins容器 1&#xff0c;首先&#xff0c;我们需要创建一个 Jenkins 数据卷&#xff0c;用于存储 Jenkins 的配置信息。可以通过以下命令创建一个数据卷&#xff1a; docker volume create jenkins_data启动 Jenkins 容器并挂载数据卷&#xff1a; docker run -dit…

算法-并查集

目录 什么是并查集 并查集基础 &#xff08;1&#xff09;原理 &#xff08;2&#xff09;初始化 &#xff08;3&#xff09;查询 &#xff08;4&#xff09;合并 &#xff08;5&#xff09;判断是否同一集合 并查集优化 路径压缩 启发式合并 并查集模板 模板 例题…

C#修改默认参数settings文件

右击项目在设置中进行修改&#xff1a; 千万不要在这里改。 如果要在自己的项目里添加这个文件&#xff0c;首先新建个文件夹&#xff0c;然后添加.setting文件&#xff0c;然后再像上面说的那样添加属性。

4.请求体

什么是请求体(Request Body) 请求体是客户端发送到API的数据。 响应体是API发送给客户端的数据 API几乎总是必须发送一个响应体&#xff0c;但是客户端并不需要一直发送请求体 定义请求体&#xff0c;需要使用 Pydantic 模型 不能通过GET请求发送请求体发送请求体数据&…

常见的容器技术有哪些

容器技术是一种轻量级的软件封装方式&#xff0c;它将软件代码及其依赖项打包在一起&#xff0c;这样应用可以在任何支持容器的系统上无缝运行。它允许应用程序及其依赖项在一个隔离的环境中运行&#xff0c;这个环境被称为容器。容器技术有助于提高应用程序的可移植性、一致性…

深度学习之基于Tensorflow卷积神经网络智能体操健身系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着人们健康意识的提高和数字化技术的快速发展&#xff0c;智能健身系统逐渐成为健身领域的新趋势。…

Redis之Linux下的安装配置

Redis之Linux下的安装配置 Redis下载 Linux下下载源码安装配置 方式一 官网下载&#xff1a;https://redis.io/download ​ 其他版本下载&#xff1a;https://download.redis.io/releases/ 方式二&#xff08;推荐&#xff09; GitHub下载&#xff1a;https://github.com/r…

景源畅信:个人抖音小店怎么开通?

在数字时代的浪潮中&#xff0c;个体创业已不再是遥不可及的梦想。特别是随着短视频平台的崛起&#xff0c;抖音不仅成为人们娱乐消遣的新宠&#xff0c;更是众多创业者眼中的“新大陆”。你是否也曾憧憬过在抖音上开一家属于自己的小店?那么&#xff0c;如何开通个人抖音小店…

java—异常

异常 什么是异常 异常的体系 编译时异常处理方式 1、选择报错的整个代码块&#xff0c;快捷键crtlaltt键&#xff0c;选择try/catch将代码围起来。 2、编译异常处理方式2 在main方法上抛出异常 自定义异常 例子&#xff1a; 自定义运行时异常 自定义编译时异常 异常…

QT截图程序,可多屏幕截图

截图程序&#xff0c;支持多屏幕时跨屏幕截图。截图使用setMask达到镂空效果&#xff0c;截图后会有预览和保存功能。截图时按下Esc可退出。 mainwindow.ui mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> …

Ansible自动化运维工具 - playbook 剧本编写

一. inventory 主机清单 Inventory 支持对主机进行分组&#xff0c;每个组内可以定义多个主机&#xff0c;每个主机都可以定义在任何一个或多个主机组内。 1.1 inventory 中的变量含义 Inventory 变量名 含义ansible_hostansible连接节点时的IP地址ansible_port连接对方…

2024-05-07 商业分析-如何在社会层面做一个更好的工具人-记录

摘要: 2024-05-07 商业分析-如何成为一个靠谱的工具人 如何在社会层面做一个更好的工具人 那么今天讲的这个主题呢&#xff0c;对吧&#xff1f;你们一看啊&#xff0c;就觉得这个就不应该我讲是吧啊&#xff0c;但是呢这个逻辑呢我还得跟你们讲一下啊&#xff0c;就是如何成为…

虚幻引擎笔记

虚幻引擎笔记 一、蓝图类二、创建自定义Character蓝图三、操作映射和轴映射 一、蓝图类 Actor&#xff1a;可以放置在关卡中的物体Pawn&#xff1a;相当于游戏角色&#xff0c;可以通过玩家控制器来控制角色&#xff1a;在Pawn的基础上增加了四处走动的功能。创建游戏角色时使用…

Freeswitch-mod开发

文章目录 一、Freeswitch-mod开发1.1 介绍1.2 实战1.2.1 新建一个mymod.c或者mymod.cpp1.2.2 新建一个Makefile1.2.3 编译 二、Freeswitch-mod-自定义Dialplan模块2.1 介绍2.2 实战2.2.1 改造mymod.c&#xff08;代码是完整的&#xff0c;自己做区别看一下&#xff09;2.2.2 编…

python实验三 实现UDP协议、TCP协议进行服务器端与客户端的交互

实验三 实验题目 1、请利用生成器构造一下求阶乘的函数Factorial()&#xff0c;定义一个函数m()&#xff0c;在m()中调用生成器Factorial()生成小于100的阶乘序列存入集合s中&#xff0c;输出s。 【代码】 def factorial():n1f1while 1:​ f * n​ yield (f)​ n1…

XORM 框架的使用

1、xorm 1.1、xorm 简介 xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。 特性 支持 struct 和数据库表之间的灵活映射&#xff0c;并支持自动同步事务支持同时支持原始SQL语句和ORM操作的混合执行使用连写来简化调用支持使用ID, In, Where, Limit,…

Python批量计算多张遥感影像的NDVI

本文介绍基于Python中的gdal模块&#xff0c;批量基于大量多波段遥感影像文件&#xff0c;计算其每1景图像各自的NDVI数值&#xff0c;并将多景结果依次保存为栅格文件的方法。 如下图所示&#xff0c;现在有大量.tif格式的遥感影像文件&#xff0c;其中均含有红光波段与近红外…

通过氧气退火增强β-Ga₂O₃二极管.中国科技大学和河北半导体研究所的研究人员在这一特定领域取得了最新重大进展

上图所示&#xff1a;&#xff08;a&#xff09;增加台面有助于提高β-Ga2O3肖特基势垒二极管的阻断电压&#xff08;b&#xff09;。 氧气退火和自对准台面终端使β-Ga2O3二极管进一步走向商业化。 虽然β-Ga2O3电力电子技术已经取得了长足的进步&#xff0c;但仍然存在挑战&…

QT creator qt6.0 使用msvc2019 64bit编译报错

qt creator qt6.0报错&#xff1a; D:\Qt6\6.3.0\msvc2019_64\include\QtCore\qglobal.h:123: error: C1189: #error: "Qt requires a C17 compiler, and a suitable value for __cplusplus. On MSVC, you must pass the /Zc:__cplusplus option to the compiler."…