Friday 1 February 2013

Gadgeteer - Setting system time from the internet


I came across a scenario recently where i needed to get set the system time from an NTP server on my gadgeteer mainboard.

















It's easy enough to set the system time using the Utility.SetLocalTime method, but we still need some way of getting the correct time from the network.

Turns out that we have some built in functionality to do this.


TimeService


The TimeService class provides some helper methods to allow syncing the local system time from an NTP server. We can also specify a time period, after which the TimeService will update from the NTP server again.

The code below gets the current time from time.windows.com syncs the system time and prints it out the the console.

First make sure you have added a reference to Microsoft.Spot.Time


    void SetTime()   
    {   
     Debug.Print("setting time");
   
     TimeService.SystemTimeChanged += new SystemTimeChangedEventHandler(TimeService_SystemTimeChanged);   
     TimeService.TimeSyncFailed += new TimeSyncFailedEventHandler(TimeService_TimeSyncFailed);  
 
     var settings = new TimeServiceSettings();   
     settings.ForceSyncAtWakeUp = true;
   
     // refresh time is in seconds   
     settings.RefreshTime = 1800;
    
     settings.PrimaryServer = GetTimeServerAddress();
   
     TimeService.Settings = settings;   
     TimeService.SetTimeZoneOffset(0);   
     TimeService.Start();   
    }
   
    byte[] GetTimeServerAddress()   
    {   
     IPAddress[] address = Dns.GetHostEntry("time.windows.com").AddressList;   
     if (address != null && address.Length > 0)   
     {   
      return address[0].GetAddressBytes();   
     }   
     throw new ApplicationException("Could not get time server address");   
    }
   
    void TimeService_TimeSyncFailed(object sender, TimeSyncFailedEventArgs e)   
    {   
     Debug.Print("error synchronizing time with NTP server: " + e.ErrorCode);   
    } 
  
    void TimeService_SystemTimeChanged(object sender, SystemTimeChangedEventArgs e)   
    {   
     Debug.Print("network time received. Current Date Time is " + DateTime.Now.ToString());   
    }   
 

Hopefully this will be useful for someone else out there.

1 comment:

  1. Hello,

    Nice code, that's exactly what I need! But I encounter several errors during the execution! I am using FEZ spider mainboard with WiFi RS21, and after I connect the device I tried to run (setTime()) method and I ended with exception from the program such as (exceeded 10 seconds etc..)

    // This method is run when the mainboard is powered up or reset.
    string ssid = "OOOOOOOOOOOOOO"; // <<<<< You need to enter your SSID here
    string PassKey = "111111111111111"; // <<<<< You need to enter your Password/Key here

    void ProgramStarted()
    {

    wifi_RS21.UseDHCP();
    WiFiNetworkInfo info = new WiFiNetworkInfo();
    info.SSID = ssid;
    info.SecMode = SecurityMode.WEP;
    info.networkType = NetworkType.AccessPoint;
    wifi_RS21.Interface.Join(info, PassKey);
    if (!wifi_RS21.Interface.IsOpen)
    wifi_RS21.Interface.Open();
    if (!wifi_RS21.Interface.NetworkInterface.IsDhcpEnabled)
    wifi_RS21.Interface.NetworkInterface.EnableDhcp();
    Debug.Print("Program Started and it's connected and " + wifi_RS21.IsNetworkConnected.ToString());
    SetTime();
    }

    void SetTime()
    {
    Debug.Print("setting time");

    TimeService.SystemTimeChanged += new SystemTimeChangedEventHandler(TimeService_SystemTimeChanged);
    TimeService.TimeSyncFailed += new TimeSyncFailedEventHandler(TimeService_TimeSyncFailed);

    var settings = new TimeServiceSettings();
    settings.ForceSyncAtWakeUp = true;

    // refresh time is in seconds
    settings.RefreshTime = 1800;

    settings.PrimaryServer = GetTimeServerAddress();

    TimeService.Settings = settings;
    TimeService.SetTimeZoneOffset(0);
    TimeService.Start();
    }

    byte[] GetTimeServerAddress()
    {
    IPAddress[] address = Dns.GetHostEntry("time.windows.com").AddressList;
    if (address != null && address.Length > 0)
    {
    return address[0].GetAddressBytes();
    }
    throw new ApplicationException("Could not get time server address");
    }

    void TimeService_TimeSyncFailed(object sender, TimeSyncFailedEventArgs e)
    {
    Debug.Print("error synchronizing time with NTP server: " + e.ErrorCode);
    }

    void TimeService_SystemTimeChanged(object sender, SystemTimeChangedEventArgs e)
    {
    Debug.Print("network time received. Current Date Time is " + DateTime.Now.ToString());
    }

    this is my full code

    ReplyDelete