Still learning, internet way to grab date and time on startup - Netduino Plus 2 (and Netduino Plus 1) - Netduino Forums
   
Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Still learning, internet way to grab date and time on startup


  • Please log in to reply
19 replies to this topic

#1 freds

freds

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 05 October 2010 - 04:36 AM

Hi Chris

Ok still learning; I was going to contribute a SNTP program; but found one
that had already been documented for the NETMF on codeplex at:

Codeplex micro framework tool kit

In looking at the project, it lists you I think as a contributor. Also it only seems
to have source to examples referencing the library DLL's.

Any idea where the source to the DLL's is?

I compiled one of the test projects after re-establishing the references to the DLL's
and it tells me the PE files are missing.

How do you get the project to generate the PE files for the DLL's?

On further investigation I found a blog with source to the NTP by the orginal author at:

Wrong Date time solution

How ever I then ran into my next obstacle in modifying the example in that a simple statement
that everyone references will not compile.

In that it doesn't understand the following line as it can't find ExtendedTimeZone:

Microsoft.SPOT.ExtendedTimeZone.SetTimeZone(TimeZoneId.Berlin);

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace SNTP
{
    public class Program
    {
        public static void Main()
        {
            Microsoft.SPOT.ExtendedTimeZone.SetTimeZone(TimeZoneId.Berlin);
            Microsoft.SPOT.Hardware.Utility.SetLocalTime(GetNetworkTime());
        }
        public static DateTime GetNetworkTime()
        {
            return null;
        }
    }
}


#2 freds

freds

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 05 October 2010 - 02:56 PM

Hi Everyone Totally disregard my last post. The NETMF documentation is in error as Microsoft.SPOT.ExtendedTimeZone.SetTimeZone() was dropped after version 3.0 in favor of an intrinsic time service in framework. I.E. SNTP is built into the framework. What does this mean? Basically if you have a network interface the netduino can query a government time server for the current time and if you elect periodically re-sync to correct for drift. If you do not have connectivity to the internet, you can substitute a windows domain controller as your time source. So if you have network connectivity you do not need a real time clock in your solution! I will post an example later. If you want to dive in checkout Microsoft.SPOT.Time.TimeService.UpdateNow(). Cheers!

#3 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 05 October 2010 - 02:57 PM

freds, Quick note: due to the size of it, I don't believe we build the time service feature into the Netduino firmware. You could probably compile it in though... [All that said, if the time service is written in C# code...then you can include it in your project.] Chris

#4 Chris Seto

Chris Seto

    Advanced Member

  • Members
  • PipPipPip
  • 405 posts

Posted 05 October 2010 - 02:59 PM

This is for standard NETMF sockets. IT should be ok with the Plus, but I have not tested it yet. :)


/// <summary>
        /// Get DateTime from NTP Server 
        /// Based on:
        /// http://weblogs.asp.net/mschwarz/archive/2008/03/09/wrong-datetime-on-net-micro-framework-devices.aspx
        /// </summary>
        /// <param name="TimeServer">Timeserver</param>
        /// <returns>Local NTP Time</returns>
        public static DateTime NTPTime(String TimeServer)
        {
            // Find endpoint for timeserver
            IPEndPoint ep = new IPEndPoint(Dns.GetHostEntry(TimeServer).AddressList[0], 123);

            // Connect to timeserver
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            s.Connect(ep);

            // Make send/receive buffer
            byte[] ntpData = new byte[48];
            Array.Clear(ntpData, 0, 48);

            // Set protocol version
            ntpData[0] = 0x1B;

            // Send Request
            s.Send(ntpData);

            // Receive Time
            s.Receive(ntpData);

            byte offsetTransmitTime = 40;

            ulong intpart = 0;
            ulong fractpart = 0;

            for (int i = 0; i <= 3; i++)
                intpart = (intpart << 8) | ntpData[offsetTransmitTime + i];

            for (int i = 4; i <= 7; i++)
                fractpart = (fractpart << 8) | ntpData[offsetTransmitTime + i];

            ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);

            s.Close();

            TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);
            DateTime dateTime = new DateTime(1900, 1, 1);
            dateTime += timeSpan;

            TimeSpan offsetAmount = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
            DateTime networkDateTime = (dateTime + offsetAmount);

            return networkDateTime;
        }


#5 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 315 posts
  • LocationIndiana, USA

Posted 12 December 2010 - 01:05 AM

This is for standard NETMF sockets. IT should be ok with the Plus, but I have not tested it yet. :)


