Skip to content

Commit ec5470c

Browse files
committed
Updated Readme file, added Fabrice's NTPClient and updated future release version
1 parent cce9612 commit ec5470c

File tree

4 files changed

+208
-8
lines changed

4 files changed

+208
-8
lines changed

NTPClient.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/**
2+
* The MIT License (MIT)
3+
* Copyright (c) 2015 by Fabrice Weinberg
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
* SOFTWARE.
20+
*/
21+
22+
#include "NTPClient.h"
23+
24+
NTPClient::NTPClient(int timeOffset) {
25+
this->_timeOffset = timeOffset;
26+
}
27+
28+
NTPClient::NTPClient(const char* poolServerName) {
29+
this->_poolServerName = poolServerName;
30+
}
31+
32+
NTPClient::NTPClient(const char* poolServerName, int timeOffset) {
33+
this->_timeOffset = timeOffset;
34+
this->_poolServerName = poolServerName;
35+
}
36+
37+
NTPClient::NTPClient(const char* poolServerName, int timeOffset, int updateInterval) {
38+
this->_timeOffset = timeOffset;
39+
this->_poolServerName = poolServerName;
40+
this->_updateInterval = updateInterval;
41+
}
42+
43+
void NTPClient::begin() {
44+
#ifdef DEBUG_NTPClient
45+
Serial.println("Begin NTPClient");
46+
Serial.print("Start udp connection on port: ");
47+
Serial.println(this->_port);
48+
#endif
49+
this->_udp.begin(this->_port);
50+
this->forceUpdate();
51+
}
52+
53+
void NTPClient::forceUpdate() {
54+
#ifdef DEBUG_NTPClient
55+
Serial.println("Update from NTP Server");
56+
#endif
57+
58+
IPAddress address;
59+
WiFi.hostByName(this->_poolServerName, address);
60+
61+
this->sendNTPPacket(address);
62+
63+
// Wait till data is there or timeout...
64+
byte timeout = 0;
65+
int cb = 0;
66+
do {
67+
delay ( 10 );
68+
cb = this->_udp.parsePacket();
69+
if (timeout > 100) return; // timeout after 1000 ms
70+
timeout++;
71+
} while (cb == 0);
72+
73+
this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time
74+
75+
this->_udp.read(this->_packetBuffer, NTP_PACKET_SIZE);
76+
77+
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
78+
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
79+
// combine the four bytes (two words) into a long integer
80+
// this is NTP time (seconds since Jan 1 1900):
81+
unsigned long secsSince1900 = highWord << 16 | lowWord;
82+
83+
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
84+
}
85+
86+
void NTPClient::update() {
87+
unsigned long runtime = millis();
88+
if (runtime - this->_lastUpdate >= this->_updateInterval && this->_updateInterval != 0) {
89+
this->forceUpdate();
90+
}
91+
}
92+
93+
unsigned long NTPClient::getRawTime() {
94+
return this->_timeOffset + // User offset
95+
this->_currentEpoc + // Epoc returned by the NTP server
96+
((millis() - this->_lastUpdate) / 1000); // Time since last update
97+
}
98+
99+
String NTPClient::getHours() {
100+
return String((this->getRawTime() % 86400L) / 3600);
101+
}
102+
String NTPClient::getMinutes() {
103+
return String((this->getRawTime() % 3600) / 60);
104+
}
105+
106+
String NTPClient::getSeconds() {
107+
return String(this->getRawTime() % 60);
108+
}
109+
110+
String NTPClient::getFormattedTime() {
111+
unsigned long rawTime = this->getRawTime();
112+
unsigned long hours = (rawTime % 86400L) / 3600;
113+
String hoursStr = hours < 10 ? "0" + String(hours) : String(hours);
114+
115+
unsigned long minutes = (rawTime % 3600) / 60;
116+
String minuteStr = minutes < 10 ? "0" + String(minutes) : String(minutes);
117+
118+
unsigned long seconds = rawTime % 60;
119+
String secondStr = seconds < 10 ? "0" + String(seconds) : String(seconds);
120+
121+
return hoursStr + ":" + minuteStr + ":" + secondStr;
122+
}
123+
124+
void NTPClient::sendNTPPacket(IPAddress ip) {
125+
// set all bytes in the buffer to 0
126+
memset(this->_packetBuffer, 0, NTP_PACKET_SIZE);
127+
// Initialize values needed to form NTP request
128+
// (see URL above for details on the packets)
129+
this->_packetBuffer[0] = 0b11100011; // LI, Version, Mode
130+
this->_packetBuffer[1] = 0; // Stratum, or type of clock
131+
this->_packetBuffer[2] = 6; // Polling Interval
132+
this->_packetBuffer[3] = 0xEC; // Peer Clock Precision
133+
// 8 bytes of zero for Root Delay & Root Dispersion
134+
this->_packetBuffer[12] = 49;
135+
this->_packetBuffer[13] = 0x4E;
136+
this->_packetBuffer[14] = 49;
137+
this->_packetBuffer[15] = 52;
138+
139+
// all NTP fields have been given values, now
140+
// you can send a packet requesting a timestamp:
141+
this->_udp.beginPacket(ip, 123); //NTP requests are to port 123
142+
this->_udp.write(this->_packetBuffer, NTP_PACKET_SIZE);
143+
this->_udp.endPacket();
144+
}

