/*
Udp NTP Client
Get the time from a Network Time Protocol (NTP) time
server
Demonstrates use of UDP sendPacket and ReceivePacket
For more on NTP time servers and the messages needed
to communicate with them,
see
http://en.wikipedia.org/wiki/Network_Time_Protocol
This code is in the public domain.
*/
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <TimeLib.h> //
https://github.com/PaulStoffregen/Time
const char* ssid = "SSID";
const char* password = "PASSWORD";
#define INTERVAL
60 // データ取得間隔(秒)
// UDPローカルポート番号
unsigned int localPort = 2390;
// NTPタイムサーバIPアドレス(ntp.nict.jp NTP server)
IPAddress timeServer(133, 243, 238, 164);
// NTPパケットバッファサイズ
const int NTP_PACKET_SIZE= 48;
// NTP送受信用パケットバッファ
byte packetBuffer[NTP_PACKET_SIZE];
// 最後にパケットを送信した時間(ミリ秒)
unsigned long lastSendPacketTime = 0;
// Udpクラス
WiFiUDP udp;
// dow_char() 曜日文字を戻す [Sun,Mon....]
char * dow_char_EN(byte days) {
char *you[] =
{"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
return you[days];
}
// dow_char() 曜日文字を戻す [日曜,火曜....]
char * dow_char_JP(byte days) {
char *you[] = {"日曜","月曜","火曜","水曜","木曜","金曜","土曜"};
return you[days];
}
// dow() 曜日を示す数値を戻す[0-Sunday, 1-Monday etc.]
uint8_t dow(unsigned long t) {
return ((t / 86400) + 4) % 7;
}
void showTime(char * title, time_t timet, char * dow) {
Serial.print(title);
Serial.print(year(timet));
Serial.print("/");
Serial.print(month(timet));
Serial.print("/");
Serial.print(day(timet));
Serial.print(" ");
Serial.print(hour(timet));
Serial.print(":");
Serial.print(minute(timet));
Serial.print(":");
Serial.print(second(timet));
Serial.print(" [");
Serial.print(dow);
Serial.println("]");
}
void setup()
{
Serial.begin(9600);
delay(500);
Serial.println();
Serial.println();
Serial.print("Wait for WiFi...");
// We start by connecting to a WiFi network
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Starting UDP");
udp.begin(localPort);
#if 0
// タイムサーバーの名前解決
DNSClient dns;
WiFi.begin(Ethernet.dnsServerIP());
//
if(dns.getHostByName("ntp.jst.mfeed.ad.jp",timeServer) ==
1) {
if(dns.getHostByName("ntp.nict.jp",timeServer) ==
1) {
Serial.print(F("ntp = "));
Serial.println(timeServer);
} else {
Serial.print(F("dns lookup failed"));
while(1) { }
}
#endif
// 最初の時刻リクエストを送信
sendNTPpacket(timeServer);
lastSendPacketTime = millis();
}
void loop()
{
static int counter=0;
byte DayOfWeek;
long now = millis();
if (now - lastSendPacketTime > 1000) { // 1秒経過
lastSendPacketTime = now;
counter++;
if (counter > INTERVAL) {
// NTPサーバへ時刻リクエストを送信
sendNTPpacket(timeServer);
counter=0;
}
}
// NTPサーバからのパケット受信
int cb = udp.parsePacket();
if (cb) {
Serial.print("packet received,
length=");
Serial.println(cb);
// バッファに受信データを読み込む
udp.read(packetBuffer,
NTP_PACKET_SIZE); // read the packet into the buffer
// 時刻情報はパケットの40バイト目からはじまる4バイトのデータ
unsigned long highWord =
word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord =
word(packetBuffer[42], packetBuffer[43]);
//
NTPタイムスタンプは64ビットの符号無し固定小数点数(整数部32ビット、小数部32ビット)
// 1900年1月1日0時との相対的な差を秒単位で表している
// 小数部は切り捨てて、秒を求めている
unsigned long secsSince1900 = highWord
<< 16 | lowWord;
Serial.print("Seconds since Jan 1 1900
= " );
Serial.println(secsSince1900);
// NTPタイムスタンプをUNIXタイムに変換する
// UNITタイムは1970年1月1日0時からはじまる
// 1900年から1970年の70年を秒で表すと2208988800秒になる
const unsigned long seventyYears =
2208988800UL;
// NTPタイムスタンプから70年分の秒を引くとUNIXタイムが得られる
unsigned long epoch = secsSince1900 -
seventyYears;
Serial.print("Unix time = ");
Serial.println(epoch);
// グリニッジ標準時間
uint8_t DayOfWeek = dow(epoch);
showTime("The UTC time is ", epoch,
dow_char_EN(DayOfWeek));
// 日本標準時にあわせるために+9時間しておく
DayOfWeek = dow(epoch + (9 * 60 * 60));
showTime("The JST time is ", epoch + (9
* 60 * 60), dow_char_JP(DayOfWeek));
#if 0
// Timeライブラリに時間を設定(UNIXタイム)
// 日本標準時にあわせるために+9時間しておく
setTime(epoch + (9 * 60 * 60));
DayOfWeek = dow(epoch + (9 * 60 * 60));
Serial.print("JST time = ");
Serial.print(year());
Serial.print('/');
Serial.print(month());
Serial.print('/');
Serial.print(day());
Serial.print(' ');
Serial.print(hour());
Serial.print(':');
Serial.print(minute());
Serial.print(':');
Serial.print(second());
Serial.print(" [");
Serial.print(dow_char_EN(DayOfWeek));
Serial.print(" ");
Serial.print(dow_char_JP(DayOfWeek));
Serial.println("]");
#endif
}
}
// send an NTP request to the time server at the given
address
unsigned long sendNTPpacket(IPAddress& address)
{
Serial.println("\nsending NTP packet...");
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
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();
}
|