using System; using System.Net; using System.Net.Sockets; public class NtpService { private readonly string _ntpServer; private TimeSpan _timeOffset = TimeSpan.Zero; private DateTime _lastSync = DateTime.MinValue; public NtpService(string ntpServer) { _ntpServer = ntpServer; } public DateTime GetCurrentTime() { // Sync with your NTP server every 1 hour if ((DateTime.UtcNow - _lastSync).TotalHours > 1) { SyncWithNtp(); } // Apply the offset so the clock advances smoothly between syncs return DateTime.Now.Add(_timeOffset); } private void SyncWithNtp() { try { var ntpData = new byte[48]; ntpData[0] = 0x1B; // NTP request header (Client mode, Version 3) var addresses = Dns.GetHostEntry(_ntpServer).AddressList; var ipEndPoint = new IPEndPoint(addresses[0], 123); using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { socket.ReceiveTimeout = 3000; socket.Connect(ipEndPoint); socket.Send(ntpData); socket.Receive(ntpData); } // Parse the 64-bit timestamp from the NTP response ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | (ulong)ntpData[43]; ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | (ulong)ntpData[47]; var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L); var networkTime = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)milliseconds); // Calculate the difference between Pi's local UTC and NTP UTC _timeOffset = networkTime - DateTime.UtcNow; _lastSync = DateTime.UtcNow; Console.WriteLine($"NTP Sync to {_ntpServer} successful. Offset: {_timeOffset.TotalMilliseconds:F1}ms"); } catch (Exception ex) { Console.WriteLine($"NTP Sync failed: {ex.Message}"); } } }