NTPClient.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#pragma once
2+
3+
#include "Arduino.h"
4+
5+
#include <ESP8266WiFi.h>
6+
#include <WiFiUdp.h>
7+
8+
#define SEVENZYYEARS 2208988800UL
9+
#define NTP_PACKET_SIZE 48
10+
11+
class NTPClient {
12+
private:
13+
WiFiUDP _udp;
14+
15+
const char* _poolServerName = "time.nist.gov"; // Default time server
16+
int _port = 1337;
17+
int _timeOffset;
18+
19+
unsigned int _updateInterval = 60000; // In ms
20+
21+
unsigned long _currentEpoc; // In s
22+
unsigned long _lastUpdate = 0; // In ms
23+
24+
byte _packetBuffer[NTP_PACKET_SIZE];
25+
26+
void sendNTPPacket(IPAddress _timeServerIP);
27+
28+
public:
29+
NTPClient(int timeOffset);
30+
NTPClient(const char* poolServerName);
31+
NTPClient(const char* poolServerName, int timeOffset);
32+
NTPClient(const char* poolServerName, int timeOffset, int updateInterval);
33+
34+
void begin();
35+
void update();
36+
void forceUpdate();
37+
38+
String getHours();
39+
String getMinutes();
40+
String getSeconds();
41+
String getFormattedTime();
42+
43+
unsigned long getRawTime();
44+
};

README.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,33 @@
22

33
New version of the ESP8266 Weather Station
44

5+
## Arduino IDE
6+
7+
Make sure you use a version of the Arduino IDE which is supported by the ESP8266 platform, e.g. 1.6.5. You can find it here: https://www.arduino.cc/en/Main/OldSoftwareReleases#previous
8+
9+
At the time of this writing **1.6.6 and 1.6.7 are not supported**!
10+
511
## Setup
612

7-
* Download this project either with a git checkout or press "Download as zip"
813
* Install the following librarys with your Arduino Library Manager in Sketch > Include Library > Manage Libraries...
14+
* ESP8266 Weather Station
915
* Json Streaming Parser (by Daniel Eichhorn)
1016
* ESP8266 Oled Driver for SSD1306 display (by me as well)
1117
* Go to http://wunderground.com, create an account and get an API Key
12-
* Open the sketch in the Arduino Include and
18+
* In the Arduino IDE go to File > Examples > ESP8266 Weather Station
1319
* Enter the Wunderground API Key
1420
* Enter your Wifi credentials
1521
* Adjust the location according to Wunderground API, e.g. Zurich, CH
1622
* Adjust UTC offset
1723

18-
## Known issues
19-
Many people asked me to finally publish the new version. I'm doing that now, knowing that some things are not perfect or stable enough. If you detect or even fix one of these issues, please contact me or create a pull request
20-
* Time is running out of sync. Sometimes off my many minutes. I assume it has something todo with the implementation of the millis() function which I based the time sync upon
21-
* The precipitation value from Wunderground currently always returns 0.0mm for my location. Maybe this looks better in other locations
22-
* Sometimes the WeatherStation crashes. I didn't have time to debug this behavior. If you have any clue, please let me know.
24+
## Available Modules
25+
* **TimeClient**: simple class which uses the header date and time to set the clock
26+
* **NTPClient**: a NTP based time class written by Fabrice Weinberg
27+
* **WundergroundClient**: fetches current weather and forecast from wunderground.com
28+
* **ThingspeakClient**: fetches data from Thingspeak which you might have collected with another sensor node and posted there. I use this to measure outdoor temperature and humidity and show it on the WeatherStation with a ClimateNode: https://shop.squix.ch/index.php/esp8266/climatenode.html
29+
30+
## Why Weather Station as a library?
31+
32+
I realized that more and more the Weather Station was becoming a general framework for displaying data over WiFi to one of these pretty displays. But everyone would have different ways or sources for data and having the important part of the library would rather be the classes which fetch the data then the main class.
33+
So if you write data fetchers which might be of interest to others please contact me to integrate them here or offer your code as extension library yourself and call it something like esp8266-weather-station-<yourservice>.
34+
I will gladly list it here as third party library...

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=ESP8266 Weather Station
2-
version=0.0.9
2+
version=1.0.0
33
author=Daniel Eichhorn
44
maintainer=Daniel Eichhorn <[email protected]>
55
sentence=ESP8266 based internet connected Weather Station

0 commit comments

Comments
 (0)