My goal is to have DateTime.Now return the correct local date/time. I also wrote code based on the same blog post and it retrieves the UTC time fine on my NetduinoPlus, but since the SetTimeZone method was dropped and the SPOT.Time Libraries are not included, that leaves no way of setting the timezone in the device, as far as I can tell. So despite having some remnants of TimeZone enumerations and a TimeZoneInformation object, there appears to be no way to do this. I think what I will have to do is create my own TimeZone collection then apply it when I set the local time. But then, although DateTime.Now will return the correct local time, DateTime.UtcNow would return the wrong time because the TimeZone is not set. Ugh. I don't mind leaving out the SPOT.Time, but there needs to be a way to set the TimeZone... So in addition to the Microsoft.SPOT.Hardware.Utility.SetLocalTime method, there should be a Utility.SetTimeZone since these are not available: Microsoft.SPOT.ExtendedTimeZone.SetTimeZone(TimeZoneId.Eastern); Microsoft.SPOT.Time.TimeService.SetTimeZoneOffset(-300);

#### Exception System.NotSupportedException - CLR_E_NOT_SUPPORTED (1) ####

Hopefully, I just missed it.

P.S. Also, I know this is a departure from standard .NET, but I think DateTime.Now should be a nullable type and it should be null at startup until it is populated... It is crazy to initialize System DateTime to 1/1/1900. That will never be the correct date. Ever!

-Valkyrie-MT

#6 spur

spur

    Member

  • Members
  • PipPip
  • 27 posts

Posted 23 December 2010 - 04:45 AM

This is for standard NETMF sockets. IT should be ok with the Plus, but I have not tested it yet. :)


Awesome, this does indeed return the correct time. At least for some other timezone ;)

Thanks :)

#7 INMCM

INMCM

    New Member

  • Members
  • Pip
  • 2 posts

Posted 22 February 2011 - 01:38 AM

I've made a modification to to Chris's code so that you can compensate for timezones. It's just an extra argument that is the time difference between UTC and the timezone you want to set the Netduino to.

public static DateTime NTPTime(String TimeServer, int UTC_offset)
        {
            // Find endpoint for timeserver
            IPEndPoint ep = new IPEndPoint(Dns.GetHostEntry(TimeServer).AddressList[0], 123);

            // Connect to timeserver
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            s.Connect(ep);

            // Make send/receive buffer
            byte[] ntpData = new byte[48];
            Array.Clear(ntpData, 0, 48);

            // Set protocol version
            ntpData[0] = 0x1B;

            // Send Request
            s.Send(ntpData);

            // Receive Time
            s.Receive(ntpData);

            byte offsetTransmitTime = 40;

            ulong intpart = 0;
            ulong fractpart = 0;

            for (int i = 0; i <= 3; i++)
                intpart = (intpart << 8) | ntpData[offsetTransmitTime + i];

            for (int i = 4; i <= 7; i++)
                fractpart = (fractpart << 8) | ntpData[offsetTransmitTime + i];

            ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);

            s.Close();

            TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);
            DateTime dateTime = new DateTime(1900, 1, 1);
            dateTime += timeSpan;
            
            TimeSpan offsetAmount = new TimeSpan(0, UTC_offset, 0, 0, 0);
            DateTime networkDateTime = (dateTime + offsetAmount);

            return networkDateTime;
        }

So if you were in the Eastern time zone of the United States, you just call:
Utility.SetLocalTime(NTPTime("time-a.nist.gov", -5));


#8 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 315 posts
  • LocationIndiana, USA

Posted 28 February 2011 - 05:31 AM

INMCM,

That looks like a good way of doing it. I wanted to post here as well, the solution I am using, which is a combination of what others have done. It's not totally cleaned up, but it's been working great for me for a few months to the point where I have totally forgotten about it. It is implemented as an extension method and the usage looks like this:

DateTime.Now.SetFromNetwork(new TimeSpan(-5, 0, 0));


Note, you should specify the timezone if you want it to use local time. Otherwise, you'll get UTC for everything. In the example above, I am setting my Netduino Date/Time to EST, which is UTC-5 hours.

This Extension.cs file has no namespace specified, so you can drop it into any project and the methods will magically be there! Also, no need to add using statements in each file this way...

This is unrelated, but for the sake of search hits; some other methods in the file are:

String.Replace(char charToFind, char charToSubstitute)
String[].Join(string delimiter)
String.StartsWith(string query)
String.EndsWith(string query)
double[].Sort()
float.ToCelcius();
float.ToFahrenheit();

