mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-22 02:06:31 +00:00
Add NTP Local Server Library
This commit is contained in:
parent
69a79c83a5
commit
1a02f52de9
39
lib/ArduinoNTPd/NTPPacket.cpp
Normal file
39
lib/ArduinoNTPd/NTPPacket.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* File: NTPPacket.cpp
|
||||||
|
* Description:
|
||||||
|
* NTP packet representation.
|
||||||
|
* Author: Mooneer Salem <mooneer@gmail.com>
|
||||||
|
* License: New BSD License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "NTPPacket.h"
|
||||||
|
|
||||||
|
void NtpPacket::swapEndian()
|
||||||
|
{
|
||||||
|
reverseBytes_(&rootDelay);
|
||||||
|
reverseBytes_(&rootDispersion);
|
||||||
|
reverseBytes_(&referenceTimestampSeconds);
|
||||||
|
reverseBytes_(&referenceTimestampFraction);
|
||||||
|
reverseBytes_(&originTimestampSeconds);
|
||||||
|
reverseBytes_(&originTimestampFraction);
|
||||||
|
reverseBytes_(&receiveTimestampSeconds);
|
||||||
|
reverseBytes_(&receiveTimestampFraction);
|
||||||
|
reverseBytes_(&transmitTimestampSeconds);
|
||||||
|
reverseBytes_(&transmitTimestampFraction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NtpPacket::reverseBytes_(uint32_t *number)
|
||||||
|
{
|
||||||
|
char buf[4];
|
||||||
|
char *numberAsChar = (char*)number;
|
||||||
|
|
||||||
|
buf[0] = numberAsChar[3];
|
||||||
|
buf[1] = numberAsChar[2];
|
||||||
|
buf[2] = numberAsChar[1];
|
||||||
|
buf[3] = numberAsChar[0];
|
||||||
|
|
||||||
|
numberAsChar[0] = buf[0];
|
||||||
|
numberAsChar[1] = buf[1];
|
||||||
|
numberAsChar[2] = buf[2];
|
||||||
|
numberAsChar[3] = buf[3];
|
||||||
|
}
|
75
lib/ArduinoNTPd/NTPPacket.h
Normal file
75
lib/ArduinoNTPd/NTPPacket.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* File: NTPPacket.h
|
||||||
|
* Description:
|
||||||
|
* NTP packet representation.
|
||||||
|
* Author: Mooneer Salem <mooneer@gmail.com>
|
||||||
|
* License: New BSD License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NTP_PACKET_H
|
||||||
|
#define NTP_PACKET_H
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains the data in a typical NTP packet.
|
||||||
|
*/
|
||||||
|
struct NtpPacket
|
||||||
|
{
|
||||||
|
static const int PACKET_SIZE = 48;
|
||||||
|
|
||||||
|
unsigned char leapVersionMode;
|
||||||
|
|
||||||
|
unsigned int leapIndicator() const { return leapVersionMode >> 6; }
|
||||||
|
void leapIndicator(unsigned int newValue) { leapVersionMode = (0x3F & leapVersionMode) | ((newValue & 0x03) << 6); }
|
||||||
|
|
||||||
|
unsigned int versionNumber() const { return (leapVersionMode >> 3) & 0x07; }
|
||||||
|
void versionNumber(unsigned int newValue) { leapVersionMode = (0xC7 & leapVersionMode) | ((newValue & 0x07) << 3); }
|
||||||
|
|
||||||
|
unsigned int mode() const { return (leapVersionMode & 0x07); }
|
||||||
|
void mode(unsigned int newValue) { leapVersionMode = (leapVersionMode & 0xF8) | (newValue & 0x07); }
|
||||||
|
|
||||||
|
char stratum;
|
||||||
|
char poll;
|
||||||
|
char precision;
|
||||||
|
uint32_t rootDelay;
|
||||||
|
uint32_t rootDispersion;
|
||||||
|
char referenceId[4];
|
||||||
|
uint32_t referenceTimestampSeconds;
|
||||||
|
uint32_t referenceTimestampFraction;
|
||||||
|
uint32_t originTimestampSeconds;
|
||||||
|
uint32_t originTimestampFraction;
|
||||||
|
uint32_t receiveTimestampSeconds;
|
||||||
|
uint32_t receiveTimestampFraction;
|
||||||
|
uint32_t transmitTimestampSeconds;
|
||||||
|
uint32_t transmitTimestampFraction;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rearranges bytes in 32 bit values from big-endian (NTP protocol)
|
||||||
|
* to little-endian (Arduino/PC), or vice versa. Must be called before
|
||||||
|
* modifying the structure or sending the packet.
|
||||||
|
*/
|
||||||
|
void swapEndian();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns packet as a char array for transmission via network.
|
||||||
|
* WARNING: modifying the return value is unsafe.
|
||||||
|
*/
|
||||||
|
const char *packet() { return (const char*)this; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copies packet buffer to packet object.
|
||||||
|
*/
|
||||||
|
void populatePacket(const char *buffer)
|
||||||
|
{
|
||||||
|
memcpy(this, buffer, PACKET_SIZE);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
* Reverses bytes in a number.
|
||||||
|
*/
|
||||||
|
void reverseBytes_(uint32_t *number);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NTP_PACKET_H
|
79
lib/ArduinoNTPd/NTPServer.cpp
Normal file
79
lib/ArduinoNTPd/NTPServer.cpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* File: NTPServer.cpp
|
||||||
|
* Description:
|
||||||
|
* NTP server implementation.
|
||||||
|
* Author: Mooneer Salem <mooneer@gmail.com>
|
||||||
|
* License: New BSD License
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
|
||||||
|
#include "NTPPacket.h"
|
||||||
|
#include "NTPServer.h"
|
||||||
|
|
||||||
|
#define NTP_PORT 123
|
||||||
|
#define NTP_TIMESTAMP_DIFF (2208988800) // 1900 to 1970 in seconds
|
||||||
|
|
||||||
|
bool NtpServer::beginListening()
|
||||||
|
{
|
||||||
|
if (timeServerPort_.begin(NTP_PORT)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NtpServer::processOneRequest(uint32_t utc, uint32_t millisecs)
|
||||||
|
{
|
||||||
|
// We need the time we've received the packet in our response.
|
||||||
|
uint32_t recvSecs = utc + NTP_TIMESTAMP_DIFF;
|
||||||
|
double recvFractDouble = (double)millisecs/0.00023283064365386963; // millisec/((10^6)/(2^32))
|
||||||
|
uint32_t recvFract = (double)recvFractDouble; //TODO: really handle this!!!
|
||||||
|
bool processed = false;
|
||||||
|
|
||||||
|
int packetDataSize = timeServerPort_.parsePacket();
|
||||||
|
if (packetDataSize && packetDataSize >= NtpPacket::PACKET_SIZE)
|
||||||
|
{
|
||||||
|
// Received what is probably an NTP packet. Read it in and verify
|
||||||
|
// that it's legit.
|
||||||
|
NtpPacket packet;
|
||||||
|
timeServerPort_.read((char*)&packet, NtpPacket::PACKET_SIZE);
|
||||||
|
// TODO: verify packet.
|
||||||
|
|
||||||
|
// Populate response.
|
||||||
|
packet.swapEndian();
|
||||||
|
packet.leapIndicator(0);
|
||||||
|
packet.versionNumber(4);
|
||||||
|
packet.mode(4);
|
||||||
|
packet.stratum = 2; // I guess stratum 1 is too optimistic
|
||||||
|
packet.poll = 10; // 6-10 per RFC 5905.
|
||||||
|
packet.precision = -21; // ~0.5 microsecond precision.
|
||||||
|
packet.rootDelay = 0; //60 * (0xFFFF / 1000); // ~60 milliseconds, TBD
|
||||||
|
packet.rootDispersion = 0; //10 * (0xFFFF / 1000); // ~10 millisecond dispersion, TBD
|
||||||
|
packet.referenceId[0] = 'G';
|
||||||
|
packet.referenceId[1] = 'P';
|
||||||
|
packet.referenceId[2] = 'S';
|
||||||
|
packet.referenceId[3] = 0;
|
||||||
|
packet.referenceTimestampSeconds = utc;
|
||||||
|
packet.referenceTimestampFraction = recvFract;
|
||||||
|
packet.originTimestampSeconds = packet.transmitTimestampSeconds;
|
||||||
|
packet.originTimestampFraction = packet.transmitTimestampFraction;
|
||||||
|
packet.receiveTimestampSeconds = recvSecs;
|
||||||
|
packet.receiveTimestampFraction = recvFract;
|
||||||
|
|
||||||
|
// ...and the transmit time.
|
||||||
|
// timeSource_.now(&packet.transmitTimestampSeconds, &packet.transmitTimestampFraction);
|
||||||
|
|
||||||
|
// Now transmit the response to the client.
|
||||||
|
packet.swapEndian();
|
||||||
|
timeServerPort_.beginPacket(timeServerPort_.remoteIP(), timeServerPort_.remotePort());
|
||||||
|
for (int count = 0; count < NtpPacket::PACKET_SIZE; count++)
|
||||||
|
{
|
||||||
|
timeServerPort_.write(packet.packet()[count]);
|
||||||
|
}
|
||||||
|
timeServerPort_.endPacket();
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
}
|
35
lib/ArduinoNTPd/NTPServer.h
Normal file
35
lib/ArduinoNTPd/NTPServer.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* File: NTPServer.h
|
||||||
|
* Description:
|
||||||
|
* NTP server implementation.
|
||||||
|
* Author: Mooneer Salem <mooneer@gmail.com>
|
||||||
|
* License: New BSD License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NTP_SERVER_H
|
||||||
|
#define NTP_SERVER_H
|
||||||
|
|
||||||
|
class NtpServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NtpServer(WiFiUDP Port)
|
||||||
|
{
|
||||||
|
timeServerPort_=Port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Begins listening for NTP requests.
|
||||||
|
*/
|
||||||
|
bool beginListening(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Processes a single NTP request.
|
||||||
|
*/
|
||||||
|
bool processOneRequest(uint32_t utc, uint32_t millisecs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
WiFiUDP timeServerPort_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NTP_SERVER_H
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
xsns_92_GPS_UBX.ino - GPS UBLOX support for Sonoff-Tasmota
|
xsns_58_GPS_UBX.ino - GPS UBLOX support for Sonoff-Tasmota
|
||||||
|
|
||||||
Copyright (C) 2019 Theo Arends, Christian Baars and Adrian Scillato
|
Copyright (C) 2019 Theo Arends, Christian Baars and Adrian Scillato
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user