pull/16/head
Martin Ger 2017-07-12 22:04:02 +02:00
rodzic 717c6c7653
commit f8715595da
7 zmienionych plików z 270 dodań i 3 usunięć

Wyświetl plik

@ -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

170
ntp/ntp.c 100644
Wyświetl plik

@ -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));
}

26
ntp/ntp.h 100644
Wyświetl plik

@ -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

Wyświetl plik

@ -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)

Wyświetl plik

@ -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);

Wyświetl plik

@ -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
//

Wyświetl plik

@ -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