An ultra-lightweight, zero-allocation UUID generator optimized for embedded systems (AVR, ESP8266, ESP32, RP2040) and C++11 environments.
This library implements two specific versions of the UUID standard to cover all embedded use cases:
- UUID Version 7 (RFC 9562) – Time-ordered, k-sortable. (Default)
- UUID Version 4 (RFC 4122) – Fully random, no clock required.
Embedded devices often lack a Real-Time Clock (RTC). Using the wrong version can lead to collisions or incorrect sorting.
| Feature | UUID v7 | UUID v4 |
|---|---|---|
| Primary Component | Timestamp (48-bit) | Randomness (122-bit) |
| Sortable by Time | ✅ Yes | ❌ No |
| Database Indexing | 🚀 Excellent (Clustered Index) | |
| Requires RTC/NTP | 🔴 YES (Critical) | 🟢 NO |
| Offline Devices | ❌ Avoid (Resets to 1970) | ✅ Recommended |
- Use UUIDv7 if: You have a reliable Time Source (RTC module, NTP sync, GPS) and need to sort data by creation time.
- Use UUIDv4 if: Your device works offline, has no battery backup for time, or frequently reboots without time sync.
lib_deps =
bkwoka/UUIDv7- Open Library Manager.
- Search for UUIDv7.
- Click Install.
Best for IoT nodes with NTP/RTC.
#include <UUID7.h>
UUID7 uuid;
// 1. Define a time provider (e.g., NTP or RTC)
uint64_t my_time_provider(void* ctx) {
// Return Unix Epoch in Milliseconds
// Example: return rtc.getUnixTime() * 1000 + rtc.getMillis();
return 1698408000000ULL + millis(); // Mock for example
}
void setup() {
Serial.begin(115200);
// 2. Inject the provider (CRITICAL for v7)
uuid.setTimeProvider(my_time_provider);
if (uuid.generate()) {
Serial.println(uuid);
// Output: 018b7... (Time-ordered)
}
}
void loop() {}Best for simple devices without a clock.
#include <UUID7.h>
UUID7 uuid;
void setup() {
Serial.begin(115200);
// 1. Switch to Version 4 (Random Mode)
uuid.setVersion(UUID_VERSION_4);
if (uuid.generate()) {
Serial.println(uuid);
// Output: 9b2075a5-483d-4920-a2bc-39d2d6452301
}
}
void loop() {}- RFC Compliant: Strict adherence to RFC 9562 (v7) and RFC 4122 (v4).
- Zero Allocation: No
malloc,new, orstd::string. Safe for minimal stack. - Fail-Fast: Reports errors immediately (e.g., if RNG fails).
- Monotonicity (v7): Handles sub-millisecond generation by incrementing the sequence counter.
- Persistence Hooks: Save/Restore timestamp state to EEPROM to prevent regression.
- Tiny Footprint: Optimized for 8-bit microcontrollers.
The library automatically selects the best available entropy source:
- ESP32 / ESP8266: Uses hardware TRNG (
esp_random,os_get_random). - RP2040: Uses hardware ROSC (Ring Oscillator).
- AVR (Uno/Nano): Uses ADC noise. Warning: Not cryptographically secure by default.
For AVR Production: Connect a noise source to a floating pin or inject a custom RNG:
// Use a specific analog pin for entropy
#define UUID7_ENTROPY_ANALOG_PIN A3
#include <UUID7.h>Or inject a custom CSPRNG function:
void my_secure_rng(uint8_t* dest, size_t len, void* ctx) {
// Read from ATECC608 secure element
}
uuid.setRandomProvider(my_secure_rng);If the clock moves backwards (e.g., NTP adjustment), UUIDv7 protects monotonicity. If the regression is huge (device reset to 1970), it handles it safely. Custom threshold:
#define UUID7_REGRESSION_THRESHOLD_MS 10000 // 10 seconds
#include <UUID7.h>To prevent generating duplicate UUIDs after a reboot (if the clock isn't perfectly synced), save the state to non-volatile memory:
uuid.setStorage(load_fn, save_fn, nullptr);
uuid.load(); // Applies "Safety Jump" on boot- RAM: ~20 bytes
- Behavior: Zero-allocation, returns
boolon success/fail. - Use case: High-performance logging, tiny AVR devices.
- RAM: ~60 bytes (Internal buffer)
- Behavior: Returns
String, auto-retries on collision. - Use case: Prototyping, ESP32 web servers.
#include "EasyUUID7.h"
EasyUUID7 uuid;
String id = uuid.toString();| Platform | Flash Cost | RAM Cost | Time per UUID |
|---|---|---|---|
| AVR (Uno) | ~1.5 KB | ~80 B | ~60 µs |
| ESP32 | ~1.0 KB | ~60 B | ~5 µs |
| RP2040 | ~1.2 KB | ~60 B | ~8 µs |
Works in standard C++11 environments (Linux, macOS, Windows) for testing or CLI tools.
#include <iostream>
#include <UUID7.h>
UUID7 uuid;
int main() {
if (uuid.generate()) {
std::cout << uuid << std::endl;
}
}bool generate(): Generates a new UUID.void setVersion(UUIDVersion v): SetUUID_VERSION_7orUUID_VERSION_4.void setTimeProvider(now_ms_fn now, void* ctx): Required for v7.void setRandomProvider(fill_random_fn rng, void* ctx): Inject custom RNG.bool toString(char* out, ...): Convert to string.static bool parseFromString(...): Parse string to binary.const uint8_t* data(): Access raw bytes.
MIT License. See LICENSE file.