-Valkyrie-MT

Attached Files



#9 Steve88W

Steve88W

    New Member

  • Members
  • Pip
  • 3 posts

Posted 20 April 2011 - 12:21 AM

Valkyrie-MT's method worked great for me but did not take into account Daylight Savings. -8 (PST) shows up as an hour off for half of the year :( I'm digging through the code now but haven't seen anything yet...

#10 TomYee

TomYee

    New Member

  • Members
  • Pip
  • 9 posts

Posted 23 May 2011 - 06:38 AM

Valkyrie-MT's method worked great for me but did not take into account Daylight Savings.
-8 (PST) shows up as an hour off for half of the year :(


Check out the Daytime Protocol (RFC-867) that operates on port 13 on various servers such as "time-nw.nist.gov".

RFC-867 doesn't specify a format, but the format of the returned time code from NIST servers is this:
JJJJJ YR-MO-DA HH:MM:SS TT L H msADV UTC(NIST) OTM

See the following for an explanation. ST versus DST information is provided in the TT field.
http://www.nist.gov/...8/grp40/its.cfm

See the following for a list of servers. Try and choose one that is close by and "recommended for new users." Heed the warning about not querying the server more often than once every four seconds.
http://tf.nist.gov/tf-cgi/servers.cgi

Tom

#11 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 315 posts
  • LocationIndiana, USA

Posted 25 May 2011 - 03:28 AM

Valkyrie-MT's method worked great for me but did not take into account Daylight Savings.
-8 (PST) shows up as an hour off for half of the year :(

I'm digging through the code now but haven't seen anything yet...


I think every method I have seen will have this problem because the timezone support is not in the netduino. The methods I have been using simply get the date/time from a time server on the web and only applies a time offset, notice though that it is not a time zone. TomYee is right, in that the TT field is the key here. We'd have to create a singleton class that is instantiated when a time request is made and continues running in the background to check once a month if this is the month for the time change. Then use the value from TT to determine what day the time change will happen. Then on that day, poll every every hour for a time change... The continuously running singleton would poll the time servers every month, then every hour on the day of the timezone change. It's totally do-able, but a bit abusive to the NIST servers...

Anyway... those are my thoughts.

-Valkyrie-MT

#12 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 315 posts
  • LocationIndiana, USA

Posted 21 June 2011 - 01:49 AM

Update - First off, we may have better time support in the next version of .NET MF:

COMMITTED: Time Protocol (SNTP) for lwIP, please note we might look into integrating RFC4833 for supporting time zone as well


Also, there is some good time parsing code here that could be used to fill in the Time Zone stuff. I'll probably wait and see what we get with .NET MF 4.2.

-Valkyrie-MT

#13 dougY

dougY

    Member

  • Members
  • PipPip
  • 19 posts

Posted 06 July 2011 - 03:23 AM

so it does appear that Valkyrie-MT is right. there is no way to set the system time. i cant believe that. anyone care to expound on why its not there? is it some byproduct of the way the CLR is implemented and that there is no underlying OS to call (like with a win32 invoke)? also, anyone got time to offer a short (50 words or less) explanation for this newb on why you would build a timer with a 555 chip? .cheers.

#14 dougY

dougY

    Member

  • Members
  • PipPip
  • 19 posts

Posted 06 July 2011 - 08:25 PM

i overlooked it, but in the first post on this thread he calls the method: Microsoft.SPOT.Hardware.Utility.SetLocalTime(); so you can set it. it just doesnt persist between bootups.

#15 Alphons

Alphons

    New Member

  • Members
  • Pip
  • 4 posts
  • LocationHelmond, Netherlands

Posted 12 July 2011 - 11:03 PM

This is my first post here :)
Got the netduino plus device today.
To init the DateTime.Now value of de the device, the assembly build Version can be of some use.

First, edit the AssemblyInfo.cs file (properties):

[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

Second, do some calculation to get a real DateTime and do a 'SetLocalTime'.

private void InitDateTime()
{
  System.Version v = 
      System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
   Microsoft.SPOT.Hardware.Utility.SetLocalTime(
      new DateTime(1 * TimeSpan.TicksPerHour + 
       (v.Build + 145731) * TimeSpan.TicksPerDay + 
        v.Revision * TimeSpan.TicksPerSecond * 2));
}

When de device is reset, the original datetime of the build is used as a starting value.
It is not NTP but maybe this can be usefull for debugging etc.

#16 Christopher Gilmore

Christopher Gilmore

    Member

  • Members
  • PipPip
  • 12 posts
  • LocationBurlington, MA

Posted 20 August 2011 - 04:58 PM

I just upgraded to the 4.2 RC1 firmware for the netduino plus, and now this function doesnt seem to work for me. It gets to the s.Connect(ep); and just hangs there. I thought it might have something to do with the network, but i can ping the device from my computer and get responses from it's webserver. Does anyone have any idea why this would change when moving to the 4.2 firmware?

#17 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 315 posts
  • LocationIndiana, USA

Posted 22 August 2011 - 04:25 AM

I just upgraded to the 4.2 RC1 firmware for the netduino plus, and now this function doesnt seem to work for me. It gets to the

s.Connect(ep);

and just hangs there. I thought it might have something to do with the network, but i can ping the device from my computer and get responses from it's webserver. Does anyone have any idea why this would change when moving to the 4.2 firmware?


Uh oh... I'm seeing the same thing. The Socket.Connect method is broken in 4.2 RC1 (at least for UDP). It does not seem to hang with the Socket.SendTo method, although I haven't looked yet to see if that method works. We need to characterize what works and what doesn't and get it to the .NET MF team soon.

Update: The Socket.SendTo Method does work, so we could work around this, but now I'm concerned about the TCP socket stuff... That needs to be tested now.

Update2: The following workaround, works... comment out the connect line and change s.Send(ntpData) to s.SendTo(ntpData, ep):
//Before
       s.Connect(ep);
       s.Send(ntpData);

//After
       //s.Connect(ep);
       s.SendTo(ntpData, ep);

-Valkyrie-MT

#18 OZ8ET

OZ8ET

    Advanced Member

  • Members
  • PipPipPip
  • 72 posts
  • LocationHundested, Denmark

Posted 25 March 2012 - 10:00 AM

Hi!

This morning we changed to Daylight Saving Time in EU.
Rather than using DateTime.Now to display date and time, I use DST which comes from this function:

		public static DateTime DST  
		{ 
			get 
			{
				DateTime dt = DateTime.Now;
				if (dt.Month < 3 || dt.Month > 10) return DateTime.Now;
				if (dt.Month > 3 && dt.Month < 10) return DateTime.Now.AddHours(1);
				if (dt.Month == 3)
				{	//	in march
					if ((dt.Day - (int)dt.DayOfWeek) < 25) return DateTime.Now;
					if (((int)dt.DayOfWeek == 0) && (dt.Hour < 2)) return DateTime.Now;
					return DateTime.Now.AddHours(1);
				}	//	in october
				if ((dt.Day - (int)dt.DayOfWeek) < 25) return DateTime.Now.AddHours(1);
				if (((int)dt.DayOfWeek == 0) && (dt.Hour < 2)) return DateTime.Now.AddHours(1);
				return DateTime.Now; 
			} 
		}
By the way - I use the SNTP to set the time.

Regards

OZ8ET

#19 Giuliano

Giuliano

    Advanced Member

  • Members
  • PipPipPip
  • 361 posts
  • LocationSimi Valley, CA

Posted 03 July 2012 - 06:16 AM

How to get the UtcOffSet from TimeZoneId? Is there a table somewhere that provides TimeZoneIds and their repectives UtcOffSets?

#20 Dan T

Dan T

    Advanced Member

  • Members
  • PipPipPip
  • 91 posts
  • LocationBoston (Greater)

Posted 13 August 2012 - 03:18 AM


To init the DateTime.Now value of the device, the assembly build Version can be of some use.

First, edit the AssemblyInfo.cs file (properties):

[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

Second, do some calculation to get a real DateTime and do a 'SetLocalTime'.

private void InitDateTime()
{
  System.Version v = 
      System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
   Microsoft.SPOT.Hardware.Utility.SetLocalTime(
      new DateTime(1 * TimeSpan.TicksPerHour + 
       (v.Build + 145731) * TimeSpan.TicksPerDay + 
        v.Revision * TimeSpan.TicksPerSecond * 2));
}

When de device is reset, the original datetime of the build is used as a starting value.
It is not NTP but maybe this can be usefull for debugging etc.


Alphons, Thanks. I'm using this code to initialize my Netduino Go (which has no internet...yet). It's a great trick in that it set's the time almost perfectly during the development phase of edit, build, edit, build.

Can you explain to me why the AssemblyInfo.cs file edit was necessary? What does that change do?




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.