kopia lustrzana https://github.com/martin-ger/esp_mqtt
176 wiersze
3.9 KiB
C
176 wiersze
3.9 KiB
C
#include <c_types.h>
|
|
#include <user_interface.h>
|
|
#include <espconn.h>
|
|
#include <osapi.h>
|
|
#include <mem.h>
|
|
#include <time.h>
|
|
#include <sys_time.h>
|
|
|
|
#include "ntp.h"
|
|
#include "lwip/def.h"
|
|
#include "user_config.h"
|
|
#include "driver/uart.h"
|
|
//#include "utils.h"
|
|
|
|
#define OFFSET 2208988800ULL
|
|
|
|
static ip_addr_t ntp_server_ip = {0};
|
|
static os_timer_t ntp_timeout;
|
|
static struct espconn *pCon, pConDNS;
|
|
|
|
static struct timeval t_tv = {0,0};
|
|
static uint64_t t_offset = 0;
|
|
|
|
void ICACHE_FLASH_ATTR get_cur_time(struct timeval *tv)
|
|
{
|
|
uint64_t t_curr = get_long_systime() - t_offset + t_tv.tv_usec;
|
|
tv->tv_sec = t_tv.tv_sec + t_curr/1000000;
|
|
tv->tv_usec = t_curr%1000000;
|
|
}
|
|
|
|
|
|
uint8_t* ICACHE_FLASH_ATTR get_timestr(int16_t timezone)
|
|
{
|
|
struct timeval tv;
|
|
static uint8_t buf[10];
|
|
|
|
get_cur_time(&tv);
|
|
tv.tv_sec += timezone * 3600;
|
|
os_sprintf(buf, "%02d:%02d:%02d", (tv.tv_sec/3600)%24, (tv.tv_sec/60)%60, tv.tv_sec%60);
|
|
return buf;
|
|
}
|
|
|
|
|
|
void ICACHE_FLASH_ATTR ntp_to_tv(uint8_t ntp[8], struct timeval *tv)
|
|
{
|
|
uint64_t aux = 0;
|
|
|
|
tv->tv_sec = ntohl(*(uint32_t*)ntp) - OFFSET;
|
|
|
|
aux = ntohl(*(uint32_t*)&ntp[4]);
|
|
|
|
// aux is the NTP fraction (0..2^32-1)
|
|
aux *= 1000000; // multiply by 1e6
|
|
aux >>= 32; // and divide by 2^32
|
|
tv->tv_usec = (uint32_t)aux;
|
|
}
|
|
|
|
|
|
LOCAL void ICACHE_FLASH_ATTR ntp_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) {
|
|
struct espconn *pespconn = (struct espconn *)arg;
|
|
|
|
if (ipaddr != NULL) {
|
|
os_printf("Got NTP server: %d.%d.%d.%d\r\n", IP2STR(ipaddr));
|
|
// Call the NTP update
|
|
ntp_server_ip.addr = ipaddr->addr;
|
|
ntp_get_time();
|
|
}
|
|
}
|
|
|
|
|
|
static void ICACHE_FLASH_ATTR ntp_udp_timeout(void *arg) {
|
|
|
|
os_timer_disarm(&ntp_timeout);
|
|
os_printf("NTP timout\r\n");
|
|
|
|
// clean up connection
|
|
if (pCon) {
|
|
espconn_delete(pCon);
|
|
os_free(pCon->proto.udp);
|
|
os_free(pCon);
|
|
pCon = 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void ICACHE_FLASH_ATTR ntp_udp_recv(void *arg, char *pdata, unsigned short len) {
|
|
ntp_t *ntp;
|
|
|
|
struct timeval tv;
|
|
int32_t hh, mm, ss;
|
|
|
|
get_cur_time(&tv);
|
|
|
|
// get the according sys_time;
|
|
t_offset = get_long_systime();
|
|
|
|
os_timer_disarm(&ntp_timeout);
|
|
|
|
// extract ntp time
|
|
ntp = (ntp_t*)pdata;
|
|
|
|
ntp_to_tv(ntp->trans_time, &t_tv);
|
|
|
|
os_printf("NTP resync - diff: %d usecs\r\n", t_tv.tv_usec-tv.tv_usec);
|
|
/*
|
|
ss = t_tv.tv_sec%60;
|
|
mm = (t_tv.tv_sec/60)%60;
|
|
hh = (t_tv.tv_sec/3600)%24;
|
|
os_printf("time: %2d:%02d:%02d\r\n", hh, mm, ss);
|
|
*/
|
|
// clean up connection
|
|
if (pCon) {
|
|
espconn_delete(pCon);
|
|
os_free(pCon->proto.udp);
|
|
os_free(pCon);
|
|
pCon = 0;
|
|
}
|
|
}
|
|
|
|
|
|
void ICACHE_FLASH_ATTR ntp_set_server(uint8_t *ntp_server) {
|
|
|
|
ntp_server_ip.addr = 0;
|
|
|
|
// invalid arg?
|
|
if (ntp_server == NULL)
|
|
return;
|
|
|
|
// ip or DNS name?
|
|
if (UTILS_IsIPV4(ntp_server)) {
|
|
// read address
|
|
UTILS_StrToIP(ntp_server, &ntp_server_ip);
|
|
ntp_get_time();
|
|
} else {
|
|
// call DNS and wait for callback
|
|
espconn_gethostbyname(&pConDNS, ntp_server, &ntp_server_ip, ntp_dns_found);
|
|
}
|
|
}
|
|
|
|
|
|
bool ICACHE_FLASH_ATTR ntp_sync_done() {
|
|
return t_offset!=0;
|
|
}
|
|
|
|
|
|
void ICACHE_FLASH_ATTR ntp_get_time() {
|
|
ntp_t ntp;
|
|
|
|
// either ongoing request or invalid ip?
|
|
if (pCon != 0 || ntp_server_ip.addr == 0)
|
|
return;
|
|
|
|
// set up the udp "connection"
|
|
pCon = (struct espconn*)os_zalloc(sizeof(struct espconn));
|
|
pCon->type = ESPCONN_UDP;
|
|
pCon->state = ESPCONN_NONE;
|
|
pCon->proto.udp = (esp_udp*)os_zalloc(sizeof(esp_udp));
|
|
pCon->proto.udp->local_port = espconn_port();
|
|
pCon->proto.udp->remote_port = 123;
|
|
os_memcpy(pCon->proto.udp->remote_ip, &ntp_server_ip, 4);
|
|
|
|
// create a really simple ntp request packet
|
|
os_memset(&ntp, 0, sizeof(ntp_t));
|
|
ntp.options = 0b00011011; // leap = 0, version = 3, mode = 3 (client)
|
|
|
|
// set timeout timer
|
|
os_timer_disarm(&ntp_timeout);
|
|
os_timer_setfn(&ntp_timeout, (os_timer_func_t*)ntp_udp_timeout, pCon);
|
|
os_timer_arm(&ntp_timeout, NTP_TIMEOUT_MS, 0);
|
|
|
|
// send the ntp request
|
|
espconn_create(pCon);
|
|
espconn_regist_recvcb(pCon, ntp_udp_recv);
|
|
espconn_sent(pCon, (uint8*)&ntp, sizeof(ntp_t));
|
|
}
|