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.
Nenhum comentário:
Postar um comentário