From b0e93da266d8020e5cf77cd1180871104b333211 Mon Sep 17 00:00:00 2001 From: rob tillaart Date: Tue, 14 Jun 2022 15:20:04 +0200 Subject: [PATCH] 0.1.0 UUID --- libraries/UUID/.arduino-ci.yml | 14 +++ .../UUID/.github/workflows/arduino-lint.yml | 13 ++ .../.github/workflows/arduino_test_runner.yml | 17 +++ .../UUID/.github/workflows/jsoncheck.yml | 18 +++ libraries/UUID/LICENSE | 21 ++++ libraries/UUID/README.md | 116 ++++++++++++++++++ libraries/UUID/UUID.cpp | 85 +++++++++++++ libraries/UUID/UUID.h | 53 ++++++++ .../examples/UUID_minimum/UUID_minimum.ino | 32 +++++ .../UUID_performance/UUID_performance.ino | 39 ++++++ .../UUID/examples/UUID_test/UUID_test.ino | 64 ++++++++++ libraries/UUID/keywords.txt | 16 +++ libraries/UUID/library.json | 23 ++++ libraries/UUID/library.properties | 11 ++ libraries/UUID/test/unit_test_001.cpp | 90 ++++++++++++++ 15 files changed, 612 insertions(+) create mode 100644 libraries/UUID/.arduino-ci.yml create mode 100644 libraries/UUID/.github/workflows/arduino-lint.yml create mode 100644 libraries/UUID/.github/workflows/arduino_test_runner.yml create mode 100644 libraries/UUID/.github/workflows/jsoncheck.yml create mode 100644 libraries/UUID/LICENSE create mode 100644 libraries/UUID/README.md create mode 100644 libraries/UUID/UUID.cpp create mode 100644 libraries/UUID/UUID.h create mode 100644 libraries/UUID/examples/UUID_minimum/UUID_minimum.ino create mode 100644 libraries/UUID/examples/UUID_performance/UUID_performance.ino create mode 100644 libraries/UUID/examples/UUID_test/UUID_test.ino create mode 100644 libraries/UUID/keywords.txt create mode 100644 libraries/UUID/library.json create mode 100644 libraries/UUID/library.properties create mode 100644 libraries/UUID/test/unit_test_001.cpp diff --git a/libraries/UUID/.arduino-ci.yml b/libraries/UUID/.arduino-ci.yml new file mode 100644 index 00000000..741de7b4 --- /dev/null +++ b/libraries/UUID/.arduino-ci.yml @@ -0,0 +1,14 @@ +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + - m4 + - esp32 + # - esp8266 + # - mega2560 + + libraries: + # - "printHelpers" diff --git a/libraries/UUID/.github/workflows/arduino-lint.yml b/libraries/UUID/.github/workflows/arduino-lint.yml new file mode 100644 index 00000000..b2ca058c --- /dev/null +++ b/libraries/UUID/.github/workflows/arduino-lint.yml @@ -0,0 +1,13 @@ + +name: Arduino-lint + +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: update + compliance: strict diff --git a/libraries/UUID/.github/workflows/arduino_test_runner.yml b/libraries/UUID/.github/workflows/arduino_test_runner.yml new file mode 100644 index 00000000..096b975b --- /dev/null +++ b/libraries/UUID/.github/workflows/arduino_test_runner.yml @@ -0,0 +1,17 @@ +--- +name: Arduino CI + +on: [push, pull_request] + +jobs: + runTest: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - run: | + gem install arduino_ci + arduino_ci.rb diff --git a/libraries/UUID/.github/workflows/jsoncheck.yml b/libraries/UUID/.github/workflows/jsoncheck.yml new file mode 100644 index 00000000..04603d08 --- /dev/null +++ b/libraries/UUID/.github/workflows/jsoncheck.yml @@ -0,0 +1,18 @@ +name: JSON check + +on: + push: + paths: + - '**.json' + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: json-syntax-check + uses: limitusus/json-syntax-check@v1 + with: + pattern: "\\.json$" + diff --git a/libraries/UUID/LICENSE b/libraries/UUID/LICENSE new file mode 100644 index 00000000..cb502675 --- /dev/null +++ b/libraries/UUID/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2022 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/UUID/README.md b/libraries/UUID/README.md new file mode 100644 index 00000000..eb5fa487 --- /dev/null +++ b/libraries/UUID/README.md @@ -0,0 +1,116 @@ + +[![Arduino CI](https://github.com/RobTillaart/UUID/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) +[![Arduino-lint](https://github.com/RobTillaart/UUID/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/UUID/actions/workflows/arduino-lint.yml) +[![JSON check](https://github.com/RobTillaart/UUID/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/UUID/actions/workflows/jsoncheck.yml) +[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/UUID/blob/master/LICENSE) +[![GitHub release](https://img.shields.io/github/release/RobTillaart/UUID.svg?maxAge=3600)](https://github.com/RobTillaart/UUID/releases) + + +# UUID + +Arduino library for generating UUID strings. + + +## Description + +This experimental library provides a UUID generator. + +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. + +In such this is for experimental use only. + +Tested on Arduino UNO only. + +A UUID generated looks like 20d24650-d900-e34f-de49-8964ab3eb46d + + + +## Interface + + +## UUID class + +Use **\#include "UUID.h"** + +- **UUID()** Constructor, initializes internals. +- **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. +- **char \* toCharArray()** returns a pointer to a char buffer +representing the last generated UUID. + + +### 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. + +```cpp +UUID uuid; + +Serial.println(uuid); +``` + +Note: there is a known compile warning on AVR on this. + + +#### Performance + +Not tested ESP32 (and many other platforms) yet. +First numbers measured with **UUID_test.ino** shows the following timing. + +| 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 | | + + +The performance of **generate()** must be improved if possible. + +Note an UNO can generate 2000++ UUID's per second. + + +## Operation + +See examples. + +Note: compile warning ... + + +## Future + +### General + +- improve documentation + - external random input needed + - GUID, UUID, versions (links) + - background + - rfc4122 layout +- test other platforms +- investigate entropy harvesting + - freeRAM, micros, timers, RAM, USB-ID, ... + +### Functions + +- add **setSeparator(char)** and **getSeparator()** ? + - one char +- add **setUpperCase()** and **setLowerCase()**, **isUpperCase()** + - one bool flag + +### Examples + +- ESP32 UUID server + - using timing of the calls as entropy ! +- RTC for entropy + +### Fixes / optimizations + +- improve performance of **generate()** +- reduce footprint + - can the buffer be reduced? + - smaller random generator? + diff --git a/libraries/UUID/UUID.cpp b/libraries/UUID/UUID.cpp new file mode 100644 index 00000000..3ce443ab --- /dev/null +++ b/libraries/UUID/UUID.cpp @@ -0,0 +1,85 @@ +// +// FILE: UUID.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// DATE: 2022-06-14 +// PURPOSE: Arduino Library for generating UUID's +// URL: https://github.com/RobTillaart/UUID +// https://en.wikipedia.org/wiki/UUID +// +// HISTORY +// 0.1.0 2022-06-14 initial version + + +#include "UUID.h" + + +UUID::UUID() +{ + seed(1, 2); + generate(); +} + + +void UUID::seed(uint32_t s1, uint32_t s2) +{ + // set Marsaglia constants, prevent 0 as value + if (s1 == 0) s1 = 1; + if (s2 == 0) s2 = 2; + _m_w = s1; + _m_z = s2; +} + + +void UUID::generate() +{ + uint32_t _ar[4]; + for (uint8_t i = 0; i < 4; i++) + { + _ar[i] = _random(); + } + + // TODO improve efficiency + for (int i = 0, j = 0; i < 32; i++, j++) + { + if (i == 8) _buffer[j++] = '-'; + if (i == 12) _buffer[j++] = '-'; + if (i == 16) _buffer[j++] = '-'; + if (i == 20) _buffer[j++] = '-'; + + uint8_t nr = i / 8; + uint8_t shft = ((i % 8) * 4); + uint8_t ch = (_ar[nr] >> shft ) & 0xF; + + _buffer[j] = (ch < 10) ? '0' + ch : 'a' - 10 + ch; + } + _buffer[36] = 0; +} + + +char * UUID::toCharArray() +{ + return _buffer; +} + + +// PRINTING +size_t UUID::printTo(Print& p) const +{ + return p.print(_buffer); +}; + + +// An example of a simple pseudo-random number generator is the +// Multiply-with-carry method invented by George Marsaglia. +// two initializers (not null) +uint32_t UUID::_random() +{ + _m_z = 36969L * (_m_z & 65535L) + (_m_z >> 16); + _m_w = 18000L * (_m_w & 65535L) + (_m_w >> 16); + return (_m_z << 16) + _m_w; /* 32-bit result */ +} + + +// -- END OF FILE -- + diff --git a/libraries/UUID/UUID.h b/libraries/UUID/UUID.h new file mode 100644 index 00000000..2e72b0dc --- /dev/null +++ b/libraries/UUID/UUID.h @@ -0,0 +1,53 @@ +#pragma once +// +// FILE: UUID.h +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// DATE: 2022-06-14 +// PURPOSE: Arduino Library for generating UUID's +// URL: https://github.com/RobTillaart/UUID +// https://en.wikipedia.org/wiki/UUID +// +// e.g. 20D24650-D900-E34F-DE49-8964AB3EB46D + + +#include "Arduino.h" +#include "Printable.h" + + +#define UUID_LIB_VERSION (F("0.1.0")) + + +///////////////////////////////////////////////// +// +// CLASS VERSION +// +class UUID : public Printable +{ +public: + UUID(); + + // at least one seed value is mandatory, two is better. + void seed(uint32_t s1, uint32_t s2 = 0); + // generate a new UUID + void generate(); + // make a UUID string + char * toCharArray(); + + // Printable interface + size_t printTo(Print& p) const; + + +private: + // Marsaglia 'constants' + function + uint32_t _m_w = 1; + uint32_t _m_z = 2; + uint32_t _random(); + + // UUID in string format + char _buffer[37]; +}; + + +// -- END OF FILE -- + diff --git a/libraries/UUID/examples/UUID_minimum/UUID_minimum.ino b/libraries/UUID/examples/UUID_minimum/UUID_minimum.ino new file mode 100644 index 00000000..3cde7507 --- /dev/null +++ b/libraries/UUID/examples/UUID_minimum/UUID_minimum.ino @@ -0,0 +1,32 @@ +// +// FILE: UUID_minimum.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo - will generate same UUID's (no external entropy) + +#include "Arduino.h" +#include "UUID.h" + +UUID uuid; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + Serial.println(); + Serial.println("UUID_minimum.ino"); + Serial.print("UUID_LIB_VERSION: "); + Serial.println(UUID_LIB_VERSION); +} + + +void loop() +{ + uuid.generate(); + Serial.print("UUID: "); + Serial.println(uuid); + delay(100); +} + + +// -- END OF FILE -- diff --git a/libraries/UUID/examples/UUID_performance/UUID_performance.ino b/libraries/UUID/examples/UUID_performance/UUID_performance.ino new file mode 100644 index 00000000..bf397fbe --- /dev/null +++ b/libraries/UUID/examples/UUID_performance/UUID_performance.ino @@ -0,0 +1,39 @@ +// +// FILE: UUID_performance.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo + +#include "Arduino.h" +#include "UUID.h" + +UUID uuid; + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + Serial.println(); + Serial.println("UUID_performance.ino"); + Serial.print("UUID_LIB_VERSION: "); + Serial.println(UUID_LIB_VERSION); + + uint16_t count = 0; + uint32_t start = millis(); + while (millis() - start < 1000) + { + uuid.generate(); + count++; + } + Serial.print("Generated "); + Serial.print(count); + Serial.println(" uuid's per second."); +} + + +void loop() +{ +} + + +// -- END OF FILE -- diff --git a/libraries/UUID/examples/UUID_test/UUID_test.ino b/libraries/UUID/examples/UUID_test/UUID_test.ino new file mode 100644 index 00000000..a7fccf6c --- /dev/null +++ b/libraries/UUID/examples/UUID_test/UUID_test.ino @@ -0,0 +1,64 @@ +// +// FILE: UUID_test.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo + + +#include "Arduino.h" +#include "UUID.h" + + +UUID uuid; + +uint32_t start, stop, randomtime; + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + + Serial.println(); + Serial.println("UUID_test.ino"); + Serial.print("UUID_LIB_VERSION: "); + Serial.println(UUID_LIB_VERSION); + + start = micros(); + uuid.seed(2); + stop = micros(); + + Serial.print(" seed: "); + Serial.println(stop - start); + delay(100); + + start = micros(); + uuid.generate(); + stop = micros(); + + Serial.print(" generate: "); + Serial.println(stop - start); + delay(100); + + start = micros(); + uuid.toCharArray(); + stop = micros(); + + Serial.print("toCharArray: "); + Serial.println(stop - start); + delay(100); + + Serial.print("UUID: "); + Serial.println(uuid); +} + + +void loop() +{ + uuid.generate(); + Serial.print("UUID: "); + Serial.println(uuid); + delay(1000); +} + + +// -- END OF FILE -- diff --git a/libraries/UUID/keywords.txt b/libraries/UUID/keywords.txt new file mode 100644 index 00000000..ae70dad3 --- /dev/null +++ b/libraries/UUID/keywords.txt @@ -0,0 +1,16 @@ +# Syntax Colouring Map For UUID + +# Data types (KEYWORD1) +UUID KEYWORD1 + + +# Methods and Functions (KEYWORD2) +seed KEYWORD2 +generate KEYWORD2 +toCharArray KEYWORD2 + + +# Constants (LITERAL1) +UUID_LIB_VERSION LITERAL1 + + diff --git a/libraries/UUID/library.json b/libraries/UUID/library.json new file mode 100644 index 00000000..6ecb660d --- /dev/null +++ b/libraries/UUID/library.json @@ -0,0 +1,23 @@ +{ + "name": "UUID", + "keywords": "UUID, GUID", + "description": "Arduino library for generating UUID's. (experimental).", + "authors": + [ + { + "name": "Rob Tillaart", + "email": "Rob.Tillaart@gmail.com", + "maintainer": true + } + ], + "repository": + { + "type": "git", + "url": "https://github.com/RobTillaart/UUID.git" + }, + "version": "0.1.0", + "license": "MIT", + "frameworks": "arduino", + "platforms": "*", + "headers": "UUID.h" +} diff --git a/libraries/UUID/library.properties b/libraries/UUID/library.properties new file mode 100644 index 00000000..1f496eff --- /dev/null +++ b/libraries/UUID/library.properties @@ -0,0 +1,11 @@ +name=UUID +version=0.1.0 +author=Rob Tillaart +maintainer=Rob Tillaart +sentence=Arduino library for generating UUID's. (experimental). +paragraph=GUID +category=Signal Input/Output +url=https://github.com/RobTillaart/UUID +architectures=* +includes=UUID.h +depends= diff --git a/libraries/UUID/test/unit_test_001.cpp b/libraries/UUID/test/unit_test_001.cpp new file mode 100644 index 00000000..09bfd04c --- /dev/null +++ b/libraries/UUID/test/unit_test_001.cpp @@ -0,0 +1,90 @@ +// +// FILE: unit_test_001.cpp +// AUTHOR: Rob Tillaart +// DATE: 2022-06-14 +// PURPOSE: unit tests for the UUID library +// https://github.com/RobTillaart/UUID +// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md +// + +// supported assertions +// https://github.com/Arduino-CI/arduino_ci/blob/master/cpp/unittest/Assertion.h#L33-L42 +// ---------------------------- +// assertEqual(expected, actual) +// assertNotEqual(expected, actual) +// assertLess(expected, actual) +// assertMore(expected, actual) +// assertLessOrEqual(expected, actual) +// assertMoreOrEqual(expected, actual) +// assertTrue(actual) +// assertFalse(actual) +// assertNull(actual) +// assertNotNull(actual) + +#include + + +#include "Arduino.h" +#include "UUID.h" + + +unittest_setup() +{ + fprintf(stderr, "UUID_LIB_VERSION: %s\n", (char *) UUID_LIB_VERSION); +} + +unittest_teardown() +{ +} + + +unittest(test_generate) +{ + UUID uuid; + char u[40], v[40], w[40]; + + uuid.generate(); + strcpy(u, uuid.toCharArray()); + assertEqual(36, strlen(u)); + + strcpy(v, uuid.toCharArray()); + assertEqual(36, strlen(v)); + assertEqual(u, v); + + uuid.generate(); + strcpy(v, uuid.toCharArray()); + assertEqual(36, strlen(v)); + + uuid.generate(); + strcpy(w, uuid.toCharArray()); + assertEqual(36, strlen(w)); + + assertNotEqual(u, v); + assertNotEqual(u, w); + assertNotEqual(w, v); +} + + +unittest(test_layout) +{ + UUID uuid; + char u[40]; + + uuid.generate(); + strcpy(u, uuid.toCharArray()); + fprintf(stderr, ">%s<\n", uuid.toCharArray()); + assertEqual(36, strlen(u)); + + assertEqual('-', u[8]); + assertEqual('-', u[13]); + assertEqual('-', u[18]); + assertEqual('-', u[23]); +} + + + +unittest_main() + + +// -------- +