S21L Timezone Compensation
Overviewβ
The S21L GPS tracker devices ship with a default timezone of Beijing (UTC+8). Unfortunately, the SMS command to change the timezone (zone,password,eXX) often does not work reliably on these devices.
The Problemβ
When the device sends position data:
- The device encodes the timestamp in BCD format using its local time (Beijing)
- The decoder reads these bytes and interprets them as UTC
- This results in timestamps that are 8 hours in the future
- The positions pipeline rejects these positions because they exceed the
filter_future_threshold_minutessetting (default: 2 hours)
Exampleβ
| Field | Value |
|---|---|
| Server UTC | 2026-01-01T21:39:36Z |
| Device sends (Beijing time) | 2026-01-02T05:39:34 |
| Decoder interprets as UTC | 2026-01-02T05:39:34Z β |
| Correct UTC | 2026-01-01T21:39:34Z β |
The Solutionβ
The S21lFrameDecoder.java includes automatic timezone compensation:
private static final int BEIJING_OFFSET_HOURS = 8;
// In readBcdDate method:
ZonedDateTime rawDate = ZonedDateTime.of(..., ZoneOffset.UTC);
ZonedDateTime adjustedDate = rawDate.minusHours(BEIJING_OFFSET_HOURS);
This subtracts 8 hours from all incoming S21L timestamps to convert from Beijing time to actual UTC.
Configurationβ
The offset is defined as a constant in S21lFrameDecoder.java:
private static final int BEIJING_OFFSET_HOURS = 8;
If devices are properly configured in UTC (via successful SMS command), set this to 0.
SMS Commands (Reference)β
While these commands may not work reliably, they are documented here for reference:
| Command | Description |
|---|---|
zone,123456,E00 | Set timezone to UTC (East 0) |
zone,123456,E08 | Set timezone to Beijing (East +8) |
zone,123456,W05 | Set timezone to EST (West 5) |
CQ | Restart device (may be needed after timezone change) |
Monitoringβ
The decoder logs timezone adjustments with type=TIME_DEBUG:
{
"type": "TIME_DEBUG",
"protocol": "S21L",
"deviceId": "019176527895",
"rawHour": 5,
"rawIso": "2026-01-02T05:39:34Z",
"adjustedIso": "2026-01-01T21:39:34Z",
"offsetApplied": "-8h"
}
Use the Grafana dashboard "S21L Time Debugger" to monitor these logs.
Related Filesβ
S21lFrameDecoder.java- Decoder with timezone compensationfilters.py- Position filters including future timestamp rejectionconfig.py- Filter threshold settings