the Ruuvi docs specify how one can read historic recordings from a Ruuvi tag: Documentation: Log Read
However, since I pull out a small plastic strip from underneath the battery to activate the tag, I am wondering, how can the tag now the UTC time? Wouldn’t it only know the relative time since start?
You are absolutely correct, RuuviTag does not know the correct UTC time at boot and history log timestamps are relative to start.
Under the hood the history logging is implemented so that the client (phone) sends the current UTC time to the Tag. The Tag then calculates real-time timestamps based on what the difference between tag’s relative time and real time is.
This is also why log entries get deleted when tag reboots. Tag cannot know how long it was offline, so all relative timestamps before boot are unreliable.
Thats wonderful. Thank you for your explanation!
Could you say a few more words about the “under the hood” part?
I am currently working on a Flutter app to read historic data. As of now I only send a single command to request the data. Surprisingly, the timestamps are correct =) When you say “under the hood”, is this part of some BLE specification?
// Construct the header
List<int> header = [0x30, 0x30, 0x11];
// Construct the payload (timestamps as 4-byte integers)
ByteData payload = ByteData(8);
payload.setUint32(0, now, Endian.big); // Current time
payload.setUint32(4, oneHourAgo, Endian.big); // One hour ago
// Combine header and payload
List<int> command = [...header, ...payload.buffer.asUint8List()];
// Write to RX characteristic
await rxCharacteristic.write(command);
The implementation is our own, not part of BLE standards. If you want to look into more details, the real time is calculated as real_time_ms = sample->timestamp_ms + time_offset_ms; where sample timestamp is the time relative to boot and time offset is difference of system clock and real clock.
For example tag was booted up at December 10th 2024 at real timestamp 1733833961, log entry was stored on January 8th at real timestamp 1736339561 and logs are queries now on January 10th at real timestamp 1736512361.
Tag considers boot-up at 0, log entry at 2505600 and current time as 2678400.
Checking at the Epoch Converter timestamp 1736339561000 matches GMT: Wednesday, 8th January 2025, 12.32
The accuracy is not perfect, any inaccuracy in phone clock and BLE data latency adds error to the measurement. In practise those errors are a few seconds at most.
Hi Otso,
I think it makes sense to me. If I am correct, the current_time_s is the current timestamp in seconds that has to be provided by the phone.
If the tag hasn’t been connected to the Ruuvi Mobile app, how can I send current_time_s from my own Flutter app? Via the rx characteristic? What would the header be?
Yes, you need to send “Read all data” command via RX characteristic. The command is 11 bytes, with 3 byte header, 4 bytes for current timestamp and 4 bytes for start of logs.
e.g. 0x3A 3A 11 67 81 30 FD 00 00 00 00 is interpreted as
0x3A 3A 11 “Send all data”
0x67 81 30 FD Time is now 1736519933 (GMT: Friday, 10th January 2025, 14.38)
0x00 00 00 00 Start from 000000000 (GMT: Thursday, 1st January 1970, 00.00)
The tag will send everything it has logged.
If you want to check again for logs tomorrow, it makes sense to use something like 0x3A 3A 11 67 82 82 7D 67 81 30 FD
0x3A 3A 11 “Send all data”
0x67 82 82 7D Time is now 1736606333 (GMT: Saturday, 11th January 2025, 14.38)
0x67 81 30 FD Start from 1736519933 (GMT: Friday, 10th January 2025, 14.38)
This way you will not fetch again old entries and you can save a bit of time and tag battery.
If we reboot the device itself, will the time get reset, or does this only happen when the battery is replaced?
I could understand there will be a few seconds of error compared to the real-world clock. Is the device keeping time with the help of an internal RTC (Real-Time Clock)?