mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-03-25 00:26:54 +01:00
233 lines
6.8 KiB
C
233 lines
6.8 KiB
C
// NTP client
|
|
// Based on my previous work here:
|
|
// https://www.elektroda.pl/rtvforum/topic3712112.html
|
|
|
|
#include "../new_common.h"
|
|
// Commands register, execution API and cmd tokenizer
|
|
#include "../cmnds/cmd_public.h"
|
|
|
|
|
|
#include "../logging/logging.h"
|
|
|
|
#define LOG_FEATURE LOG_FEATURE_NTP
|
|
|
|
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.
|
|
|
|
#define MAKE_WORD(hi, lo) hi << 8 | lo
|
|
|
|
// NTP time since 1900 to unix time (since 1970)
|
|
// Number of seconds to ad
|
|
#define NTP_OFFSET 2208988800L
|
|
|
|
static int g_ntp_socket = 0;
|
|
static struct sockaddr_in g_address;
|
|
static int adrLen;
|
|
// in seconds, before next retry
|
|
static int g_ntp_delay = 5;
|
|
// current time
|
|
static unsigned int g_time;
|
|
// time offset (time zone?)
|
|
static int g_timeOffsetHours;
|
|
|
|
int NTP_SetTimeZoneOfs(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
|
Tokenizer_TokenizeString(args);
|
|
if(Tokenizer_GetArgsCount() < 1) {
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Command requires one argument\n");
|
|
return 0;
|
|
}
|
|
g_timeOffsetHours = Tokenizer_GetArgInteger(0) * 60 * 60;
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"NTP offset set, wait for next ntp packet to apply changes\n");
|
|
return 1;
|
|
}
|
|
void NTP_Init() {
|
|
|
|
CMD_RegisterCommand("ntp_timeZoneOfs","",NTP_SetTimeZoneOfs, "Sets the time zone offset in hours", NULL);
|
|
}
|
|
|
|
unsigned int NTP_GetCurrentTime() {
|
|
return g_time;
|
|
}
|
|
|
|
|
|
void NTP_Shutdown() {
|
|
if(g_ntp_socket != 0) {
|
|
#if WINDOWS
|
|
closesocket(g_ntp_socket);
|
|
#else
|
|
lwip_close(g_ntp_socket);
|
|
#endif
|
|
}
|
|
g_ntp_socket = 0;
|
|
// can attempt in next 10 seconds
|
|
g_ntp_delay = 10;
|
|
}
|
|
void NTP_SendRequest(bool bBlocking) {
|
|
byte *ptr;
|
|
//int i, recv_len;
|
|
//char buf[64];
|
|
ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
|
|
adrLen = sizeof(g_address);
|
|
memset( &packet, 0, sizeof( ntp_packet ) );
|
|
ptr = (byte*)&packet;
|
|
// Initialize values needed to form NTP request
|
|
// (see URL above for details on the packets)
|
|
ptr[0] = 0xE3; // LI, Version, Mode
|
|
ptr[1] = 0; // Stratum, or type of clock
|
|
ptr[2] = 6; // Polling Interval
|
|
ptr[3] = 0xEC; // Peer Clock Precision
|
|
// 8 bytes of zero for Root Delay & Root Dispersion
|
|
ptr[12] = 49;
|
|
ptr[13] = 0x4E;
|
|
ptr[14] = 49;
|
|
ptr[15] = 52;
|
|
|
|
|
|
//create a UDP socket
|
|
if ((g_ntp_socket=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP )) == -1)
|
|
{
|
|
g_ntp_socket = 0;
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"NTP_SendRequest: failed to create socket");
|
|
return;
|
|
}
|
|
|
|
memset((char *) &g_address, 0, sizeof(g_address));
|
|
|
|
g_address.sin_family = AF_INET;
|
|
g_address.sin_addr.s_addr = inet_addr("217.147.223.78"); // this is address of host which I want to send the socket
|
|
g_address.sin_port = htons(123);
|
|
|
|
|
|
// Send the message to server:
|
|
if(sendto(g_ntp_socket, &packet, sizeof(packet), 0,
|
|
(struct sockaddr*)&g_address, adrLen) < 0) {
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"NTP_SendRequest: Unable to send message");
|
|
NTP_Shutdown();
|
|
return;
|
|
}
|
|
|
|
// https://github.com/tuya/tuya-iotos-embeded-sdk-wifi-ble-bk7231t/blob/5e28e1f9a1a9d88425f3fd4b658e895a8ee7b83b/platforms/bk7231t/tuya_os_adapter/src/system/tuya_hal_network.c
|
|
//
|
|
if(bBlocking == false) {
|
|
#if WINDOWS
|
|
#else
|
|
if(fcntl(g_ntp_socket, F_SETFL, O_NONBLOCK)) {
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"NTP_SendRequest: failed to make socket non-blocking!\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// can attempt in next 10 seconds
|
|
g_ntp_delay = 10;
|
|
}
|
|
void NTP_CheckForReceive() {
|
|
byte *ptr;
|
|
int i, recv_len;
|
|
//struct tm * ptm;
|
|
unsigned short highWord;
|
|
unsigned short lowWord;
|
|
unsigned int secsSince1900;
|
|
ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
ptr = (byte*)&packet;
|
|
|
|
// Receive the server's response:
|
|
i = sizeof(packet);
|
|
#if 0
|
|
recv_len = recvfrom(g_ntp_socket, ptr, i, 0,
|
|
(struct sockaddr*)&g_address, &adrLen);
|
|
#else
|
|
recv_len = recv(g_ntp_socket, ptr, i, 0);
|
|
#endif
|
|
|
|
if(recv_len < 0){
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"NTP_CheckForReceive: Error while receiving server's msg\n");
|
|
return;
|
|
}
|
|
highWord = MAKE_WORD(ptr[40], ptr[41]);
|
|
lowWord = MAKE_WORD(ptr[42], ptr[43]);
|
|
// combine the four bytes (two words) into a long integer
|
|
// this is NTP time (seconds since Jan 1 1900):
|
|
secsSince1900 = highWord << 16 | lowWord;
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Seconds since Jan 1 1900 = %u",secsSince1900);
|
|
|
|
g_time = secsSince1900 - NTP_OFFSET;
|
|
g_time += g_timeOffsetHours;
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"Unix time = %u",g_time);
|
|
#if 0
|
|
//ptm = localtime (&g_time);
|
|
ptm = gmtime(&g_time);
|
|
if(ptm == 0) {
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"gmtime somehow returned 0\n");
|
|
} else {
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"gmtime => tm_year: %i\n",ptm->tm_year);
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"gmtime => tm_mon: %i\n",ptm->tm_mon);
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"gmtime => tm_mday: %i\n",ptm->tm_mday);
|
|
addLogAdv(LOG_INFO, LOG_FEATURE_NTP,"gmtime => tm_hour: %i\n",ptm->tm_hour );
|
|
}
|
|
#endif
|
|
NTP_Shutdown();
|
|
|
|
}
|
|
|
|
void NTP_SendRequest_BlockingMode() {
|
|
NTP_Shutdown();
|
|
NTP_SendRequest(true);
|
|
NTP_CheckForReceive();
|
|
|
|
}
|
|
|
|
|
|
void NTP_OnEverySecond() {
|
|
g_time++;
|
|
|
|
if(Main_IsConnectedToWiFi()==0) {
|
|
return;
|
|
}
|
|
if(g_ntp_socket == 0) {
|
|
// if no socket, this is a reconnect delay
|
|
if(g_ntp_delay > 0) {
|
|
g_ntp_delay--;
|
|
return;
|
|
}
|
|
NTP_SendRequest(false);
|
|
} else {
|
|
NTP_CheckForReceive();
|
|
// if socket exists, this is a disconnect timeout
|
|
if(g_ntp_delay > 0) {
|
|
g_ntp_delay--;
|
|
if(g_ntp_delay<=0) {
|
|
// disconnect and force reconnect
|
|
NTP_Shutdown();
|
|
}
|
|
}
|
|
}
|
|
}
|