#include "sntp_api.h" #include "rtc.h" #include "settings_api.h" #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include "tcpip.h" #include "udp.h" #include #include #ifdef PRINTF_STDLIB #include #endif #ifdef PRINTF_CUSTOM #include "tinystdio.h" #endif #define SENDFAIL_TIMEOUT 5000 /* 5 seconds */ #define SENT_TIMEOUT 60000 /* 1 minute */ #define BADREPLY_TIMEOUT 60000 /* 1 minute */ #define VALID_TIMEOUT (8 * 3600000) /* 8 hours */ /* number of seconds between 1900 and 1970 */ #define DIFF_SEC_1900_1970 (2208988800UL) struct sntp_packet { uint8_t status; uint8_t stratum; uint8_t ppoll; uint8_t precision; uint32_t distance; uint32_t dispersion; uint32_t refid; uint64_t reftime; uint64_t org; uint64_t rec; uint64_t xmt; }; static unsigned int timeout; static struct udp_pcb* upcb; static struct ip4_addr server; static int port = 123; extern bool ntpResult; extern uint32_t SNTP_Time; /** * @brief Отладочный таск. Выводим время в консоль. * @retval */ void vTaskSntp(void *arg) { TM_RTC_t data; for (;;) { vTaskDelay(1000); TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN); printf("%d.%d.%d %d:%d:%d \n\r", data.date,data.month,data.year,data.hours,data.minutes,data.seconds); } } static void recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port) { time_t t; //struct tm *time; //struct tm *ptrTime = &time; if (p->len == sizeof(struct sntp_packet)) { int i; struct sntp_packet aligned; //myassert(p->len == p->tot_len); /* don't accept chained pbuf */ memcpy(&aligned, p->payload, sizeof(aligned)); i = (aligned.status >> 3) & 7; if ((i < 1) || (i > 4)) /* SNTP version 1..4 */ goto out; i = aligned.status & 7; if ((i != 4) && (i != 5)) /* mode 4 or 5: server or broadcast */ goto out; if (aligned.xmt == 0) goto out; t = (ntohl(aligned.xmt) - 2208988800); TM_RTC_SetDataTimeUnix((uint32_t)t); //time = __localtime32(&t); SNTP_Time = t; ntpResult = true; //printf("%s\r\n", asctime(time)); timeout = VALID_TIMEOUT; } out: pbuf_free(p); } void SNTP_Enable(bool enable) { if (enable) { if (upcb == 0) { err_t ret; upcb = udp_new(); if (upcb != 0) { ret = udp_bind(upcb, IP_ADDR_ANY, port); if (ret != ERR_OK) { udp_remove(upcb); upcb = 0; } else { udp_recv(upcb, recv, 0); } timeout = 0; } } } else if (upcb != 0) { udp_remove(upcb); upcb = 0; } } bool SNTP_IsEnabled(void) { return upcb != 0; } void SNTP_SetServerAddr(char *addr) { server.addr = ipaddr_addr(addr); } int sntp_getserverport(void) { return port; } static void send_request(void) { struct sntp_packet packet; struct pbuf* psend; memset(&packet, 0, sizeof(packet)); packet.status = (3 << 3) /* SNTP vesion 3 */ | (3 << 0); /* Mode: client */ psend = pbuf_alloc(PBUF_RAW, sizeof(packet), PBUF_REF); if (psend != 0) { psend->payload = &packet; timeout = (udp_sendto(upcb, psend, &server, port) == ERR_OK) ? SENT_TIMEOUT : SENDFAIL_TIMEOUT; pbuf_free(psend); } } void SNTP_Poll(void) { if (upcb) send_request(); }