Assim que comecei a fazer medições a primeira coisa que precisa era atribuir data e hora de cada medição ao salvar no cartão microSD. A boa notícia é que o .NETMF tem suporte ao formato "DateTime" que é muito usado no .NET normal para pegar a data e hora do windows e usar na aplicação, o problema é que o serviço de hora no Netduino é iniciado quando a placa liga ou chama o serviço de hora a primeira vez, ou seja, a primeira chamada é sempre zero hora.....
Para fazer um teste inicial você pode executar um código simples:
while (true)
{
Debug.Print("Horário Atual: " + DateTime.Now.ToString());
Thread.Sleep(50000);
}
A saída desse código é só para o Debug e é mais ou menos assim:
Note que o horário é meio louco, agora são 17:25 de 2012. Não sei que hora é essa mas vamos lá se queremos um medidor que envie dados para a internet é conveniente que ele também tenha um ajuste de hora automático. Já pensou, toda vez que a placa desligar ter que ir até ela e corrigir a hora na "mão grande"...
A solução para o Netduino Plus é utilizar um servidor de tempo. O Time Server ou servidor de tempo (NIST) é um servidor que lê uma informação de tempo de um relógio de tempo real e distribui a informação pela internet através de um protocolo próprio chamado de Network Time Protocol (NTP), embora outros protocolos de tempo menos populares (ultrapassados) ainda estejam em uso.
O NTP é um protocolo baseado no UDP que tem uma finalidade muito especial de sincronização do relógio de um conjunto de computadores em redes de dados com latência variável. O NTP permite manter o relógio de um computador com a hora sempre certa e com grande exatidão. Originalmente idealizado por David L. Mills da Universidade do Delaware e ainda hoje mantido por si e por uma equipa de voluntários, o NTP foi utilizado pela primeira vez antes de 1985, sendo ainda hoje muito popular e um dos mais antigos protocolos da internet (veja mais detalhes na wikipédia).
Exitem na internet uma série de servidores de tempo (NIST) na internet para capturar a hora certa e utilizar no sei código como referência, o site que eu peguei os IP's foi este: http://tf.nist.gov/tf-cgi/servers.cgi. Que são exatamente todos servidores no EUA, mas exitem outros pelo mundo a fora.
O código que eu fiz é bem simples. Trata-se de uma classe que quando inicializada atualiza o valor do tempo para a hora atual obtida através de um servidor da lista de servidores NIST da classe. O único parametro que deve ser passo para classe são os minutos de defasagem entre o valor da hora de referência em Greenwich para sua hora local, que no meu caso, Rio de Janeiro é -120 minutos ( -2 horas).
Esta é a classe:
using System.Net.Sockets;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.IO;
using System.Text;
using System;
using System.Net;
using Microsoft.SPOT.Net.NetworkInformation;
namespace RealTimeTest
{
/// <summary>
/// Autor: Victor Manuel
/// Data: 11/02/2012
///
/// Descrição: Classe De serviços de sincronização de relógio
/// para o NetduinoPlus
///
///
/// Exemplo:
///
/// //Seta o IP da porta
/// NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticIP("10.20.19.35", "255.255.255.0", "10.20.19.1");
/// string[] dns = { "10.20.19.1", "200.222.122.133" };
/// NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticDns(dns);
/// System.Threading.Thread.Sleep(10000);
///
/// InternetTimeService nits = new InternetTimeService(-120);
/// </summary>
class InternetTimeService
{
private int TimeServerIndex = 0;
private int OffSetMinutes = 0;
/// <summary>
/// System Synchronize Internal DateTime
/// </summary>
/// <param name="minutes">Time Zone Difference</param>
public InternetTimeService(int minutes)
{
Debug.Print("InternetTimeService routine is running ...");
OffSetMinutes = minutes;
Utility.SetLocalTime(GetNetworkTime());
Debug.GC(true);
}
/// <summary>
/// NIST Internet Time Servers
/// For server list access: http://tf.nist.gov/tf-cgi/servers.cgi
/// </summary>
public string[] InternetTimeServers = {"time.nist.gov", // global address for all servers Multiple locations
"nist1-ny.ustiming.org", //New York City, NY
"nist1.aol-va.symmetricom.com", //Reston, Virginia
"nist1-atl.ustiming.org ", //Atlanta, Georgia
"nist1-la.ustiming.org", //Los Angeles, California
"time-nw.nist.gov", //Microsoft, Redmond, Washington
"utcnist.colorado.edu" //University of Colorado, Boulder
};
/// <summary>
/// Force to system synchronize internal DateTime
/// </summary>
public void ForceToUpdate()
{
Utility.SetLocalTime(GetNetworkTime());
Debug.GC(true);
}
/// <summary>
/// Method to query a NTP server and set the device date to the returned value
/// </summary>
/// <returns>Recived Server Time</returns>
public DateTime GetNetworkTime()
{
while (true)
{
try
{
Debug.Print("Conecting to:" + InternetTimeServers[TimeServerIndex].ToString());
IPEndPoint ep = new IPEndPoint(Dns.GetHostEntry(InternetTimeServers[TimeServerIndex].ToString()).AddressList[0], 123);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.Connect(ep);
byte[] ntpData = new byte[48]; // RFC 2030
ntpData[0] = 0x1B;
for (int i = 1; i < 48; i++)
ntpData[i] = 0;
s.Send(ntpData);
s.ReceiveTimeout = 10000;
s.Receive(ntpData);
byte offsetTransmitTime = 40;
ulong intpart = 0;
ulong fractpart = 0;
for (int i = 0; i <= 3; i++)
intpart = 256 * intpart + ntpData[offsetTransmitTime + i];
for (int i = 4; i <= 7; i++)
fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];
ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);
s.Close();
TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);
DateTime networkDateTime = (new DateTime(1900, 1, 1)) + timeSpan;
Debug.Print("UTC: " + networkDateTime.ToString());
networkDateTime = (new DateTime(1900, 1, 1)) + timeSpan + TimeSpan.FromTicks((long)OffSetMinutes * TimeSpan.TicksPerMinute);
Debug.Print("LOCAL: " + networkDateTime.ToString());
return networkDateTime;
}
catch
{
Debug.Print("Impossible to conect on " + InternetTimeServers[TimeServerIndex].ToString());
Debug.Print("try next time server..");
TimeServerIndex++;
if (TimeServerIndex == InternetTimeServers.Length)
{
Debug.Print("Impossible to access Internet Time Servers... ");
return DateTime.Now;
}
}
}
}
}
}
Este é o exemplo de utilização:
NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticIP("10.20.19.35", "255.255.255.0", "10.20.19.1");
string[] dns = { "10.20.19.1", "200.222.122.133" };
NetworkInterface.GetAllNetworkInterfaces()[0].EnableStaticDns(dns);
System.Threading.Thread.Sleep(10000);
InternetTimeService nits = new InternetTimeService(-120);
while (true)
{
Debug.Print("Horário Atual: " + DateTime.Now.ToString());
Thread.Sleep(50000);
}
Quando você mandar rodar aparecerá a seguinte mensagem na janela de depuração:
Espero que tenha ajudado mais com esse artigo sobre servidores NIST no Netduino.




