ntp-rtc-hora-internet-nanoframework

Sincronización NTP y RTC en nanoFramework

  • 5 min

La sincronización horaria es el proceso de ajustar el reloj del dispositivo con una fuente fiable como NTP o un RTC.

Ya tenemos el dispositivo conectado al Wi-Fi, pero aún debemos resolver un problema invisible: el microcontrolador no sabe en qué día vive.

A diferencia de tu ordenador, que tiene una pequeña pila de botón (la pila del BIOS) para mantener la hora cuando se apaga, la mayoría de placas de desarrollo (como el ESP32 DevKit) pierden la memoria del reloj al desconectarse. Al arrancar, suelen volver a una fecha predeterminada (como el 1 de Enero de 2017).

En esta entrada aprenderemos a usar el protocolo NTP para poner nuestro reloj en hora. Y no es solo por capricho: sin la hora correcta, el Internet seguro (HTTPS) no funciona.

¿Qué es NTP?

El NTP (Network Time Protocol) es uno de los protocolos más antiguos de Internet. Básicamente, permite a nuestro dispositivo preguntar a un servidor maestro (como pool.ntp.org o time.google.com) qué hora es.

El servidor responde con la hora UTC exacta, y nuestro sistema ajusta su reloj interno.

Sincronización automática en nanoFramework

La buena noticia es que nanoFramework hace el trabajo sucio por nosotros. La pila de red del ESP32 (basada en lwIP) tiene un cliente NTP integrado.

Si has usado WifiNetworkHelper como vimos en la lección anterior, es posible que ya lo estés usando sin saberlo.

// El parámetro 'requiresDateTime: true' fuerza a esperar al NTP
WifiNetworkHelper.ConnectDhcp(
    ssid,
    pass,
    requiresDateTime: true,
    token: new CancellationTokenSource(60000).Token);
Copied!

Cuando pasamos true a este parámetro, el código se bloquea y no continúa hasta que:

  1. Se obtiene dirección IP.
  2. Se contacta con el servidor NTP por defecto.
  3. El reloj del sistema se actualiza.

Verificar el estado del reloj

Podemos comprobar si la hora es válida simplemente mirando la propiedad DateTime.UtcNow.

using System;
using System.Diagnostics;
using System.Threading;

// ...

if (DateTime.UtcNow.Year < 2025)
{
    Debug.WriteLine("¡Cuidado! El reloj no está sincronizado.");
    Debug.WriteLine($"Fecha actual del sistema: {DateTime.UtcNow}");
}
else
{
    Debug.WriteLine("Reloj Sincronizado correctamente.");
    Debug.WriteLine($"Hora UTC: {DateTime.UtcNow}");
}
Copied!

Recuerda: NTP siempre devuelve la hora UTC (Tiempo Universal Coordinado). No sabe nada de horarios de verano ni de tu zona horaria local.

Esperar la sincronización

Si por alguna razón necesitas forzar una actualización (o cambiar el servidor NTP), puedes hacerlo mediante configuración. Sin embargo, en la mayoría de versiones modernas de nanoFramework para ESP32, esto se gestiona a nivel de sistema operativo nativo.

Una práctica común si no usas el Helper es implementar un bucle de espera:

Debug.WriteLine("Esperando sincronización de hora...");

while (DateTime.UtcNow.Year < 2025)
{
    Thread.Sleep(1000);
    // El sistema subyacente sigue intentando conectar al NTP en segundo plano
}

Debug.WriteLine("¡Hora obtenida!");
Copied!

RTC interno y RTC externo

Una vez que el NTP nos da la hora, esta se guarda en el RTC (Real Time Clock) interno del microcontrolador. Este reloj sigue contando los segundos mientras el chip tenga energía.

¿Qué pasa si reinicio?

  • Soft Reset (Botón EN): Normalmente el RTC interno mantiene la hora (en ciertos modos de energía).
  • Hard Reset (Quitar cable): El RTC pierde la energía y la hora se borra. Tendrás que volver a conectar al Wi-Fi y pedir la hora NTP de nuevo al arrancar.

Módulos RTC externos

Si tu proyecto necesita saber la hora inmediatamente al encenderse, sin esperar al Wi-Fi (o donde no hay internet), necesitarás hardware extra: un módulo RTC con pila (como el DS3231 o DS1307) conectado por I2C.

En ese caso, al arrancar leerías la hora del DS3231 y la inyectarías al sistema:

// (Pseudocódigo con driver IOT.Device.Rtc)
var rtc = new Ds3231(i2cDevice);
Rtc.SetSystemTime(rtc.DateTime); // Actualizar reloj del sistema desde la pila
Copied!

Zonas horarias

Como hemos dicho, DateTime.UtcNow nos da la hora UTC, que no es lo mismo que la hora de Londres durante todo el año. Si estás en España y quieres mostrar la hora local en una pantalla, necesitas sumar el desfase (+1 en invierno, +2 en verano).

En .NET “full” tenemos TimeZoneInfo, que es una base de datos gigante con todas las reglas de cambio de hora del mundo. En nanoFramework, para ahorrar memoria, no tenemos TimeZoneInfo completo por defecto.

Tendrás que gestionarlo manualmente:

// Ejemplo manual para España (Simplificado)
DateTime utc = DateTime.UtcNow;
int offset = 1; // Invierno

// Lógica muy básica (no cubre el cambio exacto de hora en Marzo/Octubre)
// Para algo robusto, hay librerías Nuget de la comunidad
DateTime localTime = utc.AddHours(offset);

Debug.WriteLine($"Hora Local: {localTime}");
Copied!