mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-19 16:46:11 -04:00
0.1.1 UUID
This commit is contained in:
parent
a8bd32dc42
commit
ef466db4c3
@ -13,73 +13,118 @@ Arduino library for generating UUID strings.
|
||||
|
||||
## Description
|
||||
|
||||
This experimental library provides a UUID generator.
|
||||
This **experimental** library provides a UUID generator.
|
||||
A UUID is an Universally Unique IDentifier of 128 bits.
|
||||
These are typically written in the following format, defined in RFC 4122.
|
||||
|
||||
The basis for the UUID is a Marsaglia pseudo random number generator.
|
||||
This must be seeded with two random numbers to get real usable UUID's.
|
||||
```
|
||||
0ac82d02-002b-4ccb-b96c-1c7839cbc4c0
|
||||
^ ^
|
||||
```
|
||||
|
||||
In such this is for experimental use only.
|
||||
The length is 32 hexadecimal digits + four hyphens = 36 characters.
|
||||
Note that the hexadecimal digits are lower case.
|
||||
|
||||
The 0.1.1 version of the lib tries to follow the RFC4122,
|
||||
for version 4 (random generated) and variant 1.
|
||||
In the format above the version 4 is indicated by the first arrow and must be 4.
|
||||
The variant 1 is at the position of the second arrow.
|
||||
This nibble must be 8,9, a or b.
|
||||
All the remaining bits are random.
|
||||
|
||||
The basis for the UUID class is a Marsaglia pseudo random number generator.
|
||||
This PRNG must be seeded with two real random uint32_t to get real random UUID's.
|
||||
|
||||
Often one sees also the term GUID = Globally Unique Identifier.
|
||||
|
||||
Tested on Arduino UNO only.
|
||||
|
||||
A UUID generated looks like 20d24650-d900-e34f-de49-8964ab3eb46d
|
||||
|
||||
- https://en.wikipedia.org/wiki/Universally_unique_identifier
|
||||
- https://www.ietf.org/rfc/rfc4122.txt
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
|
||||
## UUID class
|
||||
### UUID class
|
||||
|
||||
Use **\#include "UUID.h"**
|
||||
|
||||
- **UUID()** Constructor, initializes internals.
|
||||
The UUID class has only a few methods.
|
||||
|
||||
- **UUID()** Constructor, initializes internals an generates a default UUID.
|
||||
- **void seed(uint32_t s1, uint32_t s2 = 0)** reseeds the internal
|
||||
pseudo random number generator.
|
||||
Mandatory to set s1 while s2 is optional.
|
||||
- **void generate()** generates a new UUID.
|
||||
It is mandatory to set s1 while s2 is optional.
|
||||
The combination {0, 0} is not allowed and overruled in software.
|
||||
- **void generate()** generates a new UUID depending on the mode.
|
||||
- **UUID_MODE_RANDOM**: all UUID bits are random.
|
||||
- **UUID_MODE_VARIANT4**: the UUID (tries to) conform to version 4 variant 1. See above.
|
||||
- **char \* toCharArray()** returns a pointer to a char buffer
|
||||
representing the last generated UUID.
|
||||
representing the last generated UUID.
|
||||
Multiple subsequent calls to **toCharArray()** gives the same UUID
|
||||
until **generate()** is called again.
|
||||
|
||||
|
||||
### Mode
|
||||
|
||||
Only two modi are supported. Default is the **UUID_MODE_VARIANT4**.
|
||||
|
||||
- **void setVariant4Mode()** set mode to **UUID_MODE_VARIANT4**.
|
||||
- **void setRandomMode()** set mode to **UUID_MODE_RANDOM**.
|
||||
- **uint8_t getMode()** returns mode set.
|
||||
|
||||
|
||||
### Printable
|
||||
|
||||
The UUID class implements the printable interface.
|
||||
This allows one to print the UUID object directly.
|
||||
To do so it uses the **toCharArray()** internally.
|
||||
This allows one to print the UUID object directly over Serial and any other
|
||||
stream implementing the Print interface. Think Ethernet or SD card.
|
||||
|
||||
```cpp
|
||||
UUID uuid;
|
||||
|
||||
Serial.println(uuid);
|
||||
|
||||
// gives same output as
|
||||
|
||||
Serial.println(uuid.toCharArray());
|
||||
```
|
||||
|
||||
Note: there is a known compile warning on AVR on this.
|
||||
|
||||
|
||||
#### Performance
|
||||
## Performance
|
||||
|
||||
Not tested ESP32 (and many other platforms) yet.
|
||||
First numbers measured with **UUID_test.ino** shows the following timing.
|
||||
|
||||
Performance measured with **UUID_test.ino** shows the following times,
|
||||
Note that 0.1.1 has substantial better performance on AVR.
|
||||
|
||||
|
||||
| Version | Function | UNO 16 MHz | ESP32 240 MHz |
|
||||
|:-------:|:-------------|:------------:|:---------------:|
|
||||
| 0.1.0 | seed | 4 us | |
|
||||
| 0.1.0 | generate | 412 us | |
|
||||
| 0.1.0 | toCharArray | 4 us | |
|
||||
| 0.1.1 | seed | 4 us | |
|
||||
| 0.1.1 | generate | 248 us | |
|
||||
| 0.1.1 | toCharArray | 4 us | |
|
||||
|
||||
|
||||
The performance of **generate()** must be improved if possible.
|
||||
UUID's per second
|
||||
|
||||
Note an UNO can generate 2000++ UUID's per second.
|
||||
| Version | UNO 16 MHz | ESP32 240 MHz | notes |
|
||||
|:-------:|:------------:|:---------------:|:------:|
|
||||
| 0.1.0 | 2000++ | |
|
||||
| 0.1.1 | 4000++ | | generate both modes
|
||||
|
||||
Note that this maximum is not realistic e.g. for a server where also
|
||||
other tasks need to be done (listening, transfer etc).
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples.
|
||||
|
||||
Note: compile warning ...
|
||||
|
||||
|
||||
## Future
|
||||
|
||||
@ -87,30 +132,39 @@ Note: compile warning ...
|
||||
|
||||
- improve documentation
|
||||
- external random input needed
|
||||
- GUID, UUID, versions (links)
|
||||
- background
|
||||
- rfc4122 layout
|
||||
- background
|
||||
- test other platforms
|
||||
- investigate entropy harvesting
|
||||
- freeRAM, micros, timers, RAM, USB-ID, ...
|
||||
- GUID as derived class?
|
||||
- (further identical?)
|
||||
|
||||
### Functions
|
||||
|
||||
- add **setSeparator(char)** and **getSeparator()** ?
|
||||
- one char
|
||||
- add **setUpperCase()** and **setLowerCase()**, **isUpperCase()**
|
||||
- one bool flag
|
||||
- binary output in a byte array
|
||||
- **getBinary(uint8_t \* array)**
|
||||
- need to store them from generate.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
- ESP32 UUID server
|
||||
- using timing of the calls as entropy !
|
||||
- RTC for entropy
|
||||
- EEPROM to store last seeds?
|
||||
|
||||
### Fixes / optimizations
|
||||
|
||||
- improve performance of **generate()**
|
||||
- reduce footprint
|
||||
- can the buffer be reduced?
|
||||
- smaller random generator?
|
||||
|
||||
### Won't
|
||||
|
||||
- support for { and }
|
||||
- add **setSeparator(char)** and **getSeparator()** ?
|
||||
- minus is the specification.
|
||||
|
||||
|
||||
|
@ -5,10 +5,16 @@
|
||||
// DATE: 2022-06-14
|
||||
// PURPOSE: Arduino Library for generating UUID's
|
||||
// URL: https://github.com/RobTillaart/UUID
|
||||
// https://en.wikipedia.org/wiki/UUID
|
||||
// https://en.wikipedia.org/wiki/Universally_unique_identifier
|
||||
//
|
||||
// HISTORY
|
||||
// 0.1.0 2022-06-14 initial version
|
||||
// 0.1.1 2022-06-15 improve performance generate()
|
||||
// minor edits in readme.md
|
||||
// fix bug in generator
|
||||
// define UUID_MODE_VARIANT4
|
||||
// define UUID_MODE_RANDOM
|
||||
|
||||
|
||||
|
||||
#include "UUID.h"
|
||||
@ -17,6 +23,7 @@
|
||||
UUID::UUID()
|
||||
{
|
||||
seed(1, 2);
|
||||
setVariant4Mode();
|
||||
generate();
|
||||
}
|
||||
|
||||
@ -38,20 +45,32 @@ void UUID::generate()
|
||||
{
|
||||
_ar[i] = _random();
|
||||
}
|
||||
|
||||
// TODO improve efficiency
|
||||
for (int i = 0, j = 0; i < 32; i++, j++)
|
||||
|
||||
// patch bits for version 1 and variant 4 here
|
||||
if (_mode == UUID_MODE_VARIANT4)
|
||||
{
|
||||
if (i == 8) _buffer[j++] = '-';
|
||||
if (i == 12) _buffer[j++] = '-';
|
||||
if (i == 16) _buffer[j++] = '-';
|
||||
if (i == 20) _buffer[j++] = '-';
|
||||
_ar[1] &= 0xFFF0FFFF; // remove 4 bits.
|
||||
_ar[1] |= 0x00040000; // variant 4
|
||||
_ar[2] &= 0xFFFFFFF3; // remove 2 bits
|
||||
_ar[2] |= 0x00000008; // version 1
|
||||
}
|
||||
|
||||
// store globally ?
|
||||
|
||||
|
||||
// build up the char array.
|
||||
for (uint8_t i = 0, j = 0; i < 32; i++, j++)
|
||||
{
|
||||
if (i == 8) _buffer[j++] = '-';
|
||||
else if (i == 12) _buffer[j++] = '-';
|
||||
else if (i == 16) _buffer[j++] = '-';
|
||||
else if (i == 20) _buffer[j++] = '-';
|
||||
|
||||
uint8_t nr = i / 8;
|
||||
uint8_t shft = ((i % 8) * 4);
|
||||
uint8_t ch = (_ar[nr] >> shft ) & 0xF;
|
||||
uint8_t ch = _ar[nr] & 0xF;
|
||||
_ar[nr] >>= 4;
|
||||
|
||||
_buffer[j] = (ch < 10) ? '0' + ch : 'a' - 10 + ch;
|
||||
_buffer[j] = (ch < 10) ? '0' + ch : ('a' - 10) + ch;
|
||||
}
|
||||
_buffer[36] = 0;
|
||||
}
|
||||
|
@ -2,20 +2,24 @@
|
||||
//
|
||||
// FILE: UUID.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// VERSION: 0.1.1
|
||||
// DATE: 2022-06-14
|
||||
// PURPOSE: Arduino Library for generating UUID's
|
||||
// URL: https://github.com/RobTillaart/UUID
|
||||
// https://en.wikipedia.org/wiki/UUID
|
||||
// https://en.wikipedia.org/wiki/Universally_unique_identifier
|
||||
//
|
||||
// e.g. 20D24650-D900-E34F-DE49-8964AB3EB46D
|
||||
// e.g. 20d24650-d900-e34f-de49-8964ab3eb46d
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Printable.h"
|
||||
|
||||
|
||||
#define UUID_LIB_VERSION (F("0.1.0"))
|
||||
#define UUID_LIB_VERSION (F("0.1.1"))
|
||||
|
||||
// TODO an enum?
|
||||
#define UUID_MODE_VARIANT4 0
|
||||
#define UUID_MODE_RANDOM 1
|
||||
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
@ -34,6 +38,10 @@ public:
|
||||
// make a UUID string
|
||||
char * toCharArray();
|
||||
|
||||
void setVariant4Mode() { _mode = UUID_MODE_VARIANT4; };
|
||||
void setRandomMode() { _mode = UUID_MODE_RANDOM; };
|
||||
uint8_t getMode() { return _mode; };
|
||||
|
||||
// Printable interface
|
||||
size_t printTo(Print& p) const;
|
||||
|
||||
@ -46,6 +54,7 @@ private:
|
||||
|
||||
// UUID in string format
|
||||
char _buffer[37];
|
||||
uint8_t _mode = UUID_MODE_VARIANT4;
|
||||
};
|
||||
|
||||
|
||||
|
@ -19,13 +19,26 @@ void setup()
|
||||
Serial.println(UUID_LIB_VERSION);
|
||||
|
||||
uint16_t count = 0;
|
||||
uuid.setVariant4Mode();
|
||||
uint32_t start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
uuid.generate();
|
||||
count++;
|
||||
}
|
||||
Serial.print("Generated ");
|
||||
Serial.print("Generate 4: ");
|
||||
Serial.print(count);
|
||||
Serial.println(" uuid's per second.");
|
||||
|
||||
count = 0;
|
||||
uuid.setRandomMode();
|
||||
start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
uuid.generate();
|
||||
count++;
|
||||
}
|
||||
Serial.print("Generate R: ");
|
||||
Serial.print(count);
|
||||
Serial.println(" uuid's per second.");
|
||||
}
|
||||
|
@ -9,8 +9,15 @@ seed KEYWORD2
|
||||
generate KEYWORD2
|
||||
toCharArray KEYWORD2
|
||||
|
||||
setVariant4Mode KEYWORD2
|
||||
setRandomMode KEYWORD2
|
||||
getMode KEYWORD2
|
||||
|
||||
|
||||
|
||||
# Constants (LITERAL1)
|
||||
UUID_LIB_VERSION LITERAL1
|
||||
UUID_MODE_RANDOM LITERAL1
|
||||
UUID_MODE_VARIANT4 LITERAL1
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/UUID.git"
|
||||
},
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=UUID
|
||||
version=0.1.0
|
||||
version=0.1.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for generating UUID's. (experimental).
|
||||
|
@ -38,6 +38,13 @@ unittest_teardown()
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constants)
|
||||
{
|
||||
assertEqual(0, UUID_MODE_VARIANT4);
|
||||
assertEqual(1, UUID_MODE_RANDOM);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_generate)
|
||||
{
|
||||
UUID uuid;
|
||||
@ -77,11 +84,33 @@ unittest(test_layout)
|
||||
|
||||
assertEqual('-', u[8]);
|
||||
assertEqual('-', u[13]);
|
||||
assertEqual('4', u[15]);
|
||||
assertEqual('-', u[18]);
|
||||
assertEqual('-', u[23]);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_mode)
|
||||
{
|
||||
UUID uuid;
|
||||
|
||||
assertEqual(UUID_MODE_VARIANT4, uuid.getMode());
|
||||
uuid.setRandomMode();
|
||||
assertEqual(UUID_MODE_RANDOM, uuid.getMode());
|
||||
uuid.setVariant4Mode();
|
||||
assertEqual(UUID_MODE_VARIANT4, uuid.getMode());
|
||||
}
|
||||
|
||||
|
||||
unittest(test_printTo)
|
||||
{
|
||||
UUID uuid;
|
||||
|
||||
assertEqual(36, Serial.print(uuid)); // 36
|
||||
assertEqual(38, Serial.println(uuid)); // 36 + \n\r
|
||||
}
|
||||
|
||||
|
||||
|
||||
unittest_main()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user