- /*
- 日期:2018.8.12
- IDE 版本:1.8.6
- ESP8266 for Arduino 版本:2.4.2
- 芯片:WeMos D1 mini
- 功能:初始化芯片,使其具有Web Browser OTA升级功能,NTP时间获取
- 通过D1-mini.local/可以访问状态
- 通过D1-mini.local/update可以进行OTA升级
- */
- #include ti.h>
- #include
- #include
- #include
- #include
- #include
- #include
- const char *host = "D1-mini"; //节点名,web update server hostname
- //数字输出管脚定义
- byte board_led = 2; //D1-mini板载灯脚,D4
- //byte board_led = 1; //ESP-01板载灯脚
- // 获取NTP时间相关配置
- unsigned int localPort = 2390; // 本地端口,侦听UDP packets
- IPAddress timeServerIP; //时间服务器动态IP地址
- //const char* ntpServerName = "time.nist.gov";//时间服务器域名
- const char* ntpServerName = "cn.pool.ntp.org";//国内时间服务器域名
- const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
- byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
- unsigned long NTPtime; //获取的NTP时间(秒)
- unsigned long nowtime; //实时时间(毫秒)
- unsigned long savetime; //获取NTP时间时,对应的系统时间(millis)
- bool NTP_got = 0; //成功获取NTP时间,1为成功,0为失败
- #define Detect_Interval 3000 // 检测周期,3秒
- unsigned int next_Detect_Time; //下次检测时间
- //创建对象
- Ticker slow_ticker; //用于板载灯慢闪烁控制
- WiFiUDP udp; //获取NTP时间需要
- ESP8266WebServer httpServer(80); //用于web服务器
- ESP8266HTTPUpdateServer httpUpdater;//用于代码OTA更新
- ESP8266WiFiMulti wifiMulti;
- void setup() {
- Serial.begin(115200);
- delay(10);
- Serial.println();
- Serial.println("D1 Initialize");
- pinMode(board_led,OUTPUT); //设置板载灯脚为输出状态
-
- digitalWrite(board_led,LOW); //点亮板载灯(低电平有效),开始连接WiFi
- //预置WiFi名称和密码,这样模块在家和单位就都可以使用了
- wifiMulti.addAP("WiFi名称", "密码");//家
- wifiMulti.addAP("WiFi名称", "密码");//单位
- //还可以再加,好像最多为6个
-
- wifi_conn();//连接WiFi
- }
-
- void loop() {
- nowtime = (millis()-savetime)/1000 + NTPtime; //现在时间计算赋值
-
- // Handle http server.
- httpServer.handleClient();
- //再次获得时间
- if( (millis() > next_Detect_Time && !NTP_got) || millis() < 250){
- //如果获取NTP时间失败,并累计超过3秒,再或模块系统时间清零,重新获取
- Serial.print("begin fetch NTP time againrn");
- fetchNTPtime();
- next_Detect_Time = millis() + Detect_Interval; //设置下次检测时间
- }
-
- //在下面输入你的代码
-
- delay(250);
- }
- void fetchNTPtime(){//获取NTP时间
- //通过域名获取IP地址
- WiFi.hostByName(ntpServerName, timeServerIP);
- sendNTPpacket(timeServerIP); // 调用这个函数,向时间服务器发请求
- // wait to see if a reply is available
- delay(1000);
-
- int cb = udp.parsePacket();
- if (!cb) {//没有接收到数据
- //Serial.println("no packet yet");
- NTP_got = 0;
- }
- else {//接收到数据
- udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
- //从接收包第40个字节开始的4个字为节时间戳,先分别赋值到2 word
- unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
- unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
- //合并4字节成长整型,这就是NTP时间(从1900.1.1开始的秒数)
- // this is NTP time (seconds since Jan 1 1900):
- unsigned long secsSince1900 = highWord << 16 | lowWord;
- //Serial.print("Seconds since Jan 1 1900 = " );
- //Serial.println(secsSince1900);
- // now convert NTP time into everyday time:
- //Serial.print("Unix time = ");
- // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
- const unsigned long seventyYears = 2208988800UL;
- // subtract seventy years:
- NTPtime = secsSince1900 - seventyYears;
- NTPtime += 8 * 3600;//北京时间,东八区修正
- NTP_got = 1;
- //Serial.print("got NTP timern");
- savetime = millis();//获得NTP时间的系统时刻
- }
- nowtime = (millis()-savetime)/1000 + NTPtime;
- //打印小时、分钟和秒:
- Serial.print("The Beijing time is ");
- Serial.println(displaytime(nowtime));
- }
- //发送NTP请求到指定IP地址的时间服务器
- unsigned long sendNTPpacket(IPAddress& address)
- {
- //Serial.println("sending NTP packet...");
- //将缓冲区里所有字节清零
- memset(packetBuffer, 0, NTP_PACKET_SIZE);
- // 准备NTP请求数据
- packetBuffer[0] = 0b11100011; // LI, Version, Mode
- packetBuffer[1] = 0; // Stratum, or type of clock
- packetBuffer[2] = 6; // Polling Interval
- packetBuffer[3] = 0xEC; // Peer Clock Precision
- // 8 bytes of zero for Root Delay & Root Dispersion
- packetBuffer[12] = 49;
- packetBuffer[13] = 0x4E;
- packetBuffer[14] = 49;
- packetBuffer[15] = 52;
- // all NTP fields have been given values, now
- // you can send a packet requesting a timestamp:
- udp.beginPacket(address, 123); //NTP requests are to port 123
- udp.write(packetBuffer, NTP_PACKET_SIZE);
- udp.endPacket();
-
- }
- void handleRoot() {
- IPAddress local_ip;
- String message = "";
- message += "初始化芯片";
- message += "
";
- message += "
";
-
- message += "";
- message += "";
- httpServer.send ( 200, "text/html", message );
- }
- void handleNotFound(){
- //digitalWrite(board_led, 1);
- String message = "File Not Foundnn";
- message += "URI: ";
- message += httpServer.uri();
- message += "nMethod: ";
- message += (httpServer.method() == HTTP_GET)?"GET":"POST";
- message += "nArguments: ";
- message += httpServer.args();
- message += "n";
- for (uint8_t i=0; i
- message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "n";
- }
- httpServer.send(404, "text/plain", message);
- //digitalWrite(board_led, 0);
- }
- String displaytime(unsigned long nt)
- {
- //显示日期,小时、分钟和秒:
- String dt;
- time_t nowtm;
- struct tm *timeinfo;
- //time( &nowtime );
- //timeinfo = localtime( &nowtime );
- nowtm = nt;
- timeinfo = localtime(&nowtm);
- int xtn = timeinfo->tm_year + 1900;
- int xty = timeinfo->tm_mon + 1;
- int xtr = timeinfo->tm_mday;
- int xts = timeinfo->tm_hour;
- int xtf = timeinfo->tm_min;
- int xtm = timeinfo->tm_sec;
- dt += xtn;
- dt += "-";
- dt += xty;
- dt += "-";
- dt += xtr;
- dt += " ";
- if (xts < 10 ) {
- // 前10小时加“ ”
- dt += ' ';
- }
- dt += xts;
- dt += ":";
- if (xtf < 10 ) {
- // 前10分加“0”
- dt += '0';
- }
- dt += xtf;
- dt += ":";
- if (xtm < 10 ) {
- // 前10秒加“0”
- dt += '0';
- }
- dt += xtm;
- return dt;
- }
- byte weekday(unsigned long nt)
- {
- //显示星期数:周一为0,周二为1,周三为2,周四为3,周五为4,周六为5,周日为6
- byte wd;
- time_t nowtm;
- struct tm *timeinfo;
- //time( &nowtime );
- //timeinfo = localtime( &nowtime );
- nowtm = nt;
- timeinfo = localtime(&nowtm);
- int xtn = timeinfo->tm_year + 1900; //年份
- int xty = timeinfo->tm_mon + 1; //月份
- int xtr = timeinfo->tm_mday; //日
- int xtc = xtn / 100; //世纪
- xtn = xtn % 100; //年数
- if (xty < 3){ //如果是一月或二月,需要修正
- xtn --;
- xty += 12;
- }
- wd = (xtn + int(xtn * 0.25) + int(xtc * 0.25) - xtc * 2 + int((xty + 1) * 2.6) + xtr - 2) % 7;
- return wd;
- }
- void led_blink(byte pin)
- { //指定pin脚改变其状态
- bool state = digitalRead(pin); // 获得pin脚当前状态
- digitalWrite(pin, !state); // 设置pin脚为反
- }
- void wifi_conn() {//进行WiFi连接
- NTPtime = 8*3600; //给NTP时间赋初值
- savetime = millis();
- NTP_got = 0;
- udp.begin(localPort);//连接UDP,获取NTP时间需要
-
- // 开启 LLMNR responder
- LLMNR.begin(host); //开启LLMNR域名解析
- httpServer.on("/", handleRoot); //调用主页面
- httpServer.onNotFound(handleNotFound); //出错调用
-
- // 开启 Web Update server.
- httpUpdater.setup(&httpServer);
- // 开启 HTTP server
- httpServer.begin();
- Serial.printf("HTTPUpdateServer ready! Open %s.local/update in your browsern", host);
- Serial.println("Wait for WiFi connection.");
-
- // ... 给ESP10秒时间连接wifi.
- unsigned long startTime = millis();
- while (wifiMulti.run() != WL_CONNECTED && millis() - startTime < 10000)
- {
- Serial.print(".");//如果没有连通向串口发送.....
- delay(250);
- }
-
- // 检查连接状态
- if(WiFi.status() == WL_CONNECTED)
- {//如果WiFi连接成功
- Serial.print("IP address: ");
- Serial.println(WiFi.localIP());
- slow_ticker.attach(0.8, led_blink, board_led);//WiFi连接正常,板载灯闪烁
- fetchNTPtime(); //获取NTP时间
- }
- else
- {//WiFi连接不成功
- Serial.println("wifi connect fail!");
- digitalWrite(board_led,HIGH);//WiFi连接失败,板载灯灭
- }
- }
复制代码
|