Shelly schedules firing at the wrong time: time zone, SNTP and the clock change

Nearly every case of “the schedule fires when it shouldn’t” has the same cause: the device’s clock. And they cluster on two dates, the last Sunday of March and the last Sunday of October. This year Spain goes back to winter time on Sunday 25 October: at 03:00 the clocks return to 02:00, and Spain moves from UTC+2 to UTC+1.

How a Shelly gets the time

Shellys have no battery-backed clock — except the Pro range, covered below. At boot they ask an SNTP server for UTC time, time.google.com by default, and convert it to local time with the configured time zone. From those two, plus the coordinates, come:

  • schedules (on at 20:00, off at 23:30);
  • sunrise and sunset, which also need latitude and longitude;
  • scenes with a time condition;
  • how meters split their history into hours and days.

Schedules are stored and run on the device itself, not in the cloud. That is why they keep working without internet once the device has the time, and why everything depends on that time being right.

Checking it through the API

On a Gen2 or later device, the time settings are in Sys.GetConfig, under location (tz, lat, lon) and sntp (server):

http://<ip>/rpc/Sys.GetConfig

What to look for is a named zone in tz, Europe/Madrid or Atlantic/Canary, not an offset. To set it:

http://<ip>/rpc/Sys.SetConfig?config={"location":{"tz":"Europe/Madrid"}}

And to know whether the device has the time right now, Sys.GetStatus: the time and unixtime fields are null until it has synchronised. If they are null after a power cut, no schedule will fire until they change.

http://<ip>/rpc/Sys.GetStatus

Symptom and cause

SymptomCauseWhere to look
Fires an hour early or lateWrong time zonelocation.tz
Sunrise or sunset shiftedWrong zone or coordinateslocation.lat / lon
Nothing fires after a power cutBooted offline, has no timetime = null
Goes wrong in March and OctoberFixed offset instead of a zonelocation.tz

Named zone or fixed offset

With Europe/Madrid, the device knows the daylight-saving rules and applies the change itself; nothing to touch. With a fixed offset — UTC+2 set by hand — the device does not know that Spain moves to UTC+1 on 25 October, and everything runs an hour late until someone corrects it. The same, the other way round, in March.

There is also an ambiguous window that no setting removes: on the October change day, the hour from 02:00 to 03:00 happens twice; on the March one, it does not happen at all. Schedule nothing critical in that window, or accept that on that day it may run twice or not at all.

After a power cut

A device that boots without a connection has no time, and without time it runs no schedules. As soon as it gets the network back and synchronises, it returns to normal; but if the Wi-Fi takes longer to come up than the Shelly — usual when power returns to everything at once —, there is a spell when schedules are paused.

SNTP uses UDP port 123. On networks with filtered outbound traffic, a rule that blocks it leaves the device without time even though everything else works. If the installation has no internet, point sntp.server at a local time server; if it does, leave the default.

Devices in the Pro range have a real-time clock (RTC) and keep the time even if the internet or the SNTP server goes down. For a schedule that must not fail — a security shutter, an irrigation run —, that margin is the case for a Pro.

And on meters

On an EM, a Plug S or any device with metering, the time decides which slot of the history each reading falls into. Accumulated kWh are not lost: the counter adds up just the same. What shifts is when each consumption appears:

  • Wrong zone: the 21:00 peak shows at 20:00 or 22:00; the curve is right but shifted.
  • Midnight cut-off shifted: the app’s daily total does not match the utility meter’s.
  • Change day: in October one hour appears twice, in March one is missing.
  • Power cut without network: a gap in the history until the device gets the time back.

Checklist

  1. location.tz set to Europe/Madrid (or auto-detect), never an offset.
  2. location.lat and lon set to your real coordinates, if you use sunrise or sunset.
  3. Outbound UDP 123 allowed, or a local sntp.server if the network is isolated.
  4. Enough Wi-Fi coverage for it to synchronise straight after boot.
  5. Nothing critical scheduled between 02:00 and 03:00.
  6. After the change on the 25th, open two or three key schedules and confirm the time.

If sunrise or sunset does not match your town’s, auto-detection set generic coordinates. Set them by hand and the calculation sharpens to the minute.