diff --git a/libraries/UUID/README.md b/libraries/UUID/README.md index eb5fa487..aa66b023 100644 --- a/libraries/UUID/README.md +++ b/libraries/UUID/README.md @@ -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. + + diff --git a/libraries/UUID/UUID.cpp b/libraries/UUID/UUID.cpp index 3ce443ab..8d02113e 100644 --- a/libraries/UUID/UUID.cpp +++ b/libraries/UUID/UUID.cpp @@ -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; } diff --git a/libraries/UUID/UUID.h b/libraries/UUID/UUID.h index 2e72b0dc..76b42be8 100644 --- a/libraries/UUID/UUID.h +++ b/libraries/UUID/UUID.h @@ -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; }; diff --git a/libraries/UUID/examples/UUID_performance/UUID_performance.ino b/libraries/UUID/examples/UUID_performance/UUID_performance.ino index bf397fbe..ab54dd12 100644 --- a/libraries/UUID/examples/UUID_performance/UUID_performance.ino +++ b/libraries/UUID/examples/UUID_performance/UUID_performance.ino @@ -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."); } diff --git a/libraries/UUID/keywords.txt b/libraries/UUID/keywords.txt index ae70dad3..df8bd211 100644 --- a/libraries/UUID/keywords.txt +++ b/libraries/UUID/keywords.txt @@ -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 diff --git a/libraries/UUID/library.json b/libraries/UUID/library.json index 6ecb660d..fcefe781 100644 --- a/libraries/UUID/library.json +++ b/libraries/UUID/library.json @@ -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": "*", diff --git a/libraries/UUID/library.properties b/libraries/UUID/library.properties index 1f496eff..0c31ac2d 100644 --- a/libraries/UUID/library.properties +++ b/libraries/UUID/library.properties @@ -1,5 +1,5 @@ name=UUID -version=0.1.0 +version=0.1.1 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for generating UUID's. (experimental). diff --git a/libraries/UUID/test/unit_test_001.cpp b/libraries/UUID/test/unit_test_001.cpp index 09bfd04c..1648756e 100644 --- a/libraries/UUID/test/unit_test_001.cpp +++ b/libraries/UUID/test/unit_test_001.cpp @@ -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()