Reply To: Updating date and time with ntp?

HomeForumsMonoBrick EV3 FirmwareUpdating date and time with ntp?Reply To: Updating date and time with ntp?

#5333
Author Image
Kristofer Jaxne
Participant

I found solutions to this problem so I can show how I did.

First I create a new class with the needed methods.

using System;
using MonoBrickFirmware;
using System.Threading;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using MonoBrickFirmware.Display;

public class Linux
{
public Linux ()
{
}

public void SendCommand (string file, string arguments)
{
	Process proc = new Process ();
	proc.StartInfo.FileName = file;
	proc.StartInfo.Arguments = arguments;
	proc.StartInfo.UseShellExecute = false; 
	proc.StartInfo.RedirectStandardError = true;
	proc.StartInfo.RedirectStandardInput = true;
	proc.StartInfo.RedirectStandardOutput = true;
	proc.Start();
	var output = proc.StandardOutput.ReadToEnd ();
	LcdConsole.WriteLine("stdout: {0}", output);
}

public DateTime GetNetworkTime()
{
	try 
	{
		//default Windows time server
		const string ntpServer = "time.windows.com";

		// NTP message size - 16 bytes of the digest (RFC 2030)
		var ntpData = new byte[48];

		//Setting the Leap Indicator, Version Number and Mode values
		ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)

		var addresses = Dns.GetHostEntry(ntpServer).AddressList;

		//The UDP port number assigned to NTP is 123
		var ipEndPoint = new IPEndPoint(addresses[0], 123);
		//NTP uses UDP
		var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

		socket.Connect(ipEndPoint);

		//Stops code hang if NTP is blocked
		socket.ReceiveTimeout = 3000;     

		socket.Send(ntpData);
		socket.Receive(ntpData);
		socket.Close();

		//Offset to get to the "Transmit Timestamp" field (time at which the reply 
		//departed the server for the client, in 64-bit timestamp format."
		const byte serverReplyTime = 40;

		//Get the seconds part
		ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);
		//Get the seconds fraction
		ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);

		//Convert From big-endian to little-endian
		intPart = SwapEndianness(intPart);
		fractPart = SwapEndianness(fractPart);

		var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);

		//**UTC** time
		var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);

		networkDateTime = networkDateTime.AddHours(2); // Local time Sweden summer time = UTC + 2
		return networkDateTime.ToLocalTime();

	}
	catch 
	{
		DateTime time = new DateTime (1900, 01, 01);
		return time;
	}
}

private static uint SwapEndianness(ulong x)
{
	return (uint) (((x & 0x000000ff) << 24) +
		((x & 0x0000ff00) << 8) +
		((x & 0x00ff0000) >> 8) +
		((x & 0xff000000) >> 24));
}
}

I use the methods in the class like this:

Linux linux = new Linux ();
DateTime servertime = new DateTime();

for (int i = 0; i < 5; i++)
{
        servertime = linux.GetNetworkTime ();
	Thread.Sleep (500);
	if (servertime.Year != 1900)
		break;
}
if (servertime.Year == 1900) 
	LcdConsole.WriteLine ("Failed to get time");
else
	LcdConsole.WriteLine (servertime.ToString ("yyyy-MM-dd HH:mm:ss"));
			
linux.SendCommand ("date", "\"" + servertime.ToString ("yyyy-MM-dd HH:mm:ss") + "\"");
linux.SendCommand ("hwclock", "-w -l");
Posted in

Make a donation