kopia lustrzana https://github.com/martin-ger/esp_mqtt
added NTP time
rodzic
717c6c7653
commit
f8715595da
2
Makefile
2
Makefile
|
@ -33,7 +33,7 @@ ESPPORT ?= /dev/ttyUSB0
|
|||
TARGET = app
|
||||
|
||||
# which modules (subdirectories) of the project to include in compiling
|
||||
MODULES = driver user mqtt
|
||||
MODULES = driver user mqtt ntp
|
||||
#EXTRA_INCDIR = $(BUILD_AREA)/esp-open-sdk/esp-open-lwip/include include
|
||||
EXTRA_INCDIR = include
|
||||
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef __NTP_H__
|
||||
#define __NTP_H__
|
||||
#include <sys/time.h>
|
||||
|
||||
#define NTP_TIMEOUT_MS 5000
|
||||
|
||||
typedef struct {
|
||||
uint8 options;
|
||||
uint8 stratum;
|
||||
uint8 poll;
|
||||
uint8 precision;
|
||||
uint32 root_delay;
|
||||
uint32 root_disp;
|
||||
uint32 ref_id;
|
||||
uint8 ref_time[8];
|
||||
uint8 orig_time[8];
|
||||
uint8 recv_time[8];
|
||||
uint8 trans_time[8];
|
||||
} ntp_t;
|
||||
|
||||
void ntp_set_server(uint8_t *ntp_server);
|
||||
void ntp_get_time();
|
||||
void get_cur_time(struct timeval *tv);
|
||||
uint8_t *get_timestr(int16_t timezone);
|
||||
|
||||
#endif
|
|
@ -42,6 +42,11 @@ uint8_t mac[6];
|
|||
wifi_get_macaddr(0, mac);
|
||||
os_sprintf(config->mqtt_id,"%s_%2x%2x%2x", MQTT_ID, mac[3], mac[4], mac[5]);
|
||||
#endif
|
||||
#ifdef NTP
|
||||
os_sprintf(config->ntp_server,"%s", "none");
|
||||
config->ntp_interval = 60000000;
|
||||
config->ntp_timezone = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int config_load(sysconfig_p config)
|
||||
|
|
|
@ -53,7 +53,11 @@ typedef struct
|
|||
uint8_t mqtt_password[32]; // Password for broker login
|
||||
uint8_t mqtt_id[32]; // MQTT clientId
|
||||
#endif
|
||||
|
||||
#ifdef NTP
|
||||
uint8_t ntp_server[32]; // IP or hostname of the MQTT broker, "none" if empty
|
||||
uint32_t ntp_interval; // Sync interval in usec
|
||||
int16_t ntp_timezone; // Timezone (hour offset to GMT)
|
||||
#endif
|
||||
} sysconfig_t, *sysconfig_p;
|
||||
|
||||
int config_load(sysconfig_p config);
|
||||
|
|
|
@ -26,6 +26,11 @@ typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SI
|
|||
|
||||
#define MQTT_ID "ESPBroker"
|
||||
|
||||
//
|
||||
// Define this if you want to have NTP support.
|
||||
//
|
||||
#define NTP 1
|
||||
|
||||
//
|
||||
// Size of the console buffers
|
||||
//
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
#include "mqtt_topiclist.h"
|
||||
#include "mqtt_retainedlist.h"
|
||||
|
||||
#ifdef NTP
|
||||
#include "ntp.h"
|
||||
uint64_t t_ntp_resync = 0;
|
||||
#endif
|
||||
|
||||
/* System Task, for signals refer to user_config.h */
|
||||
#define user_procTaskPrio 0
|
||||
#define user_procTaskQueueLen 1
|
||||
|
@ -242,6 +247,10 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
|
|||
os_sprintf(response, "|scan");
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
#endif
|
||||
#ifdef NTP
|
||||
os_sprintf(response, "|time|set ntp_server <ntp_host>|set ntp_interval <secs>|set <ntp_timezone> <hours>\r\n");
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
#endif
|
||||
#ifdef MQTT_CLIENT
|
||||
os_sprintf(response, "|set [mqtt_host|mqtt_port|mqtt_user|mqtt_password|mqtt_id] <val>\r\n");
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
|
@ -287,6 +296,13 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
|
|||
config.locked?"***":(char*)config.mqtt_password, config.mqtt_id);
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
}
|
||||
#endif
|
||||
#ifdef NTP
|
||||
if (os_strcmp(config.ntp_server, "none") != 0) {
|
||||
os_sprintf(response, "NTP server: %s (interval: %d s, tz: %d)\r\n",
|
||||
config.ntp_server, config.ntp_interval/1000000, config.ntp_timezone);
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
}
|
||||
#endif
|
||||
os_sprintf(response, "Clock speed: %d\r\n", config.clock_speed);
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
|
@ -361,6 +377,13 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
|
|||
os_sprintf(response, "Scanning...\r\n");
|
||||
goto command_handled;
|
||||
}
|
||||
#endif
|
||||
#ifdef NTP
|
||||
if (strcmp(tokens[0], "time") == 0)
|
||||
{
|
||||
os_sprintf(response, "%s\r\n", get_timestr(config.ntp_timezone));
|
||||
goto command_handled;
|
||||
}
|
||||
#endif
|
||||
if (strcmp(tokens[0], "reset") == 0)
|
||||
{
|
||||
|
@ -389,7 +412,7 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
|
|||
goto command_handled;
|
||||
}
|
||||
if (strcmp(tokens[1], "local") == 0) {
|
||||
MQTT_local_publish(tokens[2], tokens[3], os_strlen(tokens[2]), 0, 0);
|
||||
MQTT_local_publish(tokens[2], tokens[3], os_strlen(tokens[3]), 0, 0);
|
||||
}
|
||||
#ifdef MQTT_CLIENT
|
||||
else if (strcmp(tokens[1], "remote") == 0 && mqtt_connected) {
|
||||
|
@ -625,7 +648,30 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
|
|||
IP2STR(&config.my_gw));
|
||||
goto command_handled;
|
||||
}
|
||||
#ifdef NTP
|
||||
if (strcmp(tokens[1], "ntp_server") == 0)
|
||||
{
|
||||
os_strncpy(config.ntp_server, tokens[2], 32);
|
||||
config.ntp_server[31] = 0;
|
||||
ntp_set_server(config.ntp_server);
|
||||
os_sprintf(response, "NTP server set to %s\r\n", config.ntp_server);
|
||||
goto command_handled;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[1], "ntp_interval") == 0)
|
||||
{
|
||||
config.ntp_interval = atoi(tokens[2])*1000000;
|
||||
os_sprintf(response, "NTP interval set to %d s\r\n", atoi(tokens[2]));
|
||||
goto command_handled;
|
||||
}
|
||||
|
||||
if (strcmp(tokens[1], "ntp_timezone") == 0)
|
||||
{
|
||||
config.ntp_timezone = atoi(tokens[2]);
|
||||
os_sprintf(response, "NTP timezone set to %d h\r\n", config.ntp_timezone);
|
||||
goto command_handled;
|
||||
}
|
||||
#endif
|
||||
#ifdef MQTT_CLIENT
|
||||
if (strcmp(tokens[1], "mqtt_host") == 0)
|
||||
{
|
||||
|
@ -749,6 +795,12 @@ uint32_t t_diff;
|
|||
}
|
||||
|
||||
t_new = get_long_systime();
|
||||
#ifdef NTP
|
||||
if (t_new - t_ntp_resync > config.ntp_interval) {
|
||||
ntp_get_time();
|
||||
t_ntp_resync = t_new;
|
||||
}
|
||||
#endif
|
||||
|
||||
os_timer_arm(&ptimer, toggle?1000:100, 0);
|
||||
}
|
||||
|
@ -1006,6 +1058,11 @@ struct ip_info info;
|
|||
}
|
||||
#endif /* MQTT_CLIENT */
|
||||
|
||||
#ifdef NTP
|
||||
if (os_strcmp(config.ntp_server, "none") != 0)
|
||||
ntp_set_server(config.ntp_server);
|
||||
#endif
|
||||
|
||||
remote_console_disconnect = 0;
|
||||
|
||||
// Now start the STA-Mode
|
||||
|
|
Ładowanie…
Reference in New Issue