#include "freertos/FreeRTOS.h"
#include "Arduino.h"
#include "WiFi.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#define SNTP_SERVER "ntp.nict.jp"
//#define SNTP_SERVER "pool.ntp.org"
#define SNTP_PORT 123
#define
SNTP_OFFSET_LI_VN_MODE 0
#define
SNTP_LI_MASK
0xC0
#define
SNTP_LI_NO_WARNING
0x00
#define SNTP_LI_LAST_MINUTE_61_SEC 0x01
#define SNTP_LI_LAST_MINUTE_59_SEC 0x02
#define SNTP_LI_ALARM_CONDITION
0x03 /* (clock not synchronized) */
#define
SNTP_VERSION_MASK
0x38
#define
SNTP_VERSION
(4/* NTP Version 4*/<<3)
#define
SNTP_MODE_MASK
0x07
#define
SNTP_MODE_CLIENT
0x03
#define
SNTP_MODE_SERVER
0x04
#define
SNTP_MODE_BROADCAST
0x05
/* number of seconds between 1900 and 1970 */
#define
DIFF_SEC_1900_1970
(2208988800UL)
const char* WIFI_SSID = "SSID";
const char* WIFI_PASS = "PASSWORD";
//
https://qiita.com/koara-local/items/585755faac70c8b37b5b
// [C++11 ~] variadic templates
template <typename ... Args>
void _printf(const char *format, Args const & ...
args) {
// int printf(const char *format, ...);
TickType_t _nowTick =
xTaskGetTickCount();
char * _taskName = pcTaskGetTaskName(
NULL );
printf("[%s:%d] ",_taskName, _nowTick);
printf(format, args ...);
}
#if 0
// [C/C++] stdarg
void _printf(const char *format, ...) {
va_list va;
va_start(va, format);
// int vprintf(const char *format,
va_list ap);
TickType_t _nowTick =
xTaskGetTickCount();
char * _taskName = pcTaskGetTaskName(
NULL );
printf("[%s:%d] ",_taskName, _nowTick);
vprintf(format, va);
va_end(va);
}
#endif
void showNetworkInfo() {
IPAddress ip = WiFi.localIP();
IPAddress mk = WiFi.subnetMask();
IPAddress gw = WiFi.gatewayIP();
_printf("IP address=%d.%d.%d.%d\n",
ip[0], ip[1], ip[2], ip[3]);
_printf("Netmask
=%d.%d.%d.%d\n", mk[0], mk[1], mk[2], mk[3]);
_printf("Gateway
=%d.%d.%d.%d\n", gw[0], gw[1], gw[2], gw[3]);
}
// NTP Client Task
void task1(void *pvParameters)
{
typedef struct
{
uint8_t
li_vn_mode; // Eight bits.
li, vn, and mode.
// li. Two bits. Leap indicator.
// vn. Three bits. Version number of the
protocol.
// mode. Three bits. Client will pick mode 3 for client.
uint8_t
stratum;
// Eight bits. Stratum level of the local clock.
uint8_t
poll;
// Eight bits. Maximum interval between successive
messages.
uint8_t
precision; // Eight
bits. Precision of the local clock.
uint32_t
rootDelay; // 32 bits. Total
round trip delay time.
uint32_t rootDispersion; // 32 bits.
Max error aloud from primary clock source.
uint32_t
refId;
// 32 bits. Reference clock identifier.
uint32_t
refTm_s; // 32
bits. Reference time-stamp seconds.
uint32_t
refTm_f; // 32
bits. Reference time-stamp fraction of a second.
uint32_t
origTm_s; // 32 bits.
Originate time-stamp seconds.
uint32_t
origTm_f; // 32 bits.
Originate time-stamp fraction of a second.
uint32_t
rxTm_s; //
32 bits. Received time-stamp seconds.
uint32_t
rxTm_f; //
32 bits. Received time-stamp fraction of a second.
uint32_t
txTm_s; //
32 bits and the most important field the client cares
about. Transmit time-stamp seconds.
uint32_t
txTm_f; //
32 bits. Transmit time-stamp fraction of a second.
}
ntp_packet;
// Total: 384 bits or 48 bytes.
_printf("Start\n");
/* Convert URL to IP */
struct hostent *server; // Server data
structure.
server = gethostbyname(SNTP_SERVER);
LWIP_ASSERT("server != NULL", server !=
NULL);
/* set up address to connect to */
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
//addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
//addr.sin_port = PP_HTONS(SNTP_PORT);
addr.sin_port = htons(SNTP_PORT);
//addr.sin_addr.s_addr =
inet_addr("129.250.35.250");
// Copy the server's IP address to the
server address structure.
bcopy( ( char* )server->h_addr, (
char* ) &addr.sin_addr.s_addr, server->h_length );
/* create the socket */
int fd;
int ret;
fd = lwip_socket(AF_INET, SOCK_DGRAM,
IPPROTO_UDP ); // Create a UDP socket.
LWIP_ASSERT("fd >= 0", fd >= 0);
/* set NTP packet */
ntp_packet packet;
memset( &packet, 0, sizeof(
ntp_packet ) );
packet.li_vn_mode = SNTP_LI_NO_WARNING
| SNTP_VERSION | SNTP_MODE_CLIENT;
/* send NTP packet */
ret = lwip_sendto(fd,
(char*)&packet, sizeof(ntp_packet), 0, (struct
sockaddr *)&addr,sizeof(addr));
LWIP_ASSERT("ret == 48", ret == 48);
_printf("lwip_sendto ret=%d\n",ret);
/* recv NTP packet */
ret = lwip_recv(fd, (char*)
&packet, sizeof(ntp_packet), 0);
LWIP_ASSERT("ret > 0", ret > 0);
_printf("lwip_recv ret=%d\n",ret);
// NTPタイムをUNIXタイムに変換する
// NTPタイムは1900年1月1日0時0分からはじまる積算秒数
// UNITタイムは1970年1月1日0時0分からはじまる積算秒数
// 1900年から1970年の70年を秒で表すと2208988800秒になる
// NTPタイムから70年分の秒を引くとUNIXタイムが得られる
uint32_t ntpTime = ntohl( packet.txTm_s
); // NTP Time-stamp seconds.
_printf("The NTP Time = %u\n",ntpTime);
// グリニッジ標準時間
time_t txTm = ntpTime -
DIFF_SEC_1900_1970; // UNIT Time-stamp seconds.
_printf("The UTC Time: %s",ctime( (
const time_t* ) &txTm ) );
// 日本標準時にあわせるために+9時間しておく
txTm = txTm + (9 * 60 * 60);
_printf("The JST Time: %s",ctime( (
const time_t* ) &txTm ) );
/* Convert tm to timeval */
struct timeval now = { .tv_sec = txTm
};
/* Set the time as well as a timezone
*/
settimeofday(&now, NULL);
/* close */
ret = lwip_close(fd);
LWIP_ASSERT("ret == 0", ret == 0);
vTaskDelete( NULL );
}
// Clock Task
void task2(void *pvParameters)
{
_printf("Start\n");
while(1) {
time_t ts = time(NULL);
_printf("%s",ctime(&ts));
vTaskDelay(2000 /
portTICK_PERIOD_MS);
}
vTaskDelete( NULL );
}
void setup() {
vTaskDelay(2000 / portTICK_PERIOD_MS);
_printf("start
Priority=%d\n",uxTaskPriorityGet( NULL ));
_printf("portTICK_PERIOD_MS=%d\n",portTICK_PERIOD_MS);
/* Connect WiFi */
_printf("Connecting to
%s\n",WIFI_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
vTaskDelay(5000 /
portTICK_PERIOD_MS);
}
_printf("WiFi connected\n");
showNetworkInfo();
/* Start NTP Client */
xTaskCreatePinnedToCore(task1, "NTP",
4096, NULL, 1, NULL, tskNO_AFFINITY);
/* Start Clock Task */
xTaskCreatePinnedToCore(task2, "Clock",
4096, NULL, 1, NULL, tskNO_AFFINITY);
/* stop loop task */
vTaskDelete( NULL );
}
void loop() { // Never run
_printf("loop\n");
}
|