From 12ce1eee7a3bfa1746f1f4e7a78a034fc1b67d33 Mon Sep 17 00:00:00 2001
From: Jochen Vothknecht <jochen3120@gmail.com>
Date: Sun, 1 Jul 2018 22:49:59 +0200
Subject: [PATCH] make lib ready for direct inclusion

---
 .editorconfig                                 |   41 -
 .gitignore                                    |    3 -
 .vscode/c_cpp_properties.json                 |  101 -
 .vscode/launch.json                           |   16 -
 .vscode/settings.json                         |    6 -
 .vscode/tasks.json                            |   46 -
 components/bme280/BME280.cpp => BME280.cpp    |    0
 components/bme280/BME280.h => BME280.h        |    0
 CMakeLists.txt                                |   66 -
 components/cpp_utils/I2C.cpp => I2C.cpp       |    0
 components/cpp_utils/I2C.h => I2C.h           |    0
 LICENSE                                       |  201 --
 Makefile                                      |   12 -
 .../bme280/component.mk => component.mk       |    0
 components/cpp_utils/.gitignore               |    1 -
 components/cpp_utils/AWS.cpp                  |  132 -
 components/cpp_utils/AWS.h                    |   36 -
 components/cpp_utils/ArduinoBLE.md            |   43 -
 .../Arduino_ESP32_BLE.library.properties      |   10 -
 components/cpp_utils/BLE2902.cpp              |   69 -
 components/cpp_utils/BLE2902.h                |   34 -
 components/cpp_utils/BLEAddress.cpp           |   93 -
 components/cpp_utils/BLEAddress.h             |   34 -
 components/cpp_utils/BLEAdvertisedDevice.cpp  |  410 ---
 components/cpp_utils/BLEAdvertisedDevice.h    |  106 -
 components/cpp_utils/BLEAdvertising.cpp       |  155 -
 components/cpp_utils/BLEAdvertising.h         |   34 -
 components/cpp_utils/BLECharacteristic.cpp    |  693 -----
 components/cpp_utils/BLECharacteristic.h      |  132 -
 .../cpp_utils/BLECharacteristicCallbacks.cpp  |   34 -
 components/cpp_utils/BLECharacteristicMap.cpp |  136 -
 components/cpp_utils/BLEClient.cpp            |  327 ---
 components/cpp_utils/BLEClient.h              |   76 -
 components/cpp_utils/BLEDescriptor.cpp        |  278 --
 components/cpp_utils/BLEDescriptor.h          |   54 -
 components/cpp_utils/BLEDescriptorMap.cpp     |  149 -
 components/cpp_utils/BLEDevice.cpp            |  222 --
 components/cpp_utils/BLEDevice.h              |   54 -
 .../cpp_utils/BLERemoteCharacteristic.cpp     |  336 ---
 .../cpp_utils/BLERemoteCharacteristic.h       |   63 -
 components/cpp_utils/BLERemoteDescriptor.cpp  |   11 -
 components/cpp_utils/BLERemoteDescriptor.h    |   20 -
 components/cpp_utils/BLERemoteService.cpp     |  220 --
 components/cpp_utils/BLERemoteService.h       |   63 -
 components/cpp_utils/BLEScan.cpp              |  276 --
 components/cpp_utils/BLEScan.h                |   67 -
 components/cpp_utils/BLEServer.cpp            |  353 ---
 components/cpp_utils/BLEServer.h              |  117 -
 components/cpp_utils/BLEServerCallbacks.cpp   |   22 -
 components/cpp_utils/BLEService.cpp           |  353 ---
 components/cpp_utils/BLEService.h             |   99 -
 components/cpp_utils/BLEServiceMap.cpp        |   95 -
 components/cpp_utils/BLEUUID.cpp              |  326 ---
 components/cpp_utils/BLEUUID.h                |   37 -
 components/cpp_utils/BLEUtils.cpp             | 1352 ---------
 components/cpp_utils/BLEUtils.h               |   60 -
 components/cpp_utils/BLEValue.cpp             |  116 -
 components/cpp_utils/BLEValue.h               |   36 -
 .../BLEXML/Characteristics/code/.gitignore    |    3 -
 .../Characteristics/code/characteristics.txt  |  196 --
 .../BLEXML/Characteristics/code/run.sh        |   20 -
 components/cpp_utils/BLEXML/README.md         |    4 -
 .../cpp_utils/BLEXML/Services/code/.gitignore |    3 -
 .../cpp_utils/BLEXML/Services/code/run.sh     |   20 -
 .../BLEXML/Services/code/services.txt         |   36 -
 components/cpp_utils/CPPNVS.cpp               |   79 -
 components/cpp_utils/CPPNVS.h                 |   31 -
 components/cpp_utils/DesignNotes/README.md    |    2 -
 .../cpp_utils/DesignNotes/WebSockets.md       |   64 -
 components/cpp_utils/Doxyfile                 | 2496 -----------------
 components/cpp_utils/FATFS_VFS.cpp            |   69 -
 components/cpp_utils/FATFS_VFS.h              |   57 -
 components/cpp_utils/File.cpp                 |  133 -
 components/cpp_utils/File.h                   |   32 -
 components/cpp_utils/FileSystem.cpp           |  138 -
 components/cpp_utils/FileSystem.h             |   25 -
 components/cpp_utils/FreeRTOS.cpp             |  165 --
 components/cpp_utils/FreeRTOS.h               |   49 -
 components/cpp_utils/FreeRTOSTimer.cpp        |  139 -
 components/cpp_utils/FreeRTOSTimer.h          |   35 -
 components/cpp_utils/GPIO.cpp                 |  211 --
 components/cpp_utils/GPIO.h                   |   48 -
 components/cpp_utils/GeneralUtils.cpp         |  388 ---
 components/cpp_utils/GeneralUtils.h           |   28 -
 components/cpp_utils/HttpParser.cpp           |  263 --
 components/cpp_utils/HttpParser.h             |   37 -
 components/cpp_utils/HttpRequest.cpp          |  272 --
 components/cpp_utils/HttpRequest.h            |   69 -
 components/cpp_utils/HttpResponse.cpp         |  101 -
 components/cpp_utils/HttpResponse.h           |   50 -
 components/cpp_utils/HttpServer.cpp           |  255 --
 components/cpp_utils/HttpServer.h             |   59 -
 components/cpp_utils/I2S.cpp                  |  412 ---
 components/cpp_utils/I2S.h                    |   62 -
 components/cpp_utils/IFTTT.cpp                |   51 -
 components/cpp_utils/IFTTT.h                  |   26 -
 components/cpp_utils/JSON.cpp                 |  348 ---
 components/cpp_utils/JSON.h                   |   83 -
 components/cpp_utils/Kconfig                  |   21 -
 components/cpp_utils/MAX7219.cpp              |  280 --
 components/cpp_utils/MAX7219.h                |  193 --
 components/cpp_utils/MFRC522.cpp              | 1645 -----------
 components/cpp_utils/MFRC522.h                |  418 ---
 components/cpp_utils/MFRC522Debug.h           |   14 -
 components/cpp_utils/MPU6050.cpp              |   98 -
 components/cpp_utils/MPU6050.h                |   95 -
 components/cpp_utils/MRFC522Debug.cpp         |   46 -
 components/cpp_utils/Makefile.arduino         |   67 -
 .../cpp_utils/NeoPixelWiFiEventHandler.cpp    |   59 -
 .../cpp_utils/NeoPixelWiFiEventHandler.h      |   36 -
 components/cpp_utils/OV7670.cpp               |  520 ----
 components/cpp_utils/OV7670.h                 |  208 --
 components/cpp_utils/PCF8574.cpp              |  121 -
 components/cpp_utils/PCF8574.h                |   37 -
 components/cpp_utils/PWM.cpp                  |  154 -
 components/cpp_utils/PWM.h                    |   42 -
 components/cpp_utils/README.md                |   53 -
 components/cpp_utils/RESTClient.cpp           |  166 --
 components/cpp_utils/RESTClient.h             |  124 -
 components/cpp_utils/RMT.cpp                  |  115 -
 components/cpp_utils/RMT.h                    |   35 -
 components/cpp_utils/SOC.cpp                  |   67 -
 components/cpp_utils/SOC.h                    |   21 -
 components/cpp_utils/SPI.cpp                  |  143 -
 components/cpp_utils/SPI.h                    |   58 -
 components/cpp_utils/SockServ.cpp             |  198 --
 components/cpp_utils/SockServ.h               |   56 -
 components/cpp_utils/Socket.cpp               |  407 ---
 components/cpp_utils/Socket.h                 |   72 -
 components/cpp_utils/System.cpp               |   48 -
 components/cpp_utils/System.h                 |   26 -
 components/cpp_utils/TFTP.cpp                 |  380 ---
 components/cpp_utils/TFTP.h                   |   69 -
 components/cpp_utils/Task.cpp                 |   99 -
 components/cpp_utils/Task.h                   |   61 -
 components/cpp_utils/U8G2.cpp                 |   34 -
 components/cpp_utils/U8G2.h                   |  125 -
 components/cpp_utils/WS2812.cpp               |  332 ---
 components/cpp_utils/WS2812.h                 |   68 -
 components/cpp_utils/WebServer.cpp            |  847 ------
 components/cpp_utils/WebServer.h              |  194 --
 components/cpp_utils/WebSocket.cpp            |  458 ---
 components/cpp_utils/WebSocket.h              |   93 -
 .../cpp_utils/WebSocketFileTransfer.cpp       |  112 -
 components/cpp_utils/WebSocketFileTransfer.h  |   24 -
 components/cpp_utils/WiFi.cpp                 |  434 ---
 components/cpp_utils/WiFi.h                   |  137 -
 components/cpp_utils/WiFiEventHandler.cpp     |  156 --
 components/cpp_utils/WiFiEventHandler.h       |  117 -
 components/cpp_utils/component.mk             |   15 -
 components/cpp_utils/mainpage.dox             |    8 -
 .../Arduino/BLE_client/BLE_client.ino         |  132 -
 .../Arduino/BLE_notify/BLE_notify.ino         |   93 -
 .../BLETests/Arduino/BLE_scan/BLE_scan.ino    |   36 -
 .../Arduino/BLE_server/BLE_server.ino         |   41 -
 .../BLETests/Arduino/BLE_uart/BLE_uart.ino    |  111 -
 .../BLETests/Arduino/BLE_write/BLE_write.ino  |   68 -
 components/cpp_utils/tests/BLETests/README.md |    2 -
 .../tests/BLETests/Sample-MLE-15.cpp          |   89 -
 .../cpp_utils/tests/BLETests/Sample1.cpp      |   38 -
 .../cpp_utils/tests/BLETests/SampleClient.cpp |  113 -
 .../tests/BLETests/SampleClient_Notify.cpp    |  108 -
 .../cpp_utils/tests/BLETests/SampleNotify.cpp |  107 -
 .../cpp_utils/tests/BLETests/SampleRead.cpp   |   59 -
 .../cpp_utils/tests/BLETests/SampleScan.cpp   |   35 -
 .../cpp_utils/tests/BLETests/SampleServer.cpp |   58 -
 .../cpp_utils/tests/BLETests/SampleWrite.cpp  |   62 -
 components/cpp_utils/tests/BLETests/main.cpp  |   34 -
 .../cpp_utils/tests/MFRC522/DumpInfo.cpp      |   50 -
 components/cpp_utils/tests/MFRC522/main.cpp   |   38 -
 .../cpp_utils/tests/task_i2c_scanner.cpp      |   27 -
 components/cpp_utils/tests/task_mdns.cpp      |   41 -
 components/cpp_utils/tests/test_max7219.cpp   |   61 -
 components/cpp_utils/tests/test_rest.cpp      |   71 -
 .../cpp_utils/tests/test_rest_ifttt.cpp       |   55 -
 main/MeasureTask.cpp                          |   23 -
 main/MeasureTask.h                            |   18 -
 main/component.mk                             |    3 -
 main/main.cpp                                 |   22 -
 reference                                     |  112 -
 sdkconfig                                     |  452 ---
 181 files changed, 25950 deletions(-)
 delete mode 100644 .editorconfig
 delete mode 100644 .gitignore
 delete mode 100644 .vscode/c_cpp_properties.json
 delete mode 100644 .vscode/launch.json
 delete mode 100644 .vscode/settings.json
 delete mode 100644 .vscode/tasks.json
 rename components/bme280/BME280.cpp => BME280.cpp (100%)
 rename components/bme280/BME280.h => BME280.h (100%)
 delete mode 100644 CMakeLists.txt
 rename components/cpp_utils/I2C.cpp => I2C.cpp (100%)
 rename components/cpp_utils/I2C.h => I2C.h (100%)
 delete mode 100644 LICENSE
 delete mode 100644 Makefile
 rename components/bme280/component.mk => component.mk (100%)
 delete mode 100644 components/cpp_utils/.gitignore
 delete mode 100644 components/cpp_utils/AWS.cpp
 delete mode 100644 components/cpp_utils/AWS.h
 delete mode 100644 components/cpp_utils/ArduinoBLE.md
 delete mode 100644 components/cpp_utils/Arduino_ESP32_BLE.library.properties
 delete mode 100644 components/cpp_utils/BLE2902.cpp
 delete mode 100644 components/cpp_utils/BLE2902.h
 delete mode 100644 components/cpp_utils/BLEAddress.cpp
 delete mode 100644 components/cpp_utils/BLEAddress.h
 delete mode 100644 components/cpp_utils/BLEAdvertisedDevice.cpp
 delete mode 100644 components/cpp_utils/BLEAdvertisedDevice.h
 delete mode 100644 components/cpp_utils/BLEAdvertising.cpp
 delete mode 100644 components/cpp_utils/BLEAdvertising.h
 delete mode 100644 components/cpp_utils/BLECharacteristic.cpp
 delete mode 100644 components/cpp_utils/BLECharacteristic.h
 delete mode 100644 components/cpp_utils/BLECharacteristicCallbacks.cpp
 delete mode 100644 components/cpp_utils/BLECharacteristicMap.cpp
 delete mode 100644 components/cpp_utils/BLEClient.cpp
 delete mode 100644 components/cpp_utils/BLEClient.h
 delete mode 100644 components/cpp_utils/BLEDescriptor.cpp
 delete mode 100644 components/cpp_utils/BLEDescriptor.h
 delete mode 100644 components/cpp_utils/BLEDescriptorMap.cpp
 delete mode 100644 components/cpp_utils/BLEDevice.cpp
 delete mode 100644 components/cpp_utils/BLEDevice.h
 delete mode 100644 components/cpp_utils/BLERemoteCharacteristic.cpp
 delete mode 100644 components/cpp_utils/BLERemoteCharacteristic.h
 delete mode 100644 components/cpp_utils/BLERemoteDescriptor.cpp
 delete mode 100644 components/cpp_utils/BLERemoteDescriptor.h
 delete mode 100644 components/cpp_utils/BLERemoteService.cpp
 delete mode 100644 components/cpp_utils/BLERemoteService.h
 delete mode 100644 components/cpp_utils/BLEScan.cpp
 delete mode 100644 components/cpp_utils/BLEScan.h
 delete mode 100644 components/cpp_utils/BLEServer.cpp
 delete mode 100644 components/cpp_utils/BLEServer.h
 delete mode 100644 components/cpp_utils/BLEServerCallbacks.cpp
 delete mode 100644 components/cpp_utils/BLEService.cpp
 delete mode 100644 components/cpp_utils/BLEService.h
 delete mode 100644 components/cpp_utils/BLEServiceMap.cpp
 delete mode 100644 components/cpp_utils/BLEUUID.cpp
 delete mode 100644 components/cpp_utils/BLEUUID.h
 delete mode 100644 components/cpp_utils/BLEUtils.cpp
 delete mode 100644 components/cpp_utils/BLEUtils.h
 delete mode 100644 components/cpp_utils/BLEValue.cpp
 delete mode 100644 components/cpp_utils/BLEValue.h
 delete mode 100644 components/cpp_utils/BLEXML/Characteristics/code/.gitignore
 delete mode 100644 components/cpp_utils/BLEXML/Characteristics/code/characteristics.txt
 delete mode 100755 components/cpp_utils/BLEXML/Characteristics/code/run.sh
 delete mode 100644 components/cpp_utils/BLEXML/README.md
 delete mode 100644 components/cpp_utils/BLEXML/Services/code/.gitignore
 delete mode 100755 components/cpp_utils/BLEXML/Services/code/run.sh
 delete mode 100644 components/cpp_utils/BLEXML/Services/code/services.txt
 delete mode 100644 components/cpp_utils/CPPNVS.cpp
 delete mode 100644 components/cpp_utils/CPPNVS.h
 delete mode 100644 components/cpp_utils/DesignNotes/README.md
 delete mode 100644 components/cpp_utils/DesignNotes/WebSockets.md
 delete mode 100644 components/cpp_utils/Doxyfile
 delete mode 100644 components/cpp_utils/FATFS_VFS.cpp
 delete mode 100644 components/cpp_utils/FATFS_VFS.h
 delete mode 100644 components/cpp_utils/File.cpp
 delete mode 100644 components/cpp_utils/File.h
 delete mode 100644 components/cpp_utils/FileSystem.cpp
 delete mode 100644 components/cpp_utils/FileSystem.h
 delete mode 100644 components/cpp_utils/FreeRTOS.cpp
 delete mode 100644 components/cpp_utils/FreeRTOS.h
 delete mode 100644 components/cpp_utils/FreeRTOSTimer.cpp
 delete mode 100644 components/cpp_utils/FreeRTOSTimer.h
 delete mode 100644 components/cpp_utils/GPIO.cpp
 delete mode 100644 components/cpp_utils/GPIO.h
 delete mode 100644 components/cpp_utils/GeneralUtils.cpp
 delete mode 100644 components/cpp_utils/GeneralUtils.h
 delete mode 100644 components/cpp_utils/HttpParser.cpp
 delete mode 100644 components/cpp_utils/HttpParser.h
 delete mode 100644 components/cpp_utils/HttpRequest.cpp
 delete mode 100644 components/cpp_utils/HttpRequest.h
 delete mode 100644 components/cpp_utils/HttpResponse.cpp
 delete mode 100644 components/cpp_utils/HttpResponse.h
 delete mode 100644 components/cpp_utils/HttpServer.cpp
 delete mode 100644 components/cpp_utils/HttpServer.h
 delete mode 100644 components/cpp_utils/I2S.cpp
 delete mode 100644 components/cpp_utils/I2S.h
 delete mode 100644 components/cpp_utils/IFTTT.cpp
 delete mode 100644 components/cpp_utils/IFTTT.h
 delete mode 100644 components/cpp_utils/JSON.cpp
 delete mode 100644 components/cpp_utils/JSON.h
 delete mode 100644 components/cpp_utils/Kconfig
 delete mode 100644 components/cpp_utils/MAX7219.cpp
 delete mode 100644 components/cpp_utils/MAX7219.h
 delete mode 100644 components/cpp_utils/MFRC522.cpp
 delete mode 100644 components/cpp_utils/MFRC522.h
 delete mode 100644 components/cpp_utils/MFRC522Debug.h
 delete mode 100644 components/cpp_utils/MPU6050.cpp
 delete mode 100644 components/cpp_utils/MPU6050.h
 delete mode 100644 components/cpp_utils/MRFC522Debug.cpp
 delete mode 100644 components/cpp_utils/Makefile.arduino
 delete mode 100644 components/cpp_utils/NeoPixelWiFiEventHandler.cpp
 delete mode 100644 components/cpp_utils/NeoPixelWiFiEventHandler.h
 delete mode 100644 components/cpp_utils/OV7670.cpp
 delete mode 100644 components/cpp_utils/OV7670.h
 delete mode 100644 components/cpp_utils/PCF8574.cpp
 delete mode 100644 components/cpp_utils/PCF8574.h
 delete mode 100644 components/cpp_utils/PWM.cpp
 delete mode 100644 components/cpp_utils/PWM.h
 delete mode 100644 components/cpp_utils/README.md
 delete mode 100644 components/cpp_utils/RESTClient.cpp
 delete mode 100644 components/cpp_utils/RESTClient.h
 delete mode 100644 components/cpp_utils/RMT.cpp
 delete mode 100644 components/cpp_utils/RMT.h
 delete mode 100644 components/cpp_utils/SOC.cpp
 delete mode 100644 components/cpp_utils/SOC.h
 delete mode 100644 components/cpp_utils/SPI.cpp
 delete mode 100644 components/cpp_utils/SPI.h
 delete mode 100644 components/cpp_utils/SockServ.cpp
 delete mode 100644 components/cpp_utils/SockServ.h
 delete mode 100644 components/cpp_utils/Socket.cpp
 delete mode 100644 components/cpp_utils/Socket.h
 delete mode 100644 components/cpp_utils/System.cpp
 delete mode 100644 components/cpp_utils/System.h
 delete mode 100644 components/cpp_utils/TFTP.cpp
 delete mode 100644 components/cpp_utils/TFTP.h
 delete mode 100644 components/cpp_utils/Task.cpp
 delete mode 100644 components/cpp_utils/Task.h
 delete mode 100644 components/cpp_utils/U8G2.cpp
 delete mode 100644 components/cpp_utils/U8G2.h
 delete mode 100644 components/cpp_utils/WS2812.cpp
 delete mode 100644 components/cpp_utils/WS2812.h
 delete mode 100644 components/cpp_utils/WebServer.cpp
 delete mode 100644 components/cpp_utils/WebServer.h
 delete mode 100644 components/cpp_utils/WebSocket.cpp
 delete mode 100644 components/cpp_utils/WebSocket.h
 delete mode 100644 components/cpp_utils/WebSocketFileTransfer.cpp
 delete mode 100644 components/cpp_utils/WebSocketFileTransfer.h
 delete mode 100644 components/cpp_utils/WiFi.cpp
 delete mode 100644 components/cpp_utils/WiFi.h
 delete mode 100644 components/cpp_utils/WiFiEventHandler.cpp
 delete mode 100644 components/cpp_utils/WiFiEventHandler.h
 delete mode 100644 components/cpp_utils/component.mk
 delete mode 100644 components/cpp_utils/mainpage.dox
 delete mode 100644 components/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino
 delete mode 100644 components/cpp_utils/tests/BLETests/Arduino/BLE_notify/BLE_notify.ino
 delete mode 100644 components/cpp_utils/tests/BLETests/Arduino/BLE_scan/BLE_scan.ino
 delete mode 100644 components/cpp_utils/tests/BLETests/Arduino/BLE_server/BLE_server.ino
 delete mode 100644 components/cpp_utils/tests/BLETests/Arduino/BLE_uart/BLE_uart.ino
 delete mode 100644 components/cpp_utils/tests/BLETests/Arduino/BLE_write/BLE_write.ino
 delete mode 100644 components/cpp_utils/tests/BLETests/README.md
 delete mode 100644 components/cpp_utils/tests/BLETests/Sample-MLE-15.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/Sample1.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/SampleClient.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/SampleClient_Notify.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/SampleNotify.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/SampleRead.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/SampleScan.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/SampleServer.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/SampleWrite.cpp
 delete mode 100644 components/cpp_utils/tests/BLETests/main.cpp
 delete mode 100644 components/cpp_utils/tests/MFRC522/DumpInfo.cpp
 delete mode 100644 components/cpp_utils/tests/MFRC522/main.cpp
 delete mode 100644 components/cpp_utils/tests/task_i2c_scanner.cpp
 delete mode 100644 components/cpp_utils/tests/task_mdns.cpp
 delete mode 100644 components/cpp_utils/tests/test_max7219.cpp
 delete mode 100644 components/cpp_utils/tests/test_rest.cpp
 delete mode 100644 components/cpp_utils/tests/test_rest_ifttt.cpp
 delete mode 100644 main/MeasureTask.cpp
 delete mode 100644 main/MeasureTask.h
 delete mode 100644 main/component.mk
 delete mode 100644 main/main.cpp
 delete mode 100644 reference
 delete mode 100644 sdkconfig

diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index b58df04..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,41 +0,0 @@
-# EditorConfig is awesome: http://EditorConfig.org
-
-# top-most EditorConfig file
-root = true
-
-# Unix-style newlines with a newline ending every file
-[*]
-charset = utf-8
-end_of_line = lf
-insert_final_newline = true
-
-[*.{c,cpp,h}]
-indent_style = space
-indent_size = 4
-trim_trailing_whitespace = true
-insert_final_newline = true
-max_line_length = 80
-
-# Matches multiple files with brace expansion notation
-# Set default charset
-[*.{js,py}]
-charset = utf-8
-
-# 4 space indentation
-[*.py]
-indent_style = space
-indent_size = 4
-
-# Tab indentation (no size specified)
-[Makefile]
-indent_style = tab
-
-# Indentation override for all JS under lib directory
-[lib/**.js]
-indent_style = space
-indent_size = 2
-
-# Matches the exact files either package.json or .travis.yml
-[{package.json,.travis.yml}]
-indent_style = space
-indent_size = 2
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index b2321cf..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.old
-cmake-build-debug
-
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
deleted file mode 100644
index 63bab94..0000000
--- a/.vscode/c_cpp_properties.json
+++ /dev/null
@@ -1,101 +0,0 @@
-{
-    "configurations": [
-        {
-            "name": "Linux",
-            "includePath": [
-                "/usr/include",
-                "/opt/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/5.2.0",
-                "/opt/xtensa-esp32-elf/lib/gcc/xtensa-esp32-elf/5.2.0/include",
-                "${IDF_PATH}",
-                "${IDF_PATH}/components/esp32/include",
-                "${IDF_PATH}/components/newlib/include",
-                "${IDF_PATH}/components/freertos/include",
-                "${IDF_PATH}/components/nvs_flash/include",
-                "${IDF_PATH}/components/driver/include",
-                "${IDF_PATH}/components/log/include",
-                "${IDF_PATH}/components/tcpip_adapter/include",
-                "${IDF_PATH}/components/lwip/include/lwip",
-                "${IDF_PATH}/components/vfs/include",
-                "${IDF_PATH}/components/spi_flash/include",
-                "${IDF_PATH}/components/mbedtls/include",
-                "${IDF_PATH}/components/mdns/include",
-                "${IDF_PATH}/components/json/include",
-                "${IDF_PATH}/components/bt/include",
-                "${IDF_PATH}/components/bt/bluedroid/bta/include",
-                "${IDF_PATH}/components/bt/bluedroid/bta/sys/include",
-                "${IDF_PATH}/components/bt/bluedroid/btcore/include",
-                "${IDF_PATH}/components/bt/bluedroid/device/include",
-                "${IDF_PATH}/components/bt/bluedroid/gki/include",
-                "${IDF_PATH}/components/bt/bluedroid/hci/include",
-                "${IDF_PATH}/components/bt/bluedroid/osi/include",
-                "${IDF_PATH}/components/bt/bluedroid/btc/profile/esp/blufi/include",
-                "${IDF_PATH}/components/bt/bluedroid/btc/profile/esp/include",
-                "${IDF_PATH}/components/bt/bluedroid/btc/profile/std/sdp/include",
-                "${IDF_PATH}/components/bt/bluedroid/btc/profile/std/include",
-                "${IDF_PATH}/components/bt/bluedroid/stack/include",
-                "${IDF_PATH}/components/bt/bluedroid/stack/l2cap/include",
-                "${IDF_PATH}/components/bt/bluedroid/stack/sdp/include",
-                "${IDF_PATH}/components/bt/bluedroid/stack/smp/include",
-                "${IDF_PATH}/components/bt/bluedroid/api/include",
-                "${IDF_PATH}/components/bt/bluedroid/btc/include",
-                "${IDF_PATH}/components/soc/esp32/include",
-                "${IDF_PATH}/components/aws_iot/include",
-                "${IDF_PATH}/components/aws_iot/aws-iot-device-sdk-embedded-C/include",
-                "${IDF_PATH}/components/fatfs/src",
-                "${IDF_PATH}/components/wear_levelling/include",
-                "${workspaceRoot}",
-                "${workspaceRoot}/main",
-                "${workspaceRoot}/components/cpp_utils"
-            ],
-            "browse": {
-                "limitSymbolsToIncludedHeaders": true,
-                "databaseFilename": "",
-                "path": [
-                    "/usr/include",
-                    "/opt/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/5.2.0",
-                    "/opt/xtensa-esp32-elf/lib/gcc/xtensa-esp32-elf/5.2.0/include",
-                    "${IDF_PATH}",
-                    "${IDF_PATH}/components/esp32/include",
-                    "${IDF_PATH}/components/newlib/include",
-                    "${IDF_PATH}/components/freertos/include",
-                    "${IDF_PATH}/components/nvs_flash/include",
-                    "${IDF_PATH}/components/driver/include",
-                    "${IDF_PATH}/components/log/include",
-                    "${IDF_PATH}/components/tcpip_adapter/include",
-                    "${IDF_PATH}/components/lwip/include/lwip",
-                    "${IDF_PATH}/components/vfs/include",
-                    "${IDF_PATH}/components/spi_flash/include",
-                    "${IDF_PATH}/components/mbedtls/include",
-                    "${IDF_PATH}/components/mdns/include",
-                    "${IDF_PATH}/components/json/include",
-                    "${IDF_PATH}/components/bt/include",
-                    "${IDF_PATH}/components/bt/bluedroid/bta/include",
-                    "${IDF_PATH}/components/bt/bluedroid/bta/sys/include",
-                    "${IDF_PATH}/components/bt/bluedroid/btcore/include",
-                    "${IDF_PATH}/components/bt/bluedroid/device/include",
-                    "${IDF_PATH}/components/bt/bluedroid/gki/include",
-                    "${IDF_PATH}/components/bt/bluedroid/hci/include",
-                    "${IDF_PATH}/components/bt/bluedroid/osi/include",
-                    "${IDF_PATH}/components/bt/bluedroid/btc/profile/esp/blufi/include",
-                    "${IDF_PATH}/components/bt/bluedroid/btc/profile/esp/include",
-                    "${IDF_PATH}/components/bt/bluedroid/btc/profile/std/sdp/include",
-                    "${IDF_PATH}/components/bt/bluedroid/btc/profile/std/include",
-                    "${IDF_PATH}/components/bt/bluedroid/stack/include",
-                    "${IDF_PATH}/components/bt/bluedroid/stack/l2cap/include",
-                    "${IDF_PATH}/components/bt/bluedroid/stack/sdp/include",
-                    "${IDF_PATH}/components/bt/bluedroid/stack/smp/include",
-                    "${IDF_PATH}/components/bt/bluedroid/api/include",
-                    "${IDF_PATH}/components/bt/bluedroid/btc/include",
-                    "${IDF_PATH}/components/soc/esp32/include",
-                    "${IDF_PATH}/components/aws_iot/include",
-                    "${IDF_PATH}/components/aws_iot/aws-iot-device-sdk-embedded-C/include",
-                    "${IDF_PATH}/components/fatfs/src",
-                    "${IDF_PATH}/components/wear_levelling/include",
-                    "${workspaceRoot}"
-                ]
-            },
-            "intelliSenseMode": "clang-x64"
-        }
-    ],
-    "version": 2
-}
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index 69555ae..0000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "version": "0.2.0",
-    "configurations": [
-        
-        {
-            "name": "Debug",
-            "gdbpath": "/Users/alxs/Development/Workspaces/espressif/esp/xtensa-esp32-elf/bin/xtensa-esp32-elf-gdb",
-            "type": "gdb",
-            "request": "attach",
-            "executable" : "${workspaceRoot}/build/gcc-tutorial.elf",
-            "target": "/dev/tty.SLAB_USBtoUART",
-            "remote": true,
-            "cwd": "${workspaceRoot}"
-        }
-    ]
-}
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index da445d6..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-    "files.associations": {
-        "string": "cpp",
-        "*.tcc": "cpp"
-    }
-}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
deleted file mode 100644
index 15301f1..0000000
--- a/.vscode/tasks.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-    "version": "0.1.0",
-    "command": "bash",
-    "args": ["-c"],
-    "isShellCommand": true,
-    "showOutput": "always",
-    "suppressTaskName": true,
-    "options": {
-        "cwd": "${workspaceRoot}",
-        "env": { 
-            "IDF_PATH" : "/Users/alxs/Development/workspaces/espressif/esp/esp-idf", 
-            "PATH" : "${env:PATH}:/Users/alxs/Development/Workspaces/espressif/esp/xtensa-esp32-elf/bin" 
-        }
-    },
-    "tasks": [
-        {
-            "taskName": "build app",
-            "args": ["make app"],
-            "isBuildCommand": true,
-            "problemMatcher": {
-                "owner": "cpp",
-                "fileLocation": ["relative", "${workspaceRoot}"],
-                "pattern": {
-                    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
-                    "file": 1,
-                    "line": 2,
-                    "column": 3,
-                    "severity": 4,
-                    "message": 5
-                }
-            }
-        },
-        {
-            "taskName": "clean app",
-            "args": ["make app-clean"]
-        },
-        {
-            "taskName": "monitor",
-            "args": ["make monitor"]
-        },
-        {
-            "taskName": "flash app",
-            "args": ["make app-flash"]
-        }
-    ]
-}
diff --git a/components/bme280/BME280.cpp b/BME280.cpp
similarity index 100%
rename from components/bme280/BME280.cpp
rename to BME280.cpp
diff --git a/components/bme280/BME280.h b/BME280.h
similarity index 100%
rename from components/bme280/BME280.h
rename to BME280.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644
index 117094f..0000000
--- a/CMakeLists.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-PROJECT(esp32-bme280 C CXX ASM)
-set(CMAKE_VERBOSE_MAKEFILE on)
-
-CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
-ENABLE_LANGUAGE(ASM)
-
-set(CMAKE_VERBOSE_MAKEFILE on)
-
-SET(IDF_PATH $ENV{IDF_PATH})
-
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
-
-file(GLOB_RECURSE USER_SOURCES "main/*.c" "main/*.cpp" "components/*.cpp" "components/*.c")
-
-ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}.elf ${USER_SOURCES} ${PROJECT_SOURCES} ${CMSIS_SOURCES} ${STM32HAL_SOURCES})
-
-INCLUDE_DIRECTORIES(
-        ${CMAKE_CURRENT_SOURCE_DIR}
-        ${CMSIS_INCLUDE_DIRS}
-        ${STM32HAL_INCLUDE_DIR}
-        components/cpp_utils
-        components/bme280
-        "/usr/include"
-        "/opt/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/5.2.0"
-        "/opt/xtensa-esp32-elf/lib/gcc/xtensa-esp32-elf/5.2.0/include"
-        "${IDF_PATH}"
-        "${IDF_PATH}/components/esp32/include"
-        "${IDF_PATH}/components/newlib/include"
-        "${IDF_PATH}/components/freertos/include"
-        "${IDF_PATH}/components/nvs_flash/include"
-        "${IDF_PATH}/components/driver/include"
-        "${IDF_PATH}/components/log/include"
-        "${IDF_PATH}/components/tcpip_adapter/include"
-        "${IDF_PATH}/components/lwip/include/lwip"
-        "${IDF_PATH}/components/vfs/include"
-        "${IDF_PATH}/components/spi_flash/include"
-        "${IDF_PATH}/components/mbedtls/include"
-        "${IDF_PATH}/components/mdns/include"
-        "${IDF_PATH}/components/json/include"
-        "${IDF_PATH}/components/bt/include"
-        "${IDF_PATH}/components/bt/bluedroid/bta/include"
-        "${IDF_PATH}/components/bt/bluedroid/bta/sys/include"
-        "${IDF_PATH}/components/bt/bluedroid/btcore/include"
-        "${IDF_PATH}/components/bt/bluedroid/device/include"
-        "${IDF_PATH}/components/bt/bluedroid/gki/include"
-        "${IDF_PATH}/components/bt/bluedroid/hci/include"
-        "${IDF_PATH}/components/bt/bluedroid/osi/include"
-        "${IDF_PATH}/components/bt/bluedroid/btc/profile/esp/blufi/include"
-        "${IDF_PATH}/components/bt/bluedroid/btc/profile/esp/include"
-        "${IDF_PATH}/components/bt/bluedroid/btc/profile/std/sdp/include"
-        "${IDF_PATH}/components/bt/bluedroid/btc/profile/std/include"
-        "${IDF_PATH}/components/bt/bluedroid/stack/include"
-        "${IDF_PATH}/components/bt/bluedroid/stack/l2cap/include"
-        "${IDF_PATH}/components/bt/bluedroid/stack/sdp/include"
-        "${IDF_PATH}/components/bt/bluedroid/stack/smp/include"
-        "${IDF_PATH}/components/bt/bluedroid/api/include"
-        "${IDF_PATH}/components/bt/bluedroid/btc/include"
-        "${IDF_PATH}/components/soc/esp32/include"
-        "${IDF_PATH}/components/aws_iot/include"
-        "${IDF_PATH}/components/aws_iot/aws-iot-device-sdk-embedded-C/include"
-        "${IDF_PATH}/components/fatfs/src"
-        "${IDF_PATH}/components/wear_levelling/include"
-)
-
-add_custom_target(esp32-bme280 COMMAND make -C ${esp32-bme280_SOURCE_DIR}
-        CLION_EXE_DIR=${PROJECT_BINARY_DIR})
diff --git a/components/cpp_utils/I2C.cpp b/I2C.cpp
similarity index 100%
rename from components/cpp_utils/I2C.cpp
rename to I2C.cpp
diff --git a/components/cpp_utils/I2C.h b/I2C.h
similarity index 100%
rename from components/cpp_utils/I2C.h
rename to I2C.h
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 58f27fc..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "{}"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright {2017} {Alexander Sparkowsky}
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/Makefile b/Makefile
deleted file mode 100644
index e86d6ac..0000000
--- a/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# This is a project Makefile. It is assumed the directory this Makefile resides in is a
-# project subdirectory.
-#
-
-PROJECT_NAME := esp32-bme280
-
-include $(IDF_PATH)/make/project.mk
-
-#all:
-#    echo Compiling $(CLION_EXE_DIR)/$@ ...
-#    g++ mytest.cpp -o $(CLION_EXE_DIR)/esp32-bme280
diff --git a/components/bme280/component.mk b/component.mk
similarity index 100%
rename from components/bme280/component.mk
rename to component.mk
diff --git a/components/cpp_utils/.gitignore b/components/cpp_utils/.gitignore
deleted file mode 100644
index 6e68499..0000000
--- a/components/cpp_utils/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/docs/
diff --git a/components/cpp_utils/AWS.cpp b/components/cpp_utils/AWS.cpp
deleted file mode 100644
index 561162c..0000000
--- a/components/cpp_utils/AWS.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * AWS.cpp
- *
- *  Created on: May 31, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#ifdef CONFIG_AWS_IOT_SDK
-#include <esp_log.h>
-#include "AWS.h"
-#include <string>
-
-static char tag[] = "AWS";
-
-AWS::AWS() {
-}
-
-
-AWS::~AWS() {
-}
-
-
-/**
- * @brief Connect to the AWS IoT service.
- * Connect to the AWT IoT service.
- * @param [in] The client id.
- * @return N/A.
- */
-void AWS::connect(std::string clientId) {
-	IoT_Client_Connect_Params connectParams = iotClientConnectParamsDefault;
-	connectParams.keepAliveIntervalInSec = 10;
-	connectParams.isCleanSession   = true;
-	connectParams.MQTTVersion      = MQTT_3_1_1;
-	connectParams.isWillMsgPresent = false;
-	connectParams.pClientID        = clientId.c_str();
-	connectParams.clientIDLen      = clientId.length();
-
-	IoT_Error_t err = ::aws_iot_mqtt_connect(&m_client, &connectParams);
-	if (err != SUCCESS) {
-		ESP_LOGD(tag, "aws_iot_mqtt_connect: error=%d", err);
-	}
-} // connect
-
-
-/**
- * @brief Disconnect a previously formed connection.
- * Disconnect from the AWT IoT service.
- * @return N/A.
- */
-void AWS::disconnect() {
-	IoT_Error_t err = ::aws_iot_mqtt_disconnect(&m_client);
-	if (err != SUCCESS) {
-		ESP_LOGD(tag, "aws_iot_mqtt_disconnect: error=%d", err);
-	}
-} // disconnect
-
-
-/**
- * @brief Initialize our connection.
- * @param [in] host The the host of the AWS IoT service.
- * @param [in] port The port number of the AWS IoT service.
- * @return N/A.
- */
-void AWS::init(std::string host, uint16_t port) {
-	IoT_Client_Init_Params initParams = iotClientInitParamsDefault;
-
-	initParams.pHostURL                  = (char *)host.c_str();
-	initParams.port                      = port;
-	initParams.pRootCALocation           = nullptr;
-	initParams.pDeviceCertLocation       = nullptr;
-	initParams.pDevicePrivateKeyLocation = nullptr;
-	initParams.mqttCommandTimeout_ms     = 20000;
-	initParams.tlsHandshakeTimeout_ms    = 5000;
-	initParams.isSSLHostnameVerify       = true;
-
-	IoT_Error_t err = ::aws_iot_mqtt_init(&m_client, &initParams);
-	if (err != SUCCESS) {
-		ESP_LOGD(tag, "aws_iot_mqtt_init: error=%d", err);
-	}
-} // init
-
-
-/**
- * @brief Publish a message.
- * Publish a message on the given topic.
- *
- * @param [in] topic The topic against which we wish to publish.
- * @param [in] payload The payload of the message we wish to publish.
- * @param [in] qos The quality of service for the publish.
- * @return N/A.
- */
-void AWS::publish(std::string topic, std::string payload, QoS qos) {
-	IoT_Publish_Message_Params message;
-	message.payload = (void *)payload.data();
-	message.payloadLen = payload.length();
-	message.qos = qos;
-	message.isRetained = 0;
-	IoT_Error_t err = ::aws_iot_mqtt_publish(&m_client, topic.c_str(), topic.length(), &message);
-	if (err != SUCCESS) {
-		ESP_LOGD(tag, "aws_iot_mqtt_publish: error=%d", err);
-	}
-} // publish
-
-
-/**
- * @brief Subscribe to a topic.
- * Future publications on this topic will be delivered to us.
- * @param [in] topic The topic against which we wish to subscribe.
- * @return N/A.
- */
-void AWS::subscribe(std::string topic) {
-	pApplicationHandler_t iot_subscribe_callback_handler = nullptr;
-	IoT_Error_t err = ::aws_iot_mqtt_subscribe(&m_client, topic.c_str(), topic.length(), QOS0, iot_subscribe_callback_handler, NULL);
-	if (err != SUCCESS) {
-		ESP_LOGD(tag, "aws_iot_mqtt_subscribe: error=%d", err);
-	}
-} // subscribe
-
-
-/**
- * @brief Un-subscribe from a previous subscription.
- * Further publications on this topic will no longer be delivered to us.
- * @param [in] topic The topic to un-subscribe from.
- * @return N/A.
- */
-void AWS::unsubscribe(std::string topic) {
-	IoT_Error_t err = ::aws_iot_mqtt_unsubscribe(&m_client, topic.c_str(), topic.length());
-	if (err != SUCCESS) {
-		ESP_LOGD(tag, "aws_iot_mqtt_unsubscribe: error=%d", err);
-	}
-} // unsubscribe
-#endif // CONFIG_AWS_IOT_SDK
diff --git a/components/cpp_utils/AWS.h b/components/cpp_utils/AWS.h
deleted file mode 100644
index 5d2c891..0000000
--- a/components/cpp_utils/AWS.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * AWS.h
- *
- *  Created on: May 31, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_AWS_H_
-#define COMPONENTS_AWS_H_
-#include "sdkconfig.h"
-#ifdef CONFIG_AWS_IOT_SDK
-
-#include <aws_iot_mqtt_client_interface.h>
-#include <aws_iot_mqtt_client.h>
-#include <string>
-
-/**
- * @brief AWS IoT access.
- */
-class AWS {
-public:
-	AWS();
-	virtual ~AWS();
-
-	void connect(std::string clientId);
-	void disconnect();
-	void init(std::string host=CONFIG_AWS_IOT_MQTT_HOST, uint16_t port=CONFIG_AWS_IOT_MQTT_PORT);
-	void publish(std::string topic, std::string payload, QoS qos = QOS0);
-	void subscribe(std::string topic);
-	void unsubscribe(std::string topic);
-
-private:
-	AWS_IoT_Client m_client;
-};
-#endif // CONFIG_AWS_IOT_SDK
-#endif /* COMPONENTS_AWS_H_ */
diff --git a/components/cpp_utils/ArduinoBLE.md b/components/cpp_utils/ArduinoBLE.md
deleted file mode 100644
index a2cb3be..0000000
--- a/components/cpp_utils/ArduinoBLE.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Arduino BLE Support
-As part of this Github project, we provide libraries for Bluetooth Low Energy (BLE) for the ESP32 Arduino environment.  Support for this capability is still in the process of being cooked (as of September 2017).  As such you should not build product based on these functions as changes to the API and implementation are extremely likely over the next couple of months.
-
-That said, we now have the ability to produce a driver you can use for testing.  This will give you early access to the function while give those who choose to build and maintain the code early feedback on what works, what doesn't and what can be improved from a usage perspective.
-
-When complete, the BLE support for ESP32 Arduino will be available as a single ZIP file.  The file will be called **ESP32_BLE.zip**.  It is this file that will be able to be imported into the Arduino IDE from the `Sketch -> Include Library -> Add .ZIP library`.  When initial development of the library has been completed, this ZIP will be placed under some form of release control so that an ordinary Arduino IDE user can simply download this as a unit and install.
-
-We provide sample builds of the `ESP32_BLE.zip` file in the `Arduino` folder found relative to this directory.
-
-The build of the Arduino support will be current as of the date of the ZIP file however should you wish to build your own instance of the ZIP from the source, here is the recipe.
-
-1. Create a new directory called `build`
-2. Enter that directory and run `git clone https://github.com/nkolban/esp32-snippets.git`
-3. Change into the directory called  `./esp32_snippets/cpp_utils`
-4. Run `make -f Makefile.arduino build_ble`
-5. Change into the directory called `./Arduino`
-
-And here you will find the `ESP32_BLE.zip` that is build from the latest source.  You can then install this into your Arduino IDE environment are you are ready to go.
-
-
-## Installing a new version
-If you have previously installed a version of the Arduino BLE Support and need to install a new one, follow the steps above to build yourself a new instance of the `ESP32_BLE.zip` that is ready for installation.  I recommend removing the old one before installing the new one.  To remove the old one, find the directory where the Arduino IDE stores your libraries (on Linux this is commonly `$HOME/Arduino`).  In there you will find a directory called `libraries` and, if you have previously installed the BLE support, you will find a directory called `ESP32_BLE`.  Remove that directory.
-
-## Switching on debugging
-The BLE support contains extensive internal diagnostics which can be switched on by editing the file called `sdkconfig.h` and finding the lines which read:
-
-```
-#define CONFIG_LOG_DEFAULT 1
-```
-
-Change this to:
-
-```
-#define CONFIG_LOG_DEFAULT 5
-```
-
-and rebuild/deploy your project.
-
-This file can be found in your Arduino IDE installation directories at:
-
-```
-<ArduinoIDE>/hardware/espressif/esp32/tools/sdk/include/config
-```
\ No newline at end of file
diff --git a/components/cpp_utils/Arduino_ESP32_BLE.library.properties b/components/cpp_utils/Arduino_ESP32_BLE.library.properties
deleted file mode 100644
index e8fe280..0000000
--- a/components/cpp_utils/Arduino_ESP32_BLE.library.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-name=ESP32_BLE
-version=1.0
-author=Neil Kolban <kolban1@kolban.com>
-maintainer=Neil Kolban <kolban1@kolban.com>
-sentence=BLE functions for ESP32
-paragraph=BLE functions for ESP32
-category=Communication
-url=http://example.com/
-architectures=esp32
-includes=BLE.h BLEUtils.h BLEScan.h BLEAdvertisedDevice.h
\ No newline at end of file
diff --git a/components/cpp_utils/BLE2902.cpp b/components/cpp_utils/BLE2902.cpp
deleted file mode 100644
index 8984da8..0000000
--- a/components/cpp_utils/BLE2902.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * BLE2902.cpp
- *
- *  Created on: Jun 25, 2017
- *      Author: kolban
- */
-
-/*
- * See also:
- * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include "BLE2902.h"
-
-BLE2902::BLE2902() : BLEDescriptor(BLEUUID((uint16_t) 0x2902)) {
-	uint8_t data[2] = {0,0};
-	setValue(data, 2);
-} // BLE2902
-
-
-/**
- * @brief Get the notifications value.
- * @return The notifications value.  True if notifications are enabled and false if not.
- */
-bool BLE2902::getNotifications() {
-	return (getValue()[0] & (1 << 0)) != 0;
-} // getNotifications
-
-
-/**
- * @brief Get the indications value.
- * @return The indications value.  True if indications are enabled and false if not.
- */
-bool BLE2902::getIndications() {
-	return (getValue()[0] & (1 << 1)) != 0;
-} // getIndications
-
-
-/**
- * @brief Set the indications flag.
- * @param [in] flag The indications flag.
- */
-void BLE2902::setIndications(bool flag) {
-	uint8_t *pValue = getValue();
-	if (flag) {
-		pValue[0] |= 1<<1;
-	} else {
-		pValue[0] &= ~(1<<1);
-	}
-} // setIndications
-
-
-/**
- * @brief Set the notifications flag.
- * @param [in] flag The notifications flag.
- */
-void BLE2902::setNotifications(bool flag) {
-	uint8_t *pValue = getValue();
-	if (flag) {
-		pValue[0] |= 1<<0;
-	} else {
-		pValue[0] &= ~(1<<0);
-	}
-} // setNotifications
-
-
-#endif
diff --git a/components/cpp_utils/BLE2902.h b/components/cpp_utils/BLE2902.h
deleted file mode 100644
index 397360a..0000000
--- a/components/cpp_utils/BLE2902.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * BLE2902.h
- *
- *  Created on: Jun 25, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLE2902_H_
-#define COMPONENTS_CPP_UTILS_BLE2902_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include "BLEDescriptor.h"
-
-/**
- * @brief Descriptor for Client Characteristic Configuration.
- *
- * This is a convenience descriptor for the Client Characteristic Configuration which has a UUID of 0x2902.
- *
- * See also:
- * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
- */
-class BLE2902: public BLEDescriptor {
-public:
-	BLE2902();
-	bool getNotifications();
-	bool getIndications();
-	void setNotifications(bool flag);
-	void setIndications(bool flag);
-
-}; // BLE2902
-
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLE2902_H_ */
diff --git a/components/cpp_utils/BLEAddress.cpp b/components/cpp_utils/BLEAddress.cpp
deleted file mode 100644
index d2f7f8b..0000000
--- a/components/cpp_utils/BLEAddress.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * BLEAddress.cpp
- *
- *  Created on: Jul 2, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include "BLEAddress.h"
-#include <string>
-#include <sstream>
-#include <iomanip>
-#include <string.h>
-#include <stdio.h>
-
-
-/**
- * @brief Create an address from the native ESP32 representation.
- * @param [in] address The native representation.
- */
-BLEAddress::BLEAddress(esp_bd_addr_t address) {
-	memcpy(m_address, address, ESP_BD_ADDR_LEN);
-} // BLEAddress
-
-
-/**
- * @brief Create an address from a hex string
- *
- * A hex string is of the format:
- * ```
- * 00:00:00:00:00:00
- * ```
- * which is 17 characters in length.
- *
- * @param [in] stringAddress The hex representation of the address.
- */
-BLEAddress::BLEAddress(std::string stringAddress) {
-	if (stringAddress.length() != 17) {
-		return;
-	}
-	int data[6];
-	sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5]);
-	m_address[0] = (uint8_t)data[0];
-	m_address[1] = (uint8_t)data[1];
-	m_address[2] = (uint8_t)data[2];
-	m_address[3] = (uint8_t)data[3];
-	m_address[4] = (uint8_t)data[4];
-	m_address[5] = (uint8_t)data[5];
-} // BLEAddress
-
-
-/**
- * @brief Determine if this address equals another.
- * @param [in] otherAddress The other address to compare against.
- * @return True if the addresses are equal.
- */
-bool BLEAddress::equals(BLEAddress otherAddress) {
-	return memcmp(otherAddress.getNative(), m_address, 6) == 0;
-} // equals
-
-
-/**
- * @brief Return the native representation of the address.
- * @return The native representation of the address.
- */
-esp_bd_addr_t *BLEAddress::getNative() {
-	return &m_address;
-} // getNative
-
-
-/**
- * @brief Convert a BLE address to a string.
- *
- * A string representation of an address is in the format:
- *
- * ```
- * xx:xx:xx:xx:xx:xx
- * ```
- *
- * @return The string representation of the address.
- */
-std::string BLEAddress::toString() {
-	std::stringstream stream;
-	stream << std::setfill('0') << std::setw(2) << std::hex << (int)((uint8_t *)(m_address))[0] << ':';
-	stream << std::setfill('0') << std::setw(2) << std::hex << (int)((uint8_t *)(m_address))[1] << ':';
-	stream << std::setfill('0') << std::setw(2) << std::hex << (int)((uint8_t *)(m_address))[2] << ':';
-	stream << std::setfill('0') << std::setw(2) << std::hex << (int)((uint8_t *)(m_address))[3] << ':';
-	stream << std::setfill('0') << std::setw(2) << std::hex << (int)((uint8_t *)(m_address))[4] << ':';
-	stream << std::setfill('0') << std::setw(2) << std::hex << (int)((uint8_t *)(m_address))[5];
-	return stream.str();
-} // toString
-#endif
diff --git a/components/cpp_utils/BLEAddress.h b/components/cpp_utils/BLEAddress.h
deleted file mode 100644
index 7eff4da..0000000
--- a/components/cpp_utils/BLEAddress.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * BLEAddress.h
- *
- *  Created on: Jul 2, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEADDRESS_H_
-#define COMPONENTS_CPP_UTILS_BLEADDRESS_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_gap_ble_api.h> // ESP32 BLE
-#include <string>
-
-
-/**
- * @brief A %BLE device address.
- *
- * Every %BLE device has a unique address which can be used to identify it and form connections.
- */
-class BLEAddress {
-public:
-	BLEAddress(esp_bd_addr_t address);
-	BLEAddress(std::string stringAddress);
-	bool           equals(BLEAddress otherAddress);
-	esp_bd_addr_t* getNative();
-	std::string    toString();
-
-private:
-	esp_bd_addr_t m_address;
-};
-
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLEADDRESS_H_ */
diff --git a/components/cpp_utils/BLEAdvertisedDevice.cpp b/components/cpp_utils/BLEAdvertisedDevice.cpp
deleted file mode 100644
index 97ec1e3..0000000
--- a/components/cpp_utils/BLEAdvertisedDevice.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * BLEAdvertisedDevice.cpp
- *
- * During the scanning procedure, we will be finding advertised BLE devices.  This class
- * models a found device.
- *
- *
- * See also:
- * https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
- *
- *  Created on: Jul 3, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_log.h>
-#include <sstream>
-#include "BLEAdvertisedDevice.h"
-#include "BLEUtils.h"
-static const char* LOG_TAG="BLEAdvertisedDevice";
-
-BLEAdvertisedDevice::BLEAdvertisedDevice() {
-	m_adFlag           = 0;
-	m_appearance       = 0;
-	m_deviceType       = 0;
-	m_manufacturerData = "";
-	m_name             = "";
-	m_rssi             = -9999;
-	m_txPower          = 0;
-	m_pScan            = nullptr;
-
-	m_haveAppearance       = false;
-	m_haveManufacturerData = false;
-	m_haveName             = false;
-	m_haveRSSI             = false;
-	m_haveServiceUUID      = false;
-	m_haveTXPower          = false;
-
-} // BLEAdvertisedDevice
-
-
-/**
- * @brief Get the address.
- *
- * Every %BLE device exposes an address that is used to identify it and subsequently connect to it.
- * Call this function to obtain the address of the advertised device.
- *
- * @return The address of the advertised device.
- */
-BLEAddress BLEAdvertisedDevice::getAddress() {
-	return m_address;
-} // getAddress
-
-
-/**
- * @brief Get the appearance.
- *
- * A %BLE device can declare its own appearance.  The appearance is how it would like to be shown to an end user
- * typcially in the form of an icon.
- *
- * @return The appearance of the advertised device.
- */
-uint16_t BLEAdvertisedDevice::getApperance() {
-	return m_appearance;
-}
-
-
-/**
- * @brief Get the manufacturer data.
- * @return The manufacturer data of the advertised device.
- */
-std::string BLEAdvertisedDevice::getManufacturerData() {
-	return m_manufacturerData;
-}
-
-
-/**
- * @brief Get the name.
- * @return The name of the advertised device.
- */
-std::string BLEAdvertisedDevice::getName() {
-	return m_name;
-} // getName
-
-
-/**
- * @brief Get the RSSI.
- * @return The RSSI of the advertised device.
- */
-int BLEAdvertisedDevice::getRSSI() {
-	return m_rssi;
-} // getRSSI
-
-
-/**
- * @brief Get the scan object that created this advertisement.
- * @return The scan object.
- */
-BLEScan* BLEAdvertisedDevice::getScan() {
-	return m_pScan;
-} // getScan
-
-
-/**
- * @brief Get the Service UUID.
- * @return The Service UUID of the advertised device.
- */
-BLEUUID BLEAdvertisedDevice::getServiceUUID() {
-	return m_serviceUUID;
-} // getServiceUUID
-
-
-/**
- * @brief Get the TX Power.
- * @return The TX Power of the advertised device.
- */
-int8_t BLEAdvertisedDevice::getTXPower() {
-	return m_txPower;
-} // getTXPower
-
-/**
- * @brief Does this advertisement have an appearance value?
- * @return True if there is an appearance value present.
- */
-bool BLEAdvertisedDevice::haveAppearance() {
-	return m_haveAppearance;
-} // haveAppearance
-
-
-/**
- * @brief Does this advertisement have manufacturer data?
- * @return True if there is manufacturer data present.
- */
-bool BLEAdvertisedDevice::haveManufacturerData() {
-	return m_haveManufacturerData;
-} // haveManufacturerData
-
-
-/**
- * @brief Does this advertisement have a name value?
- * @return True if there is a name value present.
- */
-bool BLEAdvertisedDevice::haveName() {
-	return m_haveName;
-} // haveName
-
-
-/**
- * @brief Does this advertisement have a signal strength value?
- * @return True if there is a signal strength value present.
- */
-bool BLEAdvertisedDevice::haveRSSI() {
-	return m_haveRSSI;
-} // haveRSSI
-
-
-/**
- * @brief Does this advertisement have a service UUID value?
- * @return True if there is a service UUID value present.
- */
-bool BLEAdvertisedDevice::haveServiceUUID() {
-	return m_haveServiceUUID;
-} // haveServiceUUID
-
-
-/**
- * @brief Does this advertisement have a transmission power value?
- * @return True if there is a transmission power value present.
- */
-bool BLEAdvertisedDevice::haveTXPower() {
-	return m_haveTXPower;
-} // haveTXPower
-
-
-/**
- * @brief Parse the advertising pay load.
- *
- * The pay load is a buffer of bytes that is either 31 bytes long or terminated by
- * a 0 length value.  Each entry in the buffer has the format:
- * [length][type][data...]
- *
- * The length does not include itself but does include everything after it until the next record.  A record
- * with a length value of 0 indicates a terminator.
- *
- * https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
- */
-void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) {
-	uint8_t length;
-	uint8_t ad_type;
-	uint8_t sizeConsumed = 0;
-	bool finished = false;
-
-	while(!finished) {
-		length = *payload; // Retrieve the length of the record.
-		payload++; // Skip to type
-		sizeConsumed += 1 + length; // increase the size consumed.
-
-		if (length != 0) { // A length of 0 indicate that we have reached the end.
-			ad_type = *payload;
-			payload++;
-			length--;
-
-			char* pHex = BLEUtils::buildHexData(nullptr, payload, length);
-			ESP_LOGD(LOG_TAG, "Type: 0x%.2x (%s), length: %d, data: %s",
-					ad_type, BLEUtils::advTypeToString(ad_type), length, pHex);
-			free(pHex);
-
-
-
-			switch(ad_type) {
-				case ESP_BLE_AD_TYPE_NAME_CMPL: { // Adv Data Type: 0x09
-					setName(std::string(reinterpret_cast<char*>(payload), length));
-					break;
-				} // ESP_BLE_AD_TYPE_NAME_CMPL
-
-				case ESP_BLE_AD_TYPE_TX_PWR: { // Adv Data Type: 0x0A
-					setTXPower(*payload);
-					break;
-				} // ESP_BLE_AD_TYPE_TX_PWR
-
-				case ESP_BLE_AD_TYPE_APPEARANCE: { // Adv Data Type: 0x19
-					setAppearance(*reinterpret_cast<uint16_t*>(payload));
-					break;
-				} // ESP_BLE_AD_TYPE_APPEARANCE
-
-				case ESP_BLE_AD_TYPE_FLAG: { // Adv Data Type: 0x01
-					setAdFlag(*payload);
-					break;
-				} // ESP_BLE_AD_TYPE_FLAG
-
-				case ESP_BLE_AD_TYPE_16SRV_CMPL: { // Adv Data Type: 0x03
-					setServiceUUID(BLEUUID(*reinterpret_cast<uint16_t*>(payload)));
-					break;
-				} // ESP_BLE_AD_TYPE_16SRV_CMPL
-
-				case ESP_BLE_AD_TYPE_16SRV_PART: { // Adv Data Type: 0x02
-					setServiceUUID(BLEUUID(*reinterpret_cast<uint16_t*>(payload)));
-					break;
-				} // ESP_BLE_AD_TYPE_16SRV_PART
-
-				case ESP_BLE_AD_TYPE_32SRV_CMPL: { // Adv Data Type: 0x05
-					setServiceUUID(BLEUUID(*reinterpret_cast<uint32_t*>(payload)));
-					break;
-				} // ESP_BLE_AD_TYPE_32SRV_CMPL
-
-				case ESP_BLE_AD_TYPE_32SRV_PART: { // Adv Data Type: 0x04
-					setServiceUUID(BLEUUID(*reinterpret_cast<uint32_t*>(payload)));
-					break;
-				} // ESP_BLE_AD_TYPE_32SRV_PART
-
-				case ESP_BLE_AD_TYPE_128SRV_CMPL: { // Adv Data Type: 0x07
-					setServiceUUID(BLEUUID(payload, 16, false));
-					break;
-				} // ESP_BLE_AD_TYPE_128SRV_CMPL
-
-				case ESP_BLE_AD_TYPE_128SRV_PART: { // Adv Data Type: 0x06
-					setServiceUUID(BLEUUID(payload, 16, false));
-					break;
-				} // ESP_BLE_AD_TYPE_128SRV_PART
-
-				// See CSS Part A 1.4 Manufacturer Specific Data
-				case ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE: {
-					setManufacturerData(std::string(reinterpret_cast<char*>(payload), length));
-					break;
-				} // ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE
-
-				default: {
-					ESP_LOGD(LOG_TAG, "Unhandled type");
-					break;
-				}
-			} // switch
-			payload += length;
-		} // Length <> 0
-
-
-		if (sizeConsumed >=31 || length == 0) {
-			finished = true;
-		}
-	} // !finished
-} // parseAdvertisement
-
-
-/**
- * @brief Set the address of the advertised device.
- * @param [in] address The address of the advertised device.
- */
-void BLEAdvertisedDevice::setAddress(BLEAddress address) {
-	m_address = address;
-} // setAddress
-
-
-/**
- * @brief Set the adFlag for this device.
- * @param [in] The discovered adFlag.
- */
-void BLEAdvertisedDevice::setAdFlag(uint8_t adFlag) {
-	m_adFlag = adFlag;
-} // setAdFlag
-
-
-/**
- * @brief Set the appearance for this device.
- * @param [in] The discovered appearance.
- */
-void BLEAdvertisedDevice::setAppearance(uint16_t appearance) {
-	m_appearance     = appearance;
-	m_haveAppearance = true;
-	ESP_LOGD(LOG_TAG, "- appearance: %d", m_appearance);
-} // setAppearance
-
-
-/**
- * @brief Set the manufacturer data for this device.
- * @param [in] The discovered manufacturer data.
- */
-void BLEAdvertisedDevice::setManufacturerData(std::string manufacturerData) {
-	m_manufacturerData     = manufacturerData;
-	m_haveManufacturerData = true;
-	char* pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)m_manufacturerData.data(), (uint8_t)m_manufacturerData.length());
-	ESP_LOGD(LOG_TAG, "- manufacturer data: %s", pHex);
-	free(pHex);
-} // setManufacturerData
-
-
-/**
- * @brief Set the name for this device.
- * @param [in] name The discovered name.
- */
-void BLEAdvertisedDevice::setName(std::string name) {
-	m_name     = name;
-	m_haveName = true;
-	ESP_LOGD(LOG_TAG, "- name: %s", m_name.c_str());
-} // setName
-
-
-/**
- * @brief Set the RSSI for this device.
- * @param [in] rssi The discovered RSSI.
- */
-void BLEAdvertisedDevice::setRSSI(int rssi) {
-	m_rssi     = rssi;
-	m_haveRSSI = true;
-	ESP_LOGD(LOG_TAG, "- rssi: %d", m_rssi);
-} // setRSSI
-
-
-/**
- * @brief Set the Scan that created this advertised device.
- * @param pScan The Scan that created this advertised device.
- */
-void BLEAdvertisedDevice::setScan(BLEScan* pScan) {
-	m_pScan = pScan;
-} // setScan
-
-/**
- * @brief Set the Service UUID for this device.
- * @param [in] serviceUUID The discovered serviceUUID
- */
-void BLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
-	return setServiceUUID(BLEUUID(serviceUUID));
-} // setRSSI
-
-/**
- * @brief Set the Service UUID for this device.
- * @param [in] serviceUUID The discovered serviceUUID
- */
-void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
-	m_serviceUUID     = serviceUUID;
-	m_haveServiceUUID = true;
-	ESP_LOGD(LOG_TAG, "- serviceUUID: %s", serviceUUID.toString().c_str());
-} // setRSSI
-
-
-/**
- * @brief Set the power level for this device.
- * @param [in] txPower The discovered power level.
- */
-void BLEAdvertisedDevice::setTXPower(int8_t txPower) {
-	m_txPower     = txPower;
-	m_haveTXPower = true;
-	ESP_LOGD(LOG_TAG, "- txPower: %d", m_txPower);
-} // setTXPower
-
-
-/**
- * @brief Create a string representation of this device.
- * @return A string representation of this device.
- */
-std::string BLEAdvertisedDevice::toString() {
-	std::stringstream ss;
-	ss << "Name: " << getName() << ", Address: " << getAddress().toString();
-	if (haveAppearance()) {
-		ss << ", appearance: " << getApperance();
-	}
-	if (haveManufacturerData()) {
-		char *pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)getManufacturerData().data(), getManufacturerData().length());
-		ss << ", manufacturer data: " << pHex;
-		free(pHex);
-	}
-	if (haveServiceUUID()) {
-		ss << ", serviceUUID: " << getServiceUUID().toString();
-	}
-	if (haveTXPower()) {
-		ss << ", txPower: " << (int)getTXPower();
-	}
-	return ss.str();
-} // toString
-
-#endif /* CONFIG_BT_ENABLED */
-
diff --git a/components/cpp_utils/BLEAdvertisedDevice.h b/components/cpp_utils/BLEAdvertisedDevice.h
deleted file mode 100644
index 2fb2652..0000000
--- a/components/cpp_utils/BLEAdvertisedDevice.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * BLEAdvertisedDevice.h
- *
- *  Created on: Jul 3, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEADVERTISEDDEVICE_H_
-#define COMPONENTS_CPP_UTILS_BLEADVERTISEDDEVICE_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_gattc_api.h>
-
-#include <map>
-
-#include "BLEAddress.h"
-#include "BLEScan.h"
-#include "BLEUUID.h"
-
-
-class BLEScan;
-/**
- * @brief A representation of a %BLE advertised device found by a scan.
- *
- * When we perform a %BLE scan, the result will be a set of devices that are advertising.  This
- * class provides a model of a detected device.
- */
-class BLEAdvertisedDevice {
-public:
-	BLEAdvertisedDevice();
-
-	BLEAddress  getAddress();
-	uint16_t    getApperance();
-	std::string getManufacturerData();
-	std::string getName();
-	int         getRSSI();
-	BLEScan*    getScan();
-	BLEUUID     getServiceUUID();
-	int8_t      getTXPower();
-
-	bool        haveAppearance();
-	bool        haveManufacturerData();
-	bool        haveName();
-	bool        haveRSSI();
-	bool        haveServiceUUID();
-	bool        haveTXPower();
-
-	std::string toString();
-
-private:
-	friend class BLEScan;
-
-	void parseAdvertisement(uint8_t* payload);
-	void setAddress(BLEAddress address);
-	void setAdFlag(uint8_t adFlag);
-	void setAdvertizementResult(uint8_t* payload);
-	void setAppearance(uint16_t appearance);
-	void setManufacturerData(std::string manufacturerData);
-	void setName(std::string name);
-	void setRSSI(int rssi);
-	void setScan(BLEScan* pScan);
-	void setServiceUUID(const char* serviceUUID);
-	void setServiceUUID(BLEUUID serviceUUID);
-	void setTXPower(int8_t txPower);
-
-	bool m_haveAppearance;
-	bool m_haveManufacturerData;
-	bool m_haveName;
-	bool m_haveRSSI;
-	bool m_haveServiceUUID;
-	bool m_haveTXPower;
-
-
-	BLEAddress  m_address = BLEAddress((uint8_t*)"\0\0\0\0\0\0");
-	uint8_t     m_adFlag;
-	uint16_t    m_appearance;
-	int         m_deviceType;
-	std::string m_manufacturerData;
-	std::string m_name;
-	BLEScan*    m_pScan;
-	int         m_rssi;
-	BLEUUID     m_serviceUUID;
-	int8_t      m_txPower;
-};
-
-/**
- * @brief A callback handler for callbacks associated device scanning.
- *
- * When we are performing a scan as a %BLE client, we may wish to know when a new device that is advertising
- * has been found.  This class can be sub-classed and registered such that when a scan is performed and
- * a new advertised device has been found, we will be called back to be notified.
- */
-class BLEAdvertisedDeviceCallbacks {
-public:
-	virtual ~BLEAdvertisedDeviceCallbacks() {}
-	/**
-	 * @brief Called when a new scan result is detected.
-	 *
-	 * As we are scanning, we will find new devices.  When found, this call back is invoked with a reference to the
-	 * device that was found.  During any individual scan, a device will only be detected one time.
-	 */
-	virtual void onResult(BLEAdvertisedDevice advertisedDevice) = 0;
-};
-
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISEDDEVICE_H_ */
diff --git a/components/cpp_utils/BLEAdvertising.cpp b/components/cpp_utils/BLEAdvertising.cpp
deleted file mode 100644
index ad076dd..0000000
--- a/components/cpp_utils/BLEAdvertising.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * BLEAdvertising.cpp
- *
- * This class encapsulates advertising a BLE Server.
- *  Created on: Jun 21, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include "BLEAdvertising.h"
-#include <esp_log.h>
-#include <esp_err.h>
-#include "BLEUtils.h"
-#include "GeneralUtils.h"
-
-static const char* LOG_TAG = "BLEAdvertising";
-
-
-/**
- * @brief Construct a default advertising object.
- *
- */
-BLEAdvertising::BLEAdvertising() {
-	m_advData.set_scan_rsp        = false;
-	m_advData.include_name        = true;
-	m_advData.include_txpower     = true;
-	m_advData.min_interval        = 0x20;
-	m_advData.max_interval        = 0x40;
-	m_advData.appearance          = 0x00;
-	m_advData.manufacturer_len    = 0;
-	m_advData.p_manufacturer_data = nullptr;
-	m_advData.service_data_len    = 0;
-	m_advData.p_service_data      = nullptr;
-	m_advData.service_uuid_len    = 0;
-	m_advData.p_service_uuid      = nullptr;
-	m_advData.flag                = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT);
-
-	m_advParams.adv_int_min       = 0x20;
-	m_advParams.adv_int_max       = 0x40;
-	m_advParams.adv_type          = ADV_TYPE_IND;
-	m_advParams.own_addr_type     = BLE_ADDR_TYPE_PUBLIC;
-	m_advParams.channel_map       = ADV_CHNL_ALL;
-	m_advParams.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY;
-} // BLEAdvertising
-
-
-/**
- * @brief Set the device appearance in the advertising data.
- * The appearance attribute is of type 0x19.  The codes for distinct appearances can be found here:
- * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml.
- * @param [in] appearance The appearance of the device in the advertising data.
- * @return N/A.
- */
-void BLEAdvertising::setAppearance(uint16_t appearance) {
-	m_advData.appearance = appearance;
-} // setAppearance
-
-
-/**
- * @brief Set the service UUID.
- * We maintain a class member called m_advData (esp_ble_adv_data_t) that is passed to the
- * ESP-IDF advertising functions.  In this method, we see two fields within that structure
- * namely service_uuid_len and p_service_uuid to be the information supplied in the passed
- * in service uuid.
- * @param [in] uuid The UUID of the service.
- * @return N/A.
- */
-void BLEAdvertising::setServiceUUID(const char* serviceUUID) {
-	return setServiceUUID(BLEUUID(serviceUUID)); 
-}
-/**
- * @brief Set the service UUID.
- * We maintain a class member called m_advData (esp_ble_adv_data_t) that is passed to the
- * ESP-IDF advertising functions.  In this method, we see two fields within that structure
- * namely service_uuid_len and p_service_uuid to be the information supplied in the passed
- * in service uuid.
- * @param [in] uuid The UUID of the service.
- * @return N/A.
- */
-void BLEAdvertising::setServiceUUID(BLEUUID serviceUUID) {
-	ESP_LOGD(LOG_TAG, ">> setServiceUUID - %s", serviceUUID.toString().c_str());
-	m_serviceUUID = serviceUUID; // Save the new service UUID
-	esp_bt_uuid_t* espUUID = m_serviceUUID.getNative();
-	switch(espUUID->len) {
-		case ESP_UUID_LEN_16: {
-			m_advData.service_uuid_len = 2;
-			m_advData.p_service_uuid = reinterpret_cast<uint8_t*>(&espUUID->uuid.uuid16);
-			break;
-		}
-		case ESP_UUID_LEN_32: {
-			m_advData.service_uuid_len = 4;
-			m_advData.p_service_uuid = reinterpret_cast<uint8_t*>(&espUUID->uuid.uuid32);
-			break;
-		}
-		case ESP_UUID_LEN_128: {
-			m_advData.service_uuid_len = 16;
-			m_advData.p_service_uuid = reinterpret_cast<uint8_t*>(&espUUID->uuid.uuid128);
-			break;
-		}
-	} // switch
-	ESP_LOGD(LOG_TAG, "<< setServiceUUID");
-} // setServiceUUID
-
-
-/**
- * @brief Start advertising.
- * Start advertising.
- * @return N/A.
- */
-void BLEAdvertising::start() {
-	ESP_LOGD(LOG_TAG, ">> start");
-
-	if (m_advData.service_uuid_len > 0) {
-		uint8_t hexData[16*2+1];
-		BLEUtils::buildHexData(hexData, m_advData.p_service_uuid, m_advData.service_uuid_len);
-		ESP_LOGD(LOG_TAG, " - Service: service_uuid_len=%d, p_service_uuid=0x%x (data=%s)",
-			m_advData.service_uuid_len,
-			(uint32_t)m_advData.p_service_uuid,
-			(m_advData.service_uuid_len > 0?(char *)hexData:"N/A")
-		);
-	} // We have a service to advertise
-
-
-	// Set the configuration for advertising.
-	esp_err_t errRc = ::esp_ble_gap_config_adv_data(&m_advData);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< esp_ble_gap_config_adv_data: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	// Start advertising.
-	errRc = ::esp_ble_gap_start_advertising(&m_advParams);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< esp_ble_gap_start_advertising: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-	ESP_LOGD(LOG_TAG, "<< start");
-} // start
-
-
-/**
- * @brief Stop advertising.
- * Stop advertising.
- * @return N/A.
- */
-void BLEAdvertising::stop() {
-	ESP_LOGD(LOG_TAG, ">> stop");
-	esp_err_t errRc = ::esp_ble_gap_stop_advertising();
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gap_stop_advertising: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-	ESP_LOGD(LOG_TAG, "<< stop");
-} // stop
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLEAdvertising.h b/components/cpp_utils/BLEAdvertising.h
deleted file mode 100644
index 2d0b51c..0000000
--- a/components/cpp_utils/BLEAdvertising.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * BLEAdvertising.h
- *
- *  Created on: Jun 21, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEADVERTISING_H_
-#define COMPONENTS_CPP_UTILS_BLEADVERTISING_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_gap_ble_api.h>
-#include "BLEUUID.h"
-
-/**
- * @brief Perform and manage %BLE advertising.
- *
- * A %BLE server will want to perform advertising in order to make itself known to %BLE clients.
- */
-class BLEAdvertising {
-public:
-	BLEAdvertising();
-	void start();
-	void stop();
-	void setAppearance(uint16_t appearance);
-	void setServiceUUID(const char* serviceUUID);
-	void setServiceUUID(BLEUUID serviceUUID);
-private:
-	esp_ble_adv_data_t   m_advData;
-	esp_ble_adv_params_t m_advParams;
-	BLEUUID              m_serviceUUID;
-};
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISING_H_ */
diff --git a/components/cpp_utils/BLECharacteristic.cpp b/components/cpp_utils/BLECharacteristic.cpp
deleted file mode 100644
index f5b8200..0000000
--- a/components/cpp_utils/BLECharacteristic.cpp
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- * BLECharacteristic.cpp
- *
- *  Created on: Jun 22, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <sstream>
-#include <string.h>
-#include <iomanip>
-#include <stdlib.h>
-#include "sdkconfig.h"
-#include <esp_log.h>
-#include <esp_err.h>
-#include "BLECharacteristic.h"
-#include "BLEService.h"
-#include "BLEUtils.h"
-#include "BLE2902.h"
-#include "GeneralUtils.h"
-
-static const char* LOG_TAG = "BLECharacteristic";
-
-#define NULL_HANDLE (0xffff)
-
-
-/**
- * @brief Construct a characteristic
- * @param [in] uuid - UUID (const char*) for the characteristic.
- * @param [in] properties - Properties for the characteristic.
- */
-BLECharacteristic::BLECharacteristic(const char* uuid, uint32_t properties) : BLECharacteristic(BLEUUID(uuid), properties) {
-}
-
-/**
- * @brief Construct a characteristic
- * @param [in] uuid - UUID for the characteristic.
- * @param [in] properties - Properties for the characteristic.
- */
-BLECharacteristic::BLECharacteristic(BLEUUID uuid, uint32_t properties) {
-	m_bleUUID    = uuid;
-	m_handle     = NULL_HANDLE;
-	m_properties = (esp_gatt_char_prop_t)0;
-	m_pCallbacks = nullptr;
-
-	setBroadcastProperty((properties & PROPERTY_BROADCAST) !=0);
-	setReadProperty((properties & PROPERTY_READ) !=0);
-	setWriteProperty((properties & PROPERTY_WRITE) !=0);
-	setNotifyProperty((properties & PROPERTY_NOTIFY) !=0);
-	setIndicateProperty((properties & PROPERTY_INDICATE) !=0);
-	setWriteNoResponseProperty((properties & PROPERTY_WRITE_NR) !=0);
-} // BLECharacteristic
-
-/**
- * @brief Destructor.
- */
-BLECharacteristic::~BLECharacteristic() {
-	//free(m_value.attr_value); // Release the storage for the value.
-} // ~BLECharacteristic
-
-
-/**
- * @brief Associate a descriptor with this characteristic.
- * @param [in] pDescriptor
- * @return N/A.
- */
-void BLECharacteristic::addDescriptor(BLEDescriptor* pDescriptor) {
-	ESP_LOGD(LOG_TAG, ">> addDescriptor(): Adding %s to %s", pDescriptor->toString().c_str(), toString().c_str());
-	m_descriptorMap.setByUUID(pDescriptor->getUUID(), pDescriptor);
-	ESP_LOGD(LOG_TAG, "<< addDescriptor()");
-} // addDescriptor
-
-
-/**
- * @brief Register a new characteristic with the ESP runtime.
- * @param [in] pService The service with which to associate this characteristic.
- */
-void BLECharacteristic::executeCreate(BLEService* pService) {
-	ESP_LOGD(LOG_TAG, ">> executeCreate()");
-
-	if (m_handle != NULL_HANDLE) {
-		ESP_LOGE(LOG_TAG, "Characteristic already has a handle.");
-		return;
-	}
-
-	m_pService = pService; // Save the service for to which this characteristic belongs.
-
-	ESP_LOGD(LOG_TAG, "Registering characteristic (esp_ble_gatts_add_char): uuid: %s, service: %s",
-		getUUID().toString().c_str(),
-		m_pService->toString().c_str());
-
-	esp_attr_control_t control;
-	control.auto_rsp = ESP_GATT_RSP_BY_APP;
-
-	m_semaphoreCreateEvt.take("executeCreate");
-
-	std::string strValue = m_value.getValue();
-
-	esp_attr_value_t value;
-	value.attr_len     = strValue.length();
-	value.attr_max_len = ESP_GATT_MAX_ATTR_LEN;
-	value.attr_value   = (uint8_t*)strValue.data();
-
-	esp_err_t errRc = ::esp_ble_gatts_add_char(
-		m_pService->getHandle(),
-		getUUID().getNative(),
-		static_cast<esp_gatt_perm_t>(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
-		getProperties(),
-		&value,
-		&control); // Whether to auto respond or not.
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_add_char: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	m_semaphoreCreateEvt.wait("executeCreate");
-
-	// Now that we have registered the characteristic, we must also register all the descriptors associated with this
-	// characteristic.  We iterate through each of those and invoke the registration call to register them with the
-	// ESP environment.
-
-	BLEDescriptor* pDescriptor = m_descriptorMap.getFirst();
-
-	while (pDescriptor != nullptr) {
-		pDescriptor->executeCreate(this);
-		pDescriptor = m_descriptorMap.getNext();
-	} // End while
-
-	ESP_LOGD(LOG_TAG, "<< executeCreate");
-} // executeCreate
-
-
-
-/**
- * @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
- * @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
- * @return The BLE Descriptor.  If no such descriptor is associated with the characteristic, nullptr is returned.
- */
-BLEDescriptor* BLECharacteristic::getDescriptorByUUID(const char* descriptorUUID) {
-	return m_descriptorMap.getByUUID(BLEUUID(descriptorUUID));
-} // getDescriptorByUUID
-
-/**
- * @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
- * @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
- * @return The BLE Descriptor.  If no such descriptor is associated with the characteristic, nullptr is returned.
- */
-BLEDescriptor* BLECharacteristic::getDescriptorByUUID(BLEUUID descriptorUUID) {
-	return m_descriptorMap.getByUUID(descriptorUUID);
-} // getDescriptorByUUID
-
-
-/**
- * @brief Get the handle of the characteristic.
- * @return The handle of the characteristic.
- */
-uint16_t BLECharacteristic::getHandle() {
-	return m_handle;
-} // getHandle
-
-
-esp_gatt_char_prop_t BLECharacteristic::getProperties() {
-	return m_properties;
-} // getProperties
-
-
-/**
- * @brief Get the service associated with this characteristic.
- */
-BLEService* BLECharacteristic::getService() {
-	return m_pService;
-} // getService
-
-
-/**
- * @brief Get the UUID of the characteristic.
- * @return The UUID of the characteristic.
- */
-BLEUUID BLECharacteristic::getUUID() {
-	return m_bleUUID;
-} // getUUID
-
-
-/**
- * @brief Retrieve the current value of the characteristic.
- * @return A pointer to storage containing the current characteristic value.
- */
-std::string BLECharacteristic::getValue() {
-	return m_value.getValue();
-} // getValue
-
-
-void BLECharacteristic::handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t* param) {
-	switch(event) {
-	// Events handled:
-	// ESP_GATTS_ADD_CHAR_EVT
-	// ESP_GATTS_WRITE_EVT
-	// ESP_GATTS_READ_EVT
-	//
-
-		// ESP_GATTS_EXEC_WRITE_EVT
-		// When we receive this event it is an indication that a previous write long needs to be committed.
-		//
-		// exec_write:
-		// - uint16_t conn_id
-		// - uint32_t trans_id
-		// - esp_bd_addr_t bda
-		// - uint8_t exec_write_flag
-		//
-		case ESP_GATTS_EXEC_WRITE_EVT: {
-			if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
-				m_value.commit();
-				if (m_pCallbacks != nullptr) {
-					m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
-				}
-			} else {
-				m_value.cancel();
-			}
-
-			esp_err_t errRc = ::esp_ble_gatts_send_response(
-					gatts_if,
-					param->write.conn_id,
-					param->write.trans_id, ESP_GATT_OK, nullptr);
-			if (errRc != ESP_OK) {
-				ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-			}
-			break;
-		} // ESP_GATTS_EXEC_WRITE_EVT
-
-
-		// ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service.
-		// add_char:
-		// - esp_gatt_status_t status
-		// - uint16_t attr_handle
-		// - uint16_t service_handle
-		// - esp_bt_uuid_t char_uuid
-		case ESP_GATTS_ADD_CHAR_EVT: {
-			if (getUUID().equals(BLEUUID(param->add_char.char_uuid)) &&
-					getService()->getHandle()==param->add_char.service_handle) {
-				m_semaphoreCreateEvt.give();
-			}
-			break;
-		} // ESP_GATTS_ADD_CHAR_EVT
-
-
-		// ESP_GATTS_WRITE_EVT - A request to write the value of a characteristic has arrived.
-		//
-		// write:
-		// - uint16_t      conn_id
-		// - uint16_t      trans_id
-		// - esp_bd_addr_t bda
-		// - uint16_t      handle
-		// - uint16_t      offset
-		// - bool          need_rsp
-		// - bool          is_prep
-		// - uint16_t      len
-		// - uint8_t      *value
-		//
-		case ESP_GATTS_WRITE_EVT: {
-// We check if this write request is for us by comparing the handles in the event.  If it is for us
-// we save the new value.  Next we look at the need_rsp flag which indicates whether or not we need
-// to send a response.  If we do, then we formulate a response and send it.
-			if (param->write.handle == m_handle) {
-				if (param->write.is_prep) {
-					m_value.addPart(param->write.value, param->write.len);
-				} else {
-					setValue(param->write.value, param->write.len);
-				}
-
-				ESP_LOGD(LOG_TAG, " - Response to write event: New value: handle: %.2x, uuid: %s",
-						getHandle(), getUUID().toString().c_str());
-
-				char *pHexData = BLEUtils::buildHexData(nullptr, param->write.value, param->write.len);
-				ESP_LOGD(LOG_TAG, " - Data: length: %d, data: %s", param->write.len, pHexData);
-				free(pHexData);
-
-				if (param->write.need_rsp) {
-					esp_gatt_rsp_t rsp;
-
-					rsp.attr_value.len      = param->write.len;
-					rsp.attr_value.handle   = m_handle;
-					rsp.attr_value.offset   = param->write.offset;
-					rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
-					memcpy(rsp.attr_value.value, param->write.value, param->write.len);
-
-					esp_err_t errRc = ::esp_ble_gatts_send_response(
-							gatts_if,
-							param->write.conn_id,
-							param->write.trans_id, ESP_GATT_OK, &rsp);
-					if (errRc != ESP_OK) {
-						ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-					}
-				} // Response needed
-
-				if (m_pCallbacks != nullptr && param->write.is_prep != true) {
-					m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler.
-				}
-			} // Match on handles.
-			break;
-		} // ESP_GATTS_WRITE_EVT
-
-
-		// ESP_GATTS_READ_EVT - A request to read the value of a characteristic has arrived.
-		//
-		// read:
-		// - uint16_t      conn_id
-		// - uint32_t      trans_id
-		// - esp_bd_addr_t bda
-		// - uint16_t      handle
-		// - uint16_t      offset
-		// - bool          is_long
-		// - bool          need_rsp
-		//
-		case ESP_GATTS_READ_EVT: {
-			ESP_LOGD(LOG_TAG, "- Testing: 0x%.2x == 0x%.2x", param->read.handle, m_handle);
-			if (param->read.handle == m_handle) {
-
-				if (m_pCallbacks != nullptr) {
-					m_pCallbacks->onRead(this); // Invoke the read callback.
-				}
-
-// Here's an interesting thing.  The read request has the option of saying whether we need a response
-// or not.  What would it "mean" to receive a read request and NOT send a response back?  That feels like
-// a very strange read.
-//
-// We have to handle the case where the data we wish to send back to the client is greater than the maximum
-// packet size of 22 bytes.  In this case, we become responsible for chunking the data into uints of 22 bytes.
-// The apparent algorithm is as follows.
-// If the is_long flag is set then this is a follow on from an original read and we will already have sent at least 22 bytes.
-// If the is_long flag is not set then we need to check how much data we are going to send.  If we are sending LESS than
-// 22 bytes, then we "just" send it and thats the end of the story.
-// If we are sending 22 bytes exactly, we just send it BUT we will get a follow on request.
-// If we are sending more than 22 bytes, we send the first 22 bytes and we will get a follow on request.
-// Because of follow on request processing, we need to maintain an offset of how much data we have already sent
-// so that when a follow on request arrives, we know where to start in the data to send the next sequence.
-// Note that the indication that the client will send a follow on request is that we sent exactly 22 bytes as a response.
-// If our payload is divisible by 22 then the last response will be a response of 0 bytes in length.
-//
-// The following code has deliberately not been factored to make it fewer statements because this would cloud the
-// the logic flow comprehension.
-//
-				if (param->read.need_rsp) {
-					ESP_LOGD(LOG_TAG, "Sending a response (esp_ble_gatts_send_response)");
-					esp_gatt_rsp_t rsp;
-					std::string value = m_value.getValue();
-					if (param->read.is_long) {
-						if (value.length() - m_value.getReadOffset() < 22) {
-							// This is the last in the chain
-							rsp.attr_value.len    = value.length() - m_value.getReadOffset();
-							rsp.attr_value.offset = m_value.getReadOffset();
-							memcpy(rsp.attr_value.value, value.data() + rsp.attr_value.offset, rsp.attr_value.len);
-							m_value.setReadOffset(0);
-						} else {
-							// There will be more to come.
-							rsp.attr_value.len    = 22;
-							rsp.attr_value.offset = m_value.getReadOffset();
-							memcpy(rsp.attr_value.value, value.data() + rsp.attr_value.offset, rsp.attr_value.len);
-							m_value.setReadOffset(rsp.attr_value.offset + 22);
-						}
-					} else {
-						if (value.length() > 21) {
-							// Too big for a single shot entry.
-							m_value.setReadOffset(22);
-							rsp.attr_value.len    = 22;
-							rsp.attr_value.offset = 0;
-							memcpy(rsp.attr_value.value, value.data(), rsp.attr_value.len);
-						} else {
-							// Will fit in a single packet with no callbacks required.
-							rsp.attr_value.len    = value.length();
-							rsp.attr_value.offset = 0;
-							memcpy(rsp.attr_value.value, value.data(), rsp.attr_value.len);
-						}
-					}
-					rsp.attr_value.handle   = param->read.handle;
-					rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
-
-					char *pHexData = BLEUtils::buildHexData(nullptr, rsp.attr_value.value, rsp.attr_value.len);
-					ESP_LOGD(LOG_TAG, " - Data: length=%d, data=%s, offset=%d", rsp.attr_value.len, pHexData, rsp.attr_value.offset);
-					free(pHexData);
-
-					esp_err_t errRc = ::esp_ble_gatts_send_response(
-							gatts_if, param->read.conn_id,
-							param->read.trans_id,
-							ESP_GATT_OK,
-							&rsp);
-					if (errRc != ESP_OK) {
-						ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-					}
-				} // Response needed
-			} // Handle matches this characteristic.
-			break;
-		} // ESP_GATTS_READ_EVT
-
-		// ESP_GATTS_CONF_EVT
-		//
-		// conf:
-		// - esp_gatt_status_t status  – The status code.
-		// - uint16_t          conn_id – The connection used.
-		//
-		case ESP_GATTS_CONF_EVT: {
-			m_semaphoreConfEvt.give();
-			break;
-		}
-
-		default: {
-			break;
-		} // default
-
-	} // switch event
-
-	// Give each of the descriptors associated with this characteristic the opportunity to handle the
-	// event.
-	BLEDescriptor *pDescriptor = m_descriptorMap.getFirst();
-	while(pDescriptor != nullptr) {
-		pDescriptor->handleGATTServerEvent(event, gatts_if, param);
-		pDescriptor = m_descriptorMap.getNext();
-	}
-
-} // handleGATTServerEvent
-
-/**
- * @brief Send an indication.
- * An indication is a transmission of up to the first 20 bytes of the characteristic value.  An indication
- * will block waiting a positive confirmation from the client.
- * @return N/A
- */
-void BLECharacteristic::indicate() {
-
-	ESP_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length());
-
-	assert(getService() != nullptr);
-	assert(getService()->getServer() != nullptr);
-
-	GeneralUtils::hexDump((uint8_t*)m_value.getValue().data(), m_value.getValue().length());
-
-	if (getService()->getServer()->getConnectedCount() == 0) {
-		ESP_LOGD(LOG_TAG, "<< indicate: No connected clients.");
-		return;
-	}
-
-	// Test to see if we have a 0x2902 descriptor.  If we do, then check to see if indications are enabled
-	// and, if not, prevent the indication.
-
-	BLE2902 *p2902 = (BLE2902*)getDescriptorByUUID((uint16_t)0x2902);
-	if (p2902 != nullptr && !p2902->getIndications()) {
-		ESP_LOGD(LOG_TAG, "<< indications disabled; ignoring");
-		return;
-	}
-
-	if (m_value.getValue().length() > 20) {
-		ESP_LOGD(LOG_TAG, "- Truncating to 20 bytes (maximum notify size)");
-	}
-
-	size_t length = m_value.getValue().length();
-	if (length > 20) {
-		length = 20;
-	}
-
-	m_semaphoreConfEvt.take("indicate");
-
-	esp_err_t errRc = ::esp_ble_gatts_send_indicate(
-			getService()->getServer()->getGattsIf(),
-			getService()->getServer()->getConnId(),
-			getHandle(), length, (uint8_t*)m_value.getValue().data(), true); // The need_confirm = true makes this an indication.
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_send_indicate: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	m_semaphoreConfEvt.wait("indicate");
-	ESP_LOGD(LOG_TAG, "<< indicate");
-} // indicate
-
-
-/**
- * @brief Send a notify.
- * A notification is a transmission of up to the first 20 bytes of the characteristic value.  An notification
- * will not block; it is a fire and forget.
- * @return N/A.
- */
-void BLECharacteristic::notify() {
-	ESP_LOGD(LOG_TAG, ">> notify: length: %d", m_value.getValue().length());
-
-
-	assert(getService() != nullptr);
-	assert(getService()->getServer() != nullptr);
-
-
-	GeneralUtils::hexDump((uint8_t*)m_value.getValue().data(), m_value.getValue().length());
-
-	if (getService()->getServer()->getConnectedCount() == 0) {
-		ESP_LOGD(LOG_TAG, "<< notify: No connected clients.");
-		return;
-	}
-
-	// Test to see if we have a 0x2902 descriptor.  If we do, then check to see if notification is enabled
-	// and, if not, prevent the notification.
-
-	BLE2902 *p2902 = (BLE2902*)getDescriptorByUUID((uint16_t)0x2902);
-	if (p2902 != nullptr && !p2902->getNotifications()) {
-		ESP_LOGD(LOG_TAG, "<< notifications disabled; ignoring");
-		return;
-	}
-
-	if (m_value.getValue().length() > 20) {
-		ESP_LOGD(LOG_TAG, "- Truncating to 20 bytes (maximum notify size)");
-	}
-
-	size_t length = m_value.getValue().length();
-	if (length > 20) {
-		length = 20;
-	}
-
-	esp_err_t errRc = ::esp_ble_gatts_send_indicate(
-			getService()->getServer()->getGattsIf(),
-			getService()->getServer()->getConnId(),
-			getHandle(), length, (uint8_t*)m_value.getValue().data(), false); // The need_confirm = false makes this a notify.
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_send_indicate: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	ESP_LOGD(LOG_TAG, "<< notify");
-} // Notify
-
-
-/**
- * @brief Set the permission to broadcast.
- * A characteristics has properties associated with it which define what it is capable of doing.
- * One of these is the broadcast flag.
- * @param [in] value The flag value of the property.
- * @return N/A
- */
-void BLECharacteristic::setBroadcastProperty(bool value) {
-	//ESP_LOGD(LOG_TAG, "setBroadcastProperty(%d)", value);
-	if (value) {
-		m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_BROADCAST);
-	} else {
-		m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_BROADCAST);
-	}
-} // setBroadcastProperty
-
-
-/**
- * @brief Set the callback handlers for this characteristic.
- * @param [in] pCallbacks An instance of a callbacks structure used to define any callbacks for the characteristic.
- */
-void BLECharacteristic::setCallbacks(BLECharacteristicCallbacks* pCallbacks) {
-	m_pCallbacks = pCallbacks;
-} // setCallbacks
-
-
-/**
- * @brief Set the BLE handle associated with this characteristic.
- * A user program will request that a characteristic be created against a service.  When the characteristic has been
- * registered, the service will be given a "handle" that it knows the characteristic as.  This handle is unique to the
- * server/service but it is told to the service, not the characteristic associated with the service.  This internally
- * exposed function can be invoked by the service against this model of the characteristic to allow the characteristic
- * to learn its own handle.  Once the characteristic knows its own handle, it will be able to see incoming GATT events
- * that will be propagated down to it which contain a handle value and now know that the event is destined for it.
- * @param [in] handle The handle associated with this characteristic.
- */
-void BLECharacteristic::setHandle(uint16_t handle) {
-	ESP_LOGD(LOG_TAG, ">> setHandle: handle=0x%.2x, characteristic uuid=%s", handle, getUUID().toString().c_str());
-	m_handle = handle;
-	ESP_LOGD(LOG_TAG, "<< setHandle");
-} // setHandle
-
-
-/**
- * @brief Set the Indicate property value.
- * @param [in] value Set to true if we are to allow indicate messages.
- */
-void BLECharacteristic::setIndicateProperty(bool value) {
-	//ESP_LOGD(LOG_TAG, "setIndicateProperty(%d)", value);
-	if (value) {
-		m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_INDICATE);
-	} else {
-		m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_INDICATE);
-	}
-} // setIndicateProperty
-
-
-/**
- * @brief Set the Notify property value.
- * @param [in] value Set to true if we are to allow notification messages.
- */
-void BLECharacteristic::setNotifyProperty(bool value) {
-	//ESP_LOGD(LOG_TAG, "setNotifyProperty(%d)", value);
-	if (value) {
-		m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_NOTIFY);
-	} else {
-		m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_NOTIFY);
-	}
-} // setNotifyProperty
-
-
-/**
- * @brief Set the Read property value.
- * @param [in] value Set to true if we are to allow reads.
- */
-void BLECharacteristic::setReadProperty(bool value) {
-	//ESP_LOGD(LOG_TAG, "setReadProperty(%d)", value);
-	if (value) {
-		m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_READ);
-	} else {
-		m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_READ);
-	}
-} // setReadProperty
-
-
-/**
- * @brief Set the value of the characteristic.
- * @param [in] data The data to set for the characteristic.
- * @param [in] length The length of the data in bytes.
- */
-void BLECharacteristic::setValue(uint8_t* data, size_t length) {
-	char *pHex = BLEUtils::buildHexData(nullptr, data, length);
-	ESP_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str());
-	free(pHex);
-	if (length > ESP_GATT_MAX_ATTR_LEN) {
-		ESP_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, ESP_GATT_MAX_ATTR_LEN);
-		return;
-	}
-	m_value.setValue(data, length);
-	ESP_LOGD(LOG_TAG, "<< setValue");
-} // setValue
-
-
-/**
- * @brief Set the value of the characteristic from string data.
- * We set the value of the characteristic from the bytes contained in the
- * string.
- * @param [in] Set the value of the characteristic.
- * @return N/A.
- */
-void BLECharacteristic::setValue(std::string value) {
-	setValue((uint8_t*)(value.data()), value.length());
-} // setValue
-
-
-/**
- * @brief Set the Write No Response property value.
- * @param [in] value Set to true if we are to allow writes with no response.
- */
-void BLECharacteristic::setWriteNoResponseProperty(bool value) {
-	//ESP_LOGD(LOG_TAG, "setWriteNoResponseProperty(%d)", value);
-	if (value) {
-		m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_WRITE_NR);
-	} else {
-		m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_WRITE_NR);
-	}
-} // setWriteNoResponseProperty
-
-
-/**
- * @brief Set the Write property value.
- * @param [in] value Set to true if we are to allow writes.
- */
-void BLECharacteristic::setWriteProperty(bool value) {
-	//ESP_LOGD(LOG_TAG, "setWriteProperty(%d)", value);
-	if (value) {
-		m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_WRITE);
-	} else {
-		m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_WRITE);
-	}
-} // setWriteProperty
-
-
-/**
- * @brief Return a string representation of the characteristic.
- * @return A string representation of the characteristic.
- */
-std::string BLECharacteristic::toString() {
-	std::stringstream stringstream;
-	stringstream << std::hex << std::setfill('0');
-	stringstream << "UUID: " << m_bleUUID.toString() + ", handle: 0x" << std::setw(2) << m_handle;
-	stringstream << " " <<
-		((m_properties & ESP_GATT_CHAR_PROP_BIT_READ)?"Read ":"") <<
-		((m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE)?"Write ":"") <<
-		((m_properties & ESP_GATT_CHAR_PROP_BIT_WRITE_NR)?"WriteNoResponse ":"") <<
-		((m_properties & ESP_GATT_CHAR_PROP_BIT_BROADCAST)?"Broadcast ":"") <<
-		((m_properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY)?"Notify ":"") <<
-		((m_properties & ESP_GATT_CHAR_PROP_BIT_INDICATE)?"Indicate ":"");
-	return stringstream.str();
-} // toString
-
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLECharacteristic.h b/components/cpp_utils/BLECharacteristic.h
deleted file mode 100644
index b39c022..0000000
--- a/components/cpp_utils/BLECharacteristic.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * BLECharacteristic.h
- *
- *  Created on: Jun 22, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLECHARACTERISTIC_H_
-#define COMPONENTS_CPP_UTILS_BLECHARACTERISTIC_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <string>
-#include <map>
-#include "BLEUUID.h"
-#include <esp_gatts_api.h>
-#include "BLEDescriptor.h"
-#include "BLEValue.h"
-#include "FreeRTOS.h"
-
-class BLEService;
-class BLEDescriptor;
-class BLECharacteristicCallbacks;
-
-/**
- * @brief A management structure for %BLE descriptors.
- */
-class BLEDescriptorMap {
-public:
-	void setByUUID(const char* uuid,  BLEDescriptor *pDescriptor);
-	void setByUUID(BLEUUID uuid,      BLEDescriptor *pDescriptor);
-	void setByHandle(uint16_t handle, BLEDescriptor *pDescriptor);
-	BLEDescriptor *getByUUID(const char* uuid);
-	BLEDescriptor *getByUUID(BLEUUID uuid);
-	BLEDescriptor *getByHandle(uint16_t handle);
-	std::string toString();
-	void handleGATTServerEvent(
-			esp_gatts_cb_event_t      event,
-			esp_gatt_if_t             gatts_if,
-			esp_ble_gatts_cb_param_t *param);
-	BLEDescriptor *getFirst();
-	BLEDescriptor *getNext();
-private:
-	std::map<std::string, BLEDescriptor *> m_uuidMap;
-	std::map<uint16_t,    BLEDescriptor *> m_handleMap;
-	std::map<std::string, BLEDescriptor *>::iterator m_iterator;
-};
-
-
-/**
- * @brief The model of a %BLE Characteristic.
- *
- * A %BLE Characteristic is an identified value container that manages a value.  It is exposed by a %BLE server and
- * can be read and written to by a %BLE client.
- */
-class BLECharacteristic {
-public:
-	BLECharacteristic(const char* uuid, uint32_t properties = 0);
-	BLECharacteristic(BLEUUID uuid, uint32_t properties = 0);
-	virtual ~BLECharacteristic();
-
-	void           addDescriptor(BLEDescriptor* pDescriptor);
-	BLEDescriptor* getDescriptorByUUID(const char* descriptorUUID);
-	BLEDescriptor* getDescriptorByUUID(BLEUUID descriptorUUID);
-	//size_t         getLength();
-	BLEUUID        getUUID();
-	std::string    getValue();
-
-	void indicate();
-	void notify();
-	void setBroadcastProperty(bool value);
-	void setCallbacks(BLECharacteristicCallbacks* pCallbacks);
-	void setIndicateProperty(bool value);
-	void setNotifyProperty(bool value);
-	void setReadProperty(bool value);
-	void setValue(uint8_t* data, size_t size);
-	void setValue(std::string value);
-	void setWriteProperty(bool value);
-	void setWriteNoResponseProperty(bool value);
-	std::string toString();
-
-
-	static const uint32_t PROPERTY_READ      = 1<<0;
-	static const uint32_t PROPERTY_WRITE     = 1<<1;
-	static const uint32_t PROPERTY_NOTIFY    = 1<<2;
-	static const uint32_t PROPERTY_BROADCAST = 1<<3;
-	static const uint32_t PROPERTY_INDICATE  = 1<<4;
-	static const uint32_t PROPERTY_WRITE_NR  = 1<<5;
-
-private:
-	friend class BLEServer;
-	friend class BLEService;
-	friend class BLEDescriptor;
-	friend class BLECharacteristicMap;
-
-	BLEUUID                     m_bleUUID;
-	BLEDescriptorMap            m_descriptorMap;
-	uint16_t                    m_handle;
-	esp_gatt_char_prop_t        m_properties;
-	BLECharacteristicCallbacks* m_pCallbacks;
-	BLEService*                 m_pService;
-	BLEValue                    m_value;
-
-	void handleGATTServerEvent(
-			esp_gatts_cb_event_t      event,
-			esp_gatt_if_t             gatts_if,
-			esp_ble_gatts_cb_param_t* param);
-
-	void                 executeCreate(BLEService* pService);
-	uint16_t             getHandle();
-	esp_gatt_char_prop_t getProperties();
-	BLEService*          getService();
-	void                 setHandle(uint16_t handle);
-	FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
-	FreeRTOS::Semaphore m_semaphoreConfEvt   = FreeRTOS::Semaphore("ConfEvt");
-}; // BLECharacteristic
-
-
-/**
- * @brief Callbacks that can be associated with a %BLE characteristic to inform of events.
- *
- * When a server application creates a %BLE characteristic, we may wish to be informed when there is either
- * a read or write request to the characteristic's value.  An application can register a
- * sub-classed instance of this class and will be notified when such an event happens.
- */
-class BLECharacteristicCallbacks {
-public:
-	virtual ~BLECharacteristicCallbacks();
-	virtual void onRead(BLECharacteristic* pCharacteristic);
-	virtual void onWrite(BLECharacteristic* pCharacteristic);
-};
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLECHARACTERISTIC_H_ */
diff --git a/components/cpp_utils/BLECharacteristicCallbacks.cpp b/components/cpp_utils/BLECharacteristicCallbacks.cpp
deleted file mode 100644
index b733865..0000000
--- a/components/cpp_utils/BLECharacteristicCallbacks.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * BLECharacteristicCallbacks.cpp
- *
- *  Created on: Jul 2, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include "BLECharacteristic.h"
-#include <esp_log.h>
-static const char* LOG_TAG = "BLECharacteristicCallbacks";
-
-
-BLECharacteristicCallbacks::~BLECharacteristicCallbacks() {}
-
-/**
- * @brief Callback function to support a read request.
- * @param [in] pCharacteristic The characteristic that is the source of the event.
- */
-void BLECharacteristicCallbacks::onRead(BLECharacteristic *pCharacteristic) {
-	ESP_LOGD(LOG_TAG, ">> onRead: default");
-	ESP_LOGD(LOG_TAG, "<< onRead");
-} // onRead
-
-
-/**
- * @brief Callback function to support a write request.
- * @param [in] pCharacteristic The characteristic that is the source of the event.
- */
-void BLECharacteristicCallbacks::onWrite(BLECharacteristic *pCharacteristic) {
-	ESP_LOGD(LOG_TAG, ">> onWrite: default");
-	ESP_LOGD(LOG_TAG, "<< onWrite");
-} // onWrite
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLECharacteristicMap.cpp b/components/cpp_utils/BLECharacteristicMap.cpp
deleted file mode 100644
index f475e83..0000000
--- a/components/cpp_utils/BLECharacteristicMap.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * BLECharacteristicMap.cpp
- *
- *  Created on: Jun 22, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <sstream>
-#include <iomanip>
-#include "BLEService.h"
-
-/**
- * @brief Return the characteristic by UUID.
- * @param [in] UUID The UUID to look up the characteristic.
- * @return The characteristic.
- */
-BLECharacteristic* BLECharacteristicMap::getByUUID(const char* uuid) {
-    return getByUUID(BLEUUID(uuid));
-}
-
-/**
- * @brief Return the characteristic by UUID.
- * @param [in] UUID The UUID to look up the characteristic.
- * @return The characteristic.
- */
-BLECharacteristic* BLECharacteristicMap::getByUUID(BLEUUID uuid) {
-	for (auto &myPair : m_uuidMap) {
-		if (myPair.second->getUUID().equals(uuid)) {
-			return myPair.second;
-		}
-	}
-	//return m_uuidMap.at(uuid.toString());
-	return nullptr;
-} // getByUUID
-
-
-/**
- * @brief Return the characteristic by handle.
- * @param [in] handle The handle to look up the characteristic.
- * @return The characteristic.
- */
-BLECharacteristic* BLECharacteristicMap::getByHandle(uint16_t handle) {
-	return m_handleMap.at(handle);
-} // getByHandle
-
-
-/**
- * @brief Set the characteristic by UUID.
- * @param [in] uuid The uuid of the characteristic.
- * @param [in] characteristic The characteristic to cache.
- * @return N/A.
- */
-void BLECharacteristicMap::setByUUID(
-		BLEUUID            uuid,
-		BLECharacteristic *pCharacteristic) {
-	m_uuidMap.insert(std::pair<std::string, BLECharacteristic *>(uuid.toString(), pCharacteristic));
-} // setByUUID
-
-
-/**
- * @brief Set the characteristic by handle.
- * @param [in] handle The handle of the characteristic.
- * @param [in] characteristic The characteristic to cache.
- * @return N/A.
- */
-void BLECharacteristicMap::setByHandle(uint16_t handle,
-		BLECharacteristic *characteristic) {
-	m_handleMap.insert(std::pair<uint16_t, BLECharacteristic *>(handle, characteristic));
-} // setByHandle
-
-
-/**
- * @brief Return a string representation of the characteristic map.
- * @return A string representation of the characteristic map.
- */
-std::string BLECharacteristicMap::toString() {
-	std::stringstream stringStream;
-	stringStream << std::hex << std::setfill('0');
-	int count=0;
-	for (auto &myPair: m_uuidMap) {
-		if (count > 0) {
-			stringStream << "\n";
-		}
-		count++;
-		stringStream << "handle: 0x" << std::setw(2) << myPair.second->getHandle() << ", uuid: " + myPair.second->getUUID().toString();
-	}
-	return stringStream.str();
-} // toString
-
-
-/**
- * @breif Pass the GATT server event onwards to each of the characteristics found in the mapping
- * @param [in] event
- * @param [in] gatts_if
- * @param [in] param
- */
-void BLECharacteristicMap::handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t *param) {
-	// Invoke the handler for every Service we have.
-	for (auto &myPair : m_uuidMap) {
-		myPair.second->handleGATTServerEvent(event, gatts_if, param);
-	}
-} // handleGATTServerEvent
-
-
-/**
- * @brief Get the first characteristic in the map.
- * @return The first characteristic in the map.
- */
-BLECharacteristic* BLECharacteristicMap::getFirst() {
-	m_iterator = m_uuidMap.begin();
-	if (m_iterator == m_uuidMap.end()) {
-		return nullptr;
-	}
-	BLECharacteristic *pRet = m_iterator->second;
-	m_iterator++;
-	return pRet;
-} // getFirst
-
-
-/**
- * @brief Get the next characteristic in the map.
- * @return The next characteristic in the map.
- */
-BLECharacteristic* BLECharacteristicMap::getNext() {
-	if (m_iterator == m_uuidMap.end()) {
-		return nullptr;
-	}
-	BLECharacteristic *pRet = m_iterator->second;
-	m_iterator++;
-	return pRet;
-} // getNext
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLEClient.cpp b/components/cpp_utils/BLEClient.cpp
deleted file mode 100644
index a5d60cf..0000000
--- a/components/cpp_utils/BLEClient.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * BLEDevice.cpp
- *
- *  Created on: Mar 22, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_log.h>
-#include <bt.h>
-#include <esp_bt_main.h>
-#include <esp_gap_ble_api.h>
-#include <esp_gattc_api.h>
-#include "BLEClient.h"
-#include "BLEUtils.h"
-#include "BLEService.h"
-#include "GeneralUtils.h"
-#include <string>
-#include <sstream>
-#include <unordered_set>
-
-/*
- * Design
- * ------
- * When we perform a searchService() requests, we are asking the BLE server to return each of the services
- * that it exposes.  For each service, we received an ESP_GATTC_SEARCH_RES_EVT event which contains details
- * of the exposed service including its UUID.
- *
- * The objects we will invent for a BLEClient will be as follows:
- * * BLERemoteService - A model of a remote service.
- * * BLERemoteCharacteristic - A model of a remote characteristic
- * * BLERemoteDescriptor - A model of a remote descriptor.
- *
- * Since there is a hierarchical relationship here, we will have the idea that from a BLERemoteService will own
- * zero or more remote characteristics and a BLERemoteCharacteristic will own zero or more remote BLEDescriptors.
- *
- * We will assume that a BLERemoteService contains a map that maps BLEUUIDs to the set of owned characteristics
- * and that a BLECharacteristic contains a map that maps BLEUUIDs to the set of owned descriptors.
- *
- *
- */
-static const char* LOG_TAG = "BLEClient";
-
-BLEClient::BLEClient() {
-	m_pClientCallbacks = nullptr;
-	m_conn_id          = 0;
-	m_gattc_if         = 0;
-	m_haveServices     = false;
-} // BLEClient
-
-/**
- * @brief Connect to the partner.
- * @param [in] address The address of the partner.
- */
-bool BLEClient::connect(BLEAddress address) {
-	ESP_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
-// We need the connection handle that we get from registering the application.  We register the app
-// and then block on its completion.  When the event has arrived, we will have the handle.
-	m_semaphoreRegEvt.take("connect");
-	esp_err_t errRc = esp_ble_gattc_app_register(0);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_app_register: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return false;
-	}
-	m_semaphoreRegEvt.wait("connect");
-
-	m_peerAddress = address;
-
-	m_semaphoreOpenEvt.take("connect");
-	errRc = ::esp_ble_gattc_open(
-		getGattcIf(),
-		*getPeerAddress().getNative(), // address
-		1                              // direct connection
-	);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return false;
-	}
-
-	uint32_t rc = m_semaphoreOpenEvt.wait("connect");
-	ESP_LOGD(LOG_TAG, "<< connect(), rc=%d", rc==ESP_GATT_OK);
-	return rc == ESP_GATT_OK;
-} // connect
-
-
-/**
- * @brief Disconnect from the peer.
- * @return N/A.
- */
-void BLEClient::disconnect() {
-	ESP_LOGD(LOG_TAG, ">> disconnect()");
-	esp_err_t errRc = ::esp_ble_gattc_close(getGattcIf(), getConnId());
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_close: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-	m_peerAddress = BLEAddress("00:00:00:00:00:00");
-	ESP_LOGD(LOG_TAG, "<< disconnect()");
-} // disconnect
-
-
-/**
- * @brief Handle GATT Client events
- */
-void BLEClient::gattClientEventHandler(
-	esp_gattc_cb_event_t      event,
-	esp_gatt_if_t             gattc_if,
-	esp_ble_gattc_cb_param_t* evtParam) {
-
-	// Execute handler code based on the type of event received.
-	switch(event) {
-		//
-		// ESP_GATTC_NOTIFY_EVT
-		//
-		// notify
-		// uint16_t           conn_id
-		// esp_bd_addr_t      remote_bda
-		// esp_gatt_srvc_id_t srvc_id
-		// esp_gatt_id_t      char_id
-		// esp_gatt_id_t      descr_id
-		// uint16_t           value_len
-		// uint8_t*           value
-		// bool               is_notify
-		//
-		case ESP_GATTC_NOTIFY_EVT: {
-			BLERemoteService *pBLERemoteService = getService(BLEUUID(evtParam->notify.srvc_id.id.uuid));
-			if (pBLERemoteService == nullptr) {
-				ESP_LOGE(LOG_TAG, "Could not find service with UUID %s for notification", BLEUUID(evtParam->notify.srvc_id.id.uuid).toString().c_str());
-				break;
-			}
-			BLERemoteCharacteristic* pBLERemoteCharacteristic = pBLERemoteService->getCharacteristic(BLEUUID(evtParam->notify.char_id.uuid));
-			if (pBLERemoteCharacteristic == nullptr) {
-				ESP_LOGE(LOG_TAG, "Could not find characteristic with UUID %s for notification", BLEUUID(evtParam->notify.char_id.uuid).toString().c_str());
-				break;
-			}
-			if (pBLERemoteCharacteristic->m_notifyCallback != nullptr) {
-				pBLERemoteCharacteristic->m_notifyCallback(pBLERemoteCharacteristic, evtParam->notify.value, evtParam->notify.value_len, evtParam->notify.is_notify);
-			}
-			break;
-		} // ESP_GATTC_NOTIFY_EVT
-
-		//
-		// ESP_GATTC_OPEN_EVT
-		//
-		// open:
-		// - esp_gatt_status_t status
-		// - uint16_t          conn_id
-		// - esp_bd_addr_t     remote_bda
-		// - uint16_t          mtu
-		//
-		case ESP_GATTC_OPEN_EVT: {
-			m_conn_id = evtParam->open.conn_id;
-			if (m_pClientCallbacks != nullptr) {
-				m_pClientCallbacks->onConnect(this);
-			}
-			m_semaphoreOpenEvt.give();
-			break;
-		} // ESP_GATTC_OPEN_EVT
-
-
-		//
-		// ESP_GATTC_REG_EVT
-		//
-		// reg:
-		// esp_gatt_status_t status
-		// uint16_t          app_id
-		//
-		case ESP_GATTC_REG_EVT: {
-			m_gattc_if = gattc_if;
-			m_semaphoreRegEvt.give();
-			break;
-		} // ESP_GATTC_REG_EVT
-
-
-		//
-		// ESP_GATTC_SEARCH_CMPL_EVT
-		//
-		// search_cmpl:
-		// - esp_gatt_status_t status
-		// - uint16_t          conn_id
-		//
-		case ESP_GATTC_SEARCH_CMPL_EVT: {
-			m_semaphoreSearchCmplEvt.give();
-			break;
-		} // ESP_GATTC_SEARCH_CMPL_EVT
-
-
-		//
-		// ESP_GATTC_SEARCH_RES_EVT
-		//
-		// search_res:
-		// - uint16_t           conn_id
-		// - esp_gatt_srvc_id_t srvc_id
-		//
-		case ESP_GATTC_SEARCH_RES_EVT: {
-			BLEUUID uuid = BLEUUID(evtParam->search_res.srvc_id);
-			BLERemoteService* pRemoteService = new BLERemoteService(evtParam->search_res.srvc_id, this);
-			m_servicesMap.insert(std::pair<std::string, BLERemoteService *>(uuid.toString(), pRemoteService));
-			break;
-		} // ESP_GATTC_SEARCH_RES_EVT
-
-
-		default: {
-			break;
-		}
-	} // Switch
-
-	for (auto &myPair : m_servicesMap) {
-	   myPair.second->gattClientEventHandler(event, gattc_if, evtParam);
-	}
-
-} // gattClientEventHandler
-
-
-/**
- * @brief Retrieve the address of the peer.
- *
- * Returns the address of the %BLE peer to which this client is connected.
- */
-BLEAddress BLEClient::getPeerAddress() {
-	return m_peerAddress;
-} // getAddress
-
-
-uint16_t BLEClient::getConnId() {
-	return m_conn_id;
-} // getConnId
-
-
-esp_gatt_if_t BLEClient::getGattcIf() {
-	return m_gattc_if;
-} // getGattcIf
-
-
-
-/**
- * @brief Get the service object corresponding to the uuid.
- * @param [in] uuid The UUID of the service being sought.
- * @return A reference to the Service or nullptr if don't know about it.
- */
-BLERemoteService* BLEClient::getService(const char* uuid) {
-    return getService(BLEUUID(uuid));
-}
-
-
-/**
- * @brief Get the service object corresponding to the uuid.
- * @param [in] uuid The UUID of the service being sought.
- * @return A reference to the Service or nullptr if don't know about it.
- */
-BLERemoteService* BLEClient::getService(BLEUUID uuid) {
-// Design
-// ------
-// We wish to retrieve the service given its UUID.  It is possible that we have not yet asked the
-// device what services it has in which case we have nothing to match against.  If we have not
-// asked the device about its services, then we do that now.  Once we get the results we can then
-// examine the services map to see if it has the service we are looking for.
-	if (!m_haveServices) {
-		getServices();
-	}
-	std::string v = uuid.toString();
-	for (auto &myPair : m_servicesMap) {
-		if (myPair.first == v) {
-			return myPair.second;
-		}
-	}
-	return nullptr;
-} // getService
-
-
-/**
- * @brief Ask the remote %BLE server for its services.
- * A %BLE Server exposes a set of services for its partners.  Here we ask the server for its set of
- * services and wait until we have received them all.
- * @return N/A
- */
-std::map<std::string, BLERemoteService*>* BLEClient::getServices() {
-/*
- * Design
- * ------
- * We invoke esp_ble_gattc_search_service.  This will request a list of the service exposed by the
- * peer BLE partner to be returned as events.  Each event will be an an instance of ESP_GATTC_SEARCH_RES_EVT
- * and will culminate with an ESP_GATTC_SEARCH_CMPL_EVT when all have been received.
- */
-	ESP_LOGD(LOG_TAG, ">> getServices");
-	m_servicesMap.empty();
-	esp_err_t errRc = esp_ble_gattc_search_service(
-		getGattcIf(),
-		getConnId(),
-		NULL // Filter UUID
-	);
-	m_semaphoreSearchCmplEvt.take("getServices");
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_search_service: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return &m_servicesMap;
-	}
-	m_semaphoreSearchCmplEvt.wait("getServices");
-	m_haveServices = true; // Remember that we now have services.
-	ESP_LOGD(LOG_TAG, "<< getServices");
-	return &m_servicesMap;
-} // getServices
-
-
-/**
- * @brief Set the callbacks that will be invoked.
- */
-void BLEClient::setClientCallbacks(BLEClientCallbacks* pClientCallbacks) {
-	m_pClientCallbacks = pClientCallbacks;
-} // setClientCallbacks
-
-
-/**
- * @brief Return a string representation of this client.
- * @return A string representation of this client.
- */
-std::string BLEClient::toString() {
-	std::ostringstream ss;
-	ss << "peer address: " << m_peerAddress.toString();
-	ss << "\nServices:\n";
-	for (auto &myPair : m_servicesMap) {
-		ss << myPair.second->toString() << "\n";
-	   // myPair.second is the value
-	}
-	return ss.str();
-} // toString
-
-#endif // CONFIG_BT_ENABLED
diff --git a/components/cpp_utils/BLEClient.h b/components/cpp_utils/BLEClient.h
deleted file mode 100644
index 898f98c..0000000
--- a/components/cpp_utils/BLEClient.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * BLEDevice.h
- *
- *  Created on: Mar 22, 2017
- *      Author: kolban
- */
-
-#ifndef MAIN_BLEDEVICE_H_
-#define MAIN_BLEDEVICE_H_
-
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include <esp_gattc_api.h>
-#include <string.h>
-#include <map>
-#include <string>
-#include <BLERemoteService.h>
-#include "BLEService.h"
-#include "BLEAddress.h"
-
-class BLERemoteService;
-class BLEClientCallbacks;
-
-/**
- * @brief A model of a %BLE client.
- */
-class BLEClient {
-public:
-	BLEClient();
-	bool                                       connect(BLEAddress address);
-	void                                       disconnect();
-	BLEAddress                                 getPeerAddress();
-	std::map<std::string, BLERemoteService*>*  getServices();
-	BLERemoteService*                          getService(const char* uuid);
-	BLERemoteService*                          getService(BLEUUID uuid);
-	void                                       setClientCallbacks(BLEClientCallbacks *pClientCallbacks);
-	std::string                                toString();
-
-private:
-	friend class BLEDevice;
-	friend class BLERemoteCharacteristic;
-	friend class BLERemoteService;
-
-	void                                       gattClientEventHandler(
-		esp_gattc_cb_event_t event,
-		esp_gatt_if_t gattc_if,
-		esp_ble_gattc_cb_param_t* param);
-
-	uint16_t                                   getConnId();
-	esp_gatt_if_t                              getGattcIf();
-	BLEAddress    m_peerAddress = BLEAddress((uint8_t*)"\0\0\0\0\0\0");
-	uint16_t      m_conn_id;
-//	int           m_deviceType;
-	esp_gatt_if_t m_gattc_if;
-
-	BLEClientCallbacks* m_pClientCallbacks;
-	FreeRTOS::Semaphore m_semaphoreRegEvt        = FreeRTOS::Semaphore("RegEvt");
-	FreeRTOS::Semaphore m_semaphoreOpenEvt       = FreeRTOS::Semaphore("OpenEvt");
-	FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt");
-	std::map<std::string, BLERemoteService*> m_servicesMap;
-	bool m_haveServices; // Have we previously obtain the set of services.
-}; // class BLEDevice
-
-
-/**
- * @brief Callbacks associated with a %BLE client.
- */
-class BLEClientCallbacks {
-public:
-	virtual ~BLEClientCallbacks() {};
-	virtual void onConnect(BLEClient *pClient) = 0;
-};
-
-#endif // CONFIG_BT_ENABLED
-#endif /* MAIN_BLEDEVICE_H_ */
diff --git a/components/cpp_utils/BLEDescriptor.cpp b/components/cpp_utils/BLEDescriptor.cpp
deleted file mode 100644
index 4a7fda6..0000000
--- a/components/cpp_utils/BLEDescriptor.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * BLEDescriptor.cpp
- *
- *  Created on: Jun 22, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <sstream>
-#include <string.h>
-#include <iomanip>
-#include <stdlib.h>
-#include "sdkconfig.h"
-#include <esp_log.h>
-#include <esp_err.h>
-#include "BLEService.h"
-#include "BLEDescriptor.h"
-#include "GeneralUtils.h"
-
-static const char* LOG_TAG = "BLEDescriptor";
-
-
-#define NULL_HANDLE (0xffff)
-
-
-/**
- * @brief BLEDescriptor constructor.
- */
-BLEDescriptor::BLEDescriptor(const char* uuid) : BLEDescriptor(BLEUUID(uuid)) {
-}	
-
-/**
- * @brief BLEDescriptor constructor.
- */
-BLEDescriptor::BLEDescriptor(BLEUUID uuid) {
-	m_bleUUID            = uuid;
-	m_value.attr_value   = (uint8_t *)malloc(ESP_GATT_MAX_ATTR_LEN); // Allocate storage for the value.
-	m_value.attr_len     = 0;
-	m_value.attr_max_len = ESP_GATT_MAX_ATTR_LEN;
-	m_handle             = NULL_HANDLE;
-	m_pCharacteristic    = nullptr; // No initial characteristic.
-
-} // BLEDescriptor
-
-
-/**
- * @brief BLEDescriptor destructor.
- */
-BLEDescriptor::~BLEDescriptor() {
-	free(m_value.attr_value);
-} // ~BLEDescriptor
-
-
-/**
- * @brief Execute the creation of the descriptor with the BLE runtime in ESP.
- * @param [in] pCharacteristic The characteristic to which to register this descriptor.
- */
-void BLEDescriptor::executeCreate(BLECharacteristic* pCharacteristic) {
-	ESP_LOGD(LOG_TAG, ">> executeCreate(): %s", toString().c_str());
-
-	if (m_handle != NULL_HANDLE) {
-		ESP_LOGE(LOG_TAG, "Descriptor already has a handle.");
-		return;
-	}
-
-	m_pCharacteristic = pCharacteristic; // Save the characteristic associated with this service.
-
-	esp_attr_control_t control;
-	control.auto_rsp = ESP_GATT_RSP_BY_APP;
-	m_semaphoreCreateEvt.take("executeCreate");
-	esp_err_t errRc = ::esp_ble_gatts_add_char_descr(
-			pCharacteristic->getService()->getHandle(),
-			getUUID().getNative(),
-			(esp_gatt_perm_t)(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
-			&m_value,
-			&control);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_add_char_descr: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	m_semaphoreCreateEvt.wait("executeCreate");
-	ESP_LOGD(LOG_TAG, "<< executeCreate");
-} // executeCreate
-
-
-/**
- * @brief Get the BLE handle for this descriptor.
- * @return The handle for this descriptor.
- */
-uint16_t BLEDescriptor::getHandle() {
-	return m_handle;
-} // getHandle
-
-
-/**
- * @brief Get the length of the value of this descriptor.
- * @return The length (in bytes) of the value of this descriptor.
- */
-size_t BLEDescriptor::getLength() {
-	return m_value.attr_len;
-} // getLength
-
-
-/**
- * @brief Get the UUID of the descriptor.
- */
-BLEUUID BLEDescriptor::getUUID() {
-	return m_bleUUID;
-} // getUUID
-
-
-
-/**
- * @brief Get the value of this descriptor.
- * @return A pointer to the value of this descriptor.
- */
-uint8_t* BLEDescriptor::getValue() {
-	return m_value.attr_value;
-} // getValue
-
-
-/**
- * @brief Handle GATT server events for the descripttor.
- * @param [in] event
- * @param [in] gatts_if
- * @param [in] param
- */
-void BLEDescriptor::handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t *param) {
-	switch(event) {
-		// ESP_GATTS_ADD_CHAR_DESCR_EVT
-		//
-		// add_char_descr:
-		// - esp_gatt_status_t status
-		// - uint16_t          attr_handle
-		// - uint16_t          service_handle
-		// - esp_bt_uuid_t     char_uuid
-		case ESP_GATTS_ADD_CHAR_DESCR_EVT: {
-			/*
-			ESP_LOGD(LOG_TAG, "DEBUG: m_pCharacteristic: %x", (uint32_t)m_pCharacteristic);
-			ESP_LOGD(LOG_TAG, "DEBUG: m_bleUUID: %s, add_char_descr.char_uuid: %s, equals: %d",
-				m_bleUUID.toString().c_str(),
-				BLEUUID(param->add_char_descr.char_uuid).toString().c_str(),
-				m_bleUUID.equals(BLEUUID(param->add_char_descr.char_uuid)));
-			ESP_LOGD(LOG_TAG, "DEBUG: service->getHandle: %x, add_char_descr.service_handle: %x",
-					m_pCharacteristic->getService()->getHandle(), param->add_char_descr.service_handle);
-			ESP_LOGD(LOG_TAG, "DEBUG: service->lastCharacteristic: %x",
-					(uint32_t)m_pCharacteristic->getService()->getLastCreatedCharacteristic());
-					*/
-			if (m_pCharacteristic != nullptr &&
-					m_bleUUID.equals(BLEUUID(param->add_char_descr.char_uuid)) &&
-					m_pCharacteristic->getService()->getHandle() == param->add_char_descr.service_handle &&
-					m_pCharacteristic == m_pCharacteristic->getService()->getLastCreatedCharacteristic()) {
-				setHandle(param->add_char_descr.attr_handle);
-				m_semaphoreCreateEvt.give();
-			}
-			break;
-		} // ESP_GATTS_ADD_CHAR_DESCR_EVT
-
-		// ESP_GATTS_WRITE_EVT - A request to write the value of a descriptor has arrived.
-		//
-		// write:
-		// - uint16_t conn_id
-		// - uint16_t trans_id
-		// - esp_bd_addr_t bda
-		// - uint16_t handle
-		// - uint16_t offset
-		// - bool need_rsp
-		// - bool is_prep
-		// - uint16_t len
-		// - uint8_t *value
-		case ESP_GATTS_WRITE_EVT: {
-			if (param->write.handle == m_handle) {
-				setValue(param->write.value, param->write.len);
-				esp_gatt_rsp_t rsp;
-				rsp.attr_value.len    = getLength();
-				rsp.attr_value.handle = m_handle;
-				rsp.attr_value.offset = 0;
-				rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
-				memcpy(rsp.attr_value.value, getValue(), rsp.attr_value.len);
-				esp_err_t errRc = ::esp_ble_gatts_send_response(
-						gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, &rsp);
-				if (errRc != ESP_OK) {
-					ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-				}
-			}
-			break;
-		} // ESP_GATTS_WRITE_EVT
-
-		// ESP_GATTS_READ_EVT - A request to read the value of a descriptor has arrived.
-		//
-		// read:
-		// - uint16_t conn_id
-		// - uint32_t trans_id
-		// - esp_bd_addr_t bda
-		// - uint16_t handle
-		// - uint16_t offset
-		// - bool is_long
-		// - bool need_rsp
-		//
-		case ESP_GATTS_READ_EVT: {
-			ESP_LOGD(LOG_TAG, "- Testing: Sought handle: 0x%.2x == descriptor handle: 0x%.2x ?", param->read.handle, m_handle);
-			if (param->read.handle == m_handle) {
-				ESP_LOGD(LOG_TAG, "Sending a response (esp_ble_gatts_send_response)");
-				if (param->read.need_rsp) {
-					esp_gatt_rsp_t rsp;
-					rsp.attr_value.len    = getLength();
-					rsp.attr_value.handle = param->read.handle;
-					rsp.attr_value.offset = 0;
-					rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
-					memcpy(rsp.attr_value.value, getValue(), rsp.attr_value.len);
-					esp_err_t errRc = ::esp_ble_gatts_send_response(
-							gatts_if, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp);
-					if (errRc != ESP_OK) {
-						ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-					}
-				}
-			} // ESP_GATTS_READ_EVT
-			break;
-		} // ESP_GATTS_READ_EVT
-		default: {
-			break;
-		}
-	}// switch event
-} // handleGATTServerEvent
-
-
-/**
- * @brief Set the handle of this descriptor.
- * Set the handle of this descriptor to be the supplied value.
- * @param [in] handle The handle to be associated with this descriptor.
- * @return N/A.
- */
-void BLEDescriptor::setHandle(uint16_t handle) {
-	ESP_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle);
-	m_handle = handle;
-	ESP_LOGD(LOG_TAG, "<< setHandle()");
-} // setHandle
-
-
-/**
- * @brief Set the value of the descriptor.
- * @param [in] data The data to set for the descriptor.
- * @param [in] length The length of the data in bytes.
- */
-void BLEDescriptor::setValue(uint8_t* data, size_t length) {
-	if (length > ESP_GATT_MAX_ATTR_LEN) {
-		ESP_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, ESP_GATT_MAX_ATTR_LEN);
-		return;
-	}
-	m_value.attr_len = length;
-	memcpy(m_value.attr_value, data, length);
-} // setValue
-
-
-/**
- * @brief Set the value of the descriptor.
- * @param [in] value The value of the descriptor in string form.
- */
-void BLEDescriptor::setValue(std::string value) {
-	setValue((uint8_t *)value.data(), value.length());
-} // setValue
-
-
-/**
- * @brief Return a string representation of the descriptor.
- * @return A string representation of the descriptor.
- */
-std::string BLEDescriptor::toString() {
-	std::stringstream stringstream;
-	stringstream << std::hex << std::setfill('0');
-	stringstream << "UUID: " << m_bleUUID.toString() + ", handle: 0x" << std::setw(2) << m_handle;
-	return stringstream.str();
-} // toString
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLEDescriptor.h b/components/cpp_utils/BLEDescriptor.h
deleted file mode 100644
index 1d32d50..0000000
--- a/components/cpp_utils/BLEDescriptor.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * BLEDescriptor.h
- *
- *  Created on: Jun 22, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEDESCRIPTOR_H_
-#define COMPONENTS_CPP_UTILS_BLEDESCRIPTOR_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <string>
-#include "BLEUUID.h"
-#include "BLECharacteristic.h"
-#include <esp_gatts_api.h>
-#include "FreeRTOS.h"
-
-class BLEService;
-class BLECharacteristic;
-
-/**
- * @brief A model of a %BLE descriptor.
- */
-class BLEDescriptor {
-public:
-	BLEDescriptor(const char* uuid);
-	BLEDescriptor(BLEUUID uuid);
-	virtual ~BLEDescriptor();
-
-	size_t   getLength();
-	BLEUUID  getUUID();
-	uint8_t* getValue();
-	void handleGATTServerEvent(
-			esp_gatts_cb_event_t      event,
-			esp_gatt_if_t             gatts_if,
-			esp_ble_gatts_cb_param_t* param);
-	void setValue(uint8_t* data, size_t size);
-	void setValue(std::string value);
-	std::string toString();
-
-private:
-	friend class BLEDescriptorMap;
-	friend class BLECharacteristic;
-	BLEUUID              m_bleUUID;
-	esp_attr_value_t     m_value;
-	uint16_t             m_handle;
-	BLECharacteristic*   m_pCharacteristic;
-	void executeCreate(BLECharacteristic* pCharacteristic);
-	uint16_t getHandle();
-	void setHandle(uint16_t handle);
-	FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
-};
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLEDESCRIPTOR_H_ */
diff --git a/components/cpp_utils/BLEDescriptorMap.cpp b/components/cpp_utils/BLEDescriptorMap.cpp
deleted file mode 100644
index b211652..0000000
--- a/components/cpp_utils/BLEDescriptorMap.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * BLEDescriptorMap.cpp
- *
- *  Created on: Jun 22, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <sstream>
-#include <iomanip>
-#include "BLECharacteristic.h"
-#include "BLEDescriptor.h"
-#include <esp_gatts_api.h>   // ESP32 BLE
-
-/**
- * @brief Return the descriptor by UUID.
- * @param [in] UUID The UUID to look up the descriptor.
- * @return The descriptor.  If not present, then nullptr is returned.
- */
-BLEDescriptor* BLEDescriptorMap::getByUUID(const char* uuid) {
-    return getByUUID(BLEUUID(uuid));
-}
-
-
-/**
- * @brief Return the descriptor by UUID.
- * @param [in] UUID The UUID to look up the descriptor.
- * @return The descriptor.  If not present, then nullptr is returned.
- */
-BLEDescriptor* BLEDescriptorMap::getByUUID(BLEUUID uuid) {
-	for (auto &myPair : m_uuidMap) {
-		if (myPair.second->getUUID().equals(uuid)) {
-			return myPair.second;
-		}
-	}
-	//return m_uuidMap.at(uuid.toString());
-	return nullptr;
-} // getByUUID
-
-
-/**
- * @brief Return the descriptor by handle.
- * @param [in] handle The handle to look up the descriptor.
- * @return The descriptor.
- */
-BLEDescriptor* BLEDescriptorMap::getByHandle(uint16_t handle) {
-	return m_handleMap.at(handle);
-} // getByHandle
-
-
-/**
- * @brief Set the descriptor by UUID.
- * @param [in] uuid The uuid of the descriptor.
- * @param [in] characteristic The descriptor to cache.
- * @return N/A.
- */
-void BLEDescriptorMap::setByUUID(const char* uuid, BLEDescriptor *pDescriptor){
-	m_uuidMap.insert(std::pair<std::string, BLEDescriptor *>(uuid, pDescriptor));
-} // setByUUID
-
-
-
-/**
- * @brief Set the descriptor by UUID.
- * @param [in] uuid The uuid of the descriptor.
- * @param [in] characteristic The descriptor to cache.
- * @return N/A.
- */
-void BLEDescriptorMap::setByUUID(BLEUUID uuid, BLEDescriptor *pDescriptor) {
-	m_uuidMap.insert(std::pair<std::string, BLEDescriptor *>(uuid.toString(), pDescriptor));
-} // setByUUID
-
-
-/**
- * @brief Set the descriptor by handle.
- * @param [in] handle The handle of the descriptor.
- * @param [in] descriptor The descriptor to cache.
- * @return N/A.
- */
-void BLEDescriptorMap::setByHandle(uint16_t handle,
-		BLEDescriptor *pDescriptor) {
-	m_handleMap.insert(std::pair<uint16_t, BLEDescriptor *>(handle, pDescriptor));
-} // setByHandle
-
-
-/**
- * @brief Return a string representation of the descriptor map.
- * @return A string representation of the descriptor map.
- */
-std::string BLEDescriptorMap::toString() {
-	std::stringstream stringStream;
-	stringStream << std::hex << std::setfill('0');
-	int count=0;
-	for (auto &myPair: m_uuidMap) {
-		if (count > 0) {
-			stringStream << "\n";
-		}
-		count++;
-		stringStream << "handle: 0x" << std::setw(2) << myPair.second->getHandle() << ", uuid: " + myPair.second->getUUID().toString();
-	}
-	return stringStream.str();
-} // toString
-
-
-/**
- * @breif Pass the GATT server event onwards to each of the descriptors found in the mapping
- * @param [in] event
- * @param [in] gatts_if
- * @param [in] param
- */
-void BLEDescriptorMap::handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t *param) {
-	// Invoke the handler for every descriptor we have.
-	for (auto &myPair : m_uuidMap) {
-		myPair.second->handleGATTServerEvent(event, gatts_if, param);
-	}
-} // handleGATTServerEvent
-
-
-/**
- * @brief Get the first descriptor in the map.
- * @return The first descriptor in the map.
- */
-BLEDescriptor* BLEDescriptorMap::getFirst() {
-	m_iterator = m_uuidMap.begin();
-	if (m_iterator == m_uuidMap.end()) {
-		return nullptr;
-	}
-	BLEDescriptor *pRet = m_iterator->second;
-	m_iterator++;
-	return pRet;
-} // getFirst
-
-
-/**
- * @brief Get the next descriptor in the map.
- * @return The next descriptor in the map.
- */
-BLEDescriptor* BLEDescriptorMap::getNext() {
-	if (m_iterator == m_uuidMap.end()) {
-		return nullptr;
-	}
-	BLEDescriptor *pRet = m_iterator->second;
-	m_iterator++;
-	return pRet;
-} // getNext
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLEDevice.cpp b/components/cpp_utils/BLEDevice.cpp
deleted file mode 100644
index 04cae14..0000000
--- a/components/cpp_utils/BLEDevice.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * BLE.cpp
- *
- *  Created on: Mar 16, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <freertos/FreeRTOS.h>
-#include <freertos/task.h>
-#include <esp_err.h>
-#include <nvs_flash.h>
-#include <freertos/FreeRTOS.h>
-#include <freertos/event_groups.h>
-#include <bt.h>              // ESP32 BLE
-#include <esp_bt_main.h>     // ESP32 BLE
-#include <esp_gap_ble_api.h> // ESP32 BLE
-// ESP32 BLE
-#include <esp_gatts_api.h>   // ESP32 BLE
-#include <esp_err.h>         // ESP32 ESP-IDF
-#include <esp_log.h>         // ESP32 ESP-IDF
-#include <map>               // Part of C++ STL
-#include <sstream>
-#include <iomanip>
-
-#include "BLEDevice.h"
-#include "BLEClient.h"
-#include "BLEUtils.h"
-#include "GeneralUtils.h"
-
-static const char* LOG_TAG = "BLEDevice";
-
-BLEServer *BLEDevice::m_bleServer = nullptr;
-BLEScan   *BLEDevice::m_pScan     = nullptr;
-BLEClient *BLEDevice::m_pClient   = nullptr;
-
-#include <esp_gattc_api.h>
-
-
-BLEClient* BLEDevice::createClient() {
-	m_pClient = new BLEClient();
-	return m_pClient;
-} // createClient
-
-
-/**
- * @brief Handle GATT server events.
- *
- * @param [in] event
- * @param [in] gatts_if
- * @param [in] param
- */
-void BLEDevice::gattServerEventHandler(
-   esp_gatts_cb_event_t      event,
-   esp_gatt_if_t             gatts_if,
-   esp_ble_gatts_cb_param_t *param
-) {
-	ESP_LOGD(LOG_TAG, "gattServerEventHandler [esp_gatt_if: %d] ... %s",
-		gatts_if,
-		BLEUtils::gattServerEventTypeToString(event).c_str());
-	BLEUtils::dumpGattServerEvent(event, gatts_if, param);
-	if (BLEDevice::m_bleServer != nullptr) {
-		BLEDevice::m_bleServer->handleGATTServerEvent(event, gatts_if, param);
-	}
-} // gattServerEventHandler
-
-
-/**
- * @brief Handle GATT client events.
- *
- * Handler for the GATT client events.
- * * `ESP_GATTC_OPEN_EVT` – Invoked when a connection is opened.
- * * `ESP_GATTC_PREP_WRITE_EVT` – Response to write a characteristic.
- * * `ESP_GATTC_READ_CHAR_EVT` – Response to read a characteristic.
- * * `ESP_GATTC_REG_EVT` – Invoked when a GATT client has been registered.
- *
- * @param [in] event
- * @param [in] gattc_if
- * @param [in] param
- */
-void BLEDevice::gattClientEventHandler(
-	esp_gattc_cb_event_t event,
-	esp_gatt_if_t gattc_if,
-	esp_ble_gattc_cb_param_t *param) {
-
-	ESP_LOGD(LOG_TAG, "gattClientEventHandler [esp_gatt_if: %d] ... %s",
-		gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str());
-	BLEUtils::dumpGattClientEvent(event, gattc_if, param);
-
-	switch(event) {
-		default: {
-			break;
-		}
-	} // switch
-
-	// If we have a client registered, call it.
-	if (BLEDevice::m_pClient != nullptr) {
-		BLEDevice::m_pClient->gattClientEventHandler(event, gattc_if, param);
-	}
-
-} // gattClientEventHandler
-
-
-/**
- * @brief Handle GAP events.
- */
-void BLEDevice::gapEventHandler(
-	esp_gap_ble_cb_event_t event,
-	esp_ble_gap_cb_param_t *param) {
-
-	BLEUtils::dumpGapEvent(event, param);
-
-	switch(event) {
-		case ESP_GAP_BLE_SEC_REQ_EVT: {
-			esp_err_t errRc = ::esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true);
-			if (errRc != ESP_OK) {
-				ESP_LOGE(LOG_TAG, "esp_ble_gap_security_rsp: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-			}
-			break;
-		}
-
-		default: {
-			break;
-		}
-	} // switch
-
-	if (BLEDevice::m_bleServer != nullptr) {
-		BLEDevice::m_bleServer->handleGAPEvent(event, param);
-	}
-
-	if (BLEDevice::m_pScan != nullptr) {
-		BLEDevice::getScan()->gapEventHandler(event, param);
-	}
-} // gapEventHandler
-
-
-/**
- * @brief Initialize the %BLE environment.
- * @param deviceName The device name of the device.
- */
-void BLEDevice::init(std::string deviceName) {
-	esp_err_t errRc = ::nvs_flash_init();
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "nvs_flash_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-  esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
-  errRc = esp_bt_controller_init(&bt_cfg);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_bt_controller_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	errRc = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_bt_controller_enable: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	errRc = esp_bluedroid_init();
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_bluedroid_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	errRc = esp_bluedroid_enable();
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_bluedroid_enable: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	errRc = esp_ble_gap_register_callback(BLEDevice::gapEventHandler);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gap_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	errRc = esp_ble_gattc_register_callback(BLEDevice::gattClientEventHandler);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	errRc = esp_ble_gatts_register_callback(BLEDevice::gattServerEventHandler);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gatts_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	errRc = ::esp_ble_gap_set_device_name(deviceName.c_str());
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gap_set_device_name: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	};
-
-	esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE;
-	errRc = ::esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gap_set_security_param: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	};
-
-	vTaskDelay(200/portTICK_PERIOD_MS); // Delay for 200 msecs as a workaround to an apparent Arduino environment issue.
-} // init
-
-
-
-/**
- * @brief Retrieve the Scan object that we use for scanning.
- * @return The scanning object reference.
- */
-BLEScan* BLEDevice::getScan() {
-	if (m_pScan == nullptr) {
-		m_pScan = new BLEScan();
-	}
-	return m_pScan;
-} // getScan
-
-
-
-#endif // CONFIG_BT_ENABLED
diff --git a/components/cpp_utils/BLEDevice.h b/components/cpp_utils/BLEDevice.h
deleted file mode 100644
index 9d767c1..0000000
--- a/components/cpp_utils/BLEDevice.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * BLEDevice.h
- *
- *  Created on: Mar 16, 2017
- *      Author: kolban
- */
-
-#ifndef MAIN_BLEDevice_H_
-#define MAIN_BLEDevice_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_gap_ble_api.h> // ESP32 BLE
-#include <esp_gattc_api.h>   // ESP32 BLE
-#include <map>               // Part of C++ STL
-#include <string>
-
-#include "BLEServer.h"
-#include "BLEClient.h"
-#include "BLEUtils.h"
-#include "BLEScan.h"
-#include "BLEAddress.h"
-/**
- * @brief %BLE functions.
- */
-class BLEDevice {
-public:
-	static void dumpDevices();
-	static BLEClient *createClient();
-
-	static void init(std::string deviceName);
-	//static void scan(int duration, esp_ble_scan_type_t scan_type = BLE_SCAN_TYPE_PASSIVE);
-	static BLEScan   *getScan();
-	static BLEServer *m_bleServer;
-	static BLEScan   *m_pScan;
-	static BLEClient *m_pClient;
-
-private:
-	static esp_gatt_if_t getGattcIF();
-
-	static void gattClientEventHandler(
-		esp_gattc_cb_event_t event,
-		esp_gatt_if_t gattc_if,
-		esp_ble_gattc_cb_param_t *param);
-	static void gattServerEventHandler(
-	   esp_gatts_cb_event_t      event,
-	   esp_gatt_if_t             gatts_if,
-	   esp_ble_gatts_cb_param_t *param);
-	static void gapEventHandler(
-		esp_gap_ble_cb_event_t event,
-		esp_ble_gap_cb_param_t *param);
-}; // class BLE
-
-#endif // CONFIG_BT_ENABLED
-#endif /* MAIN_BLEDevice_H_ */
diff --git a/components/cpp_utils/BLERemoteCharacteristic.cpp b/components/cpp_utils/BLERemoteCharacteristic.cpp
deleted file mode 100644
index 5227bf6..0000000
--- a/components/cpp_utils/BLERemoteCharacteristic.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * BLERemoteCharacteristic.cpp
- *
- *  Created on: Jul 8, 2017
- *      Author: kolban
- */
-
-#include "BLERemoteCharacteristic.h"
-
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include <esp_gattc_api.h>
-#include <esp_log.h>
-#include <esp_err.h>
-
-#include <sstream>
-#include "BLEUtils.h"
-#include "GeneralUtils.h"
-
-
-static const char* LOG_TAG = "BLERemoteCharacteristic";
-
-BLERemoteCharacteristic::BLERemoteCharacteristic(
-		esp_gatt_id_t        charId,
-		esp_gatt_char_prop_t charProp,
-		BLERemoteService*    pRemoteService) {
-	m_charId         = charId;
-	m_charProp       = charProp;
-	m_pRemoteService = pRemoteService;
-	m_notifyCallback = nullptr;
-} // BLERemoteCharacteristic
-
-
-static bool compareSrvcId(esp_gatt_srvc_id_t id1, esp_gatt_srvc_id_t id2) {
-	if (id1.id.inst_id != id2.id.inst_id) {
-		return false;
-	}
-	if (!BLEUUID(id1.id.uuid).equals(BLEUUID(id2.id.uuid))) {
-		return false;
-	}
-	return true;
-} // compareSrvcId
-
-
-static bool compareGattId(esp_gatt_id_t id1, esp_gatt_id_t id2) {
-	if (id1.inst_id != id2.inst_id) {
-		return false;
-	}
-	if (!BLEUUID(id1.uuid).equals(BLEUUID(id2.uuid))) {
-		return false;
-	}
-	return true;
-} // compareCharId
-
-
-/**
- * @brief Handle GATT Client events.
- * When an event arrives for a GATT client we give this characteristic the opportunity to
- * take a look at it to see if there is interest in it.
- * @param [in] event The type of event.
- * @param [in] gattc_if The interface on which the event was received.
- * @param [in] evtParam Payload data for the event.
- * @returns N/A
- */
-void BLERemoteCharacteristic::gattClientEventHandler(
-	esp_gattc_cb_event_t      event,
-	esp_gatt_if_t             gattc_if,
-	esp_ble_gattc_cb_param_t* evtParam) {
-	switch(event) {
-		//
-		// ESP_GATTC_READ_CHAR_EVT
-		// This event indicates that the server has responded to the read request.
-		//
-		// read:
-		// esp_gatt_status_t  status
-		// uint16_t           conn_id
-		// esp_gatt_srvc_id_t srvc_id
-		// esp_gatt_id_t      char_id
-		// esp_gatt_id_t      descr_id
-		// uint8_t*           value
-		// uint16_t           value_type
-		// uint16_t           value_len
-		case ESP_GATTC_READ_CHAR_EVT: {
-			if (compareSrvcId(evtParam->read.srvc_id, *m_pRemoteService->getSrvcId()) == false) {
-				break;
-			}
-
-			if (evtParam->read.conn_id != m_pRemoteService->getClient()->getConnId()) {
-				break;
-			}
-
-			if (compareGattId(evtParam->read.char_id, m_charId) == false) {
-				break;
-			}
-
-			if (evtParam->read.status == ESP_GATT_OK) {
-				m_value = std::string((char*)evtParam->read.value, evtParam->read.value_len);
-			} else {
-				m_value = "";
-			}
-
-			m_semaphoreReadCharEvt.give();
-			break;
-		} // ESP_GATTC_READ_CHAR_EVT
-
-
-		//
-		// ESP_GATTC_REG_FOR_NOTIFY_EVT
-		//
-		// reg_for_notify:
-		// - esp_gatt_status_t status
-		// - esp_gatt_srvc_id_t srvc_id
-		// - esp_gatt_id_t char_id
-		case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
-			if (compareSrvcId(evtParam->reg_for_notify.srvc_id, *m_pRemoteService->getSrvcId()) == false) {
-				break;
-			}
-			if (compareGattId(evtParam->reg_for_notify.char_id, m_charId) == false) {
-				break;
-			}
-			m_semaphoreRegForNotifyEvt.give();
-			break;
-		} // ESP_GATTC_REG_FOR_NOTIFY_EVT
-
-
-		//
-		// ESP_GATTC_WRITE_CHAR_EVT
-		//
-		// write:
-		// esp_gatt_status_t  status
-		// uint16_t           conn_id
-		// esp_gatt_srvc_id_t srvc_id
-		// esp_gatt_id_t      char_id
-		// esp_gatt_id_t      descr_id
-		case ESP_GATTC_WRITE_CHAR_EVT: {
-			if (compareSrvcId(evtParam->write.srvc_id, *m_pRemoteService->getSrvcId()) == false) {
-				break;
-			}
-			if (evtParam->write.conn_id != m_pRemoteService->getClient()->getConnId()) {
-				break;
-			}
-			if (compareGattId(evtParam->write.char_id, m_charId) == false) {
-				break;
-			}
-			m_semaphoreWriteCharEvt.give();
-			break;
-		} // ESP_GATTC_WRITE_CHAR_EVT
-
-
-		default: {
-			break;
-		}
-	}
-}; // gattClientEventHandler
-
-
-BLEUUID BLERemoteCharacteristic::getUUID() {
-	return BLEUUID(m_charId.uuid);
-}
-
-/**
- * @brief Read an unsigned 16 bit value
- * @return The unsigned 16 bit value.
- */
-uint16_t BLERemoteCharacteristic::readUInt16(void) {
-	std::string value = readValue();
-	if (value.length() >= 2) {
-		return *(uint16_t*)(value.data());
-	}
-	return 0;
-} // readUInt16
-
-
-/**
- * @brief Read an unsigned 32 bit value.
- * @return the unsigned 32 bit value.
- */
-uint32_t BLERemoteCharacteristic::readUInt32(void) {
-	std::string value = readValue();
-	if (value.length() >= 4) {
-		return *(uint32_t*)(value.data());
-	}
-	return 0;
-} // readUInt32
-
-
-/**
- * @brief Read a byte value
- * @return The value as a byte
- */
-uint8_t BLERemoteCharacteristic::readUInt8(void) {
-	std::string value = readValue();
-	if (value.length() >= 1) {
-		return (uint8_t)value[0];
-	}
-	return 0;
-} // readUInt8
-
-
-/**
- * @brief Read the value of the remote characteristic.
- * @return The value of the remote characteristic.
- */
-std::string BLERemoteCharacteristic::readValue() {
-	ESP_LOGD(LOG_TAG, ">> readValue()");
-
-	m_semaphoreReadCharEvt.take("readValue");
-
-	// Ask the BLE subsystem to retrieve the value for the remote hosted characteristic.
-	esp_err_t errRc = ::esp_ble_gattc_read_char(
-		m_pRemoteService->getClient()->getGattcIf(),
-		m_pRemoteService->getClient()->getConnId(),
-		m_pRemoteService->getSrvcId(),
-		&m_charId,
-		ESP_GATT_AUTH_REQ_NONE);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_read_char: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return "";
-	}
-
-	// Block waiting for the event that indicates that the read has completed.  When it has, the std::string found
-	// in m_value will contain our data.
-	m_semaphoreReadCharEvt.wait("readValue");
-
-	ESP_LOGD(LOG_TAG, "<< readValue()");
-	return m_value;
-} // readValue
-
-
-/**
- * @brief Register for notifications.
- * @param [in] notifyCallback A callback to be invoked for a notification.
- * @return N/A.
- */
-void BLERemoteCharacteristic::registerForNotify(
-		void (*notifyCallback)(
-			BLERemoteCharacteristic* pBLERemoteCharacteristic,
-			uint8_t* pData,
-			size_t length,
-			bool isNotify)) {
-	ESP_LOGD(LOG_TAG, ">> registerForNotify()");
-
-	m_notifyCallback = notifyCallback; // Save the notification callback.
-
-	m_semaphoreRegForNotifyEvt.take("registerForNotify");
-
-	esp_err_t errRc = ::esp_ble_gattc_register_for_notify(
-		m_pRemoteService->getClient()->getGattcIf(),
-		*m_pRemoteService->getClient()->getPeerAddress().getNative(),
-		m_pRemoteService->getSrvcId(),
-		&m_charId);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_register_for_notify: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	m_semaphoreRegForNotifyEvt.wait("registerForNotify");
-
-	ESP_LOGD(LOG_TAG, "<< registerForNotify()");
-} // registerForNotify
-
-
-/**
- * @brief Convert a BLERemoteCharacteristic to a string representation;
- * @return a String representation.
- */
-std::string BLERemoteCharacteristic::toString() {
-	std::ostringstream ss;
-	ss << "Characteristic: uuid: " << BLEUUID(m_charId.uuid).toString() <<
-		", props: " << BLEUtils::characteristicPropertiesToString(m_charProp) <<
-		", inst_id: " << (int)m_charId.inst_id;
-	return ss.str();
-} // toString
-
-
-/**
- * @brief Write the new value for the characteristic.
- * @param [in] newValue The new value to write.
- * @param [in] response Do we expect a response?
- * @return N/A.
- */
-void BLERemoteCharacteristic::writeValue(std::string newValue, bool response) {
-	ESP_LOGD(LOG_TAG, ">> writeValue(), length: %d", newValue.length());
-
-	m_semaphoreWriteCharEvt.take("writeValue");
-
-	esp_err_t errRc = ::esp_ble_gattc_write_char(
-		m_pRemoteService->getClient()->getGattcIf(),
-		m_pRemoteService->getClient()->getConnId(),
-		m_pRemoteService->getSrvcId(),
-		&m_charId,
-		newValue.length(),
-		(uint8_t*)newValue.data(),
-		response?ESP_GATT_WRITE_TYPE_RSP:ESP_GATT_WRITE_TYPE_NO_RSP,
-		ESP_GATT_AUTH_REQ_NONE
-	);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_write_char: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	m_semaphoreWriteCharEvt.wait("writeValue");
-
-	ESP_LOGD(LOG_TAG, "<< writeValue");
-} // writeValue
-
-
-/**
- * @brief Write the new value for the characteristic.
- *
- * This is a convenience function.  Many BLE characteristics are a single byte of data.
- * @param [in] newValue The new byte value to write.
- * @param [in] response Whether we require a response from the write.
- * @return N/A.
- */
-void BLERemoteCharacteristic::writeValue(uint8_t newValue, bool response) {
-	writeValue(std::string(reinterpret_cast<char*>(&newValue), 1), response);
-} // writeValue
-
-
-/**
- * @brief Write the new value for the characteristic from a data buffer.
- * @param [in] data A pointer to a data buffer.
- * @param [in] length The length of the data in the data buffer.
- * @param [in] response Whether we require a response from the write.
- */
-void BLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool response) {
-	writeValue(std::string((char *)data, length), response);
-} // writeValue
-
-
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLERemoteCharacteristic.h b/components/cpp_utils/BLERemoteCharacteristic.h
deleted file mode 100644
index b5b22b6..0000000
--- a/components/cpp_utils/BLERemoteCharacteristic.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * BLERemoteCharacteristic.h
- *
- *  Created on: Jul 8, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEREMOTECHARACTERISTIC_H_
-#define COMPONENTS_CPP_UTILS_BLEREMOTECHARACTERISTIC_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include <string>
-
-#include <esp_gattc_api.h>
-
-#include "BLERemoteService.h"
-#include "BLEUUID.h"
-#include "FreeRTOS.h"
-
-class BLERemoteService;
-
-/**
- * @brief A model of a remote %BLE characteristic.
- */
-class BLERemoteCharacteristic {
-public:
-	BLERemoteCharacteristic(esp_gatt_id_t charId, esp_gatt_char_prop_t charProp, BLERemoteService* pRemoteService);
-
-	// Public member functions
-	BLEUUID     getUUID();
-	std::string readValue(void);
-	uint8_t     readUInt8(void);
-	uint16_t    readUInt16(void);
-	uint32_t    readUInt32(void);
-	void        registerForNotify(void (*notifyCallback)(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify));
-	void        writeValue(uint8_t* data, size_t length, bool response = false);
-	void        writeValue(std::string newValue, bool response = false);
-	void        writeValue(uint8_t newValue, bool response = false);
-	std::string toString(void);
-
-private:
-	friend class BLEClient;
-	friend class BLERemoteService;
-
-	// Private member functions
-	void gattClientEventHandler(
-		esp_gattc_cb_event_t      event,
-		esp_gatt_if_t             gattc_if,
-		esp_ble_gattc_cb_param_t *evtParam);
-
-	// Private properties
-	esp_gatt_id_t        m_charId;
-	esp_gatt_char_prop_t m_charProp;
-	BLERemoteService*    m_pRemoteService;
-	FreeRTOS::Semaphore  m_semaphoreReadCharEvt      = FreeRTOS::Semaphore("ReadCharEvt");
-	FreeRTOS::Semaphore  m_semaphoreRegForNotifyEvt  = FreeRTOS::Semaphore("RegForNotifyEvt");
-	FreeRTOS::Semaphore  m_semaphoreWriteCharEvt     = FreeRTOS::Semaphore("WriteCharEvt");
-	std::string          m_value;
-  void (*m_notifyCallback)(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify);
-}; // BLERemoteCharacteristic
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLEREMOTECHARACTERISTIC_H_ */
diff --git a/components/cpp_utils/BLERemoteDescriptor.cpp b/components/cpp_utils/BLERemoteDescriptor.cpp
deleted file mode 100644
index 2be312a..0000000
--- a/components/cpp_utils/BLERemoteDescriptor.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * BLERemoteDescriptor.cpp
- *
- *  Created on: Jul 8, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include "BLERemoteDescriptor.h"
-
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLERemoteDescriptor.h b/components/cpp_utils/BLERemoteDescriptor.h
deleted file mode 100644
index a8d944d..0000000
--- a/components/cpp_utils/BLERemoteDescriptor.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * BLERemoteDescriptor.h
- *
- *  Created on: Jul 8, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEREMOTEDESCRIPTOR_H_
-#define COMPONENTS_CPP_UTILS_BLEREMOTEDESCRIPTOR_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-/**
- * @brief A model of remote %BLE descriptor.
- */
-class BLERemoteDescriptor {
-public:
-};
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLEREMOTEDESCRIPTOR_H_ */
diff --git a/components/cpp_utils/BLERemoteService.cpp b/components/cpp_utils/BLERemoteService.cpp
deleted file mode 100644
index a29a758..0000000
--- a/components/cpp_utils/BLERemoteService.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * BLERemoteService.cpp
- *
- *  Created on: Jul 8, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include <sstream>
-#include "BLERemoteService.h"
-#include "BLEUtils.h"
-#include "GeneralUtils.h"
-#include <esp_log.h>
-#include <esp_err.h>
-
-static const char* LOG_TAG = "BLERemoteService";
-
-BLERemoteService::BLERemoteService(
-	esp_gatt_srvc_id_t srvcId,
-	BLEClient *pClient) {
-
-	m_srvcId  = srvcId;
-	m_pClient = pClient;
-	m_uuid    = BLEUUID(m_srvcId);
-	m_haveCharacteristics = false;
-}
-
-
-BLERemoteService::~BLERemoteService() {
-	removeCharacteristics();
-}
-
-static bool compareSrvcId(esp_gatt_srvc_id_t id1, esp_gatt_srvc_id_t id2) {
-	if (id1.id.inst_id != id2.id.inst_id) {
-		return false;
-	}
-	if (!BLEUUID(id1.id.uuid).equals(BLEUUID(id2.id.uuid))) {
-		return false;
-	}
-	return true;
-} // compareSrvcId
-
-
-/**
- * @brief Handle GATT Client events
- */
-void BLERemoteService::gattClientEventHandler(
-	esp_gattc_cb_event_t      event,
-	esp_gatt_if_t             gattc_if,
-	esp_ble_gattc_cb_param_t *evtParam) {
-	switch(event) {
-		//
-		// ESP_GATTC_GET_CHAR_EVT
-		//
-		// get_char:
-		// - esp_gatt_status_t    status
-		// - uin1t6_t             conn_id
-		// - esp_gatt_srvc_id_t   srvc_id
-		// - esp_gatt_id_t        char_id
-		// - esp_gatt_char_prop_t char_prop
-		//
-		case ESP_GATTC_GET_CHAR_EVT: {
-			// Is this event for this service?  If yes, then the local srvc_id and the event srvc_id will be
-			// the same.
-			if (compareSrvcId(m_srvcId, evtParam->get_char.srvc_id) == false) {
-				break;
-			}
-
-			// If the status is NOT OK then we have a problem and continue.
-			if (evtParam->get_char.status != ESP_GATT_OK) {
-				m_semaphoreGetCharEvt.give();
-				break;
-			}
-
-			// This is an indication that we now have the characteristic details for a characteristic owned
-			// by this service so remember it.
-			m_characteristicMap.insert(std::pair<std::string, BLERemoteCharacteristic*>(
-					BLEUUID(evtParam->get_char.char_id.uuid).toString(),
-					new BLERemoteCharacteristic(evtParam->get_char.char_id, evtParam->get_char.char_prop, this)	));
-
-
-			// Now that we have received a characteristic, lets ask for the next one.
-			esp_err_t errRc = ::esp_ble_gattc_get_characteristic(
-					m_pClient->getGattcIf(),
-					m_pClient->getConnId(),
-					&m_srvcId,
-					&evtParam->get_char.char_id);
-			if (errRc != ESP_OK) {
-				ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_characteristic: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-				break;
-			}
-
-			//m_semaphoreGetCharEvt.give();
-			break;
-		} // ESP_GATTC_GET_CHAR_EVT
-
-		default: {
-			break;
-		}
-	} // switch
-
-	// Send the event to each of the characteristics owned by this service.
-	for (auto &myPair : m_characteristicMap) {
-	   myPair.second->gattClientEventHandler(event, gattc_if, evtParam);
-	}
-} // gattClientEventHandler
-
-
-/**
- * @brief Get the characteristic object for the UUID.
- * @param [in] uuid Characteristic uuid.
- * @return Reference to the characteristic object.
- */
-BLERemoteCharacteristic* BLERemoteService::getCharacteristic(const char* uuid) {
-    return getCharacteristic(BLEUUID(uuid));
-}
-	
-	
-/**
- * @brief Get the characteristic object for the UUID.
- * @param [in] uuid Characteristic uuid.
- * @return Reference to the characteristic object.
- */
-BLERemoteCharacteristic* BLERemoteService::getCharacteristic(BLEUUID uuid) {
-// Design
-// ------
-// We wish to retrieve the characteristic given its UUID.  It is possible that we have not yet asked the
-// device what characteristics it has in which case we have nothing to match against.  If we have not
-// asked the device about its characteristics, then we do that now.  Once we get the results we can then
-// examine the characteristics map to see if it has the characteristic we are looking for.
-	if (!m_haveCharacteristics) {
-		getCharacteristics();
-	}
-	std::string v = uuid.toString();
-	for (auto &myPair : m_characteristicMap) {
-		if (myPair.first == v) {
-			return myPair.second;
-		}
-	}
-	return nullptr;
-} // getCharacteristic
-
-
-/**
- * @brief Retrieve all the characteristics for this service.
- * @return N/A
- */
-void BLERemoteService::getCharacteristics() {
-
-	ESP_LOGD(LOG_TAG, ">> getCharacteristics() for service: %s", getUUID().toString().c_str());
-
-	removeCharacteristics(); // Forget any previous characteristics.
-
-	m_semaphoreGetCharEvt.take("getCharacteristics");
-
-	esp_err_t errRc = ::esp_ble_gattc_get_characteristic(
-		m_pClient->getGattcIf(),
-		m_pClient->getConnId(),
-		&m_srvcId,
-		nullptr);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_characteristic: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	m_semaphoreGetCharEvt.wait("getCharacteristics"); // Wait for the characteristics to become available.
-
-	m_haveCharacteristics = true; // Remember that we have received the characteristics.
-	ESP_LOGD(LOG_TAG, "<< getCharacteristics()");
-} // getCharacteristics
-
-
-BLEClient* BLERemoteService::getClient() {
-	return m_pClient;
-}
-
-esp_gatt_srvc_id_t* BLERemoteService::getSrvcId() {
-	return &m_srvcId;
-}
-
-BLEUUID BLERemoteService::getUUID() {
-	return m_uuid;
-}
-
-
-/**
- * @brief Delete the characteristics in the characteristics map.
- * We maintain a map called m_characteristicsMap that contains pointers to BLERemoteCharacteristic
- * object references.  Since we allocated these in this class, we are also responsible for deleteing
- * them.  This method does just that.
- * @return N/A.
- */
-void BLERemoteService::removeCharacteristics() {
-	for (auto &myPair : m_characteristicMap) {
-	   delete myPair.second;
-	}
-	m_characteristicMap.empty();
-} // removeCharacteristics
-
-
-
-/**
- * @brief Create a string representation of this remote service.
- * @return A string representation of this remote service.
- */
-std::string BLERemoteService::toString() {
-	std::ostringstream ss;
-	ss << "Service: uuid: " + m_uuid.toString();
-	for (auto &myPair : m_characteristicMap) {
-		ss << "\n" << myPair.second->toString();
-	   // myPair.second is the value
-	}
-	return ss.str();
-} // toString
-
-
-
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLERemoteService.h b/components/cpp_utils/BLERemoteService.h
deleted file mode 100644
index 4393fbc..0000000
--- a/components/cpp_utils/BLERemoteService.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * BLERemoteService.h
- *
- *  Created on: Jul 8, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEREMOTESERVICE_H_
-#define COMPONENTS_CPP_UTILS_BLEREMOTESERVICE_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include <map>
-
-#include "BLEClient.h"
-#include "BLERemoteCharacteristic.h"
-#include "BLEUUID.h"
-#include "FreeRTOS.h"
-
-class BLEClient;
-class BLERemoteCharacteristic;
-
-
-/**
- * @brief A model of a remote %BLE service.
- */
-class BLERemoteService {
-public:
-	BLERemoteService(esp_gatt_srvc_id_t srvcId, BLEClient* pClient);
-	virtual ~BLERemoteService();
-
-	// Public methods
-	BLERemoteCharacteristic* getCharacteristic(const char* uuid);	
-	BLERemoteCharacteristic* getCharacteristic(BLEUUID uuid);
-	void                     getCharacteristics(void);
-	BLEClient*               getClient(void);
-	BLEUUID                  getUUID(void);
-	std::string              toString(void);
-
-private:
-	// Friends
-	friend class BLEClient;
-	friend class BLERemoteCharacteristic;
-
-	// Private methods
-	esp_gatt_srvc_id_t* getSrvcId(void);
-	void                gattClientEventHandler(
-		esp_gattc_cb_event_t      event,
-		esp_gatt_if_t             gattc_if,
-		esp_ble_gattc_cb_param_t* evtParam);
-	void                removeCharacteristics();
-
-	// Properties
-	std::map<std::string, BLERemoteCharacteristic *> m_characteristicMap;
-	bool                m_haveCharacteristics; // Have we previously obtained the characteristics.
-	BLEClient*          m_pClient;
-	FreeRTOS::Semaphore m_semaphoreGetCharEvt = FreeRTOS::Semaphore("GetCharEvt");
-	esp_gatt_srvc_id_t  m_srvcId;
-	BLEUUID             m_uuid;
-}; // BLERemoteService
-
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLEREMOTESERVICE_H_ */
diff --git a/components/cpp_utils/BLEScan.cpp b/components/cpp_utils/BLEScan.cpp
deleted file mode 100644
index 9fdcffd..0000000
--- a/components/cpp_utils/BLEScan.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * BLEScan.cpp
- *
- *  Created on: Jul 1, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-
-#include <esp_log.h>
-#include <esp_err.h>
-
-#include <map>
-
-#include "BLEAdvertisedDevice.h"
-#include "BLEScan.h"
-#include "BLEUtils.h"
-#include "GeneralUtils.h"
-
-static const char* LOG_TAG = "BLEScan";
-
-
-BLEScan::BLEScan() {
-	m_scan_params.scan_type          = BLE_SCAN_TYPE_PASSIVE; // Default is a passive scan.
-	m_scan_params.own_addr_type      = BLE_ADDR_TYPE_PUBLIC;
-	m_scan_params.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL;
-	setInterval(100);
-	setWindow(100);
-	m_pAdvertisedDeviceCallbacks = nullptr;
-	m_stopped = true;
-} // BLEScan
-
-
-
-/**
- * @brief Clear the history of previously detected advertised devices.
- * @return N/A
- */
-/*
-void BLEScan::clearAdvertisedDevices() {
-	for (int i=0; i<m_vectorAvdertisedDevices.size(); i++) {
-		delete m_vectorAvdertisedDevices[i];
-	}
-	m_vectorAvdertisedDevices.clear();
-} // clearAdvertisedDevices
-*/
-
-
-/**
- * @brief Handle GAP events related to scans.
- * @param [in] event The event type for this event.
- * @param [in] param Parameter data for this event.
- */
-void BLEScan::gapEventHandler(
-	esp_gap_ble_cb_event_t  event,
-	esp_ble_gap_cb_param_t* param) {
-
-	switch(event) {
-
-	// ESP_GAP_BLE_SCAN_RESULT_EVT
-	// ---------------------------
-	// scan_rst:
-	// esp_gap_search_evt_t search_evt
-	// esp_bd_addr_t bda
-	// esp_bt_dev_type_t dev_type
-	// esp_ble_addr_type_t ble_addr_type
-	// esp_ble_evt_type_t ble_evt_type
-	// int rssi
-	// uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX]
-	// int flag
-	// int num_resps
-	// uint8_t adv_data_len
-	// uint8_t scan_rsp_len
-		case ESP_GAP_BLE_SCAN_RESULT_EVT: {
-
-			switch(param->scan_rst.search_evt) {
-				case ESP_GAP_SEARCH_INQ_CMPL_EVT: {
-					m_stopped = true;
-					m_semaphoreScanEnd.give();
-					break;
-				} // ESP_GAP_SEARCH_INQ_CMPL_EVT
-
-				case ESP_GAP_SEARCH_INQ_RES_EVT: {
-					if (m_stopped) { // If we are not scanning, nothing to do with the extra results.
-						break;
-					}
-
-// Examine our list of previously scanned addresses and, if we found this one already,
-// ignore it.
-					BLEAddress advertisedAddress(param->scan_rst.bda);
-					bool found = false;
-					/*
-					for (int i=0; i<m_vectorAvdertisedDevices.size(); i++) {
-						if (m_vectorAvdertisedDevices[i]->getAddress().equals(advertisedAddress)) {
-							found = true;
-							break;
-						}
-					}
-					*/
-					for (int i=0; i<m_scanResults.getCount(); i++) {
-						if (m_scanResults.getDevice(i).getAddress().equals(advertisedAddress)) {
-							found = true;
-							break;
-						}
-					}
-					if (found) {
-						ESP_LOGD(LOG_TAG, "Ignoring %s, already seen it.", advertisedAddress.toString().c_str());
-						break;
-					}
-
-					// We now construct a model of the advertised device that we have just found for the first
-					// time.
-					BLEAdvertisedDevice advertisedDevice;
-					advertisedDevice.setAddress(advertisedAddress);
-					advertisedDevice.setRSSI(param->scan_rst.rssi);
-					advertisedDevice.setAdFlag(param->scan_rst.flag);
-					advertisedDevice.parseAdvertisement((uint8_t*)param->scan_rst.ble_adv);
-					advertisedDevice.setScan(this);
-
-					//m_vectorAvdertisedDevices.push_back(pAdvertisedDevice);
-					if (m_pAdvertisedDeviceCallbacks) {
-						m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
-					}
-
-					m_scanResults.m_vectorAdvertisedDevices.push_back(advertisedDevice);
-
-					break;
-				} // ESP_GAP_SEARCH_INQ_RES_EVT
-
-				default: {
-					break;
-				}
-			} // switch - search_evt
-
-
-			break;
-		} // ESP_GAP_BLE_SCAN_RESULT_EVT
-
-		default: {
-			break;
-		} // default
-	} // End switch
-} // gapEventHandler
-
-
-/*
-void BLEScan::onResults() {
-	ESP_LOGD(LOG_TAG, ">> onResults: default");
-	ESP_LOGD(LOG_TAG, "<< onResults");
-} // onResults
-*/
-
-
-/**
- * @brief Should we perform an active or passive scan?
- * The default is a passive scan.  An active scan means that we will wish a scan response.
- * @param [in] active If true, we perform an active scan otherwise a passive scan.
- * @return N/A.
- */
-void BLEScan::setActiveScan(bool active) {
-	if (active) {
-		m_scan_params.scan_type = BLE_SCAN_TYPE_ACTIVE;
-	} else {
-		m_scan_params.scan_type = BLE_SCAN_TYPE_PASSIVE;
-	}
-} // setActiveScan
-
-
-/**
- * @brief Set the call backs to be invoked.
- * @param [in] pAdvertisedDeviceCallbacks Call backs to be invoked.
- */
-void BLEScan::setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks) {
-	m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
-} // setAdvertisedDeviceCallbacks
-
-
-/**
- * @brief Set the interval to scan.
- * @param [in] The interval in msecs.
- */
-void BLEScan::setInterval(uint16_t intervalMSecs) {
-	m_scan_params.scan_interval = intervalMSecs / 0.625;
-} // setInterval
-
-
-/**
- * @brief Set the window to actively scan.
- * @param [in] windowMSecs How long to actively scan.
- */
-void BLEScan::setWindow(uint16_t windowMSecs) {
-	m_scan_params.scan_window = windowMSecs / 0.625;
-} // setWindow
-
-
-/**
- * @brief Start scanning.
- * @param [in] duration The duration in seconds for which to scan.
- * @return N/A.
- */
-BLEScanResults BLEScan::start(uint32_t duration) {
-	ESP_LOGD(LOG_TAG, ">> start(%d)", duration);
-
-	m_semaphoreScanEnd.take("start");
-
-	m_scanResults.m_vectorAdvertisedDevices.empty();
-
-	esp_err_t errRc = ::esp_ble_gap_set_scan_params(&m_scan_params);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gap_set_scan_params: err: %d, text: %s", errRc, GeneralUtils::errorToString(errRc));
-		m_semaphoreScanEnd.give();
-		return m_scanResults;
-	}
-
-	errRc = ::esp_ble_gap_start_scanning(duration);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gap_start_scanning: err: %d, text: %s", errRc, GeneralUtils::errorToString(errRc));
-		m_semaphoreScanEnd.give();
-		return m_scanResults;
-	}
-
-	m_stopped = false;
-
-	m_semaphoreScanEnd.take("start");
-	m_semaphoreScanEnd.give();
-
-	ESP_LOGD(LOG_TAG, "<< start()");
-	return m_scanResults;
-} // start
-
-
-/**
- * @brief Stop an in progress scan.
- * @return N/A.
- */
-void BLEScan::stop() {
-	ESP_LOGD(LOG_TAG, ">> stop()");
-
-	esp_err_t errRc = ::esp_ble_gap_stop_scanning();
-
-	m_stopped = true;
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gap_stop_scanning: err: %d, text: %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	m_semaphoreScanEnd.give();
-
-	ESP_LOGD(LOG_TAG, "<< stop()");
-} // stop
-
-
-/**
- * @brief Return the count of devices found in the last scan.
- * @return The number of devices found in the last scan.
- */
-int BLEScanResults::getCount() {
-	return m_vectorAdvertisedDevices.size();
-} // getCount
-
-
-/**
- * @brief Return the specified device at the given index.
- * The index should be between 0 and getCount()-1.
- * @param [in] i The index of the device.
- * @return The device at the specified index.
- */
-BLEAdvertisedDevice BLEScanResults::getDevice(uint32_t i) {
-	return m_vectorAdvertisedDevices.at(i);
-}
-
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLEScan.h b/components/cpp_utils/BLEScan.h
deleted file mode 100644
index f9575ea..0000000
--- a/components/cpp_utils/BLEScan.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * BLEScan.h
- *
- *  Created on: Jul 1, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLESCAN_H_
-#define COMPONENTS_CPP_UTILS_BLESCAN_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_gap_ble_api.h>
-
-#include <vector>
-#include "BLEAdvertisedDevice.h"
-#include "BLEClient.h"
-#include "FreeRTOS.h"
-
-class BLEAdvertisedDevice;
-class BLEAdvertisedDeviceCallbacks;
-class BLEClient;
-class BLEScan;
-
-class BLEScanResults {
-public:
-	int getCount();
-	BLEAdvertisedDevice getDevice(uint32_t i);
-private:
-	friend BLEScan;
-	std::vector<BLEAdvertisedDevice> m_vectorAdvertisedDevices;
-};
-
-/**
- * @brief Perform and manage %BLE scans.
- *
- * Scanning is associated with a %BLE client that is attempting to locate BLE servers.
- */
-class BLEScan {
-public:
-	BLEScan();
-
-	//virtual void onResults();
-	void           setActiveScan(bool active);
-	void           setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks);
-	void           setInterval(uint16_t intervalMSecs);
-	void           setWindow(uint16_t windowMSecs);
-	BLEScanResults start(uint32_t duration);
-	void           stop();
-
-private:
-	friend class BLEDevice;
-	void         gapEventHandler(
-		esp_gap_ble_cb_event_t  event,
-		esp_ble_gap_cb_param_t* param);
-	void parseAdvertisement(BLEClient* pRemoteDevice, uint8_t *payload);
-
-
-	esp_ble_scan_params_t         m_scan_params;
-	BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks;
-	bool                          m_stopped;
-	FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd");
-	//std::vector<BLEAdvertisedDevice*> m_vectorAvdertisedDevices;
-	BLEScanResults m_scanResults;
-}; // BLEScan
-
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLESCAN_H_ */
diff --git a/components/cpp_utils/BLEServer.cpp b/components/cpp_utils/BLEServer.cpp
deleted file mode 100644
index be9773d..0000000
--- a/components/cpp_utils/BLEServer.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * BLEServer.cpp
- *
- *  Created on: Apr 16, 2017
- *      Author: kolban
- */
-
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_log.h>
-#include <bt.h>
-#include <esp_bt_main.h>
-#include <esp_gap_ble_api.h>
-#include <esp_gatts_api.h>
-#include "BLEDevice.h"
-#include "BLEServer.h"
-#include "BLEService.h"
-#include "BLEUtils.h"
-#include <string.h>
-#include <string>
-#include <gatt_api.h>
-#include <unordered_set>
-
-static const char* LOG_TAG = "BLEServer";
-
-
-/**
- * @brief Construct a %BLE Server
- *
- * This class is not designed to be individually instantiated.  Instead one should create a server by asking
- * the BLEDevice class.
- */
-BLEServer::BLEServer() {
-	m_appId            = -1;
-	m_gatts_if         = -1;
-	m_connectedCount   = 0;
-	m_connId           = -1;
-	BLEDevice::m_bleServer   = this;
-	m_pServerCallbacks = nullptr;
-
-	createApp(0);
-} // BLEServer
-
-
-void BLEServer::createApp(uint16_t appId) {
-	m_appId = appId;
-	registerApp();
-}
-
-
-/**
- * @brief Create a %BLE Service.
- *
- * With a %BLE server, we can host one or more services.  Invoking this function causes the creation of a definition
- * of a new service.  Every service must have a unique UUID.
- * @param [in] uuid The UUID of the new service.
- * @return A reference to the new service object.
- */
-BLEService* BLEServer::createService(const char* uuid) {
-	return createService(BLEUUID(uuid));
-}
-
-
-/**
- * @brief Create a %BLE Service.
- *
- * With a %BLE server, we can host one or more services.  Invoking this function causes the creation of a definition
- * of a new service.  Every service must have a unique UUID.
- * @param [in] uuid The UUID of the new service.
- * @return A reference to the new service object.
- */
-BLEService* BLEServer::createService(BLEUUID uuid) {
-	ESP_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
-	m_semaphoreCreateEvt.take("createService");
-
-	// Check that a service with the supplied UUID does not already exist.
-	if (m_serviceMap.getByUUID(uuid) != nullptr) {
-		ESP_LOGE(LOG_TAG, "<< Attempt to create a new service with uuid %s but a service with that UUID already exists.",
-			uuid.toString().c_str());
-		m_semaphoreCreateEvt.give();
-		return nullptr;
-	}
-
-	BLEService* pService = new BLEService(uuid);
-	m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server.
-	pService->executeCreate(this);          // Perform the API calls to actually create the service.
-
-	m_semaphoreCreateEvt.wait("createService");
-
-	ESP_LOGD(LOG_TAG, "<< createService");
-	return pService;
-} // createService
-
-
-/**
- * @brief Retrieve the advertising object that can be used to advertise the existence of the server.
- *
- * @return An advertising object.
- */
-BLEAdvertising* BLEServer::getAdvertising() {
-	return &m_bleAdvertising;
-}
-
-uint16_t BLEServer::getConnId() {
-	return m_connId;
-}
-
-
-/**
- * @brief Return the number of connected clients.
- * @return The number of connected clients.
- */
-uint32_t BLEServer::getConnectedCount() {
-	return m_connectedCount;
-} // getConnectedCount
-
-
-uint16_t BLEServer::getGattsIf() {
-	return m_gatts_if;
-}
-
-/**
- * @brief Handle a receiver GAP event.
- *
- * @param [in] event
- * @param [in] param
- */
-void BLEServer::handleGAPEvent(
-		esp_gap_ble_cb_event_t  event,
-		esp_ble_gap_cb_param_t* param) {
-	ESP_LOGD(LOG_TAG, "BLEServer ... handling GAP event!");
-	switch(event) {
-		case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: {
-			/*
-			esp_ble_adv_params_t adv_params;
-			adv_params.adv_int_min       = 0x20;
-			adv_params.adv_int_max       = 0x40;
-			adv_params.adv_type          = ADV_TYPE_IND;
-			adv_params.own_addr_type     = BLE_ADDR_TYPE_PUBLIC;
-			adv_params.channel_map       = ADV_CHNL_ALL;
-			adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY;
-			ESP_LOGD(tag, "Starting advertising");
-			esp_err_t errRc = ::esp_ble_gap_start_advertising(&adv_params);
-			if (errRc != ESP_OK) {
-				ESP_LOGE(tag, "esp_ble_gap_start_advertising: rc=%d %s", errRc, espToString(errRc));
-				return;
-			}
-			*/
-			break;
-		}
-		default:
-			break;
-	}
-} // handleGAPEvent
-
-
-
-/**
- * @brief Handle a GATT Server Event.
- *
- * @param [in] event
- * @param [in] gatts_if
- * @param [in] param
- *
- */
-void BLEServer::handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t* param) {
-
-	ESP_LOGD(LOG_TAG, ">> handleGATTServerEvent: %s",
-			BLEUtils::gattServerEventTypeToString(event).c_str());
-
-	// Invoke the handler for every Service we have.
-	m_serviceMap.handleGATTServerEvent(event, gatts_if, param);
-
-	switch(event) {
-
-
-		// ESP_GATTS_CONNECT_EVT
-		// connect:
-		// - uint16_t conn_id
-		// - esp_bd_addr_t remote_bda
-		// - bool is_connected
-		case ESP_GATTS_CONNECT_EVT: {
-			m_connId = param->connect.conn_id; // Save the connection id.
-			if (m_pServerCallbacks != nullptr) {
-				m_pServerCallbacks->onConnect(this);
-			}
-			m_connectedCount++;
-			break;
-		} // ESP_GATTS_CONNECT_EVT
-
-
-		// ESP_GATTS_REG_EVT
-		// reg:
-		// - esp_gatt_status_t status
-		// - uint16_t app_id
-		case ESP_GATTS_REG_EVT: {
-			m_gatts_if = gatts_if;
-
-			m_semaphoreRegisterAppEvt.give();
-			break;
-		} // ESP_GATTS_REG_EVT
-
-
-		// ESP_GATTS_CREATE_EVT
-		// Called when a new service is registered as having been created.
-		//
-		// create:
-		// * esp_gatt_status_t status
-		// * uint16_t service_handle
-		// * esp_gatt_srvc_id_t service_id
-		//
-		case ESP_GATTS_CREATE_EVT: {
-			BLEService* pService = m_serviceMap.getByUUID(param->create.service_id.id.uuid);
-			m_serviceMap.setByHandle(param->create.service_handle, pService);
-			//pService->setHandle(param->create.service_handle);
-			m_semaphoreCreateEvt.give();
-			break;
-		} // ESP_GATTS_CREATE_EVT
-
-
-		// ESP_GATTS_READ_EVT - A request to read the value of a characteristic has arrived.
-		//
-		// read:
-		// - uint16_t conn_id
-		// - uint32_t trans_id
-		// - esp_bd_addr_t bda
-		// - uint16_t handle
-		// - uint16_t offset
-		// - bool is_long
-		// - bool need_rsp
-		//
-		case ESP_GATTS_READ_EVT: {
-			break;
-		} // ESP_GATTS_READ_EVT
-
-
-		// ESP_GATTS_WRITE_EVT - A request to write the value of a characteristic has arrived.
-		//
-		// write:
-		// - uint16_t conn_id
-		// - uint16_t trans_id
-		// - esp_bd_addr_t bda
-		// - uint16_t handle
-		// - uint16_t offset
-		// - bool need_rsp
-		// - bool is_prep
-		// - uint16_t len
-		// - uint8_t *value
-
-		case ESP_GATTS_WRITE_EVT: {
-			break;
-		}
-
-		// ESP_GATTS_DISCONNECT_EVT
-		// If we receive a disconnect event then invoke the callback for disconnects (if one is present).
-		// we also want to start advertising again.
-		case ESP_GATTS_DISCONNECT_EVT: {
-			m_connectedCount--;
-			if (m_pServerCallbacks != nullptr) {
-				m_pServerCallbacks->onDisconnect(this);
-			}
-			startAdvertising();
-			break;
-		} // ESP_GATTS_DISCONNECT_EVT
-
-
-		// ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service.
-		// add_char:
-		// - esp_gatt_status_t status
-		// - uint16_t attr_handle
-		// - uint16_t service_handle
-		// - esp_bt_uuid_t char_uuid
-		case ESP_GATTS_ADD_CHAR_EVT: {
-			break;
-		} // ESP_GATTS_ADD_CHAR_EVT
-
-
-		default: {
-			break;
-		}
-	}
-	ESP_LOGD(LOG_TAG, "<< handleGATTServerEvent");
-} // handleGATTServerEvent
-
-
-/**
- * @brief Register the app.
- *
- * @return N/A
- */
-void BLEServer::registerApp() {
-	ESP_LOGD(LOG_TAG, ">> registerApp - %d", m_appId);
-	m_semaphoreRegisterAppEvt.take("registerApp"); // Take the mutex, will be released by ESP_GATTS_REG_EVT event.
-	::esp_ble_gatts_app_register(m_appId);
-	m_semaphoreRegisterAppEvt.wait("registerApp");
-	ESP_LOGD(LOG_TAG, "<< registerApp");
-} // registerApp
-
-
-/**
- * @brief Set the callbacks.
- *
- * As a %BLE server operates, it will generate server level events such as a new client connecting or a previous client
- * disconnecting.  This function can be called to register a callback handler that will be invoked when these
- * events are detected.
- *
- * @param [in] pCallbacks The callbacks to be invoked.
- */
-void BLEServer::setCallbacks(BLEServerCallbacks* pCallbacks) {
-	m_pServerCallbacks = pCallbacks;
-} // setCallbacks
-
-
-/**
- * @brief Start advertising.
- *
- * Start the server advertising its existence.  This is a convenience function and is equivalent to
- * retrieving the advertising object and invoking start upon it.
- */
-void BLEServer::startAdvertising() {
-	ESP_LOGD(LOG_TAG, ">> startAdvertising");
-	m_bleAdvertising.start();
-	ESP_LOGD(LOG_TAG, "<< startAdvertising");
-} // startAdvertising
-
-
-/*
-void BLEServer::addCharacteristic(BLECharacteristic *characteristic, BLEService *pService) {
-	ESP_LOGD(tag, "Adding characteristic (esp_ble_gatts_add_char): uuid=%s, serviceHandle=0x%.2x",
-		characteristic->m_bleUUID.toString().c_str(),
-		pService->getHandle());
-
-	m_characteristicMap.setByUUID(characteristic->m_bleUUID, characteristic);
-
-	esp_err_t errRc = ::esp_ble_gatts_add_char(
-		pService->getHandle(),
-		characteristic->getUUID().getNative(),
-		(esp_gatt_perm_t)(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
-		characteristic->getProperties(),
-		&characteristic->m_value,
-		NULL);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(tag, "esp_ble_gatts_add_char: rc=%d %s", errRc, espToString(errRc));
-		return;
-	}
-}
-*/
-
-#endif // CONFIG_BT_ENABLED
diff --git a/components/cpp_utils/BLEServer.h b/components/cpp_utils/BLEServer.h
deleted file mode 100644
index c6307bc..0000000
--- a/components/cpp_utils/BLEServer.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * BLEServer.h
- *
- *  Created on: Apr 16, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLESERVER_H_
-#define COMPONENTS_CPP_UTILS_BLESERVER_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_gatts_api.h>
-
-#include <string>
-#include <string.h>
-
-#include "BLEUUID.h"
-#include "BLEAdvertising.h"
-#include "BLECharacteristic.h"
-#include "BLEService.h"
-#include "FreeRTOS.h"
-
-class BLEServerCallbacks;
-
-
-/**
- * @brief A data structure that manages the %BLE servers owned by a BLE server.
- */
-class BLEServiceMap {
-public:
-	BLEService* getByHandle(uint16_t handle);
-	BLEService* getByUUID(const char* uuid);	
-	BLEService* getByUUID(BLEUUID uuid);
-	void        handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t* param);
-	void        setByHandle(uint16_t handle, BLEService* service);
-	void        setByUUID(const char* uuid, BLEService* service);
-	void        setByUUID(BLEUUID uuid, BLEService* service);
-	std::string toString();
-
-private:
-	std::map<std::string, BLEService*> m_uuidMap;
-	std::map<uint16_t, BLEService*>    m_handleMap;
-};
-
-
-/**
- * @brief The model of a %BLE server.
- */
-class BLEServer {
-public:
-	BLEServer();
-
-
-	uint32_t        getConnectedCount();
-	BLEService*     createService(const char* uuid);	
-	BLEService*     createService(BLEUUID uuid);
-	BLEAdvertising* getAdvertising();
-	void            setCallbacks(BLEServerCallbacks *pCallbacks);
-	void            startAdvertising();
-
-
-private:
-	friend class BLEService;
-	friend class BLECharacteristic;
-	friend class BLEDevice;
-	esp_ble_adv_data_t  m_adv_data;
-	uint16_t            m_appId;
-	BLEAdvertising      m_bleAdvertising;
-  uint16_t						m_connId;
-  uint32_t            m_connectedCount;
-  uint16_t            m_gatts_if;
-	FreeRTOS::Semaphore m_semaphoreRegisterAppEvt = FreeRTOS::Semaphore("RegisterAppEvt");
-	FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
-	BLEServiceMap       m_serviceMap;
-	BLEServerCallbacks* m_pServerCallbacks;
-
-	void            createApp(uint16_t appId);
-	uint16_t        getConnId();
-	uint16_t        getGattsIf();
-	void            handleGAPEvent(esp_gap_ble_cb_event_t event,	esp_ble_gap_cb_param_t *param);
-	void            handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
-	void            registerApp();
-}; // BLEServer
-
-
-/**
- * @brief Callbacks associated with the operation of a %BLE server.
- */
-class BLEServerCallbacks {
-public:
-	virtual ~BLEServerCallbacks() {};
-	/**
-	 * @brief Handle a new client connection.
-	 *
-	 * When a new client connects, we are invoked.
-	 *
-	 * @param [in] pServer A reference to the %BLE server that received the client connection.
-	 */
-	virtual void onConnect(BLEServer* pServer);
-
-	/**
-	 * @brief Handle an existing client disconnection.
-	 *
-	 * When an existing client disconnects, we are invoked.
-	 *
-	 * @param [in] pServer A reference to the %BLE server that received the existing client disconnection.
-	 */
-	virtual void onDisconnect(BLEServer* pServer);
-}; // BLEServerCallbacks
-
-
-
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLESERVER_H_ */
diff --git a/components/cpp_utils/BLEServerCallbacks.cpp b/components/cpp_utils/BLEServerCallbacks.cpp
deleted file mode 100644
index 8808720..0000000
--- a/components/cpp_utils/BLEServerCallbacks.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * BLEServerCallbacks.cpp
- *
- *  Created on: Jul 4, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include "BLEServer.h"
-#include <esp_log.h>
-static const char* LOG_TAG = "BLEServerCallbacks";
-
-void BLEServerCallbacks::onConnect(BLEServer* pServer) {
-	ESP_LOGD(LOG_TAG, ">> onConnect(): Default");
-	ESP_LOGD(LOG_TAG, "<< onConnect()");
-}
-
-void BLEServerCallbacks::onDisconnect(BLEServer* pServer) {
-	ESP_LOGD(LOG_TAG, ">> onDisconnect(): Default");
-	ESP_LOGD(LOG_TAG, "<< onDisconnect()");
-}
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLEService.cpp b/components/cpp_utils/BLEService.cpp
deleted file mode 100644
index ec16db8..0000000
--- a/components/cpp_utils/BLEService.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * BLEService.cpp
- *
- *  Created on: Mar 25, 2017
- *      Author: kolban
- */
-
-// A service is identified by a UUID.  A service is also the container for one or more characteristics.
-
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_err.h>
-#include <esp_gatts_api.h>
-#include <esp_log.h>
-
-#include <iomanip>
-#include <sstream>
-#include <string>
-
-#include "BLEServer.h"
-#include "BLEService.h"
-#include "BLEUtils.h"
-#include "GeneralUtils.h"
-
-#define NULL_HANDLE (0xffff)
-
-static const char* LOG_TAG = "BLEService"; // Tag for logging.
-
-/**
- * @brief Construct an instance of the BLEService
- * @param [in] uuid The UUID of the service.
- */
-BLEService::BLEService(const char* uuid) : BLEService(BLEUUID(uuid)) {
-}
-
-
-/**
- * @brief Construct an instance of the BLEService
- * @param [in] uuid The UUID of the service.
- */
-BLEService::BLEService(BLEUUID uuid) {
-	m_uuid     = uuid;
-	m_handle   = NULL_HANDLE;
-	m_pServer  = nullptr;
-	//m_serializeMutex.setName("BLEService");
-	m_lastCreatedCharacteristic = nullptr;
-} // BLEService
-
-
-/**
- * @brief Create the service.
- * Create the service.
- * @param [in] gatts_if The handle of the GATT server interface.
- * @return N/A.
- */
-void BLEService::executeCreate(BLEServer *pServer) {
-	ESP_LOGD(LOG_TAG, ">> executeCreate() - Creating service (esp_ble_gatts_create_service) service uuid: %s", getUUID().toString().c_str());
-
-	m_pServer          = pServer;
-	esp_gatt_srvc_id_t srvc_id;
-	srvc_id.id.inst_id = 0;
-	srvc_id.id.uuid    = *m_uuid.getNative();
-
-	m_semaphoreCreateEvt.take("executeCreate"); // Take the mutex and release at event ESP_GATTS_CREATE_EVT
-
-	esp_err_t errRc = ::esp_ble_gatts_create_service(getServer()->getGattsIf(), &srvc_id, 10);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "esp_ble_gatts_create_service: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	m_semaphoreCreateEvt.wait("executeCreate");
-
-	ESP_LOGD(LOG_TAG, "<< executeCreate");
-} // executeCreate
-
-
-/**
- * @brief Dump details of this BLE GATT service.
- * @return N/A.
- */
-void BLEService::dump() {
-	ESP_LOGD(LOG_TAG, "Service: uuid:%s, handle: 0x%.2x",
-		m_uuid.toString().c_str(),
-		m_handle);
-	ESP_LOGD(LOG_TAG, "Characteristics:\n%s", m_characteristicMap.toString().c_str());
-} // dump
-
-/*
-void BLEService::setService(esp_gatt_srvc_id_t srvc_id) {
-	m_srvc_id = srvc_id;
-}
-*/
-
-/*
-esp_gatt_srvc_id_t BLEService::getService() {
-	return m_srvc_id;
-}
-*/
-
-
-/**
- * @brief Get the UUID of the service.
- * @return the UUID of the service.
- */
-BLEUUID BLEService::getUUID() {
-	return m_uuid;
-} // getUUID
-
-
-/**
- * @brief Start the service.
- * Here we wish to start the service which means that we will respond to partner requests about it.
- * Starting a service also means that we can create the corresponding characteristics.
- * @return Start the service.
- */
-void BLEService::start() {
-// We ask the BLE runtime to start the service and then create each of the characteristics.
-// We start the service through its local handle which was returned in the ESP_GATTS_CREATE_EVT event
-// obtained as a result of calling esp_ble_gatts_create_service().
-//
-	ESP_LOGD(LOG_TAG, ">> start(): Starting service (esp_ble_gatts_start_service): %s", toString().c_str());
-	if (m_handle == NULL_HANDLE) {
-		ESP_LOGE(LOG_TAG, "<< !!! We attempted to start a service but don't know its handle!");
-		return;
-	}
-
-
-	BLECharacteristic *pCharacteristic = m_characteristicMap.getFirst();
-
-	while(pCharacteristic != nullptr) {
-		m_lastCreatedCharacteristic = pCharacteristic;
-		pCharacteristic->executeCreate(this);
-
-		pCharacteristic = m_characteristicMap.getNext();
-	}
-	// Start each of the characteristics ... these are found in the m_characteristicMap.
-
-	m_semaphoreStartEvt.take("start");
-	esp_err_t errRc = ::esp_ble_gatts_start_service(m_handle);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_start_service: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-	m_semaphoreStartEvt.wait("start");
-
-	ESP_LOGD(LOG_TAG, "<< start()");
-} // start
-
-
-/**
- * @brief Set the handle associated with this service.
- * @param [in] handle The handle associated with the service.
- */
-void BLEService::setHandle(uint16_t handle) {
-	ESP_LOGD(LOG_TAG, ">> setHandle - Handle=0x%.2x, service UUID=%s)", handle, getUUID().toString().c_str());
-	if (m_handle != NULL_HANDLE) {
-		ESP_LOGE(LOG_TAG, "!!! Handle is already set %.2x", m_handle);
-		return;
-	}
-	m_handle = handle;
-	ESP_LOGD(LOG_TAG, "<< setHandle");
-} // setHandle
-
-
-/**
- * @brief Get the handle associated with this service.
- * @return The handle associated with this service.
- */
-uint16_t BLEService::getHandle() {
-	return m_handle;
-} // getHandle
-
-
-/**
- * @brief Add a characteristic to the service.
- * @param [in] pCharacteristic A pointer to the characteristic to be added.
- */
-void BLEService::addCharacteristic(BLECharacteristic* pCharacteristic) {
-// We maintain a mapping of characteristics owned by this service.  These are managed by the
-// BLECharacteristicMap class instance found in m_characteristicMap.  We add the characteristic
-// to the map and then ask the service to add the characteristic at the BLE level (ESP-IDF).
-//
-	ESP_LOGD(LOG_TAG, ">> addCharacteristic()");
-	ESP_LOGD(LOG_TAG, "Adding characteristic (esp_ble_gatts_add_char): uuid=%s to service: %s",
-		pCharacteristic->getUUID().toString().c_str(),
-		toString().c_str());
-
-	// Check that we don't add the same characteristic twice.
-	if (m_characteristicMap.getByUUID(pCharacteristic->getUUID()) != nullptr) {
-		ESP_LOGE(LOG_TAG, "<< Attempt to add a characteristic but we already have one with this UUID");
-		return;
-	}
-
-	// Remember this characteristic in our map of characteristics.  At this point, we can lookup by UUID
-	// but not by handle.  The handle is allocated to us on the ESP_GATTS_ADD_CHAR_EVT.
-	m_characteristicMap.setByUUID(pCharacteristic->getUUID(), pCharacteristic);
-
-	ESP_LOGD(LOG_TAG, "<< addCharacteristic()");
-} // addCharacteristic
-
-
-/**
- * @brief Create a new BLE Characteristic associated with this service.
- * @param [in] uuid - The UUID of the characteristic.
- * @param [in] properties - The properties of the characteristic.
- * @return The new BLE characteristic.
- */
-BLECharacteristic* BLEService::createCharacteristic(const char* uuid, uint32_t properties) {
-	return createCharacteristic(BLEUUID(uuid), properties);
-}
-	
-/**
- * @brief Create a new BLE Characteristic associated with this service.
- * @param [in] uuid - The UUID of the characteristic.
- * @param [in] properties - The properties of the characteristic.
- * @return The new BLE characteristic.
- */
-BLECharacteristic* BLEService::createCharacteristic(BLEUUID uuid, uint32_t properties) {
-	BLECharacteristic *pCharacteristic = new BLECharacteristic(uuid, properties);
-	addCharacteristic(pCharacteristic);
-	return pCharacteristic;
-} // createCharacteristic
-
-
-/**
- * @brief Handle a GATTS server event.
- */
-void BLEService::handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t *param) {
-
-
-	switch(event) {
-	  // ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service.
-		// add_char:
-		// - esp_gatt_status_t status
-		// - uint16_t attr_handle
-		// - uint16_t service_handle
-		// - esp_bt_uuid_t char_uuid
-
-		// If we have reached the correct service, then locate the characteristic and remember the handle
-		// for that characteristic.
-		case ESP_GATTS_ADD_CHAR_EVT: {
-			if (m_handle == param->add_char.service_handle) {
-				BLECharacteristic *pCharacteristic = getCharacteristic(BLEUUID(param->add_char.char_uuid));
-				if (pCharacteristic == nullptr) {
-					ESP_LOGE(LOG_TAG, "Expected to find characteristic with UUID: %s, but didnt!",
-							BLEUUID(param->add_char.char_uuid).toString().c_str());
-					dump();
-					m_semaphoreAddCharEvt.give();
-					break;
-				}
-				pCharacteristic->setHandle(param->add_char.attr_handle);
-				m_characteristicMap.setByHandle(param->add_char.attr_handle, pCharacteristic);
-				//ESP_LOGD(tag, "Characteristic map: %s", m_characteristicMap.toString().c_str());
-				m_semaphoreAddCharEvt.give();
-				break;
-			} // Reached the correct service.
-			break;
-		} // ESP_GATTS_ADD_CHAR_EVT
-
-		// ESP_GATTS_START_EVT
-		//
-		// start:
-		// esp_gatt_status_t status
-		// uint16_t service_handle
-		case ESP_GATTS_START_EVT: {
-			if (param->start.service_handle == getHandle()) {
-				m_semaphoreStartEvt.give();
-			}
-			break;
-		} // ESP_GATTS_START_EVT
-
-
-		// ESP_GATTS_CREATE_EVT
-		// Called when a new service is registered as having been created.
-		//
-		// create:
-		// * esp_gatt_status_t status
-		// * uint16_t service_handle
-		// * esp_gatt_srvc_id_t service_id
-		// * - esp_gatt_id id
-		// *   - esp_bt_uuid uuid
-		// *   - uint8_t inst_id
-		// * - bool is_primary
-		//
-		case ESP_GATTS_CREATE_EVT: {
-			if (getUUID().equals(BLEUUID(param->create.service_id.id.uuid))) {
-				setHandle(param->create.service_handle);
-				m_semaphoreCreateEvt.give();
-			}
-			break;
-		} // ESP_GATTS_CREATE_EVT
-
-		default: {
-			break;
-		} // Default
-	} // Switch
-
-	m_characteristicMap.handleGATTServerEvent(event, gatts_if, param);
-} // handleGATTServerEvent
-
-
-BLECharacteristic* BLEService::getCharacteristic(const char* uuid) {
-	return getCharacteristic(BLEUUID(uuid));
-}
-
-
-BLECharacteristic* BLEService::getCharacteristic(BLEUUID uuid) {
-	return m_characteristicMap.getByUUID(uuid);
-}
-
-
-/**
- * @brief Return a string representation of this service.
- * A service is defined by:
- * * Its UUID
- * * Its handle
- * @return A string representation of this service.
- */
-std::string BLEService::toString() {
-	std::stringstream stringStream;
-	stringStream << "UUID: " << getUUID().toString() <<
-		", handle: 0x" << std::hex << std::setfill('0') << std::setw(2) << getHandle();
-	return stringStream.str();
-} // toString
-
-
-/**
- * @brief Get the last created characteristic.
- * It is lamentable that this function has to exist.  It returns the last created characteristic.
- * We need this because the descriptor API is built around the notion that a new descriptor, when created,
- * is associated with the last characteristics created and we need that information.
- * @return The last created characteristic.
- */
-BLECharacteristic* BLEService::getLastCreatedCharacteristic() {
-	return m_lastCreatedCharacteristic;
-} // getLastCreatedCharacteristic
-
-
-/**
- * @brief Get the BLE server associated with this service.
- * @return The BLEServer associated with this service.
- */
-BLEServer* BLEService::getServer() {
-	return m_pServer;
-} // getServer
-
-#endif // CONFIG_BT_ENABLED
diff --git a/components/cpp_utils/BLEService.h b/components/cpp_utils/BLEService.h
deleted file mode 100644
index 86d0776..0000000
--- a/components/cpp_utils/BLEService.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * BLEService.h
- *
- *  Created on: Mar 25, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLESERVICE_H_
-#define COMPONENTS_CPP_UTILS_BLESERVICE_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include <esp_gatts_api.h>
-
-#include "BLECharacteristic.h"
-#include "BLEServer.h"
-#include "BLEUUID.h"
-#include "FreeRTOS.h"
-
-class BLEServer;
-
-/**
- * @brief A data mapping used to manage the set of %BLE characteristics known to the server.
- */
-class BLECharacteristicMap {
-public:
-	void setByUUID(const char* uuid, BLECharacteristic* pCharacteristic);
-	void setByUUID(BLEUUID uuid, BLECharacteristic* pCharacteristic);
-	void setByHandle(uint16_t handle, BLECharacteristic* pCharacteristic);
-	BLECharacteristic* getByUUID(const char* uuid);	
-	BLECharacteristic* getByUUID(BLEUUID uuid);
-	BLECharacteristic* getByHandle(uint16_t handle);
-	BLECharacteristic* getFirst();
-	BLECharacteristic* getNext();
-	std::string toString();
-	void handleGATTServerEvent(
-			esp_gatts_cb_event_t      event,
-			esp_gatt_if_t             gatts_if,
-			esp_ble_gatts_cb_param_t* param);
-
-
-private:
-	std::map<std::string, BLECharacteristic*> m_uuidMap;
-	std::map<uint16_t, BLECharacteristic*> m_handleMap;
-	std::map<std::string, BLECharacteristic*>::iterator m_iterator;
-};
-
-
-/**
- * @brief The model of a %BLE service.
- *
- */
-class BLEService {
-public:
-	BLEService(const char* uuid);
-	BLEService(BLEUUID uuid);
-
-	void               addCharacteristic(BLECharacteristic* pCharacteristic);
-	BLECharacteristic* createCharacteristic(const char* uuid, uint32_t properties);
-	BLECharacteristic* createCharacteristic(BLEUUID uuid, uint32_t properties);
-	void               dump();
-	void               executeCreate(BLEServer* pServer);
-	BLECharacteristic* getCharacteristic(const char* uuid);
-	BLECharacteristic* getCharacteristic(BLEUUID uuid);
-	BLEUUID            getUUID();
-	BLEServer*         getServer();
-	void               start();
-	std::string        toString();
-
-private:
-	friend class BLEServer;
-	friend class BLEServiceMap;
-	friend class BLEDescriptor;
-	friend class BLECharacteristic;
-	friend class BLEDevice;
-
-	BLECharacteristicMap m_characteristicMap;
-	uint16_t             m_handle;
-	BLECharacteristic*   m_lastCreatedCharacteristic;
-	BLEServer*           m_pServer;
-	//FreeRTOS::Semaphore  m_serializeMutex;
-	FreeRTOS::Semaphore m_semaphoreAddCharEvt = FreeRTOS::Semaphore("AddCharEvt");
-	FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
-	FreeRTOS::Semaphore m_semaphoreStartEvt = FreeRTOS::Semaphore("StartEvt");
-	BLEUUID              m_uuid;
-
-	uint16_t           getHandle();
-	BLECharacteristic* getLastCreatedCharacteristic();
-	void               handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t* param);
-	void               setHandle(uint16_t handle);
-	//void               setService(esp_gatt_srvc_id_t srvc_id);
-}; // BLEService
-
-
-#endif // CONFIG_BT_ENABLED
-#endif /* COMPONENTS_CPP_UTILS_BLESERVICE_H_ */
diff --git a/components/cpp_utils/BLEServiceMap.cpp b/components/cpp_utils/BLEServiceMap.cpp
deleted file mode 100644
index 8fdbd5a..0000000
--- a/components/cpp_utils/BLEServiceMap.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * BLEServiceMap.cpp
- *
- *  Created on: Jun 22, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <sstream>
-#include <iomanip>
-#include "BLEService.h"
-
-
-/**
- * @brief Return the service by UUID.
- * @param [in] UUID The UUID to look up the service.
- * @return The characteristic.
- */
-BLEService* BLEServiceMap::getByUUID(const char* uuid) {
-    return getByUUID(BLEUUID(uuid));
-}
-	
-/**
- * @brief Return the service by UUID.
- * @param [in] UUID The UUID to look up the service.
- * @return The characteristic.
- */
-BLEService* BLEServiceMap::getByUUID(BLEUUID uuid) {
-	for (auto &myPair : m_uuidMap) {
-		if (myPair.second->getUUID().equals(uuid)) {
-			return myPair.second;
-		}
-	}
-	//return m_uuidMap.at(uuid.toString());
-	return nullptr;
-} // getByUUID
-
-
-/**
- * @brief Return the service by handle.
- * @param [in] handle The handle to look up the service.
- * @return The service.
- */
-BLEService* BLEServiceMap::getByHandle(uint16_t handle) {
-	return m_handleMap.at(handle);
-} // getByHandle
-
-
-/**
- * @brief Set the service by UUID.
- * @param [in] uuid The uuid of the service.
- * @param [in] characteristic The service to cache.
- * @return N/A.
- */
-void BLEServiceMap::setByUUID(BLEUUID uuid,
-		BLEService *service) {
-	m_uuidMap.insert(std::pair<std::string, BLEService *>(uuid.toString(), service));
-} // setByUUID
-
-
-/**
- * @brief Set the service by handle.
- * @param [in] handle The handle of the service.
- * @param [in] service The service to cache.
- * @return N/A.
- */
-void BLEServiceMap::setByHandle(uint16_t handle,
-		BLEService* service) {
-	m_handleMap.insert(std::pair<uint16_t, BLEService *>(handle, service));
-} // setByHandle
-
-
-/**
- * @brief Return a string representation of the service map.
- * @return A string representation of the service map.
- */
-std::string BLEServiceMap::toString() {
-	std::stringstream stringStream;
-	stringStream << std::hex << std::setfill('0');
-	for (auto &myPair: m_handleMap) {
-		stringStream << "handle: 0x" << std::setw(2) << myPair.first << ", uuid: " + myPair.second->getUUID().toString() << "\n";
-	}
-	return stringStream.str();
-} // toString
-
-void BLEServiceMap::handleGATTServerEvent(
-		esp_gatts_cb_event_t      event,
-		esp_gatt_if_t             gatts_if,
-		esp_ble_gatts_cb_param_t *param) {
-	// Invoke the handler for every Service we have.
-	for (auto &myPair : m_uuidMap) {
-		myPair.second->handleGATTServerEvent(event, gatts_if, param);
-	}
-}
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLEUUID.cpp b/components/cpp_utils/BLEUUID.cpp
deleted file mode 100644
index 9a4fe45..0000000
--- a/components/cpp_utils/BLEUUID.cpp
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * BLEUUID.cpp
- *
- *  Created on: Jun 21, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_log.h>
-#include <string.h>
-#include <sstream>
-#include <iomanip>
-#include <stdio.h>
-#include "BLEUUID.h"
-static const char* LOG_TAG = "BLEUUID";
-
-
-/**
- * @brief Copy memory from source to target but in reverse order.
- *
- * When we move memory from one location it is normally:
- *
- * ```
- * [0][1][2]...[n] -> [0][1][2]...[n]
- * ```
- *
- * with this function, it is:
- *
- * ```
- * [0][1][2]...[n] -> [n][n-1][n-2]...[0]
- * ```
- *
- * @param [in] target The target of the copy
- * @param [in] source The source of the copy
- * @param [in] size The number of bytes to copy
- */
-static void memrcpy(uint8_t* target, uint8_t* source, uint32_t size) {
-	target+=(size-1); // Point target to the last byte of the target data
-	while (size > 0) {
-		*target = *source;
-		target--;
-		source++;
-		size--;
-	}
-} // memrcpy
-
-
-/**
- * @brief Create a UUID from a string.
- *
- * Create a UUID from a string.  There will be two possible stories here.  Either the string represents
- * a binary data field or the string represents a hex encoding of a UUID.
- * For the hex encoding, here is an example:
- *
- * ```
- * "beb5483e-36e1-4688-b7f5-ea07361b26a8"
- *  0 1 2 3  4 5  6 7  8 9  0 1 2 3 4 5
- *  12345678-90ab-cdef-1234-567890abcdef
- * ```
- *
- * This has a length of 36 characters.  We need to parse this into 16 bytes.
- *
- * @param [in] value The string to build a UUID from.
- */
-BLEUUID::BLEUUID(std::string value) {
-	m_valueSet = true;
-	if (value.length() == 2) {
-		m_uuid.len = ESP_UUID_LEN_16;
-		m_uuid.uuid.uuid16 = value[0] | (value[1] << 8);
-	} else if (value.length() == 4) {
-		m_uuid.len = ESP_UUID_LEN_32;
-		m_uuid.uuid.uuid32 = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
-	} else if (value.length() == 16) {
-		m_uuid.len = ESP_UUID_LEN_128;
-		memrcpy(m_uuid.uuid.uuid128, (uint8_t*)value.data(), 16);
-	} else if (value.length() == 36) {
-// If the length of the string is 36 bytes then we will assume it is a long hex string in
-// UUID format.
-		m_uuid.len = ESP_UUID_LEN_128;
-		int vals[16];
-		sscanf(value.c_str(), "%2x%2x%2x%2x-%2x%2x-%2x%2x-%2x%2x-%2x%2x%2x%2x%2x%2x",
-			&vals[15],
-			&vals[14],
-			&vals[13],
-			&vals[12],
-			&vals[11],
-			&vals[10],
-			&vals[9],
-			&vals[8],
-			&vals[7],
-			&vals[6],
-			&vals[5],
-			&vals[4],
-			&vals[3],
-			&vals[2],
-			&vals[1],
-			&vals[0]
-		);
-
-		int i;
-		for (i=0; i<16; i++) {
-			m_uuid.uuid.uuid128[i] = vals[i];
-		}
-	}
-	else {
-		ESP_LOGE(LOG_TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes");
-		m_valueSet = false;
-	}
-} //BLEUUID(std::string)
-
-
-/**
- * @brief Create a UUID from 16 bytes of memory.
- *
- * @param [in] pData The pointer to the start of the UUID.
- * @param [in] size The size of the data.
- * @param [in] msbFirst Is the MSB first in pData memory?
- */
-BLEUUID::BLEUUID(uint8_t* pData, size_t size, bool msbFirst) {
-	if (size != 16) {
-		ESP_LOGE(LOG_TAG, "ERROR: UUID length not 16 bytes");
-		return;
-	}
-	m_uuid.len = ESP_UUID_LEN_128;
-	if (msbFirst) {
-		memrcpy(m_uuid.uuid.uuid128, pData, 16);
-	} else {
-		memcpy(m_uuid.uuid.uuid128, pData, 16);
-	}
-	m_valueSet         = true;
-} // BLEUUID
-
-/**
- * @brief Create a UUID from the 16bit value.
- *
- * @param [in] uuid The 16bit short form UUID.
- */
-BLEUUID::BLEUUID(uint16_t uuid) {
-	m_uuid.len         = ESP_UUID_LEN_16;
-	m_uuid.uuid.uuid16 = uuid;
-	m_valueSet         = true;
-} // BLEUUID
-
-
-/**
- * @brief Create a UUID from the 32bit value.
- *
- * @param [in] uuid The 32bit short form UUID.
- */
-BLEUUID::BLEUUID(uint32_t uuid) {
-	m_uuid.len         = ESP_UUID_LEN_32;
-	m_uuid.uuid.uuid32 = uuid;
-	m_valueSet         = true;
-} // BLEUUID
-
-
-/**
- * @brief Create a UUID from the native UUID.
- *
- * @param [in] uuid The native UUID.
- */
-BLEUUID::BLEUUID(esp_bt_uuid_t uuid) {
-	m_uuid     = uuid;
-	m_valueSet = true;
-} // BLEUUID
-
-
-/**
- * @brief Create a UUID from the ESP32 esp_gatt_srvc_id_t.
- *
- * @param [in] srvcId The data to create the UUID from.
- */
-BLEUUID::BLEUUID(esp_gatt_srvc_id_t srcvId) : BLEUUID(srcvId.id.uuid) {
-} // BLEUUID
-
-
-BLEUUID::BLEUUID() {
-	m_valueSet = false;
-} // BLEUUID
-
-
-/**
- * @brief Compare a UUID against this UUID.
- *
- * @param [in] uuid The UUID to compare against.
- * @return True if the UUIDs are equal and false otherwise.
- */
-bool BLEUUID::equals(BLEUUID uuid) {
-	//ESP_LOGD(TAG, "Comparing: %s to %s", toString().c_str(), uuid.toString().c_str());
-	if (m_valueSet == false || uuid.m_valueSet == false) {
-		return false;
-	}
-
-	if (uuid.m_uuid.len != m_uuid.len) {
-		return uuid.toString() == toString();
-	}
-
-	if (uuid.m_uuid.len == ESP_UUID_LEN_16) {
-		return uuid.m_uuid.uuid.uuid16 == m_uuid.uuid.uuid16;
-	}
-
-	if (uuid.m_uuid.len == ESP_UUID_LEN_32) {
-		return uuid.m_uuid.uuid.uuid32 == m_uuid.uuid.uuid32;
-	}
-
-	return memcmp(uuid.m_uuid.uuid.uuid128, m_uuid.uuid.uuid128, 16) == 0;
-} // equals
-
-
-/**
- * @brief Get the native UUID value.
- *
- * @return The native UUID value or NULL if not set.
- */
-esp_bt_uuid_t* BLEUUID::getNative() {
-	//ESP_LOGD(TAG, ">> getNative()")
-	if (m_valueSet == false) {
-		ESP_LOGD(LOG_TAG, "<< Return of un-initialized UUID!");
-		return nullptr;
-	}
-	//ESP_LOGD(TAG, "<< getNative()");
-	return &m_uuid;
-} // getNative
-
-
-/**
- * @brief Convert a UUID to its 128 bit representation.
- *
- * A UUID can be internally represented as 16bit, 32bit or the full 128bit.  This method
- * will convert 16 or 32 bit representations to the full 128bit.
- */
-BLEUUID BLEUUID::to128() {
-	//ESP_LOGD(LOG_TAG, ">> toFull() - %s", toString().c_str());
-
-	// If we either don't have a value or are already a 128 bit UUID, nothing further to do.
-	if (m_valueSet == false || m_uuid.len == ESP_UUID_LEN_128) {
-		return *this;
-	}
-
-	// If we are 16 bit or 32 bit, then set the 4 bytes of the variable part of the UUID.
-	if (m_uuid.len == ESP_UUID_LEN_16) {
-		uint16_t temp = m_uuid.uuid.uuid16;
-		m_uuid.uuid.uuid128[15] = 0;
-		m_uuid.uuid.uuid128[14] = 0;
-		m_uuid.uuid.uuid128[13] = (temp >> 8) & 0xff;
-		m_uuid.uuid.uuid128[12] = temp & 0xff;
-
-	}
-	else if (m_uuid.len == ESP_UUID_LEN_32) {
-		uint32_t temp = m_uuid.uuid.uuid32;
-		m_uuid.uuid.uuid128[15] = (temp >> 24) & 0xff;
-		m_uuid.uuid.uuid128[14] = (temp >> 16) & 0xff;
-		m_uuid.uuid.uuid128[13] = (temp >> 8) & 0xff;
-		m_uuid.uuid.uuid128[12] = temp & 0xff;
-	}
-
-	// Set the fixed parts of the UUID.
-	m_uuid.uuid.uuid128[11] = 0x00;
-	m_uuid.uuid.uuid128[10] = 0x00;
-
-	m_uuid.uuid.uuid128[9]  = 0x10;
-	m_uuid.uuid.uuid128[8]  = 0x00;
-
-	m_uuid.uuid.uuid128[7]  = 0x80;
-	m_uuid.uuid.uuid128[6]  = 0x00;
-
-	m_uuid.uuid.uuid128[5]  = 0x00;
-	m_uuid.uuid.uuid128[4]  = 0x80;
-	m_uuid.uuid.uuid128[3]  = 0x5f;
-	m_uuid.uuid.uuid128[2]  = 0x9b;
-	m_uuid.uuid.uuid128[1]  = 0x34;
-	m_uuid.uuid.uuid128[0]  = 0xfb;
-
-	m_uuid.len = ESP_UUID_LEN_128;
-	//ESP_LOGD(TAG, "<< toFull <-  %s", toString().c_str());
-	return *this;
-} // to128
-
-
-//01234567 8901 2345 6789 012345678901
-//0000180d-0000-1000-8000-00805f9b34fb
-//0 1 2 3  4 5  6 7  8 9  0 1 2 3 4 5
-
-/**
- * @brief Get a string representation of the UUID.
- *
- * @return A string representation of the UUID.
- */
-std::string BLEUUID::toString() {
-	if (m_valueSet == false) {
-		return "<NULL>";
-	}
-
-	if (m_uuid.len == ESP_UUID_LEN_16) {
-		std::stringstream ss;
-		ss << "0000" << std::hex << std::setfill('0') << std::setw(4) << m_uuid.uuid.uuid16 << "-0000-1000-8000-00805f9b34fb";
-		return ss.str();
-	}
-
-	if (m_uuid.len == ESP_UUID_LEN_32) {
-		std::stringstream ss;
-		ss << std::hex << std::setfill('0') << std::setw(8) << m_uuid.uuid.uuid32 << "-0000-1000-8000-00805f9b34fb";
-		return ss.str();
-	}
-
-	std::stringstream ss;
-	ss << std::hex << std::setfill('0') <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[15] <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[14] <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[13] <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[12] << "-" <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[11] <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[10] << "-" <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[9]  <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[8]  << "-" <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[7]  <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[6]  << "-" <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[5]  <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[4]  <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[3]  <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[2]  <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[1]  <<
-			std::setw(2) << (int)m_uuid.uuid.uuid128[0];
-	return ss.str();
-} // toString
-#endif /* CONFIG_BT_ENABLED */
diff --git a/components/cpp_utils/BLEUUID.h b/components/cpp_utils/BLEUUID.h
deleted file mode 100644
index c364796..0000000
--- a/components/cpp_utils/BLEUUID.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * BLEUUID.h
- *
- *  Created on: Jun 21, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEUUID_H_
-#define COMPONENTS_CPP_UTILS_BLEUUID_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_gatt_defs.h>
-#include <string>
-
-/**
- * @brief A model of a %BLE UUID.
- */
-class BLEUUID {
-public:
-	BLEUUID(std::string uuid);
-	BLEUUID(uint16_t uuid);
-	BLEUUID(uint32_t uuid);
-	BLEUUID(esp_bt_uuid_t uuid);
-	BLEUUID(uint8_t* pData, size_t size, bool msbFirst);
-	BLEUUID(esp_gatt_srvc_id_t srcvId);
-	BLEUUID();
-	bool           equals(BLEUUID uuid);
-	esp_bt_uuid_t* getNative();
-	BLEUUID        to128();
-	std::string    toString();
-
-private:
-	esp_bt_uuid_t m_uuid;
-	bool          m_valueSet;
-}; // BLEUUID
-#endif /* CONFIG_BT_ENABLED */
-#endif /* COMPONENTS_CPP_UTILS_BLEUUID_H_ */
diff --git a/components/cpp_utils/BLEUtils.cpp b/components/cpp_utils/BLEUtils.cpp
deleted file mode 100644
index 468a7e1..0000000
--- a/components/cpp_utils/BLEUtils.cpp
+++ /dev/null
@@ -1,1352 +0,0 @@
-/*
- * BLEUtils.cpp
- *
- *  Created on: Mar 25, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include "BLEUtils.h"
-#include "BLEUUID.h"
-#include "BLEClient.h"
-#include "BLEAddress.h"
-#include "GeneralUtils.h"
-
-#include <freertos/FreeRTOS.h>
-#include <freertos/event_groups.h>
-#include <bt.h>              // ESP32 BLE
-#include <esp_bt_main.h>     // ESP32 BLE
-#include <esp_gap_ble_api.h> // ESP32 BLE
-#include <esp_gattc_api.h>   // ESP32 BLE
-#include <esp_err.h>         // ESP32 ESP-IDF
-#include <esp_log.h>         // ESP32 ESP-IDF
-#include <map>               // Part of C++ STL
-#include <sstream>
-#include <iomanip>
-
-static const char* LOG_TAG = "BLEUtils";
-
-/*
-static std::map<std::string, BLEClient *> g_addressMap;
-static std::map<uint16_t, BLEClient *> g_connIdMap;
-*/
-
-typedef struct {
-	uint32_t assignedNumber;
-	std::string name;
-} characteristicMap_t;
-
-static characteristicMap_t g_characteristicsMappings[] = {
-		{0x2a00, "Device Name"},
-		{0x2a01, "Appearance"},
-		{0, ""}
-};
-
-/**
- * @brief Mapping from service ids to names
- */
-typedef struct {
-	std::string name;
-	std::string type;
-	uint32_t assignedNumber;
-} gattService_t;
-
-
-/**
- * Definition of the service ids to names that we know about.
- */
-static const gattService_t g_gattServices[] = {
-	{"Alert Notification Service", "org.bluetooth.service.alert_notification", 0x1811},
-	{"Automation IO", "org.bluetooth.service.automation_io",	0x1815 },
-	{"Battery Service","org.bluetooth.service.battery_service",	0x180F},
-	{"Blood Pressure", "org.bluetooth.service.blood_pressure", 0x1810},
-	{"Body Composition", "org.bluetooth.service.body_composition", 0x181B},
-	{"Bond Management", "org.bluetooth.service.bond_management", 0x181E},
-	{"Continuous Glucose Monitoring", "org.bluetooth.service.continuous_glucose_monitoring", 0x181F},
-	{"Current Time Service", "org.bluetooth.service.current_time", 0x1805},
-	{"Cycling Power", "org.bluetooth.service.cycling_power", 0x1818},
-	{"Cycling Speed and Cadence", "org.bluetooth.service.cycling_speed_and_cadence", 0x1816},
-	{"Device Information", "org.bluetooth.service.device_information", 0x180A},
-	{"Environmental Sensing", "org.bluetooth.service.environmental_sensing", 0x181A},
-	{"Generic Access", "org.bluetooth.service.generic_access", 0x1800},
-	{"Generic Attribute", "org.bluetooth.service.generic_attribute", 0x1801},
-	{"Glucose", "org.bluetooth.service.glucose", 0x1808},
-	{"Health Thermometer", "org.bluetooth.service.health_thermometer", 0x1809},
-	{"Heart Rate", "org.bluetooth.service.heart_rate", 0x180D},
-	{"HTTP Proxy", "org.bluetooth.service.http_proxy", 0x1823},
-	{"Human Interface Device", "org.bluetooth.service.human_interface_device", 0x1812},
-	{"Immediate Alert", "org.bluetooth.service.immediate_alert", 0x1802},
-	{"Indoor Positioning", "org.bluetooth.service.indoor_positioning", 0x1821},
-	{"Internet Protocol Support", "org.bluetooth.service.internet_protocol_support", 0x1820},
-	{"Link Loss", "org.bluetooth.service.link_loss", 0x1803},
-	{"Location and Navigation", "org.bluetooth.service.location_and_navigation", 0x1819},
-	{"Next DST Change Service", "org.bluetooth.service.next_dst_change", 0x1807},
-	{"Object Transfer", "org.bluetooth.service.object_transfer", 0x1825},
-	{"Phone Alert Status Service", "org.bluetooth.service.phone_alert_status", 0x180E},
-	{"Pulse Oximeter", "org.bluetooth.service.pulse_oximeter", 0x1822},
-	{"Reference Time Update Service", "org.bluetooth.service.reference_time_update", 0x1806},
-	{"Running Speed and Cadence", "org.bluetooth.service.running_speed_and_cadence", 0x1814},
-	{"Scan Parameters", "org.bluetooth.service.scan_parameters", 0x1813},
-	{"Transport Discovery", "org.bluetooth.service.transport_discovery", 0x1824},
-	{"Tx Power", "org.bluetooth.service.tx_power", 0x1804},
-	{"User Data", "org.bluetooth.service.user_data", 0x181C},
-	{"Weight Scale", "org.bluetooth.service.weight_scale", 0x181D},
-	{"", "", 0 }
-};
-
-/**
- * @brief Convert characteristic properties into a string representation.
- * @param [in] prop Characteristic properties.
- * @return A string representation of characteristic properties.
- */
-std::string BLEUtils::characteristicPropertiesToString(esp_gatt_char_prop_t prop) {
-	std::stringstream stream;
-	stream <<
-			"broadcast: "  << ((prop & ESP_GATT_CHAR_PROP_BIT_BROADCAST)?"1":"0") <<
-			", read: "     << ((prop & ESP_GATT_CHAR_PROP_BIT_READ)?"1":"0") <<
-			", write_nr: " << ((prop & ESP_GATT_CHAR_PROP_BIT_WRITE_NR)?"1":"0") <<
-			", write: "    << ((prop & ESP_GATT_CHAR_PROP_BIT_WRITE)?"1":"0") <<
-			", notify: "   << ((prop & ESP_GATT_CHAR_PROP_BIT_NOTIFY)?"1":"0") <<
-			", indicate: " << ((prop & ESP_GATT_CHAR_PROP_BIT_INDICATE)?"1":"0") <<
-			", auth: "     << ((prop & ESP_GATT_CHAR_PROP_BIT_AUTH)?"1":"0");
-	return stream.str();
-} // characteristicPropertiesToString
-
-/**
- * @brief Convert an esp_gatt_id_t to a string.
- */
-static std::string gattIdToString(esp_gatt_id_t gattId) {
-	std::stringstream stream;
-	stream << "uuid: " << BLEUUID(gattId.uuid).toString() << ", inst_id: " << (int)gattId.inst_id;
-	//sprintf(buffer, "uuid: %s, inst_id: %d", uuidToString(gattId.uuid).c_str(), gattId.inst_id);
-	return stream.str();
-} // gattIdToString
-
-
-/**
- * @brief Convert an esp_ble_addr_type_t to a string representation.
- */
-const char* BLEUtils::addressTypeToString(esp_ble_addr_type_t type) {
-	switch(type) {
-		case BLE_ADDR_TYPE_PUBLIC:
-			return "BLE_ADDR_TYPE_PUBLIC";
-		case BLE_ADDR_TYPE_RANDOM:
-			return "BLE_ADDR_TYPE_RANDOM";
-		case BLE_ADDR_TYPE_RPA_PUBLIC:
-			return "BLE_ADDR_TYPE_RPA_PUBLIC";
-		case BLE_ADDR_TYPE_RPA_RANDOM:
-			return "BLE_ADDR_TYPE_RPA_RANDOM";
-		default:
-			return "Unknown addr_t";
-	}
-} // addressTypeToString
-
-
-/**
- * @brief Given an advertising type, return a string representation of the type.
- *
- * For details see ...
- * https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
- *
- * @return A string representation of the type.
- */
-const char* BLEUtils::advTypeToString(uint8_t advType) {
-	switch(advType) {
-		case ESP_BLE_AD_TYPE_FLAG:
-			return "ESP_BLE_AD_TYPE_FLAG";
-		case ESP_BLE_AD_TYPE_16SRV_PART:
-			return "ESP_BLE_AD_TYPE_16SRV_PART";
-		case ESP_BLE_AD_TYPE_16SRV_CMPL:
-			return "ESP_BLE_AD_TYPE_16SRV_CMPL";
-		case ESP_BLE_AD_TYPE_32SRV_PART:
-			return "ESP_BLE_AD_TYPE_32SRV_PART";
-		case ESP_BLE_AD_TYPE_32SRV_CMPL:
-			return "ESP_BLE_AD_TYPE_32SRV_CMPL";
-		case ESP_BLE_AD_TYPE_128SRV_PART:
-			return "ESP_BLE_AD_TYPE_128SRV_PART";
-		case ESP_BLE_AD_TYPE_128SRV_CMPL:
-			return "ESP_BLE_AD_TYPE_128SRV_CMPL";
-		case ESP_BLE_AD_TYPE_NAME_SHORT:
-			return "ESP_BLE_AD_TYPE_NAME_SHORT";
-		case ESP_BLE_AD_TYPE_NAME_CMPL:
-			return "ESP_BLE_AD_TYPE_NAME_CMPL";
-		case ESP_BLE_AD_TYPE_TX_PWR:
-			return "ESP_BLE_AD_TYPE_TX_PWR";
-		case ESP_BLE_AD_TYPE_DEV_CLASS:
-			return "ESP_BLE_AD_TYPE_DEV_CLASS";
-		case ESP_BLE_AD_TYPE_SM_TK:
-			return "ESP_BLE_AD_TYPE_SM_TK";
-		case ESP_BLE_AD_TYPE_SM_OOB_FLAG:
-			return "ESP_BLE_AD_TYPE_SM_OOB_FLAG";
-		case ESP_BLE_AD_TYPE_INT_RANGE:
-			return "ESP_BLE_AD_TYPE_INT_RANGE";
-		case ESP_BLE_AD_TYPE_SOL_SRV_UUID:
-			return "ESP_BLE_AD_TYPE_SOL_SRV_UUID";
-		case ESP_BLE_AD_TYPE_128SOL_SRV_UUID:
-			return "ESP_BLE_AD_TYPE_128SOL_SRV_UUID";
-		case ESP_BLE_AD_TYPE_SERVICE_DATA:
-			return "ESP_BLE_AD_TYPE_SERVICE_DATA";
-		case ESP_BLE_AD_TYPE_PUBLIC_TARGET:
-			return "ESP_BLE_AD_TYPE_PUBLIC_TARGET";
-		case ESP_BLE_AD_TYPE_RANDOM_TARGET:
-			return "ESP_BLE_Amap1D_TYPE_RANDOM_TARGET";
-		case ESP_BLE_AD_TYPE_APPEARANCE:
-			return "ESP_BLE_AD_TYPE_APPEARANCE";
-		case ESP_BLE_AD_TYPE_ADV_INT:
-			return "ESP_BLE_AD_TYPE_ADV_INT";
-		case ESP_BLE_AD_TYPE_32SOL_SRV_UUID:
-			return "ESP_BLE_AD_TYPE_32SOL_SRV_UUID";
-		case ESP_BLE_AD_TYPE_32SERVICE_DATA:
-			return "ESP_BLE_AD_TYPE_32SERVICE_DATA";
-		case ESP_BLE_AD_TYPE_128SERVICE_DATA:
-			return "ESP_BLE_AD_TYPE_128SERVICE_DATA";
-		case ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE:
-			return "ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE";
-		default:
-			ESP_LOGD(LOG_TAG, "Unknown adv data type: 0x%x", advType);
-			return "Unknown";
-	} // End switch
-} // advTypeToString
-
-
-esp_gatt_id_t BLEUtils::buildGattId(esp_bt_uuid_t uuid, uint8_t inst_id) {
-	esp_gatt_id_t retGattId;
-	retGattId.uuid = uuid;
-	retGattId.inst_id = inst_id;
-	return retGattId;
-}
-
-esp_gatt_srvc_id_t BLEUtils::buildGattSrvcId(esp_gatt_id_t gattId,
-		bool is_primary) {
-	esp_gatt_srvc_id_t retSrvcId;
-	retSrvcId.id = gattId;
-	retSrvcId.is_primary = is_primary;
-	return retSrvcId;
-}
-
-/**
- * @brief Create a hex representation of data.
- *
- * @param [in] target Where to write the hex string.  If this is null, we malloc storage.
- * @param [in] source The start of the binary data.
- * @param [in] length The length of the data to convert.
- * @return A pointer to the formatted buffer.
- */
-char *BLEUtils::buildHexData(uint8_t *target, uint8_t *source, uint8_t length) {
-// Guard against too much data.
-	if (length > 100) {
-		length = 100;
-	}
-
-
-	if (target == nullptr) {
-		target = (uint8_t *)malloc(length * 2 + 1);
-		if (target == nullptr) {
-			ESP_LOGE(LOG_TAG, "buildHexData: malloc failed");
-			return nullptr;
-		}
-	}
-	char *startOfData = (char *)target;
-
-	int i;
-	for (i=0; i<length; i++) {
-		sprintf((char *)target, "%.2x", (char)*source);
-		source++;
-		target +=2;
-	}
-
-// Handle the special case where there was no data.
-	if (length == 0) {
-		*startOfData = 0;
-	}
-
-	return startOfData;
-} // buildHexData
-
-
-/**
- * @brief Build a printable string of memory range.
- * Create a string representation of a piece of memory. Only printable characters will be included
- * while those that are not printable will be replaced with '.'.
- * @param [in] source Start of memory.
- * @param [in] length Length of memory.
- * @return A string representation of a piece of memory.
- */
-std::string BLEUtils::buildPrintData(uint8_t* source, size_t length) {
-	std::ostringstream ss;
-	for (int i=0; i<length; i++) {
-		char c = *source;
-		if (isprint(c)) {
-			ss << c;
-		} else {
-			ss << '.';
-		}
-		source++;
-	}
-	return ss.str();
-} // buildPrintData
-
-
-std::string BLEUtils::gattCloseReasonToString(esp_gatt_conn_reason_t reason) {
-	switch(reason) {
-		case ESP_GATT_CONN_UNKNOWN:
-			return "ESP_GATT_CONN_UNKNOWN";
-		case ESP_GATT_CONN_L2C_FAILURE:
-			return "ESP_GATT_CONN_L2C_FAILURE";
-		case ESP_GATT_CONN_TIMEOUT:
-			return "ESP_GATT_CONN_TIMEOUT";
-		case ESP_GATT_CONN_TERMINATE_PEER_USER:
-			return "ESP_GATT_CONN_TERMINATE_PEER_USER";
-		case ESP_GATT_CONN_TERMINATE_LOCAL_HOST:
-			return "ESP_GATT_CONN_TERMINATE_LOCAL_HOST";
-		case ESP_GATT_CONN_FAIL_ESTABLISH:
-			return "ESP_GATT_CONN_FAIL_ESTABLISH";
-		case ESP_GATT_CONN_LMP_TIMEOUT:
-			return "ESP_GATT_CONN_LMP_TIMEOUT";
-		case ESP_GATT_CONN_CONN_CANCEL:
-			return "ESP_GATT_CONN_CONN_CANCEL";
-		case ESP_GATT_CONN_NONE:
-			return "ESP_GATT_CONN_NONE";
-		default:
-			return "Unknown";
-	}
-} // gattCloseReasonToString
-
-
-std::string BLEUtils::gattClientEventTypeToString(esp_gattc_cb_event_t eventType) {
-	switch(eventType) {
-		case ESP_GATTC_ACL_EVT:
-			return "ESP_GATTC_ACL_EVT";
-		case ESP_GATTC_ADV_DATA_EVT:
-			return "ESP_GATTC_ADV_DATA_EVT";
-		case ESP_GATTC_ADV_VSC_EVT:
-			return "ESP_GATTC_ADV_VSC_EVT";
-		case ESP_GATTC_BTH_SCAN_CFG_EVT:
-			return "ESP_GATTC_BTH_SCAN_CFG_EVT";
-		case ESP_GATTC_BTH_SCAN_DIS_EVT:
-			return "ESP_GATTC_BTH_SCAN_DIS_EVT";
-		case ESP_GATTC_BTH_SCAN_ENB_EVT:
-			return "ESP_GATTC_BTH_SCAN_ENB_EVT";
-		case ESP_GATTC_BTH_SCAN_PARAM_EVT:
-			return "ESP_GATTC_BTH_SCAN_PARAM_EVT";
-		case ESP_GATTC_BTH_SCAN_RD_EVT:
-			return "ESP_GATTC_BTH_SCAN_RD_EVT";
-		case ESP_GATTC_BTH_SCAN_THR_EVT:
-			return "ESP_GATTC_BTH_SCAN_THR_EVT";
-		case ESP_GATTC_CANCEL_OPEN_EVT:
-			return "ESP_GATTC_CANCEL_OPEN_EVT";
-		case ESP_GATTC_CFG_MTU_EVT:
-			return "ESP_GATTC_CFG_MTU_EVT";
-		case ESP_GATTC_CLOSE_EVT:
-			return "ESP_GATTC_CLOSE_EVT";
-		case ESP_GATTC_CONGEST_EVT:
-			return "ESP_GATTC_CONGEST_EVT";
-		case ESP_GATTC_CONNECT_EVT:
-			return "ESP_GATTC_CONNECT_EVT";
-		case ESP_GATTC_DISCONNECT_EVT:
-			return "ESP_GATTC_DISCONNECT_EVT";
-		case ESP_GATTC_ENC_CMPL_CB_EVT:
-			return "ESP_GATTC_ENC_CMPL_CB_EVT";
-		case ESP_GATTC_EXEC_EVT:
-			return "ESP_GATTC_EXEC_EVT";
-		case ESP_GATTC_GET_CHAR_EVT:
-			return "ESP_GATTC_GET_CHAR_EVT";
-		case ESP_GATTC_GET_DESCR_EVT:
-			return "ESP_GATTC_GET_DESCR_EVT";
-		case ESP_GATTC_GET_INCL_SRVC_EVT:
-			return "ESP_GATTC_GET_INCL_SRVC_EVT";
-		case ESP_GATTC_MULT_ADV_DATA_EVT:
-			return "ESP_GATTC_MULT_ADV_DATA_EVT";
-		case ESP_GATTC_MULT_ADV_DIS_EVT:
-			return "ESP_GATTC_MULT_ADV_DIS_EVT";
-		case ESP_GATTC_MULT_ADV_ENB_EVT:
-			return "ESP_GATTC_MULT_ADV_ENB_EVT";
-		case ESP_GATTC_MULT_ADV_UPD_EVT:
-			return "ESP_GATTC_MULT_ADV_UPD_EVT";
-		case ESP_GATTC_NOTIFY_EVT:
-			return "ESP_GATTC_NOTIFY_EVT";
-		case ESP_GATTC_OPEN_EVT:
-			return "ESP_GATTC_OPEN_EVT";
-		case ESP_GATTC_PREP_WRITE_EVT:
-			return "ESP_GATTC_PREP_WRITE_EVT";
-		case ESP_GATTC_READ_CHAR_EVT:
-			return "ESP_GATTC_READ_CHAR_EVT";
-		case ESP_GATTC_REG_EVT:
-			return "ESP_GATTC_REG_EVT";
-		case ESP_GATTC_REG_FOR_NOTIFY_EVT:
-			return "ESP_GATTC_REG_FOR_NOTIFY_EVT";
-		case ESP_GATTC_SCAN_FLT_CFG_EVT:
-			return "ESP_GATTC_SCAN_FLT_CFG_EVT";
-		case ESP_GATTC_SCAN_FLT_PARAM_EVT:
-			return "ESP_GATTC_SCAN_FLT_PARAM_EVT";
-		case ESP_GATTC_SCAN_FLT_STATUS_EVT:
-			return "ESP_GATTC_SCAN_FLT_STATUS_EVT";
-		case ESP_GATTC_SEARCH_CMPL_EVT:
-			return "ESP_GATTC_SEARCH_CMPL_EVT";
-		case ESP_GATTC_SEARCH_RES_EVT:
-			return "ESP_GATTC_SEARCH_RES_EVT";
-		case ESP_GATTC_SRVC_CHG_EVT:
-			return "ESP_GATTC_SRVC_CHG_EVT";
-		case ESP_GATTC_READ_DESCR_EVT:
-			return "ESP_GATTC_READ_DESCR_EVT";
-		case ESP_GATTC_UNREG_EVT:
-			return "ESP_GATTC_UNREG_EVT";
-		case ESP_GATTC_UNREG_FOR_NOTIFY_EVT:
-			return "ESP_GATTC_UNREG_FOR_NOTIFY_EVT";
-		case ESP_GATTC_WRITE_CHAR_EVT:
-			return "ESP_GATTC_WRITE_CHAR_EVT";
-		case ESP_GATTC_WRITE_DESCR_EVT:
-			return "ESP_GATTC_WRITE_DESCR_EVT";
-		default:
-			ESP_LOGW(LOG_TAG, "Unknown GATT Client event type: %d", eventType);
-			return "Unknown";
-	}
-} // gattClientEventTypeToString
-
-
-/**
- * @brief Return a string representation of a GATT server event code.
- * @param [in] eventType A GATT server event code.
- * @return A string representation of the GATT server event code.
- */
-std::string BLEUtils::gattServerEventTypeToString(esp_gatts_cb_event_t eventType) {
-	switch(eventType) {
-	case ESP_GATTS_REG_EVT:
-		return "ESP_GATTS_REG_EVT";
-	case ESP_GATTS_READ_EVT:
-		return "ESP_GATTS_READ_EVT";
-	case ESP_GATTS_WRITE_EVT:
-		return "ESP_GATTS_WRITE_EVT";
-	case ESP_GATTS_EXEC_WRITE_EVT:
-		return "ESP_GATTS_EXEC_WRITE_EVT";
-	case ESP_GATTS_MTU_EVT:
-		return "ESP_GATTS_MTU_EVT";
-	case ESP_GATTS_CONF_EVT:
-		return "ESP_GATTS_CONF_EVT";
-	case ESP_GATTS_UNREG_EVT:
-		return "ESP_GATTS_UNREG_EVT";
-	case ESP_GATTS_CREATE_EVT:
-		return "ESP_GATTS_CREATE_EVT";
-	case ESP_GATTS_ADD_INCL_SRVC_EVT:
-		return "ESP_GATTS_ADD_INCL_SRVC_EVT";
-	case ESP_GATTS_ADD_CHAR_EVT:
-		return "ESP_GATTS_ADD_CHAR_EVT";
-	case ESP_GATTS_ADD_CHAR_DESCR_EVT:
-		return "ESP_GATTS_ADD_CHAR_DESCR_EVT";
-	case ESP_GATTS_DELETE_EVT:
-		return "ESP_GATTS_DELETE_EVT";
-	case ESP_GATTS_START_EVT:
-		return "ESP_GATTS_START_EVT";
-	case ESP_GATTS_STOP_EVT:
-		return "ESP_GATTS_STOP_EVT";
-	case ESP_GATTS_CONNECT_EVT:
-		return "ESP_GATTS_CONNECT_EVT";
-	case ESP_GATTS_DISCONNECT_EVT:
-		return "ESP_GATTS_DISCONNECT_EVT";
-	case ESP_GATTS_OPEN_EVT:
-		return "ESP_GATTS_OPEN_EVT";
-	case ESP_GATTS_CANCEL_OPEN_EVT:
-		return "ESP_GATTS_CANCEL_OPEN_EVT";
-	case ESP_GATTS_CLOSE_EVT:
-		return "ESP_GATTS_CLOSE_EVT";
-	case ESP_GATTS_LISTEN_EVT:
-		return "ESP_GATTS_LISTEN_EVT";
-	case ESP_GATTS_CONGEST_EVT:
-		return "ESP_GATTS_CONGEST_EVT";
-	case ESP_GATTS_RESPONSE_EVT:
-		return "ESP_GATTS_RESPONSE_EVT";
-	case ESP_GATTS_CREAT_ATTR_TAB_EVT:
-		return "ESP_GATTS_CREAT_ATTR_TAB_EVT";
-	case ESP_GATTS_SET_ATTR_VAL_EVT:
-		return "ESP_GATTS_SET_ATTR_VAL_EVT";
-	}
-	return "Unknown";
-} // gattServerEventTypeToString
-
-
-
-/**
- * @brief Convert a BLE device type to a string.
- * @param [in] type The device type.
- */
-const char* BLEUtils::devTypeToString(esp_bt_dev_type_t type) {
-	switch(type) {
-	case ESP_BT_DEVICE_TYPE_BREDR:
-		return "ESP_BT_DEVICE_TYPE_BREDR";
-	case ESP_BT_DEVICE_TYPE_BLE:
-		return "ESP_BT_DEVICE_TYPE_BLE";
-	case ESP_BT_DEVICE_TYPE_DUMO:
-		return "ESP_BT_DEVICE_TYPE_DUMO";
-	default:
-		return "Unknown";
-	}
-} // devTypeToString
-
-
-/**
- * @brief Dump the GAP event to the log.
- */
-void BLEUtils::dumpGapEvent(
-	esp_gap_ble_cb_event_t event,
-	esp_ble_gap_cb_param_t *param) {
-	ESP_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event));
-	switch(event) {
-		//
-		// ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
-		//
-		case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %d]",	param->scan_rsp_data_cmpl.status);
-			break;
-		} // ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
-
-
-		//
-		// ESP_GAP_BLE_ADV_START_COMPLETE_EVT
-		//
-		case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %d]",	param->scan_start_cmpl.status);
-			break;
-		} // ESP_GAP_BLE_ADV_START_COMPLETE_EVT
-
-
-		//
-		// ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
-		//
-		case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %d]",	param->scan_stop_cmpl.status);
-			break;
-		} // ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
-
-
-		//
-		// ESP_GAP_BLE_AUTH_CMPL_EVT
-		//
-		case ESP_GAP_BLE_AUTH_CMPL_EVT: {
-			ESP_LOGD(LOG_TAG, "[bd_addr: %s, key_present: %d, key: ***, key_type: %d, success: %d, fail_reason: %d, addr_type: ***, dev_type: %s]",
-				BLEAddress(param->ble_security.auth_cmpl.bd_addr).toString().c_str(),
-				param->ble_security.auth_cmpl.key_present,
-				param->ble_security.auth_cmpl.key_type,
-				param->ble_security.auth_cmpl.success,
-				param->ble_security.auth_cmpl.fail_reason,
-				BLEUtils::devTypeToString(param->ble_security.auth_cmpl.dev_type)
-			);
-			break;
-		} // ESP_GAP_BLE_AUTH_CMPL_EVT
-
-
-		//
-		// ESP_GAP_BLE_LOCAL_IR_EVT
-		//
-		case ESP_GAP_BLE_LOCAL_IR_EVT: {
-			break;
-		} // ESP_GAP_BLE_LOCAL_IR_EVT
-
-
-		//
-		// ESP_GAP_BLE_LOCAL_ER_EVT
-		//
-		case ESP_GAP_BLE_LOCAL_ER_EVT: {
-			break;
-		} // ESP_GAP_BLE_LOCAL_ER_EVT
-
-
-		//
-		// ESP_GAP_BLE_NC_REQ_EVT
-		//
-		case ESP_GAP_BLE_NC_REQ_EVT: {
-			ESP_LOGD(LOG_TAG, "[bd_addr: %s, passkey: %d]",
-				BLEAddress(param->ble_security.key_notif.bd_addr).toString().c_str(),
-				param->ble_security.key_notif.passkey);
-			break;
-		} // ESP_GAP_BLE_NC_REQ_EVT
-
-
-		//
-		// ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT
-		//
-		case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %d]",	param->scan_param_cmpl.status);
-			break;
-		} // ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT
-
-		//
-		// ESP_GAP_BLE_SCAN_RESULT_EVT
-		//
-		// scan_rst:
-		// - search_evt
-		// - bda
-		// - dev_type
-		// - ble_addr_type
-		// - ble_evt_type
-		// - rssi
-		// - ble_adv
-		// - flag
-		// - num_resps
-		case ESP_GAP_BLE_SCAN_RESULT_EVT: {
-			switch(param->scan_rst.search_evt) {
-				case ESP_GAP_SEARCH_INQ_RES_EVT: {
-					ESP_LOGD(LOG_TAG, "search_evt: %s, bda: %s, dev_type: %s, ble_addr_type: %s, ble_evt_type: %s, rssi: %d, ble_adv: ??, flag: %d, num_resps: %d, adv_data_len: %d, scan_rsp_len: %d",
-						searchEventTypeToString(param->scan_rst.search_evt),
-						BLEAddress(param->scan_rst.bda).toString().c_str(),
-						devTypeToString(param->scan_rst.dev_type),
-						addressTypeToString(param->scan_rst.ble_addr_type),
-						eventTypeToString(param->scan_rst.ble_evt_type),
-						param->scan_rst.rssi,
-						param->scan_rst.flag,
-						param->scan_rst.num_resps,
-						param->scan_rst.adv_data_len,
-						param->scan_rst.scan_rsp_len
-					);
-					break;
-				} // ESP_GAP_SEARCH_INQ_RES_EVT
-
-				default: {
-					ESP_LOGD(LOG_TAG, "search_evt: %s",searchEventTypeToString(param->scan_rst.search_evt));
-					break;
-				}
-			}
-			break;
-		} // ESP_GAP_BLE_SCAN_RESULT_EVT
-
-
-		//
-		// ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
-		//
-		case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_start_cmpl.status);
-			break;
-		} // ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
-
-
-		//
-		// ESP_GAP_BLE_SEC_REQ_EVT
-		//
-		case ESP_GAP_BLE_SEC_REQ_EVT: {
-			ESP_LOGD(LOG_TAG, "[bd_addr: %s]", BLEAddress(param->ble_security.ble_req.bd_addr).toString().c_str());
-			break;
-		} // ESP_GAP_BLE_SEC_REQ_EVT
-
-
-		//
-		// ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT
-		//
-		case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_stop_cmpl.status);
-			break;
-		} // ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT
-
-		default: {
-			ESP_LOGD(LOG_TAG, "*** dumpGapEvent: Logger not coded ***");
-			break;
-		} // default
-	} // switch
-} // dumpGapEvent
-
-
-/**
- * @brief Decode and dump a GATT client event
- *
- * @param [in] event The type of event received.
- * @param [in] evtParam The data associated with the event.
- */
-void BLEUtils::dumpGattClientEvent(
-	esp_gattc_cb_event_t event,
-	esp_gatt_if_t gattc_if,
-	esp_ble_gattc_cb_param_t *evtParam) {
-
-	//esp_ble_gattc_cb_param_t *evtParam = (esp_ble_gattc_cb_param_t *)param;
-	ESP_LOGD(LOG_TAG, "GATT Event: %s", BLEUtils::gattClientEventTypeToString(event).c_str());
-	switch(event) {
-		//
-		// ESP_GATTC_CLOSE_EVT
-		//
-		// close:
-		// - esp_gatt_status_t      status
-		// - uint16_t               conn_id
-		// - esp_bd_addr_t          remote_bda
-		// - esp_gatt_conn_reason_t reason
-		//
-		case ESP_GATTC_CLOSE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, reason:%s, conn_id: %d]",
-				BLEUtils::gattStatusToString(evtParam->close.status).c_str(),
-				BLEUtils::gattCloseReasonToString(evtParam->close.reason).c_str(),
-				evtParam->close.conn_id);
-			break;
-		}
-
-		//
-		// ESP_GATTC_CONNECT_EVT
-		//
-		// connect:
-		// - esp_gatt_status_t status
-		// - uint16_t          conn_id
-		// - esp_bd_addr_t     remote_bda
-		case ESP_GATTC_CONNECT_EVT: {
-			ESP_LOGD(LOG_TAG, "[staus: %s, conn_id: %d, remote_bda: %s]",
-				BLEUtils::gattStatusToString(evtParam->connect.status).c_str(),
-				evtParam->connect.conn_id,
-				BLEAddress(evtParam->connect.remote_bda).toString().c_str()
-			);
-			break;
-		}
-
-		//
-		// ESP_GATTC_DISCONNECT_EVT
-		//
-		// disconnect:
-		// - esp_gatt_status_t status
-		// - uint16_t          conn_id
-		// - esp_bd_addr_t     remote_bda
-		case ESP_GATTC_DISCONNECT_EVT: {
-			ESP_LOGD(LOG_TAG, "[staus: %s, conn_id: %d, remote_bda: %s]",
-				BLEUtils::gattStatusToString(evtParam->disconnect.status).c_str(),
-				evtParam->disconnect.conn_id,
-				BLEAddress(evtParam->disconnect.remote_bda).toString().c_str()
-			);
-			break;
-		} // ESP_GATTC_DISCONNECT_EVT
-
-		//
-		// ESP_GATTC_GET_CHAR_EVT
-		//
-		// get_char:
-		// - esp_gatt_status_t    status
-		// - uin1t6_t             conn_id
-		// - esp_gatt_srvc_id_t   srvc_id
-		// - esp_gatt_id_t        char_id
-		// - esp_gatt_char_prop_t char_prop
-		//
-		case ESP_GATTC_GET_CHAR_EVT: {
-
-			// If the status of the event shows that we have a value other than ESP_GATT_OK then the
-			// characteristic fields are not set to a usable value .. so don't try and log them.
-			if (evtParam->get_char.status == ESP_GATT_OK) {
-				std::string description = "Unknown";
-				if (evtParam->get_char.char_id.uuid.len == ESP_UUID_LEN_16) {
-					description = BLEUtils::gattCharacteristicUUIDToString(evtParam->get_char.char_id.uuid.uuid.uuid16);
-				}
-				ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: %s, char_id: %s [description: %s]\nchar_prop: %s]",
-					BLEUtils::gattStatusToString(evtParam->get_char.status).c_str(),
-					evtParam->get_char.conn_id,
-					BLEUtils::gattServiceIdToString(evtParam->get_char.srvc_id).c_str(),
-					gattIdToString(evtParam->get_char.char_id).c_str(),
-					description.c_str(),
-					BLEUtils::characteristicPropertiesToString(evtParam->get_char.char_prop).c_str()
-				);
-			} else {
-				ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: %s]",
-					BLEUtils::gattStatusToString(evtParam->get_char.status).c_str(),
-					evtParam->get_char.conn_id,
-					BLEUtils::gattServiceIdToString(evtParam->get_char.srvc_id).c_str()
-				);
-			}
-			break;
-		} // ESP_GATTC_GET_CHAR_EVT
-
-		//
-		// ESP_GATTC_NOTIFY_EVT
-		//
-		// notify
-		// uint16_t           conn_id
-		// esp_bd_addr_t      remote_bda
-		// esp_gatt_srvc_id_t srvc_id
-		// esp_gatt_id_t      char_id
-		// esp_gatt_id_t      descr_id
-		// uint16_t           value_len
-		// uint8_t*           value
-		// bool               is_notify
-		//
-		case ESP_GATTC_NOTIFY_EVT: {
-			ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s, srvc_id: <%s>, char_id: <%s>, descr_id: <%s>, value_len: %d, is_notify: %d]",
-				evtParam->notify.conn_id,
-				BLEAddress(evtParam->notify.remote_bda).toString().c_str(),
-				BLEUtils::gattServiceIdToString(evtParam->notify.srvc_id).c_str(),
-				gattIdToString(evtParam->notify.char_id).c_str(),
-				gattIdToString(evtParam->notify.descr_id).c_str(),
-				evtParam->notify.value_len,
-				evtParam->notify.is_notify
-			);
-			break;
-		}
-
-		//
-		// ESP_GATTC_OPEN_EVT
-		//
-		// open:
-		// - esp_gatt_status_t status
-		// - uint16_t          conn_id
-		// - esp_bd_addr_t     remote_bda
-		// - uint16_t          mtu
-		//
-		case ESP_GATTC_OPEN_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, remote_bda: %s, mtu: %d]",
-				BLEUtils::gattStatusToString(evtParam->open.status).c_str(),
-				evtParam->open.conn_id,
-				BLEAddress(evtParam->open.remote_bda).toString().c_str(),
-				evtParam->open.mtu);
-			break;
-		} // ESP_GATTC_OPEN_EVT
-
-
-		//
-		// ESP_GATTC_READ_CHAR_EVT
-		//
-		// Callback to indicate that requested data that we wanted to read is now available.
-		//
-		// read:
-		// esp_gatt_status_t  status
-		// uint16_t           conn_id
-		// esp_gatt_srvc_id_t srvc_id
-		// esp_gatt_id_t      char_id
-		// esp_gatt_id_t      descr_id
-		// uint8_t*           value
-		// uint16_t           value_type
-		// uint16_t           value_len
-		case ESP_GATTC_READ_CHAR_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: <%s>, char_id: <%s>, descr_id: <%s>, value_type: 0x%x, value_len: %d]",
-				BLEUtils::gattStatusToString(evtParam->read.status).c_str(),
-				evtParam->read.conn_id,
-				BLEUtils::gattServiceIdToString(evtParam->read.srvc_id).c_str(),
-				gattIdToString(evtParam->read.char_id).c_str(),
-				gattIdToString(evtParam->read.descr_id).c_str(),
-				evtParam->read.value_type,
-				evtParam->read.value_len
-			);
-			if (evtParam->read.status == ESP_GATT_OK) {
-				GeneralUtils::hexDump(evtParam->read.value, evtParam->read.value_len);
-				/*
-				char *pHexData = BLEUtils::buildHexData(nullptr, evtParam->read.value, evtParam->read.value_len);
-				ESP_LOGD(LOG_TAG, "value: %s \"%s\"", pHexData, BLEUtils::buildPrintData(evtParam->read.value, evtParam->read.value_len).c_str());
-				free(pHexData);
-				*/
-			}
-			break;
-		} // ESP_GATTC_READ_CHAR_EVT
-
-
-		//
-		// ESP_GATTC_REG_EVT
-		//
-		// reg:
-		// - esp_gatt_status_t status
-		// - uint16_t          app_id
-		//
-		case ESP_GATTC_REG_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, app_id: 0x%x]",
-				BLEUtils::gattStatusToString(evtParam->reg.status).c_str(),
-				evtParam->reg.app_id);
-			break;
-		} // ESP_GATTC_REG_EVT
-
-
-		//
-		// ESP_GATTC_REG_FOR_NOTIFY_EVT
-		//
-		// reg_for_notify:
-		// - esp_gatt_status_t status
-		// - esp_gatt_srvc_id_t srvc_id
-		// - esp_gatt_id_t char_id
-		case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, srvc_id: <%s>, char_id: <%s>]",
-				BLEUtils::gattStatusToString(evtParam->reg_for_notify.status).c_str(),
-				BLEUtils::gattServiceIdToString(evtParam->reg_for_notify.srvc_id).c_str(),
-				gattIdToString(evtParam->reg_for_notify.char_id).c_str());
-			break;
-		} // ESP_GATTC_REG_FOR_NOTIFY_EVT
-
-
-		//
-		// ESP_GATTC_SEARCH_CMPL_EVT
-		//
-		// search_cmpl:
-		// - esp_gatt_status_t status
-		// - uint16_t          conn_id
-		//
-		case ESP_GATTC_SEARCH_CMPL_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d]",
-				BLEUtils::gattStatusToString(evtParam->search_cmpl.status).c_str(),
-				evtParam->search_cmpl.conn_id);
-			break;
-		} // ESP_GATTC_SEARCH_CMPL_EVT
-
-
-		//
-		// ESP_GATTC_SEARCH_RES_EVT
-		//
-		// search_res:
-		// - uint16_t           conn_id
-		// - esp_gatt_srvc_id_t srvc_id
-		//
-		case ESP_GATTC_SEARCH_RES_EVT: {
-			std::string name = "";
-			if (evtParam->search_res.srvc_id.id.uuid.len == ESP_UUID_LEN_16) {
-				name = BLEUtils::gattServiceToString(evtParam->search_res.srvc_id.id.uuid.uuid.uuid16);
-			}
-			if (name.length() == 0) {
-				name = "<Unknown Service>";
-			}
-
-			ESP_LOGD(LOG_TAG, "[srvc_id: %s [%s], instanceId: 0x%.2x conn_id: %d]",
-				BLEUtils::gattServiceIdToString(evtParam->search_res.srvc_id).c_str(),
-				name.c_str(),
-				evtParam->search_res.srvc_id.id.inst_id,
-				evtParam->search_res.conn_id);
-			break;
-		} // ESP_GATTC_SEARCH_RES_EVT
-
-
-		//
-		// ESP_GATTC_WRITE_CHAR_EVT
-		//
-		// write:
-		// esp_gatt_status_t  status
-		// uint16_t           conn_id
-		// esp_gatt_srvc_id_t srvc_id
-		// esp_gatt_id_t      char_id
-		// esp_gatt_id_t      descr_id
-		case ESP_GATTC_WRITE_CHAR_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: <%s>, char_id: <%s>, descr_id: <%s>]",
-				BLEUtils::gattStatusToString(evtParam->write.status).c_str(),
-				evtParam->write.conn_id,
-				BLEUtils::gattServiceIdToString(evtParam->write.srvc_id).c_str(),
-				gattIdToString(evtParam->write.char_id).c_str(),
-				gattIdToString(evtParam->write.descr_id).c_str()
-			);
-			break;
-		}
-
-		default:
-			break;
-	}
-} // dumpGattClientEvent
-
-
-/**
- * @brief Dump the details of a GATT server event.
- * A GATT Server event is a callback received from the BLE subsystem when we are acting as a BLE
- * server.  The callback indicates the type of event in the `event` field.  The `evtParam` is a
- * union of structures where we can use the `event` to indicate which of the structures has been
- * populated and hence is valid.
- *
- * @param [in] event The event type that was posted.
- * @param [in] evtParam A union of structures only one of which is populated.
- */
-void BLEUtils::dumpGattServerEvent(
-		esp_gatts_cb_event_t event,
-		esp_gatt_if_t gatts_if,
-		esp_ble_gatts_cb_param_t *evtParam) {
-	ESP_LOGD(LOG_TAG, "GATT ServerEvent: %s", BLEUtils::gattServerEventTypeToString(event).c_str());
-	switch(event) {
-
-		case ESP_GATTS_ADD_CHAR_DESCR_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, attr_handle: 0x%.2x, service_handle: 0x%.2x, char_uuid: %s]",
-				gattStatusToString(evtParam->add_char_descr.status).c_str(),
-				evtParam->add_char_descr.attr_handle,
-				evtParam->add_char_descr.service_handle,
-				BLEUUID(evtParam->add_char_descr.char_uuid).toString().c_str());
-			break;
-		} // ESP_GATTS_ADD_CHAR_DESCR_EVT
-
-		case ESP_GATTS_ADD_CHAR_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, attr_handle: 0x%.2x, service_handle: 0x%.2x, char_uuid: %s]",
-				gattStatusToString(evtParam->add_char.status).c_str(),
-				evtParam->add_char.attr_handle,
-				evtParam->add_char.service_handle,
-				BLEUUID(evtParam->add_char.char_uuid).toString().c_str());
-			break;
-		} // ESP_GATTS_ADD_CHAR_EVT
-
-
-		// ESP_GATTS_CONF_EVT
-		//
-		// conf:
-		// - esp_gatt_status_t status  – The status code.
-		// - uint16_t          conn_id – The connection used.
-		//
-		case ESP_GATTS_CONF_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, conn_id: 0x%.2x]",
-				gattStatusToString(evtParam->conf.status).c_str(),
-				evtParam->conf.conn_id);
-			break;
-		} // ESP_GATTS_CONF_EVT
-
-
-		case ESP_GATTS_CONGEST_EVT: {
-			ESP_LOGD(LOG_TAG, "[conn_id: %d, congested: %d]",
-				evtParam->congest.conn_id,
-				evtParam->congest.congested);
-			break;
-		} // ESP_GATTS_CONGEST_EVT
-
-		case ESP_GATTS_CONNECT_EVT: {
-			ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s, is_connected: %d]",
-				evtParam->connect.conn_id,
-				BLEAddress(evtParam->connect.remote_bda).toString().c_str(),
-				evtParam->connect.is_connected);
-			break;
-		} // ESP_GATTS_CONNECT_EVT
-
-		case ESP_GATTS_CREATE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, service_handle: 0x%.2x, service_id: [%s]]",
-				gattStatusToString(evtParam->create.status).c_str(),
-				evtParam->create.service_handle,
-				gattServiceIdToString(evtParam->create.service_id).c_str());
-			break;
-		} // ESP_GATTS_CREATE_EVT
-
-		case ESP_GATTS_DISCONNECT_EVT: {
-			ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s, is_connected: %d]",
-				evtParam->connect.conn_id,
-				BLEAddress(evtParam->connect.remote_bda).toString().c_str(),
-				evtParam->connect.is_connected);
-			break;
-		} // ESP_GATTS_DISCONNECT_EVT
-
-
-		// ESP_GATTS_EXEC_WRITE_EVT
-		// exec_write:
-		// - uint16_t conn_id
-		// - uint32_t trans_id
-		// - esp_bd_addr_t bda
-		// - uint8_t exec_write_flag
-		//
-		case ESP_GATTS_EXEC_WRITE_EVT: {
-			char* pWriteFlagText;
-			switch(evtParam->exec_write.exec_write_flag) {
-				case ESP_GATT_PREP_WRITE_EXEC: {
-					pWriteFlagText = (char*)"WRITE";
-					break;
-				}
-
-				case ESP_GATT_PREP_WRITE_CANCEL: {
-					pWriteFlagText = (char*)"CANCEL";
-					break;
-				}
-
-				default:
-					pWriteFlagText = (char*)"<Unknown>";
-					break;
-			}
-
-			ESP_LOGD(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, exec_write_flag: 0x%.2x=%s]",
-				evtParam->exec_write.conn_id,
-				evtParam->exec_write.trans_id,
-				BLEAddress(evtParam->exec_write.bda).toString().c_str(),
-				evtParam->exec_write.exec_write_flag,
-				pWriteFlagText);
-			break;
-		} // ESP_GATTS_DISCONNECT_EVT
-
-
-		case ESP_GATTS_MTU_EVT: {
-			ESP_LOGD(LOG_TAG, "[conn_id: %d, mtu: %d]",
-					evtParam->mtu.conn_id,
-					evtParam->mtu.mtu);
-			break;
-		} // ESP_GATTS_MTU_EVT
-
-		case ESP_GATTS_READ_EVT: {
-			ESP_LOGD(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, handle: 0x%.2x, is_long: %d, need_rsp:%d]",
-					evtParam->read.conn_id,
-					evtParam->read.trans_id,
-					BLEAddress(evtParam->read.bda).toString().c_str(),
-					evtParam->read.handle,
-					evtParam->read.is_long,
-					evtParam->read.need_rsp);
-			break;
-		} // ESP_GATTS_READ_EVT
-
-		case ESP_GATTS_RESPONSE_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, handle: 0x%.2x]",
-				gattStatusToString(evtParam->rsp.status).c_str(),
-				evtParam->rsp.handle);
-			break;
-		} // ESP_GATTS_RESPONSE_EVT
-
-		case ESP_GATTS_REG_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, app_id: %d]",
-				gattStatusToString(evtParam->reg.status).c_str(),
-				evtParam->reg.app_id);
-			break;
-		} // ESP_GATTS_REG_EVT
-
-
-		// ESP_GATTS_START_EVT
-		//
-		// start:
-		// - esp_gatt_status_t status
-		// - uint16_t          service_handle
-		//
-		case ESP_GATTS_START_EVT: {
-			ESP_LOGD(LOG_TAG, "[status: %s, service_handle: 0x%.2x]",
-				gattStatusToString(evtParam->start.status).c_str(),
-				evtParam->start.service_handle);
-			break;
-		} // ESP_GATTS_START_EVT
-
-
-		// ESP_GATTS_WRITE_EVT
-		//
-		// write:
-		// - uint16_t      conn_id  – The connection id.
-		// - uint16_t      trans_id – The transfer id.
-		// - esp_bd_addr_t bda      – The address of the partner.
-		// - uint16_t      handle   – The attribute handle.
-		// - uint16_t      offset   – The offset of the currently received within the whole value.
-		// - bool          need_rsp – Do we need a response?
-		// - bool          is_prep  – Is this a write prepare?  If set, then this is to be considered part of the received value and not the whole value.  A subsequent ESP_GATTS_EXEC_WRITE will mark the total.
-		// - uint16_t      len      – The length of the incoming value part.
-		// - uint8_t*      value    – The data for this value part.
-		//
-		case ESP_GATTS_WRITE_EVT: {
-			ESP_LOGD(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, handle: 0x%.2x, offset: %d, need_rsp: %d, is_prep: %d, len: %d]",
-					evtParam->write.conn_id,
-					evtParam->write.trans_id,
-					BLEAddress(evtParam->write.bda).toString().c_str(),
-					evtParam->write.handle,
-					evtParam->write.offset,
-					evtParam->write.need_rsp,
-					evtParam->write.is_prep,
-					evtParam->write.len);
-			char *pHex = buildHexData(nullptr, evtParam->write.value, evtParam->write.len);
-			ESP_LOGD(LOG_TAG, "[Data: %s]", pHex);
-			free(pHex);
-			break;
-		} // ESP_GATTS_WRITE_EVT
-
-		default:
-			ESP_LOGD(LOG_TAG, "dumpGattServerEvent: *** NOT CODED ***");
-			break;
-		}
-} // dumpGattServerEvent
-
-
-/**
- * @brief Convert a BLE event type to a string.
- * @param [in] eventType The event type.
- * @return The event type as a string.
- */
-const char* BLEUtils::eventTypeToString(esp_ble_evt_type_t eventType) {
-	switch(eventType) {
-		case ESP_BLE_EVT_CONN_ADV:
-			return "ESP_BLE_EVT_CONN_ADV";
-		case ESP_BLE_EVT_CONN_DIR_ADV:
-			return "ESP_BLE_EVT_CONN_DIR_ADV";
-		case ESP_BLE_EVT_DISC_ADV:
-			return "ESP_BLE_EVT_DISC_ADV";
-		case ESP_BLE_EVT_NON_CONN_ADV:
-			return "ESP_BLE_EVT_NON_CONN_ADV";
-		case ESP_BLE_EVT_SCAN_RSP:
-			return "ESP_BLE_EVT_SCAN_RSP";
-		default:
-			ESP_LOGD(LOG_TAG, "Unknown esp_ble_evt_type_t: %d", eventType);
-			return "*** Unknown ***";
-	}
-} // eventTypeToString
-
-
-
-/**
- * @brief Convert a BT GAP event type to a string representation.
- * @param [in] eventType The type of event.
- * @return A string representation of the event type.
- */
-const char* BLEUtils::gapEventToString(uint32_t eventType) {
-	switch(eventType) {
-		case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
-			return "ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT";
-		case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
-			return "ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT";
-		case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
-			return "ESP_GAP_BLE_ADV_START_COMPLETE_EVT";
-		case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
-			return "ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT";
-		case ESP_GAP_BLE_SCAN_RESULT_EVT:
-			return "ESP_GAP_BLE_SCAN_RESULT_EVT";
-		case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
-			return "ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT";
-		case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
-			return "ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT";
-		case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
-			return "ESP_GAP_BLE_SCAN_START_COMPLETE_EVT";
-		case ESP_GAP_BLE_AUTH_CMPL_EVT:                              /* Authentication complete indication. */
-			return "ESP_GAP_BLE_AUTH_CMPL_EVT";
-		case ESP_GAP_BLE_KEY_EVT:                                    /* BLE  key event for peer device keys */
-			return "ESP_GAP_BLE_KEY_EVT";
-		case ESP_GAP_BLE_SEC_REQ_EVT:                                /* BLE  security request */
-			return "ESP_GAP_BLE_SEC_REQ_EVT";
-		case ESP_GAP_BLE_PASSKEY_NOTIF_EVT:                          /* passkey notification event */
-			return "ESP_GAP_BLE_PASSKEY_NOTIF_EVT";
-		case ESP_GAP_BLE_PASSKEY_REQ_EVT:                            /* passkey request event */
-			return "ESP_GAP_BLE_PASSKEY_REQ_EVT";
-		case ESP_GAP_BLE_OOB_REQ_EVT:                                /* OOB request event */
-			return "ESP_GAP_BLE_OOB_REQ_EVT";
-		case ESP_GAP_BLE_LOCAL_IR_EVT:                               /* BLE local IR event */
-			return "ESP_GAP_BLE_LOCAL_IR_EVT";
-		case ESP_GAP_BLE_LOCAL_ER_EVT:                               /* BLE local ER event */
-			return "ESP_GAP_BLE_LOCAL_ER_EVT";
-		case ESP_GAP_BLE_NC_REQ_EVT:                                 /* Numeric Comparison request event */
-			return "ESP_GAP_BLE_NC_REQ_EVT";
-		case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:                      /*!< When stop adv complete, the event comes */
-			return "ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT";
-		case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
-			return "ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT";
-		default:
-			ESP_LOGD(LOG_TAG, "gapEventToString: Unknown event type 0x%x", eventType);
-			return "Unknown event type";
-	}
-} // gapEventToString
-
-
-std::string BLEUtils::gattCharacteristicUUIDToString(uint32_t characteristicUUID) {
-	characteristicMap_t *p = g_characteristicsMappings;
-	while (p->name.length() > 0) {
-		if (p->assignedNumber == characteristicUUID) {
-			return p->name;
-		}
-		p++;
-	}
-	return "Unknown";
-} // gattCharacteristicUUIDToString
-
-
-/**
- * @brief Convert an esp_gatt_srvc_id_t to a string.
- */
-std::string BLEUtils::gattServiceIdToString(esp_gatt_srvc_id_t srvcId) {
-	return gattIdToString(srvcId.id);
-} // gattServiceIdToString
-
-
-std::string BLEUtils::gattServiceToString(uint32_t serviceId) {
-	gattService_t* p = (gattService_t *)g_gattServices;
-	while (p->name.length() > 0) {
-		if (p->assignedNumber == serviceId) {
-			return p->name;
-		}
-		p++;
-	}
-	return "Unknown";
-} // gattServiceToString
-
-
-/**
- * @brief Convert a GATT status to a string.
- *
- * @param [in] status The status to convert.
- * @return A string representation of the status.
- */
-std::string BLEUtils::gattStatusToString(esp_gatt_status_t status) {
-	switch(status) {
-		case ESP_GATT_OK:
-			return "ESP_GATT_OK";
-		case ESP_GATT_INVALID_HANDLE:
-			return "ESP_GATT_INVALID_HANDLE";
-		case ESP_GATT_READ_NOT_PERMIT:
-			return "ESP_GATT_READ_NOT_PERMIT";
-		case ESP_GATT_WRITE_NOT_PERMIT:
-			return "ESP_GATT_WRITE_NOT_PERMIT";
-		case ESP_GATT_INVALID_PDU:
-			return "ESP_GATT_INVALID_PDU";
-		case ESP_GATT_INSUF_AUTHENTICATION:
-			return "ESP_GATT_INSUF_AUTHENTICATION";
-		case ESP_GATT_REQ_NOT_SUPPORTED:
-			return "ESP_GATT_REQ_NOT_SUPPORTED";
-		case ESP_GATT_INVALID_OFFSET:
-			return "ESP_GATT_INVALID_OFFSET";
-		case ESP_GATT_INSUF_AUTHORIZATION:
-			return "ESP_GATT_INSUF_AUTHORIZATION";
-		case ESP_GATT_PREPARE_Q_FULL:
-			return "ESP_GATT_PREPARE_Q_FULL";
-		case ESP_GATT_NOT_FOUND:
-			return "ESP_GATT_NOT_FOUND";
-		case ESP_GATT_NOT_LONG:
-			return "ESP_GATT_NOT_LONG";
-		case ESP_GATT_INSUF_KEY_SIZE:
-			return "ESP_GATT_INSUF_KEY_SIZE";
-		case ESP_GATT_INVALID_ATTR_LEN:
-			return "ESP_GATT_INVALID_ATTR_LEN";
-		case ESP_GATT_ERR_UNLIKELY:
-			return "ESP_GATT_ERR_UNLIKELY";
-		case ESP_GATT_INSUF_ENCRYPTION:
-			return "ESP_GATT_INSUF_ENCRYPTION";
-		case ESP_GATT_UNSUPPORT_GRP_TYPE:
-			return "ESP_GATT_UNSUPPORT_GRP_TYPE";
-		case ESP_GATT_INSUF_RESOURCE:
-			return "ESP_GATT_INSUF_RESOURCE";
-		case ESP_GATT_NO_RESOURCES:
-			return "ESP_GATT_NO_RESOURCES";
-		case ESP_GATT_INTERNAL_ERROR:
-			return "ESP_GATT_INTERNAL_ERROR";
-		case ESP_GATT_WRONG_STATE:
-			return "ESP_GATT_WRONG_STATE";
-		case ESP_GATT_DB_FULL:
-			return "ESP_GATT_DB_FULL";
-		case ESP_GATT_BUSY:
-			return "ESP_GATT_BUSY";
-		case ESP_GATT_ERROR:
-			return "ESP_GATT_ERROR";
-		case ESP_GATT_CMD_STARTED:
-			return "ESP_GATT_CMD_STARTED";
-		case ESP_GATT_ILLEGAL_PARAMETER:
-			return "ESP_GATT_ILLEGAL_PARAMETER";
-		case ESP_GATT_PENDING:
-			return "ESP_GATT_PENDING";
-		case ESP_GATT_AUTH_FAIL:
-			return "ESP_GATT_AUTH_FAIL";
-		case ESP_GATT_MORE:
-			return "ESP_GATT_MORE";
-		case ESP_GATT_INVALID_CFG:
-			return "ESP_GATT_INVALID_CFG";
-		case ESP_GATT_SERVICE_STARTED:
-			return "ESP_GATT_SERVICE_STARTED";
-		case ESP_GATT_ENCRYPED_NO_MITM:
-			return "ESP_GATT_ENCRYPED_NO_MITM";
-		case ESP_GATT_NOT_ENCRYPTED:
-			return "ESP_GATT_NOT_ENCRYPTED";
-		case ESP_GATT_CONGESTED:
-			return "ESP_GATT_CONGESTED";
-		case ESP_GATT_DUP_REG:
-			return "ESP_GATT_DUP_REG";
-		case ESP_GATT_ALREADY_OPEN:
-			return "ESP_GATT_ALREADY_OPEN";
-		case ESP_GATT_CANCEL:
-			return "ESP_GATT_CANCEL";
-		case ESP_GATT_CCC_CFG_ERR:
-			return "ESP_GATT_CCC_CFG_ERR";
-		case ESP_GATT_PRC_IN_PROGRESS:
-			return "ESP_GATT_PRC_IN_PROGRESS";
-		default:
-			return "Unknown";
-	}
-} // gattStatusToString
-
-
-/**
- * @brief convert a GAP search event to a string.
- * @param [in] searchEvt
- * @return The search event type as a string.
- */
-const char* BLEUtils::searchEventTypeToString(esp_gap_search_evt_t searchEvt) {
-	switch(searchEvt) {
-		case ESP_GAP_SEARCH_INQ_RES_EVT:
-			return "ESP_GAP_SEARCH_INQ_RES_EVT";
-		case ESP_GAP_SEARCH_INQ_CMPL_EVT:
-			return "ESP_GAP_SEARCH_INQ_CMPL_EVT";
-		case ESP_GAP_SEARCH_DISC_RES_EVT:
-			return "ESP_GAP_SEARCH_DISC_RES_EVT";
-		case ESP_GAP_SEARCH_DISC_BLE_RES_EVT:
-			return "ESP_GAP_SEARCH_DISC_BLE_RES_EVT";
-		case ESP_GAP_SEARCH_DISC_CMPL_EVT:
-			return "ESP_GAP_SEARCH_DISC_CMPL_EVT";
-		case ESP_GAP_SEARCH_DI_DISC_CMPL_EVT:
-			return "ESP_GAP_SEARCH_DI_DISC_CMPL_EVT";
-		case ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT:
-			return "ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT";
-		default:
-			ESP_LOGD(LOG_TAG, "Unknown event type: 0x%x", searchEvt);
-			return "Unknown event type";
-	}
-} // searchEventTypeToString
-
-#endif // CONFIG_BT_ENABLED
diff --git a/components/cpp_utils/BLEUtils.h b/components/cpp_utils/BLEUtils.h
deleted file mode 100644
index 28c7a7e..0000000
--- a/components/cpp_utils/BLEUtils.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * BLEUtils.h
- *
- *  Created on: Mar 25, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEUTILS_H_
-#define COMPONENTS_CPP_UTILS_BLEUTILS_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <esp_gattc_api.h>   // ESP32 BLE
-#include <esp_gatts_api.h>   // ESP32 BLE
-#include <esp_gap_ble_api.h> // ESP32 BLE
-#include <string>
-#include "BLEClient.h"
-
-/**
- * @brief A set of general %BLE utilities.
- */
-class BLEUtils {
-public:
-	static const char* advTypeToString(uint8_t advType);
-	static esp_gatt_id_t buildGattId(esp_bt_uuid_t uuid, uint8_t inst_id=0);
-
-	static esp_gatt_srvc_id_t buildGattSrvcId(esp_gatt_id_t gattId, bool is_primary=true);
-	static std::string characteristicPropertiesToString(esp_gatt_char_prop_t prop);
-	static char* buildHexData(uint8_t *target, uint8_t *source, uint8_t length);
-	static BLEClient* findByConnId(uint16_t conn_id);
-	static BLEClient* findByAddress(BLEAddress address);
-	static std::string gattClientEventTypeToString(esp_gattc_cb_event_t eventType);
-	static std::string gattServerEventTypeToString(esp_gatts_cb_event_t eventType);
-	static std::string gattServiceIdToString(esp_gatt_srvc_id_t srvcId);
-	static std::string gattStatusToString(esp_gatt_status_t status);
-	static std::string gattServiceToString(uint32_t serviceId);
-	static std::string gattCloseReasonToString(esp_gatt_conn_reason_t reason);
-	static void registerByAddress(BLEAddress address, BLEClient* pDevice);
-	static void registerByConnId(uint16_t conn_id, BLEClient* pDevice);
-	static std::string gattCharacteristicUUIDToString(uint32_t characteristicUUID);
-	static std::string buildPrintData(uint8_t* source, size_t length);
-	static void dumpGattClientEvent(
-		esp_gattc_cb_event_t event,
-		esp_gatt_if_t gattc_if,
-		esp_ble_gattc_cb_param_t* evtParam);
-	static void dumpGattServerEvent(
-		esp_gatts_cb_event_t event,
-		esp_gatt_if_t gatts_if,
-		esp_ble_gatts_cb_param_t* evtParam);
-	static const char* devTypeToString(esp_bt_dev_type_t type);
-	static void dumpGapEvent(
-		esp_gap_ble_cb_event_t event,
-		esp_ble_gap_cb_param_t* param);
-	static const char* gapEventToString(uint32_t eventType);
-	static const char* searchEventTypeToString(esp_gap_search_evt_t searchEvt);
-	static const char* addressTypeToString(esp_ble_addr_type_t type);
-	static const char *eventTypeToString(esp_ble_evt_type_t eventType);
-};
-
-#endif // CONFIG_BT_ENABLED
-#endif /* COMPONENTS_CPP_UTILS_BLEUTILS_H_ */
diff --git a/components/cpp_utils/BLEValue.cpp b/components/cpp_utils/BLEValue.cpp
deleted file mode 100644
index 1989993..0000000
--- a/components/cpp_utils/BLEValue.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * BLEValue.cpp
- *
- *  Created on: Jul 17, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
-#include <esp_log.h>
-
-#include "BLEValue.h"
-
-static const char* LOG_TAG="BLEValue";
-
-BLEValue::BLEValue() {
-	m_accumulation = "";
-	m_value        = "";
-	m_readOffset   = 0;
-} // BLEValue
-
-
-/**
- * @brief Add a message part to the accumulation.
- * The accumulation is a growing set of data that is added to until a commit or cancel.
- * @param [in] part A message part being added.
- */
-void BLEValue::addPart(std::string part) {
-	ESP_LOGD(LOG_TAG, ">> addPart: length=%d", part.length());
-	m_accumulation += part;
-} // addPart
-
-
-/**
- * @brief Add a message part to the accumulation.
- * The accumulation is a growing set of data that is added to until a commit or cancel.
- * @param [in] pData A message part being added.
- * @param [in] length The number of bytes being added.
- */
-void BLEValue::addPart(uint8_t* pData, size_t length) {
-	ESP_LOGD(LOG_TAG, ">> addPart: length=%d", length);
-	m_accumulation += std::string((char *)pData, length);
-} // addPart
-
-
-/**
- * @brief Cancel the current accumulation.
- */
-void BLEValue::cancel() {
-	ESP_LOGD(LOG_TAG, ">> cancel");
-	m_accumulation = "";
-	m_readOffset   = 0;
-} // cancel
-
-
-/**
- * @brief Commit the current accumulation.
- * When writing a value, we may find that we write it in "parts" meaning that the writes come in in pieces
- * of the overall message.  After the last part has been received, we may perform a commit which means that
- * we now have the complete message and commit the change as a unit.
- */
-void BLEValue::commit() {
-	ESP_LOGD(LOG_TAG, ">> commit");
-	// If there is nothing to commit, do nothing.
-	if (m_accumulation.length() == 0) {
-		return;
-	}
-	setValue(m_accumulation);
-	m_accumulation = "";
-	m_readOffset   = 0;
-} // commit
-
-
-/**
- * @brief Get the read offset.
- * @return The read offset into the read.
- */
-uint16_t BLEValue::getReadOffset() {
-	return m_readOffset;
-} // getReadOffset
-
-
-/**
- * @brief Get the current value.
- */
-std::string BLEValue::getValue() {
-	return m_value;
-} // getValue
-
-
-/**
- * @brief Set the read offset
- * @param [in] readOffset The offset into the read.
- */
-void BLEValue::setReadOffset(uint16_t readOffset) {
-	m_readOffset = readOffset;
-} // setReadOffset
-
-
-/**
- * @brief Set the current value.
- */
-void BLEValue::setValue(std::string value) {
-	m_value = value;
-} // setValue
-
-
-/**
- * @brief Set the current value.
- * @param [in] pData The data for the current value.
- * @param [in] The length of the new current value.
- */
-void BLEValue::setValue(uint8_t* pData, size_t length) {
-	m_value = std::string((char*)pData, length);
-} // setValue
-#endif // CONFIG_BT_ENABLED
diff --git a/components/cpp_utils/BLEValue.h b/components/cpp_utils/BLEValue.h
deleted file mode 100644
index a292c6e..0000000
--- a/components/cpp_utils/BLEValue.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * BLEValue.h
- *
- *  Created on: Jul 17, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_BLEVALUE_H_
-#define COMPONENTS_CPP_UTILS_BLEVALUE_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-#include <string>
-
-/**
- * @brief The model of a %BLE value.
- */
-class BLEValue {
-public:
-	BLEValue();
-	void        addPart(std::string part);
-	void        addPart(uint8_t* pData, size_t length);
-	void        cancel();
-	void        commit();
-	uint16_t    getReadOffset();
-	std::string getValue();
-	void        setReadOffset(uint16_t readOffset);
-	void        setValue(std::string value);
-	void        setValue(uint8_t* pData, size_t length);
-
-private:
-	std::string m_accumulation;
-	uint16_t    m_readOffset;
-	std::string m_value;
-};
-#endif // CONFIG_BT_ENABLED
-#endif /* COMPONENTS_CPP_UTILS_BLEVALUE_H_ */
diff --git a/components/cpp_utils/BLEXML/Characteristics/code/.gitignore b/components/cpp_utils/BLEXML/Characteristics/code/.gitignore
deleted file mode 100644
index 982fcb1..0000000
--- a/components/cpp_utils/BLEXML/Characteristics/code/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.xml
-*.json
-
diff --git a/components/cpp_utils/BLEXML/Characteristics/code/characteristics.txt b/components/cpp_utils/BLEXML/Characteristics/code/characteristics.txt
deleted file mode 100644
index 8917deb..0000000
--- a/components/cpp_utils/BLEXML/Characteristics/code/characteristics.txt
+++ /dev/null
@@ -1,196 +0,0 @@
-org.bluetooth.characteristic.aerobic_heart_rate_lower_limit
-org.bluetooth.characteristic.aerobic_heart_rate_upper_limit
-org.bluetooth.characteristic.aerobic_threshold
-org.bluetooth.characteristic.age
-org.bluetooth.characteristic.aggregate
-org.bluetooth.characteristic.alert_category_id
-org.bluetooth.characteristic.alert_category_id_bit_mask
-org.bluetooth.characteristic.alert_level
-org.bluetooth.characteristic.alert_notification_control_point
-org.bluetooth.characteristic.alert_status
-org.bluetooth.characteristic.altitude
-org.bluetooth.characteristic.anaerobic_heart_rate_lower_limit
-org.bluetooth.characteristic.anaerobic_heart_rate_upper_limit
-org.bluetooth.characteristic.anaerobic_threshold
-org.bluetooth.characteristic.analog
-org.bluetooth.characteristic.apparent_wind_direction
-org.bluetooth.characteristic.apparent_wind_speed
-org.bluetooth.characteristic.gap.appearance
-org.bluetooth.characteristic.barometric_pressure_trend
-org.bluetooth.characteristic.battery_level
-org.bluetooth.characteristic.blood_pressure_feature
-org.bluetooth.characteristic.blood_pressure_measurement
-org.bluetooth.characteristic.body_composition_feature
-org.bluetooth.characteristic.body_composition_measurement
-org.bluetooth.characteristic.body_sensor_location
-org.bluetooth.characteristic.bond_management_control_point
-org.bluetooth.characteristic.bond_management_feature
-org.bluetooth.characteristic.boot_keyboard_input_report
-org.bluetooth.characteristic.boot_keyboard_output_report
-org.bluetooth.characteristic.boot_mouse_input_report
-org.bluetooth.characteristic.gap.central_address_resolution_support
-org.bluetooth.characteristic.cgm_feature
-org.bluetooth.characteristic.cgm_measurement
-org.bluetooth.characteristic.cgm_session_run_time
-org.bluetooth.characteristic.cgm_session_start_time
-org.bluetooth.characteristic.cgm_specific_ops_control_point
-org.bluetooth.characteristic.cgm_status
-org.bluetooth.characteristic.cross_trainer_data
-org.bluetooth.characteristic.csc_feature
-org.bluetooth.characteristic.csc_measurement
-org.bluetooth.characteristic.current_time
-org.bluetooth.characteristic.cycling_power_control_point
-org.bluetooth.characteristic.cycling_power_feature
-org.bluetooth.characteristic.cycling_power_measurement
-org.bluetooth.characteristic.cycling_power_vector
-org.bluetooth.characteristic.database_change_increment
-org.bluetooth.characteristic.date_of_birth
-org.bluetooth.characteristic.date_of_threshold_assessment
-org.bluetooth.characteristic.date_time
-org.bluetooth.characteristic.day_date_time
-org.bluetooth.characteristic.day_of_week
-org.bluetooth.characteristic.descriptor_value_changed
-org.bluetooth.characteristic.gap.device_name
-org.bluetooth.characteristic.dew_point
-org.bluetooth.characteristic.digital
-org.bluetooth.characteristic.dst_offset
-org.bluetooth.characteristic.elevation
-org.bluetooth.characteristic.email_address
-org.bluetooth.characteristic.exact_time_256
-org.bluetooth.characteristic.fat_burn_heart_rate_lower_limit
-org.bluetooth.characteristic.fat_burn_heart_rate_upper_limit
-org.bluetooth.characteristic.firmware_revision_string
-org.bluetooth.characteristic.first_name
-org.bluetooth.characteristic.fitness_machine_control_point
-org.bluetooth.characteristic.fitness_machine_feature
-org.bluetooth.characteristic.fitness_machine_status
-org.bluetooth.characteristic.five_zone_heart_rate_limits
-org.bluetooth.characteristic.floor_number
-org.bluetooth.characteristic.gender
-org.bluetooth.characteristic.glucose_feature
-org.bluetooth.characteristic.glucose_measurement
-org.bluetooth.characteristic.glucose_measurement_context
-org.bluetooth.characteristic.gust_factor
-org.bluetooth.characteristic.hardware_revision_string
-org.bluetooth.characteristic.heart_rate_control_point
-org.bluetooth.characteristic.heart_rate_max
-org.bluetooth.characteristic.heart_rate_measurement
-org.bluetooth.characteristic.heat_index
-org.bluetooth.characteristic.height
-org.bluetooth.characteristic.hid_control_point
-org.bluetooth.characteristic.hid_information
-org.bluetooth.characteristic.hip_circumference	
-org.bluetooth.characteristic.http_control_point
-org.bluetooth.characteristic.http_entity_body
-org.bluetooth.characteristic.http_headers
-org.bluetooth.characteristic.http_status_code
-org.bluetooth.characteristic.https_security
-org.bluetooth.characteristic.humidity
-org.bluetooth.characteristic.ieee_11073-20601_regulatory_certification_data_list
-org.bluetooth.characteristic.indoor_bike_data
-org.bluetooth.characteristic.indoor_positioning_configuration
-org.bluetooth.characteristic.intermediate_cuff_pressure
-org.bluetooth.characteristic.intermediate_temperature
-org.bluetooth.characteristic.irradiance
-org.bluetooth.characteristic.language
-org.bluetooth.characteristic.last_name
-org.bluetooth.characteristic.latitude
-org.bluetooth.characteristic.ln_control_point
-org.bluetooth.characteristic.ln_feature
-org.bluetooth.characteristic.local_east_coordinate
-org.bluetooth.characteristic.local_north_coordinate
-org.bluetooth.characteristic.local_time_information
-org.bluetooth.characteristic.location_and_speed
-org.bluetooth.characteristic.location_name
-org.bluetooth.characteristic.longitude
-org.bluetooth.characteristic.magnetic_declination
-org.bluetooth.characteristic.magnetic_flux_density_2D
-org.bluetooth.characteristic.magnetic_flux_density_3D
-org.bluetooth.characteristic.manufacturer_name_string
-org.bluetooth.characteristic.maximum_recommended_heart_rate
-org.bluetooth.characteristic.measurement_interval
-org.bluetooth.characteristic.model_number_string
-org.bluetooth.characteristic.navigation
-org.bluetooth.characteristic.new_alert
-org.bluetooth.characteristic.object_action_control_point
-org.bluetooth.characteristic.object_changed
-org.bluetooth.characteristic.object_first_created
-org.bluetooth.characteristic.object_id
-org.bluetooth.characteristic.object_last_modified
-org.bluetooth.characteristic.object_list_control_point
-org.bluetooth.characteristic.object_list_filter
-org.bluetooth.characteristic.object_name
-org.bluetooth.characteristic.object_properties
-org.bluetooth.characteristic.object_size
-org.bluetooth.characteristic.object_type
-org.bluetooth.characteristic.ots_feature
-org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters
-org.bluetooth.characteristic.gap.peripheral_privacy_flag
-org.bluetooth.characteristic.plx_continuous_measurement
-org.bluetooth.characteristic.plx_features
-org.bluetooth.characteristic.plx_spot_check_measurement
-org.bluetooth.characteristic.pnp_id
-org.bluetooth.characteristic.pollen_concentration
-org.bluetooth.characteristic.position_quality
-org.bluetooth.characteristic.pressure
-org.bluetooth.characteristic.protocol_mode
-org.bluetooth.characteristic.rainfall
-org.bluetooth.characteristic.gap.reconnection_address
-org.bluetooth.characteristic.record_access_control_point
-org.bluetooth.characteristic.reference_time_information
-org.bluetooth.characteristic.report
-org.bluetooth.characteristic.report_map
-org.bluetooth.characteristic.resolvable_private_address_only
-org.bluetooth.characteristic.resting_heart_rate
-org.bluetooth.characteristic.ringer_control_point
-org.bluetooth.characteristic.ringer_setting
-org.bluetooth.characteristic.rower_data
-org.bluetooth.characteristic.rsc_feature
-org.bluetooth.characteristic.rsc_measurement
-org.bluetooth.characteristic.sc_control_point
-org.bluetooth.characteristic.scan_interval_window
-org.bluetooth.characteristic.scan_refresh
-org.bluetooth.characteristic.sensor_location
-org.bluetooth.characteristic.serial_number_string
-org.bluetooth.characteristic.gatt.service_changed
-org.bluetooth.characteristic.software_revision_string
-org.bluetooth.characteristic.sport_type_for_aerobic_and_anaerobic_thresholds
-org.bluetooth.characteristic.stair_climber_data
-org.bluetooth.characteristic.step_climber_data
-org.bluetooth.characteristic.supported_heart_rate_range
-org.bluetooth.characteristic.supported_inclination_range
-org.bluetooth.characteristic.supported_new_alert_category
-org.bluetooth.characteristic.supported_power_range
-org.bluetooth.characteristic.supported_resistance_level_range
-org.bluetooth.characteristic.supported_speed_range
-org.bluetooth.characteristic.supported_unread_alert_category
-org.bluetooth.characteristic.system_id
-org.bluetooth.characteristic.tds_control_point
-org.bluetooth.characteristic.temperature
-org.bluetooth.characteristic.temperature_measurement
-org.bluetooth.characteristic.temperature_type
-org.bluetooth.characteristic.three_zone_heart_rate_limits
-org.bluetooth.characteristic.time_accuracy
-org.bluetooth.characteristic.time_source
-org.bluetooth.characteristic.time_update_control_point
-org.bluetooth.characteristic.time_update_state
-org.bluetooth.characteristic.time_with_dst
-org.bluetooth.characteristic.time_zone
-org.bluetooth.characteristic.training_status
-org.bluetooth.characteristic.treadmill_data
-org.bluetooth.characteristic.true_wind_direction
-org.bluetooth.characteristic.true_wind_speed
-org.bluetooth.characteristic.two_zone_heart_rate_limit
-org.bluetooth.characteristic.tx_power_level
-org.bluetooth.characteristic.uncertainty
-org.bluetooth.characteristic.unread_alert_status
-org.bluetooth.characteristic.uri
-org.bluetooth.characteristic.user_control_point
-org.bluetooth.characteristic.user_index
-org.bluetooth.characteristic.uv_index
-org.bluetooth.characteristic.vo2_max
-org.bluetooth.characteristic.waist_circumference
-org.bluetooth.characteristic.weight
-org.bluetooth.characteristic.weight_measurement
-org.bluetooth.characteristic.weight_scale_feature
-org.bluetooth.characteristic.wind_chill
\ No newline at end of file
diff --git a/components/cpp_utils/BLEXML/Characteristics/code/run.sh b/components/cpp_utils/BLEXML/Characteristics/code/run.sh
deleted file mode 100755
index 77f193f..0000000
--- a/components/cpp_utils/BLEXML/Characteristics/code/run.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash 
-BASE_URL="https://www.bluetooth.com/api/gatt/XmlFile?xmlFileName="
-RESULT=characteristics.json
-COUNT=0
-echo -e "[\n" > ${RESULT}
-for fileName in `cat characteristics.txt`
-do
-	echo "Process file ${fileName}"
-	wget --output-document ${fileName}.xml --quiet "${BASE_URL}${fileName}.xml"
-	if [ ${COUNT} -gt 0 ]
-	then
-	   echo -e ",\n" >> ${RESULT}
-	fi
-	#xml2json < "${fileName}.xml" >> ${RESULT}
-	xml2json "${fileName}.xml" "${fileName}.json"
-	cat "${fileName}.json" >> ${RESULT}
-	COUNT=$(expr ${COUNT} + 1)
-done
-echo -e "\n]\n" >> ${RESULT}
-echo "done"
\ No newline at end of file
diff --git a/components/cpp_utils/BLEXML/README.md b/components/cpp_utils/BLEXML/README.md
deleted file mode 100644
index 889721d..0000000
--- a/components/cpp_utils/BLEXML/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# XML to JSON
-The BLE authority makes available description of Services and Characteristics in XML documents.  Our goal is to work with these
-in JavaScript. These tools download each of the XML documents and convert them to JSON equivalents.  To perform that task we
-use the NPM package called [xml2json-cli](https://www.npmjs.com/package/xml2json-cli).
\ No newline at end of file
diff --git a/components/cpp_utils/BLEXML/Services/code/.gitignore b/components/cpp_utils/BLEXML/Services/code/.gitignore
deleted file mode 100644
index 982fcb1..0000000
--- a/components/cpp_utils/BLEXML/Services/code/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.xml
-*.json
-
diff --git a/components/cpp_utils/BLEXML/Services/code/run.sh b/components/cpp_utils/BLEXML/Services/code/run.sh
deleted file mode 100755
index bfa084d..0000000
--- a/components/cpp_utils/BLEXML/Services/code/run.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash 
-BASE_URL="https://www.bluetooth.com/api/gatt/XmlFile?xmlFileName="
-RESULT=services.json
-COUNT=0
-echo -e "[\n" > ${RESULT}
-for fileName in `cat services.txt`
-do
-	echo "Process file ${fileName}"
-	wget --output-document ${fileName}.xml --quiet "${BASE_URL}${fileName}.xml"
-	if [ ${COUNT} -gt 0 ]
-	then
-	   echo -e ",\n" >> ${RESULT}
-	fi
-	#xml2json < "${fileName}.xml" >> ${RESULT}
-	xml2json "${fileName}.xml" "${fileName}.json"
-	cat "${fileName}.json" >> ${RESULT}
-	COUNT=$(expr ${COUNT} + 1)
-done
-echo -e "\n]\n" >> ${RESULT}
-echo "done"
\ No newline at end of file
diff --git a/components/cpp_utils/BLEXML/Services/code/services.txt b/components/cpp_utils/BLEXML/Services/code/services.txt
deleted file mode 100644
index c184dc9..0000000
--- a/components/cpp_utils/BLEXML/Services/code/services.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-org.bluetooth.service.alert_notification
-org.bluetooth.service.automation_io
-org.bluetooth.service.battery_service
-org.bluetooth.service.blood_pressure
-org.bluetooth.service.body_composition
-org.bluetooth.service.bond_management
-org.bluetooth.service.continuous_glucose_monitoring
-org.bluetooth.service.current_time
-org.bluetooth.service.cycling_power
-org.bluetooth.service.cycling_speed_and_cadence
-org.bluetooth.service.device_information
-org.bluetooth.service.environmental_sensing
-org.bluetooth.service.fitness_machine
-org.bluetooth.service.generic_access
-org.bluetooth.service.generic_attribute
-org.bluetooth.service.glucose
-org.bluetooth.service.health_thermometer
-org.bluetooth.service.heart_rate
-org.bluetooth.service.http_proxy
-org.bluetooth.service.human_interface_device
-org.bluetooth.service.immediate_alert
-org.bluetooth.service.indoor_positioning
-org.bluetooth.service.internet_protocol_support
-org.bluetooth.service.link_loss
-org.bluetooth.service.location_and_navigation
-org.bluetooth.service.next_dst_change
-org.bluetooth.service.object_transfer
-org.bluetooth.service.phone_alert_status
-org.bluetooth.service.pulse_oximeter
-org.bluetooth.service.reference_time_update
-org.bluetooth.service.running_speed_and_cadence
-org.bluetooth.service.scan_parameters
-org.bluetooth.service.transport_discovery
-org.bluetooth.service.tx_power
-org.bluetooth.service.user_data
-org.bluetooth.service.weight_scale
\ No newline at end of file
diff --git a/components/cpp_utils/CPPNVS.cpp b/components/cpp_utils/CPPNVS.cpp
deleted file mode 100644
index 734cc17..0000000
--- a/components/cpp_utils/CPPNVS.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * NVS.cpp
- *
- *  Created on: Mar 27, 2017
- *      Author: kolban
- */
-
-#include "CPPNVS.h"
-
-#include <stdlib.h>
-
-/**
- * @brief Constructor.
- *
- * @param [in] name The namespace to open for access.
- * @param [in] openMode
- */
-NVS::NVS(std::string name, nvs_open_mode openMode) {
-	m_name = name;
-	nvs_open(name.c_str(), openMode, &m_handle);
-} // NVS
-
-
-NVS::~NVS() {
-	nvs_close(m_handle);
-} // ~NVS
-
-
-/**
- * @brief Commit any work performed in the namespace.
- */
-void NVS::commit() {
-	nvs_commit(m_handle);
-} // commit
-
-
-/**
- * @brief Erase ALL the keys in the namespace.
- */
-void NVS::erase() {
-	nvs_erase_all(m_handle);
-} // erase
-
-
-/**
- * @brief Erase a specific key in the namespace.
- *
- * @param [in] key The key to erase from the namespace.
- */
-void NVS::erase(std::string key) {
-	nvs_erase_key(m_handle, key.c_str());
-} // erase
-
-
-/**
- * @brief Retrieve a string value by key.
- *
- * @param [in] key The key to read from the namespace.
- * @param [out] result The string read from the %NVS storage.
- */
-void NVS::get(std::string key, std::string* result) {
-	size_t length;
-	nvs_get_str(m_handle, key.c_str(), NULL, &length);
-	char *data = (char *)malloc(length);
-	nvs_get_str(m_handle, key.c_str(), data, &length);
-	*result = std::string(data);
-	free(data);
-} // get
-
-
-/**
- * @brief Set the string value by key.
- *
- * @param [in] key The key to set from the namespace.
- * @param [in] data The value to set for the key.
- */
-void NVS::set(std::string key, std::string data) {
-	nvs_set_str(m_handle, key.c_str(), data.c_str());
-} // set
diff --git a/components/cpp_utils/CPPNVS.h b/components/cpp_utils/CPPNVS.h
deleted file mode 100644
index 6802ff9..0000000
--- a/components/cpp_utils/CPPNVS.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * NVS.h
- *
- *  Created on: Mar 27, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_CPPNVS_H_
-#define COMPONENTS_CPP_UTILS_CPPNVS_H_
-#include <nvs.h>
-#include <string>
-
-/**
- * @brief Provide Non Volatile Storage access.
- */
-class NVS {
-public:
-	NVS(std::string name, nvs_open_mode openMode = NVS_READWRITE);
-	virtual ~NVS();
-	void commit();
-
-	void erase();
-	void erase(std::string key);
-	void get(std::string key, std::string *result);
-	void set(std::string key, std::string data);
-private:
-	std::string m_name;
-	nvs_handle m_handle;
-};
-
-#endif /* COMPONENTS_CPP_UTILS_CPPNVS_H_ */
diff --git a/components/cpp_utils/DesignNotes/README.md b/components/cpp_utils/DesignNotes/README.md
deleted file mode 100644
index b28c907..0000000
--- a/components/cpp_utils/DesignNotes/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Design Notes
-Here is where we keep some of our design documents.
\ No newline at end of file
diff --git a/components/cpp_utils/DesignNotes/WebSockets.md b/components/cpp_utils/DesignNotes/WebSockets.md
deleted file mode 100644
index 0a5ef89..0000000
--- a/components/cpp_utils/DesignNotes/WebSockets.md
+++ /dev/null
@@ -1,64 +0,0 @@
-#WebSockets
-The WebSocket implementation attempts to implement [RFC 6455 - The WebSocket Protocol](https://tools.ietf.org/html/rfc6455).
-
-
-
-When an HTTP request arrives, we examine the request to see if it is a request to open a new WebSocket connection.  If it is, we respond with the acknowledgement that we are prepared to be a WebSocket partner.  Once done, the socket that was once used to handle the REST request now becomes the one used to handle bi-directional communications between the ESP32 (original WebSocket server) and the client (browser/Node.js).
-
-Since we don't know when a client may transmit, it could actually transmit at any time.  As such we want to register an asynchronous callback handler that will be invoked when the client sends in some WebSocket data.  To handle this, we then need to `select()` on the WebSocket socket and, when it wakes, invoke the callback handler.  We must **not** issue a new `select()` until the WebSocket message has been consumed.
-
-It is anticipated that a WebSocket message could be large.  The first use case I have come across for using WebSockets is for file transfer and since we have 4MBytes of flash and only 512K of RAM (of which likely only 100K or so may be available) we are likely going to run out of RAM if we wish to write a large file to flash file systems.  What this means is that we likely can't buffer a large WebSocket data message in RAM.
-
-For example, imagine a WebSocket client wants to send a file of 1MByte to the ESP32.  That is more data than we have RAM so we can't hold that message in its entirety in RAM.  What we need to do is "read some" and then "write some" and repeat until all has been consumed.  This sounds like the concept of a stream.  We would have an input stream (data coming into the ESP32) associated with the WebSocket and an output stream (data going out from the ESP32) being written to the file.  We could thus read a small section of the input, write it to the output and continue while we have new data in the input.
-
-This sounds workable ... so let us now think about how we might go about creating an input stream for a WebSocket message.  Each WebSocket message starts with a WebSocket frame which contains, amongst other things, the length of the payload data.  This means that we know up front how much of the remaining data is payload.  This becomes essential as we can't rely on an "end of file" marker in the input stream to indicate the end of the WebSocket payload.  The reason for this is that the WebSocket is a TCP stream that will be used to carry multiple sequential messages.
-
-Let us now invent a new class.  Let us call it a SocketInputRecordStreambuf.
-It will have a constructor of the form:
-
-```
-SocketInputRecordStreambuf(Socket &socket, size_t dataLength, size_t bufferSize=512)
-```
-
-The `socket` is the TCP/IP socket that we are going to read data from.  The `dataLength` is the size of the data we wish to read.  The class will extend `std::streambuf`.  It will internally maintain a data buffer of size `bufferSize`.  Initially, the buffer will be empty.  When a read is performed on the stream, a call to `underflow()` will be made (this is a `std::streambuf` virtual function).
-
-Our rules for this class include:
-
-* We must **not** read more the `dataLength` bytes from the socket.
-* We must **indicate** and `EOF` once we have had `dataLength` bytes consumed by a stream reader.
-* The class must implement a `discard()` method that will discard further bytes from the socket such that the total number of bytes read from the socket will equal `dataLength`.
-* Deleting an instance of the class must invoke `discard()`.
-
-## File transfer
-WebSockets make a great file transfer technology.  While this is more an application utilization of the technology than the design of the framework, we'll capture it here.  Let us first set the scene.  We have a client application that wishes to transmit a file.  We will assume that the file is composed of three logical components:
-
-* The file name
-* The file length
-* The content of the file
-
-It would be wrong to expect the client to send the file as one continuous unit in one WebSocket message.  The reason for this is that the client would have to have loaded the complete file into its memory buffers in order to send it.  As such, we should assume that the client will send the files as one or more "parts" where each part represents a piece of the file.
-
-We thus invent the following protocol:
-
-For the first message we have:
-
-```
-+-----------------------+-----------+----+--------------------+-----------+
-| transferId (32bit/LE) | file name | \0 | length (32bits/LE) | Data .... |
-+-----------------------+-----------+----+--------------------+-----------+
-```
-
-For subsequent messages we have:
-
-```
-+-----------------------+-----------+
-| transferId (32bit/LE) | Data .... |
-+-----------------------+-----------+
-```
-Let us look at these.
-
-* `transferId` - An Id that is randomly generated by the client.  This is used to associate multiple messages for the same file together.
-* `file name` - The name of the file that the client wishes to send.  Can include paths.  This will be used to determine where on the file system the file will be written.
-* `length` - The size of the file in bytes.  Knowing the size will allow us to know when the whole file has been received.
-
-We will create an encapsulation class called `WebSocketFileTransfer`.
\ No newline at end of file
diff --git a/components/cpp_utils/Doxyfile b/components/cpp_utils/Doxyfile
deleted file mode 100644
index 5ac1509..0000000
--- a/components/cpp_utils/Doxyfile
+++ /dev/null
@@ -1,2496 +0,0 @@
-# Doxyfile 1.8.13
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project.
-#
-# All text after a double hash (##) is considered a comment and is placed in
-# front of the TAG it is preceding.
-#
-# All text after a single hash (#) is considered a comment and will be ignored.
-# The format is:
-# TAG = value [value, ...]
-# For lists, items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (\" \").
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
-# The default value is: UTF-8.
-
-DOXYFILE_ENCODING      = UTF-8
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
-# double-quotes, unless you are using Doxywizard) that should identify the
-# project for which the documentation is generated. This name is used in the
-# title of most generated pages and in a few other places.
-# The default value is: My Project.
-
-PROJECT_NAME           = "My Project"
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
-# could be handy for archiving the generated documentation or if some version
-# control system is used.
-
-PROJECT_NUMBER         = 
-
-# Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer a
-# quick idea about the purpose of the project. Keep the description short.
-
-PROJECT_BRIEF          = 
-
-# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
-# in the documentation. The maximum height of the logo should not exceed 55
-# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
-# the logo to the output directory.
-
-PROJECT_LOGO           = 
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
-# into which the generated documentation will be written. If a relative path is
-# entered, it will be relative to the location where doxygen was started. If
-# left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       = /home/kolban/esp32/esptest/apps/workspace/esp32-snippets/cpp_utils/docs
-
-# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
-# option can be useful when feeding doxygen a huge amount of source files, where
-# putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
-# The default value is: NO.
-
-CREATE_SUBDIRS         = NO
-
-# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
-# characters to appear in the names of generated files. If set to NO, non-ASCII
-# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
-# U+3044.
-# The default value is: NO.
-
-ALLOW_UNICODE_NAMES    = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
-# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
-# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
-# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
-# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
-# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
-# Ukrainian and Vietnamese.
-# The default value is: English.
-
-OUTPUT_LANGUAGE        = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
-# descriptions after the members that are listed in the file and class
-# documentation (similar to Javadoc). Set to NO to disable this.
-# The default value is: YES.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
-# description of a member or function before the detailed description
-#
-# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-# The default value is: YES.
-
-REPEAT_BRIEF           = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator that is
-# used to form the text in various listings. Each string in this list, if found
-# as the leading text of the brief description, will be stripped from the text
-# and the result, after processing the whole list, is used as the annotated
-# text. Otherwise, the brief description is used as-is. If left blank, the
-# following values are used ($name is automatically replaced with the name of
-# the entity):The $name class, The $name widget, The $name file, is, provides,
-# specifies, contains, represents, a, an and the.
-
-ABBREVIATE_BRIEF       = "The $name class" \
-                         "The $name widget" \
-                         "The $name file" \
-                         is \
-                         provides \
-                         specifies \
-                         contains \
-                         represents \
-                         a \
-                         an \
-                         the
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# doxygen will generate a detailed section even if there is only a brief
-# description.
-# The default value is: NO.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-# The default value is: NO.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
-# before files name in the file list and in the header files. If set to NO the
-# shortest path that makes the file name unique will be used
-# The default value is: YES.
-
-FULL_PATH_NAMES        = YES
-
-# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
-# Stripping is only done if one of the specified strings matches the left-hand
-# part of the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the path to
-# strip.
-#
-# Note that you can specify absolute paths here, but also relative paths, which
-# will be relative from the directory where doxygen is started.
-# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-
-STRIP_FROM_PATH        = 
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
-# path mentioned in the documentation of a class, which tells the reader which
-# header file to include in order to use a class. If left blank only the name of
-# the header file containing the class definition is used. Otherwise one should
-# specify the list of include paths that are normally passed to the compiler
-# using the -I flag.
-
-STRIP_FROM_INC_PATH    = 
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
-# less readable) file names. This can be useful is your file systems doesn't
-# support long names like on DOS, Mac, or CD-ROM.
-# The default value is: NO.
-
-SHORT_NAMES            = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
-# first line (until the first dot) of a Javadoc-style comment as the brief
-# description. If set to NO, the Javadoc-style will behave just like regular Qt-
-# style comments (thus requiring an explicit @brief command for a brief
-# description.)
-# The default value is: NO.
-
-JAVADOC_AUTOBRIEF      = NO
-
-# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
-# line (until the first dot) of a Qt-style comment as the brief description. If
-# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
-# requiring an explicit \brief command for a brief description.)
-# The default value is: NO.
-
-QT_AUTOBRIEF           = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
-# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
-# a brief description. This used to be the default behavior. The new default is
-# to treat a multi-line C++ comment block as a detailed description. Set this
-# tag to YES if you prefer the old behavior instead.
-#
-# Note that setting this tag to YES also means that rational rose comments are
-# not recognized any more.
-# The default value is: NO.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
-# documentation from any documented member that it re-implements.
-# The default value is: YES.
-
-INHERIT_DOCS           = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
-# page for each member. If set to NO, the documentation of a member will be part
-# of the file/class/namespace that contains it.
-# The default value is: NO.
-
-SEPARATE_MEMBER_PAGES  = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
-# uses this value to replace tabs by spaces in code fragments.
-# Minimum value: 1, maximum value: 16, default value: 4.
-
-TAB_SIZE               = 4
-
-# This tag can be used to specify a number of aliases that act as commands in
-# the documentation. An alias has the form:
-# name=value
-# For example adding
-# "sideeffect=@par Side Effects:\n"
-# will allow you to put the command \sideeffect (or @sideeffect) in the
-# documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
-
-ALIASES                = 
-
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding "class=itcl::class"
-# will allow you to use the command class in the itcl::class meaning.
-
-TCL_SUBST              = 
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
-# only. Doxygen will then generate output that is more tailored for C. For
-# instance, some of the names that are used will be different. The list of all
-# members will be omitted, etc.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_FOR_C  = NO
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
-# Python sources only. Doxygen will then generate output that is more tailored
-# for that language. For instance, namespaces will be presented as packages,
-# qualified scopes will look different, etc.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources. Doxygen will then generate output that is tailored for Fortran.
-# The default value is: NO.
-
-OPTIMIZE_FOR_FORTRAN   = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for VHDL.
-# The default value is: NO.
-
-OPTIMIZE_OUTPUT_VHDL   = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given
-# extension. Doxygen has a built-in mapping, but you can override or extend it
-# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
-#
-# Note: For files without extension you can use no_extension as a placeholder.
-#
-# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
-
-EXTENSION_MAPPING      = 
-
-# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
-# according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you can
-# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
-# case of backward compatibilities issues.
-# The default value is: YES.
-
-MARKDOWN_SUPPORT       = YES
-
-# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
-# to that level are automatically included in the table of contents, even if
-# they do not have an id attribute.
-# Note: This feature currently applies only to Markdown headings.
-# Minimum value: 0, maximum value: 99, default value: 0.
-# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
-
-TOC_INCLUDE_HEADINGS   = 0
-
-# When enabled doxygen tries to link words that correspond to documented
-# classes, or namespaces to their corresponding documentation. Such a link can
-# be prevented in individual cases by putting a % sign in front of the word or
-# globally by setting AUTOLINK_SUPPORT to NO.
-# The default value is: YES.
-
-AUTOLINK_SUPPORT       = YES
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should set this
-# tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string);
-# versus func(std::string) {}). This also make the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-# The default value is: NO.
-
-BUILTIN_STL_SUPPORT    = NO
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-# The default value is: NO.
-
-CPP_CLI_SUPPORT        = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
-# will parse them like normal C++ but will assume all classes use public instead
-# of private inheritance when no explicit protection keyword is present.
-# The default value is: NO.
-
-SIP_SUPPORT            = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate
-# getter and setter methods for a property. Setting this option to YES will make
-# doxygen to replace the get and set methods by a property in the documentation.
-# This will only work if the methods are indeed getting or setting a simple
-# type. If this is not the case, or you want to show the methods anyway, you
-# should set this option to NO.
-# The default value is: YES.
-
-IDL_PROPERTY_SUPPORT   = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-# The default value is: NO.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# If one adds a struct or class to a group and this option is enabled, then also
-# any nested class or struct is added to the same group. By default this option
-# is disabled and one has to add nested compounds explicitly via \ingroup.
-# The default value is: NO.
-
-GROUP_NESTED_COMPOUNDS = NO
-
-# Set the SUBGROUPING tag to YES to allow class member groups of the same type
-# (for instance a group of public functions) to be put as a subgroup of that
-# type (e.g. under the Public Functions section). Set it to NO to prevent
-# subgrouping. Alternatively, this can be done per class using the
-# \nosubgrouping command.
-# The default value is: YES.
-
-SUBGROUPING            = YES
-
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
-# are shown inside the group in which they are included (e.g. using \ingroup)
-# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
-# and RTF).
-#
-# Note that this feature does not work in combination with
-# SEPARATE_MEMBER_PAGES.
-# The default value is: NO.
-
-INLINE_GROUPED_CLASSES = NO
-
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
-# with only public data fields or simple typedef fields will be shown inline in
-# the documentation of the scope in which they are defined (i.e. file,
-# namespace, or group documentation), provided this scope is documented. If set
-# to NO, structs, classes, and unions are shown on a separate page (for HTML and
-# Man pages) or section (for LaTeX and RTF).
-# The default value is: NO.
-
-INLINE_SIMPLE_STRUCTS  = NO
-
-# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
-# enum is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically be
-# useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-# The default value is: NO.
-
-TYPEDEF_HIDES_STRUCT   = NO
-
-# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
-# cache is used to resolve symbols given their name and scope. Since this can be
-# an expensive process and often the same symbol appears multiple times in the
-# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
-# doxygen will become slower. If the cache is too large, memory is wasted. The
-# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
-# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
-# symbols. At the end of a run doxygen will report the cache usage and suggest
-# the optimal cache size from a speed point of view.
-# Minimum value: 0, maximum value: 9, default value: 0.
-
-LOOKUP_CACHE_SIZE      = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
-# documentation are documented, even if no documentation was available. Private
-# class members and static file members will be hidden unless the
-# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
-# Note: This will also disable the warnings about undocumented members that are
-# normally produced when WARNINGS is set to YES.
-# The default value is: NO.
-
-EXTRACT_ALL            = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
-# be included in the documentation.
-# The default value is: NO.
-
-EXTRACT_PRIVATE        = NO
-
-# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
-# scope will be included in the documentation.
-# The default value is: NO.
-
-EXTRACT_PACKAGE        = NO
-
-# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
-# included in the documentation.
-# The default value is: NO.
-
-EXTRACT_STATIC         = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
-# locally in source files will be included in the documentation. If set to NO,
-# only classes defined in header files are included. Does not have any effect
-# for Java sources.
-# The default value is: YES.
-
-EXTRACT_LOCAL_CLASSES  = YES
-
-# This flag is only useful for Objective-C code. If set to YES, local methods,
-# which are defined in the implementation section but not in the interface are
-# included in the documentation. If set to NO, only methods in the interface are
-# included.
-# The default value is: NO.
-
-EXTRACT_LOCAL_METHODS  = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base name of
-# the file that contains the anonymous namespace. By default anonymous namespace
-# are hidden.
-# The default value is: NO.
-
-EXTRACT_ANON_NSPACES   = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
-# undocumented members inside documented classes or files. If set to NO these
-# members will be included in the various overviews, but no documentation
-# section is generated. This option has no effect if EXTRACT_ALL is enabled.
-# The default value is: NO.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy. If set
-# to NO, these classes will be included in the various overviews. This option
-# has no effect if EXTRACT_ALL is enabled.
-# The default value is: NO.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO, these declarations will be
-# included in the documentation.
-# The default value is: NO.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
-# documentation blocks found inside the body of a function. If set to NO, these
-# blocks will be appended to the function's detailed documentation block.
-# The default value is: NO.
-
-HIDE_IN_BODY_DOCS      = NO
-
-# The INTERNAL_DOCS tag determines if documentation that is typed after a
-# \internal command is included. If the tag is set to NO then the documentation
-# will be excluded. Set it to YES to include the internal documentation.
-# The default value is: NO.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES, upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
-
-CASE_SENSE_NAMES       = NO
-
-# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
-# their full class and namespace scopes in the documentation. If set to YES, the
-# scope will be hidden.
-# The default value is: NO.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
-# append additional text to a page's title, such as Class Reference. If set to
-# YES the compound reference will be hidden.
-# The default value is: NO.
-
-HIDE_COMPOUND_REFERENCE= NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
-# the files that are included by a file in the documentation of that file.
-# The default value is: YES.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
-# grouped member an include statement to the documentation, telling the reader
-# which file to include in order to use the member.
-# The default value is: NO.
-
-SHOW_GROUPED_MEMB_INC  = NO
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
-# files with double quotes in the documentation rather than with sharp brackets.
-# The default value is: NO.
-
-FORCE_LOCAL_INCLUDES   = NO
-
-# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
-# documentation for inline members.
-# The default value is: YES.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
-# (detailed) documentation of file and class members alphabetically by member
-# name. If set to NO, the members will appear in declaration order.
-# The default value is: YES.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
-# descriptions of file, namespace and class members alphabetically by member
-# name. If set to NO, the members will appear in declaration order. Note that
-# this will also influence the order of the classes in the class list.
-# The default value is: NO.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
-# (brief and detailed) documentation of class members so that constructors and
-# destructors are listed first. If set to NO the constructors will appear in the
-# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
-# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
-# member documentation.
-# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
-# detailed member documentation.
-# The default value is: NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
-# of group names into alphabetical order. If set to NO the group names will
-# appear in their defined order.
-# The default value is: NO.
-
-SORT_GROUP_NAMES       = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
-# fully-qualified names, including namespaces. If set to NO, the class list will
-# be sorted only by class name, not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the alphabetical
-# list.
-# The default value is: NO.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
-# type resolution of all parameters of a function it will reject a match between
-# the prototype and the implementation of a member function even if there is
-# only one candidate or it is obvious which candidate to choose by doing a
-# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
-# accept a match between prototype and implementation in such cases.
-# The default value is: NO.
-
-STRICT_PROTO_MATCHING  = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
-# list. This list is created by putting \todo commands in the documentation.
-# The default value is: YES.
-
-GENERATE_TODOLIST      = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
-# list. This list is created by putting \test commands in the documentation.
-# The default value is: YES.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
-# list. This list is created by putting \bug commands in the documentation.
-# The default value is: YES.
-
-GENERATE_BUGLIST       = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
-# the deprecated list. This list is created by putting \deprecated commands in
-# the documentation.
-# The default value is: YES.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional documentation
-# sections, marked by \if <section_label> ... \endif and \cond <section_label>
-# ... \endcond blocks.
-
-ENABLED_SECTIONS       = 
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
-# initial value of a variable or macro / define can have for it to appear in the
-# documentation. If the initializer consists of more lines than specified here
-# it will be hidden. Use a value of 0 to hide initializers completely. The
-# appearance of the value of individual variables and macros / defines can be
-# controlled using \showinitializer or \hideinitializer command in the
-# documentation regardless of this setting.
-# Minimum value: 0, maximum value: 10000, default value: 30.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
-# the bottom of the documentation of classes and structs. If set to YES, the
-# list will mention the files that were used to generate the documentation.
-# The default value is: YES.
-
-SHOW_USED_FILES        = YES
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
-# will remove the Files entry from the Quick Index and from the Folder Tree View
-# (if specified).
-# The default value is: YES.
-
-SHOW_FILES             = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
-# page. This will remove the Namespaces entry from the Quick Index and from the
-# Folder Tree View (if specified).
-# The default value is: YES.
-
-SHOW_NAMESPACES        = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command command input-file, where command is the value of the
-# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
-# by doxygen. Whatever the program writes to standard output is used as the file
-# version. For an example see the documentation.
-
-FILE_VERSION_FILTER    = 
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
-# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option. You can
-# optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
-#
-# Note that if you run doxygen from a directory containing a file called
-# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
-# tag is left empty.
-
-LAYOUT_FILE            = 
-
-# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
-# the reference definitions. This must be a list of .bib files. The .bib
-# extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
-# For LaTeX the style of the bibliography can be controlled using
-# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
-# search path. See also \cite for info how to create references.
-
-CITE_BIB_FILES         = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated to
-# standard output by doxygen. If QUIET is set to YES this implies that the
-# messages are off.
-# The default value is: NO.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
-# this implies that the warnings are on.
-#
-# Tip: Turn warnings on while writing the documentation.
-# The default value is: YES.
-
-WARNINGS               = YES
-
-# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
-# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
-# will automatically be disabled.
-# The default value is: YES.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
-# The default value is: YES.
-
-WARN_IF_DOC_ERROR      = YES
-
-# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
-# are documented, but have no documentation for their parameters or return
-# value. If set to NO, doxygen will only warn about wrong or incomplete
-# parameter documentation, but not about the absence of documentation.
-# The default value is: NO.
-
-WARN_NO_PARAMDOC       = NO
-
-# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
-# a warning is encountered.
-# The default value is: NO.
-
-WARN_AS_ERROR          = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that doxygen
-# can produce. The string should contain the $file, $line, and $text tags, which
-# will be replaced by the file and line number from which the warning originated
-# and the warning text. Optionally the format may contain $version, which will
-# be replaced by the version of the file (if it could be obtained via
-# FILE_VERSION_FILTER)
-# The default value is: $file:$line: $text.
-
-WARN_FORMAT            = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning and error
-# messages should be written. If left blank the output is written to standard
-# error (stderr).
-
-WARN_LOGFILE           = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag is used to specify the files and/or directories that contain
-# documented source files. You may enter file names like myfile.cpp or
-# directories like /usr/src/myproject. Separate the files or directories with
-# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
-# Note: If this tag is empty the current directory is searched.
-
-INPUT                  = 
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
-# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
-# The default value is: UTF-8.
-
-INPUT_ENCODING         = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
-# *.h) to filter out the source-files in the directories.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# read by doxygen.
-#
-# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
-# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
-# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
-# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
-# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
-
-FILE_PATTERNS          = *.c \
-                         *.cc \
-                         *.cxx \
-                         *.cpp \
-                         *.c++ \
-                         *.java \
-                         *.ii \
-                         *.ixx \
-                         *.ipp \
-                         *.i++ \
-                         *.inl \
-                         *.idl \
-                         *.ddl \
-                         *.odl \
-                         *.h \
-                         *.hh \
-                         *.hxx \
-                         *.hpp \
-                         *.h++ \
-                         *.cs \
-                         *.d \
-                         *.php \
-                         *.php4 \
-                         *.php5 \
-                         *.phtml \
-                         *.inc \
-                         *.m \
-                         *.markdown \
-                         *.md \
-                         *.mm \
-                         *.dox \
-                         *.py \
-                         *.pyw \
-                         *.f90 \
-                         *.f \
-                         *.for \
-                         *.tcl \
-                         *.vhd \
-                         *.vhdl \
-                         *.ucf \
-                         *.qsf \
-                         *.as \
-                         *.js
-
-# The RECURSIVE tag can be used to specify whether or not subdirectories should
-# be searched for input files as well.
-# The default value is: NO.
-
-RECURSIVE              = NO
-
-# The EXCLUDE tag can be used to specify files and/or directories that should be
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-#
-# Note that relative paths are relative to the directory from which doxygen is
-# run.
-
-EXCLUDE                = 
-
-# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
-# directories that are symbolic links (a Unix file system feature) are excluded
-# from the input.
-# The default value is: NO.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories.
-#
-# Note that the wildcards are matched against the file with absolute path, so to
-# exclude all test directories for example use the pattern */test/*
-
-EXCLUDE_PATTERNS       = 
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-#
-# Note that the wildcards are matched against the file with absolute path, so to
-# exclude all test directories use the pattern */test/*
-
-EXCLUDE_SYMBOLS        = profile_inst \
-                         data_packet
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or directories
-# that contain example code fragments that are included (see the \include
-# command).
-
-EXAMPLE_PATH           = 
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
-# *.h) to filter out the source-files in the directories. If left blank all
-# files are included.
-
-EXAMPLE_PATTERNS       = *
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude commands
-# irrespective of the value of the RECURSIVE tag.
-# The default value is: NO.
-
-EXAMPLE_RECURSIVE      = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or directories
-# that contain images that are to be included in the documentation (see the
-# \image command).
-
-IMAGE_PATH             = 
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command:
-#
-# <filter> <input-file>
-#
-# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
-# name of an input file. Doxygen will then use the output that the filter
-# program writes to standard output. If FILTER_PATTERNS is specified, this tag
-# will be ignored.
-#
-# Note that the filter must not add or remove lines; it is applied before the
-# code is scanned, but not when the output code is generated. If lines are added
-# or removed, the anchors will not be placed correctly.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# properly processed by doxygen.
-
-INPUT_FILTER           = 
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form: pattern=filter
-# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
-# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
-# patterns match the file name, INPUT_FILTER is applied.
-#
-# Note that for custom extensions or not directly supported extensions you also
-# need to set EXTENSION_MAPPING for the extension otherwise the files are not
-# properly processed by doxygen.
-
-FILTER_PATTERNS        = 
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will also be used to filter the input files that are used for
-# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
-# The default value is: NO.
-
-FILTER_SOURCE_FILES    = NO
-
-# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
-# it is also possible to disable source filtering for a specific pattern using
-# *.ext= (so without naming a filter).
-# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
-
-FILTER_SOURCE_PATTERNS = 
-
-# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
-# is part of the input, its contents will be placed on the main page
-# (index.html). This can be useful if you have a project on for instance GitHub
-# and want to reuse the introduction page also for the doxygen output.
-
-USE_MDFILE_AS_MAINPAGE = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
-# generated. Documented entities will be cross-referenced with these sources.
-#
-# Note: To get rid of all source code in the generated output, make sure that
-# also VERBATIM_HEADERS is set to NO.
-# The default value is: NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body of functions,
-# classes and enums directly into the documentation.
-# The default value is: NO.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
-# special comment blocks from generated source code fragments. Normal C, C++ and
-# Fortran comments will always remain visible.
-# The default value is: YES.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
-# The default value is: NO.
-
-REFERENCED_BY_RELATION = NO
-
-# If the REFERENCES_RELATION tag is set to YES then for each documented function
-# all documented entities called/used by that function will be listed.
-# The default value is: NO.
-
-REFERENCES_RELATION    = NO
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
-# to YES then the hyperlinks from functions in REFERENCES_RELATION and
-# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
-# link to the documentation.
-# The default value is: YES.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
-# source code will show a tooltip with additional information such as prototype,
-# brief description and links to the definition and documentation. Since this
-# will make the HTML file larger and loading of large files a bit slower, you
-# can opt to disable this feature.
-# The default value is: YES.
-# This tag requires that the tag SOURCE_BROWSER is set to YES.
-
-SOURCE_TOOLTIPS        = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code will
-# point to the HTML generated by the htags(1) tool instead of doxygen built-in
-# source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
-# 4.8.6 or higher.
-#
-# To use it do the following:
-# - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
-# - Make sure the INPUT points to the root of the source tree
-# - Run doxygen as normal
-#
-# Doxygen will invoke htags (and that will in turn invoke gtags), so these
-# tools must be available from the command line (i.e. in the search path).
-#
-# The result: instead of the source browser generated by doxygen, the links to
-# source code will now point to the output of htags.
-# The default value is: NO.
-# This tag requires that the tag SOURCE_BROWSER is set to YES.
-
-USE_HTAGS              = NO
-
-# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
-# verbatim copy of the header file for each class for which an include is
-# specified. Set to NO to disable this.
-# See also: Section \class.
-# The default value is: YES.
-
-VERBATIM_HEADERS       = YES
-
-# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
-# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
-# cost of reduced performance. This can be particularly helpful with template
-# rich C++ code for which doxygen's built-in parser lacks the necessary type
-# information.
-# Note: The availability of this option depends on whether or not doxygen was
-# generated with the -Duse-libclang=ON option for CMake.
-# The default value is: NO.
-
-CLANG_ASSISTED_PARSING = NO
-
-# If clang assisted parsing is enabled you can provide the compiler with command
-# line options that you would normally use when invoking the compiler. Note that
-# the include paths will already be set by doxygen for the files and directories
-# specified with INPUT and INCLUDE_PATH.
-# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
-
-CLANG_OPTIONS          = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
-# compounds will be generated. Enable this if the project contains a lot of
-# classes, structs, unions or interfaces.
-# The default value is: YES.
-
-ALPHABETICAL_INDEX     = YES
-
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-IGNORE_PREFIX          = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
-# The default value is: YES.
-
-GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: html.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_OUTPUT            = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
-# generated HTML page (for example: .htm, .php, .asp).
-# The default value is: .html.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
-# each generated HTML page. If the tag is left blank doxygen will generate a
-# standard header.
-#
-# To get valid HTML the header file that includes any scripts and style sheets
-# that doxygen needs, which is dependent on the configuration options used (e.g.
-# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
-# default header using
-# doxygen -w html new_header.html new_footer.html new_stylesheet.css
-# YourConfigFile
-# and then modify the file new_header.html. See also section "Doxygen usage"
-# for information on how to generate the default header that doxygen normally
-# uses.
-# Note: The header is subject to change so you typically have to regenerate the
-# default header when upgrading to a newer version of doxygen. For a description
-# of the possible markers and block names see the documentation.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_HEADER            = 
-
-# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
-# generated HTML page. If the tag is left blank doxygen will generate a standard
-# footer. See HTML_HEADER for more information on how to generate a default
-# footer and what special commands can be used inside the footer. See also
-# section "Doxygen usage" for information on how to generate the default footer
-# that doxygen normally uses.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_FOOTER            = 
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
-# sheet that is used by each HTML page. It can be used to fine-tune the look of
-# the HTML output. If left blank doxygen will generate a default style sheet.
-# See also section "Doxygen usage" for information on how to generate the style
-# sheet that doxygen normally uses.
-# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
-# it is more robust and this tag (HTML_STYLESHEET) will in the future become
-# obsolete.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_STYLESHEET        = 
-
-# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
-# cascading style sheets that are included after the standard style sheets
-# created by doxygen. Using this option one can overrule certain style aspects.
-# This is preferred over using HTML_STYLESHEET since it does not replace the
-# standard style sheet and is therefore more robust against future updates.
-# Doxygen will copy the style sheet files to the output directory.
-# Note: The order of the extra style sheet files is of importance (e.g. the last
-# style sheet in the list overrules the setting of the previous ones in the
-# list). For an example see the documentation.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_EXTRA_STYLESHEET  = 
-
-# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
-# other source files which should be copied to the HTML output directory. Note
-# that these files will be copied to the base HTML output directory. Use the
-# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
-# files will be copied as-is; there are no commands or markers available.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_EXTRA_FILES       = 
-
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
-# will adjust the colors in the style sheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
-# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
-# purple, and 360 is red again.
-# Minimum value: 0, maximum value: 359, default value: 220.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_HUE    = 220
-
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
-# value of 255 will produce the most vivid colors.
-# Minimum value: 0, maximum value: 255, default value: 100.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_SAT    = 100
-
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
-# luminance component of the colors in the HTML output. Values below 100
-# gradually make the output lighter, whereas values above 100 make the output
-# darker. The value divided by 100 is the actual gamma applied, so 80 represents
-# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
-# change the gamma.
-# Minimum value: 40, maximum value: 240, default value: 80.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_COLORSTYLE_GAMMA  = 80
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting this
-# to YES can help to show when doxygen was last run and thus if the
-# documentation is up to date.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_TIMESTAMP         = NO
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_DYNAMIC_SECTIONS  = NO
-
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
-# shown in the various tree structured indices initially; the user can expand
-# and collapse entries dynamically later on. Doxygen will expand the tree to
-# such a level that at most the specified number of entries are visible (unless
-# a fully collapsed tree already exceeds this amount). So setting the number of
-# entries 1 will produce a full collapsed tree by default. 0 is a special value
-# representing an infinite number of entries and will result in a full expanded
-# tree by default.
-# Minimum value: 0, maximum value: 9999, default value: 100.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-HTML_INDEX_NUM_ENTRIES = 100
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files will be
-# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_DOCSET        = NO
-
-# This tag determines the name of the docset feed. A documentation feed provides
-# an umbrella under which multiple documentation sets from a single provider
-# (such as a company or product suite) can be grouped.
-# The default value is: Doxygen generated docs.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_FEEDNAME        = "Doxygen generated docs"
-
-# This tag specifies a string that should uniquely identify the documentation
-# set bundle. This should be a reverse domain-name style string, e.g.
-# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_BUNDLE_ID       = org.doxygen.Project
-
-# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
-# the documentation publisher. This should be a reverse domain-name style
-# string, e.g. com.mycompany.MyDocSet.documentation.
-# The default value is: org.doxygen.Publisher.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
-
-# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
-# The default value is: Publisher.
-# This tag requires that the tag GENERATE_DOCSET is set to YES.
-
-DOCSET_PUBLISHER_NAME  = Publisher
-
-# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
-# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
-# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
-#
-# The HTML Help Workshop contains a compiler that can convert all HTML output
-# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
-# files are now used as the Windows 98 help format, and will replace the old
-# Windows help format (.hlp) on all Windows platforms in the future. Compressed
-# HTML files also contain an index, a table of contents, and you can search for
-# words in the documentation. The HTML workshop also contains a viewer for
-# compressed HTML files.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_HTMLHELP      = NO
-
-# The CHM_FILE tag can be used to specify the file name of the resulting .chm
-# file. You can add a path in front of the file if the result should not be
-# written to the html output directory.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-CHM_FILE               = 
-
-# The HHC_LOCATION tag can be used to specify the location (absolute path
-# including file name) of the HTML help compiler (hhc.exe). If non-empty,
-# doxygen will try to run the HTML help compiler on the generated index.hhp.
-# The file has to be specified with full path.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-HHC_LOCATION           = 
-
-# The GENERATE_CHI flag controls if a separate .chi index file is generated
-# (YES) or that it should be included in the master .chm file (NO).
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-GENERATE_CHI           = NO
-
-# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
-# and project file content.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-CHM_INDEX_ENCODING     = 
-
-# The BINARY_TOC flag controls whether a binary table of contents is generated
-# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
-# enables the Previous and Next buttons.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members to
-# the table of contents of the HTML help documentation and to the tree view.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-
-TOC_EXPAND             = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
-# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
-# (.qch) of the generated HTML documentation.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_QHP           = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
-# the file name of the resulting .qch file. The path specified is relative to
-# the HTML output folder.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QCH_FILE               = 
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
-# Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_NAMESPACE          = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
-# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
-# The default value is: doc.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_VIRTUAL_FOLDER     = doc
-
-# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
-# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_CUST_FILTER_NAME   = 
-
-# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_CUST_FILTER_ATTRS  = 
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHP_SECT_FILTER_ATTRS  = 
-
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
-# This tag requires that the tag GENERATE_QHP is set to YES.
-
-QHG_LOCATION           = 
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
-# generated, together with the HTML files, they form an Eclipse help plugin. To
-# install this plugin and make it available under the help contents menu in
-# Eclipse, the contents of the directory containing the HTML and XML files needs
-# to be copied into the plugins directory of eclipse. The name of the directory
-# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
-# After copying Eclipse needs to be restarted before the help appears.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_ECLIPSEHELP   = NO
-
-# A unique identifier for the Eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have this
-# name. Each documentation set should have its own identifier.
-# The default value is: org.doxygen.Project.
-# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
-
-ECLIPSE_DOC_ID         = org.doxygen.Project
-
-# If you want full control over the layout of the generated HTML pages it might
-# be necessary to disable the index and replace it with your own. The
-# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
-# of each HTML page. A value of NO enables the index and the value YES disables
-# it. Since the tabs in the index contain the same information as the navigation
-# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-DISABLE_INDEX          = NO
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information. If the tag
-# value is set to YES, a side panel will be generated containing a tree-like
-# index structure (just like the one that is generated for HTML Help). For this
-# to work a browser that supports JavaScript, DHTML, CSS and frames is required
-# (i.e. any modern browser). Windows users are probably better off using the
-# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-GENERATE_TREEVIEW      = NO
-
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
-# doxygen will group on one line in the generated HTML documentation.
-#
-# Note that a value of 0 will completely suppress the enum values from appearing
-# in the overview section.
-# Minimum value: 0, maximum value: 20, default value: 4.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
-# to set the initial width (in pixels) of the frame in which the tree is shown.
-# Minimum value: 0, maximum value: 1500, default value: 250.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-TREEVIEW_WIDTH         = 250
-
-# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
-# external symbols imported via tag files in a separate window.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-EXT_LINKS_IN_WINDOW    = NO
-
-# Use this tag to change the font size of LaTeX formulas included as images in
-# the HTML documentation. When you change the font size after a successful
-# doxygen run you need to manually remove any form_*.png images from the HTML
-# output directory to force them to be regenerated.
-# Minimum value: 8, maximum value: 50, default value: 10.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-FORMULA_FONTSIZE       = 10
-
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-FORMULA_TRANSPARENT    = YES
-
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
-# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
-# installed or if you want to formulas look prettier in the HTML output. When
-# enabled you may also need to install MathJax separately and configure the path
-# to it using the MATHJAX_RELPATH option.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-USE_MATHJAX            = NO
-
-# When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
-# Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
-# The default value is: HTML-CSS.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_FORMAT         = HTML-CSS
-
-# When MathJax is enabled you need to specify the location relative to the HTML
-# output directory using the MATHJAX_RELPATH option. The destination directory
-# should contain the MathJax.js script. For instance, if the mathjax directory
-# is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
-# Content Delivery Network so you can quickly see the result without installing
-# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
-
-# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
-# extension names that should be enabled during MathJax rendering. For example
-# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_EXTENSIONS     = 
-
-# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
-# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
-# example see the documentation.
-# This tag requires that the tag USE_MATHJAX is set to YES.
-
-MATHJAX_CODEFILE       = 
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
-# the HTML output. The underlying search engine uses javascript and DHTML and
-# should work on any modern browser. Note that when using HTML help
-# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
-# there is already a search function so this one should typically be disabled.
-# For large projects the javascript based search engine can be slow, then
-# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
-# search using the keyboard; to jump to the search box use <access key> + S
-# (what the <access key> is depends on the OS and browser, but it is typically
-# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
-# key> to jump into the search results window, the results can be navigated
-# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
-# the search. The filter options can be selected when the cursor is inside the
-# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
-# to select a filter and <Enter> or <escape> to activate or cancel the filter
-# option.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
-
-SEARCHENGINE           = YES
-
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
-# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
-# setting. When disabled, doxygen will generate a PHP script for searching and
-# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
-# and searching needs to be provided by external tools. See the section
-# "External Indexing and Searching" for details.
-# The default value is: NO.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-SERVER_BASED_SEARCH    = NO
-
-# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
-# script for searching. Instead the search results are written to an XML file
-# which needs to be processed by an external indexer. Doxygen will invoke an
-# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
-# search results.
-#
-# Doxygen ships with an example indexer (doxyindexer) and search engine
-# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
-#
-# See the section "External Indexing and Searching" for details.
-# The default value is: NO.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-EXTERNAL_SEARCH        = NO
-
-# The SEARCHENGINE_URL should point to a search engine hosted by a web server
-# which will return the search results when EXTERNAL_SEARCH is enabled.
-#
-# Doxygen ships with an example indexer (doxyindexer) and search engine
-# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-SEARCHENGINE_URL       = 
-
-# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
-# search data is written to a file for indexing by an external tool. With the
-# SEARCHDATA_FILE tag the name of this file can be specified.
-# The default file is: searchdata.xml.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-SEARCHDATA_FILE        = searchdata.xml
-
-# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
-# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
-# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
-# projects and redirect the results back to the right project.
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-EXTERNAL_SEARCH_ID     = 
-
-# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
-# projects other than the one defined by this configuration file, but that are
-# all added to the same external search index. Each project needs to have a
-# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
-# to a relative location where the documentation can be found. The format is:
-# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
-# This tag requires that the tag SEARCHENGINE is set to YES.
-
-EXTRA_SEARCH_MAPPINGS  = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
-# The default value is: YES.
-
-GENERATE_LATEX         = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: latex.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_OUTPUT           = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked.
-#
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_CMD_NAME         = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
-# index for LaTeX.
-# The default file is: makeindex.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-MAKEINDEX_CMD_NAME     = makeindex
-
-# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
-# documents. This may be useful for small projects and may help to save some
-# trees in general.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used by the
-# printer.
-# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
-# 14 inches) and executive (7.25 x 10.5 inches).
-# The default value is: a4.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-PAPER_TYPE             = a4
-
-# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
-# that should be included in the LaTeX output. The package can be specified just
-# by its name or with the correct syntax as to be used with the LaTeX
-# \usepackage command. To get the times font for instance you can specify :
-# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
-# To use the option intlimits with the amsmath package you can specify:
-# EXTRA_PACKAGES=[intlimits]{amsmath}
-# If left blank no extra packages will be included.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-EXTRA_PACKAGES         = 
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
-# generated LaTeX document. The header should contain everything until the first
-# chapter. If it is left blank doxygen will generate a standard header. See
-# section "Doxygen usage" for information on how to let doxygen write the
-# default header to a separate file.
-#
-# Note: Only use a user-defined header if you know what you are doing! The
-# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
-# string, for the replacement values of the other commands the user is referred
-# to HTML_HEADER.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_HEADER           = 
-
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
-# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer. See
-# LATEX_HEADER for more information on how to generate a default footer and what
-# special commands can be used inside the footer.
-#
-# Note: Only use a user-defined footer if you know what you are doing!
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_FOOTER           = 
-
-# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
-# LaTeX style sheets that are included after the standard style sheets created
-# by doxygen. Using this option one can overrule certain style aspects. Doxygen
-# will copy the style sheet files to the output directory.
-# Note: The order of the extra style sheet files is of importance (e.g. the last
-# style sheet in the list overrules the setting of the previous ones in the
-# list).
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_EXTRA_STYLESHEET = 
-
-# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
-# other source files which should be copied to the LATEX_OUTPUT output
-# directory. Note that the files will be copied as-is; there are no commands or
-# markers available.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_EXTRA_FILES      = 
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
-# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
-# contain links (just like the HTML output) instead of page references. This
-# makes the output suitable for online browsing using a PDF viewer.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-PDF_HYPERLINKS         = YES
-
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES, to get a
-# higher quality PDF documentation.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-USE_PDFLATEX           = YES
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
-# command to the generated LaTeX files. This will instruct LaTeX to keep running
-# if errors occur, instead of asking the user for help. This option is also used
-# when generating formulas in HTML.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_BATCHMODE        = NO
-
-# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
-# index chapters (such as File Index, Compound Index, etc.) in the output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_HIDE_INDICES     = NO
-
-# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
-# code with syntax highlighting in the LaTeX output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_SOURCE_CODE      = NO
-
-# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
-# The default value is: plain.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_BIB_STYLE        = plain
-
-# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
-# page will contain the date and time when the page was generated. Setting this
-# to NO can help when comparing the output of multiple runs.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_TIMESTAMP        = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
-# RTF output is optimized for Word 97 and may not look too pretty with other RTF
-# readers/editors.
-# The default value is: NO.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: rtf.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_OUTPUT             = rtf
-
-# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
-# documents. This may be useful for small projects and may help to save some
-# trees in general.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
-# contain hyperlink fields. The RTF file will contain links (just like the HTML
-# output) instead of page references. This makes the output suitable for online
-# browsing using Word or some other Word compatible readers that support those
-# fields.
-#
-# Note: WordPad (write) and others do not support links.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_HYPERLINKS         = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
-#
-# See also section "Doxygen usage" for information on how to generate the
-# default style sheet that doxygen normally uses.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_STYLESHEET_FILE    = 
-
-# Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_EXTENSIONS_FILE    = 
-
-# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
-# with syntax highlighting in the RTF output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_SOURCE_CODE        = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
-# classes and files.
-# The default value is: NO.
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it. A directory man3 will be created inside the directory specified by
-# MAN_OUTPUT.
-# The default directory is: man.
-# This tag requires that the tag GENERATE_MAN is set to YES.
-
-MAN_OUTPUT             = man
-
-# The MAN_EXTENSION tag determines the extension that is added to the generated
-# man pages. In case the manual section does not start with a number, the number
-# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
-# optional.
-# The default value is: .3.
-# This tag requires that the tag GENERATE_MAN is set to YES.
-
-MAN_EXTENSION          = .3
-
-# The MAN_SUBDIR tag determines the name of the directory created within
-# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
-# MAN_EXTENSION with the initial . removed.
-# This tag requires that the tag GENERATE_MAN is set to YES.
-
-MAN_SUBDIR             = 
-
-# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
-# will generate one additional man file for each entity documented in the real
-# man page(s). These additional files only source the real man page, but without
-# them the man command would be unable to find the correct page.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_MAN is set to YES.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
-# captures the structure of the code including all documentation.
-# The default value is: NO.
-
-GENERATE_XML           = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
-# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
-# it.
-# The default directory is: xml.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_OUTPUT             = xml
-
-# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
-# listings (including syntax highlighting and cross-referencing information) to
-# the XML output. Note that enabling this will significantly increase the size
-# of the XML output.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_PROGRAMLISTING     = YES
-
-#---------------------------------------------------------------------------
-# Configuration options related to the DOCBOOK output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
-# that can be used to generate PDF.
-# The default value is: NO.
-
-GENERATE_DOCBOOK       = NO
-
-# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
-# front of it.
-# The default directory is: docbook.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_OUTPUT         = docbook
-
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
-# program listings (including syntax highlighting and cross-referencing
-# information) to the DOCBOOK output. Note that enabling this will significantly
-# increase the size of the DOCBOOK output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_PROGRAMLISTING = NO
-
-#---------------------------------------------------------------------------
-# Configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
-# AutoGen Definitions (see http://autogen.sf.net) file that captures the
-# structure of the code including all documentation. Note that this feature is
-# still experimental and incomplete at the moment.
-# The default value is: NO.
-
-GENERATE_AUTOGEN_DEF   = NO
-
-#---------------------------------------------------------------------------
-# Configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
-# file that captures the structure of the code including all documentation.
-#
-# Note that this feature is still experimental and incomplete at the moment.
-# The default value is: NO.
-
-GENERATE_PERLMOD       = NO
-
-# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
-# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
-# output from the Perl module output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-
-PERLMOD_LATEX          = NO
-
-# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
-# formatted so it can be parsed by a human reader. This is useful if you want to
-# understand what is going on. On the other hand, if this tag is set to NO, the
-# size of the Perl module output will be much smaller and Perl will parse it
-# just the same.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-
-PERLMOD_PRETTY         = YES
-
-# The names of the make variables in the generated doxyrules.make file are
-# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
-# so different doxyrules.make files included by the same Makefile don't
-# overwrite each other's variables.
-# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-
-PERLMOD_MAKEVAR_PREFIX = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
-# C-preprocessor directives found in the sources and include files.
-# The default value is: YES.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
-# in the source code. If set to NO, only conditional compilation will be
-# performed. Macro expansion can be done in a controlled way by setting
-# EXPAND_ONLY_PREDEF to YES.
-# The default value is: NO.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-MACRO_EXPANSION        = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
-# the macro expansion is limited to the macros specified with the PREDEFINED and
-# EXPAND_AS_DEFINED tags.
-# The default value is: NO.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-EXPAND_ONLY_PREDEF     = NO
-
-# If the SEARCH_INCLUDES tag is set to YES, the include files in the
-# INCLUDE_PATH will be searched if a #include is found.
-# The default value is: YES.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by the
-# preprocessor.
-# This tag requires that the tag SEARCH_INCLUDES is set to YES.
-
-INCLUDE_PATH           = 
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will be
-# used.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-INCLUDE_FILE_PATTERNS  = 
-
-# The PREDEFINED tag can be used to specify one or more macro names that are
-# defined before the preprocessor is started (similar to the -D option of e.g.
-# gcc). The argument of the tag is a list of macros of the form: name or
-# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
-# is assumed. To prevent a macro definition from being undefined via #undef or
-# recursively expanded use the := operator instead of the = operator.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-PREDEFINED             = CONFIG_MONGOOSE_PRESENT \
-                         CONFIG_WIFI_ENABLED \
-                         CONFIG_BT_ENABLED
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
-# tag can be used to specify a list of macro names that should be expanded. The
-# macro definition that is found in the sources will be used. Use the PREDEFINED
-# tag if you want to use a different macro definition that overrules the
-# definition found in the source code.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-EXPAND_AS_DEFINED      = 
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all references to function-like macros that are alone on a line, have
-# an all uppercase name, and do not end with a semicolon. Such function macros
-# are typically used for boiler-plate code, and will confuse the parser if not
-# removed.
-# The default value is: YES.
-# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-
-SKIP_FUNCTION_MACROS   = YES
-
-#---------------------------------------------------------------------------
-# Configuration options related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES tag can be used to specify one or more tag files. For each tag
-# file the location of the external documentation should be added. The format of
-# a tag file without this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where loc1 and loc2 can be relative or absolute paths or URLs. See the
-# section "Linking to external documentation" for more information about the use
-# of tag files.
-# Note: Each tag file must have a unique name (where the name does NOT include
-# the path). If a tag file is not located in the directory in which doxygen is
-# run, you must also specify the path to the tagfile here.
-
-TAGFILES               = 
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
-# tag file that is based on the input files it reads. See section "Linking to
-# external documentation" for more information about the usage of tag files.
-
-GENERATE_TAGFILE       = 
-
-# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
-# the class index. If set to NO, only the inherited external classes will be
-# listed.
-# The default value is: NO.
-
-ALLEXTERNALS           = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will be
-# listed.
-# The default value is: YES.
-
-EXTERNAL_GROUPS        = YES
-
-# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
-# the related pages index. If set to NO, only the current project's pages will
-# be listed.
-# The default value is: YES.
-
-EXTERNAL_PAGES         = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of 'which perl').
-# The default file (with absolute path) is: /usr/bin/perl.
-
-PERL_PATH              = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
-# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
-# NO turns the diagrams off. Note that this option also works with HAVE_DOT
-# disabled, but it is recommended to install and use dot, since it yields more
-# powerful graphs.
-# The default value is: YES.
-
-CLASS_DIAGRAMS         = YES
-
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see:
-# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH            = 
-
-# You can include diagrams made with dia in doxygen documentation. Doxygen will
-# then run dia to produce the diagram and insert it in the documentation. The
-# DIA_PATH tag allows you to specify the directory where the dia binary resides.
-# If left empty dia is assumed to be found in the default search path.
-
-DIA_PATH               = 
-
-# If set to YES the inheritance and collaboration graphs will hide inheritance
-# and usage relations if the target is undocumented or is not a class.
-# The default value is: YES.
-
-HIDE_UNDOC_RELATIONS   = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz (see:
-# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
-# Bell Labs. The other options in this section have no effect if this option is
-# set to NO
-# The default value is: YES.
-
-HAVE_DOT               = YES
-
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
-# to run in parallel. When set to 0 doxygen will base this on the number of
-# processors available in the system. You can set it explicitly to a value
-# larger than 0 to get control over the balance between CPU load and processing
-# speed.
-# Minimum value: 0, maximum value: 32, default value: 0.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_NUM_THREADS        = 0
-
-# When you want a differently looking font in the dot files that doxygen
-# generates you can specify the font name using DOT_FONTNAME. You need to make
-# sure dot is able to find the font, which can be done by putting it in a
-# standard location or by setting the DOTFONTPATH environment variable or by
-# setting DOT_FONTPATH to the directory containing the font.
-# The default value is: Helvetica.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_FONTNAME           = Helvetica
-
-# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
-# dot graphs.
-# Minimum value: 4, maximum value: 24, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_FONTSIZE           = 10
-
-# By default doxygen will tell dot to use the default font as specified with
-# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
-# the path where dot can find it using this tag.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_FONTPATH           = 
-
-# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
-# each documented class showing the direct and indirect inheritance relations.
-# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
-# graph for each documented class showing the direct and indirect implementation
-# dependencies (inheritance, containment, and class references variables) of the
-# class with other documented classes.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-COLLABORATION_GRAPH    = YES
-
-# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
-# groups, showing the direct groups dependencies.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-GROUP_GRAPHS           = YES
-
-# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-UML_LOOK               = NO
-
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
-# class node. If there are many fields or methods and many nodes the graph may
-# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
-# number of items for each type to make the size more manageable. Set this to 0
-# for no limit. Note that the threshold may be exceeded by 50% before the limit
-# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
-# but if the number exceeds 15, the total amount of fields shown is limited to
-# 10.
-# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-UML_LIMIT_NUM_FIELDS   = 10
-
-# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
-# collaboration graphs will show the relations between templates and their
-# instances.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-TEMPLATE_RELATIONS     = NO
-
-# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
-# YES then doxygen will generate a graph for each documented file showing the
-# direct and indirect include dependencies of the file with other documented
-# files.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-INCLUDE_GRAPH          = YES
-
-# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
-# set to YES then doxygen will generate a graph for each documented file showing
-# the direct and indirect include dependencies of the file with other documented
-# files.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
-# dependency graph for every global function or class method.
-#
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable call graphs for selected
-# functions only using the \callgraph command. Disabling a call graph can be
-# accomplished by means of the command \hidecallgraph.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-CALL_GRAPH             = NO
-
-# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
-# dependency graph for every global function or class method.
-#
-# Note that enabling this option will significantly increase the time of a run.
-# So in most cases it will be better to enable caller graphs for selected
-# functions only using the \callergraph command. Disabling a caller graph can be
-# accomplished by means of the command \hidecallergraph.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-CALLER_GRAPH           = NO
-
-# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
-# hierarchy of all classes instead of a textual one.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
-# dependencies a directory has on other directories in a graphical way. The
-# dependency relations are determined by the #include relations between the
-# files in the directories.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DIRECTORY_GRAPH        = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. For an explanation of the image formats see the section
-# output formats in the documentation of the dot tool (Graphviz (see:
-# http://www.graphviz.org/)).
-# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
-# to make the SVG files visible in IE 9+ (other browsers do not have this
-# requirement).
-# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
-# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
-# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
-# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
-# png:gdiplus:gdiplus.
-# The default value is: png.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_IMAGE_FORMAT       = png
-
-# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
-# enable generation of interactive SVG images that allow zooming and panning.
-#
-# Note that this requires a modern browser other than Internet Explorer. Tested
-# and working are Firefox, Chrome, Safari, and Opera.
-# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
-# the SVG files visible. Older versions of IE do not have SVG support.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-INTERACTIVE_SVG        = NO
-
-# The DOT_PATH tag can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_PATH               = 
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the \dotfile
-# command).
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOTFILE_DIRS           = 
-
-# The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the \mscfile
-# command).
-
-MSCFILE_DIRS           = 
-
-# The DIAFILE_DIRS tag can be used to specify one or more directories that
-# contain dia files that are included in the documentation (see the \diafile
-# command).
-
-DIAFILE_DIRS           = 
-
-# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
-# path where java can find the plantuml.jar file. If left blank, it is assumed
-# PlantUML is not used or called during a preprocessing step. Doxygen will
-# generate a warning when it encounters a \startuml command in this case and
-# will not generate output for the diagram.
-
-PLANTUML_JAR_PATH      = 
-
-# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
-# configuration file for plantuml.
-
-PLANTUML_CFG_FILE      = 
-
-# When using plantuml, the specified paths are searched for files specified by
-# the !include statement in a plantuml block.
-
-PLANTUML_INCLUDE_PATH  = 
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
-# that will be shown in the graph. If the number of nodes in a graph becomes
-# larger than this value, doxygen will truncate the graph, which is visualized
-# by representing a node as a red box. Note that doxygen if the number of direct
-# children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
-# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-# Minimum value: 0, maximum value: 10000, default value: 50.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_GRAPH_MAX_NODES    = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
-# generated by dot. A depth value of 3 means that only nodes reachable from the
-# root by following a path via at most 3 edges will be shown. Nodes that lay
-# further from the root node will be omitted. Note that setting this option to 1
-# or 2 may greatly reduce the computation time needed for large code bases. Also
-# note that the size of a graph can be further restricted by
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-# Minimum value: 0, maximum value: 1000, default value: 0.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-MAX_DOT_GRAPH_DEPTH    = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not seem
-# to support this out of the box.
-#
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_TRANSPARENT        = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10) support
-# this, this feature is disabled by default.
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_MULTI_TARGETS      = NO
-
-# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
-# explaining the meaning of the various boxes and arrows in the dot generated
-# graphs.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
-# files that are used to generate the various graphs.
-# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_CLEANUP            = YES
diff --git a/components/cpp_utils/FATFS_VFS.cpp b/components/cpp_utils/FATFS_VFS.cpp
deleted file mode 100644
index 30af8e4..0000000
--- a/components/cpp_utils/FATFS_VFS.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * FATFS.cpp
- *
- *  Created on: May 20, 2017
- *      Author: kolban
- */
-
-#include "FATFS_VFS.h"
-#include <esp_err.h>
-
-#include <esp_vfs_fat.h>
-
-
-/**
- * @brief Constructor.
- *
- * In ESP32, every file system has a mount point.  If a file access is attempted south of that
- * mount point, then the corresponding file system will be used.  The `mountPath` parameter defines
- * the mount point for this instance of the FATFS file system.
- * In order to save the files for subsequent retrieval, the file data has to be written to flash memory.
- * A partition table provides a map or layout of the flash memory by defining named partitions.  The
- * `partitionName` parameter defines the name of the partition used to provide the underlying storage
- * for this instance of the FATFS file system.
- *
- * @param [in] mountPath The path in the VFS where the FAT file system should be mounted.
- * @param [in] partitionName The name of the partition used to store the FAT file system.
- */
-FATFS_VFS::FATFS_VFS(std::string mountPath, std::string partitionName) {
-	m_mountPath     = mountPath;
-	m_partitionName = partitionName;
-	m_maxFiles      = 4;
-	m_wl_handle     = WL_INVALID_HANDLE;
-} // FATFS_VFS
-
-
-FATFS_VFS::~FATFS_VFS() {
-} // ~FATFS_VFS
-
-
-/**
- * @brief Mount the FAT file system into VFS.
- * The FAT file system found in the partition is mounted into the VFS.
- * @return N/A.
- */
-void FATFS_VFS::mount() {
-	esp_vfs_fat_mount_config_t mountConfig;
-	mountConfig.max_files = m_maxFiles;
-	mountConfig.format_if_mount_failed = true;
-	ESP_ERROR_CHECK(esp_vfs_fat_spiflash_mount(m_mountPath.c_str(), m_partitionName.c_str(), &mountConfig, &m_wl_handle));
-} // mount
-
-
-/**
- * @brief Set the allowable number of concurrently open files.
- * @param [in] maxFiles Number of concurrently open files.
- * @return N/A.
- */
-void FATFS_VFS::setMaxFiles(int maxFiles) {
-	m_maxFiles = maxFiles;
-} // setMaxFiles
-
-
-/**
- * @brief Unmount a previously mounted file system.
- * @return N/A.
- */
-void FATFS_VFS::unmount() {
-	ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount(m_mountPath.c_str(), m_wl_handle));
-} // unmount
diff --git a/components/cpp_utils/FATFS_VFS.h b/components/cpp_utils/FATFS_VFS.h
deleted file mode 100644
index 24ce492..0000000
--- a/components/cpp_utils/FATFS_VFS.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * FATFS.h
- *
- *  Created on: May 20, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_FATFS_VFS_H_
-#define COMPONENTS_CPP_UTILS_FATFS_VFS_H_
-#include <string>
-extern "C" {
-#include <esp_vfs_fat.h>
-#include <wear_levelling.h>
-}
-/**
- * @brief Provide access to the FAT file system on %SPI flash.
- * The FATFS_VFS file system needs a partition definition.  This is a map of flash memory that
- * specified an array into which the files should be saved and loaded.  A partition is a named
- * entity and the name we choose in the partition definition should be named in the constructor.
- *
- * A partition configuration file can be described in the `make menuconfig` settings.  For example:
- * ~~~~
- * nvs,      data, nvs,     0x9000,  0x6000,
- * phy_init, data, phy,     0xf000,  0x1000,
- * factory,  app,  factory, 0x10000, 1M,
- * storage,  data, fat,     ,        1M,
- * ~~~~
- *
- * The recommended file name for the partition description is `partitions.csv`
- *
- * A typical example would be:
- *
- * @code{.cpp}
- * FATFS_VFS *fs = new FATFS_VFS("/spiflash", "storage");
- * fs->mount();
- * // Perform file I/O
- * fs->unmount();
- * delete fs;
- * @endcode
- *
- */
-class FATFS_VFS {
-public:
-	FATFS_VFS(std::string mountPath, std::string partitionName);
-	virtual ~FATFS_VFS();
-
-	void mount();
-	void setMaxFiles(int maxFiles);
-	void unmount();
-private:
-	wl_handle_t m_wl_handle;
-	std::string m_mountPath;
-	std::string m_partitionName;
-	int         m_maxFiles;
-};
-
-#endif /* COMPONENTS_CPP_UTILS_FATFS_VFS_H_ */
diff --git a/components/cpp_utils/File.cpp b/components/cpp_utils/File.cpp
deleted file mode 100644
index 6b0627a..0000000
--- a/components/cpp_utils/File.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * File.cpp
- *
- *  Created on: Jun 1, 2017
- *      Author: kolban
- */
-
-#include "File.h"
-#include <sys/stat.h>
-#include <esp_log.h>
-#include <string>
-#include <stdlib.h>
-#include <stdio.h>
-#include <GeneralUtils.h>
-
-static const char* LOG_TAG = "File";
-/**
- * @brief Construct a file.
- * @param [in] name The name of the file.
- * @param [in] type The type of the file (DT_REGULAR, DT_DIRECTORY or DT_UNKNOWN).
- */
-File::File(std::string name, uint8_t type) {
-	m_name = name;
-	m_type = type;
-} // File
-
-
-/**
- * @brief Retrieve the content of the file.
- * @param [in] base64Encode Should we base64 encode the content?
- * @return The content of the file.
- */
-std::string File::getContent(bool base64Encode) {
-	uint32_t size = length();
-	ESP_LOGD(LOG_TAG, "File:: getContent(), name=%s, length=%d", m_name.c_str(), size);
-	if (size == 0) {
-		return "";
-	}
-	uint8_t *pData = (uint8_t *)malloc(size);
-	if (pData == nullptr) {
-		ESP_LOGE(LOG_TAG, "getContent: Failed to allocate memory");
-		return "";
-	}
-	FILE *file = fopen(m_name.c_str(), "r");
-	fread(pData, size, 1, file);
-	fclose(file);
-	std::string ret((char *)pData, size);
-	free(pData);
-	if (base64Encode) {
-		std::string encoded;
-		GeneralUtils::base64Decode(ret, &encoded);
-		return encoded;
-	}
-	return ret;
-} // getContent
-
-
-/**
- * @brief Retrieve the content of the file.
- * @param [in] offset The file offset to read from.
- * @param [in] readSize The number of bytes to read.
- * @return The content of the file.
- */
-std::string File::getContent(uint32_t offset, uint32_t readSize) {
-	uint32_t fileSize = length();
-	ESP_LOGD(LOG_TAG, "File:: getContent(), name=%s, fileSize=%d, offset=%d, readSize=%d",
-		m_name.c_str(), fileSize, offset, readSize);
-	if (fileSize == 0 || offset > fileSize) {
-		return "";
-	}
-	uint8_t *pData = (uint8_t *)malloc(readSize);
-	if (pData == nullptr) {
-		ESP_LOGE(LOG_TAG, "getContent: Failed to allocate memory");
-		return "";
-	}
-	FILE *file = fopen(m_name.c_str(), "r");
-	fseek(file, offset, SEEK_SET);
-	size_t bytesRead = fread(pData, 1, readSize, file);
-	fclose(file);
-	std::string ret((char *)pData, bytesRead);
-	free(pData);
-	return ret;
-} // getContent
-
-
-/**
- * @brief Get the name of the file.
- * @return The name of the file.
- */
-std::string File::getName() {
-	return m_name;
-} // getName
-
-
-/**
- * @brief Get the type of the file.
- * The type of a file can be DT_REGULAR, DT_DIRECTORY or DT_UNKNOWN.
- * @return The type of the file.
- */
-uint8_t File::getType() {
-	return m_type;
-} // getName
-
-
-/**
- * @brief Get the length of the file in bytes.
- * @return The length of the file in bytes.
- */
-uint32_t File::length() {
-	struct stat buf;
-	int rc = stat(m_name.c_str(), &buf);
-	if (rc != 0) {
-		return 0;
-	}
-	return buf.st_size;
-} // length
-
-
-/**
- * @brief Determine if the type of the file is a directory.
- * @return True if the file is a directory.
- */
-bool File::isDirectory() {
-	struct stat buf;
-	int rc = stat(m_name.c_str(), &buf);
-	if (rc != 0) {
-		return false;
-	}
-	if (S_ISDIR(buf.st_mode)) {
-		return true;
-	}
-	return false;
-} // isDirectory
diff --git a/components/cpp_utils/File.h b/components/cpp_utils/File.h
deleted file mode 100644
index cd64435..0000000
--- a/components/cpp_utils/File.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * File.h
- *
- *  Created on: Jun 1, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_FILE_H_
-#define COMPONENTS_CPP_UTILS_FILE_H_
-#include <string>
-#include <dirent.h>
-
-/**
- * @brief A logical representation of a file.
- */
-class File {
-public:
-	File(std::string name, uint8_t type = DT_UNKNOWN);
-
-	std::string getContent(bool base64Encode=false);
-	std::string getContent(uint32_t offset, uint32_t size);
-	std::string getName();
-	uint8_t     getType();
-	bool        isDirectory();
-	uint32_t    length();
-
-private:
-	std::string m_name;
-	uint8_t     m_type;
-};
-
-#endif /* COMPONENTS_CPP_UTILS_FILE_H_ */
diff --git a/components/cpp_utils/FileSystem.cpp b/components/cpp_utils/FileSystem.cpp
deleted file mode 100644
index d024074..0000000
--- a/components/cpp_utils/FileSystem.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * FileSystem.cpp
- *
- *  Created on: May 20, 2017
- *      Author: kolban
- */
-#include <iostream>
-#include <sstream>
-#include <string>
-
-#include <dirent.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <esp_log.h>
-
-#include "FileSystem.h"
-
-static const char* LOG_TAG = "FileSystem";
-
-/**
- * @brief Dump a given directory to the log.
- * @param [in] path The path to the directory to dump.
- * @return N/A.
- */
-void FileSystem::dumpDirectory(std::string path) {
-	DIR *pDir = ::opendir(path.c_str());
-	if (pDir == nullptr) {
-		ESP_LOGD(LOG_TAG, "Unable to open directory: %s [errno=%d]", path.c_str(), errno);
-		return;
-	}
-	struct dirent *pDirent;
-	ESP_LOGD(LOG_TAG, "Directory dump of %s", path.c_str());
-	while((pDirent = readdir(pDir)) != nullptr) {
-		std::string type;
-		switch(pDirent->d_type) {
-		case DT_UNKNOWN:
-			type = "Unknown";
-			break;
-		case DT_REG:
-			type = "Regular";
-			break;
-		case DT_DIR:
-			type = "Directory";
-			break;
-		}
-		ESP_LOGD(LOG_TAG, "Entry: d_ino: %d, d_name: %s, d_type: %s", pDirent->d_ino, pDirent->d_name, type.c_str());
-	}
-	::closedir(pDir);
-} // dumpDirectory
-
-
-/**
- * @brief Get the contents of a directory.
- * @param [in] path The path to the directory.
- * @return A vector of Files in the directory.
- */
-std::vector<File> FileSystem::getDirectoryContents(std::string path) {
-	std::vector<File> ret;
-	DIR *pDir = ::opendir(path.c_str());
-	if (pDir == nullptr) {
-		ESP_LOGE(LOG_TAG, "getDirectoryContents:: Unable to open directory: %s [errno=%d]", path.c_str(), errno);
-		return ret;
-	}
-	struct dirent *pDirent;
-	ESP_LOGD(LOG_TAG, "Directory dump of %s", path.c_str());
-	while((pDirent = readdir(pDir)) != nullptr) {
-		File file(std::string(pDirent->d_name), pDirent->d_type);
-		ret.push_back(file);
-	}
-	::closedir(pDir);
-	return ret;
-} // getDirectoryContents
-
-
-/**
- * @brief Create a directory
- * @param [in] path The directory to create.
- * @return N/A.
- */
-int FileSystem::mkdir(std::string path) {
-	int rc = ::mkdir(path.c_str(), 0);
-	if (rc != 0) {
-		ESP_LOGE(LOG_TAG, "mkdir: errno=%d", errno);
-		rc = errno;
-	}
-	return rc;
-} // mkdir
-
-
-/**
- * @brief Return the constituent parts of the path.
- * If we imagine a path as composed of parts separated by slashes, then this function
- * returns a vector composed of the parts.  For example:
- *
- * ```
- * /x/y/z
- * ```
- * will break out to:
- *
- * ```
- * path[0] = ""
- * path[1] = "x"
- * path[2] = "y"
- * path[3] = "z"
- * ```
- *
- * @return A vector of the constituent parts of the path.
- */
-std::vector<std::string> FileSystem::pathSplit(std::string path) {
-	std::istringstream stream(path);
-	std::vector<std::string> ret;
-	std::string pathPart;
-	while(std::getline(stream, pathPart, '/')) {
-		ret.push_back(pathPart);
-	}
-	// Debug
-	for (int i=0; i<ret.size(); i++) {
-		ESP_LOGD(LOG_TAG, "part[%d]: %s", i, ret[i].c_str());
-	}
-	return ret;
-} // pathSplit
-
-
-/**
- * @brief Remove a file from the file system.
- * @param [in] path The path to the file to be removed.
- * @return The return code of the underlying call.
- */
-int FileSystem::remove(std::string path) {
-	int rc = ::unlink(path.c_str());
-	if (rc != 0) {
-		ESP_LOGE(LOG_TAG, "unlink: errno=%d", errno);
-		rc = errno;
-	}
-	return rc;
-} // remove
diff --git a/components/cpp_utils/FileSystem.h b/components/cpp_utils/FileSystem.h
deleted file mode 100644
index b2ab63b..0000000
--- a/components/cpp_utils/FileSystem.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * FileSystem.h
- *
- *  Created on: May 20, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_FILESYSTEM_H_
-#define COMPONENTS_CPP_UTILS_FILESYSTEM_H_
-#include <string>
-#include <vector>
-#include <File.h>
-/**
- * @brief File system utilities.
- */
-class FileSystem {
-public:
-	static std::vector<File>        getDirectoryContents(std:: string path);
-	static void                     dumpDirectory(std::string path);
-	static int                      mkdir(std::string path);
-	static std::vector<std::string> pathSplit(std::string path);
-	static int                      remove(std::string path);
-};
-
-#endif /* COMPONENTS_CPP_UTILS_FILESYSTEM_H_ */
diff --git a/components/cpp_utils/FreeRTOS.cpp b/components/cpp_utils/FreeRTOS.cpp
deleted file mode 100644
index 663128d..0000000
--- a/components/cpp_utils/FreeRTOS.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * FreeRTOS.cpp
- *
- *  Created on: Feb 24, 2017
- *      Author: kolban
- */
-#include <freertos/FreeRTOS.h>
-#include <freertos/task.h>
-#include <string>
-#include <sstream>
-#include <iomanip>
-#include "FreeRTOS.h"
-#include <esp_log.h>
-#include "sdkconfig.h"
-
-static const char* LOG_TAG = "FreeRTOS";
-
-/**
- * Sleep for the specified number of milliseconds.
- * @param[in] ms The period in milliseconds for which to sleep.
- */
-void FreeRTOS::sleep(uint32_t ms) {
-	::vTaskDelay(ms/portTICK_PERIOD_MS);
-} // sleep
-
-
-/**
- * Start a new task.
- * @param[in] task The function pointer to the function to be run in the task.
- * @param[in] taskName A string identifier for the task.
- * @param[in] param An optional parameter to be passed to the started task.
- * @param[in] stackSize An optional paremeter supplying the size of the stack in which to run the task.
- */
-void FreeRTOS::startTask(void task(void*), std::string taskName, void *param, int stackSize) {
-	::xTaskCreate(task, taskName.data(), stackSize, param, 5, NULL);
-} // startTask
-
-
-/**
- * Delete the task.
- * @param[in] pTask An optional handle to the task to be deleted.  If not supplied the calling task will be deleted.
- */
-void FreeRTOS::deleteTask(TaskHandle_t pTask) {
-	::vTaskDelete(pTask);
-} // deleteTask
-
-
-/**
- * Get the time in milliseconds since the %FreeRTOS scheduler started.
- * @return The time in milliseconds since the %FreeRTOS scheduler started.
- */
-uint32_t FreeRTOS::getTimeSinceStart() {
-	return (uint32_t)(xTaskGetTickCount()*portTICK_PERIOD_MS);
-} // getTimeSinceStart
-
-/*
- * 	public:
-		Semaphore(std::string = "<Unknown>");
-		~Semaphore();
-		void give();
-		void take(std::string owner="<Unknown>");
-		void take(uint32_t timeoutMs, std::string owner="<Unknown>");
-	private:
-		SemaphoreHandle_t m_semaphore;
-		std::string m_name;
-		std::string m_owner;
-	};
- *
- */
-
-/**
- * @brief Wait for a semaphore to be released by trying to take it and
- * then releasing it again.
- * @param [in] owner A debug tag.
- * @return The value associated with the semaphore.
- */
-uint32_t FreeRTOS::Semaphore::wait(std::string owner) {
-	ESP_LOGV(LOG_TAG, "Semaphore waiting: %s for %s", toString().c_str(), owner.c_str());
-	xSemaphoreTake(m_semaphore, portMAX_DELAY);
-	m_owner = owner;
-	xSemaphoreGive(m_semaphore);
-	ESP_LOGV(LOG_TAG, "Semaphore released: %s", toString().c_str());
-	m_owner = "<N/A>";
-	return m_value;
-} // wait
-
-FreeRTOS::Semaphore::Semaphore(std::string name) {
-	m_semaphore = xSemaphoreCreateMutex();
-	m_name      = name;
-	m_owner     = "<N/A>";
-	m_value     = 0;
-}
-
-FreeRTOS::Semaphore::~Semaphore() {
-	vSemaphoreDelete(m_semaphore);
-}
-
-
-/**
- * @brief Give a semaphore.
- * The Semaphore is given.
- */
-void FreeRTOS::Semaphore::give() {
-	xSemaphoreGive(m_semaphore);
-	ESP_LOGV(LOG_TAG, "Semaphore giving: %s", toString().c_str());
-	m_owner = "<N/A>";
-} // Semaphore::give
-
-
-/**
- * @brief Give a semaphore.
- * The Semaphore is given with an associated value.
- * @param [in] value The value to associate with the semaphore.
- */
-void FreeRTOS::Semaphore::give(uint32_t value) {
-	m_value = value;
-	give();
-}
-
-
-/**
- * @brief Give a semaphore from an ISR.
- */
-void FreeRTOS::Semaphore::giveFromISR() {
-	BaseType_t higherPriorityTaskWoken;
-	xSemaphoreGiveFromISR(m_semaphore, &higherPriorityTaskWoken);
-} // giveFromISR
-
-
-/**
- * @brief Take a semaphore.
- * Take a semaphore and wait indefinitely.
- */
-void FreeRTOS::Semaphore::take(std::string owner)
-{
-
-	ESP_LOGV(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str());
-	xSemaphoreTake(m_semaphore, portMAX_DELAY);
-	m_owner = owner;
-	ESP_LOGV(LOG_TAG, "Semaphore taken:  %s", toString().c_str());
-} // Semaphore::take
-
-
-/**
- * @brief Take a semaphore.
- * Take a semaphore but return if we haven't obtained it in the given period of milliseconds.
- * @param [in] timeoutMs Timeout in milliseconds.
- */
-void FreeRTOS::Semaphore::take(uint32_t timeoutMs, std::string owner) {
-	ESP_LOGV(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str());
-	m_owner = owner;
-	xSemaphoreTake(m_semaphore, timeoutMs/portTICK_PERIOD_MS);
-	ESP_LOGV(LOG_TAG, "Semaphore taken:  %s", toString().c_str());
-} // Semaphore::take
-
-std::string FreeRTOS::Semaphore::toString() {
-	std::stringstream stringStream;
-	stringStream << "name: "<< m_name << " (0x" << std::hex << std::setfill('0') << (uint32_t)m_semaphore << "), owner: " << m_owner;
-	return stringStream.str();
-}
-
-void FreeRTOS::Semaphore::setName(std::string name) {
-	m_name = name;
-}
-
diff --git a/components/cpp_utils/FreeRTOS.h b/components/cpp_utils/FreeRTOS.h
deleted file mode 100644
index 320f4cc..0000000
--- a/components/cpp_utils/FreeRTOS.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * FreeRTOS.h
- *
- *  Created on: Feb 24, 2017
- *      Author: kolban
- */
-
-#ifndef MAIN_FREERTOS_H_
-#define MAIN_FREERTOS_H_
-#include <stdint.h>
-#include <string>
-
-#include <freertos/FreeRTOS.h>
-#include <freertos/task.h>
-#include <freertos/semphr.h>
-
-
-/**
- * @brief Interface to %FreeRTOS functions.
- */
-class FreeRTOS {
-public:
-	static void sleep(uint32_t ms);
-	static void startTask(void task(void *), std::string taskName, void *param=nullptr, int stackSize = 2048);
-	static void deleteTask(TaskHandle_t pTask = nullptr);
-
-	static uint32_t getTimeSinceStart();
-
-	class Semaphore {
-	public:
-		Semaphore(std::string owner = "<Unknown>");
-		~Semaphore();
-		void give();
-		void giveFromISR();
-		void give(uint32_t value);
-		void setName(std::string name);
-		void take(std::string owner="<Unknown>");
-		void take(uint32_t timeoutMs, std::string owner="<Unknown>");
-		uint32_t wait(std::string owner="<Unknown>");
-		std::string toString();
-	private:
-		SemaphoreHandle_t m_semaphore;
-		std::string m_name;
-		std::string m_owner;
-		uint32_t    m_value;
-	};
-};
-
-#endif /* MAIN_FREERTOS_H_ */
diff --git a/components/cpp_utils/FreeRTOSTimer.cpp b/components/cpp_utils/FreeRTOSTimer.cpp
deleted file mode 100644
index 4baec3e..0000000
--- a/components/cpp_utils/FreeRTOSTimer.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * FreeRTOSTimer.cpp
- *
- *  Created on: Mar 8, 2017
- *      Author: kolban
- */
-
-#include <assert.h>
-#include <map>
-
-#include "FreeRTOSTimer.h"
-
-
-static std::map<void *, FreeRTOSTimer *> timersMap;
-
-void FreeRTOSTimer::internalCallback(TimerHandle_t xTimer) {
-	FreeRTOSTimer *timer = timersMap.at(xTimer);
-	timer->callback(timer);
-}
-
-/**
- * @brief Construct a timer.
- *
- * We construct a timer that will fire after the given period has elapsed.  The period is measured
- * in ticks.  When the timer fires, the callback function is invoked within the scope/context of
- * the timer demon thread.  As such it must **not** block.  Once the timer has fired, if the reload
- * flag is true, then the timer will be automatically restarted.
- *
- * Note that the timer does *not* start immediately.  It starts ticking after the start() method
- * has been called.
- *
- * The signature of the callback function is:
- *
- * @code{.cpp}
- * void callback(FreeRTOSTimer *pTimer) {
- *    // Callback code here ...
- * }
- * @endcode
- *
- * @param [in] name The name of the timer.
- * @param [in] period The period of the timer in ticks.
- * @param [in] reload True if the timer is to restart once fired.
- * @param [in] data Data to be passed to the callback.
- * @param [in] callback Callback function to be fired when the timer expires.
- */
-FreeRTOSTimer::FreeRTOSTimer(
-	char          *name,
-	TickType_t     period,
-	UBaseType_t    reload,
-	void          *data,
-	void         (*callback)(FreeRTOSTimer *pTimer)) {
-	/*
-	 * The callback function to actually be called is saved as member data in the object and
-	 * a static callback function is called.  This will be passed the FreeRTOS timer handle
-	 * which is used as a key in a map to lookup the saved user supplied callback which is then
-	 * actually called.
-	 */
-
-	assert(callback != nullptr);
-	this->period = period;
-	this->callback = callback;
-	timerHandle = ::xTimerCreate(name, period, reload, data, internalCallback);
-
-	// Add the association between the timer handle and this class instance into the map.
-	timersMap.insert(std::make_pair(timerHandle, this));
-} // FreeRTOSTimer
-
-/**
- * @brief Destroy a class instance.
- *
- * The timer is deleted.
- */
-FreeRTOSTimer::~FreeRTOSTimer() {
-	::xTimerDelete(timerHandle, portMAX_DELAY);
-	timersMap.erase(timerHandle);
-}
-
-/**
- * @brief Start the timer ticking.
- */
-void FreeRTOSTimer::start(TickType_t blockTime) {
-	::xTimerStart(timerHandle, blockTime);
-} // start
-
-/**
- * @brief Stop the timer from ticking.
- */
-void FreeRTOSTimer::stop(TickType_t blockTime) {
-	::xTimerStop(timerHandle, blockTime);
-} // stop
-
-/**
- * @brief Reset the timer to the period and start it ticking.
- */
-void FreeRTOSTimer::reset(TickType_t blockTime) {
-	::xTimerReset(timerHandle, blockTime);
-} // reset
-
-
-/**
- * @brief Return the period of the timer.
- *
- * @return The period of the timer.
- */
-TickType_t FreeRTOSTimer::getPeriod() {
-	return period;
-} // getPeriod
-
-
-/**
- * @brief Change the period of the timer.
- *
- * @param [in] newPeriod The new period of the timer in ticks.
- */
-void FreeRTOSTimer::changePeriod(TickType_t newPeriod, TickType_t blockTime) {
-	if (::xTimerChangePeriod(timerHandle, newPeriod, blockTime) == pdPASS) {
-		period = newPeriod;
-	}
-} // changePeriod
-
-
-/**
- * @brief Get the name of the timer.
- *
- * @return The name of the timer.
- */
-const char *FreeRTOSTimer::getName() {
-	return ::pcTimerGetTimerName(timerHandle);
-} // getName
-
-
-/**
- * @brief Get the user supplied data associated with the timer.
- *
- * @return The user supplied data associated with the timer.
- */
-void *FreeRTOSTimer::getData() {
-	return ::pvTimerGetTimerID(timerHandle);
-} // getData
diff --git a/components/cpp_utils/FreeRTOSTimer.h b/components/cpp_utils/FreeRTOSTimer.h
deleted file mode 100644
index 8556ea3..0000000
--- a/components/cpp_utils/FreeRTOSTimer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * FreeRTOSTimer.h
- *
- *  Created on: Mar 8, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_FREERTOSTIMER_H_
-#define COMPONENTS_CPP_UTILS_FREERTOSTIMER_H_
-#include <freertos/FreeRTOS.h>
-#include <freertos/task.h>
-#include <freertos/timers.h>
-/**
- * @brief Wrapper around the %FreeRTOS timer functions.
- */
-class FreeRTOSTimer {
-public:
-	FreeRTOSTimer(char *name, TickType_t period, UBaseType_t reload, void *data, void (*callback)(FreeRTOSTimer *pTimer));
-	virtual ~FreeRTOSTimer();
-	void changePeriod(TickType_t newPeriod, TickType_t blockTime=portMAX_DELAY);
-	void *getData();
-	const char *getName();
-	TickType_t getPeriod();
-	void reset(TickType_t blockTime=portMAX_DELAY);
-	void start(TickType_t blockTime=portMAX_DELAY);
-	void stop(TickType_t blockTime=portMAX_DELAY);
-
-private:
-	TimerHandle_t timerHandle;
-	TickType_t period;
-	void (*callback)(FreeRTOSTimer *pTimer);
-	static void internalCallback(TimerHandle_t xTimer);
-};
-
-#endif /* COMPONENTS_CPP_UTILS_FREERTOSTIMER_H_ */
diff --git a/components/cpp_utils/GPIO.cpp b/components/cpp_utils/GPIO.cpp
deleted file mode 100644
index 4188d30..0000000
--- a/components/cpp_utils/GPIO.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * GPIO.cpp
- *
- *  Created on: Feb 28, 2017
- *      Author: kolban
- */
-
-#include "GPIO.h"
-#include <driver/gpio.h>
-#include "sdkconfig.h"
-#include <esp_log.h>
-#include "GeneralUtils.h"
-
-static const char* LOG_TAG = "GPIO";
-
-static bool g_isrServiceInstalled = false;
-
-/**
- * @brief Add an ISR handler to the pin.
- * @param [in] pin The pin to have the ISR associated with it.
- * @param [in] handler The function to be invoked when the interrupt is detected.
- * @param [in] pArgs Optional arguments to pass to the handler.
- */
-void ESP32CPP::GPIO::addISRHandler(
-	gpio_num_t pin,
-	gpio_isr_t handler,
-	void*      pArgs) {
-
-	ESP_LOGD(LOG_TAG, ">> addISRHandler:  pin=%d", pin);
-
-	// If we have not yet installed the ISR service handler, install it now.
-	if (g_isrServiceInstalled == false) {
-		ESP_LOGD(LOG_TAG, "Installing the global ISR service");
-		esp_err_t errRc = ::gpio_install_isr_service(0);
-		if (errRc != ESP_OK) {
-			ESP_LOGE(LOG_TAG, "<< gpio_install_isr_service: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-			return;
-		}
-		g_isrServiceInstalled = true;
-	}
-
-	esp_err_t errRc = ::gpio_isr_handler_add(pin, handler, pArgs);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< gpio_isr_handler_add: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
-		return;
-	}
-
-	ESP_LOGD(LOG_TAG, "<< addISRHandler");
-} // addISRHandler
-
-
-/**
- * @brief Set the pin high.
- *
- * Ensure that the pin is set to be output prior to calling this method.
- *
- * @param [in] pin The pin to be set high.
- * @return N/A.
- */
-void ESP32CPP::GPIO::high(gpio_num_t pin) {
-	write(pin, true);
-} // high
-
-
-/**
- * @brief Determine if the pin is a valid pin for an ESP32 (i.e. is it in range).
- *
- * @param [in] pin The pin number to validate.
- * @return The value of true if the pin is valid and false otherwise.
- */
-bool ESP32CPP::GPIO::inRange(gpio_num_t pin) {
-	if (pin>=0 && pin<=39) {
-		return true;
-	}
-	return false;
-} // inRange
-
-
-/**
- * @brief Disable interrupts on the named pin.
- * @param [in] pin The pin to disable interrupts upon.
- * @return N/A.
- */
-void ESP32CPP::GPIO::interruptDisable(gpio_num_t pin) {
-	esp_err_t rc = ::gpio_intr_disable(pin);
-	if (rc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "interruptDisable: %d", rc);
-	}
-} // interruptDisable
-
-
-/**
- * @brief Enable interrupts on the named pin.
- * @param [in] pin The pin to enable interrupts upon.
- * @return N/A.
- */
-void ESP32CPP::GPIO::interruptEnable(gpio_num_t pin) {
-	esp_err_t rc = ::gpio_intr_enable(pin);
-	if (rc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "interruptEnable: %d", rc);
-	}
-} // interruptEnable
-
-
-/**
- * @brief Set the pin low.
- *
- * Ensure that the pin is set to be output prior to calling this method.
- *
- * @param [in] pin The pin to be set low.
- * @return N/A.
- */
-void ESP32CPP::GPIO::low(gpio_num_t pin) {
-	write(pin, false);
-} // low
-
-
-/**
- * @brief Read a value from the given pin.
- *
- * Ensure the pin is set as input before calling this method.
- * @param [in] pin The pin to read from.
- * @return True if the pin is high, false if the pin is low.
- */
-bool ESP32CPP::GPIO::read(gpio_num_t pin) {
-	return ::gpio_get_level(pin);
-} // read
-
-
-/**
- * @brief Set the pin as input.
- *
- * Set the direction of the pin as input.
- * @param [in] pin The pin to set as input.
- * @return N/A.
- */
-void ESP32CPP::GPIO::setInput(gpio_num_t pin) {
-	::gpio_set_direction(pin, GPIO_MODE_INPUT);
-} // setInput
-
-
-/**
- * @brief Set the interrupt type.
- * The type of interrupt can be one of:
- *
- * * GPIO_INTR_ANYEDGE
- * * GPIO_INTR_DISABLE
- * * GPIO_INTR_NEGEDGE
- * * GPIO_INTR_POSEDGE
- * * GPIO_INTR_LOW_LEVEL
- * * GPIO_INTR_HIGH_LEVEL
- *
- * @param [in] pin The pin to set the interrupt upon.
- * @param [in] intrType The type of interrupt.
- * @return N/A.
- */
-void ESP32CPP::GPIO::setInterruptType(
-		gpio_num_t pin,
-		gpio_int_type_t intrType) {
-	esp_err_t rc = ::gpio_set_intr_type(pin, intrType);
-	if (rc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "setInterruptType: %d", rc);
-	}
-
-} // setInterruptType
-
-
-/**
- * @brief Set the pin as output.
- *
- * Set the direction of the pin as output.  Note that pins 34 through 39 are input only and can **not** be
- * set as output.
- * @param [in] pin The pin to set as output.
- * @return N/A.
- */
-void ESP32CPP::GPIO::setOutput(gpio_num_t pin) {
-	::gpio_set_direction(pin, GPIO_MODE_OUTPUT);
-} // setOutput
-
-
-/**
- * @brief Write a value to the given pin.
- *
- * Ensure that the pin is set as output before calling this method.
- * @param [in] pin The gpio pin to change.
- * @param [out] value The value to be written to the pin.
- * @return N/A.
- */
-void ESP32CPP::GPIO::write(gpio_num_t pin, bool value) {
-	//ESP_LOGD(LOG_TAG, ">> write: pin: %d, value: %d", pin, value);
-	esp_err_t errRc = ::gpio_set_level(pin, value);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(LOG_TAG, "<< gpio_set_level: pin=%d, rc=%d %s", pin, errRc, GeneralUtils::errorToString(errRc));
-	}
-} // write
-
-
-/**
- * @brief Write up to 8 bits of data to a set of pins.
- * @param [in] pins An array of pins to set their values.
- * @param [in] value The data value to write.
- * @param [in] bits The number of bits to write.
- */
-void ESP32CPP::GPIO::writeByte(gpio_num_t pins[], uint8_t value, int bits) {
-	ESP_LOGD(LOG_TAG, ">> writeByte: value: %.2x, bits: %d", value, bits);
-	for (int i=0; i<bits; i++) {
-		//ESP_LOGD(LOG_TAG, "i=%d, bits=%d", i, bits);
-		write(pins[i], (value & (1<<i)) != 0);
-	}
-	ESP_LOGD(LOG_TAG, "<< writeByte");
-} // writeByte
diff --git a/components/cpp_utils/GPIO.h b/components/cpp_utils/GPIO.h
deleted file mode 100644
index 76642cb..0000000
--- a/components/cpp_utils/GPIO.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * GPIO.h
- *
- *  Created on: Feb 28, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_GPIO_H_
-#define COMPONENTS_CPP_UTILS_GPIO_H_
-#include <driver/gpio.h>
-namespace ESP32CPP
-{
-	/**
-	 * @brief Interface to %GPIO functions.
-	 *
-	 * The %GPIO functions encapsulate the %GPIO access.  The GPIOs available to us are
-	 * 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,21,23,25,26,27,32,33,34,35,36,37,38,39.
-	 *
-	 * The GPIOs of 34,35,36,37,38 and 39 are input only.
-	 *
-	 * Note that we must not use `int` values for the pin numbers but instead use the `gpio_num_t`.  There
-	 * are constants defined for these of the form `GPIO_NUM_xx`.
-	 *
-	 * To toggle a pin we might code:
-	 *
-	 * @code{.cpp}
-	 * ESP32CPP::GPIO::setOutput(pin);
-	 * ESP32CPP::GPIO::high(pin);
-	 * ESP32CPP::GPIO::low(pin);
-	 * @endcode
-	 */
-	class GPIO {
-	public:
-		static void addISRHandler(gpio_num_t pin, gpio_isr_t handler, void* pArgs);
-		static void high(gpio_num_t pin);
-		static void interruptDisable(gpio_num_t pin);
-		static void interruptEnable(gpio_num_t pin);
-		static bool inRange(gpio_num_t pin);
-		static void low(gpio_num_t pin);
-		static bool read(gpio_num_t pin);
-		static void setInput(gpio_num_t pin);
-		static void setInterruptType(gpio_num_t pin, gpio_int_type_t intrType);
-		static void setOutput(gpio_num_t pin);
-		static void write(gpio_num_t pin, bool value);
-		static void writeByte(gpio_num_t pins[], uint8_t value, int bits);
-	}; // End GPIO
-} // End ESP32CPP namespace
-#endif /* COMPONENTS_CPP_UTILS_GPIO_H_ */
diff --git a/components/cpp_utils/GeneralUtils.cpp b/components/cpp_utils/GeneralUtils.cpp
deleted file mode 100644
index 87c55bd..0000000
--- a/components/cpp_utils/GeneralUtils.cpp
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * GeneralUtils.cpp
- *
- *  Created on: May 20, 2017
- *      Author: kolban
- */
-
-#include "GeneralUtils.h"
-#include <esp_log.h>
-#include <string.h>
-#include <stdio.h>
-#include <string>
-#include <sstream>
-#include <iomanip>
-#include <FreeRTOS.h>
-#include <esp_err.h>
-#include <nvs.h>
-#include <esp_wifi.h>
-
-static const char* LOG_TAG = "GeneralUtils";
-
-static const char kBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-    "abcdefghijklmnopqrstuvwxyz"
-    "0123456789+/";
-
-GeneralUtils::GeneralUtils() {
-	// TODO Auto-generated constructor stub
-
-}
-
-GeneralUtils::~GeneralUtils() {
-	// TODO Auto-generated destructor stub
-}
-
-static int base64EncodedLength(size_t length) {
-	return (length + 2 - ((length + 2) % 3)) / 3 * 4;
-} // base64EncodedLength
-
-
-static int base64EncodedLength(const std::string &in) {
-	return base64EncodedLength(in.length());
-} // base64EncodedLength
-
-
-static void a3_to_a4(unsigned char * a4, unsigned char * a3) {
-	a4[0] = (a3[0] & 0xfc) >> 2;
-	a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
-	a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
-	a4[3] = (a3[2] & 0x3f);
-} // a3_to_a4
-
-
-static void a4_to_a3(unsigned char * a3, unsigned char * a4) {
-	a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
-	a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
-	a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
-} // a4_to_a3
-
-
-/**
- * @brief Encode a string into base 64.
- * @param [in] in
- * @param [out] out
- */
-bool GeneralUtils::base64Encode(const std::string &in, std::string *out) {
-	int i = 0, j = 0;
-	size_t enc_len = 0;
-	unsigned char a3[3];
-	unsigned char a4[4];
-
-	out->resize(base64EncodedLength(in));
-
-	int input_len = in.size();
-	std::string::const_iterator input = in.begin();
-
-	while (input_len--) {
-		a3[i++] = *(input++);
-		if (i == 3) {
-			a3_to_a4(a4, a3);
-
-			for (i = 0; i < 4; i++) {
-				(*out)[enc_len++] = kBase64Alphabet[a4[i]];
-			}
-
-			i = 0;
-		}
-	}
-
-	if (i) {
-		for (j = i; j < 3; j++) {
-			a3[j] = '\0';
-		}
-
-		a3_to_a4(a4, a3);
-
-		for (j = 0; j < i + 1; j++) {
-			(*out)[enc_len++] = kBase64Alphabet[a4[j]];
-		}
-
-		while ((i++ < 3)) {
-			(*out)[enc_len++] = '=';
-		}
-	}
-
-	return (enc_len == out->size());
-} // base64Encode
-
-
-static int DecodedLength(const std::string &in) {
-	int numEq = 0;
-	int n = in.size();
-
-	for (std::string::const_reverse_iterator it = in.rbegin(); *it == '='; ++it) {
-		++numEq;
-	}
-	return ((6 * n) / 8) - numEq;
-} // DecodedLength
-
-
-static unsigned char b64_lookup(unsigned char c) {
-	if(c >='A' && c <='Z') return c - 'A';
-	if(c >='a' && c <='z') return c - 71;
-	if(c >='0' && c <='9') return c + 4;
-	if(c == '+') return 62;
-	if(c == '/') return 63;
-	return 255;
-}; // b64_lookup
-
-
-/**
- * @brief Decode a chunk of data that is base64 encoded.
- * @param [in] in The string to be decoded.
- * @param [out] out The resulting data.
- */
-bool GeneralUtils::base64Decode(const std::string &in, std::string *out) {
-	int i = 0, j = 0;
-	size_t dec_len = 0;
-	unsigned char a3[3];
-	unsigned char a4[4];
-
-	int input_len = in.size();
-	std::string::const_iterator input = in.begin();
-
-	out->resize(DecodedLength(in));
-
-	while (input_len--) {
-		if (*input == '=') {
-			break;
-		}
-
-		a4[i++] = *(input++);
-		if (i == 4) {
-			for (i = 0; i <4; i++) {
-				a4[i] = b64_lookup(a4[i]);
-			}
-
-			a4_to_a3(a3,a4);
-
-			for (i = 0; i < 3; i++) {
-				(*out)[dec_len++] = a3[i];
-			}
-
-			i = 0;
-		}
-	}
-
-	if (i) {
-		for (j = i; j < 4; j++) {
-			a4[j] = '\0';
-		}
-
-		for (j = 0; j < 4; j++) {
-			a4[j] = b64_lookup(a4[j]);
-		}
-
-		a4_to_a3(a3,a4);
-
-		for (j = 0; j < i - 1; j++) {
-			(*out)[dec_len++] = a3[j];
-		}
-	}
-
-	return (dec_len == out->size());
- } // base64Decode
-
-/*
-void GeneralUtils::hexDump(uint8_t* pData, uint32_t length) {
-	uint32_t index=0;
-	std::stringstream ascii;
-	std::stringstream hex;
-	char asciiBuf[80];
-	char hexBuf[80];
-	hex.str("");
-	ascii.str("");
-	while(index < length) {
-		hex << std::setfill('0') << std::setw(2) << std::hex << (int)pData[index] << ' ';
-		if (std::isprint(pData[index])) {
-			ascii << pData[index];
-		} else {
-			ascii << '.';
-		}
-		index++;
-		if (index % 16 == 0) {
-			strcpy(hexBuf, hex.str().c_str());
-			strcpy(asciiBuf, ascii.str().c_str());
-			ESP_LOGD(tag, "%s %s", hexBuf, asciiBuf);
-			hex.str("");
-			ascii.str("");
-		}
-	}
-	if (index %16 != 0) {
-		while(index % 16 != 0) {
-			hex << "   ";
-			index++;
-		}
-		strcpy(hexBuf, hex.str().c_str());
-		strcpy(asciiBuf, ascii.str().c_str());
-		ESP_LOGD(tag, "%s %s", hexBuf, asciiBuf);
-		//ESP_LOGD(tag, "%s %s", hex.str().c_str(), ascii.str().c_str());
-	}
-	FreeRTOS::sleep(1000);
-}
-*/
-
-/*
-void GeneralUtils::hexDump(uint8_t* pData, uint32_t length) {
-	uint32_t index=0;
-	static std::stringstream ascii;
-	static std::stringstream hex;
-	hex.str("");
-	ascii.str("");
-	while(index < length) {
-		hex << std::setfill('0') << std::setw(2) << std::hex << (int)pData[index] << ' ';
-		if (std::isprint(pData[index])) {
-			ascii << pData[index];
-		} else {
-			ascii << '.';
-		}
-		index++;
-		if (index % 16 == 0) {
-			ESP_LOGD(tag, "%s %s", hex.str().c_str(), ascii.str().c_str());
-			hex.str("");
-			ascii.str("");
-		}
-	}
-	if (index %16 != 0) {
-		while(index % 16 != 0) {
-			hex << "   ";
-			index++;
-		}
-		ESP_LOGD(tag, "%s %s", hex.str().c_str(), ascii.str().c_str());
-	}
-	FreeRTOS::sleep(1000);
-}
-*/
-
-/**
- * @brief Dump a representation of binary data to the console.
- *
- * @param [in] pData Pointer to the start of data to be logged.
- * @param [in] length Length of the data (in bytes) to be logged.
- * @return N/A.
- */
-void GeneralUtils::hexDump(const uint8_t* pData, uint32_t length) {
-	char ascii[80];
-	char hex[80];
-	char tempBuf[80];
-	uint32_t lineNumber = 0;
-
-	ESP_LOGD(LOG_TAG, "     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  ----------------");
-	strcpy(ascii, "");
-	strcpy(hex, "");
-	uint32_t index=0;
-	while(index < length) {
-		sprintf(tempBuf, "%.2x ", pData[index]);
-		strcat(hex, tempBuf);
-		if (isprint(pData[index])) {
-			sprintf(tempBuf, "%c", pData[index]);
-		} else {
-			sprintf(tempBuf, ".");
-		}
-		strcat(ascii, tempBuf);
-		index++;
-		if (index % 16 == 0) {
-			ESP_LOGD(LOG_TAG, "%.4x %s %s", lineNumber*16, hex, ascii);
-			strcpy(ascii, "");
-			strcpy(hex, "");
-			lineNumber++;
-		}
-	}
-	if (index %16 != 0) {
-		while(index % 16 != 0) {
-			strcat(hex, "   ");
-			index++;
-		}
-		ESP_LOGD(LOG_TAG, "%.4x %s %s", lineNumber*16, hex, ascii);
-	}
-} // hexDump
-
-/**
- * @brief Convert an IP address to string.
- * @param ip The 4 byte IP address.
- * @return A string representation of the IP address.
- */
-std::string GeneralUtils::ipToString(uint8_t *ip) {
-	std::stringstream s;
-	s << (int)ip[0] << '.' << (int)ip[1] << '.' << (int)ip[2] << '.' << (int)ip[3];
-	return s.str();
-} // ipToString
-
-
-/**
- * @brief Convert an ESP error code to a string.
- * @param [in] errCode The errCode to be converted.
- * @return A string representation of the error code.
- */
-const char* GeneralUtils::errorToString(esp_err_t errCode) {
-	switch(errCode) {
-		case ESP_OK:
-			return "OK";
-		case ESP_FAIL:
-			return "Fail";
-		case ESP_ERR_NO_MEM:
-			return "No memory";
-		case ESP_ERR_INVALID_ARG:
-			return "Invalid argument";
-		case ESP_ERR_INVALID_SIZE:
-			return "Invalid state";
-		case ESP_ERR_INVALID_STATE:
-			return "Invalid state";
-		case ESP_ERR_NOT_FOUND:
-			return "Not found";
-		case ESP_ERR_NOT_SUPPORTED:
-			return "Not supported";
-		case ESP_ERR_TIMEOUT:
-			return "Timeout";
-		case ESP_ERR_NVS_NOT_INITIALIZED:
-			return "ESP_ERR_NVS_NOT_INITIALIZED";
-		case ESP_ERR_NVS_NOT_FOUND:
-			return "ESP_ERR_NVS_NOT_FOUND";
-		case ESP_ERR_NVS_TYPE_MISMATCH:
-			return "ESP_ERR_NVS_TYPE_MISMATCH";
-		case ESP_ERR_NVS_READ_ONLY:
-			return "ESP_ERR_NVS_READ_ONLY";
-		case ESP_ERR_NVS_NOT_ENOUGH_SPACE:
-			return "ESP_ERR_NVS_NOT_ENOUGH_SPACE";
-		case ESP_ERR_NVS_INVALID_NAME:
-			return "ESP_ERR_NVS_INVALID_NAME";
-		case ESP_ERR_NVS_INVALID_HANDLE:
-			return "ESP_ERR_NVS_INVALID_HANDLE";
-		case ESP_ERR_NVS_REMOVE_FAILED:
-			return "ESP_ERR_NVS_REMOVE_FAILED";
-		case ESP_ERR_NVS_KEY_TOO_LONG:
-			return "ESP_ERR_NVS_KEY_TOO_LONG";
-		case ESP_ERR_NVS_PAGE_FULL:
-			return "ESP_ERR_NVS_PAGE_FULL";
-		case ESP_ERR_NVS_INVALID_STATE:
-			return "ESP_ERR_NVS_INVALID_STATE";
-		case ESP_ERR_NVS_INVALID_LENGTH:
-			return "ESP_ERR_NVS_INVALID_LENGTH";
-		case ESP_ERR_WIFI_NOT_INIT:
-			return "ESP_ERR_WIFI_NOT_INIT";
-		//case ESP_ERR_WIFI_NOT_START:
-		//	return "ESP_ERR_WIFI_NOT_START";
-		case ESP_ERR_WIFI_IF:
-			return "ESP_ERR_WIFI_IF";
-		case ESP_ERR_WIFI_MODE:
-			return "ESP_ERR_WIFI_MODE";
-		case ESP_ERR_WIFI_STATE:
-			return "ESP_ERR_WIFI_STATE";
-		case ESP_ERR_WIFI_CONN:
-			return "ESP_ERR_WIFI_CONN";
-		case ESP_ERR_WIFI_NVS:
-			return "ESP_ERR_WIFI_NVS";
-		case ESP_ERR_WIFI_MAC:
-			return "ESP_ERR_WIFI_MAC";
-		case ESP_ERR_WIFI_SSID:
-			return "ESP_ERR_WIFI_SSID";
-		case ESP_ERR_WIFI_PASSWORD:
-			return "ESP_ERR_WIFI_PASSWORD";
-		case ESP_ERR_WIFI_TIMEOUT:
-			return "ESP_ERR_WIFI_TIMEOUT";
-		case ESP_ERR_WIFI_WAKE_FAIL:
-			return "ESP_ERR_WIFI_WAKE_FAIL";
-		}
-	return "Unknown ESP_ERR error";
-} // errorToString
-
diff --git a/components/cpp_utils/GeneralUtils.h b/components/cpp_utils/GeneralUtils.h
deleted file mode 100644
index ca38c75..0000000
--- a/components/cpp_utils/GeneralUtils.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * GeneralUtils.h
- *
- *  Created on: May 20, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_GENERALUTILS_H_
-#define COMPONENTS_CPP_UTILS_GENERALUTILS_H_
-#include <stdint.h>
-#include <string>
-#include <esp_err.h>
-
-/**
- * @brief General utilities.
- */
-class GeneralUtils {
-public:
-	GeneralUtils();
-	virtual ~GeneralUtils();
-	static void hexDump(const uint8_t *pData, uint32_t length);
-	static std::string ipToString(uint8_t *ip);
-	static bool base64Encode(const std::string &in, std::string *out);
-	static bool base64Decode(const std::string &in, std::string *out);
-	static const char *errorToString(esp_err_t errCode);
-};
-
-#endif /* COMPONENTS_CPP_UTILS_GENERALUTILS_H_ */
diff --git a/components/cpp_utils/HttpParser.cpp b/components/cpp_utils/HttpParser.cpp
deleted file mode 100644
index 9137431..0000000
--- a/components/cpp_utils/HttpParser.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * HttpParser.cpp
- *
- *  Created on: Aug 28, 2017
- *      Author: kolban
- */
-
-#include <string>
-#include <iostream>
-#include <cstdlib>
-#include "HttpParser.h"
-#include "HttpRequest.h"
-
-#include <esp_log.h>
-/**
- * RFC7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
- * RFC3986 - URI
- *
- * <Request Line>
- * <Header>
- * <Header>
- * ...
- * <Header>
- * <CRLF>
- * <BODY>
- *
- * Example:
- * GET /hello.txt HTTP/1.1
- */
-
-static const char* LOG_TAG = "HttpParser";
-
-static std::string lineTerminator = "\r\n";
-
-
-/**
- * @brief Remove white space from a string.
- */
-static std::string trim(const std::string& str)
-{
-    size_t first = str.find_first_not_of(' ');
-    if (std::string::npos == first)
-    {
-        return str;
-    }
-    size_t last = str.find_last_not_of(' ');
-    return str.substr(first, (last - first + 1));
-} // trim
-
-
-/**
- * @brief Parse an incoming line of text until we reach a delimiter.
- * @param [in/out] it The current iterator in the text input.
- * @param [in] str The string we are parsing.
- * @param [in] token The token delimiter.
- */
-static std::string toStringToken(std::string::iterator &it, std::string &str, std::string &token) {
-	std::string ret;
-	std::string part;
-	auto itToken = token.begin();
-	for(; it != str.end(); ++it) {
-		if ((*it) == (*itToken)) {
-			part += (*itToken);
-			++itToken;
-			if (itToken == token.end()) {
-				++it;
-				break;
-			}
-		} else {
-			if (part.empty()) {
-				ret += part;
-				part.clear();
-				itToken = token.begin();
-			}
-			ret += *it;
-		}
-	} // for
-	return ret;
-} // toStringToken
-
-
-/**
- * @brief Parse a string until the given token is found.
- * @param [in] it The current iterator.
- * @param [in] str The string being parsed.
- * @param [in] token The token terminating the parse.
- * @return The parsed string token.
- */
-static std::string toCharToken(std::string::iterator &it, std::string &str, char token) {
-	std::string ret;
-	for(; it != str.end(); ++it) {
-		if ((*it) == token) {
-			++it;
-			break;
-		}
-		ret += *it;
-	}
-	return ret;
-} // toCharToken
-
-
-/**
- * @brief Parse a header line.
- * An HTTP Header is of the form:
- *
- * Name":" Value
- *
- * We parse this and return a pair.
- * @param [in] line The line of text to parse.
- * @return A pair of the form name/value.
- */
-std::pair<std::string, std::string> parseHeader(std::string &line) {
-	auto it    = line.begin();
-	auto name  = toCharToken(it, line, ':');
-	auto value = trim(toStringToken(it, line, lineTerminator));
-	return std::pair<std::string, std::string>(name, value);
-} // parseHeader
-
-
-HttpParser::HttpParser() {
-	// TODO Auto-generated constructor stub
-
-}
-
-HttpParser::~HttpParser() {
-	// TODO Auto-generated destructor stub
-}
-
-
-/**
- * @brief Dump the outcome of the parse.
- *
- */
-void HttpParser::dump() {
-	ESP_LOGD(LOG_TAG, "Method: %s, URL: \"%s\", Version: %s", m_method.c_str(), m_url.c_str(), m_version.c_str());
-	auto it2 = m_headers.begin();
-	for (; it2 != m_headers.end(); ++it2) {
-		ESP_LOGD(LOG_TAG, "name=\"%s\", value=\"%s\"", it2->first.c_str(), it2->second.c_str());
-	}
-	ESP_LOGD(LOG_TAG, "Body: \"%s\"", m_body.c_str());
-} // dump
-
-
-std::string HttpParser::getBody() {
-	return m_body;
-}
-
-
-std::string HttpParser::getHeader(const std::string& name) {
-	if (!hasHeader(name)) {
-		return "";
-	}
-	return m_headers.at(name);
-}
-
-
-std::map<std::string, std::string> HttpParser::getHeaders() {
-	return m_headers;
-}
-
-
-std::string HttpParser::getMethod() {
-	return m_method;
-} // getMethod
-
-
-std::string HttpParser::getURL() {
-	return m_url;
-} // getURL
-
-
-std::string HttpParser::getVersion() {
-	return m_version;
-} // getVersion
-
-
-/**
- * @brief Determine if we have a header of the given name.
- * @param [in] name The name of the header to find.
- * @return True if the header is present and false otherwise.
- */
-bool HttpParser::hasHeader(const std::string& name) {
-	return m_headers.find(name) != m_headers.end();
-} // hasHeader
-
-
-/**
- * @brief Parse socket data.
- * @param [in] s The socket from which to retrieve data.
- */
-void HttpParser::parse(Socket s) {
-	std::string line;
-	line = s.readToDelim(lineTerminator);
-	parseRequestLine(line);
-	line = s.readToDelim(lineTerminator);
-	while(!line.empty()) {
-		m_headers.insert(parseHeader(line));
-		line = s.readToDelim(lineTerminator);
-	}
-	// Only PUT and POST requests have a body
-	if (getMethod() != "POST" && getMethod() != "PUT") {
-		return;
-	}
-
-	// We have now parsed up to and including the separator ... we are now at the point where we
-	// want to read the body.  There are two stories here.  The first is that we know the exact length
-	// of the body or we read until we can't read anymore.
-	if (hasHeader(HttpRequest::HTTP_HEADER_CONTENT_LENGTH)) {
-		std::string val = getHeader(HttpRequest::HTTP_HEADER_CONTENT_LENGTH);
-		int length = std::atoi(val.c_str());
-		uint8_t data[length];
-		s.receive_cpp(data, length, true);
-		m_body = std::string((char *)data, length);
-	} else {
-		uint8_t data[512];
-		int rc = s.receive_cpp(data, sizeof(data));
-		m_body = std::string((char *)data, rc);
-	}
-	ESP_LOGD(LOG_TAG, "Size of body: %d", m_body.length());
-} // parse
-
-
-/**
- * @brief Parse a string message.
- * @param [in] message The HTTP message to parse.
- */
-/*
-void HttpParser::parse(std::string message) {
-	auto it = message.begin();
-	auto line = toStringToken(it, message, lineTerminator);
-	parseRequestLine(line);
-
-	line = toStringToken(it, message, lineTerminator);
-	while(!line.empty()) {
-		//ESP_LOGD(LOG_TAG, "Header: \"%s\"", line.c_str());
-		m_headers.insert(parseHeader(line));
-		line = toStringToken(it, message, lineTerminator);
-	}
-
-	m_body = message.substr(std::distance(message.begin(), it));
-} // parse
-*/
-
-/**
- * @brief Parse A request line.
- * @param [in] line The request line to parse.
- */
-// A request Line is built from:
-// <method> <sp> <request-target> <sp> <HTTP-version>
-//
-void HttpParser::parseRequestLine(std::string &line) {
-	ESP_LOGD(LOG_TAG, ">> parseRequestLine: %s [%d]", line.c_str(), line.length());
-	std::string::iterator it = line.begin();
-
-	// Get the method
-	m_method = toCharToken(it, line, ' ');
-
-	// Get the url
-	m_url = toCharToken(it, line, ' ');
-
-	// Get the version
-	m_version = toCharToken(it, line, ' ');
-} // parseRequestLine
diff --git a/components/cpp_utils/HttpParser.h b/components/cpp_utils/HttpParser.h
deleted file mode 100644
index 7719116..0000000
--- a/components/cpp_utils/HttpParser.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * HttpParser.h
- *
- *  Created on: Aug 28, 2017
- *      Author: kolban
- */
-
-#ifndef CPP_UTILS_HTTPPARSER_H_
-#define CPP_UTILS_HTTPPARSER_H_
-#include <string>
-#include <map>
-#include "Socket.h"
-
-class HttpParser {
-private:
-	std::string m_method;
-	std::string m_url;
-	std::string m_version;
-	std::string m_body;
-	std::map<std::string, std::string> m_headers;
-	void dump();
-	void parseRequestLine(std::string &line);
-public:
-	HttpParser();
-	virtual ~HttpParser();
-	std::string getBody();
-	std::string getHeader(const std::string& name);
-	std::map<std::string, std::string> getHeaders();
-	std::string getMethod();
-	std::string getURL();
-	std::string getVersion();
-	bool hasHeader(const std::string& name);
-	void parse(std::string message);
-	void parse(Socket s);
-};
-
-#endif /* CPP_UTILS_HTTPPARSER_H_ */
diff --git a/components/cpp_utils/HttpRequest.cpp b/components/cpp_utils/HttpRequest.cpp
deleted file mode 100644
index 265d4ef..0000000
--- a/components/cpp_utils/HttpRequest.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * HTTPRequest.cpp
- *
- *  Created on: Aug 30, 2017
- *      Author: kolban
- */
-
-/*
- * A Websocket hand shake request looks like:
- *
- * GET /chat HTTP/1.1
- * Host: server.example.com
- * Upgrade: websocket
- * Connection: Upgrade
- * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
- * Origin: http://example.com
- * Sec-WebSocket-Protocol: chat, superchat
- * Sec-WebSocket-Version: 13
- *
- *
- * A corresponding hand shake response looks like:
- *
- * HTTP/1.1 101 Switching Protocols
- * Upgrade: websocket
- * Connection: Upgrade
- * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
- * Sec-WebSocket-Protocol: chat
- *
- * The server key returned in Sec-WebSocket-Accept is the value of Sec-WebSocket-Key passed in the
- * request concatenated with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" and then take the SHA-1 hash
- * of the result to give a 20 byte value which is then base64() encoded.
- */
-
-#include <sstream>
-#include <vector>
-#include "HttpResponse.h"
-#include "HttpRequest.h"
-#include "GeneralUtils.h"
-
-#include <esp_log.h>
-#include <hwcrypto/sha.h>
-
-
-static const char* LOG_TAG="HttpRequest";
-
-//static std::string lineTerminator = "\r\n";
-
-const std::string HttpRequest::HTTP_HEADER_ACCEPT         = "Accept";
-const std::string HttpRequest::HTTP_HEADER_ALLOW          = "Allow";
-const std::string HttpRequest::HTTP_HEADER_CONNECTION     = "Connection";
-const std::string HttpRequest::HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
-const std::string HttpRequest::HTTP_HEADER_CONTENT_TYPE   = "Content-Type";
-const std::string HttpRequest::HTTP_HEADER_COOKIE         = "Cookie";
-const std::string HttpRequest::HTTP_HEADER_HOST           = "Host";
-const std::string HttpRequest::HTTP_HEADER_LAST_MODIFIED  = "Last-Modified";
-const std::string HttpRequest::HTTP_HEADER_ORIGIN         = "Origin";
-const std::string HttpRequest::HTTP_HEADER_SEC_WEBSOCKET_ACCEPT   = "Sec-WebSocket-Accept";
-const std::string HttpRequest::HTTP_HEADER_SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol";
-const std::string HttpRequest::HTTP_HEADER_SEC_WEBSOCKET_KEY      = "Sec-WebSocket-Key";
-const std::string HttpRequest::HTTP_HEADER_SEC_WEBSOCKET_VERSION  = "Sec-WebSocket-Version";
-const std::string HttpRequest::HTTP_HEADER_UPGRADE        = "Upgrade";
-const std::string HttpRequest::HTTP_HEADER_USER_AGENT     = "User-Agent";
-
-const std::string HttpRequest::HTTP_METHOD_CONNECT = "CONNECT";
-const std::string HttpRequest::HTTP_METHOD_DELETE  = "DELETE";
-const std::string HttpRequest::HTTP_METHOD_GET     = "GET";
-const std::string HttpRequest::HTTP_METHOD_HEAD    = "HEAD";
-const std::string HttpRequest::HTTP_METHOD_OPTIONS = "OPTIONS";
-const std::string HttpRequest::HTTP_METHOD_PATCH   = "PATCH";
-const std::string HttpRequest::HTTP_METHOD_POST    = "POST";
-const std::string HttpRequest::HTTP_METHOD_PUT     = "PUT";
-
-
-
-
-std::string buildResponseHash(std::string requestKey) {
-	std::string newKey = requestKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
-	uint8_t shaData[20];
-	esp_sha(SHA1, (uint8_t*)newKey.data(), newKey.length(), shaData);
-	//GeneralUtils::hexDump(shaData, 20);
-	std::string retStr;
-	GeneralUtils::base64Encode(std::string((char*)shaData, sizeof(shaData)), &retStr);
-	return retStr;
-}
-
-
-HttpRequest::HttpRequest(Socket clientSocket) {
-	m_clientSocket = clientSocket;
-	m_status       = 0;
-	m_pWebSocket   = nullptr;
-
-	m_parser.parse(clientSocket); // Parse the socket stream to build the HTTP data.
-
-	// Is this a Web Socket?
-	if (getMethod() == HTTP_METHOD_GET &&
-			!getHeader(HTTP_HEADER_HOST).empty() &&
-			getHeader(HTTP_HEADER_UPGRADE) == "websocket" &&
-			getHeader(HTTP_HEADER_CONNECTION) == "Upgrade" &&
-			!getHeader(HTTP_HEADER_SEC_WEBSOCKET_KEY).empty() &&
-			!getHeader(HTTP_HEADER_SEC_WEBSOCKET_VERSION).empty()) {
-		ESP_LOGD(LOG_TAG, "Websocket detected!");
-		// do something
-		// Process the web socket request
-
-		// Send the response HTTP message to switch to being a Web Socket
-		HttpResponse response(this);
-
-		response.setStatus(HttpResponse::HTTP_STATUS_SWITCHING_PROTOCOL, "Switching Protocols");
-		response.addHeader(HTTP_HEADER_UPGRADE, "websocket");
-		response.addHeader(HTTP_HEADER_CONNECTION, "Upgrade");
-		response.addHeader(HTTP_HEADER_SEC_WEBSOCKET_ACCEPT,
-			buildResponseHash(getHeader(HTTP_HEADER_SEC_WEBSOCKET_KEY)));
-		response.sendData("");
-		m_pWebSocket = new WebSocket(clientSocket);
-	} else {
-		ESP_LOGD(LOG_TAG, "Not a Websocket");
-	}
-} // HttpRequest
-
-
-HttpRequest::~HttpRequest() {
-} // ~HttpRequest
-
-
-void HttpRequest::close() {
-	m_clientSocket.close_cpp();
-} // close_cpp
-
-
-void HttpRequest::dump() {
-	ESP_LOGD(LOG_TAG, "Method: %s, URL: \"%s\", Version: %s", getMethod().c_str(), getPath().c_str(), getVersion().c_str());
-	auto headers = getHeaders();
-	auto it2 = headers.begin();
-	for (; it2 != headers.end(); ++it2) {
-		ESP_LOGD(LOG_TAG, "name=\"%s\", value=\"%s\"", it2->first.c_str(), it2->second.c_str());
-	}
-	ESP_LOGD(LOG_TAG, "Body: \"%s\"", getBody().c_str());
-} // dump
-
-
-std::string HttpRequest::getBody() {
-	return m_parser.getBody();
-} // getBody
-
-
-std::string HttpRequest::getHeader(std::string name) {
-	return m_parser.getHeader(name);
-} // getHeader
-
-
-std::map<std::string, std::string> HttpRequest::getHeaders() {
-	return m_parser.getHeaders();
-} // getHeaders
-
-
-std::string HttpRequest::getMethod() {
-	return m_parser.getMethod();
-} // getMethod
-
-
-std::string HttpRequest::getPath() {
-	return m_parser.getURL();
-} // getPath
-
-
-#define STATE_NAME 0
-#define STATE_VALUE 1
-/**
- * @brief Get the query part of the request.
- * The query is a set of name = value pairs.  The return is a map keyed by the name items.
- *
- * @return The query part of the request.
- */
-std::map<std::string, std::string> HttpRequest::getQuery() {
-	// Walk through all the characters in the query string maintaining a simple state machine
-	// that lets us know what we are parsing.
-	std::map<std::string, std::string> queryMap;
-	std::string queryString = "";
-	int i=0;
-
-	/*
-	 * We maintain a simple state machine with states of:
-	 * * STATE_NAME - We are parsing a name.
-	 * * STATE_VALUE - We are parsing a value.
-	 */
-	int state = STATE_NAME;
-	std::string name = "";
-	std::string value;
-	// Loop through each character in the query string.
-	for (i=0; i<queryString.length(); i++) {
-		char currentChar = queryString[i];
-		if (state == STATE_NAME) {
-			if (currentChar != '=') {
-				name += currentChar;
-			} else {
-				state = STATE_VALUE;
-				value = "";
-			}
-		} // End state = STATE_NAME
-		else if (state == STATE_VALUE) {
-			if (currentChar != '&') {
-				value += currentChar;
-			} else {
-				//ESP_LOGD(tag, "name=%s, value=%s", name.c_str(), value.c_str());
-				queryMap[name] = value;
-				state = STATE_NAME;
-				name = "";
-			}
-		} // End state = STATE_VALUE
-	} // End for loop
-	if (state == STATE_VALUE) {
-		//ESP_LOGD(tag, "name=%s, value=%s", name.c_str(), value.c_str());
-		queryMap[name] = value;
-	}
-	return queryMap;
-} // getQuery
-
-
-Socket HttpRequest::getSocket() {
-		return m_clientSocket;
-} // getSocket
-
-
-std::string HttpRequest::getVersion() {
-	return m_parser.getVersion();
-} // getVersion
-
-WebSocket* HttpRequest::getWebSocket() {
-	return m_pWebSocket;
-} // getWebSocket
-
-
-/**
- * @brief Determine if this request represents a WebSocket
- * @return True if the request creates a web socket.
- */
-bool HttpRequest::isWebsocket() {
-	return m_pWebSocket != nullptr;
-} // isWebsocket
-
-/**
- * @brief Return the constituent parts of the path.
- * If we imagine a path as composed of parts separated by slashes, then this function
- * returns a vector composed of the parts.  For example:
- *
- * ```
- * /x/y/z
- * ```
- * will break out to:
- *
- * ```
- * path[0] = ""
- * path[1] = "x"
- * path[2] = "y"
- * path[3] = "z"
- * ```
- *
- * @return A vector of the constituent parts of the path.
- */
-std::vector<std::string> HttpRequest::pathSplit() {
-	std::istringstream stream(getPath());
-	std::vector<std::string> ret;
-	std::string pathPart;
-	while(std::getline(stream, pathPart, '/')) {
-		ret.push_back(pathPart);
-	}
-	// Debug
-	for (int i=0; i<ret.size(); i++) {
-		ESP_LOGD(LOG_TAG, "part[%d]: %s", i, ret[i].c_str());
-	}
-	return ret;
-} // pathSplit
diff --git a/components/cpp_utils/HttpRequest.h b/components/cpp_utils/HttpRequest.h
deleted file mode 100644
index 398e02e..0000000
--- a/components/cpp_utils/HttpRequest.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * HTTPRequest.h
- *
- *  Created on: Aug 30, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_HTTPREQUEST_H_
-#define COMPONENTS_CPP_UTILS_HTTPREQUEST_H_
-#include <string>
-#include <map>
-#include <vector>
-#include "Socket.h"
-#include "WebSocket.h"
-#include "HttpParser.h"
-
-#undef close
-
-class HttpRequest {
-private:
-	Socket      m_clientSocket;
-	HttpParser  m_parser;
-	int         m_status;
-	WebSocket  *m_pWebSocket;
-public:
-
-	HttpRequest(Socket s);
-	virtual ~HttpRequest();
-	static const std::string HTTP_HEADER_ACCEPT;
-	static const std::string HTTP_HEADER_ALLOW;
-	static const std::string HTTP_HEADER_CONNECTION;
-	static const std::string HTTP_HEADER_CONTENT_LENGTH;
-	static const std::string HTTP_HEADER_CONTENT_TYPE;
-	static const std::string HTTP_HEADER_COOKIE;
-	static const std::string HTTP_HEADER_HOST;
-	static const std::string HTTP_HEADER_LAST_MODIFIED;
-	static const std::string HTTP_HEADER_ORIGIN;
-	static const std::string HTTP_HEADER_SEC_WEBSOCKET_ACCEPT;
-	static const std::string HTTP_HEADER_SEC_WEBSOCKET_PROTOCOL;
-	static const std::string HTTP_HEADER_SEC_WEBSOCKET_KEY;
-	static const std::string HTTP_HEADER_SEC_WEBSOCKET_VERSION;
-	static const std::string HTTP_HEADER_UPGRADE;
-	static const std::string HTTP_HEADER_USER_AGENT;
-
-	static const std::string HTTP_METHOD_CONNECT;
-	static const std::string HTTP_METHOD_DELETE;
-	static const std::string HTTP_METHOD_GET;
-	static const std::string HTTP_METHOD_HEAD;
-	static const std::string HTTP_METHOD_OPTIONS;
-	static const std::string HTTP_METHOD_PATCH;
-	static const std::string HTTP_METHOD_POST;
-	static const std::string HTTP_METHOD_PUT;
-
-	void        close();
-	void        dump();
-	std::string getBody();
-	std::string getHeader(std::string name);
-	std::map<std::string, std::string> getHeaders();
-	std::string getMethod();
-	std::string getPath();
-	std::map<std::string, std::string> getQuery();
-	Socket      getSocket();
-	std::string getVersion();
-	WebSocket*  getWebSocket();
-	bool        isWebsocket();
-	std::vector<std::string> pathSplit();
-};
-
-#endif /* COMPONENTS_CPP_UTILS_HTTPREQUEST_H_ */
diff --git a/components/cpp_utils/HttpResponse.cpp b/components/cpp_utils/HttpResponse.cpp
deleted file mode 100644
index 4063932..0000000
--- a/components/cpp_utils/HttpResponse.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * HttpResponse.cpp
- *
- *  Created on: Sep 2, 2017
- *      Author: kolban
- */
-#include <sstream>
-#include "HttpRequest.h"
-#include "HttpResponse.h"
-#include <esp_log.h>
-
-//static const char* LOG_TAG = "HttpResponse";
-
-const int HttpResponse::HTTP_STATUS_CONTINUE              = 100;
-const int HttpResponse::HTTP_STATUS_SWITCHING_PROTOCOL    = 101;
-const int HttpResponse::HTTP_STATUS_OK                    = 200;
-const int HttpResponse::HTTP_STATUS_MOVED_PERMANENTLY     = 301;
-const int HttpResponse::HTTP_STATUS_BAD_REQUEST           = 400;
-const int HttpResponse::HTTP_STATUS_UNAUTHORIZED          = 401;
-const int HttpResponse::HTTP_STATUS_FORBIDDEN             = 403;
-const int HttpResponse::HTTP_STATUS_NOT_FOUND             = 404;
-const int HttpResponse::HTTP_STATUS_METHOD_NOT_ALLOWED    = 405;
-const int HttpResponse::HTTP_STATUS_INTERNAL_SERVER_ERROR = 500;
-const int HttpResponse::HTTP_STATUS_NOT_IMPLEMENTED       = 501;
-const int HttpResponse::HTTP_STATUS_SERVICE_UNAVAILABLE   = 503;
-
-static std::string lineTerminator = "\r\n";
-HttpResponse::HttpResponse(HttpRequest *request) {
-	m_request = request;
-	m_status  = 0;
-	m_headerCommitted = false; // We have not yet sent a header.
-}
-
-HttpResponse::~HttpResponse() {
-	// TODO Auto-generated destructor stub
-}
-
-
-/**
- * @brief Add a header to the response message.
- * If the response has already been committed then ignore this request.
- * @param [in] name The name of the header.
- * @param [in] value The value of the header.
- */
-void HttpResponse::addHeader(const std::string name, const std::string value) {
-	if (m_headerCommitted) {
-		return;
-	}
-	m_responseHeaders.insert(std::pair<std::string, std::string>(name, value));
-} // addHeader
-
-
-void HttpResponse::close() {
-	m_request->close();
-} // close
-
-
-std::string HttpResponse::getHeader(std::string name) {
-	if (m_responseHeaders.find(name) == m_responseHeaders.end()) {
-		return "";
-	}
-	return m_responseHeaders.at(name);
-} // getHeader
-
-
-std::map<std::string, std::string> HttpResponse::getHeaders() {
-	return m_responseHeaders;
-} // getHeaders
-
-
-/**
- * @brief Send data to the partner.
- * Send some data to the partner.  If we haven't yet sent the HTTP header then send that now.
- * @param [in] data The data to send to the partner.
- */
-void HttpResponse::sendData(std::string data) {
-	// If we haven't yet sent the header of the data, send that now.
-	if (m_headerCommitted == false) {
-		std::ostringstream oss;
-		oss << m_request->getVersion() << " " << m_status << " " << m_statusMessage << lineTerminator;
-		for (auto it = m_responseHeaders.begin(); it != m_responseHeaders.end(); ++it) {
-			oss << it->first.c_str() << ": " << it->second.c_str() << lineTerminator;
-		}
-		oss << lineTerminator;
-		m_headerCommitted = true;
-		m_request->getSocket().send_cpp(oss.str());
-	}
-
-	// Send the payload data.
-	m_request->getSocket().send_cpp(data);
-} // sendData
-
-
-void HttpResponse::setStatus(const int status, const std::string message) {
-	if (m_headerCommitted) {
-		return;
-	}
-	m_status = status;
-	m_statusMessage = message;
-} // setStatus
-
diff --git a/components/cpp_utils/HttpResponse.h b/components/cpp_utils/HttpResponse.h
deleted file mode 100644
index 5a9fe2e..0000000
--- a/components/cpp_utils/HttpResponse.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * HttpResponse.h
- *
- *  Created on: Sep 2, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_HTTPRESPONSE_H_
-#define COMPONENTS_CPP_UTILS_HTTPRESPONSE_H_
-#include <string>
-#include <map>
-#include "HttpRequest.h"
-
-class HttpResponse {
-private:
-	HttpRequest* m_request;
-	std::string  m_statusMessage;
-	int          m_status;
-	bool         m_headerCommitted;
-	std::map<std::string, std::string> m_responseHeaders;
-public:
-	static const int HTTP_STATUS_CONTINUE;
-	static const int HTTP_STATUS_SWITCHING_PROTOCOL;
-	static const int HTTP_STATUS_OK;
-	static const int HTTP_STATUS_MOVED_PERMANENTLY;
-	static const int HTTP_STATUS_BAD_REQUEST;
-	static const int HTTP_STATUS_UNAUTHORIZED;
-	static const int HTTP_STATUS_FORBIDDEN;
-	static const int HTTP_STATUS_NOT_FOUND;
-	static const int HTTP_STATUS_METHOD_NOT_ALLOWED;
-	static const int HTTP_STATUS_INTERNAL_SERVER_ERROR;
-	static const int HTTP_STATUS_NOT_IMPLEMENTED;
-	static const int HTTP_STATUS_SERVICE_UNAVAILABLE;
-
-	HttpResponse(HttpRequest* httpRequest);
-	virtual ~HttpResponse();
-
-	void addHeader(std::string name, std::string value);
-	void close();
-	//std::string getRootPath();
-	std::string getHeader(std::string name);
-	std::map<std::string, std::string> getHeaders();
-	void sendData(std::string data);
-	//void sendData(uint8_t *pData, size_t length);
-	//void setHeaders(std::map<std::string, std::string>  headers);
-	void setStatus(int status, std::string message);
-	//void setRootPath(std::string path);
-};
-
-#endif /* COMPONENTS_CPP_UTILS_HTTPRESPONSE_H_ */
diff --git a/components/cpp_utils/HttpServer.cpp b/components/cpp_utils/HttpServer.cpp
deleted file mode 100644
index c342d09..0000000
--- a/components/cpp_utils/HttpServer.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * HttpServer.cpp
- *
- *  Created on: Aug 30, 2017
- *      Author: kolban
- */
-
-#include <fstream>
-#include "HttpServer.h"
-#include "SockServ.h"
-#include "Task.h"
-#include <esp_log.h>
-#include "HttpRequest.h"
-#include "HttpResponse.h"
-#include "WebSocket.h"
-static const char* LOG_TAG = "HttpServer";
-
-#undef close
-/**
- * Constructor for HTTP Server
- */
-HttpServer::HttpServer() {
-	m_portNumber = 80;
-}
-
-HttpServer::~HttpServer() {
-	ESP_LOGD(LOG_TAG, "~HttpServer");
-}
-
-/**
- * @brief Be an HTTP server task.
- */
-class HttpServerTask: public Task {
-public:
-	HttpServerTask(std::string name): Task(name) {
-		m_pHttpServer = nullptr;
-	};
-
-private:
-	HttpServer* m_pHttpServer; // Reference to the HTTP Server
-
-	/**
-	 * @brief Process an incoming HTTP Request
-	 *
-	 * We examine each of the path handlers to see if we have a match for the method/path pair.  If we do,
-	 * we invoke the handler callback passing in both the request and response.
-	 *
-	 * If we didn't find a handler, then we are going to behave as a Web Server and try and serve up the
-	 * content from the file on the "file system".
-	 * @param [in] request The HTTP request to process.
-	 */
-	void processRequest(HttpRequest &request) {
-		ESP_LOGD("HttpServerTask", ">> processRequest: Method: %s, Path: %s",
-			request.getMethod().c_str(), request.getPath().c_str());
-
-		for (auto it = m_pHttpServer->m_pathHandlers.begin(); it != m_pHttpServer->m_pathHandlers.end(); ++it) {
-			if (it->match(request.getMethod(), request.getPath())) {
-				ESP_LOGD("HttpServerTask", "Found a path handler match!!");
-				if (request.isWebsocket()) {
-					it->invokePathHandler(&request, nullptr);
-					request.getWebSocket()->startReader();
-				} else {
-					HttpResponse response(&request);
-					it->invokePathHandler(&request, &response);
-				}
-				return;
-			} // Path handler match
-		} // For each path handler
-
-		ESP_LOGD("HttpServerTask", "No Path handler found");
-		// If we reach here, then we did not find a handler for the request.
-
-		// Check to see if we have an un-handled WebSocket
-		if (request.isWebsocket()) {
-			request.getWebSocket()->close_cpp();
-			return;
-		}
-
-		// Serve up the content from the file on the file system ... if found ...
-
-		std::ifstream ifStream;
-		std::string fileName = m_pHttpServer->getRootPath() + request.getPath();
-		ESP_LOGD("HttpServerTask", "Opening file: %s", fileName.c_str());
-		ifStream.open(fileName, std::ifstream::in | std::ifstream::binary);
-
-		// If we failed to open the requested file, then it probably didn't exist so return a not found.
-		if (!ifStream.is_open()) {
-			HttpResponse response(&request);
-			response.setStatus(HttpResponse::HTTP_STATUS_NOT_FOUND, "Not Found");
-			response.sendData("");
-			return;
-		}
-
-		// We now have an open file and want to push the content of that file through to the browser.
-		HttpResponse response(&request);
-		response.setStatus(HttpResponse::HTTP_STATUS_OK, "OK");
-		std::stringstream ss;
-		ss << ifStream.rdbuf();
-		response.sendData(ss.str());
-		ifStream.close();
-
-	} // processRequest
-
-
-	/**
-	 * @brief Perform the task handling for server.
-	 * @param [in] data A reference to the HttpServer.
-	 */
-	void run(void* data) {
-		m_pHttpServer = (HttpServer*)data;
-
-		// Create a socket server and start it running.
-		SockServ sockServ(m_pHttpServer->getPort());
-		sockServ.start();
-		ESP_LOGD("HttpServerTask", "Listening on port %d", m_pHttpServer->getPort());
-
-		while(1) {
-			ESP_LOGD("HttpServerTask", "Waiting for new peer client");
-			Socket clientSocket = sockServ.waitForNewClient();
-			ESP_LOGD("HttpServerTask", "HttpServer listening on port %d received a new client connection", m_pHttpServer->getPort());
-
-			HttpRequest request(clientSocket);
-			request.dump();
-			processRequest(request);
-			if (!request.isWebsocket()) {
-				request.close();
-			}
-		} // while
-	} // run
-}; // HttpServerTask
-
-
-/**
- * @brief Register a handler for a path.
- *
- * When a browser request arrives, the request will contain a method (GET, POST, etc) and a path
- * to be accessed.  Using this method we can register a regular expression and, if the incoming method
- * and path match the expression, the corresponding handler will be called.
- *
- * Example:
- * @code{.cpp}
- * static void handle_REST_WiFi(WebServer::HttpRequest *pRequest, WebServer::HttpResponse *pResponse) {
- *    ...
- * }
- *
- * webServer.addPathHandler("GET", "\\/ESP32\\/WiFi", handle_REST_WiFi);
- * @endcode
- *
- * @param [in] method The method being used for access ("GET", "POST" etc).
- * @param [in] pathExpr The path being accessed.
- * @param [in] handler The callback function to be invoked when a request arrives.
- */
-void HttpServer::addPathHandler(
-		std::string method,
-		std::string pathExpr,
-		void (*handler)(HttpRequest *pHttpRequest, HttpResponse *pHttpResponse)) {
-	m_pathHandlers.push_back(PathHandler(method, pathExpr, handler));
-} // addPathHandler
-
-
-/**
- * @brief Get the port number on which the HTTP Server is listening.
- * @return The port number on which the HTTP server is listening.
- */
-uint16_t HttpServer::getPort() {
-	return m_portNumber;
-} // getPort
-
-
-/**
- * @brief Get the current root path.
- * @return The current root path.
- */
-std::string HttpServer::getRootPath() {
-	return m_rootPath;
-} // getRootPath
-
-
-/**
- * @brief Set the root path for URL file mapping.
- *
- * When a browser requests a file, it uses the address form:
- *
- * @code{.unparsed}
- * http://<host>:<port>/<path>
- * @endcode
- *
- * The path part can be considered the path to where the file should be retrieved on the
- * file system available to the web server.  Typically, we want a directory structure on the file
- * system to host the web served files and not expose the whole file system.  Using this method
- * we specify the root directory from which the files will be served.
- *
- * @param [in] path The root path on the file system.
- * @return N/A.
- */
-void HttpServer::setRootPath(std::string path) {
-	m_rootPath = path;
-} // setRootPath
-
-
-/**
- * @brief Start the HTTP server listening.
- * We start an instance of the HTTP server listening.  A new task is spawned to perform this work in the
- * back ground.
- * @param [in] portNumber The port number on which the HTTP server should listen.
- */
-void HttpServer::start(uint16_t portNumber) {
-	ESP_LOGD(LOG_TAG, ">> start");
-	m_portNumber = portNumber;
-	HttpServerTask* pHttpServerTask = new HttpServerTask("HttpServerTask");
-	pHttpServerTask->start(this);
-} // start
-
-
-/**
- * @brief Construct an instance of a PathHandler.
- *
- * @param [in] method The method to be matched.
- * @param [in] pathPattern The path pattern to be matched.
- * @param [in] webServerRequestHandler The request handler to be called.
- */
-PathHandler::PathHandler(std::string method, std::string pathPattern,
-		void (*webServerRequestHandler)(HttpRequest *pHttpRequest, HttpResponse *pHttpResponse)) {
-	m_method         = method;
-	m_pattern        = std::regex(pathPattern);
-	m_textPattern    = pathPattern;
-	m_requestHandler = webServerRequestHandler;
-} // PathHandler
-
-
-/**
- * @brief Determine if the path matches.
- *
- * @param [in] method The method to be matched.
- * @param [in] path The path to be matched.
- * @return True if the path matches.
- */
-bool PathHandler::match(std::string method, std::string path) {
-	ESP_LOGD(LOG_TAG, "matching: %s with %s", m_textPattern.c_str(), path.c_str());
-	if (method != m_method) {
-		return false;
-	}
-	return std::regex_search(path, m_pattern);
-} // match
-
-
-/**
- * @brief Invoke the handler.
- * @param [in] request An object representing the request.
- * @param [in] response An object representing the response.
- * @return N/A.
- */
-void PathHandler::invokePathHandler(HttpRequest* request, HttpResponse *response) {
-	m_requestHandler(request, response);
-} // invokePathHandler
diff --git a/components/cpp_utils/HttpServer.h b/components/cpp_utils/HttpServer.h
deleted file mode 100644
index 4e4de64..0000000
--- a/components/cpp_utils/HttpServer.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * HttpServer.h
- *
- *  Created on: Aug 30, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_HTTPSERVER_H_
-#define COMPONENTS_CPP_UTILS_HTTPSERVER_H_
-#include <stdint.h>
-#include <regex>
-#include <vector>
-#include "SockServ.h"
-#include "HttpRequest.h"
-#include "HttpResponse.h"
-
-class HttpServerTask;
-
-class PathHandler {
-	public:
-		PathHandler(
-			std::string method,
-			std::string pathPattern,
-			void (*webServerRequestHandler)(HttpRequest* pHttpRequest, HttpResponse* pHttpResponse));
-		bool match(std::string method, std::string path);
-		void invokePathHandler(HttpRequest* request, HttpResponse* response);
-	private:
-		std::string m_method;
-		std::regex  m_pattern;
-		std::string m_textPattern;
-		void (*m_requestHandler)(HttpRequest* pHttpRequest, HttpResponse* pHttpResponse);
-}; // PathHandler
-
-
-
-
-class HttpServer {
-public:
-	HttpServer();
-	virtual ~HttpServer();
-
-	void        addPathHandler(std::string method,
-		std::string pathExpr,
-		void (*webServerRequestHandler)(
-			HttpRequest* pHttpRequest,
-			HttpResponse* pHttpResponse) );
-	uint16_t    getPort();
-	std::string getRootPath();
-	void        setRootPath(std::string path);
-	void        start(uint16_t portNumber);
-private:
-	friend class HttpServerTask;
-	friend class WebSocket;
-	uint16_t                 m_portNumber;
-	std::vector<PathHandler> m_pathHandlers;
-	std::string              m_rootPath; // Root path into the file system.
-}; // HttpServer
-
-#endif /* COMPONENTS_CPP_UTILS_HTTPSERVER_H_ */
diff --git a/components/cpp_utils/I2S.cpp b/components/cpp_utils/I2S.cpp
deleted file mode 100644
index c5bcb99..0000000
--- a/components/cpp_utils/I2S.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * I2S.cpp
- *
- *  Created on: Jul 23, 2017
- *      Author: kolban
- */
-#include <driver/periph_ctrl.h>
-#include <string>
-#include <sstream>
-#include <iomanip>
-#include "I2S.h"
-#include "GPIO.h"
-#include "FreeRTOS.h"
-#include "GeneralUtils.h"
-
-extern "C" {
-	#include <soc/i2s_reg.h>
-	#include <soc/i2s_struct.h>
-}
-
-#include <rom/lldesc.h>
-#include <esp_intr_alloc.h>
-#include <esp_log.h>
-
-static const char* LOG_TAG = "I2S";
-
-static intr_handle_t i2s_intr_handle;
-
-
-
-/**
- * A representation of a DMA buffer.
- */
-class DMABuffer {
-public:
-	DMABuffer();
-	~DMABuffer();
-
-	void       dump();
-	uint32_t   getData(uint8_t* pData, uint32_t length);
-	lldesc_t*  getDesc();
-	uint32_t   getLength();
-	DMABuffer* getNext();
-	bool       isEoF();
-	void       setNext(DMABuffer* pNext);
-
-private:
-	lldesc_t   m_desc;
-	DMABuffer* m_pNext;
-};
-
-
-DMABuffer::DMABuffer() {
-	m_desc.length = 0;
-	m_desc.size   = 4092;
-	m_desc.owner  = 1;
-	m_desc.sosf   = 1;
-	m_desc.offset = 0;
-	m_desc.eof    = 0;
-	m_desc.empty  = 0;
-	m_desc.buf    = new uint8_t[m_desc.size];
-	m_pNext       = nullptr;
-} // DMABuffer
-
-
-DMABuffer::~DMABuffer() {
-	delete[] m_desc.buf;
-} // ~DMABuffer
-
-/**
- * @brief Dump the state of the buffer.
- * @return N/A
- */
-void DMABuffer::dump() {
-	std::ostringstream ss;
-	ss << "size: "     << m_desc.size;
-	ss << ", buf: 0x"  << std::hex << (uint32_t)m_desc.buf << std::dec;
-	ss << ", length: " << m_desc.length;
-	ss << ", offset: " << m_desc.offset;
-	ss << ", sosf: "   << m_desc.sosf;
-	ss << ", eof: "    << m_desc.eof;
-	ss << ", owner: "  << m_desc.owner;
-	ESP_LOGD(LOG_TAG, "Desc: %s", ss.str().c_str());
-	int length = 100;
-	if (length > m_desc.length) {
-		length = m_desc.length;
-	}
-	GeneralUtils::hexDump((uint8_t*)m_desc.buf, length);
-}
-
-/**
- * @brief Populate a buffer of data with the DMA data.
- * @param [in] pData A pointer to data to be populated with the DMA data.
- * @param [in] length The size in bytes of the pData buffer.
- * @return The number of bytes actually copied.
- */
-uint32_t DMABuffer::getData(uint8_t* pData, uint32_t length) {
-	uint8_t* pBuf = (uint8_t*)m_desc.buf;
-	if (length > getLength()) {
-		length = getLength();
-	}
-	uint32_t i;
-	//
-	// The descriptor buffer is filled with data that contains:
-	//
-	// b1 00 b0 00  b3 00 b2 00  b5 00 b4 00  b7 00 b6 00
-	//
-	// Our goal is to populate the passed in buffer with data of the form:
-	//
-	// b0 b1 b2 b3  b4 b5 b6 b7 ...
-	//
-	// The following alogrithm does that.
-	//
-	for (i=0; i<length; i+=2) {
-		*pData = pBuf[2];
-		pData++;
-		*pData = pBuf[0];
-		pData++;
-		pBuf += 4;
-	}
-	return i;
-} // getData
-
-
-/**
- * @brief Get the underlying linked list descriptor.
- * @return The underlying linked list descriptor.
- */
-lldesc_t* DMABuffer::getDesc() {
-	return &m_desc;
-} // getDesc
-
-
-/**
- * @brief Get the number of populated bytes.
- * @return The number of populated bytes.
- */
-uint32_t DMABuffer::getLength() {
-	return m_desc.length/4;
-} // getLength
-
-
-/**
- * @brief Get the next DMA Buffer.
- * @return The next DMA Buffer;
- */
-DMABuffer* DMABuffer::getNext() {
-	return m_pNext;
-} // getNext
-
-
-/**
- * @brief Have we received all the data we expected?
- * @return True if we have received all the data we expected.
- */
-bool DMABuffer::isEoF() {
-	return m_desc.eof != 0;
-} // isEoF
-
-
-/**
- * @brief Set the next DMA buffer in the chain.
- * @param [in] pNext The next DMA buffer in the chain.
- */
-void DMABuffer::setNext(DMABuffer* pNext) {
-	m_pNext = pNext;
-	m_desc.empty = 0;
-	m_desc.qe.stqe_next = pNext->getDesc();
-} // setNext
-
-
-I2S::I2S() {
-	// TODO Auto-generated constructor stub
-
-}
-
-I2S::~I2S() {
-	// TODO Auto-generated destructor stub
-}
-
-DMABuffer *pCurrentDMABuffer;
-DMABuffer *pLastDMABuffer;
-
-
-static void i2s_conf_reset()
-{
-    const uint32_t lc_conf_reset_flags = I2S_IN_RST_M | I2S_AHBM_RST_M
-            | I2S_AHBM_FIFO_RST_M;
-    I2S0.lc_conf.val |= lc_conf_reset_flags;
-    I2S0.lc_conf.val &= ~lc_conf_reset_flags;
-
-    const uint32_t conf_reset_flags = I2S_RX_RESET_M | I2S_RX_FIFO_RESET_M
-            | I2S_TX_RESET_M | I2S_TX_FIFO_RESET_M;
-    I2S0.conf.val |= conf_reset_flags;
-    I2S0.conf.val &= ~conf_reset_flags;
-    while (I2S0.state.rx_fifo_reset_back) {
-        ;
-    }
-}
-
-/*
-static void IRAM_ATTR logI2SIntr() {
-	std::ostringstream ss;
-	ss << "IN_DONE: "         << I2S0.int_raw.in_done;
-	ss << ", IN_DSCR_EMPTY: " << I2S0.int_raw.in_dscr_empty;
-	ss << ", IN_DSCR_ERR: "   << I2S0.int_raw.in_dscr_err;
-	ss << ", IN_ERR_EOF: "    << I2S0.int_raw.in_err_eof;
-	ss << ", IN_SUC_EOF: "    << I2S0.int_raw.in_suc_eof;
-	ESP_EARLY_LOGV(LOG_TAG, "I2S Intr: %s", ss.str().c_str());
-}
-*/
-
-/*
-static void IRAM_ATTR logDesc(lldesc_t* pDesc) {
-	std::ostringstream ss;
-	ss << "size: "     << pDesc->size;
-	ss << ", buf: 0x" << std::hex << (uint32_t)pDesc->buf << std::dec;
-	ss << ", length: " << pDesc->length;
-	ss << ", offset: " << pDesc->offset;
-	ss << ", sosf: "   << pDesc->sosf;
-	ss << ", eof: "    << pDesc->eof;
-	ss << ", owner: "  << pDesc->owner;
-	ESP_EARLY_LOGV(LOG_TAG, "Desc: %s", ss.str().c_str());
-}
-*/
-
-
-/**
- * @brief I2S DMA Interrupt handler
- */
-static void IRAM_ATTR i2s_isr(void* arg)
-{
-	I2S* pI2S = (I2S*)arg;
-  //ESP_EARLY_LOGV(LOG_TAG, "I2S isr");
-  pLastDMABuffer = pCurrentDMABuffer;
-  //logI2SIntr();
-  //logDesc(pCurrentDMABuffer->getDesc());
-  pCurrentDMABuffer = pCurrentDMABuffer->getNext();
-  I2S0.int_clr.val = I2S0.int_raw.val;
-  pI2S->m_dmaSemaphore.giveFromISR();
-}
-
-/**
- * @brief EXPERIMENTAL
- */
-void I2S::cameraMode(dma_config_t config, int desc_count, int sample_count) {
-	ESP_LOGD(LOG_TAG, ">> cameraMode");
-	ESP32CPP::GPIO::setInput(config.pin_d0);
-	ESP32CPP::GPIO::setInput(config.pin_d1);
-	ESP32CPP::GPIO::setInput(config.pin_d2);
-	ESP32CPP::GPIO::setInput(config.pin_d3);
-	ESP32CPP::GPIO::setInput(config.pin_d4);
-	ESP32CPP::GPIO::setInput(config.pin_d5);
-	ESP32CPP::GPIO::setInput(config.pin_d6);
-	ESP32CPP::GPIO::setInput(config.pin_d7);
-	//ESP32CPP::GPIO::setInput(config.pin_xclk);
-	ESP32CPP::GPIO::setInput(config.pin_vsync);
-	ESP32CPP::GPIO::setInput(config.pin_href);
-	ESP32CPP::GPIO::setInput(config.pin_pclk);
-	//ESP32CPP::GPIO::setOutput(config.pin_reset);
-
-	const uint32_t const_high = 0x38;
-
-  gpio_matrix_in(config.pin_d0,    I2S0I_DATA_IN0_IDX, false);
-  gpio_matrix_in(config.pin_d1,    I2S0I_DATA_IN1_IDX, false);
-  gpio_matrix_in(config.pin_d2,    I2S0I_DATA_IN2_IDX, false);
-  gpio_matrix_in(config.pin_d3,    I2S0I_DATA_IN3_IDX, false);
-  gpio_matrix_in(config.pin_d4,    I2S0I_DATA_IN4_IDX, false);
-  gpio_matrix_in(config.pin_d5,    I2S0I_DATA_IN5_IDX, false);
-  gpio_matrix_in(config.pin_d6,    I2S0I_DATA_IN6_IDX, false);
-  gpio_matrix_in(config.pin_d7,    I2S0I_DATA_IN7_IDX, false);
-  gpio_matrix_in(config.pin_vsync,       I2S0I_V_SYNC_IDX,   true);
-  gpio_matrix_in(config.pin_href,       I2S0I_H_SYNC_IDX,   false);
-  //gpio_matrix_in(const_high,       I2S0I_V_SYNC_IDX,   false);
-  //gpio_matrix_in(const_high,       I2S0I_H_SYNC_IDX,   false);
-  gpio_matrix_in(const_high,       I2S0I_H_ENABLE_IDX, false);
-  gpio_matrix_in(config.pin_pclk,  I2S0I_WS_IN_IDX,    false);
-
-	// Enable and configure I2S peripheral
-	periph_module_enable(PERIPH_I2S0_MODULE);
-	// Toggle some reset bits in LC_CONF register
-	// Toggle some reset bits in CONF register
-	// Enable slave mode (sampling clock is external)
-
-	i2s_conf_reset();
-
-	// Switch on Slave mode.
-	// I2S_CONF_REG -> I2S_RX_SLAVE_MOD
-	// Set to 1 to enable slave mode.
-	I2S0.conf.rx_slave_mod = 1;
-
-	// Enable parallel mode
-	// I2S_CONF2_REG -> I2S_LCD_END
-	// Set to 1 to enable LCD mode.
-	I2S0.conf2.lcd_en = 1;
-
-	// Use HSYNC/VSYNC/HREF to control sampling
-	// I2S_CONF2_REG -> I2S_CAMERA_EN
-	// Set to 1 to enable camera mode.
-	I2S0.conf2.camera_en = 1;
-
-
-	// Configure clock divider
-	I2S0.clkm_conf.clkm_div_a   = 1;
-	I2S0.clkm_conf.clkm_div_b   = 0;
-	I2S0.clkm_conf.clkm_div_num = 2;
-
-	// I2S_FIFO_CONF_REG -> I2S_DSCR_EN
-	// FIFO will sink data to DMA
-	I2S0.fifo_conf.dscr_en = 1;
-
-	// FIFO configuration
-	// I2S_FIFO_CONF_REG -> RX_FIFO_MOD
-	I2S0.fifo_conf.rx_fifo_mod          = 1; // 0-3???
-
-	// I2S_FIFO_CONF_REG -> RX_FIFO_MOD_FORCE_EN
-	I2S0.fifo_conf.rx_fifo_mod_force_en = 1;
-
-	// I2S_CONF_CHAN_REG -> I2S_RX_CHAN_MOD
-	I2S0.conf_chan.rx_chan_mod          = 1;
-
-	// Clear flags which are used in I2S serial mode
-	// I2S_SAMPLE_RATE_CONF_REG -> I2S_RX_BITS_MOD
-	I2S0.sample_rate_conf.rx_bits_mod = 0;
-
-	// I2S_CONF_REG -> I2S_RX_RIGHT_FIRST
-	I2S0.conf.rx_right_first = 0;
-	//I2S0.conf.rx_right_first = 0;
-
-	// I2S_CONF_REG -> I2S_RX_MSB_RIGHT
-	I2S0.conf.rx_msb_right   = 0;
-	//I2S0.conf.rx_msb_right   = 1;
-
-	// I2S_CONF_REG -> I2S_RX_MSB_SHIFT
-	I2S0.conf.rx_msb_shift   = 0;
-	//I2S0.conf.rx_msb_shift   = 1;
-
-	// I2S_CONF_REG -> I2S_RX_MSB_MONO
-	I2S0.conf.rx_mono        = 0;
-
-	// I2S_CONF_REG -> I2S_RX_SHORT_SYNC
-	I2S0.conf.rx_short_sync  = 0;
-
-	I2S0.timing.val          = 0;
-
-
-	ESP_LOGD(LOG_TAG, "Initializing %d descriptors", desc_count);
-	DMABuffer *pFirst = new DMABuffer();
-	DMABuffer *pLast = pFirst;
-	for (int i=1; i<desc_count; i++) {
-		DMABuffer* pNewDMABuffer = new DMABuffer();
-		pLast->setNext(pNewDMABuffer);
-		pLast = pNewDMABuffer;
-	}
-	pLast->setNext(pFirst);
-	pCurrentDMABuffer = pFirst;
-
-	// I2S_RX_EOF_NUM_REG
-  I2S0.rx_eof_num      = sample_count;
-
-  // I2S_IN_LINK_REG -> I2S_INLINK_ADDR
-  I2S0.in_link.addr    = (uint32_t) pFirst;
-
-  // I2S_IN_LINK_REG -> I2S_INLINK_START
-  I2S0.in_link.start   = 1;
-
-  I2S0.int_clr.val     = I2S0.int_raw.val;
-  I2S0.int_ena.val     = 0;
-  I2S0.int_ena.in_done = 1;
-
-  // Register the interrupt handler.
-  esp_intr_alloc(
-  	ETS_I2S0_INTR_SOURCE,
-		ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM,
-		&i2s_isr,
-		this,
-		&i2s_intr_handle);
-
-  m_dmaSemaphore.take();
-  // Start the interrupt handler
-  esp_intr_enable(i2s_intr_handle);
-
-  I2S0.conf.rx_start = 1;
-
-  /*
-  while(1) {
-  	m_dmaSemaphore.wait();
-  	uint32_t dataLength = pLastDMABuffer->getLength();
-  	ESP_LOGD(LOG_TAG, "Got a DMA buffer; length=%d", dataLength);
-  	//pLastDMABuffer->dump();
-  	uint8_t *pData = new uint8_t[dataLength];
-  	pLastDMABuffer->getData(pData, dataLength);
-		GeneralUtils::hexDump(pData, dataLength);
-		delete[] pData;
-		m_dmaSemaphore.take();
-  }
-  */
-
-	ESP_LOGD(LOG_TAG, "<< cameraMode");
-}
-
-
-DMAData I2S::waitForData() {
-	DMAData dmaData;
-	m_dmaSemaphore.wait();
-	dmaData.m_length = pLastDMABuffer->getLength();
-	ESP_LOGD(LOG_TAG, "Got a DMA buffer; length=%d", dmaData.m_length);
-	//pLastDMABuffer->dump();
-	dmaData.m_pData = new uint8_t[dmaData.m_length];
-	pLastDMABuffer->getData(dmaData.m_pData, dmaData.m_length);
-	return dmaData;
-}
diff --git a/components/cpp_utils/I2S.h b/components/cpp_utils/I2S.h
deleted file mode 100644
index 7d8fd26..0000000
--- a/components/cpp_utils/I2S.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * I2S.h
- *
- *  Created on: Jul 23, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_I2S_H_
-#define COMPONENTS_CPP_UTILS_I2S_H_
-#include <driver/gpio.h>
-#include <FreeRTOS.h>
-typedef struct {
-    gpio_num_t pin_reset;          /*!< GPIO pin for camera reset line - OUT */
-    gpio_num_t pin_xclk;           /*!< GPIO pin for camera XCLK line  - IN  */
-    gpio_num_t pin_sscb_sda;       /*!< GPIO pin for camera SDA line   - OUT */
-    gpio_num_t pin_sscb_scl;       /*!< GPIO pin for camera SCL line   - OUT */
-    gpio_num_t pin_d7;             /*!< GPIO pin for camera D7 line    - IN  */
-    gpio_num_t pin_d6;             /*!< GPIO pin for camera D6 line    - IN  */
-    gpio_num_t pin_d5;             /*!< GPIO pin for camera D5 line    - IN  */
-    gpio_num_t pin_d4;             /*!< GPIO pin for camera D4 line    - IN  */
-    gpio_num_t pin_d3;             /*!< GPIO pin for camera D3 line    - IN  */
-    gpio_num_t pin_d2;             /*!< GPIO pin for camera D2 line    - IN  */
-    gpio_num_t pin_d1;             /*!< GPIO pin for camera D1 line    - IN  */
-    gpio_num_t pin_d0;             /*!< GPIO pin for camera D0 line    - IN  */
-    gpio_num_t pin_vsync;          /*!< GPIO pin for camera VSYNC line - IN  */
-    gpio_num_t pin_href;           /*!< GPIO pin for camera HREF line  - IN  */
-    gpio_num_t pin_pclk;           /*!< GPIO pin for camera PCLK line  - IN  */
-
-    int xclk_freq_hz;       /*!< Frequency of XCLK signal, in Hz */
-} dma_config_t;
-
-class DMAData {
-public:
-	uint32_t getLength() {
-		return m_length;
-	}
-	uint8_t* getData() {
-		return m_pData;
-	}
-
-	void free() {
-		delete[] m_pData;
-		m_pData = nullptr;
-	}
-private:
-	friend class I2S;
-	uint32_t m_length;
-	uint8_t* m_pData;
-};
-
-class I2S {
-public:
-	I2S();
-	virtual ~I2S();
-	void cameraMode(dma_config_t config, int desc_count, int sample_count);
-	DMAData waitForData();
-	FreeRTOS::Semaphore m_dmaSemaphore;
-private:
-
-};
-
-#endif /* COMPONENTS_CPP_UTILS_I2S_H_ */
diff --git a/components/cpp_utils/IFTTT.cpp b/components/cpp_utils/IFTTT.cpp
deleted file mode 100644
index 0cf7a6d..0000000
--- a/components/cpp_utils/IFTTT.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * IFTTT.cpp
- *
- *  Created on: Mar 14, 2017
- *      Author: kolban
- */
-#if defined(ESP_HAVE_CURL)
-#include "IFTTT.h"
-#include <cJSON.h>
-
-
-/**
- * @brief Construct an IFTTT maker client using the supplied key.
- */
-IFTTT::IFTTT(std::string key) {
-	m_key = key;
-	m_restClient.addHeader("Content-Type", "application/json");
-	m_restClient.setVerbose(true);
-} // IFTTT
-
-
-IFTTT::~IFTTT() {
-} // ~IFTTT
-
-
-/**
- * @brief Trigger a maker event at IFTTT.
- *
- * @param [in] event The event type to send.
- * @param [in] value1 The value of value1.
- * @param [in] value2 The value of value2.
- * @param [in] value3 The value of value3.
- */
-void IFTTT::trigger(
-		std::string event,
-		std::string value1,
-		std::string value2,
-		std::string value3) {
-	m_restClient.setURL("https://maker.ifttt.com/trigger/" + event + "/with/key/" + m_key);
-	cJSON *root;
-	root = cJSON_CreateObject();
-
-	cJSON_AddStringToObject(root, "value1", value1.c_str());
-	cJSON_AddStringToObject(root, "value2", value2.c_str());
-	cJSON_AddStringToObject(root, "value3", value3.c_str());
-
-	m_restClient.post(std::string(cJSON_Print(root)));
-
-	cJSON_Delete(root);
-} // trigger
-#endif // ESP_HAVE_CURL
diff --git a/components/cpp_utils/IFTTT.h b/components/cpp_utils/IFTTT.h
deleted file mode 100644
index 08877e8..0000000
--- a/components/cpp_utils/IFTTT.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * IFTTT.h
- *
- *  Created on: Mar 14, 2017
- *      Author: kolban
- */
-
-#ifndef MAIN_IFTTT_H_
-#define MAIN_IFTTT_H_
-
-#include <RESTClient.h>
-#include <string>
-/**
- * @brief Encapsulate %IFTTT calls.
- */
-class IFTTT {
-public:
-	IFTTT(std::string key);
-	virtual ~IFTTT();
-	void trigger(std::string event, std::string value1 = "", std::string value2 = "", std::string value3 = "");
-private:
-	RESTClient m_restClient;
-	std::string m_key;
-};
-
-#endif /* MAIN_IFTTT_H_ */
diff --git a/components/cpp_utils/JSON.cpp b/components/cpp_utils/JSON.cpp
deleted file mode 100644
index f7b296f..0000000
--- a/components/cpp_utils/JSON.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * JSON.cpp
- *
- *  Created on: May 23, 2017
- *      Author: kolban
- */
-
-
-#include <string>
-#include <stdlib.h>
-#include "JSON.h"
-
-/**
- * @brief Create an empty JSON array.
- * @return An empty JSON array.
- */
-JsonArray JSON::createArray() {
-	return JsonArray(cJSON_CreateArray());
-} // createArray
-
-
-/**
- * @brief Create an empty JSON object.
- * @return An empty JSON object.
- */
-JsonObject JSON::createObject() {
-	return JsonObject(cJSON_CreateObject());
-} // createObject
-
-
-/**
- * @brief Delete a JSON array.
- * @param [in] jsonArray The array to be deleted.
- * @return N/A.
- */
-void JSON::deleteArray(JsonArray jsonArray) {
-	cJSON_Delete(jsonArray.m_node);
-} // deleteArray
-
-
-/**
- * @brief Delete a JSON object.
- * @param [in] jsonObject The object to be deleted.
- */
-void JSON::deleteObject(JsonObject jsonObject) {
-	cJSON_Delete(jsonObject.m_node);
-} // deleteObject
-
-
-/**
- * @brief Parse a string that contains a JSON array.
- * @param [in] text The JSON text string.
- * @return A JSON array.
- */
-JsonArray JSON::parseArray(std::string text) {
-	return JsonArray(cJSON_Parse(text.c_str()));
-} // parseArray
-
-
-/**
- * @brief Parse a string that contains a JSON object.
- * @param [in] text The JSON text string.
- * @return a JSON object.
- */
-JsonObject JSON::parseObject(std::string text) {
-	return JsonObject(cJSON_Parse(text.c_str()));
-} // parseObject
-
-
-JsonArray::JsonArray(cJSON* node) {
-	m_node = node;
-}
-
-
-/**
- * @brief Add a boolean value to the array.
- * @param [in] value The boolean value to add to the array.
- */
-void JsonArray::addBoolean(bool value) {
-	cJSON_AddItemToArray(m_node, cJSON_CreateBool(value));
-} // addBoolean
-
-
-/**
- * @brief Add a double value to the array.
- * @param [in] value The double value to add to the array.
- */
-void JsonArray::addDouble(double value) {
-	cJSON_AddItemToArray(m_node, cJSON_CreateNumber(value));
-} // addDouble
-
-
-/**
- * @brief Add an int value to the array.
- * @param [in] value The int value to add to the array.
- */
-void JsonArray::addInt(int value) {
-	cJSON_AddItemToArray(m_node, cJSON_CreateDouble((double)value, value));
-} // addInt
-
-
-/**
- * @brief Add an object value to the array.
- * @param [in] value The object value to add to the array.
- */
-void JsonArray::addObject(JsonObject value) {
-	cJSON_AddItemToArray(m_node, value.m_node);
-} // addObject
-
-
-/**
- * @brief Add a string value to the array.
- * @param [in] value The string value to add to the array.
- */
-void JsonArray::addString(std::string value) {
-	cJSON_AddItemToArray(m_node, cJSON_CreateString(value.c_str()));
-} // addString
-
-
-/**
- * @brief Get the indexed boolean value from the array.
- * @param [in] item The index of the array to retrieve.
- * @return The boolean value at the given index.
- */
-bool JsonArray::getBoolean(int item) {
-	cJSON *node = cJSON_GetArrayItem(m_node, item);
-	if (node->valueint == 0) {
-		return false;
-	}
-	return true;
-} // getBoolean
-
-
-/**
- * @brief Get the indexed double value from the array.
- * @param [in] item The index of the array to retrieve.
- * @return The double value at the given index.
- */
-double JsonArray::getDouble(int item) {
-	cJSON *node = cJSON_GetArrayItem(m_node, item);
-	return node->valuedouble;
-} // getDouble
-
-
-/**
- * @brief Get the indexed int value from the array.
- * @param [in] item The index of the array to retrieve.
- * @return The int value at the given index.
- */
-int JsonArray::getInt(int item) {
-	cJSON *node = cJSON_GetArrayItem(m_node, item);
-	return node->valueint;
-} // getInt
-
-
-/**
- * @brief Get the indexed object value from the array.
- * @param [in] item The index of the array to retrieve.
- * @return The object value at the given index.
- */
-JsonObject JsonArray::getObject(int item) {
-	cJSON *node = cJSON_GetArrayItem(m_node, item);
-	return JsonObject(node);
-} // getObject
-
-
-/**
- * @brief Get the indexed object value from the array.
- * @param [in] item The index of the array to retrieve.
- * @return The object value at the given index.
- */
-std::string JsonArray::getString(int item) {
-	cJSON *node = cJSON_GetArrayItem(m_node, item);
-	return std::string(node->valuestring);
-} // getString
-
-
-/**
- * @brief Convert the JSON array to a string.
- * @return A JSON string representation of the array.
- */
-std::string JsonArray::toString() {
-	char *data = cJSON_Print(m_node);
-	std::string ret(data);
-	free(data);
-	return ret;
-} // toString
-
-
-/**
- * @brief Get the number of elements from the array.
- * @return The int value that represents the number of elements.
- */
-std::size_t JsonArray::size() {
-	return cJSON_GetArraySize(m_node);
-} // size
-
-
-JsonObject::JsonObject(cJSON* node) {
-	m_node = node;
-}
-
-/**
- * @brief Get the named boolean value from the object.
- * @param [in] name The name of the object property.
- * @return The boolean value from the object.
- */
-bool JsonObject::getBoolean(std::string name) {
-	cJSON *node = cJSON_GetObjectItem(m_node, name.c_str());
-	if (node->valueint == 0) {
-		return false;
-	}
-	return true;
-} // getBoolean
-
-
-/**
- * @brief Get the named double value from the object.
- * @param [in] name The name of the object property.
- * @return The double value from the object.
- */
-double JsonObject::getDouble(std::string name) {
-	cJSON *node = cJSON_GetObjectItem(m_node, name.c_str());
-	return node->valuedouble;
-} // getDouble
-
-
-/**
- * @brief Get the named int value from the object.
- * @param [in] name The name of the object property.
- * @return The int value from the object.
- */
-int JsonObject::getInt(std::string name) {
-	cJSON *node = cJSON_GetObjectItem(m_node, name.c_str());
-	return node->valueint;
-} // getInt
-
-
-/**
- * @brief Get the named object value from the object.
- * @param [in] name The name of the object property.
- * @return The object value from the object.
- */
-JsonObject JsonObject::getObject(std::string name) {
-	cJSON *node = cJSON_GetObjectItem(m_node, name.c_str());
-	return JsonObject(node);
-} // getObject
-
-
-/**
- * @brief Get the named string value from the object.
- * @param [in] name The name of the object property.
- * @return The string value from the object.
- */
-std::string JsonObject::getString(std::string name) {
-	cJSON *node = cJSON_GetObjectItem(m_node, name.c_str());
-	return std::string(node->valuestring);
-} // getString
-
-
-/**
- * @brief Determine if the object has the specified item.
- * @param [in] name The name of the property to check for presence.
- * @return True if the object contains this property.
- */
-bool JsonObject::hasItem(std::string name) {
-	return cJSON_GetObjectItem(m_node, name.c_str()) != nullptr;
-} // hasItem
-
-
-
-/**
- * @brief Set the named array property.
- * @param [in] name The name of the property to add.
- * @param [in] array The array to add to the object.
- * @return N/A.
- */
-void JsonObject::setArray(std::string name, JsonArray array) {
-	cJSON_AddItemToObject(m_node, name.c_str(), array.m_node);
-} // setArray
-
-
-/**
- * @brief Set the named boolean property.
- * @param [in] name The name of the property to add.
- * @param [in] value The boolean to add to the object.
- * @return N/A.
- */
-void JsonObject::setBoolean(std::string name, bool value) {
-	cJSON_AddItemToObject(m_node, name.c_str(), cJSON_CreateBool(value));
-} // setBoolean
-
-
-/**
- * @brief Set the named double property.
- * @param [in] name The name of the property to add.
- * @param [in] value The double to add to the object.
- * @return N/A.
- */
-void JsonObject::setDouble(std::string name, double value) {
-	cJSON_AddItemToObject(m_node, name.c_str(), cJSON_CreateNumber(value));
-} // setDouble
-
-
-/**
- * @brief Set the named int property.
- * @param [in] name The name of the property to add.
- * @param [in] value The int to add to the object.
- * @return N/A.
- */
-void JsonObject::setInt(std::string name, int value) {
-	cJSON_AddItemToObject(m_node, name.c_str(), cJSON_CreateDouble((double)value, value));
-} // setInt
-
-
-/**
- * @brief Set the named object property.
- * @param [in] name The name of the property to add.
- * @param [in] value The object to add to the object.
- * @return N/A.
- */
-void JsonObject::setObject(std::string name, JsonObject value) {
-	cJSON_AddItemToObject(m_node, name.c_str(), value.m_node);
-} // setObject
-
-
-/**
- * @brief Set the named string property.
- * @param [in] name The name of the property to add.
- * @param [in] value The string to add to the object.
- * @return N/A.
- */
-void JsonObject::setString(std::string name, std::string value) {
-	cJSON_AddItemToObject(m_node, name.c_str(), cJSON_CreateString(value.c_str()));
-} // setString
-
-
-/**
- * @brief Convert the JSON object to a string.
- * @return A JSON string representation of the object.
- */
-std::string JsonObject::toString() {
-	char *data = cJSON_Print(m_node);
-	std::string ret(data);
-	free(data);
-	return ret;
-} // toString
-
diff --git a/components/cpp_utils/JSON.h b/components/cpp_utils/JSON.h
deleted file mode 100644
index bca2d64..0000000
--- a/components/cpp_utils/JSON.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * JSON.h
- *
- *  Created on: May 23, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_JSON_H_
-#define COMPONENTS_CPP_UTILS_JSON_H_
-#include <cJSON.h>
-#include <string>
-
-// Forward declarations
-class JsonObject;
-class JsonArray;
-
-/**
- * @brief Top level JSON handler.
- */
-class JSON {
-public:
-	static JsonObject createObject();
-	static JsonArray  createArray();
-	static void       deleteObject(JsonObject jsonObject);
-	static void       deleteArray(JsonArray jsonArray);
-	static JsonObject parseObject(std::string text);
-	static JsonArray  parseArray(std::string text);
-}; // JSON
-
-
-/**
- * @brief A JSON array.
- */
-class JsonArray {
-public:
-	JsonArray(cJSON* node);
-	int         getInt(int item);
-	JsonObject  getObject(int item);
-	std::string getString(int item);
-	bool        getBoolean(int item);
-	double      getDouble(int item);
-	void        addBoolean(bool value);
-	void        addDouble(double value);
-	void        addInt(int value);
-	void        addObject(JsonObject value);
-	void        addString(std::string value);
-	std::string toString();
-	std::size_t size();
-	/**
-	 * @brief The underlying cJSON node.
-	 */
-	cJSON *m_node;
-}; // JsonArray
-
-
-/**
- * @brief A JSON object.
- */
-class JsonObject {
-public:
-	JsonObject(cJSON* node);
-	bool        getBoolean(std::string name);
-	double      getDouble(std::string name);
-	int         getInt(std::string name);
-	JsonObject  getObject(std::string name);
-	std::string getString(std::string name);
-	bool        hasItem(std::string name);
-	void        setArray(std::string name, JsonArray array);
-	void        setBoolean(std::string name, bool value);
-	void        setDouble(std::string name, double value);
-	void        setInt(std::string name, int value);
-	void        setObject(std::string name, JsonObject value);
-	void        setString(std::string name, std::string value);
-	std::string toString();
-
-	/**
-	 * @brief The underlying cJSON node.
-	 */
-	cJSON* m_node;
-}; // JsonObject
-
-
-#endif /* COMPONENTS_CPP_UTILS_JSON_H_ */
diff --git a/components/cpp_utils/Kconfig b/components/cpp_utils/Kconfig
deleted file mode 100644
index e3d51c7..0000000
--- a/components/cpp_utils/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-menu "C++ settings"
-
-config LIBCURL_PRESENT
-	bool "LibCurl present"
-	default false
-	help
-		Set to true to indicate that LibCurl is present.
-
-config U8G2_PRESENT
-	bool "U8G2 present"
-	default false
-	help
-		Set to true to indicate that U8G2 library is present.
-
-config MONGOOSE_PRESENT
-	bool "Mongoose present"
-	default false
-	help
-		Set to true to indicate that the Mongoose library is present.
-
-endmenu
diff --git a/components/cpp_utils/MAX7219.cpp b/components/cpp_utils/MAX7219.cpp
deleted file mode 100644
index d83615d..0000000
--- a/components/cpp_utils/MAX7219.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- *    MAX7219.cpp - A library for controling Leds with a MAX7219/MAX7221
- *    Copyright (c) 2007 Eberhard Fahle
- *
- *    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:
- *
- *    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.
- */
-
-/**
- * Modified by Neil Kolban (2017) for ESP32 support.
- */
-
-#include "MAX7219.h"
-#include <math.h>
-
-//the opcodes for the MAX7221 and MAX7219
-#define OP_NOOP        0x00
-#define OP_DIGIT0      0x01
-#define OP_DIGIT1      0x02
-#define OP_DIGIT2      0x03
-#define OP_DIGIT3      0x04
-#define OP_DIGIT4      0x05
-#define OP_DIGIT5      0x06
-#define OP_DIGIT6      0x07
-#define OP_DIGIT7      0x08
-#define OP_DECODEMODE  0x09
-#define OP_INTENSITY   0x0a
-#define OP_SCANLIMIT   0x0b
-#define OP_SHUTDOWN    0x0c
-#define OP_DISPLAYTEST 0x0f
-
-/*
- * Segments to be switched on for characters and digits on
- * 7-Segment Displays
- */
-const static uint8_t charTable[] = {
-		0b01111110, 0b00110000, 0b01101101,
-		0b01111001, 0b00110011, 0b01011011, 0b01011111, 0b01110000, 0b01111111,
-		0b01111011, 0b01110111, 0b00011111, 0b00001101, 0b00111101, 0b01001111,
-		0b01000111, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b10000000,
-		0b00000001, 0b10000000, 0b00000000, 0b01111110, 0b00110000, 0b01101101,
-		0b01111001, 0b00110011, 0b01011011, 0b01011111, 0b01110000, 0b01111111,
-		0b01111011, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b01110111, 0b00011111, 0b00001101, 0b00111101,
-		0b01001111, 0b01000111, 0b00000000, 0b00110111, 0b00000000, 0b00000000,
-		0b00000000, 0b00001110, 0b00000000, 0b00000000, 0b00000000, 0b01100111,
-		0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b00001000, 0b00000000, 0b01110111, 0b00011111,
-		0b00001101, 0b00111101, 0b01001111, 0b01000111, 0b00000000, 0b00110111,
-		0b00000000, 0b00000000, 0b00000000, 0b00001110, 0b00000000, 0b00010101,
-		0b00011101, 0b01100111, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
-		0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000 };
-
-
-MAX7219::MAX7219(SPI *spi, int numDevices) {
-	assert(spi != nullptr);
-	this->spi = spi;
-	if (numDevices <= 0 || numDevices > 8) {
-		numDevices = 8;
-	}
-	maxDevices = numDevices;
-
-	for (int i = 0; i < 64; i++) {
-		status[i] = 0x00;
-	}
-	for (int i = 0; i < maxDevices; i++) {
-		spiTransfer(i, OP_DISPLAYTEST, 0);
-		//scanlimit is set to max on startup
-		setScanLimit(7, i);
-		//decode is done in source
-		spiTransfer(i, OP_DECODEMODE, 0);
-		clearDisplay(i);
-		//we go into shutdown-mode on startup
-		shutdown(true, i);
-	}
-}
-
-
-int MAX7219::getDeviceCount() {
-	return maxDevices;
-}
-
-
-void MAX7219::shutdown(bool b, int addr) {
-	if (addr < 0 || addr >= maxDevices)
-		return;
-	if (b) {
-		spiTransfer(addr, OP_SHUTDOWN, 0);
-	}
-	else {
-		spiTransfer(addr, OP_SHUTDOWN, 1);
-	}
-}
-
-
-void MAX7219::setScanLimit(int limit, int addr) {
-	if (addr < 0 || addr >= maxDevices) {
-		return;
-	}
-	if (limit >= 0 && limit < 8) {
-		spiTransfer(addr, OP_SCANLIMIT, limit);
-	}
-}
-
-
-void MAX7219::setIntensity(int intensity, int addr) {
-	if (addr < 0 || addr >= maxDevices) {
-		return;
-	}
-	if (intensity >= 0 && intensity < 16) {
-		spiTransfer(addr, OP_INTENSITY, intensity);
-	}
-}
-
-
-void MAX7219::clearDisplay(int addr) {
-	int offset;
-
-	if (addr < 0 || addr >= maxDevices) {
-		return;
-	}
-	offset = addr * 8;
-	for (int i = 0; i < 8; i++) {
-		status[offset + i] = 0;
-		spiTransfer(addr, i + 1, status[offset + i]);
-	}
-}
-
-
-void MAX7219::setLed(int row, int column, bool state, int addr) {
-	int offset;
-	uint8_t val = 0x00;
-
-	if (addr < 0 || addr >= maxDevices) {
-		return;
-	}
-	if (row < 0 || row > 7 || column < 0 || column > 7) {
-		return;
-	}
-	offset = addr * 8;
-	val = 0b10000000 >> column;
-	if (state) {
-		status[offset + row] = status[offset + row] | val;
-	}
-	else {
-		val = ~val;
-		status[offset + row] = status[offset + row] & val;
-	}
-	spiTransfer(addr, row + 1, status[offset + row]);
-}
-
-
-void MAX7219::setRow(int row, uint8_t value, int addr) {
-	int offset;
-	if (addr < 0 || addr >= maxDevices) {
-		return;
-	}
-	if (row < 0 || row > 7) {
-		return;
-	}
-	offset = addr * 8;
-	status[offset + row] = value;
-	spiTransfer(addr, row + 1, status[offset + row]);
-}
-
-
-void MAX7219::setColumn(int col, uint8_t value, int addr) {
-	uint8_t val;
-
-	if (addr < 0 || addr >= maxDevices) {
-		return;
-	}
-	if (col < 0 || col > 7) {
-		return;
-	}
-	for (int row = 0; row < 8; row++) {
-		val = value >> (7 - row);
-		val = val & 0x01;
-		setLed(row, col, val, addr);
-	}
-}
-
-
-void MAX7219::setDigit(int digit, uint8_t value, bool dp, int addr) {
-	int offset;
-	uint8_t v;
-
-	if (addr < 0 || addr >= maxDevices) {
-		return;
-	}
-	if (digit < 0 || digit > 7 || value > 15) {
-		return;
-	}
-	offset = addr * 8;
-	v = charTable[value];
-	if (dp) {
-		v |= 0b10000000;
-	}
-	status[offset + digit] = v;
-	spiTransfer(addr, digit + 1, v);
-}
-
-
-void MAX7219::setChar(int digit, char value, bool dp, int addr) {
-	int offset;
-	uint8_t index, v;
-
-	if (addr < 0 || addr >= maxDevices) {
-		return;
-	}
-	if (digit < 0 || digit > 7) {
-		return;
-	}
-	offset = addr * 8;
-	index = (uint8_t) value;
-	if (index > 127) {
-		//no defined beyond index 127, so we use the space char
-		index = 32;
-	}
-	v = charTable[index];
-	if (dp) {
-		v |= 0b10000000;
-	}
-	status[offset + digit] = v;
-	spiTransfer(addr, digit + 1, v);
-}
-
-
-void MAX7219::spiTransfer(int addr, volatile uint8_t opcode,	volatile uint8_t data) {
-	//Create an array with the data to shift out
-	int offset = addr * 2;
-	int maxbytes = maxDevices * 2;
-
-	/* The array for shifting the data to the devices */
-	uint8_t spidata[16];
-
-	for (int i = 0; i < maxbytes; i++) {
-		spidata[i] = (uint8_t) 0;
-	}
-	//put our device data into the array
-	spidata[offset] = opcode;
-	spidata[offset + 1] = data;
-	spi->transfer(spidata, maxbytes);
-}
-
-void MAX7219::setNumber(uint32_t number, int addr) {
-	//number = number % (uint32_t)pow(10, maxDevices);
-	for (auto i=0; i<8; i++) {
-		if (number == 0 && i > 0){
-			setChar(i, ' ', addr);
-		} else {
-			setDigit(i, number%10, addr);
-			number = number/10;
-		}
-	}
-}
diff --git a/components/cpp_utils/MAX7219.h b/components/cpp_utils/MAX7219.h
deleted file mode 100644
index b5ae41f..0000000
--- a/components/cpp_utils/MAX7219.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- *    LedControl.h - A library for controling Leds with a MAX7219/MAX7221
- *    Copyright (c) 2007 Eberhard Fahle
- *
- *    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:
- *
- *    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.
- */
-
-#ifndef MAX7219_h
-#define MAX7219_h
-
-#include <SPI.h>
-
-/**
- * @brief %MAX7219 and MAX7221 controller.
- *
- * This is a port of the Arduino [MAX7219 class](http://playground.arduino.cc/Main/MAX7219) to the ESP32.
- * We can attach multiple IC instances daisy chained together.  Each device has its own *address* with the
- * first device being 0 (the default).
- *
- * All the devices are in shutdown mode by default when we start.  Any devices that are to be used
- * must be taken out of shutdown mode with a call to:
- *
- * @code{.cpp}
- * shutdown(false);
- * @endcode
- *
- * For a given configuration, we are likely going to work with the %MAX7219 as either an 8 digit
- * 7 segment LED driver or an 8x8 led matrix.  Working with the two styles have similarities and
- * distinctions.  For the 7 segment LED, we will typically use setDigit(), setChar() and
- * setNumber() to set digits while in the 8x8 led matrix, we will use setLed(), setRow()
- * and setColumn().
- */
-class MAX7219 {
-private:
-
-	/* Send out a single command to the device */
-	void spiTransfer(int addr, uint8_t opcode, uint8_t data);
-
-	/* We keep track of the led-status for all 8 devices in this array */
-	uint8_t status[64];
-
-	/* The maximum number of devices we use */
-	int maxDevices;
-	SPI *spi;
-
-public:
-	/**
-	 * @brief Create a new %MAX7219 controller
-	 *
-	 * @param [in] spi %SPI controller.
-	 * @param [in] numDevices	maximum number of devices that can be controlled that are
-	 * daisy chained together.
-	 */
-	MAX7219(SPI *spi, int numDevices = 1);
-
-
-	/**
-	 * @brief Switch all Leds on the display off.
-	 *
-	 * @param [in] addr	Address of the display to control.
-	 */
-	void clearDisplay(int addr);
-
-
-	/**
-	 * @brief Gets the number of devices attached to this %MAX7219.
-	 * @return The number of devices on this %MAX7219.
-	 */
-	int getDeviceCount();
-
-
-	/**
-	 * @brief Display a character on a 7-Segment display.
-	 *
-	 * There are only a few characters that make sense here :
-	 *	'0','1','2','3','4','5','6','7','8','9','0',
-	 *  'A','b','c','d','E','F','H','L','P',
-	 *  '.','-','_',' '
-	 *
-	 * @param [in] digit	The position of the character on the display (0..7).
-	 * @param [in] value	The character to be displayed.
-	 * @param [in] dp	Sets the decimal point.
-	 * @param [in] addr	Address of the display.
-	 */
-	void setChar(int digit, char value, bool dp=false, int addr=0);
-
-
-	/**
-	 * @brief Set all 8 Led's in a column to a new state.
-	 *
-	 * @param [in] col	column which is to be set (0..7).
-	 * @param [in] value	each bit set to 1 will light up the corresponding Led.
-	 * @param [in] addr	address of the display.
-	 */
-	void setColumn(int col, uint8_t value, int addr=0);
-
-
-	/**
-	 * @brief Display a hexadecimal digit on a 7-Segment Display
-	 *
-	 * @param [in] digit	The position of the digit on the display (0..7).
-	 * @param [in] value	The value to be displayed. (0x00..0x0F).
-	 * @param [in] dp	Sets the decimal point.
-	 * @param [in] addr	Address of the display.
-	 */
-	void setDigit(int digit, uint8_t value, bool dp=false, int addr=0);
-
-
-	/**
-	 * @brief Set the brightness of the display.
-	 *
-	 * @param [in] intensity	the brightness of the display. (0..15).
-	 * @param [in] addr		The address of the display to control.
-	 */
-	void setIntensity(int intensity, int addr=0);
-
-
-	/**
-	 * @brief Set the status of a single Led.
-	 *
-	 * @param [in] row	The row of the Led (0..7).
-	 * @param [in] col	The column of the Led (0..7).
-	 * @param [in] state	If true the led is switched on, if false it is switched off.
-	 * @param [in] addr	Address of the display.
-	 */
-	void setLed(int row, int col, bool state, int addr=0);
-
-
-	/**
-	 * @brief Display a number on the 7-Segment display.
-	 *
-	 * A non negative whole number that is 8 digits or less is displayed.
-	 *
-	 * @param [in] number The number to display.
-	 * @param [in] addr	Address of the display.
-	 */
-	void setNumber(uint32_t number, int addr=0);
-
-
-	/**
-	 * @brief Set all 8 Led's in a row to a new state
-	 *
-	 * @param [in] row	Row which is to be set (0..7).
-	 * @param [in] value	Each bit set to 1 will light up the corresponding Led.
-	 * @param [in] addr	Address of the display.
-	 */
-	void setRow(int row, uint8_t value, int addr=0);
-
-
-	/**
-	 * @brief Set the number of digits (or rows) to be displayed.
-	 * See datasheet for side effects of the scanlimit on the brightness
-	 * of the display.
-	 *
-	 *
-	 * @param [in] limit	Number of digits to be displayed (1..8).
-	 * @param [in] addr	Address of the display to control.
-	 */
-	void setScanLimit(int limit, int addr=0);
-
-
-	/**
-	 * @brief Set the shutdown (power saving) mode for the device.
-	 *
-	 * @param [in] status	If true the device goes into power-down mode. Set to false
-	 *		for normal operation.
-	 * @param [in] addr	The address of the display to control.
-	 */
-	void shutdown(bool status, int addr=0);
-
-};
-
-#endif	// MAX7219.h
-
diff --git a/components/cpp_utils/MFRC522.cpp b/components/cpp_utils/MFRC522.cpp
deleted file mode 100644
index a860e9b..0000000
--- a/components/cpp_utils/MFRC522.cpp
+++ /dev/null
@@ -1,1645 +0,0 @@
-/*
-* MFRC522.cpp - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
-* NOTE: Please also check the comments in MFRC522.h - they provide useful hints and background information.
-* Released into the public domain.
-*/
-
-/*
- * Notes:
- * This source file modified from the Github project found here:
- *
- * https://github.com/miguelbalboa/rfid
- *
- * Changes made to accommodate native ESP32 and ESP32 C++ class wrappers.
- *
- * Neil Kolban, July 2017.
- *
- */
-
-#include "MFRC522.h"
-#include "MFRC522Debug.h"
-#include <FreeRTOS.h>
-#include <GPIO.h>
-#include <string.h>
-#include <sstream>
-#include <iomanip>
-#include <esp_log.h>
-
-static const char LOG_TAG[] = "MFRC522";
-
-//#include "MFRC522Debug.h"
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Functions for setting up the Arduino
-/////////////////////////////////////////////////////////////////////////////////////
-
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Basic interface functions for communicating with the MFRC522
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Writes a byte to the specified register in the MFRC522 chip.
- * The interface is described in the datasheet section 8.1.2.
- */
-void MFRC522::PCD_WriteRegister(
-		PCD_Register reg,	///< The register to write to. One of the PCD_Register enums.
-		byte value			  ///< The value to write.
-	) {
-	uint8_t data[2];
-	data[0] = reg;
-	data[1] = value;
-	m_spi.transfer(data, 2);
-} // End PCD_WriteRegister()
-
-/**
- * Writes a number of bytes to the specified register in the MFRC522 chip.
- * The interface is described in the datasheet section 8.1.2.
- */
-void MFRC522::PCD_WriteRegister(	PCD_Register reg,	///< The register to write to. One of the PCD_Register enums.
-									byte count,			///< The number of bytes to write to the register
-									byte *values		///< The values to write. Byte array.
-								) {
-	uint8_t* pData = new uint8_t[count+1];
-	pData[0] = reg;
-	memcpy(pData+1, values, count);
-	m_spi.transfer(pData, count+1);
-	delete[] pData;
-} // End PCD_WriteRegister()
-
-
-/**
- * Reads a byte from the specified register in the MFRC522 chip.
- * The interface is described in the datasheet section 8.1.2.
- */
-byte MFRC522::PCD_ReadRegister(	PCD_Register reg	///< The register to read from. One of the PCD_Register enums.
-								) {
-	uint8_t data[2];
-	data[0] = reg | 0x80;
-	data[1] = 0;
-	m_spi.transfer(data, 2);
-	return data[1];
-} // End PCD_ReadRegister()
-
-/**
- * Reads a number of bytes from the specified register in the MFRC522 chip.
- * The interface is described in the datasheet section 8.1.2.
- */
-void MFRC522::PCD_ReadRegister(	PCD_Register reg,	///< The register to read from. One of the PCD_Register enums.
-								byte count,			///< The number of bytes to read
-								byte *values,		///< Byte array to store the values in.
-								byte rxAlign		///< Only bit positions rxAlign..7 in values[0] are updated.
-								) {
-	if (count == 0) {
-		return;
-	}
-	//Serial.print(F("Reading ")); 	Serial.print(count); Serial.println(F(" bytes from register."));
-	byte address = 0x80 | reg;				// MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
-	byte index = 0;							// Index in values array.
-	count--;								// One read is performed outside of the loop
-	m_spi.transferByte(address);					// Tell MFRC522 which address we want to read
-	if (rxAlign) {		// Only update bit positions rxAlign..7 in values[0]
-		// Create bit mask for bit positions rxAlign..7
-		byte mask = (0xFF << rxAlign) & 0xFF;
-		// Read value and tell that we want to read the same address again.
-		byte value = m_spi.transferByte(address);
-		// Apply mask to both current value of values[0] and the new data in value.
-		values[0] = (values[0] & ~mask) | (value & mask);
-		index++;
-	}
-	while (index < count) {
-		values[index] = m_spi.transferByte(address);	// Read value and tell that we want to read the same address again.
-		index++;
-	}
-	values[index] = m_spi.transferByte(0);			// Read the final byte. Send 0 to stop reading.
-} // End PCD_ReadRegister()
-
-/**
- * Sets the bits given in mask in register reg.
- */
-void MFRC522::PCD_SetRegisterBitMask(	PCD_Register reg,	///< The register to update. One of the PCD_Register enums.
-										byte mask			///< The bits to set.
-									) {
-	byte tmp;
-	tmp = PCD_ReadRegister(reg);
-	PCD_WriteRegister(reg, tmp | mask);			// set bit mask
-} // End PCD_SetRegisterBitMask()
-
-/**
- * Clears the bits given in mask from register reg.
- */
-void MFRC522::PCD_ClearRegisterBitMask(	PCD_Register reg,	///< The register to update. One of the PCD_Register enums.
-										byte mask			///< The bits to clear.
-									  ) {
-	byte tmp;
-	tmp = PCD_ReadRegister(reg);
-	PCD_WriteRegister(reg, tmp & (~mask));		// clear bit mask
-} // End PCD_ClearRegisterBitMask()
-
-
-/**
- * Use the CRC coprocessor in the MFRC522 to calculate a CRC_A.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PCD_CalculateCRC(	byte *data,		///< In: Pointer to the data to transfer to the FIFO for CRC calculation.
-												byte length,	///< In: The number of bytes to transfer.
-												byte *result	///< Out: Pointer to result buffer. Result is written to result[0..1], low byte first.
-					 ) {
-	PCD_WriteRegister(CommandReg, PCD_Idle);		// Stop any active command.
-	PCD_WriteRegister(DivIrqReg, 0x04);				// Clear the CRCIRq interrupt request bit
-	PCD_WriteRegister(FIFOLevelReg, 0x80);			// FlushBuffer = 1, FIFO initialization
-	PCD_WriteRegister(FIFODataReg, length, data);	// Write data to the FIFO
-	PCD_WriteRegister(CommandReg, PCD_CalcCRC);		// Start the calculation
-
-	// Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73μs.
-	// TODO check/modify for other architectures than Arduino Uno 16bit
-
-	// Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73us.
-	for (uint16_t i = 5000; i > 0; i--) {
-		// DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq reserved CRCIRq reserved reserved
-		byte n = PCD_ReadRegister(DivIrqReg);
-		if (n & 0x04) {									// CRCIRq bit set - calculation done
-			PCD_WriteRegister(CommandReg, PCD_Idle);	// Stop calculating CRC for new content in the FIFO.
-			// Transfer the result from the registers to the result buffer
-			result[0] = PCD_ReadRegister(CRCResultRegL);
-			result[1] = PCD_ReadRegister(CRCResultRegH);
-			return STATUS_OK;
-		}
-	}
-	// 89ms passed and nothing happend. Communication with the MFRC522 might be down.
-	return STATUS_TIMEOUT;
-} // End PCD_CalculateCRC()
-
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Functions for manipulating the MFRC522
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Initializes the MFRC522 chip.
- */
-void MFRC522::PCD_Init() {
-	//m_spi.setHost(VSPI_HOST);
-	m_spi.init();
-
-	bool hardReset = false;
-
-
-	// Set the chipSelectPin as digital output, do not select the slave yet
-/*
-	pinMode(_chipSelectPin, OUTPUT);
-	digitalWrite(_chipSelectPin, HIGH);
-*/
-	// If a valid pin number has been set, pull device out of power down / reset state.
-	if (_resetPowerDownPin != UNUSED_PIN) {
-		// Set the resetPowerDownPin as digital output, do not reset or power down.
-		//pinMode(_resetPowerDownPin, OUTPUT);
-		ESP32CPP::GPIO::setInput((gpio_num_t)_resetPowerDownPin);
-
-		if (ESP32CPP::GPIO::read((gpio_num_t)_resetPowerDownPin) == false) {	// The MFRC522 chip is in power down mode.
-			ESP32CPP::GPIO::setOutput((gpio_num_t)_resetPowerDownPin);
-			ESP32CPP::GPIO::high((gpio_num_t)_resetPowerDownPin);		// Exit power down mode. This triggers a hard reset.
-			// Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74μs. Let us be generous: 50ms.
-			FreeRTOS::sleep(50);
-			hardReset = true;
-		}
-	}
-
-
-	if (!hardReset) { // Perform a soft reset if we haven't triggered a hard reset above.
-		PCD_Reset();
-	}
-
-	// Reset baud rates
-	PCD_WriteRegister(TxModeReg, 0x00);
-	PCD_WriteRegister(RxModeReg, 0x00);
-	// Reset ModWidthReg
-	PCD_WriteRegister(ModWidthReg, 0x26);
-
-	// When communicating with a PICC we need a timeout if something goes wrong.
-	// f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
-	// TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
-	PCD_WriteRegister(TModeReg, 0x80);			// TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
-	PCD_WriteRegister(TPrescalerReg, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
-	PCD_WriteRegister(TReloadRegH, 0x03);		// Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
-	PCD_WriteRegister(TReloadRegL, 0xE8);
-
-	PCD_WriteRegister(TxASKReg, 0x40);		// Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
-	PCD_WriteRegister(ModeReg, 0x3D);		// Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4)
-	PCD_AntennaOn();						// Enable the antenna driver pins TX1 and TX2 (they were disabled by the reset)
-} // End PCD_Init()
-
-/**
- * Initializes the MFRC522 chip.
- */
-void MFRC522::PCD_Init(	byte chipSelectPin,		///< Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
-						byte resetPowerDownPin	///< Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
-					) {
-	_chipSelectPin = chipSelectPin;
-	_resetPowerDownPin = resetPowerDownPin;
-	// Set the chipSelectPin as digital output, do not select the slave yet
-	PCD_Init();
-} // End PCD_Init()
-
-/**
- * Performs a soft reset on the MFRC522 chip and waits for it to be ready again.
- */
-void MFRC522::PCD_Reset() {
-	PCD_WriteRegister(CommandReg, PCD_SoftReset);	// Issue the SoftReset command.
-	// The datasheet does not mention how long the SoftRest command takes to complete.
-	// But the MFRC522 might have been in soft power-down mode (triggered by bit 4 of CommandReg)
-	// Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74μs. Let us be generous: 50ms.
-	FreeRTOS::sleep(50);
-	// Wait for the PowerDown bit in CommandReg to be cleared
-	while (PCD_ReadRegister(CommandReg) & (1<<4)) {
-		// PCD still restarting - unlikely after waiting 50ms, but better safe than sorry.
-	}
-} // End PCD_Reset()
-
-/**
- * Turns the antenna on by enabling pins TX1 and TX2.
- * After a reset these pins are disabled.
- */
-void MFRC522::PCD_AntennaOn() {
-	byte value = PCD_ReadRegister(TxControlReg);
-	if ((value & 0x03) != 0x03) {
-		PCD_WriteRegister(TxControlReg, value | 0x03);
-	}
-} // End PCD_AntennaOn()
-
-/**
- * Turns the antenna off by disabling pins TX1 and TX2.
- */
-void MFRC522::PCD_AntennaOff() {
-	PCD_ClearRegisterBitMask(TxControlReg, 0x03);
-} // End PCD_AntennaOff()
-
-/**
- * Get the current MFRC522 Receiver Gain (RxGain[2:0]) value.
- * See 9.3.3.6 / table 98 in http://www.nxp.com/documents/data_sheet/MFRC522.pdf
- * NOTE: Return value scrubbed with (0x07<<4)=01110000b as RCFfgReg may use reserved bits.
- *
- * @return Value of the RxGain, scrubbed to the 3 bits used.
- */
-byte MFRC522::PCD_GetAntennaGain() {
-	return PCD_ReadRegister(RFCfgReg) & (0x07<<4);
-} // End PCD_GetAntennaGain()
-
-/**
- * Set the MFRC522 Receiver Gain (RxGain) to value specified by given mask.
- * See 9.3.3.6 / table 98 in http://www.nxp.com/documents/data_sheet/MFRC522.pdf
- * NOTE: Given mask is scrubbed with (0x07<<4)=01110000b as RCFfgReg may use reserved bits.
- */
-void MFRC522::PCD_SetAntennaGain(byte mask) {
-	if (PCD_GetAntennaGain() != mask) {						// only bother if there is a change
-		PCD_ClearRegisterBitMask(RFCfgReg, (0x07<<4));		// clear needed to allow 000 pattern
-		PCD_SetRegisterBitMask(RFCfgReg, mask & (0x07<<4));	// only set RxGain[2:0] bits
-	}
-} // End PCD_SetAntennaGain()
-
-/**
- * Performs a self-test of the MFRC522
- * See 16.1.1 in http://www.nxp.com/documents/data_sheet/MFRC522.pdf
- *
- * @return Whether or not the test passed. Or false if no firmware reference is available.
- */
-bool MFRC522::PCD_PerformSelfTest() {
-	// This follows directly the steps outlined in 16.1.1
-	// 1. Perform a soft reset.
-	PCD_Reset();
-
-	// 2. Clear the internal buffer by writing 25 bytes of 00h
-	byte ZEROES[25] = {0x00};
-	PCD_WriteRegister(FIFOLevelReg, 0x80);		// flush the FIFO buffer
-	PCD_WriteRegister(FIFODataReg, 25, ZEROES);	// write 25 bytes of 00h to FIFO
-	PCD_WriteRegister(CommandReg, PCD_Mem);		// transfer to internal buffer
-
-	// 3. Enable self-test
-	PCD_WriteRegister(AutoTestReg, 0x09);
-
-	// 4. Write 00h to FIFO buffer
-	PCD_WriteRegister(FIFODataReg, 0x00);
-
-	// 5. Start self-test by issuing the CalcCRC command
-	PCD_WriteRegister(CommandReg, PCD_CalcCRC);
-
-	// 6. Wait for self-test to complete
-	byte n;
-	for (uint8_t i = 0; i < 0xFF; i++) {
-		// The datasheet does not specify exact completion condition except
-		// that FIFO buffer should contain 64 bytes.
-		// While selftest is initiated by CalcCRC command
-		// it behaves differently from normal CRC computation,
-		// so one can't reliably use DivIrqReg to check for completion.
-		// It is reported that some devices does not trigger CRCIRq flag
-		// during selftest.
-		n = PCD_ReadRegister(FIFOLevelReg);
-		if (n >= 64) {
-			break;
-		}
-	}
-	PCD_WriteRegister(CommandReg, PCD_Idle);		// Stop calculating CRC for new content in the FIFO.
-
-	// 7. Read out resulting 64 bytes from the FIFO buffer.
-	byte result[64];
-	PCD_ReadRegister(FIFODataReg, 64, result, 0);
-
-	// Auto self-test done
-	// Reset AutoTestReg register to be 0 again. Required for normal operation.
-	PCD_WriteRegister(AutoTestReg, 0x00);
-
-	// Determine firmware version (see section 9.3.4.8 in spec)
-	byte version = PCD_ReadRegister(VersionReg);
-
-	// Pick the appropriate reference values
-	const byte *reference;
-	switch (version) {
-		case 0x88:	// Fudan Semiconductor FM17522 clone
-			reference = FM17522_firmware_reference;
-			break;
-		case 0x90:	// Version 0.0
-			reference = MFRC522_firmware_referenceV0_0;
-			break;
-		case 0x91:	// Version 1.0
-			reference = MFRC522_firmware_referenceV1_0;
-			break;
-		case 0x92:	// Version 2.0
-			reference = MFRC522_firmware_referenceV2_0;
-			break;
-		default:	// Unknown version
-			return false; // abort test
-	}
-
-	// Verify that the results match up to our expectations
-	for (uint8_t i = 0; i < 64; i++) {
-		if (result[i] != (reference[i])) {
-			return false;
-		}
-	}
-
-	// Test passed; all is good.
-	return true;
-} // End PCD_PerformSelfTest()
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Functions for communicating with PICCs
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Executes the Transceive command.
- * CRC validation can only be done if backData and backLen are specified.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PCD_TransceiveData(	byte *sendData,		///< Pointer to the data to transfer to the FIFO.
-													byte sendLen,		///< Number of bytes to transfer to the FIFO.
-													byte *backData,		///< nullptr or pointer to buffer if data should be read back after executing the command.
-													byte *backLen,		///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
-													byte *validBits,	///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits. Default nullptr.
-													byte rxAlign,		///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
-													bool checkCRC		///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
-								 ) {
-	byte waitIRq = 0x30;		// RxIRq and IdleIRq
-	return PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, sendData, sendLen, backData, backLen, validBits, rxAlign, checkCRC);
-} // End PCD_TransceiveData()
-
-/**
- * Transfers data to the MFRC522 FIFO, executes a command, waits for completion and transfers data back from the FIFO.
- * CRC validation can only be done if backData and backLen are specified.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PCD_CommunicateWithPICC(	byte command,		///< The command to execute. One of the PCD_Command enums.
-														byte waitIRq,		///< The bits in the ComIrqReg register that signals successful completion of the command.
-														byte *sendData,		///< Pointer to the data to transfer to the FIFO.
-														byte sendLen,		///< Number of bytes to transfer to the FIFO.
-														byte *backData,		///< nullptr or pointer to buffer if data should be read back after executing the command.
-														byte *backLen,		///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
-														byte *validBits,	///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits.
-														byte rxAlign,		///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
-														bool checkCRC		///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
-									 ) {
-	// Prepare values for BitFramingReg
-	byte txLastBits = validBits ? *validBits : 0;
-	byte bitFraming = (rxAlign << 4) + txLastBits;		// RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
-
-	PCD_WriteRegister(CommandReg, PCD_Idle);			// Stop any active command.
-	PCD_WriteRegister(ComIrqReg, 0x7F);					// Clear all seven interrupt request bits
-	PCD_WriteRegister(FIFOLevelReg, 0x80);				// FlushBuffer = 1, FIFO initialization
-	PCD_WriteRegister(FIFODataReg, sendLen, sendData);	// Write sendData to the FIFO
-	PCD_WriteRegister(BitFramingReg, bitFraming);		// Bit adjustments
-	PCD_WriteRegister(CommandReg, command);				// Execute the command
-	if (command == PCD_Transceive) {
-		PCD_SetRegisterBitMask(BitFramingReg, 0x80);	// StartSend=1, transmission of data starts
-	}
-
-	// Wait for the command to complete.
-	// In PCD_Init() we set the TAuto flag in TModeReg. This means the timer automatically starts when the PCD stops transmitting.
-	// Each iteration of the do-while-loop takes 17.86μs.
-	// TODO check/modify for other architectures than Arduino Uno 16bit
-	uint16_t i;
-	for (i = 2000; i > 0; i--) {
-		byte n = PCD_ReadRegister(ComIrqReg);	// ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
-		if (n & waitIRq) {					// One of the interrupts that signal success has been set.
-			break;
-		}
-		if (n & 0x01) {						// Timer interrupt - nothing received in 25ms
-			return STATUS_TIMEOUT;
-		}
-	}
-	// 35.7ms and nothing happend. Communication with the MFRC522 might be down.
-	if (i == 0) {
-		return STATUS_TIMEOUT;
-	}
-
-	// Stop now if any errors except collisions were detected.
-	byte errorRegValue = PCD_ReadRegister(ErrorReg); // ErrorReg[7..0] bits are: WrErr TempErr reserved BufferOvfl CollErr CRCErr ParityErr ProtocolErr
-	if (errorRegValue & 0x13) {	 // BufferOvfl ParityErr ProtocolErr
-		return STATUS_ERROR;
-	}
-
-	byte _validBits = 0;
-
-	// If the caller wants data back, get it from the MFRC522.
-	if (backData && backLen) {
-		byte n = PCD_ReadRegister(FIFOLevelReg);	// Number of bytes in the FIFO
-		if (n > *backLen) {
-			return STATUS_NO_ROOM;
-		}
-		*backLen = n;											// Number of bytes returned
-		PCD_ReadRegister(FIFODataReg, n, backData, rxAlign);	// Get received data from FIFO
-		_validBits = PCD_ReadRegister(ControlReg) & 0x07;		// RxLastBits[2:0] indicates the number of valid bits in the last received byte. If this value is 000b, the whole byte is valid.
-		if (validBits) {
-			*validBits = _validBits;
-		}
-	}
-
-	// Tell about collisions
-	if (errorRegValue & 0x08) {		// CollErr
-		return STATUS_COLLISION;
-	}
-
-	// Perform CRC_A validation if requested.
-	if (backData && backLen && checkCRC) {
-		// In this case a MIFARE Classic NAK is not OK.
-		if (*backLen == 1 && _validBits == 4) {
-			return STATUS_MIFARE_NACK;
-		}
-		// We need at least the CRC_A value and all 8 bits of the last byte must be received.
-		if (*backLen < 2 || _validBits != 0) {
-			return STATUS_CRC_WRONG;
-		}
-		// Verify CRC_A - do our own calculation and store the control in controlBuffer.
-		byte controlBuffer[2];
-		MFRC522::StatusCode status = PCD_CalculateCRC(&backData[0], *backLen - 2, &controlBuffer[0]);
-		if (status != STATUS_OK) {
-			return status;
-		}
-		if ((backData[*backLen - 2] != controlBuffer[0]) || (backData[*backLen - 1] != controlBuffer[1])) {
-			return STATUS_CRC_WRONG;
-		}
-	}
-
-	return STATUS_OK;
-} // End PCD_CommunicateWithPICC()
-
-/**
- * Transmits a REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
- * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PICC_RequestA(	byte *bufferATQA,	///< The buffer to store the ATQA (Answer to request) in
-											byte *bufferSize	///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
-										) {
-	return PICC_REQA_or_WUPA(PICC_CMD_REQA, bufferATQA, bufferSize);
-} // End PICC_RequestA()
-
-/**
- * Transmits a Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
- * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PICC_WakeupA(	byte *bufferATQA,	///< The buffer to store the ATQA (Answer to request) in
-											byte *bufferSize	///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
-										) {
-	return PICC_REQA_or_WUPA(PICC_CMD_WUPA, bufferATQA, bufferSize);
-} // End PICC_WakeupA()
-
-/**
- * Transmits REQA or WUPA commands.
- * Beware: When two PICCs are in the field at the same time I often get STATUS_TIMEOUT - probably due do bad antenna design.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PICC_REQA_or_WUPA(	byte command, 		///< The command to send - PICC_CMD_REQA or PICC_CMD_WUPA
-												byte *bufferATQA,	///< The buffer to store the ATQA (Answer to request) in
-												byte *bufferSize	///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
-											) {
-	byte validBits;
-	MFRC522::StatusCode status;
-
-	if (bufferATQA == nullptr || *bufferSize < 2) {	// The ATQA response is 2 bytes long.
-		return STATUS_NO_ROOM;
-	}
-	PCD_ClearRegisterBitMask(CollReg, 0x80);		// ValuesAfterColl=1 => Bits received after collision are cleared.
-	validBits = 7;									// For REQA and WUPA we need the short frame format - transmit only 7 bits of the last (and only) byte. TxLastBits = BitFramingReg[2..0]
-	status = PCD_TransceiveData(&command, 1, bufferATQA, bufferSize, &validBits);
-	if (status != STATUS_OK) {
-		return status;
-	}
-	if (*bufferSize != 2 || validBits != 0) {		// ATQA must be exactly 16 bits.
-		return STATUS_ERROR;
-	}
-	return STATUS_OK;
-} // End PICC_REQA_or_WUPA()
-
-/**
- * Transmits SELECT/ANTICOLLISION commands to select a single PICC.
- * Before calling this function the PICCs must be placed in the READY(*) state by calling PICC_RequestA() or PICC_WakeupA().
- * On success:
- * 		- The chosen PICC is in state ACTIVE(*) and all other PICCs have returned to state IDLE/HALT. (Figure 7 of the ISO/IEC 14443-3 draft.)
- * 		- The UID size and value of the chosen PICC is returned in *uid along with the SAK.
- *
- * A PICC UID consists of 4, 7 or 10 bytes.
- * Only 4 bytes can be specified in a SELECT command, so for the longer UIDs two or three iterations are used:
- * 		UID size	Number of UID bytes		Cascade levels		Example of PICC
- * 		========	===================		==============		===============
- * 		single				 4						1				MIFARE Classic
- * 		double				 7						2				MIFARE Ultralight
- * 		triple				10						3				Not currently in use?
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PICC_Select(	Uid *uid,			///< Pointer to Uid struct. Normally output, but can also be used to supply a known UID.
-											byte validBits		///< The number of known UID bits supplied in *uid. Normally 0. If set you must also supply uid->size.
-										 ) {
-	bool uidComplete;
-	bool selectDone;
-	bool useCascadeTag;
-	byte cascadeLevel = 1;
-	MFRC522::StatusCode result;
-	byte count;
-	byte index;
-	byte uidIndex;					// The first index in uid->uidByte[] that is used in the current Cascade Level.
-	int8_t currentLevelKnownBits;		// The number of known UID bits in the current Cascade Level.
-	byte buffer[9];					// The SELECT/ANTICOLLISION commands uses a 7 byte standard frame + 2 bytes CRC_A
-	byte bufferUsed;				// The number of bytes used in the buffer, ie the number of bytes to transfer to the FIFO.
-	byte rxAlign;					// Used in BitFramingReg. Defines the bit position for the first bit received.
-	byte txLastBits;				// Used in BitFramingReg. The number of valid bits in the last transmitted byte.
-	byte *responseBuffer;
-	byte responseLength;
-
-	// Description of buffer structure:
-	//		Byte 0: SEL 				Indicates the Cascade Level: PICC_CMD_SEL_CL1, PICC_CMD_SEL_CL2 or PICC_CMD_SEL_CL3
-	//		Byte 1: NVB					Number of Valid Bits (in complete command, not just the UID): High nibble: complete bytes, Low nibble: Extra bits.
-	//		Byte 2: UID-data or CT		See explanation below. CT means Cascade Tag.
-	//		Byte 3: UID-data
-	//		Byte 4: UID-data
-	//		Byte 5: UID-data
-	//		Byte 6: BCC					Block Check Character - XOR of bytes 2-5
-	//		Byte 7: CRC_A
-	//		Byte 8: CRC_A
-	// The BCC and CRC_A are only transmitted if we know all the UID bits of the current Cascade Level.
-	//
-	// Description of bytes 2-5: (Section 6.5.4 of the ISO/IEC 14443-3 draft: UID contents and cascade levels)
-	//		UID size	Cascade level	Byte2	Byte3	Byte4	Byte5
-	//		========	=============	=====	=====	=====	=====
-	//		 4 bytes		1			uid0	uid1	uid2	uid3
-	//		 7 bytes		1			CT		uid0	uid1	uid2
-	//						2			uid3	uid4	uid5	uid6
-	//		10 bytes		1			CT		uid0	uid1	uid2
-	//						2			CT		uid3	uid4	uid5
-	//						3			uid6	uid7	uid8	uid9
-
-	// Sanity checks
-	if (validBits > 80) {
-		return STATUS_INVALID;
-	}
-
-	// Prepare MFRC522
-	PCD_ClearRegisterBitMask(CollReg, 0x80);		// ValuesAfterColl=1 => Bits received after collision are cleared.
-
-	// Repeat Cascade Level loop until we have a complete UID.
-	uidComplete = false;
-	while (!uidComplete) {
-		// Set the Cascade Level in the SEL byte, find out if we need to use the Cascade Tag in byte 2.
-		switch (cascadeLevel) {
-			case 1:
-				buffer[0] = PICC_CMD_SEL_CL1;
-				uidIndex = 0;
-				useCascadeTag = validBits && uid->size > 4;	// When we know that the UID has more than 4 bytes
-				break;
-
-			case 2:
-				buffer[0] = PICC_CMD_SEL_CL2;
-				uidIndex = 3;
-				useCascadeTag = validBits && uid->size > 7;	// When we know that the UID has more than 7 bytes
-				break;
-
-			case 3:
-				buffer[0] = PICC_CMD_SEL_CL3;
-				uidIndex = 6;
-				useCascadeTag = false;						// Never used in CL3.
-				break;
-
-			default:
-				return STATUS_INTERNAL_ERROR;
-				break;
-		}
-
-		// How many UID bits are known in this Cascade Level?
-		currentLevelKnownBits = validBits - (8 * uidIndex);
-		if (currentLevelKnownBits < 0) {
-			currentLevelKnownBits = 0;
-		}
-		// Copy the known bits from uid->uidByte[] to buffer[]
-		index = 2; // destination index in buffer[]
-		if (useCascadeTag) {
-			buffer[index++] = PICC_CMD_CT;
-		}
-		byte bytesToCopy = currentLevelKnownBits / 8 + (currentLevelKnownBits % 8 ? 1 : 0); // The number of bytes needed to represent the known bits for this level.
-		if (bytesToCopy) {
-			byte maxBytes = useCascadeTag ? 3 : 4; // Max 4 bytes in each Cascade Level. Only 3 left if we use the Cascade Tag
-			if (bytesToCopy > maxBytes) {
-				bytesToCopy = maxBytes;
-			}
-			for (count = 0; count < bytesToCopy; count++) {
-				buffer[index++] = uid->uidByte[uidIndex + count];
-			}
-		}
-		// Now that the data has been copied we need to include the 8 bits in CT in currentLevelKnownBits
-		if (useCascadeTag) {
-			currentLevelKnownBits += 8;
-		}
-
-		// Repeat anti collision loop until we can transmit all UID bits + BCC and receive a SAK - max 32 iterations.
-		selectDone = false;
-		while (!selectDone) {
-			// Find out how many bits and bytes to send and receive.
-			if (currentLevelKnownBits >= 32) { // All UID bits in this Cascade Level are known. This is a SELECT.
-				//Serial.print(F("SELECT: currentLevelKnownBits=")); Serial.println(currentLevelKnownBits, DEC);
-				buffer[1] = 0x70; // NVB - Number of Valid Bits: Seven whole bytes
-				// Calculate BCC - Block Check Character
-				buffer[6] = buffer[2] ^ buffer[3] ^ buffer[4] ^ buffer[5];
-				// Calculate CRC_A
-				result = PCD_CalculateCRC(buffer, 7, &buffer[7]);
-				if (result != STATUS_OK) {
-					return result;
-				}
-				txLastBits		= 0; // 0 => All 8 bits are valid.
-				bufferUsed		= 9;
-				// Store response in the last 3 bytes of buffer (BCC and CRC_A - not needed after tx)
-				responseBuffer	= &buffer[6];
-				responseLength	= 3;
-			}
-			else { // This is an ANTICOLLISION.
-				//Serial.print(F("ANTICOLLISION: currentLevelKnownBits=")); Serial.println(currentLevelKnownBits, DEC);
-				txLastBits		= currentLevelKnownBits % 8;
-				count			= currentLevelKnownBits / 8;	// Number of whole bytes in the UID part.
-				index			= 2 + count;					// Number of whole bytes: SEL + NVB + UIDs
-				buffer[1]		= (index << 4) + txLastBits;	// NVB - Number of Valid Bits
-				bufferUsed		= index + (txLastBits ? 1 : 0);
-				// Store response in the unused part of buffer
-				responseBuffer	= &buffer[index];
-				responseLength	= sizeof(buffer) - index;
-			}
-
-			// Set bit adjustments
-			rxAlign = txLastBits;											// Having a separate variable is overkill. But it makes the next line easier to read.
-			PCD_WriteRegister(BitFramingReg, (rxAlign << 4) + txLastBits);	// RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
-
-			// Transmit the buffer and receive the response.
-			result = PCD_TransceiveData(buffer, bufferUsed, responseBuffer, &responseLength, &txLastBits, rxAlign);
-			if (result == STATUS_COLLISION) { // More than one PICC in the field => collision.
-				byte valueOfCollReg = PCD_ReadRegister(CollReg); // CollReg[7..0] bits are: ValuesAfterColl reserved CollPosNotValid CollPos[4:0]
-				if (valueOfCollReg & 0x20) { // CollPosNotValid
-					return STATUS_COLLISION; // Without a valid collision position we cannot continue
-				}
-				byte collisionPos = valueOfCollReg & 0x1F; // Values 0-31, 0 means bit 32.
-				if (collisionPos == 0) {
-					collisionPos = 32;
-				}
-				if (collisionPos <= currentLevelKnownBits) { // No progress - should not happen
-					return STATUS_INTERNAL_ERROR;
-				}
-				// Choose the PICC with the bit set.
-				currentLevelKnownBits = collisionPos;
-				count			= (currentLevelKnownBits - 1) % 8; // The bit to modify
-				index			= 1 + (currentLevelKnownBits / 8) + (count ? 1 : 0); // First byte is index 0.
-				buffer[index]	|= (1 << count);
-			}
-			else if (result != STATUS_OK) {
-				return result;
-			}
-			else { // STATUS_OK
-				if (currentLevelKnownBits >= 32) { // This was a SELECT.
-					selectDone = true; // No more anticollision
-					// We continue below outside the while.
-				}
-				else { // This was an ANTICOLLISION.
-					// We now have all 32 bits of the UID in this Cascade Level
-					currentLevelKnownBits = 32;
-					// Run loop again to do the SELECT.
-				}
-			}
-		} // End of while (!selectDone)
-
-		// We do not check the CBB - it was constructed by us above.
-
-		// Copy the found UID bytes from buffer[] to uid->uidByte[]
-		index			= (buffer[2] == PICC_CMD_CT) ? 3 : 2; // source index in buffer[]
-		bytesToCopy		= (buffer[2] == PICC_CMD_CT) ? 3 : 4;
-		for (count = 0; count < bytesToCopy; count++) {
-			uid->uidByte[uidIndex + count] = buffer[index++];
-		}
-
-		// Check response SAK (Select Acknowledge)
-		if (responseLength != 3 || txLastBits != 0) { // SAK must be exactly 24 bits (1 byte + CRC_A).
-			return STATUS_ERROR;
-		}
-		// Verify CRC_A - do our own calculation and store the control in buffer[2..3] - those bytes are not needed anymore.
-		result = PCD_CalculateCRC(responseBuffer, 1, &buffer[2]);
-		if (result != STATUS_OK) {
-			return result;
-		}
-		if ((buffer[2] != responseBuffer[1]) || (buffer[3] != responseBuffer[2])) {
-			return STATUS_CRC_WRONG;
-		}
-		if (responseBuffer[0] & 0x04) { // Cascade bit set - UID not complete yes
-			cascadeLevel++;
-		}
-		else {
-			uidComplete = true;
-			uid->sak = responseBuffer[0];
-		}
-	} // End of while (!uidComplete)
-
-	// Set correct uid->size
-	uid->size = 3 * cascadeLevel + 1;
-
-	return STATUS_OK;
-} // End PICC_Select()
-
-/**
- * Instructs a PICC in state ACTIVE(*) to go to state HALT.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PICC_HaltA() {
-	MFRC522::StatusCode result;
-	byte buffer[4];
-
-	// Build command buffer
-	buffer[0] = PICC_CMD_HLTA;
-	buffer[1] = 0;
-	// Calculate CRC_A
-	result = PCD_CalculateCRC(buffer, 2, &buffer[2]);
-	if (result != STATUS_OK) {
-		return result;
-	}
-
-	// Send the command.
-	// The standard says:
-	//		If the PICC responds with any modulation during a period of 1 ms after the end of the frame containing the
-	//		HLTA command, this response shall be interpreted as 'not acknowledge'.
-	// We interpret that this way: Only STATUS_TIMEOUT is a success.
-	result = PCD_TransceiveData(buffer, sizeof(buffer), nullptr, 0);
-	if (result == STATUS_TIMEOUT) {
-		return STATUS_OK;
-	}
-	if (result == STATUS_OK) { // That is ironically NOT ok in this case ;-)
-		return STATUS_ERROR;
-	}
-	return result;
-} // End PICC_HaltA()
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Functions for communicating with MIFARE PICCs
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Executes the MFRC522 MFAuthent command.
- * This command manages MIFARE authentication to enable a secure communication to any MIFARE Mini, MIFARE 1K and MIFARE 4K card.
- * The authentication is described in the MFRC522 datasheet section 10.3.1.9 and http://www.nxp.com/documents/data_sheet/MF1S503x.pdf section 10.1.
- * For use with MIFARE Classic PICCs.
- * The PICC must be selected - ie in state ACTIVE(*) - before calling this function.
- * Remember to call PCD_StopCrypto1() after communicating with the authenticated PICC - otherwise no new communications can start.
- *
- * All keys are set to FFFFFFFFFFFFh at chip delivery.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise. Probably STATUS_TIMEOUT if you supply the wrong key.
- */
-MFRC522::StatusCode MFRC522::PCD_Authenticate(byte command,		///< PICC_CMD_MF_AUTH_KEY_A or PICC_CMD_MF_AUTH_KEY_B
-											byte blockAddr, 	///< The block number. See numbering in the comments in the .h file.
-											MIFARE_Key *key,	///< Pointer to the Crypteo1 key to use (6 bytes)
-											Uid *uid			///< Pointer to Uid struct. The first 4 bytes of the UID is used.
-											) {
-	byte waitIRq = 0x10;		// IdleIRq
-
-	// Build command buffer
-	byte sendData[12];
-	sendData[0] = command;
-	sendData[1] = blockAddr;
-	for (byte i = 0; i < MF_KEY_SIZE; i++) {	// 6 key bytes
-		sendData[2+i] = key->keyByte[i];
-	}
-	// Use the last uid bytes as specified in http://cache.nxp.com/documents/application_note/AN10927.pdf
-	// section 3.2.5 "MIFARE Classic Authentication".
-	// The only missed case is the MF1Sxxxx shortcut activation,
-	// but it requires cascade tag (CT) byte, that is not part of uid.
-	for (byte i = 0; i < 4; i++) {				// The last 4 bytes of the UID
-		sendData[8+i] = uid->uidByte[i+uid->size-4];
-	}
-
-	// Start the authentication.
-	return PCD_CommunicateWithPICC(PCD_MFAuthent, waitIRq, &sendData[0], sizeof(sendData));
-} // End PCD_Authenticate()
-
-/**
- * Used to exit the PCD from its authenticated state.
- * Remember to call this function after communicating with an authenticated PICC - otherwise no new communications can start.
- */
-void MFRC522::PCD_StopCrypto1() {
-	// Clear MFCrypto1On bit
-	PCD_ClearRegisterBitMask(Status2Reg, 0x08); // Status2Reg[7..0] bits are: TempSensClear I2CForceHS reserved reserved MFCrypto1On ModemState[2:0]
-} // End PCD_StopCrypto1()
-
-/**
- * Reads 16 bytes (+ 2 bytes CRC_A) from the active PICC.
- *
- * For MIFARE Classic the sector containing the block must be authenticated before calling this function.
- *
- * For MIFARE Ultralight only addresses 00h to 0Fh are decoded.
- * The MF0ICU1 returns a NAK for higher addresses.
- * The MF0ICU1 responds to the READ command by sending 16 bytes starting from the page address defined by the command argument.
- * For example; if blockAddr is 03h then pages 03h, 04h, 05h, 06h are returned.
- * A roll-back is implemented: If blockAddr is 0Eh, then the contents of pages 0Eh, 0Fh, 00h and 01h are returned.
- *
- * The buffer must be at least 18 bytes because a CRC_A is also returned.
- * Checks the CRC_A before returning STATUS_OK.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_Read(	byte blockAddr, 	///< MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The first page to return data from.
-											byte *buffer,		///< The buffer to store the data in
-											byte *bufferSize	///< Buffer size, at least 18 bytes. Also number of bytes returned if STATUS_OK.
-										) {
-	MFRC522::StatusCode result;
-
-	// Sanity check
-	if (buffer == nullptr || *bufferSize < 18) {
-		return STATUS_NO_ROOM;
-	}
-
-	// Build command buffer
-	buffer[0] = PICC_CMD_MF_READ;
-	buffer[1] = blockAddr;
-	// Calculate CRC_A
-	result = PCD_CalculateCRC(buffer, 2, &buffer[2]);
-	if (result != STATUS_OK) {
-		return result;
-	}
-
-	// Transmit the buffer and receive the response, validate CRC_A.
-	return PCD_TransceiveData(buffer, 4, buffer, bufferSize, nullptr, 0, true);
-} // End MIFARE_Read()
-
-/**
- * Writes 16 bytes to the active PICC.
- *
- * For MIFARE Classic the sector containing the block must be authenticated before calling this function.
- *
- * For MIFARE Ultralight the operation is called "COMPATIBILITY WRITE".
- * Even though 16 bytes are transferred to the Ultralight PICC, only the least significant 4 bytes (bytes 0 to 3)
- * are written to the specified address. It is recommended to set the remaining bytes 04h to 0Fh to all logic 0.
- * *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_Write(	byte blockAddr, ///< MIFARE Classic: The block (0-0xff) number. MIFARE Ultralight: The page (2-15) to write to.
-											byte *buffer,	///< The 16 bytes to write to the PICC
-											byte bufferSize	///< Buffer size, must be at least 16 bytes. Exactly 16 bytes are written.
-										) {
-	MFRC522::StatusCode result;
-
-	// Sanity check
-	if (buffer == nullptr || bufferSize < 16) {
-		return STATUS_INVALID;
-	}
-
-	// Mifare Classic protocol requires two communications to perform a write.
-	// Step 1: Tell the PICC we want to write to block blockAddr.
-	byte cmdBuffer[2];
-	cmdBuffer[0] = PICC_CMD_MF_WRITE;
-	cmdBuffer[1] = blockAddr;
-	result = PCD_MIFARE_Transceive(cmdBuffer, 2); // Adds CRC_A and checks that the response is MF_ACK.
-	if (result != STATUS_OK) {
-		return result;
-	}
-
-	// Step 2: Transfer the data
-	result = PCD_MIFARE_Transceive(buffer, bufferSize); // Adds CRC_A and checks that the response is MF_ACK.
-	if (result != STATUS_OK) {
-		return result;
-	}
-
-	return STATUS_OK;
-} // End MIFARE_Write()
-
-/**
- * Writes a 4 byte page to the active MIFARE Ultralight PICC.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_Ultralight_Write(	byte page, 		///< The page (2-15) to write to.
-														byte *buffer,	///< The 4 bytes to write to the PICC
-														byte bufferSize	///< Buffer size, must be at least 4 bytes. Exactly 4 bytes are written.
-													) {
-	MFRC522::StatusCode result;
-
-	// Sanity check
-	if (buffer == nullptr || bufferSize < 4) {
-		return STATUS_INVALID;
-	}
-
-	// Build commmand buffer
-	byte cmdBuffer[6];
-	cmdBuffer[0] = PICC_CMD_UL_WRITE;
-	cmdBuffer[1] = page;
-	memcpy(&cmdBuffer[2], buffer, 4);
-
-	// Perform the write
-	result = PCD_MIFARE_Transceive(cmdBuffer, 6); // Adds CRC_A and checks that the response is MF_ACK.
-	if (result != STATUS_OK) {
-		return result;
-	}
-	return STATUS_OK;
-} // End MIFARE_Ultralight_Write()
-
-/**
- * MIFARE Decrement subtracts the delta from the value of the addressed block, and stores the result in a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_Decrement(	byte blockAddr, ///< The block (0-0xff) number.
-												int32_t delta		///< This number is subtracted from the value of block blockAddr.
-											) {
-	return MIFARE_TwoStepHelper(PICC_CMD_MF_DECREMENT, blockAddr, delta);
-} // End MIFARE_Decrement()
-
-/**
- * MIFARE Increment adds the delta to the value of the addressed block, and stores the result in a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_Increment(	byte blockAddr, ///< The block (0-0xff) number.
-												int32_t delta		///< This number is added to the value of block blockAddr.
-											) {
-	return MIFARE_TwoStepHelper(PICC_CMD_MF_INCREMENT, blockAddr, delta);
-} // End MIFARE_Increment()
-
-/**
- * MIFARE Restore copies the value of the addressed block into a volatile memory.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- * Use MIFARE_Transfer() to store the result in a block.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_Restore(	byte blockAddr ///< The block (0-0xff) number.
-											) {
-	// The datasheet describes Restore as a two step operation, but does not explain what data to transfer in step 2.
-	// Doing only a single step does not work, so I chose to transfer 0L in step two.
-	return MIFARE_TwoStepHelper(PICC_CMD_MF_RESTORE, blockAddr, 0L);
-} // End MIFARE_Restore()
-
-/**
- * Helper function for the two-step MIFARE Classic protocol operations Decrement, Increment and Restore.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_TwoStepHelper(	byte command,	///< The command to use
-													byte blockAddr,	///< The block (0-0xff) number.
-													int32_t data		///< The data to transfer in step 2
-													) {
-	MFRC522::StatusCode result;
-	byte cmdBuffer[2]; // We only need room for 2 bytes.
-
-	// Step 1: Tell the PICC the command and block address
-	cmdBuffer[0] = command;
-	cmdBuffer[1] = blockAddr;
-	result = PCD_MIFARE_Transceive(	cmdBuffer, 2); // Adds CRC_A and checks that the response is MF_ACK.
-	if (result != STATUS_OK) {
-		return result;
-	}
-
-	// Step 2: Transfer the data
-	result = PCD_MIFARE_Transceive(	(byte *)&data, 4, true); // Adds CRC_A and accept timeout as success.
-	if (result != STATUS_OK) {
-		return result;
-	}
-
-	return STATUS_OK;
-} // End MIFARE_TwoStepHelper()
-
-/**
- * MIFARE Transfer writes the value stored in the volatile memory into one MIFARE Classic block.
- * For MIFARE Classic only. The sector containing the block must be authenticated before calling this function.
- * Only for blocks in "value block" mode, ie with access bits [C1 C2 C3] = [110] or [001].
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_Transfer(	byte blockAddr ///< The block (0-0xff) number.
-											) {
-	MFRC522::StatusCode result;
-	byte cmdBuffer[2]; // We only need room for 2 bytes.
-
-	// Tell the PICC we want to transfer the result into block blockAddr.
-	cmdBuffer[0] = PICC_CMD_MF_TRANSFER;
-	cmdBuffer[1] = blockAddr;
-	result = PCD_MIFARE_Transceive(	cmdBuffer, 2); // Adds CRC_A and checks that the response is MF_ACK.
-	if (result != STATUS_OK) {
-		return result;
-	}
-	return STATUS_OK;
-} // End MIFARE_Transfer()
-
-/**
- * Helper routine to read the current value from a Value Block.
- *
- * Only for MIFARE Classic and only for blocks in "value block" mode, that
- * is: with access bits [C1 C2 C3] = [110] or [001]. The sector containing
- * the block must be authenticated before calling this function.
- *
- * @param[in]   blockAddr   The block (0x00-0xff) number.
- * @param[out]  value       Current value of the Value Block.
- * @return STATUS_OK on success, STATUS_??? otherwise.
-  */
-MFRC522::StatusCode MFRC522::MIFARE_GetValue(byte blockAddr, int32_t *value) {
-	MFRC522::StatusCode status;
-	byte buffer[18];
-	byte size = sizeof(buffer);
-
-	// Read the block
-	status = MIFARE_Read(blockAddr, buffer, &size);
-	if (status == STATUS_OK) {
-		// Extract the value
-		*value = (int32_t(buffer[3])<<24) | (int32_t(buffer[2])<<16) | (int32_t(buffer[1])<<8) | int32_t(buffer[0]);
-	}
-	return status;
-} // End MIFARE_GetValue()
-
-/**
- * Helper routine to write a specific value into a Value Block.
- *
- * Only for MIFARE Classic and only for blocks in "value block" mode, that
- * is: with access bits [C1 C2 C3] = [110] or [001]. The sector containing
- * the block must be authenticated before calling this function.
- *
- * @param[in]   blockAddr   The block (0x00-0xff) number.
- * @param[in]   value       New value of the Value Block.
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::MIFARE_SetValue(byte blockAddr, int32_t value) {
-	byte buffer[18];
-
-	// Translate the int32_t into 4 bytes; repeated 2x in value block
-	buffer[0] = buffer[ 8] = (value & 0xFF);
-	buffer[1] = buffer[ 9] = (value & 0xFF00) >> 8;
-	buffer[2] = buffer[10] = (value & 0xFF0000) >> 16;
-	buffer[3] = buffer[11] = (value & 0xFF000000) >> 24;
-	// Inverse 4 bytes also found in value block
-	buffer[4] = ~buffer[0];
-	buffer[5] = ~buffer[1];
-	buffer[6] = ~buffer[2];
-	buffer[7] = ~buffer[3];
-	// Address 2x with inverse address 2x
-	buffer[12] = buffer[14] = blockAddr;
-	buffer[13] = buffer[15] = ~blockAddr;
-
-	// Write the whole data block
-	return MIFARE_Write(blockAddr, buffer, 16);
-} // End MIFARE_SetValue()
-
-/**
- * Authenticate with a NTAG216.
- *
- * Only for NTAG216. First implemented by Gargantuanman.
- *
- * @param[in]   passWord   password.
- * @param[in]   pACK       result success???.
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PCD_NTAG216_AUTH(byte* passWord, byte pACK[]) //Authenticate with 32bit password
-{
-	// TODO: Fix cmdBuffer length and rxlength. They really should match.
-	//       (Better still, rxlength should not even be necessary.)
-
-	MFRC522::StatusCode result;
-	byte				cmdBuffer[18]; // We need room for 16 bytes data and 2 bytes CRC_A.
-
-	cmdBuffer[0] = 0x1B; //Comando de autentificacion
-
-	for (byte i = 0; i<4; i++)
-		cmdBuffer[i+1] = passWord[i];
-
-	result = PCD_CalculateCRC(cmdBuffer, 5, &cmdBuffer[5]);
-
-	if (result!=STATUS_OK) {
-		return result;
-	}
-
-	// Transceive the data, store the reply in cmdBuffer[]
-	byte waitIRq		= 0x30;	// RxIRq and IdleIRq
-//	byte cmdBufferSize	= sizeof(cmdBuffer);
-	byte validBits		= 0;
-	byte rxlength		= 5;
-	result = PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, cmdBuffer, 7, cmdBuffer, &rxlength, &validBits);
-
-	pACK[0] = cmdBuffer[0];
-	pACK[1] = cmdBuffer[1];
-
-	if (result!=STATUS_OK) {
-		return result;
-	}
-
-	return STATUS_OK;
-} // End PCD_NTAG216_AUTH()
-
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Support functions
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Wrapper for MIFARE protocol communication.
- * Adds CRC_A, executes the Transceive command and checks that the response is MF_ACK or a timeout.
- *
- * @return STATUS_OK on success, STATUS_??? otherwise.
- */
-MFRC522::StatusCode MFRC522::PCD_MIFARE_Transceive(	byte *sendData,		///< Pointer to the data to transfer to the FIFO. Do NOT include the CRC_A.
-													byte sendLen,		///< Number of bytes in sendData.
-													bool acceptTimeout	///< True => A timeout is also success
-												) {
-	MFRC522::StatusCode result;
-	byte cmdBuffer[18]; // We need room for 16 bytes data and 2 bytes CRC_A.
-
-	// Sanity check
-	if (sendData == nullptr || sendLen > 16) {
-		return STATUS_INVALID;
-	}
-
-	// Copy sendData[] to cmdBuffer[] and add CRC_A
-	memcpy(cmdBuffer, sendData, sendLen);
-	result = PCD_CalculateCRC(cmdBuffer, sendLen, &cmdBuffer[sendLen]);
-	if (result != STATUS_OK) {
-		return result;
-	}
-	sendLen += 2;
-
-	// Transceive the data, store the reply in cmdBuffer[]
-	byte waitIRq = 0x30;		// RxIRq and IdleIRq
-	byte cmdBufferSize = sizeof(cmdBuffer);
-	byte validBits = 0;
-	result = PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, cmdBuffer, sendLen, cmdBuffer, &cmdBufferSize, &validBits);
-	if (acceptTimeout && result == STATUS_TIMEOUT) {
-		return STATUS_OK;
-	}
-	if (result != STATUS_OK) {
-		return result;
-	}
-	// The PICC must reply with a 4 bit ACK
-	if (cmdBufferSize != 1 || validBits != 4) {
-		return STATUS_ERROR;
-	}
-	if (cmdBuffer[0] != MF_ACK) {
-		return STATUS_MIFARE_NACK;
-	}
-	return STATUS_OK;
-} // End PCD_MIFARE_Transceive()
-
-
-/**
- * Translates the SAK (Select Acknowledge) to a PICC type.
- *
- * @return PICC_Type
- */
-MFRC522::PICC_Type MFRC522::PICC_GetType(byte sak		///< The SAK byte returned from PICC_Select().
-										) {
-	// http://www.nxp.com/documents/application_note/AN10833.pdf
-	// 3.2 Coding of Select Acknowledge (SAK)
-	// ignore 8-bit (iso14443 starts with LSBit = bit 1)
-	// fixes wrong type for manufacturer Infineon (http://nfc-tools.org/index.php?title=ISO14443A)
-	sak &= 0x7F;
-	switch (sak) {
-		case 0x04:	return PICC_TYPE_NOT_COMPLETE;	// UID not complete
-		case 0x09:	return PICC_TYPE_MIFARE_MINI;
-		case 0x08:	return PICC_TYPE_MIFARE_1K;
-		case 0x18:	return PICC_TYPE_MIFARE_4K;
-		case 0x00:	return PICC_TYPE_MIFARE_UL;
-		case 0x10:
-		case 0x11:	return PICC_TYPE_MIFARE_PLUS;
-		case 0x01:	return PICC_TYPE_TNP3XXX;
-		case 0x20:	return PICC_TYPE_ISO_14443_4;
-		case 0x40:	return PICC_TYPE_ISO_18092;
-		default:	return PICC_TYPE_UNKNOWN;
-	}
-} // End PICC_GetType()
-
-
-/**
- * Dumps debug info about the connected PCD to Serial.
- * Shows all known firmware versions
- */
-void MFRC522::PCD_DumpVersionToSerial() {
-	// Get the MFRC522 firmware version
-	byte v = PCD_ReadRegister(VersionReg);
-	std::ostringstream oss;
-	oss << "Firmware Version: 0x" << std::hex << (int)v;
-
-	// Lookup which version
-	switch(v) {
-		case 0x88: oss << " = (clone)";  break;
-		case 0x90: oss << " = v0.0";     break;
-		case 0x91: oss << " = v1.0";     break;
-		case 0x92: oss << " = v2.0";     break;
-		default:   oss << " = (unknown)";
-	}
-
-	ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-	// When 0x00 or 0xFF is returned, communication probably failed
-	if ((v == 0x00) || (v == 0xFF))
-		ESP_LOGD(LOG_TAG, "WARNING: Communication failure, is the MFRC522 properly connected?");
-} // End PCD_DumpVersionToSerial()
-
-/**
- * Dumps debug info about the selected PICC to Serial.
- * On success the PICC is halted after dumping the data.
- * For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried.
- *
- * @DEPRECATED Kept for bakward compatibility
- */
-void MFRC522::PICC_DumpToSerial(Uid *uid	///< Pointer to Uid struct returned from a successful PICC_Select().
-								) {
-	MIFARE_Key key;
-
-	// Dump UID, SAK and Type
-	PICC_DumpDetailsToSerial(uid);
-
-	// Dump contents
-	PICC_Type piccType = PICC_GetType(uid->sak);
-	switch (piccType) {
-		case PICC_TYPE_MIFARE_MINI:
-		case PICC_TYPE_MIFARE_1K:
-		case PICC_TYPE_MIFARE_4K:
-			// All keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
-			for (byte i = 0; i < 6; i++) {
-				key.keyByte[i] = 0xFF;
-			}
-			PICC_DumpMifareClassicToSerial(uid, piccType, &key);
-			break;
-
-		case PICC_TYPE_MIFARE_UL:
-			PICC_DumpMifareUltralightToSerial();
-			break;
-
-		case PICC_TYPE_ISO_14443_4:
-		case PICC_TYPE_MIFARE_DESFIRE:
-		case PICC_TYPE_ISO_18092:
-		case PICC_TYPE_MIFARE_PLUS:
-		case PICC_TYPE_TNP3XXX:
-			ESP_LOGD(LOG_TAG, "Dumping memory contents not implemented for that PICC type.");
-			break;
-
-		case PICC_TYPE_UNKNOWN:
-		case PICC_TYPE_NOT_COMPLETE:
-		default:
-			break; // No memory dump here
-	}
-
-	ESP_LOGD(LOG_TAG,"");
-	PICC_HaltA(); // Already done if it was a MIFARE Classic PICC.
-} // End PICC_DumpToSerial()
-
-/**
- * Dumps card info (UID,SAK,Type) about the selected PICC to Serial.
- *
- * @DEPRECATED kept for backward compatibility
- */
-void MFRC522::PICC_DumpDetailsToSerial(Uid *uid	///< Pointer to Uid struct returned from a successful PICC_Select().
-									) {
-	// UID
-	std::ostringstream oss;
-	oss << std::hex << std::setfill('0');
-
-	oss << "Card UID: ";
-	for (byte i = 0; i < uid->size; i++) {
-		oss << std::setw(2) << (int)uid->uidByte[i];
-	}
-	ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-
-	// SAK
-	oss.str("");
-	oss << "" << "Card SAK: " << std::setw(2) << (int)uid->sak;
-	ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-
-
-	// (suggested) PICC type
-	PICC_Type piccType = PICC_GetType(uid->sak);
-	oss.str("");
-	oss << "PICC type: " << MFRC522Debug::PICC_GetTypeName(piccType);
-	ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-} // End PICC_DumpDetailsToSerial()
-
-/**
- * Dumps memory contents of a MIFARE Classic PICC.
- * On success the PICC is halted after dumping the data.
- */
-void MFRC522::PICC_DumpMifareClassicToSerial(	Uid *uid,			///< Pointer to Uid struct returned from a successful PICC_Select().
-												PICC_Type piccType,	///< One of the PICC_Type enums.
-												MIFARE_Key *key		///< Key A used for all sectors.
-											) {
-	byte no_of_sectors = 0;
-	switch (piccType) {
-		case PICC_TYPE_MIFARE_MINI:
-			// Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes.
-			no_of_sectors = 5;
-			break;
-
-		case PICC_TYPE_MIFARE_1K:
-			// Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes.
-			no_of_sectors = 16;
-			break;
-
-		case PICC_TYPE_MIFARE_4K:
-			// Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = 4096 bytes.
-			no_of_sectors = 40;
-			break;
-
-		default: // Should not happen. Ignore.
-			break;
-	}
-
-	// Dump sectors, highest address first.
-	if (no_of_sectors) {
-		ESP_LOGD(LOG_TAG, "Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits");
-		for (int8_t i = no_of_sectors - 1; i >= 0; i--) {
-			PICC_DumpMifareClassicSectorToSerial(uid, key, i);
-		}
-	}
-	PICC_HaltA(); // Halt the PICC before stopping the encrypted session.
-	PCD_StopCrypto1();
-} // End PICC_DumpMifareClassicToSerial()
-
-/**
- * Dumps memory contents of a sector of a MIFARE Classic PICC.
- * Uses PCD_Authenticate(), MIFARE_Read() and PCD_StopCrypto1.
- * Always uses PICC_CMD_MF_AUTH_KEY_A because only Key A can always read the sector trailer access bits.
- */
-void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid,			///< Pointer to Uid struct returned from a successful PICC_Select().
-													MIFARE_Key *key,	///< Key A for the sector.
-													byte sector			///< The sector to dump, 0..39.
-													) {
-	MFRC522::StatusCode status;
-	byte firstBlock;		// Address of lowest address to dump actually last block dumped)
-	byte no_of_blocks;		// Number of blocks in sector
-	bool isSectorTrailer;	// Set to true while handling the "last" (ie highest address) in the sector.
-
-	// The access bits are stored in a peculiar fashion.
-	// There are four groups:
-	//		g[3]	Access bits for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
-	//		g[2]	Access bits for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
-	//		g[1]	Access bits for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
-	//		g[0]	Access bits for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
-	// Each group has access bits [C1 C2 C3]. In this code C1 is MSB and C3 is LSB.
-	// The four CX bits are stored together in a nible cx and an inverted nible cx_.
-	byte c1, c2, c3;		// Nibbles
-	byte c1_, c2_, c3_;		// Inverted nibbles
-	bool invertedError;		// True if one of the inverted nibbles did not match
-	byte g[4];				// Access bits for each of the four groups.
-	byte group;				// 0-3 - active group for access bits
-	bool firstInGroup;		// True for the first block dumped in the group
-
-	// Determine position and size of sector.
-	if (sector < 32) { // Sectors 0..31 has 4 blocks each
-		no_of_blocks = 4;
-		firstBlock = sector * no_of_blocks;
-	}
-	else if (sector < 40) { // Sectors 32-39 has 16 blocks each
-		no_of_blocks = 16;
-		firstBlock = 128 + (sector - 32) * no_of_blocks;
-	}
-	else { // Illegal input, no MIFARE Classic PICC has more than 40 sectors.
-		return;
-	}
-
-	// Dump blocks, highest address first.
-	byte byteCount;
-	byte buffer[18];
-	byte blockAddr;
-	isSectorTrailer = true;
-	invertedError = false;	// Avoid "unused variable" warning.
-	for (int8_t blockOffset = no_of_blocks - 1; blockOffset >= 0; blockOffset--) {
-		blockAddr = firstBlock + blockOffset;
-		// Sector number - only on first line
-		std::ostringstream oss;
-		if (isSectorTrailer) {
-			if(sector < 10) {
-				oss << "   "; // Pad with spaces
-			}
-			else {
-				oss << "  "; // Pad with spaces
-			}
-			oss << (int)sector;
-
-			oss <<  "   ";
-		}
-		else {
-			oss << "       ";
-		}
-		// Block number
-		if(blockAddr < 10) {
-			oss << "   "; // Pad with spaces
-		}
-		else {
-			if(blockAddr < 100) {
-				oss << "  "; // Pad with spaces
-			}
-			else {
-				oss << " "; // Pad with spaces
-			}
-		}
-		oss << (int) blockAddr;
-		oss << "  ";
-		// Establish encrypted communications before reading the first block
-		if (isSectorTrailer) {
-			status = PCD_Authenticate(PICC_CMD_MF_AUTH_KEY_A, firstBlock, key, uid);
-			if (status != STATUS_OK) {
-				oss << "PCD_Authenticate() failed: ";
-				oss << (int) MFRC522Debug::GetStatusCodeName(status);
-				ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-				return;
-			}
-		}
-		// Read block
-		byteCount = sizeof(buffer);
-		status = MIFARE_Read(blockAddr, buffer, &byteCount);
-		if (status != STATUS_OK) {
-			oss << "MIFARE_Read() failed: ";
-			oss << (int)MFRC522Debug::GetStatusCodeName(status);
-			ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-			continue;
-		}
-		// Dump data
-		oss << std::hex << std::setfill('0');
-		for (byte index = 0; index < 16; index++) {
-			oss << " " << std::setw(2) << (int)buffer[index];
-
-			if ((index % 4) == 3) {
-				oss << " ";
-			}
-		}
-		// Parse sector trailer data
-		if (isSectorTrailer) {
-			c1  = buffer[7] >> 4;
-			c2  = buffer[8] & 0xF;
-			c3  = buffer[8] >> 4;
-			c1_ = buffer[6] & 0xF;
-			c2_ = buffer[6] >> 4;
-			c3_ = buffer[7] & 0xF;
-			invertedError = (c1 != (~c1_ & 0xF)) || (c2 != (~c2_ & 0xF)) || (c3 != (~c3_ & 0xF));
-			g[0] = ((c1 & 1) << 2) | ((c2 & 1) << 1) | ((c3 & 1) << 0);
-			g[1] = ((c1 & 2) << 1) | ((c2 & 2) << 0) | ((c3 & 2) >> 1);
-			g[2] = ((c1 & 4) << 0) | ((c2 & 4) >> 1) | ((c3 & 4) >> 2);
-			g[3] = ((c1 & 8) >> 1) | ((c2 & 8) >> 2) | ((c3 & 8) >> 3);
-			isSectorTrailer = false;
-		}
-
-		// Which access group is this block in?
-		if (no_of_blocks == 4) {
-			group = blockOffset;
-			firstInGroup = true;
-		}
-		else {
-			group = blockOffset / 5;
-			firstInGroup = (group == 3) || (group != (blockOffset + 1) / 5);
-		}
-
-		if (firstInGroup) {
-			// Print access bits
-			oss << std::dec;
-			oss << " [ " << (int)((g[group] >> 2) & 1) << " " << (int)((g[group] >> 1) & 1) << " " << (int) ((g[group] >> 0) & 1) << " ] ";
-			if (invertedError) {
-				oss << " Inverted access bits did not match! ";
-			}
-		}
-
-		if (group != 3 && (g[group] == 1 || g[group] == 6)) { // Not a sector trailer, a value block
-			int32_t value = (int32_t(buffer[3])<<24) | (int32_t(buffer[2])<<16) | (int32_t(buffer[1])<<8) | int32_t(buffer[0]);
-			oss << " Value=0x" << std::hex << value << " Adr=0x" << (int)buffer[12];
-		}
-		ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-	}
-
-	return;
-} // End PICC_DumpMifareClassicSectorToSerial()
-
-/**
- * Dumps memory contents of a MIFARE Ultralight PICC.
- */
-void MFRC522::PICC_DumpMifareUltralightToSerial() {
-	MFRC522::StatusCode status;
-	byte byteCount;
-	byte buffer[18];
-	byte i;
-
-	std::ostringstream oss;
-	oss << "Page  0  1  2  3";
-	// Try the mpages of the original Ultralight. Ultralight C has more pages.
-	for (byte page = 0; page < 16; page +=4) { // Read returns data for 4 pages at a time.
-		// Read pages
-		byteCount = sizeof(buffer);
-		status = MIFARE_Read(page, buffer, &byteCount);
-		if (status != STATUS_OK) {
-			oss << "MIFARE_Read() failed: ";
-			oss << std::dec << (int) MFRC522Debug::GetStatusCodeName(status);
-			ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-			break;
-		}
-		// Dump data
-		oss << std::dec;
-		for (byte offset = 0; offset < 4; offset++) {
-			i = page + offset;
-			oss << " " << std::setw(2) << (int) i << " ";
-
-			for (byte index = 0; index < 4; index++) {
-				i = 4 * offset + index;
-				oss << std::hex << std::setw(2) << (int)buffer[i];
-			}
-			ESP_LOGD(LOG_TAG, "%s", oss.str().c_str());
-		}
-	}
-} // End PICC_DumpMifareUltralightToSerial()
-
-/**
- * Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1).
- */
-void MFRC522::MIFARE_SetAccessBits(	byte *accessBitBuffer,	///< Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set.
-									byte g0,				///< Access bits [C1 C2 C3] for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
-									byte g1,				///< Access bits C1 C2 C3] for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
-									byte g2,				///< Access bits C1 C2 C3] for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
-									byte g3					///< Access bits C1 C2 C3] for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
-								) {
-	byte c1 = ((g3 & 4) << 1) | ((g2 & 4) << 0) | ((g1 & 4) >> 1) | ((g0 & 4) >> 2);
-	byte c2 = ((g3 & 2) << 2) | ((g2 & 2) << 1) | ((g1 & 2) << 0) | ((g0 & 2) >> 1);
-	byte c3 = ((g3 & 1) << 3) | ((g2 & 1) << 2) | ((g1 & 1) << 1) | ((g0 & 1) << 0);
-
-	accessBitBuffer[0] = (~c2 & 0xF) << 4 | (~c1 & 0xF);
-	accessBitBuffer[1] =          c1 << 4 | (~c3 & 0xF);
-	accessBitBuffer[2] =          c3 << 4 | c2;
-} // End MIFARE_SetAccessBits()
-
-/////////////////////////////////////////////////////////////////////////////////////
-// Convenience functions - does not add extra functionality
-/////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Returns true if a PICC responds to PICC_CMD_REQA.
- * Only "new" cards in state IDLE are invited. Sleeping cards in state HALT are ignored.
- *
- * @return bool
- */
-bool MFRC522::PICC_IsNewCardPresent() {
-	byte bufferATQA[2];
-	byte bufferSize = sizeof(bufferATQA);
-
-	// Reset baud rates
-	PCD_WriteRegister(TxModeReg, 0x00);
-	PCD_WriteRegister(RxModeReg, 0x00);
-	// Reset ModWidthReg
-	PCD_WriteRegister(ModWidthReg, 0x26);
-
-	MFRC522::StatusCode result = PICC_RequestA(bufferATQA, &bufferSize);
-	return (result == STATUS_OK || result == STATUS_COLLISION);
-} // End PICC_IsNewCardPresent()
-
-/**
- * Simple wrapper around PICC_Select.
- * Returns true if a UID could be read.
- * Remember to call PICC_IsNewCardPresent(), PICC_RequestA() or PICC_WakeupA() first.
- * The read UID is available in the class variable uid.
- *
- * @return bool
- */
-bool MFRC522::PICC_ReadCardSerial() {
-	MFRC522::StatusCode result = PICC_Select(&uid);
-	return (result == STATUS_OK);
-} // End
diff --git a/components/cpp_utils/MFRC522.h b/components/cpp_utils/MFRC522.h
deleted file mode 100644
index 2e06071..0000000
--- a/components/cpp_utils/MFRC522.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/**
- * MFRC522.h - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
- * Based on code Dr.Leong   ( WWW.B2CQSHOP.COM )
- * Created by Miguel Balboa (circuitito.com), Jan, 2012.
- * Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013 (Translation to English, refactored, comments, anti collision, cascade levels.)
- * Extended by Tom Clement with functionality to write to sector 0 of UID changeable Mifare cards.
- * Released into the public domain.
- *
- * Please read this file for an overview and then MFRC522.cpp for comments on the specific functions.
- * Search for "mf-rc522" on ebay.com to purchase the MF-RC522 board.
- *
- * There are three hardware components involved:
- * 1) The micro controller: An Arduino
- * 2) The PCD (short for Proximity Coupling Device): NXP MFRC522 Contactless Reader IC
- * 3) The PICC (short for Proximity Integrated Circuit Card): A card or tag using the ISO 14443A interface, eg Mifare or NTAG203.
- *
- * The microcontroller and card reader uses SPI for communication.
- * The protocol is described in the MFRC522 datasheet: http://www.nxp.com/documents/data_sheet/MFRC522.pdf
- *
- * The card reader and the tags communicate using a 13.56MHz electromagnetic field.
- * The protocol is defined in ISO/IEC 14443-3 Identification cards -- Contactless integrated circuit cards -- Proximity cards -- Part 3: Initialization and anticollision".
- * A free version of the final draft can be found at http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf
- * Details are found in chapter 6, Type A – Initialization and anticollision.
- *
- * If only the PICC UID is wanted, the above documents has all the needed information.
- * To read and write from MIFARE PICCs, the MIFARE protocol is used after the PICC has been selected.
- * The MIFARE Classic chips and protocol is described in the datasheets:
- *		1K:   http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf
- * 		4K:   http://datasheet.octopart.com/MF1S7035DA4,118-NXP-Semiconductors-datasheet-11046188.pdf
- * 		Mini: http://www.idcardmarket.com/download/mifare_S20_datasheet.pdf
- * The MIFARE Ultralight chip and protocol is described in the datasheets:
- *		Ultralight:   http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf
- * 		Ultralight C: http://www.nxp.com/documents/short_data_sheet/MF0ICU2_SDS.pdf
- *
- * MIFARE Classic 1K (MF1S503x):
- * 		Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes.
- * 		The blocks are numbered 0-63.
- * 		Block 3 in each sector is the Sector Trailer. See http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf sections 8.6 and 8.7:
- * 				Bytes 0-5:   Key A
- * 				Bytes 6-8:   Access Bits
- * 				Bytes 9:     User data
- * 				Bytes 10-15: Key B (or user data)
- * 		Block 0 is read-only manufacturer data.
- * 		To access a block, an authentication using a key from the block's sector must be performed first.
- * 		Example: To read from block 10, first authenticate using a key from sector 3 (blocks 8-11).
- * 		All keys are set to FFFFFFFFFFFFh at chip delivery.
- * 		Warning: Please read section 8.7 "Memory Access". It includes this text: if the PICC detects a format violation the whole sector is irreversibly blocked.
- *		To use a block in "value block" mode (for Increment/Decrement operations) you need to change the sector trailer. Use PICC_SetAccessBits() to calculate the bit patterns.
- * MIFARE Classic 4K (MF1S703x):
- * 		Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = 4096 bytes.
- * 		The blocks are numbered 0-255.
- * 		The last block in each sector is the Sector Trailer like above.
- * MIFARE Classic Mini (MF1 IC S20):
- * 		Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes.
- * 		The blocks are numbered 0-19.
- * 		The last block in each sector is the Sector Trailer like above.
- *
- * MIFARE Ultralight (MF0ICU1):
- * 		Has 16 pages of 4 bytes = 64 bytes.
- * 		Pages 0 + 1 is used for the 7-byte UID.
- * 		Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
- * 		Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
- * 		Pages 4-15 are read/write unless blocked by the lock bytes in page 2.
- * MIFARE Ultralight C (MF0ICU2):
- * 		Has 48 pages of 4 bytes = 192 bytes.
- * 		Pages 0 + 1 is used for the 7-byte UID.
- * 		Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
- * 		Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
- * 		Pages 4-39 are read/write unless blocked by the lock bytes in page 2.
- * 		Page 40 Lock bytes
- * 		Page 41 16 bit one way counter
- * 		Pages 42-43 Authentication configuration
- * 		Pages 44-47 Authentication key
- */
-#ifndef MFRC522_h
-#define MFRC522_h
-
-
-
-#include <stdint.h>
-#include <SPI.h>
-
-typedef uint8_t byte;
-
-// Firmware data for self-test
-// Reference values based on firmware version
-// Hint: if needed, you can remove unused self-test data to save flash memory
-//
-// Version 0.0 (0x90)
-// Philips Semiconductors; Preliminary Specification Revision 2.0 - 01 August 2005; 16.1 self-test
-const byte MFRC522_firmware_referenceV0_0[] = {
-	0x00, 0x87, 0x98, 0x0f, 0x49, 0xFF, 0x07, 0x19,
-	0xBF, 0x22, 0x30, 0x49, 0x59, 0x63, 0xAD, 0xCA,
-	0x7F, 0xE3, 0x4E, 0x03, 0x5C, 0x4E, 0x49, 0x50,
-	0x47, 0x9A, 0x37, 0x61, 0xE7, 0xE2, 0xC6, 0x2E,
-	0x75, 0x5A, 0xED, 0x04, 0x3D, 0x02, 0x4B, 0x78,
-	0x32, 0xFF, 0x58, 0x3B, 0x7C, 0xE9, 0x00, 0x94,
-	0xB4, 0x4A, 0x59, 0x5B, 0xFD, 0xC9, 0x29, 0xDF,
-	0x35, 0x96, 0x98, 0x9E, 0x4F, 0x30, 0x32, 0x8D
-};
-// Version 1.0 (0x91)
-// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 self-test
-const byte MFRC522_firmware_referenceV1_0[] = {
-	0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C,
-	0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73,
-	0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1, 0x3E, 0x5A,
-	0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E,
-	0x64, 0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC,
-	0x22, 0xBC, 0xD3, 0x72, 0x35, 0xCD, 0xAA, 0x41,
-	0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02,
-	0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79
-};
-// Version 2.0 (0x92)
-// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 self-test
-const byte MFRC522_firmware_referenceV2_0[] = {
-	0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95,
-	0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE,
-	0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B, 0x89, 0x82,
-	0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49,
-	0x7C, 0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81,
-	0x5D, 0x48, 0x76, 0xD5, 0x71, 0x61, 0x21, 0xA9,
-	0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D,
-	0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F
-};
-// Clone
-// Fudan Semiconductor FM17522 (0x88)
-const byte FM17522_firmware_reference[] = {
-	0x00, 0xD6, 0x78, 0x8C, 0xE2, 0xAA, 0x0C, 0x18,
-	0x2A, 0xB8, 0x7A, 0x7F, 0xD3, 0x6A, 0xCF, 0x0B,
-	0xB1, 0x37, 0x63, 0x4B, 0x69, 0xAE, 0x91, 0xC7,
-	0xC3, 0x97, 0xAE, 0x77, 0xF4, 0x37, 0xD7, 0x9B,
-	0x7C, 0xF5, 0x3C, 0x11, 0x8F, 0x15, 0xC3, 0xD7,
-	0xC1, 0x5B, 0x00, 0x2A, 0xD0, 0x75, 0xDE, 0x9E,
-	0x51, 0x64, 0xAB, 0x3E, 0xE9, 0x15, 0xB5, 0xAB,
-	0x56, 0x9A, 0x98, 0x82, 0x26, 0xEA, 0x2A, 0x62
-};
-
-class MFRC522 {
-public:
-	// Size of the MFRC522 FIFO
-	static constexpr byte FIFO_SIZE = 64;		// The FIFO is 64 bytes.
-	// Default value for unused pin
-	static constexpr uint8_t UNUSED_PIN = UINT8_MAX;
-
-	// MFRC522 registers. Described in chapter 9 of the datasheet.
-	// When using SPI all addresses are shifted one bit left in the "SPI address byte" (section 8.1.2.3)
-	enum PCD_Register : byte {
-		// Page 0: Command and status
-		//						  0x00			// reserved for future use
-		CommandReg				= 0x01 << 1,	// starts and stops command execution
-		ComIEnReg				= 0x02 << 1,	// enable and disable interrupt request control bits
-		DivIEnReg				= 0x03 << 1,	// enable and disable interrupt request control bits
-		ComIrqReg				= 0x04 << 1,	// interrupt request bits
-		DivIrqReg				= 0x05 << 1,	// interrupt request bits
-		ErrorReg				= 0x06 << 1,	// error bits showing the error status of the last command executed
-		Status1Reg				= 0x07 << 1,	// communication status bits
-		Status2Reg				= 0x08 << 1,	// receiver and transmitter status bits
-		FIFODataReg				= 0x09 << 1,	// input and output of 64 byte FIFO buffer
-		FIFOLevelReg			= 0x0A << 1,	// number of bytes stored in the FIFO buffer
-		WaterLevelReg			= 0x0B << 1,	// level for FIFO underflow and overflow warning
-		ControlReg				= 0x0C << 1,	// miscellaneous control registers
-		BitFramingReg			= 0x0D << 1,	// adjustments for bit-oriented frames
-		CollReg					= 0x0E << 1,	// bit position of the first bit-collision detected on the RF interface
-		//						  0x0F			// reserved for future use
-
-		// Page 1: Command
-		// 						  0x10			// reserved for future use
-		ModeReg					= 0x11 << 1,	// defines general modes for transmitting and receiving
-		TxModeReg				= 0x12 << 1,	// defines transmission data rate and framing
-		RxModeReg				= 0x13 << 1,	// defines reception data rate and framing
-		TxControlReg			= 0x14 << 1,	// controls the logical behavior of the antenna driver pins TX1 and TX2
-		TxASKReg				= 0x15 << 1,	// controls the setting of the transmission modulation
-		TxSelReg				= 0x16 << 1,	// selects the internal sources for the antenna driver
-		RxSelReg				= 0x17 << 1,	// selects internal receiver settings
-		RxThresholdReg			= 0x18 << 1,	// selects thresholds for the bit decoder
-		DemodReg				= 0x19 << 1,	// defines demodulator settings
-		// 						  0x1A			// reserved for future use
-		// 						  0x1B			// reserved for future use
-		MfTxReg					= 0x1C << 1,	// controls some MIFARE communication transmit parameters
-		MfRxReg					= 0x1D << 1,	// controls some MIFARE communication receive parameters
-		// 						  0x1E			// reserved for future use
-		SerialSpeedReg			= 0x1F << 1,	// selects the speed of the serial UART interface
-
-		// Page 2: Configuration
-		// 						  0x20			// reserved for future use
-		CRCResultRegH			= 0x21 << 1,	// shows the MSB and LSB values of the CRC calculation
-		CRCResultRegL			= 0x22 << 1,
-		// 						  0x23			// reserved for future use
-		ModWidthReg				= 0x24 << 1,	// controls the ModWidth setting?
-		// 						  0x25			// reserved for future use
-		RFCfgReg				= 0x26 << 1,	// configures the receiver gain
-		GsNReg					= 0x27 << 1,	// selects the conductance of the antenna driver pins TX1 and TX2 for modulation
-		CWGsPReg				= 0x28 << 1,	// defines the conductance of the p-driver output during periods of no modulation
-		ModGsPReg				= 0x29 << 1,	// defines the conductance of the p-driver output during periods of modulation
-		TModeReg				= 0x2A << 1,	// defines settings for the internal timer
-		TPrescalerReg			= 0x2B << 1,	// the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
-		TReloadRegH				= 0x2C << 1,	// defines the 16-bit timer reload value
-		TReloadRegL				= 0x2D << 1,
-		TCounterValueRegH		= 0x2E << 1,	// shows the 16-bit timer value
-		TCounterValueRegL		= 0x2F << 1,
-
-		// Page 3: Test Registers
-		// 						  0x30			// reserved for future use
-		TestSel1Reg				= 0x31 << 1,	// general test signal configuration
-		TestSel2Reg				= 0x32 << 1,	// general test signal configuration
-		TestPinEnReg			= 0x33 << 1,	// enables pin output driver on pins D1 to D7
-		TestPinValueReg			= 0x34 << 1,	// defines the values for D1 to D7 when it is used as an I/O bus
-		TestBusReg				= 0x35 << 1,	// shows the status of the internal test bus
-		AutoTestReg				= 0x36 << 1,	// controls the digital self-test
-		VersionReg				= 0x37 << 1,	// shows the software version
-		AnalogTestReg			= 0x38 << 1,	// controls the pins AUX1 and AUX2
-		TestDAC1Reg				= 0x39 << 1,	// defines the test value for TestDAC1
-		TestDAC2Reg				= 0x3A << 1,	// defines the test value for TestDAC2
-		TestADCReg				= 0x3B << 1		// shows the value of ADC I and Q channels
-		// 						  0x3C			// reserved for production tests
-		// 						  0x3D			// reserved for production tests
-		// 						  0x3E			// reserved for production tests
-		// 						  0x3F			// reserved for production tests
-	};
-
-	// MFRC522 commands. Described in chapter 10 of the datasheet.
-	enum PCD_Command : byte {
-		PCD_Idle				= 0x00,		// no action, cancels current command execution
-		PCD_Mem					= 0x01,		// stores 25 bytes into the internal buffer
-		PCD_GenerateRandomID	= 0x02,		// generates a 10-byte random ID number
-		PCD_CalcCRC				= 0x03,		// activates the CRC coprocessor or performs a self-test
-		PCD_Transmit			= 0x04,		// transmits data from the FIFO buffer
-		PCD_NoCmdChange			= 0x07,		// no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
-		PCD_Receive				= 0x08,		// activates the receiver circuits
-		PCD_Transceive 			= 0x0C,		// transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
-		PCD_MFAuthent 			= 0x0E,		// performs the MIFARE standard authentication as a reader
-		PCD_SoftReset			= 0x0F		// resets the MFRC522
-	};
-
-	// MFRC522 RxGain[2:0] masks, defines the receiver's signal voltage gain factor (on the PCD).
-	// Described in 9.3.3.6 / table 98 of the datasheet at http://www.nxp.com/documents/data_sheet/MFRC522.pdf
-	enum PCD_RxGain : byte {
-		RxGain_18dB				= 0x00 << 4,	// 000b - 18 dB, minimum
-		RxGain_23dB				= 0x01 << 4,	// 001b - 23 dB
-		RxGain_18dB_2			= 0x02 << 4,	// 010b - 18 dB, it seems 010b is a duplicate for 000b
-		RxGain_23dB_2			= 0x03 << 4,	// 011b - 23 dB, it seems 011b is a duplicate for 001b
-		RxGain_33dB				= 0x04 << 4,	// 100b - 33 dB, average, and typical default
-		RxGain_38dB				= 0x05 << 4,	// 101b - 38 dB
-		RxGain_43dB				= 0x06 << 4,	// 110b - 43 dB
-		RxGain_48dB				= 0x07 << 4,	// 111b - 48 dB, maximum
-		RxGain_min				= 0x00 << 4,	// 000b - 18 dB, minimum, convenience for RxGain_18dB
-		RxGain_avg				= 0x04 << 4,	// 100b - 33 dB, average, convenience for RxGain_33dB
-		RxGain_max				= 0x07 << 4		// 111b - 48 dB, maximum, convenience for RxGain_48dB
-	};
-
-	// Commands sent to the PICC.
-	enum PICC_Command : byte {
-		// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
-		PICC_CMD_REQA			= 0x26,		// REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
-		PICC_CMD_WUPA			= 0x52,		// Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
-		PICC_CMD_CT				= 0x88,		// Cascade Tag. Not really a command, but used during anti collision.
-		PICC_CMD_SEL_CL1		= 0x93,		// Anti collision/Select, Cascade Level 1
-		PICC_CMD_SEL_CL2		= 0x95,		// Anti collision/Select, Cascade Level 2
-		PICC_CMD_SEL_CL3		= 0x97,		// Anti collision/Select, Cascade Level 3
-		PICC_CMD_HLTA			= 0x50,		// HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
-		PICC_CMD_RATS           = 0xE0,     // Request command for Answer To Reset.
-		// The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf, Section 9)
-		// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.
-		// The read/write commands can also be used for MIFARE Ultralight.
-		PICC_CMD_MF_AUTH_KEY_A	= 0x60,		// Perform authentication with Key A
-		PICC_CMD_MF_AUTH_KEY_B	= 0x61,		// Perform authentication with Key B
-		PICC_CMD_MF_READ		= 0x30,		// Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
-		PICC_CMD_MF_WRITE		= 0xA0,		// Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
-		PICC_CMD_MF_DECREMENT	= 0xC0,		// Decrements the contents of a block and stores the result in the internal data register.
-		PICC_CMD_MF_INCREMENT	= 0xC1,		// Increments the contents of a block and stores the result in the internal data register.
-		PICC_CMD_MF_RESTORE		= 0xC2,		// Reads the contents of a block into the internal data register.
-		PICC_CMD_MF_TRANSFER	= 0xB0,		// Writes the contents of the internal data register to a block.
-		// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
-		// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
-		PICC_CMD_UL_WRITE		= 0xA2		// Writes one 4 byte page to the PICC.
-	};
-
-	// MIFARE constants that does not fit anywhere else
-	enum MIFARE_Misc {
-		MF_ACK					= 0xA,		// The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK.
-		MF_KEY_SIZE				= 6			// A Mifare Crypto1 key is 6 bytes.
-	};
-
-	// PICC types we can detect. Remember to update PICC_GetTypeName() if you add more.
-	// last value set to 0xff, then compiler uses less ram, it seems some optimisations are triggered
-	enum PICC_Type : byte {
-		PICC_TYPE_UNKNOWN		,
-		PICC_TYPE_ISO_14443_4	,	// PICC compliant with ISO/IEC 14443-4
-		PICC_TYPE_ISO_18092		, 	// PICC compliant with ISO/IEC 18092 (NFC)
-		PICC_TYPE_MIFARE_MINI	,	// MIFARE Classic protocol, 320 bytes
-		PICC_TYPE_MIFARE_1K		,	// MIFARE Classic protocol, 1KB
-		PICC_TYPE_MIFARE_4K		,	// MIFARE Classic protocol, 4KB
-		PICC_TYPE_MIFARE_UL		,	// MIFARE Ultralight or Ultralight C
-		PICC_TYPE_MIFARE_PLUS	,	// MIFARE Plus
-		PICC_TYPE_MIFARE_DESFIRE,	// MIFARE DESFire
-		PICC_TYPE_TNP3XXX		,	// Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
-		PICC_TYPE_NOT_COMPLETE	= 0xff	// SAK indicates UID is not complete.
-	};
-
-	// Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.
-	// last value set to 0xff, then compiler uses less ram, it seems some optimisations are triggered
-	enum StatusCode : byte {
-		STATUS_OK				,	// Success
-		STATUS_ERROR			,	// Error in communication
-		STATUS_COLLISION		,	// Collission detected
-		STATUS_TIMEOUT			,	// Timeout in communication.
-		STATUS_NO_ROOM			,	// A buffer is not big enough.
-		STATUS_INTERNAL_ERROR	,	// Internal error in the code. Should not happen ;-)
-		STATUS_INVALID			,	// Invalid argument.
-		STATUS_CRC_WRONG		,	// The CRC_A does not match
-		STATUS_MIFARE_NACK		= 0xff	// A MIFARE PICC responded with NAK.
-	};
-
-	// A struct used for passing the UID of a PICC.
-	typedef struct {
-		byte		size;			// Number of bytes in the UID. 4, 7 or 10.
-		byte		uidByte[10];
-		byte		sak;			// The SAK (Select acknowledge) byte returned from the PICC after successful selection.
-	} Uid;
-
-	// A struct used for passing a MIFARE Crypto1 key
-	typedef struct {
-		byte		keyByte[MF_KEY_SIZE];
-	} MIFARE_Key;
-
-	// Member variables
-	Uid uid;	// Used by PICC_ReadCardSerial().
-
-	/////////////////////////////////////////////////////////////////////////////////////
-	// Functions for setting up the Arduino
-	/////////////////////////////////////////////////////////////////////////////////////
-	//MFRC522();
-
-	/////////////////////////////////////////////////////////////////////////////////////
-	// Basic interface functions for communicating with the MFRC522
-	/////////////////////////////////////////////////////////////////////////////////////
-	void PCD_WriteRegister(PCD_Register reg, byte value);
-	void PCD_WriteRegister(PCD_Register reg, byte count, byte *values);
-	byte PCD_ReadRegister(PCD_Register reg);
-	void PCD_ReadRegister(PCD_Register reg, byte count, byte *values, byte rxAlign = 0);
-	void PCD_SetRegisterBitMask(PCD_Register reg, byte mask);
-	void PCD_ClearRegisterBitMask(PCD_Register reg, byte mask);
-	StatusCode PCD_CalculateCRC(byte *data, byte length, byte *result);
-
-	/////////////////////////////////////////////////////////////////////////////////////
-	// Functions for manipulating the MFRC522
-	/////////////////////////////////////////////////////////////////////////////////////
-	void PCD_Init();
-	void PCD_Init(byte chipSelectPin, byte resetPowerDownPin);
-	void PCD_Reset();
-	void PCD_AntennaOn();
-	void PCD_AntennaOff();
-	byte PCD_GetAntennaGain();
-	void PCD_SetAntennaGain(byte mask);
-	bool PCD_PerformSelfTest();
-
-	/////////////////////////////////////////////////////////////////////////////////////
-	// Functions for communicating with PICCs
-	/////////////////////////////////////////////////////////////////////////////////////
-	StatusCode PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits = nullptr, byte rxAlign = 0, bool checkCRC = false);
-	StatusCode PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData = nullptr, byte *backLen = nullptr, byte *validBits = nullptr, byte rxAlign = 0, bool checkCRC = false);
-	StatusCode PICC_RequestA(byte *bufferATQA, byte *bufferSize);
-	StatusCode PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
-	StatusCode PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
-	virtual StatusCode PICC_Select(Uid *uid, byte validBits = 0);
-	StatusCode PICC_HaltA();
-
-	/////////////////////////////////////////////////////////////////////////////////////
-	// Functions for communicating with MIFARE PICCs
-	/////////////////////////////////////////////////////////////////////////////////////
-	StatusCode PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
-	void PCD_StopCrypto1();
-	StatusCode MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
-	StatusCode MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
-	StatusCode MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize);
-	StatusCode MIFARE_Decrement(byte blockAddr, int32_t delta);
-	StatusCode MIFARE_Increment(byte blockAddr, int32_t delta);
-	StatusCode MIFARE_Restore(byte blockAddr);
-	StatusCode MIFARE_Transfer(byte blockAddr);
-	StatusCode MIFARE_GetValue(byte blockAddr, int32_t *value);
-	StatusCode MIFARE_SetValue(byte blockAddr, int32_t value);
-	StatusCode PCD_NTAG216_AUTH(byte *passWord, byte pACK[]);
-
-	/////////////////////////////////////////////////////////////////////////////////////
-	// Support functions
-	/////////////////////////////////////////////////////////////////////////////////////
-	StatusCode PCD_MIFARE_Transceive(byte *sendData, byte sendLen, bool acceptTimeout = false);
-	static PICC_Type PICC_GetType(byte sak);
-
-	// Support functions for debuging
-	void PCD_DumpVersionToSerial();
-	void PICC_DumpToSerial(Uid *uid);
-	void PICC_DumpDetailsToSerial(Uid *uid);
-	void PICC_DumpMifareClassicToSerial(Uid *uid, PICC_Type piccType, MIFARE_Key *key);
-	void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);
-	void PICC_DumpMifareUltralightToSerial();
-
-	// Advanced functions for MIFARE
-	void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
-
-	/////////////////////////////////////////////////////////////////////////////////////
-	// Convenience functions - does not add extra functionality
-	/////////////////////////////////////////////////////////////////////////////////////
-	virtual bool PICC_IsNewCardPresent();
-	virtual bool PICC_ReadCardSerial();
-
-protected:
-	// Pins
-	byte _chipSelectPin;		// Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
-	byte _resetPowerDownPin;	// Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
-
-
-	// Functions for communicating with MIFARE PICCs
-	StatusCode MIFARE_TwoStepHelper(byte command, byte blockAddr, int32_t data);
-	SPI m_spi;
-};
-
-#endif
diff --git a/components/cpp_utils/MFRC522Debug.h b/components/cpp_utils/MFRC522Debug.h
deleted file mode 100644
index 6c1c9ac..0000000
--- a/components/cpp_utils/MFRC522Debug.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "MFRC522.h"
-
-#ifndef MFRC522Debug_h
-#define MFRC522Debug_h
-
-class MFRC522Debug {
-private:
-
-public:
-	// Get human readable code and type
-	static const char* PICC_GetTypeName(MFRC522::PICC_Type type);
-	static const char* GetStatusCodeName(MFRC522::StatusCode code);
-};
-#endif // MFRC522Debug_h
diff --git a/components/cpp_utils/MPU6050.cpp b/components/cpp_utils/MPU6050.cpp
deleted file mode 100644
index 5bcf5bb..0000000
--- a/components/cpp_utils/MPU6050.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * Encapsulate the MPU6050.
- */
-
-#include "MPU6050.h"
-#define I2C_ADDRESS 0x68 // I2C address of MPU6050
-
-#define MPU6050_ACCEL_XOUT_H 0x3B
-#define MPU6050_GYRO_XOUT_H  0x43
-#define MPU6050_PWR_MGMT_1   0x6B
-
-/**
- * @brief Construct an %MPU6050 handler.
- */
-MPU6050::MPU6050() {
-	accel_x = accel_y = accel_z = 0;
-	gyro_x  = gyro_y  = gyro_z  = 0;
-	i2c=nullptr;
-	inited=false;
-}
-
-
-/**
- * @brief Destory the class instance.
- */
-MPU6050::~MPU6050() {
-	delete i2c;
-}
-
-
-/**
- * @brief Read the acceleration value from the device.
- *
- * Calling this method results in communication with the device to retrieve the
- * acceleration data that is then stored in the class instance ready for retrieval.
- */
-void MPU6050::readAccel() {
-	assert(inited);
-	i2c->beginTransaction();
-	i2c->write(MPU6050_ACCEL_XOUT_H);
-	i2c->endTransaction();
-
-	uint8_t data[6];
-	i2c->beginTransaction();
-	i2c->read(data, 5, true);
-	i2c->read(data+5, false);
-	i2c->endTransaction();
-
-	accel_x = (data[0] << 8) | data[1];
-	accel_y = (data[2] << 8) | data[3];
-	accel_z = (data[4] << 8) | data[5];
-} // readAccel
-
-/**
- * @brief Read the gyroscopic values from the device.
- *
- * Calling this method results in communication with the device to retrieve the
- * gyroscopic data that is then stored in the class instance ready for retrieval.
- */
-void MPU6050::readGyro() {
-	assert(inited);
-	i2c->beginTransaction();
-	i2c->write(MPU6050_GYRO_XOUT_H);
-	i2c->endTransaction();
-
-	uint8_t data[6];
-	i2c->beginTransaction();
-	i2c->read(data, 5, true);
-	i2c->read(data+5, false);
-	i2c->endTransaction();
-
-	gyro_x = (data[0] << 8) | data[1];
-	gyro_y = (data[2] << 8) | data[3];
-	gyro_z = (data[4] << 8) | data[5];
-} // readGyro
-
-/**
- * @brief Initialize the %MPU6050.
- * @param [in] sdaPin The %GPIO pin to use for %I2C SDA.
- * @param [in] clkPin The %GPIO pin to use for %I2C CLK.
- *
- * This method must be called before any other methods.
- */
-void MPU6050::init(gpio_num_t sdaPin, gpio_num_t clkPin) {
-	i2c = new I2C();
-	i2c->init(I2C_ADDRESS, sdaPin, clkPin);
-	// Dummy call
-	//i2c->setAddress(I2C_ADDRESS);
-	i2c->beginTransaction();
-	i2c->write(MPU6050_ACCEL_XOUT_H);
-	i2c->endTransaction();
-
-	i2c->beginTransaction();
-	i2c->write(MPU6050_PWR_MGMT_1);
-	i2c->write(0);
-	i2c->endTransaction();
-	inited=true;
-}
diff --git a/components/cpp_utils/MPU6050.h b/components/cpp_utils/MPU6050.h
deleted file mode 100644
index fe69193..0000000
--- a/components/cpp_utils/MPU6050.h
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef MAIN_MPU6050_H_
-#define MAIN_MPU6050_H_
-
-#include <math.h>
-#include "I2C.h"
-#include <driver/gpio.h>
-
-/**
- * @brief Driver for the %MPU6050 accelerometer and gyroscope.
- *
- * The %MPU6050 uses %I2C as the communication between the master and the slave.  The class stores
- * the last read values as class instance local data.  The data can be retrieved from the class
- * using the appropriate getters.  The readAccel() and readGyro() methods cause communication
- * with the device to retrieve and locally hold the values from the device.
- *
- * A call to init() must precede all other API calls.
- */
-class MPU6050 {
-private:
-	I2C *i2c;
-	short accel_x, accel_y, accel_z;
-	short gyro_x, gyro_y, gyro_z;
-	bool inited;
-public:
-	MPU6050();
-	virtual ~MPU6050();
-
-
-	/**
-	 * @brief Get the X acceleration value.
-	 */
-	short getAccelX() const
-	{
-		return accel_x;
-	}
-
-	/**
-	 * @brief Get the Y acceleration value.
-	 */
-	short getAccelY() const
-	{
-		return accel_y;
-	}
-
-	/**
-	 * @brief Get the Z acceleration value.
-	 */
-	short getAccelZ() const
-	{
-		return accel_z;
-	}
-
-	/**
-	 * @brief Get the X gyroscopic value.
-	 */
-	short getGyroX() const
-	{
-		return gyro_x;
-	}
-
-	/**
-	 * @brief Get the Y gyroscopic value.
-	 */
-	short getGyroY() const
-	{
-		return gyro_y;
-	}
-
-	/**
-	 * @brief Get the Z gyroscopic value.
-	 */
-	short getGyroZ() const
-	{
-		return gyro_z;
-	}
-
-	/**
-	 * @brief Get the magnitude of the acceleration.
-	 *
-	 * Since acceleration is a vector quantity, it has both direction and magnitude.  This
-	 * method returns the currently known magnitude of the last read data.
-	 *
-	 * @return The magnitude of the acceleration.
-	 */
-	uint32_t getMagnitude() {
-		return sqrt(accel_x * accel_x + accel_y * accel_y + accel_z * accel_z);
-	}
-
-	void init(gpio_num_t sdaPin=I2C::DEFAULT_SDA_PIN, gpio_num_t clkPin=I2C::DEFAULT_CLK_PIN);
-	void readAccel();
-
-	void readGyro();
-};
-
-#endif /* MAIN_MPU6050_H_ */
diff --git a/components/cpp_utils/MRFC522Debug.cpp b/components/cpp_utils/MRFC522Debug.cpp
deleted file mode 100644
index 82cd031..0000000
--- a/components/cpp_utils/MRFC522Debug.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-
-#include "MFRC522Debug.h"
-
-/**
- * Returns a __FlashStringHelper pointer to the PICC type name.
- *
- * @return const __FlashStringHelper *
- */
-const char* MFRC522Debug::PICC_GetTypeName(MFRC522::PICC_Type piccType	///< One of the PICC_Type enums.
-) {
-	switch (piccType) {
-		case MFRC522::PICC_TYPE_ISO_14443_4:		return "PICC compliant with ISO/IEC 14443-4";
-		case MFRC522::PICC_TYPE_ISO_18092:		return "PICC compliant with ISO/IEC 18092 (NFC)";
-		case MFRC522::PICC_TYPE_MIFARE_MINI:		return "MIFARE Mini, 320 bytes";
-		case MFRC522::PICC_TYPE_MIFARE_1K:		return "MIFARE 1KB";
-		case MFRC522::PICC_TYPE_MIFARE_4K:		return "MIFARE 4KB";
-		case MFRC522::PICC_TYPE_MIFARE_UL:		return "MIFARE Ultralight or Ultralight C";
-		case MFRC522::PICC_TYPE_MIFARE_PLUS:		return "MIFARE Plus";
-		case MFRC522::PICC_TYPE_MIFARE_DESFIRE:	return "MIFARE DESFire";
-		case MFRC522::PICC_TYPE_TNP3XXX:			return "MIFARE TNP3XXX";
-		case MFRC522::PICC_TYPE_NOT_COMPLETE:	return "SAK indicates UID is not complete.";
-		case MFRC522::PICC_TYPE_UNKNOWN:
-		default:						return "Unknown type";
-	}
-} // End PICC_GetTypeName()
-
-/**
- * Returns a __FlashStringHelper pointer to a status code name.
- *
- * @return const __FlashStringHelper *
- */
-const char *MFRC522Debug::GetStatusCodeName(MFRC522::StatusCode code	///< One of the StatusCode enums.
-) {
-	switch (code) {
-		case MFRC522::STATUS_OK:				return "Success.";
-		case MFRC522::STATUS_ERROR:			return "Error in communication.";
-		case MFRC522::STATUS_COLLISION:		return "Collission detected.";
-		case MFRC522::STATUS_TIMEOUT:		return "Timeout in communication.";
-		case MFRC522::STATUS_NO_ROOM:		return "A buffer is not big enough.";
-		case MFRC522::STATUS_INTERNAL_ERROR:	return "Internal error in the code. Should not happen.";
-		case MFRC522::STATUS_INVALID:		return "Invalid argument.";
-		case MFRC522::STATUS_CRC_WRONG:		return "The CRC_A does not match.";
-		case MFRC522::STATUS_MIFARE_NACK:	return "A MIFARE PICC responded with NAK.";
-		default:					return "Unknown error";
-	}
-} // End GetStatusCodeName()
diff --git a/components/cpp_utils/Makefile.arduino b/components/cpp_utils/Makefile.arduino
deleted file mode 100644
index c14be63..0000000
--- a/components/cpp_utils/Makefile.arduino
+++ /dev/null
@@ -1,67 +0,0 @@
-# A Makefile that will build the Arduino libraries
-#
-# Targets
-# build_ble - Build the Arduino BLE library.  This will result in a ZIP that can be found at Arduino/ESP32_BLE.zip
-#
-
-#
-# The source file for BLE
-#
-BLE_FILES= \
-	BLE2902.cpp \
-	BLE2902.h \
-	BLEAddress.cpp \
-	BLEAddress.h \
-	BLEAdvertisedDevice.cpp \
-	BLEAdvertisedDevice.h \
-	BLEAdvertising.cpp \
-	BLEAdvertising.h \
-	BLECharacteristic.cpp \
-	BLECharacteristic.h \
-	BLECharacteristicCallbacks.cpp \
-	BLECharacteristicMap.cpp \
-	BLEClient.cpp \
-	BLEClient.h \
-	BLEDescriptor.cpp \
-	BLEDescriptor.h \
-	BLEDescriptorMap.cpp \
-	BLEDevice.cpp \
-	BLEDevice.h \
-	BLERemoteCharacteristic.cpp \
-	BLERemoteCharacteristic.h \
-	BLERemoteDescriptor.cpp \
-	BLERemoteDescriptor.h \
-	BLERemoteService.cpp \
-	BLERemoteService.h \
-	BLEScan.cpp \
-	BLEScan.h \
-	BLEServerCallbacks.cpp \
-	BLEServer.cpp \
-	BLEServer.h \
-	BLEService.cpp \
-	BLEService.h \
-	BLEServiceMap.cpp \
-	BLEUtils.cpp \
-	BLEUtils.h \
-	BLEUUID.cpp \
-	BLEUUID.h \
-	BLEValue.cpp \
-	BLEValue.h \
-	FreeRTOS.h \
-	FreeRTOS.cpp \
-	GeneralUtils.h \
-	GeneralUtils.cpp 
-
-
-build_ble:
-	rm -rf Arduino/ESP32_BLE
-	mkdir -p Arduino/ESP32_BLE/src
-	cp $(BLE_FILES) Arduino/ESP32_BLE/src
-	cp Arduino_ESP32_BLE.library.properties Arduino/ESP32_BLE/library.properties
-	mkdir -p Arduino/ESP32_BLE/examples
-	cp --recursive tests/BLETests/Arduino Arduino/ESP32_BLE/examples
-	rm -f Arduino/ESP32_BLE.zip
-	cd Arduino; zip -r ESP32_BLE.zip ESP32_BLE
-	rm -rf Arduino/ESP32_BLE
-	@echo "---------------------------------------"
-	@echo "ESP32_BLE.zip Arduino library now built"
diff --git a/components/cpp_utils/NeoPixelWiFiEventHandler.cpp b/components/cpp_utils/NeoPixelWiFiEventHandler.cpp
deleted file mode 100644
index 9206b56..0000000
--- a/components/cpp_utils/NeoPixelWiFiEventHandler.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * NeoPixelWiFiEventHandler.cpp
- *
- *  Created on: Mar 1, 2017
- *      Author: kolban
- */
-#include <stdio.h>
-#include "NeoPixelWiFiEventHandler.h"
-
-NeoPixelWiFiEventHandler::NeoPixelWiFiEventHandler(gpio_num_t gpioPin) {
-	this->gpioPin = gpioPin;
-	ws2812 = new WS2812(gpioPin, 8);
-}
-
-NeoPixelWiFiEventHandler::~NeoPixelWiFiEventHandler() {
-	delete ws2812;
-}
-
-esp_err_t NeoPixelWiFiEventHandler::apStart() {
-	printf("XXX apStart\n");
-	ws2812->setPixel(0, 0, 00, 64);
-	ws2812->show();
-	return ESP_OK;
-}
-
-esp_err_t NeoPixelWiFiEventHandler::staConnected() {
-	printf("XXX staConnected\n");
-	ws2812->setPixel(0, 57, 89, 66);
-	ws2812->show();
-	return ESP_OK;
-}
-
-esp_err_t NeoPixelWiFiEventHandler::staDisconnected() {
-	printf("XXX staDisconnected\n");
-	ws2812->setPixel(0, 64, 0, 0);
-	ws2812->show();
-	return ESP_OK;
-}
-
-esp_err_t NeoPixelWiFiEventHandler::staStart() {
-	printf("XXX staStart\n");
-	ws2812->setPixel(0, 64, 64, 0);
-	ws2812->show();
-	return ESP_OK;
-}
-
-esp_err_t NeoPixelWiFiEventHandler::staGotIp(system_event_sta_got_ip_t event_sta_got_ip) {
-	printf("XXX staGotIp\n");
-	ws2812->setPixel(0, 0, 64, 0);
-	ws2812->show();
-	return ESP_OK;
-}
-
-esp_err_t NeoPixelWiFiEventHandler::wifiReady() {
-	printf("XXX wifiReady\n");
-	ws2812->setPixel(0, 64, 64, 0);
-	ws2812->show();
-	return ESP_OK;
-}
diff --git a/components/cpp_utils/NeoPixelWiFiEventHandler.h b/components/cpp_utils/NeoPixelWiFiEventHandler.h
deleted file mode 100644
index c271e3e..0000000
--- a/components/cpp_utils/NeoPixelWiFiEventHandler.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * NeoPixelWiFiEventHandler.h
- *
- *  Created on: Mar 1, 2017
- *      Author: kolban
- */
-
-#ifndef MAIN_NEOPIXELWIFIEVENTHANDLER_H_
-#define MAIN_NEOPIXELWIFIEVENTHANDLER_H_
-#include "WiFiEventHandler.h"
-#include <WS2812.h>
-
-/**
- * @brief Color a neopixel as a function of the %WiFi state.
- *
- * When an ESP32 runs, we can't tell by looking at it the state of the %WiFi connection.
- * This class provides a %WiFi event handler that colors a NeoPixel as a function of the
- * state of the %WiFi.
- */
-class NeoPixelWiFiEventHandler: public WiFiEventHandler {
-public:
-	NeoPixelWiFiEventHandler(gpio_num_t gpioPin);
-	virtual ~NeoPixelWiFiEventHandler();
-
-	esp_err_t apStart() override;
-	esp_err_t staConnected() override;
-	esp_err_t staGotIp(system_event_sta_got_ip_t event_sta_got_ip) override;
-	esp_err_t staDisconnected() override;
-	esp_err_t wifiReady() override;
-	esp_err_t staStart() override;
-private:
-	gpio_num_t gpioPin;
-	WS2812 *ws2812;
-};
-
-#endif /* MAIN_NEOPIXELWIFIEVENTHANDLER_H_ */
diff --git a/components/cpp_utils/OV7670.cpp b/components/cpp_utils/OV7670.cpp
deleted file mode 100644
index 9e4fa7a..0000000
--- a/components/cpp_utils/OV7670.cpp
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * OV7670.cpp
- *
- *  Created on: Jun 10, 2017
- *      Author: kolban
- */
-
-#include "OV7670.h"
-#include "I2S.h"
-#include <driver/gpio.h>
-#include <driver/ledc.h>
-#include "GPIO.h"
-#include "FreeRTOS.h"
-#include "GeneralUtils.h"
-#include "sdkconfig.h"
-#include <esp_log.h>
-extern "C" {
-	#include <soc/i2s_reg.h>
-	#include <soc/i2s_struct.h>
-}
-
-static const char *LOG_TAG="OV7670";
-
-static bool getBit(uint8_t value, uint8_t bitNum) {
-	return (value & (1<<bitNum)) != 0;
-}
-
-static uint8_t setBit(uint8_t value, uint8_t bitNum, bool bitValue) {
-	value = value & (~(1<<bitNum));
-	value = value | (bitValue << bitNum);
-	return value;
-}
-
-static void toGrayscale(uint8_t* pData, uint32_t length) {
-	uint32_t i=0;
-	uint8_t* pLine = new uint8_t[length/2];
-	uint8_t* pLineSave = pLine;
-	// RGB 565
-	// 76543210 76543210
-	//  RRRRRGGG GGGBBBBB
-	while(i < length) {
-		uint8_t byte1 = *pData;
-		pData++;
-		uint8_t byte2 = *pData;
-		pData++;
-		uint8_t red   = ((byte1 & 0b11111000) >> 3) << 3;
-		uint8_t green = (((byte1 & 0b111) << 3) | ((byte2 & 0b11100000) >> 5)) << 2;
-		uint8_t blue  = (byte2 & 0b11111) << 3;
-		*pLine = (red + green + blue)/3;
-		pLine++;
-		i+=2;
-	}
-	pLine = pLineSave;
-	GeneralUtils::hexDump(pLine, length/2);
-}
-
-void OV7670::setFormat(uint8_t value) {
-	uint8_t com7 = readRegister(OV7670_REG_COM7);
-	com7 = setBit(com7, 2, getBit(value, 1));
-	com7 = setBit(com7, 0, getBit(value, 0));
-	writeRegister(OV7670_REG_COM7, com7);
-}
-
-void OV7670::resetCamera() {
-	uint8_t com7 = readRegister(OV7670_REG_COM7);
-	com7 = setBit(com7, 7, true);
-	writeRegister(OV7670_REG_COM7, com7);
-}
-
-void OV7670::setRGBFormat(uint8_t value) {
-	uint8_t com15 = readRegister(OV7670_REG_COM15);
-	com15 = setBit(com15, 5, getBit(value, 1));
-	com15 = setBit(com15, 4, getBit(value, 0));
-	writeRegister(OV7670_REG_COM15, com15);
-}
-
-void OV7670::setTestPattern(uint8_t value) {
-	uint8_t com7 = readRegister(OV7670_REG_COM7);
-	if (value == OV7670_TESTPATTERN_NONE) {
-		com7 = setBit(com7, 1, false);
-	} else {
-		com7 = setBit(com7, 1, true);
-	}
-	writeRegister(OV7670_REG_COM7, com7);
-
-	uint8_t scaling_xsc = readRegister(OV7670_REG_SCALING_XSC);
-	scaling_xsc = setBit(scaling_xsc, 7, getBit(value, 1));
-	writeRegister(OV7670_REG_SCALING_XSC, scaling_xsc);
-	uint8_t scaling_ysc = readRegister(OV7670_REG_SCALING_YSC);
-	scaling_ysc = setBit(scaling_ysc, 7, getBit(value, 0));
-	writeRegister(OV7670_REG_SCALING_YSC, scaling_ysc);
-}
-/*
- *
- * COM7
- * +---+
- * | 7 | SCCB Register Reset
- * |   | 0 - No change
- * |   | 1 - Reset
- * +---+
- * | 6 | Reserved
- * +---+
- * | 5 | Output format - CIF selection
- * +---+
- * | 4 | Output format - QVGA selection
- * +---+
- * | 3 | Output format - QCIF selection
- * +---+
- * | 2 | Output format - RGB selection
- * +---+
- * | 1 | Output format - Color Bar
- * +---+
- * | 0 | Output format - Raw RGB
- * |   |                          COM7[2]   COM7[0]
- * |   | YUV                        0         0
- * |   | RGB                        1         0
- * |   | Bayer RAW                  0         1
- * |   | Processed Bayer RAW        1         1
- * +---+
- *
- */
-
-#define OV7670_I2C_ADDR (0x21)
-/*
-static void IRAM_ATTR isr_vsync(void* arg) {
-	ESP_EARLY_LOGD(LOG_TAG, "VSYNC");
-}
-*/
-
-static uint32_t vsyncCounter = 0;
-//static uint32_t hrefCounter = 0;
-static uint32_t lastHref = 0;
-static uint32_t pclkCounter = 0;
-//static uint32_t lastPclk = 0;
-
-/*
-static void IRAM_ATTR vsyncHandler(void* arg) {
-	vsyncCounter++;
-	lastHref = hrefCounter;
-	hrefCounter = 0;
-}
-*/
-
-/*
-static void IRAM_ATTR hrefHandler(void* arg) {
-	hrefCounter++;
-}
-*/
-
-/*
-static void IRAM_ATTR pclckHandler(void* arg) {
-	pclkCounter++;
-	portYIELD_FROM_ISR();
-}
-*/
-
-/*
-static inline void i2s_conf_reset()
-{
-    const uint32_t lc_conf_reset_flags = I2S_IN_RST_M | I2S_AHBM_RST_M | I2S_AHBM_FIFO_RST_M;
-    I2S0.lc_conf.val |= lc_conf_reset_flags;
-    I2S0.lc_conf.val &= ~lc_conf_reset_flags;
-
-    const uint32_t conf_reset_flags = I2S_RX_RESET_M | I2S_RX_FIFO_RESET_M | I2S_TX_RESET_M | I2S_TX_FIFO_RESET_M;
-    I2S0.conf.val |= conf_reset_flags;
-    I2S0.conf.val &= ~conf_reset_flags;
-    while (I2S0.state.rx_fifo_reset_back) {
-        ;
-    }
-}
-*/
-
-OV7670::OV7670() {
-	m_i2c = nullptr;
-}
-
-
-OV7670::~OV7670() {
-	if (m_i2c != nullptr) {
-		delete m_i2c;
-		m_i2c = nullptr;
-	}
-}
-
-
-static esp_err_t camera_enable_out_clock(camera_config_t* config)
-{
-	ESP_LOGD(LOG_TAG, ">> camera_enable_out_clock: freq_hz=%d, pin=%d", config->xclk_freq_hz, config->pin_xclk);
-	periph_module_enable(PERIPH_LEDC_MODULE);
-
-	ledc_timer_config_t timer_conf;
-	timer_conf.bit_num    = (ledc_timer_bit_t)1;
-	timer_conf.freq_hz    = config->xclk_freq_hz;
-	timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
-	timer_conf.timer_num  = config->ledc_timer;
-	esp_err_t err = ledc_timer_config(&timer_conf);
-	if (err != ESP_OK) {
-			ESP_LOGE(LOG_TAG, "ledc_timer_config failed, rc=%x", err);
-			return err;
-	}
-
-	ledc_channel_config_t ch_conf;
-	ch_conf.channel    = config->ledc_channel;
-	ch_conf.timer_sel  = config->ledc_timer;
-	ch_conf.intr_type  = LEDC_INTR_DISABLE;
-	ch_conf.duty       = 1;
-	ch_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
-	ch_conf.gpio_num   = config->pin_xclk;
-
-	err = ledc_channel_config(&ch_conf);
-	if (err != ESP_OK) {
-			ESP_LOGE(LOG_TAG, "ledc_channel_config failed, rc=%x", err);
-			return err;
-	}
-	ESP_LOGD(LOG_TAG, "<< camera_enable_out_clock");
-	return ESP_OK;
-} // camera_enable_out_clock
-
-/*
-static void i2s_init() {
-	// Enable and configure I2S peripheral
-	periph_module_enable(PERIPH_I2S0_MODULE);
-	// Toggle some reset bits in LC_CONF register
-	// Toggle some reset bits in CONF register
-	// Enable slave mode (sampling clock is external)
-
-	// Switch on Slave mode.
-	// I2S_CONF_REG -> I2S_RX_SLAVE_MOD
-	I2S0.conf.rx_slave_mod = 1;
-
-	// Enable parallel mode
-	// I2S_CONF2_REG -> I2S_LCD_END
-	I2S0.conf2.lcd_en = 1;
-
-	// Use HSYNC/VSYNC/HREF to control sampling
-	// I2S_CONF2_REG -> I2S_CAMERA_EN
-	I2S0.conf2.camera_en = 1;
-
-
-	// Configure clock divider
-	I2S0.clkm_conf.clkm_div_a   = 1;
-	I2S0.clkm_conf.clkm_div_b   = 0;
-	I2S0.clkm_conf.clkm_div_num = 2;
-
-	// FIFO will sink data to DMA
-	I2S0.fifo_conf.dscr_en = 1;
-
-	// FIFO configuration
-	I2S0.fifo_conf.rx_fifo_mod          = 0; // 0-3???
-	I2S0.fifo_conf.rx_fifo_mod_force_en = 1;
-	I2S0.conf_chan.rx_chan_mod          = 1;
-
-	// Clear flags which are used in I2S serial mode
-	I2S0.sample_rate_conf.rx_bits_mod = 0;
-	I2S0.conf.rx_right_first = 0;
-	I2S0.conf.rx_msb_right   = 0;
-	I2S0.conf.rx_msb_shift   = 0;
-	I2S0.conf.rx_mono        = 0;
-	I2S0.conf.rx_short_sync  = 0;
-	I2S0.timing.val          = 0;
-
-}
-*/
-
-/**
- * @brief Dump the settings.
- */
-void OV7670::dump() {
-	ESP_LOGD(LOG_TAG, "PID: 0x%.2x, VER: 0x%.2x, MID: 0x%.4x",
-		readRegister(OV7670_REG_PID),
-		readRegister(OV7670_REG_VER),
-		readRegister(OV7670_REG_MIDH) << 8 | readRegister(OV7670_REG_MIDL));
-	uint8_t com7 = readRegister(OV7670_REG_COM7);
-	uint32_t outputFormat = getBit(com7, 2) << 1 | getBit(com7, 0);
-	//uint32_t outputFormat = (com7 & (1<<2)) >> 1 | (com7 & (1<<0));
-	std::string outputFormatString;
-	switch(outputFormat) {
-	case 0b00:
-		outputFormatString = "YUV";
-		break;
-	case 0b10:
-		outputFormatString = "RGB";
-		break;
-	case 0b01:
-		outputFormatString = "Raw Bayer RGB";
-		break;
-	case 0b11:
-		outputFormatString = "Process Bayer RGB";
-		break;
-	default:
-		outputFormatString = "Unknown";
-		break;
-	}
-	ESP_LOGD(LOG_TAG, "Output format: %s", outputFormatString.c_str());
-	if (outputFormat == 0b10) {
-		uint8_t com15 = readRegister(OV7670_REG_COM15);
-		uint8_t rgbType = getBit(com15, 5) << 1 | getBit(com15,4);
-		char *rgbTypeString;
-		switch(rgbType) {
-		case 0b00:
-		case 0b10:
-			rgbTypeString = (char*)"Normal RGB Output";
-			break;
-		case 0b01:
-			rgbTypeString = (char*)"RGB 565";
-			break;
-		case 0b11:
-			rgbTypeString = (char*)"RGB 555";
-			break;
-		default:
-			rgbTypeString = (char*)"Unknown";
-			break;
-		}
-		ESP_LOGD(LOG_TAG, "Rgb Type: %s", rgbTypeString);
-	}
-	ESP_LOGD(LOG_TAG, "Color bar: %s", getBit(com7, 1)?"Enabled":"Disabled");
-
-	uint8_t scaling_xsc = readRegister(OV7670_REG_SCALING_XSC);
-	uint8_t scaling_ysc = readRegister(OV7670_REG_SCALING_YSC);
-	uint32_t testPattern = getBit(scaling_xsc, 7) << 1 | getBit(scaling_ysc, 7);
-	char *testPatternString;
-	switch(testPattern) {
-	case 0b00:
-		testPatternString = (char*)"No test output";
-		break;
-	case 0b01:
-		testPatternString = (char*)"Shifting 1";
-		break;
-	case 0b10:
-		testPatternString = (char*)"8-bar color bar";
-		break;
-	case 0b11:
-		testPatternString = (char*)"Fade to gray color bar";
-		break;
-	default:
-		testPatternString = (char*)"Unknown";
-		break;
-	}
-	ESP_LOGD(LOG_TAG, "Test pattern: %s", testPatternString);
-	ESP_LOGD(LOG_TAG, "Horizontal scale factor: %d", scaling_xsc & 0x3f);
-	ESP_LOGD(LOG_TAG, "Vertical scale factor: %d", scaling_ysc & 0x3f);
-	uint8_t com15 = readRegister(OV7670_REG_COM15);
-	switch((com15 & 0b11000000) >> 6) {
-	case 0b00:
-	case 0b01:
-		ESP_LOGD(LOG_TAG, "Output range: 0x10 to 0xf0");
-		break;
-	case 0b10:
-		ESP_LOGD(LOG_TAG, "Output range: 0x01 to 0xfe");
-		break;
-	case 0b11:
-		ESP_LOGD(LOG_TAG, "Output range: 0x00 to 0xff");
-		break;
-	}
-} // dump
-
-/*
-static void log(char *marker) {
-	ESP_LOGD(LOG_TAG, "%s", marker);
-	FreeRTOS::sleep(100);
-}
-*/
-
-/**
- * @brief Initialize the camera.
- */
-void OV7670::init(camera_config_t cameraConfig) {
-	ESP_LOGD(LOG_TAG, ">> init");
-	m_cameraConfig = cameraConfig;
-
-	// Define the GPIO pin directions.
-	/*
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_d0);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_d1);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_d2);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_d3);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_d4);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_d5);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_d6);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_d7);
-
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_vsync);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_href);
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_pclk);
-		*/
-	ESP32CPP::GPIO::setInput(m_cameraConfig.pin_xclk);
-	ESP32CPP::GPIO::setOutput(m_cameraConfig.pin_reset);
-
-
-	// Reset the camera.
-	reset();
-	// provide a 20MHz clock on the pin_xclck
-	camera_enable_out_clock(&m_cameraConfig);
-
-	// Create the I2C interface.
-	m_i2c = new I2C();
-	m_i2c->init(OV7670_I2C_ADDR, (gpio_num_t)m_cameraConfig.pin_sscb_sda, (gpio_num_t)m_cameraConfig.pin_sscb_scl);
-	m_i2c->scan();
-	ESP_LOGD(LOG_TAG, "Do you see 0x21 listed?");
-	resetCamera();
-	FreeRTOS::sleep(100);
-	resetCamera();
-	setFormat(OV7670_FORMAT_RGB);
-	setRGBFormat(OV7670_FORMAT_RGB_RGB_565);
-	setTestPattern(OV7670_TESTPATTERN_GRAY_FADE);
-	dump();
-
-	// Setup the VSYNC interrupt handler
-/*
-  ESP32CPP::GPIO::addISRHandler(m_cameraConfig.pin_vsync, vsyncHandler, nullptr);
-  ESP32CPP::GPIO::setInterruptType(m_cameraConfig.pin_vsync, GPIO_INTR_NEGEDGE);
-  ESP32CPP::GPIO::interruptEnable(m_cameraConfig.pin_vsync);
-
-
-  ESP32CPP::GPIO::addISRHandler(m_cameraConfig.pin_href, hrefHandler, nullptr);
-  ESP32CPP::GPIO::setInterruptType(m_cameraConfig.pin_href, GPIO_INTR_NEGEDGE);
-  ESP32CPP::GPIO::interruptEnable(m_cameraConfig.pin_href);
-*/
-
-
-  //ESP32CPP::GPIO::addISRHandler(m_cameraConfig.pin_pclk, pclckHandler, nullptr);
-  //ESP32CPP::GPIO::setInterruptType(m_cameraConfig.pin_pclk, GPIO_INTR_NEGEDGE);
-  //ESP32CPP::GPIO::interruptEnable(m_cameraConfig.pin_pclk);
-
-  /*
-	gpio_isr_handle_t handle;
-	esp_err_t err = ::gpio_isr_register(isr_vsync, nullptr, ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM, &handle);
-	if (err != ESP_OK) {
-		ESP_LOGD(LOG_TAG, "gpio_isr_register: %d", err);
-	}
-	*/
-
-  I2S i2s;
-  dma_config_t dmaConfig;
-  dmaConfig.pin_d0    = cameraConfig.pin_d0;
-  dmaConfig.pin_d1    = cameraConfig.pin_d1;
-  dmaConfig.pin_d2    = cameraConfig.pin_d2;
-  dmaConfig.pin_d3    = cameraConfig.pin_d3;
-  dmaConfig.pin_d4    = cameraConfig.pin_d4;
-  dmaConfig.pin_d5    = cameraConfig.pin_d5;
-  dmaConfig.pin_d6    = cameraConfig.pin_d6;
-  dmaConfig.pin_d7    = cameraConfig.pin_d7;
-  dmaConfig.pin_href  = cameraConfig.pin_href;
-  dmaConfig.pin_pclk  = cameraConfig.pin_pclk;
-  dmaConfig.pin_vsync = cameraConfig.pin_vsync;
-  i2s.cameraMode(dmaConfig, 50, 360*2);
-  ESP_LOGD(LOG_TAG, "Waiting for data!");
-  while(1) {
-  	DMAData dmaData = i2s.waitForData();
-		//GeneralUtils::hexDump(dmaData.getData(), dmaData.getLength());
-  	toGrayscale(dmaData.getData(), dmaData.getLength());
-  	dmaData.free();
-  }
-
-  ESP_LOGD(LOG_TAG, "Waiting for positive edge on VSYNC");
-  while (gpio_get_level(m_cameraConfig.pin_vsync) == 0) {
-      ;
-  }
-  while (gpio_get_level(m_cameraConfig.pin_vsync) != 0) {
-      ;
-  }
-
-
-  ESP_LOGD(LOG_TAG, "Got VSYNC");
-
-
-
-
-  while(1) {
-  	FreeRTOS::sleep(1000);
-  	ESP_LOGD(LOG_TAG, "VSYNC Counter: %d, lastHref=%d, pclk=%d", vsyncCounter, lastHref, pclkCounter);
-  }
-
-	ESP_LOGD(LOG_TAG, "<< init");
-} // init
-
-
-/**
- * Read a register from the camera.
- * @param [in] reg The register to read.
- * @return The value of the register.
- */
-uint8_t OV7670::readRegister(uint8_t reg) {
-	uint8_t val;
-	m_i2c->beginTransaction();
-	m_i2c->write(reg);
-	m_i2c->endTransaction();
-	m_i2c->beginTransaction();
-	m_i2c->read(&val, false);
-	m_i2c->endTransaction();
-	return val;
-} // readRegister
-
-
-/**
- * @brief Write a value to a camera register.
- * @param [in] reg The register to write.
- * @param [in] value The value to write into the register.
- * @return N/A.
- */
-void OV7670::writeRegister(uint8_t reg, uint8_t value) {
-	m_i2c->beginTransaction();
-	m_i2c->write(reg);
-	m_i2c->write(value);
-	m_i2c->endTransaction();
-} // writeRegister
-
-
-/**
- * @brief Reset the camera.
- * Toggle the reset pin on the camera.
- */
-void OV7670::reset() {
-	// Reset the camera
-	ESP_LOGD(LOG_TAG, "x1");
-	ESP32CPP::GPIO::low(m_cameraConfig.pin_reset);
-	FreeRTOS::sleep(10);
-	ESP32CPP::GPIO::high(m_cameraConfig.pin_reset);
-	FreeRTOS::sleep(10);
-} // reset
diff --git a/components/cpp_utils/OV7670.h b/components/cpp_utils/OV7670.h
deleted file mode 100644
index b7baf1f..0000000
--- a/components/cpp_utils/OV7670.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * OV7670.h
- *
- *  Created on: Jun 10, 2017
- *      Author: kolban
- */
-
-#ifndef CPP_UTILS_OV7670_H_
-#define CPP_UTILS_OV7670_H_
-#include <I2C.h>
-#include <driver/ledc.h>
-
-#define OV7670_REG_GAIN   (0x00)
-#define OV7670_REG_BLUE   (0x01)
-#define OV7670_REG_RED    (0x02)
-#define OV7670_REG_VREF   (0x03)
-#define OV7670_REG_COM1   (0x04)
-#define OV7670_REG_BAVE   (0x05)
-#define OV7670_REG_GbAVE  (0x06)
-#define OV7670_REG_AECHH  (0x07)
-#define OV7670_REG_RAVE   (0x08)
-#define OV7670_REG_COM2   (0x09)
-#define OV7670_REG_PID    (0x0A)
-#define OV7670_REG_VER    (0x0B)
-#define OV7670_REG_COM3   (0x0C)
-#define OV7670_REG_COM4   (0x0D)
-#define OV7670_REG_COM5   (0x0E)
-#define OV7670_REG_COM6   (0x0F)
-#define OV7670_REG_AECH   (0x10)
-#define OV7670_REG_CLKRC  (0x11)
-#define OV7670_REG_COM7   (0x12)
-#define OV7670_REG_COM8   (0x13)
-#define OV7670_REG_COM9   (0x14)
-#define OV7670_REG_COM10  (0x15)
-#define OV7670_REG_HSTART (0x17)
-#define OV7670_REG_HSTOP  (0x18)
-#define OV7670_REG_VSTRT  (0x19)
-#define OV7670_REG_VSTOP  (0x1a)
-#define OV7670_REG_PSHFT  (0x1b)
-#define OV7670_REG_MIDH   (0x1c)
-#define OV7670_REG_MIDL   (0x1d)
-#define OV7670_REG_MFVP   (0x1e)
-#define OV7670_REG_LAEC   (0x1f)
-#define OV7670_REG_ADCCTR0 (0x20)
-#define OV7670_REG_ADCCTR1 (0x21)
-#define OV7670_REG_ADCCTR2 (0x22)
-#define OV7670_REG_ADCCTR3 (0x23)
-#define OV7670_REG_AEW    (0x24)
-#define OV7670_REG_AEB    (0x25)
-#define OV7670_REG_VPT    (0x26)
-#define OV7670_REG_BBIAS  (0x27)
-#define OV7670_REG_GbBIAS (0x28)
-#define OV7670_REG_RSVD   (0x00)
-#define OV7670_REG_EXHCH  (0x2a)
-#define OV7670_REG_EXHCL  (0x2b)
-#define OV7670_REG_RBIAS  (0x2c)
-#define OV7670_REG_ADVFL  (0x2d)
-#define OV7670_REG_ADVFH  (0x2e)
-#define OV7670_REG_YAVE   (0x2f)
-#define OV7670_REG_HSYST  (0x30)
-#define OV7670_REG_HSYEN  (0x31)
-#define OV7670_REG_HREF   (0x32)
-#define OV7670_REG_CHLF   (0x33)
-#define OV7670_REG_ARBLM  (0x34)
-#define OV7670_REG_ADC    (0x37)
-#define OV7670_REG_ACOM   (0x38)
-#define OV7670_REG_OFON   (0x39)
-#define OV7670_REG_TSLB   (0x3a)
-#define OV7670_REG_COM11  (0x3b)
-#define OV7670_REG_COM12  (0x3c)
-#define OV7670_REG_COM13  (0x3d)
-#define OV7670_REG_COM14  (0x3e)
-#define OV7670_REG_EDGE   (0x3f)
-#define OV7670_REG_COM15  (0x40)
-#define OV7670_REG_COM16  (0x41)
-#define OV7670_REG_COM17  (0x42)
-#define OV7670_REG_AWBC1  (0x43)
-#define OV7670_REG_AWBC2  (0x44)
-#define OV7670_REG_AWBC3  (0x45)
-#define OV7670_REG_AWBC4  (0x46)
-#define OV7670_REG_AWBC5  (0x47)
-#define OV7670_REG_AWBC6  (0x48)
-#define OV7670_REG_RSVD   (0x00)
-#define OV7670_REG_REG4B  (0x4b)
-#define OV7670_REG_DNSTH  (0x4c)
-#define OV7670_REG_RSVD   (0x00)
-#define OV7670_REG_MTX1   (0x4f)
-#define OV7670_REG_MTX2   (0x50)
-#define OV7670_REG_MTX3   (0x51)
-#define OV7670_REG_MTX4   (0x52)
-#define OV7670_REG_MTX5   (0x53)
-#define OV7670_REG_MTX6   (0x54)
-#define OV7670_REG_BRIGHT (0x55)
-#define OV7670_REG_CONTRAS (0x56)
-#define OV7670_REG_CONTRAS_CENTER (0x57)
-#define OV7670_REG_MTXS  (0x58)
-#define OV7670_REG_RSVD  (0x00)
-#define OV7670_REG_LCC1  (0x62)
-#define OV7670_REG_LCC2  (0x63)
-#define OV7670_REG_LCC3  (0x64)
-#define OV7670_REG_LCC4  (0x65)
-#define OV7670_REG_LCC5  (0x66)
-#define OV7670_REG_MANU  (0x67)
-#define OV7670_REG_MANV  (0x68)
-#define OV7670_REG_GFIX  (0x69)
-#define OV7670_REG_GGAIN (0x6a)
-#define OV7670_REG_DBLV  (0x6b)
-#define OV7670_REG_AWBCTR3 (0x6c)
-#define OV7670_REG_AWBCTR2 (0x6d)
-#define OV7670_REG_AWBCTR1 (0x6e)
-#define OV7670_REG_AWBCTR0 (0x6f)
-#define OV7670_REG_SCALING_XSC      (0x70)
-#define OV7670_REG_SCALING_YSC      (0x71)
-#define OV7670_REG_SCALING_DCWCTR   (0x72)
-#define OV7670_REG_SCALING_PCLK_DIV (0x73)
-#define OV7670_REG_REG74   (0x74)
-#define OV7670_REG_REG75   (0x75)
-#define OV7670_REG_REG76   (0x76)
-#define OV7670_REG_REG77   (0x77)
-#define OV7670_REG_GAM1    (0x7a)
-#define OV7670_REG_GAM2    (0x7b)
-#define OV7670_REG_GAM3    (0x7c)
-#define OV7670_REG_GAM4    (0x7d)
-#define OV7670_REG_GAM5    (0x7e)
-#define OV7670_REG_GAM6    (0x7f)
-#define OV7670_REG_GAM7    (0x80)
-#define OV7670_REG_GAM8    (0x81)
-#define OV7670_REG_GAM9    (0x82)
-#define OV7670_REG_GAM10   (0x83)
-#define OV7670_REG_GAM11   (0x84)
-#define OV7670_REG_GAM12   (0x85)
-#define OV7670_REG_GAM13   (0x86)
-#define OV7670_REG_GAM14   (0x87)
-#define OV7670_REG_GAM15   (0x88)
-#define OV7670_REG_RSVD    (0x00)
-#define OV7670_REG_DM_LNL  (0x92)
-#define OV7670_REG_DML_LNH (0x93)
-#define OV7670_REG_LCC6    (0x94)
-#define OV7670_REG_LCC7    (0x95)
-#define OV7670_REG_BD50ST  (0x9d)
-#define OV7670_REG_BD60ST  (0x9e)
-#define OV7670_REG_STR_OPT (0xAC)
-#define OV7670_REG_STR_R   (0xAD)
-#define OV7670_REG_STR_G   (0xAE)
-#define OV7670_REG_STR_B   (0xAF)
-#define OV7670_REG_THL_ST  (0xB3)
-#define OV7670_REG_THL_DLT (0xB5)
-#define OV7670_REG_AD_CHB  (0xBE)
-#define OV7670_REG_AD_CHR  (0xBF)
-#define OV7670_REG_AD_CHGb (0xC0)
-#define OV7670_REG_AD_CHGr (0xC1)
-#define OV7670_REG_SATCTR  (0xC9)
-
-// COM7[2] and COM7[0]
-#define OV7670_FORMAT_YUV (0b00)
-#define OV7670_FORMAT_RGB (0b10)
-
-#define OV7670_FORMAT_RGB_RGB_NORMAL (0b00)
-#define OV7670_FORMAT_RGB_RGB_565    (0b01)
-#define OV7670_FORMAT_RGB_RGB_555    (0b11)
-
-// SCALING_XSC[7] and SCALINT_YSC[7]
-#define OV7670_TESTPATTERN_NONE      (0b00)
-#define OV7670_TESTPATTERN_SHIFT_1   (0b01)
-#define OV7670_TESTPATTERN_BAR_8     (0b10)
-#define OV7670_TESTPATTERN_GRAY_FADE (0b11)
-
-typedef struct {
-    gpio_num_t pin_reset;          /*!< GPIO pin for camera reset line - OUT */
-    gpio_num_t pin_xclk;           /*!< GPIO pin for camera XCLK line  - IN  */
-    gpio_num_t pin_sscb_sda;       /*!< GPIO pin for camera SDA line   - OUT */
-    gpio_num_t pin_sscb_scl;       /*!< GPIO pin for camera SCL line   - OUT */
-    gpio_num_t pin_d7;             /*!< GPIO pin for camera D7 line    - IN  */
-    gpio_num_t pin_d6;             /*!< GPIO pin for camera D6 line    - IN  */
-    gpio_num_t pin_d5;             /*!< GPIO pin for camera D5 line    - IN  */
-    gpio_num_t pin_d4;             /*!< GPIO pin for camera D4 line    - IN  */
-    gpio_num_t pin_d3;             /*!< GPIO pin for camera D3 line    - IN  */
-    gpio_num_t pin_d2;             /*!< GPIO pin for camera D2 line    - IN  */
-    gpio_num_t pin_d1;             /*!< GPIO pin for camera D1 line    - IN  */
-    gpio_num_t pin_d0;             /*!< GPIO pin for camera D0 line    - IN  */
-    gpio_num_t pin_vsync;          /*!< GPIO pin for camera VSYNC line - IN  */
-    gpio_num_t pin_href;           /*!< GPIO pin for camera HREF line  - IN  */
-    gpio_num_t pin_pclk;           /*!< GPIO pin for camera PCLK line  - IN  */
-
-    int xclk_freq_hz;       /*!< Frequency of XCLK signal, in Hz */
-    ledc_timer_t ledc_timer;        /*!< LEDC timer to be used for generating XCLK  */
-    ledc_channel_t ledc_channel;    /*!< LEDC channel to be used for generating XCLK  */
-} camera_config_t;
-
-class OV7670 {
-public:
-	OV7670();
-	virtual ~OV7670();
-	void init(camera_config_t cameraConfig);
-	void dump();
-	void reset();
-	void setFormat(uint8_t value);
-	void setRGBFormat(uint8_t value);
-	void setTestPattern(uint8_t value);
-	void resetCamera();
-private:
-	uint8_t readRegister(uint8_t reg);
-	void writeRegister(uint8_t reg, uint8_t value);
-	camera_config_t m_cameraConfig;
-	I2C *m_i2c;
-};
-
-#endif /* CPP_UTILS_OV7670_H_ */
diff --git a/components/cpp_utils/PCF8574.cpp b/components/cpp_utils/PCF8574.cpp
deleted file mode 100644
index 4d850a8..0000000
--- a/components/cpp_utils/PCF8574.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * PCF8574.cpp
- *
- *  Created on: Mar 2, 2017
- *      Author: kolban
- */
-
-#include "PCF8574.h"
-#include "I2C.h"
-
-/**
- * @brief Class constructor.
- *
- * The address is the address of the device on the %I2C bus.  This is the value 0x20 plus
- * the value of the device input pins `A0`, `A1` and `A2`.  This means that the address should
- * be between 0x20 and 0x27.
- *
- * @param [in] address The %I2C address of the device on the %I2C bus.
- */
-PCF8574::PCF8574(uint8_t address) {
-	i2c.setAddress(address);
-	lastWrite = 0;
-}
-
-/**
- * @brief Class instance destructor.
- */
-PCF8574::~PCF8574() {
-}
-
-
-/**
- * @brief Read all the input bits from the device.
- * @return An 8 bit value representing the values on each of the input pins.
- */
-uint8_t PCF8574::read() {
-	uint8_t value;
-	i2c.beginTransaction();
-	i2c.read(&value,true);
-	i2c.endTransaction();
-	return value;
-} // read
-
-
-/**
- * @brief Read the logic level on a given pin.
- *
- * @param [in] bit The input pin of the device to read.  Values are 0-7.
- * @return True if the pin is high, false otherwise.  Undefined if there is no signal on the pin.
- */
-bool PCF8574::readBit(uint8_t bit) {
-	if (bit > 7) {
-		return false;
-	}
-	uint8_t value = read();
-	return (value & (1<<bit)) != 0;
-} // readBit
-
-
-/**
- * @brief Set the output values of the device.
- *
- * @param [in] value The bit pattern to set on the output.
- */
-void PCF8574::write(uint8_t value) {
-	if (invert) {
-		value = ~value;
-	}
-	i2c.beginTransaction();
-	i2c.write(value, true);
-	i2c.endTransaction();
-	lastWrite = value;
-} // write
-
-
-/**
- * @brief Change the output value of a specific pin.
- *
- * The other bits beyond the one setting retain their values from the previous call to write() or
- * previous calls to writeBit().
- *
- * @param [in] bit The pin to have its value changed.  The pin may be 0-7.
- * @param [in] value The logic level to appear on the identified output pin.
- */
-void PCF8574::writeBit(uint8_t bit, bool value) {
-	if (bit > 7) {
-		return;
-	}
-	if (invert) {
-		value = !value;
-	}
-	if (value) {
-		lastWrite |= (1<<bit);
-	} else {
-		lastWrite &= ~(1<<bit);
-	}
-	write(lastWrite);
-} // writeBit
-
-
-/**
- * @brief Invert the bit values.
- * Normally setting a pin's value to 1 means that a high signal is generated and a 0 means a low
- * signal is generated.  Setting the inversion to true, inverts that meaning.
- *
- * @param [in] value True if we wish to invert the signals and false otherwise.
- */
-void PCF8574::setInvert(bool value) {
-	this->invert = value;
-} // setInvert
-
-
-/**
- * @brief Initialize the PCF8574 device.
- *
- * @param [in] sdaPin The pin to use for the %I2C SDA functions.
- * @param [in] clkPin The pin to use for the %I2C CLK functions.
- */
-void PCF8574::init(gpio_num_t sdaPin, gpio_num_t clkPin) {
-	i2c.init(0, sdaPin, clkPin);
-} // init
diff --git a/components/cpp_utils/PCF8574.h b/components/cpp_utils/PCF8574.h
deleted file mode 100644
index 15b11da..0000000
--- a/components/cpp_utils/PCF8574.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * PCF8574.h
- *
- *  Created on: Mar 2, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_PCF8574_H_
-#define COMPONENTS_CPP_UTILS_PCF8574_H_
-#include "I2C.h"
-
-/**
- * @brief Encapsulate a %PCF8574 device.
- *
- * The %PCF8574 is a 8 bit %GPIO expander attached to %I2C.  It can read and write 8 bits of data
- * and hence has 8 pins that can be used for input or output.
- *
- * @see [PCF8574 home page](http://www.ti.com/product/PCF8574)
- */
-class PCF8574 {
-public:
-	PCF8574(uint8_t address);
-	virtual ~PCF8574();
-	void init(gpio_num_t sdaPin=I2C::DEFAULT_SDA_PIN, gpio_num_t clkPin=I2C::DEFAULT_CLK_PIN);
-	uint8_t read();
-	bool readBit(uint8_t bit);
-	void setInvert(bool value);
-	void write(uint8_t value);
-	void writeBit(uint8_t bit, bool value);
-
-private:
-	I2C i2c = I2C();
-	uint8_t lastWrite;
-	bool invert = false;
-};
-
-#endif /* COMPONENTS_CPP_UTILS_PCF8574_H_ */
diff --git a/components/cpp_utils/PWM.cpp b/components/cpp_utils/PWM.cpp
deleted file mode 100644
index 3155b42..0000000
--- a/components/cpp_utils/PWM.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * PWM.cpp
- *
- *  Created on: Mar 9, 2017
- *      Author: kolban
- */
-
-#include "PWM.h"
-
-/**
- * @brief Construct an instance.
- *
- * A timer starts ticking up from 0 to the maximum value of the bit size.  When it reaches
- * the maximum value, it resets.
- *
- * In the following example, we create a signal that has a frequency of 100Hz and is
- * a square wave (50% on, 50% off).
- *
- * @code{.cpp}
- * PWM pwm(GPIO_NUM_21);
- * pwm.setDutyPercentage(50);
- * pwm.setFrequency(100);
- * @endcode
- *
- * @param [in] gpioNum The GPIO pin to use for output.
- * @param [in] frequency The frequency of the period.
- * @param [in] bitSize The size in bits of the timer.  Allowed values are LEDC_TIMER_10_BIT,
- * LEDC_TIMER_11_BIT, LEDC_TIMER_12_BIT, LEDC_TIMER_13_BIT, LEDC_TIMER_14_BIT, LEDC_TIMER_15_BIT.
- * @param [in] timer The timer to use. A value of LEDC_TIMER0, LEDC_TIMER1, LEDC_TIMER2 or LEDC_TIMER3.
- * @param [in] channel The channel to use.  A value from LEDC_CHANNEL0 to LEDC_CHANNEL1.
-
- * @return N/A.
- */
-PWM::PWM(int gpioNum, uint32_t frequency, ledc_timer_bit_t bitSize, ledc_timer_t timer, ledc_channel_t channel) {
-	ledc_timer_config_t timer_conf;
-	timer_conf.bit_num    = bitSize;
-	timer_conf.freq_hz    = frequency;
-	timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
-	timer_conf.timer_num  = timer;
-	ESP_ERROR_CHECK(::ledc_timer_config(&timer_conf));
-
-	ledc_channel_config_t ledc_conf;
-	ledc_conf.channel    = channel;
-	ledc_conf.duty       = 0;
-	ledc_conf.gpio_num   = gpioNum;
-	ledc_conf.intr_type  = LEDC_INTR_DISABLE;
-	ledc_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
-	ledc_conf.timer_sel  = timer;
-	ESP_ERROR_CHECK(::ledc_channel_config(&ledc_conf));
-
-	this->channel  = channel;
-	this->timer    = timer;
-	this->bitSize  = bitSize;
-} // PWM
-
-
-/**
- * @brief Get the duty cycle value.
- *
- * @return The duty cycle value.
- */
-uint32_t PWM::getDuty() {
-	return ::ledc_get_duty(LEDC_HIGH_SPEED_MODE, channel);
-} // getDuty
-
-
-/**
- * @brief Get the frequency/period in Hz.
- *
- * @return The frequency/period in Hz.
- */
-uint32_t PWM::getFrequency() {
-	return ::ledc_get_freq(LEDC_HIGH_SPEED_MODE, timer);
-} // getFrequency
-
-
-/**
- * @brief Set the duty cycle value.
- *
- * The duty cycle value is a numeric between 0 and the maximum bit size.  When the
- * %PWM tick value is less than this value, the output is high while when it is higher
- * than this value, the output is low.
- * @param [in] duty The duty cycle value.
- * @return N/A.
- */
-void PWM::setDuty(uint32_t duty) {
-	ESP_ERROR_CHECK(::ledc_set_duty(LEDC_HIGH_SPEED_MODE, channel, duty));
-	ESP_ERROR_CHECK(::ledc_update_duty(LEDC_HIGH_SPEED_MODE, channel));
-} // setDuty
-
-
-/**
- * @brief Set the duty cycle as a percentage value.
- *
- * @param [in] percent The percentage of the duty cycle (0-100).
- * @return N/A.
- */
-void PWM::setDutyPercentage(uint8_t percent) {
-	uint32_t max;
-	switch(bitSize) {
-		case LEDC_TIMER_10_BIT:
-			max = 1 << 10;
-			break;
-		case LEDC_TIMER_11_BIT:
-			max = 1 << 11;
-			break;
-		case LEDC_TIMER_12_BIT:
-			max = 1 << 12;
-			break;
-		case LEDC_TIMER_13_BIT:
-			max = 1 << 13;
-			break;
-		case LEDC_TIMER_14_BIT:
-			max = 1 << 14;
-			break;
-		case LEDC_TIMER_15_BIT:
-			max = 1 << 15;
-			break;
-		default:
-			max = 1 << 10;
-			break;
-	}
-	if (percent > 100) {
-		percent = 100;
-	}
-	uint32_t value = max * percent / 100;
-	if (value >= max) {
-		value = max-1;
-	}
-	setDuty(value);
-
-} // setDutyPercentage
-
-
-/**
- * @brief Set the frequency/period in Hz.
- *
- * @param [in] freq The frequency to set the %PWM.
- * @return N/A.
- */
-void PWM::setFrequency(uint32_t freq) {
-	ESP_ERROR_CHECK(::ledc_set_freq(LEDC_HIGH_SPEED_MODE, timer, freq));
-} // setFrequency
-
-
-/**
- * @brief Stop the %PWM.
- *
- * @param [in] idleLevel The level to leave the output after end.
- * @return N/A.
- */
-void PWM::stop(bool idleLevel) {
-	ESP_ERROR_CHECK(::ledc_stop(LEDC_HIGH_SPEED_MODE, channel, idleLevel));
-} // stop
diff --git a/components/cpp_utils/PWM.h b/components/cpp_utils/PWM.h
deleted file mode 100644
index a048b81..0000000
--- a/components/cpp_utils/PWM.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * PWM.h
- *
- *  Created on: Mar 9, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_PWM_H_
-#define COMPONENTS_CPP_UTILS_PWM_H_
-#include <driver/ledc.h>
-/**
- * @brief A wrapper for ESP32 %PWM control.
- *
- * Pulse Width Modulation (%PWM) is known as "LEDC" in the ESP32.  It allows us to set a repeating
- * clock signal.  There are two aspects to the signal called the frequency and duty cycle.  The
- * frequency is how many times per second the signal repeats.  The duty cycle is how much of a single
- * period the output signal is high compared to low.  For example, a duty cycle of 0% means that the signal
- * is always low, while a duty cycle of 100% means the signal is always high.  A duty cycle of 50% means
- * that the signal is high for 50% of the output and low for the remaining 50%.
- */
-class PWM {
-public:
-	PWM(
-		int gpioNum,
-		uint32_t frequency = 100,
-		ledc_timer_bit_t bitSize = LEDC_TIMER_10_BIT,
-		ledc_timer_t timer = LEDC_TIMER_0,
-		ledc_channel_t channel = LEDC_CHANNEL_0);
-
-	uint32_t getDuty();
-	uint32_t getFrequency();
-	void setDuty(uint32_t duty);
-	void setDutyPercentage(uint8_t percent);
-	void setFrequency(uint32_t freq);
-	void stop(bool idleLevel=false);
-private:
-	ledc_channel_t channel;
-	ledc_timer_t timer;
-	ledc_timer_bit_t bitSize; // Bit size of timer.
-};
-
-#endif /* COMPONENTS_CPP_UTILS_PWM_H_ */
diff --git a/components/cpp_utils/README.md b/components/cpp_utils/README.md
deleted file mode 100644
index fee451e..0000000
--- a/components/cpp_utils/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# CPP Utils
-This directory contains a wealth of C++ classes that have been found useful when working in C++ in conjunction
-with the ESP-IDF.  The classes have been documented using `doxygen` so one can run a doxygen processor over them
-to create the user guides and programming references.
-
-# Compiling the C++ classes
-The C++ classes found here exist as an ESP-IDF component.  To build the classes and then use them in your project perform the following
-steps:
-
-1. Create an ESP-IDF project.
-2. Create a directory called `components` in the root of your ESP-IDF project.
-3. Copy this directory (`cpp_utils`) into your new `components` directory.  The result will be `<project>/components/cpp_utils/<files>`.
-4. In your ESP-IDF project build as normal.
-
-The C++ classes will be compiled and available to be used in your own code.
-
-# Adding a main function
-When working with C++, your calling function should also be written in C++.  Consider replacing your `main.c` with the following
-`main.cpp` file:
-
-```
-extern "C" {
-   void app_main();
-}
-
-void app_main() {
-   // Your code goes here
-}
-```
-
-The way to read the above is that we are defining a global function called `app_main` but we are saying that its external
-linkage (i.e. how it is found and called) is using the C language convention.  However, since the source file is `main.cpp` and
-hence compiled by the C++ compiler, you can utilize C++ classes and language features within and, since it has C linkage, it will
-satisfy the ESP-IDF environment as the entry point into your own code.
-
-## BLE Functions
-The Bluetooth BLE functions are only compiled if Bluetooth is enabled in `make menuconfig`.  This is primarily because
-the ESP-IDF build system has chosen to only compile the underlying BLE functions if Bluetooth is enabled.
-
-## Building the Documentation
-The code is commented using the Doxygen tags.  As such we can run Doxygen to generate the data.  I use `doxywizard` using
-the `Doxyfile` located in this directory.
-
-## Building the Arduino libraries
-Some of the classes in this package also have applicability in an Arduino environment.  A `Makefile` called `Makefile.arduino` is provided to build the libraries.  For example:
-
-```
-$ make -f Makefile.arduino
-```
-
-The results of this will be ZIP files found in the `Arduino` directory relative to this one.  Targets include:
-
-* `build_ble` - Build the BLE libraries. See also: [Arduino BLE Support](ArduinoBLE.md) .
\ No newline at end of file
diff --git a/components/cpp_utils/RESTClient.cpp b/components/cpp_utils/RESTClient.cpp
deleted file mode 100644
index 5cc259c..0000000
--- a/components/cpp_utils/RESTClient.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * RESTClient.cpp
- *
- *  Created on: Mar 12, 2017
- *      Author: kolban
- */
-#if defined(ESP_HAVE_CURL)
-
-#define _GLIBCXX_USE_C99 // Needed for std::string -> to_string inclusion.
-
-
-#include <curl/curl.h>
-#include <esp_log.h>
-#include <string>
-
-#include "RESTClient.h"
-
-static char tag[] = "RESTClient";
-
-
-RESTClient::RESTClient() {
-	m_curlHandle = curl_easy_init();
-	m_timings = new RESTTimings(this);
-} // RESTClient
-
-
-RESTClient::~RESTClient() {
-	::curl_easy_cleanup(m_curlHandle);
-	curl_slist_free_all(m_headers);
-	delete m_timings;
-} // ~RESTClient
-
-
-/**
- * @brief Perform an HTTP GET request.
- */
-void RESTClient::get() {
-	prepForCall();
-	::curl_easy_setopt(m_curlHandle, CURLOPT_HTTPGET, 1);
-	int rc = ::curl_easy_perform(m_curlHandle);
-	if (rc != CURLE_OK) {
-		ESP_LOGE(tag, "get(): %s", getErrorMessage().c_str());
-	}
-} // get
-
-
-/**
- * @brief Perform an HTTP POST request.
- *
- * @param [in] body The body of the payload to send with the post request.
- *
- */
-void RESTClient::post(std::string body) {
-	prepForCall();
-	::curl_easy_setopt(m_curlHandle, CURLOPT_POSTFIELDS, body.c_str());
-	int rc = ::curl_easy_perform(m_curlHandle);
-	if (rc != CURLE_OK) {
-		ESP_LOGE(tag, "post(): %s", getErrorMessage().c_str());
-	}
-} // post
-
-
-/**
- * @brief Get the last error message.
- */
-std::string RESTClient::getErrorMessage() {
-	std::string errMsg(m_errbuf);
-	return errMsg;
-} // getErrorMessage
-
-
-/**
- * @brief Callback function to handle the data received.
- *
- * This is a callback function architected by libcurl to be called when data is received.
- * We append the data to an accumulating buffer.
- *
- * @param [in] buffer A buffer of records.
- * @param [in] size The size of a record.
- * @param [in] nmemb The number of records of unit `size`.
- * @param [in] userp A pointer to the RESTClient class instance.
- *
- * @return The number of bytes of data processed.
- */
-size_t RESTClient::handleData(void *buffer, size_t size, size_t nmemb, void *userp) {
-	//printf("handleData: size: %d, num: %d\n", size, nmemb);
-	RESTClient *pClient = (RESTClient *)userp;
-	pClient->m_response.append((const char *)buffer, size*nmemb);
-	return size * nmemb;
-} // handleData
-
-
-/**
- * @brief Add a header to the list of headers.
- *
- * For example:
- *
- * @code{.cpp}
- * client.addHeader("Content-Type", "application/json");
- * @endcode
- *
- * @param [in] name The name of the header to be added.
- * @param [in] value The value of the header to be added.
- */
-void RESTClient::addHeader(std::string name, std::string value) {
-	std::string headerString = name + ": " + value;
-	m_headers = curl_slist_append(m_headers, headerString.c_str());
-} // addHeader
-
-
-/**
- * @brief Prepare for a call using a reset handle.
- */
-void RESTClient::prepForCall() {
-	::curl_easy_reset(m_curlHandle);
-
-	if (m_verbose) {
-		::curl_easy_setopt(m_curlHandle, CURLOPT_VERBOSE, 1L);
-	} else {
-		::curl_easy_setopt(m_curlHandle, CURLOPT_VERBOSE, 0L);
-	}
-
-	::curl_easy_setopt(m_curlHandle, CURLOPT_ERRORBUFFER, m_errbuf);
-	::curl_easy_setopt(m_curlHandle, CURLOPT_SSL_VERIFYPEER, 0L);
-	::curl_easy_setopt(m_curlHandle, CURLOPT_CAINFO, nullptr);
-	::curl_easy_setopt(m_curlHandle, CURLOPT_URL, m_url.c_str());
-	::curl_easy_setopt(m_curlHandle, CURLOPT_HTTPHEADER, m_headers);
-	::curl_easy_setopt(m_curlHandle, CURLOPT_WRITEFUNCTION, handleData);
-	::curl_easy_setopt(m_curlHandle, CURLOPT_WRITEDATA, this);
-	m_response = "";
-} // prepForCall
-
-
-RESTTimings::RESTTimings(RESTClient *client) {
-	this->client = client;
-}
-
-
-/**
- * @brief Refresh the timings information.
- */
-void RESTTimings::refresh() {
-	::curl_easy_getinfo(client->m_curlHandle, CURLINFO_STARTTRANSFER_TIME, &m_starttransfer);
-	::curl_easy_getinfo(client->m_curlHandle, CURLINFO_NAMELOOKUP_TIME, &m_namelookup);
-	::curl_easy_getinfo(client->m_curlHandle, CURLINFO_CONNECT_TIME, &m_connect);
-	::curl_easy_getinfo(client->m_curlHandle, CURLINFO_APPCONNECT_TIME, &m_appconnect);
-	::curl_easy_getinfo(client->m_curlHandle, CURLINFO_PRETRANSFER_TIME, &m_pretransfer);
-	::curl_easy_getinfo(client->m_curlHandle, CURLINFO_TOTAL_TIME, &m_total);
-} // refresh
-
-
-/**
- * @brief Return the timings information as a string.
- *
- * @return The timings information.
- */
-std::string RESTTimings::toString() {
-	std::string ret = "Start Transfer: " + std::to_string(m_starttransfer) + \
-			"\nName lookup: " + std::to_string(m_namelookup) + \
-			"\nConnect: " + std::to_string(m_connect) + \
-			"\nApp Connect: " + std::to_string(m_appconnect) + \
-			"\nPre Transfer: " + std::to_string(m_pretransfer) + \
-			"\nTotal: " + std::to_string(m_total);
-	return ret;
-} // toString
-#endif // ESP_HAVE_CURL
diff --git a/components/cpp_utils/RESTClient.h b/components/cpp_utils/RESTClient.h
deleted file mode 100644
index d9c4e04..0000000
--- a/components/cpp_utils/RESTClient.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * RESTClient.h
- *
- *  Created on: Mar 12, 2017
- *      Author: kolban
- */
-
-#ifndef MAIN_RESTCLIENT_H_
-#define MAIN_RESTCLIENT_H_
-#if defined(ESP_HAVE_CURL)
-
-#include <string>
-#include <curl/curl.h>
-class RESTClient;
-
-/**
- * @brief Timing data for REST calls.
- */
-class RESTTimings {
-public:
-	RESTTimings(RESTClient *client);
-	void refresh();
-	std::string toString();
-private:
-	double m_namelookup = 0;
-	double m_connect = 0;
-	double m_appconnect = 0;
-	double m_pretransfer = 0;
-	double m_starttransfer = 0;
-	double m_total = 0;
-	RESTClient *client = nullptr;
-};
-
-/**
- * @brief Encapsulate a REST client call.
- *
- * REST is the ability to make service calls using TCP and the HTTP protocols.  This class provides a
- * REST client encapsulation.  A REST client is the part of the story that makes calls to a partner
- * REST service provider (or server).  To make a call to a REST provider we need to specify:
- *
- * * The endpoint ... i.e. where are we sending the request.
- * * The protocol ... i.e. plain HTTP or secure HTTPS.
- * * The HTTP command ... i.e. one of GET, PUT, POST etc.
- * * The headers to the HTTP request.
- * * An optional payload for command types that accept payloads.
- *
- * Here is a code example:
- *
- * @code{cpp}
- * #include <RESTClient.h>
- *
- * RESTClient client;
- * client.setURL("https://httpbin.org/post");
- * client.addHeader("Content-Type", "application/json");
- * client.post("{ \"greeting\": \"hello world!\"");
- * @endcode
- *
- * To use this class you **must** define the `ESP_HAVE_CURL` build definition.  In your component.mk file
- * add:
- *
- * ```
- * CXXFLAGS+=-DESP_HAVE_CURL
- * ```
- */
-class RESTClient {
-public:
-	RESTClient();
-	virtual ~RESTClient();
-	void addHeader(std::string name, std::string value);
-	void get();
-	std::string getErrorMessage();
-	/**
-	 * @brief Get the response payload data from the last REST call.
-	 *
-	 * @return The response payload data.
-	 */
-	std::string getResponse() {
-		return m_response;
-	}
-
-	/**
-	 * @brief Get the timing information associated with this REST connection.
-	 */
-	RESTTimings *getTimings() {
-		return m_timings;
-	}
-
-	void post(std::string body);
-
-	/**
-	 * @brief Set the URL for the target.
-	 *
-	 * @param [in] url The target for HTTP request.
-	 *
-	 */
-	void setURL(std::string url) {
-		m_url = url;
-	};
-
-	/**
-	 * @brief Set the verbosity flag.
-	 *
-	 * @param [in] The value of the verbosity.
-	 */
-	void setVerbose(bool value) {
-		m_verbose = value;
-	};
-
-
-
-private:
-	CURL *m_curlHandle;
-	std::string m_url;
-	char m_errbuf[CURL_ERROR_SIZE];
-	struct curl_slist *m_headers = nullptr;
-	bool m_verbose = false;
-	friend class RESTTimings;
-	RESTTimings *m_timings;
-	std::string m_response;
-	static size_t handleData(void *buffer, size_t size, size_t nmemb, void *userp);
-	void prepForCall();
-};
-#endif /* ESP_HAVE_CURL */
-#endif /* MAIN_RESTCLIENT_H_ */
diff --git a/components/cpp_utils/RMT.cpp b/components/cpp_utils/RMT.cpp
deleted file mode 100644
index 750da1a..0000000
--- a/components/cpp_utils/RMT.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * RMT.cpp
- *
- *  Created on: Mar 1, 2017
- *      Author: kolban
- */
-#include <esp_log.h>
-#include <driver/rmt.h>
-#include "RMT.h"
-
-//static char tag[] = "RMT";
-/**
- * @brief Create a class instance.
- *
- * @param [in] pin The GPIO pin on which the signal is sent/received.
- * @param [in] channel The RMT channel to work with.
- */
-RMT::RMT(gpio_num_t pin, rmt_channel_t channel) {
-	this->channel = channel;
-
-	rmt_config_t config;
-	config.rmt_mode                  = RMT_MODE_TX;
-	config.channel                   = channel;
-	config.gpio_num                  = pin;
-	config.mem_block_num             = 8-this->channel;
-	config.clk_div                   = 8;
-	config.tx_config.loop_en         = 0;
-	config.tx_config.carrier_en      = 0;
-	config.tx_config.idle_output_en  = 1;
-	config.tx_config.idle_level      = (rmt_idle_level_t)0;
-	config.tx_config.carrier_freq_hz = 10000;
-	config.tx_config.carrier_level   = (rmt_carrier_level_t)1;
-	config.tx_config.carrier_duty_percent = 50;
-
-
-	ESP_ERROR_CHECK(rmt_config(&config));
-	ESP_ERROR_CHECK(rmt_driver_install(this->channel, 0, 0));
-}
-
-
-/**
- * @brief Class destructor.
- */
-RMT::~RMT() {
-	ESP_ERROR_CHECK(::rmt_driver_uninstall(this->channel));
-}
-
-/**
- * @brief Start receiving.
- */
-void RMT::rxStart() {
-	ESP_ERROR_CHECK(::rmt_rx_start(this->channel, true));
-}
-
-/**
- * @brief Stop receiving.
- */
-void RMT::rxStop() {
-	ESP_ERROR_CHECK(::rmt_rx_stop(this->channel));
-}
-
-/**
- * @brief Start transmitting.
- */
-void RMT::txStart() {
-	ESP_ERROR_CHECK(::rmt_tx_start(this->channel, true));
-}
-
-/**
- * @brief Stop transmitting.
- */
-void RMT::txStop() {
-	ESP_ERROR_CHECK(::rmt_tx_stop(this->channel));
-}
-
-/**
- * @brief Write the items out through the RMT.
- *
- * The level/duration set of bits that were added to the transaction are written
- * out through the RMT device.  After transmission, the list of level/durations
- * is cleared.
- */
-void RMT::write() {
-	add(false,0);
-	ESP_ERROR_CHECK(::rmt_write_items(this->channel, &items[0], items.size(), true));
-	clear();
-}
-
-
-/**
- * @brief Add a level/duration to the transaction to be written.
- *
- * @param [in] level The level of the bit to output.
- * @param [in] duration The duration of the bit to output.
- */
-void RMT::add(bool level, uint32_t duration) {
-	if (bitCount%2 == 0) {
-		rmt_item32_t item;
-		item.level0 = level;
-		item.duration0 = duration;
-		items.push_back(item);
-	} else {
-		items.at(bitCount/2).level1 = level;
-		items.at(bitCount/2).duration1 = duration;
-	}
-	bitCount++;
-}
-
-/**
- * @brief Clear any previously written level/duration pairs that have not been sent.
- */
-void RMT::clear() {
-	items.clear();
-	bitCount = 0;
-}
diff --git a/components/cpp_utils/RMT.h b/components/cpp_utils/RMT.h
deleted file mode 100644
index 90e5900..0000000
--- a/components/cpp_utils/RMT.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * RMT.h
- *
- *  Created on: Mar 1, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_RMT_H_
-#define COMPONENTS_CPP_UTILS_RMT_H_
-#include <driver/rmt.h>
-#include <vector>
-
-/**
- * @brief Drive the %RMT peripheral.
- */
-class RMT {
-public:
-	RMT(gpio_num_t pin, rmt_channel_t channel=RMT_CHANNEL_0);
-	virtual ~RMT();
-	void add(bool level, uint32_t duration);
-	void clear();
-	void rxStart();
-	void rxStop();
-	void txStart();
-	void txStop();
-	void write();
-
-
-private:
-	rmt_channel_t channel;
-	std::vector<rmt_item32_t> items;
-	int bitCount = 0;
-};
-
-#endif /* COMPONENTS_CPP_UTILS_RMT_H_ */
diff --git a/components/cpp_utils/SOC.cpp b/components/cpp_utils/SOC.cpp
deleted file mode 100644
index 2f4d3a9..0000000
--- a/components/cpp_utils/SOC.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SOC.cpp
- *
- *  Created on: May 16, 2017
- *      Author: kolban
- */
-
-#include "SOC.h"
-#include <esp_log.h>
-extern "C" {
-	#include <soc/i2s_struct.h>
-}
-#include <stdio.h>
-
-SOC::SOC() {
-}
-
-SOC::~SOC() {
-}
-
-/**
- * @brief Dump the status of the I2S peripheral.
- * @return N/A.
- */
-void SOC::I2S::dump() {
-	printf("I2S settings\n");
-	printf("I2S_CLKM_CONF_REG\n");
-	printf("-----------------\n");
-	printf("clkm_div_num: %d, clkm_div_b: %d, clkm_div_a: %d, clk_en: %d, clka_en: %d\n",
-		I2S0.clkm_conf.clkm_div_num,
-		I2S0.clkm_conf.clkm_div_b,
-		I2S0.clkm_conf.clkm_div_a,
-		I2S0.clkm_conf.clk_en,
-		I2S0.clkm_conf.clka_en);
-	uint32_t clockSpeed;
-	if (I2S0.clkm_conf.clkm_div_a == 0) {
-		clockSpeed = 160000000/I2S0.clkm_conf.clkm_div_num;
-	} else {
-		clockSpeed = 160000000/(I2S0.clkm_conf.clkm_div_num + I2S0.clkm_conf.clkm_div_b/I2S0.clkm_conf.clkm_div_a);
-	}
-	printf("Clock speed: %d\n", clockSpeed);
-	printf("\n");
-
-	printf("I2S_CONF_REG\n");
-	printf("------------\n");
-	printf("tx_slave_mod: %s, rx_slave_mod: %s, rx_msb_right: %d, rx_right_first: %d\n",
-		I2S0.conf.tx_slave_mod==0?"Master":"Slave",
-		I2S0.conf.rx_slave_mod==0?"Master":"Slave",
-		I2S0.conf.rx_msb_right,
-		I2S0.conf.rx_right_first);
-	printf("\n");
-
-	printf("I2S_CONF2_REG\n");
-	printf("-------------\n");
-	printf("camera_en: %d, lcd_en: %d, inter_valud_en: %d\n",
-		I2S0.conf2.camera_en,
-		I2S0.conf2.lcd_en,
-		I2S0.conf2.inter_valid_en);
-	printf("\n");
-
-	printf("I2S_CONF_CHAN_REG\n");
-	printf("-----------------\n");
-	printf("tx_chan_mod: %d, rx_chan_mod: %d\n",
-		I2S0.conf_chan.tx_chan_mod,
-		I2S0.conf_chan.rx_chan_mod);
-	printf("\n");
-} // I2S::dump
diff --git a/components/cpp_utils/SOC.h b/components/cpp_utils/SOC.h
deleted file mode 100644
index 6f94a73..0000000
--- a/components/cpp_utils/SOC.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * SOC.h
- *
- *  Created on: May 16, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_SOC_H_
-#define COMPONENTS_CPP_UTILS_SOC_H_
-
-class SOC {
-public:
-	SOC();
-	virtual ~SOC();
-	class I2S {
-	public:
-		static void dump();
-	};
-};
-
-#endif /* COMPONENTS_CPP_UTILS_SOC_H_ */
diff --git a/components/cpp_utils/SPI.cpp b/components/cpp_utils/SPI.cpp
deleted file mode 100644
index e20131f..0000000
--- a/components/cpp_utils/SPI.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * SPI.cpp
- *
- *  Created on: Mar 3, 2017
- *      Author: kolban
- */
-
-#include "SPI.h"
-#include <driver/spi_master.h>
-#include <esp_log.h>
-#include "sdkconfig.h"
-
-//#define DEBUG 1
-
-static char tag[] = "SPI";
-/**
- * @brief Construct an instance of the class.
- *
- * @return N/A.
- */
-SPI::SPI() {
-	m_handle = nullptr;
-	m_host   = HSPI_HOST;
-}
-
-/**
- * @brief Class instance destructor.
- */
-SPI::~SPI() {
-  ESP_LOGI(tag, "... Removing device.");
-  ESP_ERROR_CHECK(::spi_bus_remove_device(m_handle));
-
-  ESP_LOGI(tag, "... Freeing bus.");
-  ESP_ERROR_CHECK(::spi_bus_free(m_host));
-}
-
-/**
- * @brief Initialize SPI.
- *
- * @param [in] mosiPin Pin to use for MOSI %SPI function.
- * @param [in] misoPin Pin to use for MISO %SPI function.
- * @param [in] clkPin Pin to use for CLK %SPI function.
- * @param [in] csPin Pin to use for CS %SPI function.
- * @return N/A.
- */
-void SPI::init(int mosiPin, int misoPin, int clkPin, int csPin) {
-	ESP_LOGD(tag, "init: mosi=%d, miso=%d, clk=%d, cs=%d", mosiPin, misoPin, clkPin, csPin);
-
-	spi_bus_config_t bus_config;
-	bus_config.sclk_io_num     = clkPin;  // CLK
-	bus_config.mosi_io_num     = mosiPin; // MOSI
-	bus_config.miso_io_num     = misoPin; // MISO
-	bus_config.quadwp_io_num   = -1;      // Not used
-	bus_config.quadhd_io_num   = -1;      // Not used
-	bus_config.max_transfer_sz = 0;       // 0 means use default.
-
-	ESP_LOGI(tag, "... Initializing bus; host=%d", m_host);
-
-	esp_err_t errRc = ::spi_bus_initialize(
-			m_host,
-			&bus_config,
-			1 // DMA Channel
-	);
-
-	if (errRc != ESP_OK) {
-		ESP_LOGE(tag, "spi_bus_initialize(): rc=%d", errRc);
-		abort();
-	}
-
-	spi_device_interface_config_t dev_config;
-	dev_config.address_bits     = 0;
-	dev_config.command_bits     = 0;
-	dev_config.dummy_bits       = 0;
-	dev_config.mode             = 0;
-	dev_config.duty_cycle_pos   = 0;
-	dev_config.cs_ena_posttrans = 0;
-	dev_config.cs_ena_pretrans  = 0;
-	dev_config.clock_speed_hz   = 100000;
-	dev_config.spics_io_num     = csPin;
-	dev_config.flags            = 0;
-	dev_config.queue_size       = 1;
-	dev_config.pre_cb           = NULL;
-	dev_config.post_cb          = NULL;
-	ESP_LOGI(tag, "... Adding device bus.");
-	errRc = ::spi_bus_add_device(m_host, &dev_config, &m_handle);
-	if (errRc != ESP_OK) {
-		ESP_LOGE(tag, "spi_bus_add_device(): rc=%d", errRc);
-		abort();
-	}
-} // init
-
-
-/**
- * @brief Set the SPI host to use.
- * Call this prior to init().
- * @param [in] host The SPI host to use.  Either HSPI_HOST (default) or VSPI_HOST.
- */
-void SPI::setHost(spi_host_device_t host) {
-	m_host = host;
-} // setHost
-
-/**
- * @brief Send and receive data through %SPI.  This is a blocking call.
- *
- * @param [in] data A data buffer used to send and receive.
- * @param [in] dataLen The number of bytes to transmit and receive.
- */
-void SPI::transfer(uint8_t* data, size_t dataLen) {
-	assert(data != nullptr);
-	assert(dataLen > 0);
-#ifdef DEBUG
-	for (auto i=0; i<dataLen; i++) {
-		ESP_LOGD(tag, "> %2d %.2x", i, data[i]);
-	}
-#endif
-	spi_transaction_t trans_desc;
-	//trans_desc.address   = 0;
-	//trans_desc.command   = 0;
-	trans_desc.flags     = 0;
-	trans_desc.length    = dataLen * 8;
-	trans_desc.rxlength  = 0;
-	trans_desc.tx_buffer = data;
-	trans_desc.rx_buffer = data;
-
-	//ESP_LOGI(tag, "... Transferring");
-	esp_err_t rc = ::spi_device_transmit(m_handle, &trans_desc);
-	if (rc != ESP_OK) {
-		ESP_LOGE(tag, "transfer:spi_device_transmit: %d", rc);
-	}
-} // transmit
-
-
-/**
- * @brief Send and receive a single byte.
- * @param [in] value The byte to send.
- * @return The byte value received.
- */
-uint8_t SPI::transferByte(uint8_t value) {
-	transfer(&value, 1);
-	return value;
-} // transferByte
-
-
diff --git a/components/cpp_utils/SPI.h b/components/cpp_utils/SPI.h
deleted file mode 100644
index d2de5d9..0000000
--- a/components/cpp_utils/SPI.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SPI.h
- *
- *  Created on: Mar 3, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_SPI_H_
-#define COMPONENTS_CPP_UTILS_SPI_H_
-#include <driver/spi_master.h>
-#include <driver/gpio.h>
-/**
- * @brief Handle %SPI protocol.
- */
-class SPI {
-public:
-	SPI();
-	virtual ~SPI();
-	void    init(
-		int mosiPin = DEFAULT_MOSI_PIN,
-		int misoPin = DEFAULT_MISO_PIN,
-		int clkPin  = DEFAULT_CLK_PIN,
-		int csPin   = DEFAULT_CS_PIN);
-	void    setHost(spi_host_device_t host);
-	void    transfer(uint8_t *data, size_t dataLen);
-	uint8_t transferByte(uint8_t value);
-	/**
-	 * @brief The default MOSI pin.
-	 */
-  static const int DEFAULT_MOSI_PIN = GPIO_NUM_13;
-
-  /**
-   * @brief The default MISO pin.
-   */
-  static const int DEFAULT_MISO_PIN = GPIO_NUM_12;
-
-  /**
-   * @brief The default CLK pin.
-   */
-  static const int DEFAULT_CLK_PIN  = GPIO_NUM_14;
-
-  /**
-   * @brief The default CS pin.
-   */
-  static const int DEFAULT_CS_PIN   = GPIO_NUM_15;
-
-  /**
-   * @brief Value of unset pin.
-   */
-  static const int PIN_NOT_SET      = -1;
-
-private:
-  spi_device_handle_t m_handle;
-  spi_host_device_t   m_host;
-
-};
-
-#endif /* COMPONENTS_CPP_UTILS_SPI_H_ */
diff --git a/components/cpp_utils/SockServ.cpp b/components/cpp_utils/SockServ.cpp
deleted file mode 100644
index 8c6cccb..0000000
--- a/components/cpp_utils/SockServ.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * SockServ.cpp
- *
- *  Created on: Feb 24, 2017
- *      Author: kolban
- */
-
-#include <errno.h>
-#include <esp_log.h>
-#include <FreeRTOS.h>
-#include <freertos/FreeRTOS.h>
-#include <freertos/queue.h>
-
-#include <stdint.h>
-#include <string.h>
-#include <string>
-
-#include "sdkconfig.h"
-#include "SockServ.h"
-#include "Socket.h"
-
-static const char* LOG_TAG = "SockServ";
-
-
-/**
- * @brief Create an instance of the class.
- *
- * We won't actually start listening for clients until after the start() method has been called.
- * @param [in] port The TCP/IP port number on which we will listen for incoming connection requests.
- */
-SockServ::SockServ(uint16_t port) : SockServ() {
-	this->m_port = port;
-
-} // SockServ
-
-SockServ::SockServ() {
-	m_port = 0;
-	m_clientSemaphore.take("SockServ");
-	m_acceptQueue = xQueueCreate(10, sizeof(Socket));
-} // SockServ
-
-/**
- * @brief Accept an incoming connection.
- * @private
- *
- * Block waiting for an incoming connection and accept it when it arrives.
- */
-void SockServ::acceptTask(void *data) {
-
-	SockServ* pSockServ = (SockServ*)data;
-	while(1) {
-		Socket tempSock = pSockServ->m_serverSocket.accept_cpp();
-		if (!tempSock.isValid()) {
-			continue;
-		}
-
-		pSockServ->m_clientSet.insert(tempSock);
-		xQueueSendToBack(pSockServ->m_acceptQueue, &tempSock, portMAX_DELAY);
-		pSockServ->m_clientSemaphore.give();
-	}
-} // acceptTask
-
-
-
-/**
- * @brief Determine the number of connected partners.
- *
- * @return The number of connected partners.
- */
-int SockServ::connectedCount() {
-	return m_clientSet.size();
-} // connectedCount
-
-
-/**
- * @brief Disconnect any connected partners.
- */
-void SockServ::disconnect(Socket s) {
-	auto search = m_clientSet.find(s);
-	m_clientSet.erase(search);
-} // disconnect
-
-
-/**
- * @brief Wait for data
- * @param [in] pData Pointer to buffer to hold the data.
- * @param [in] maxData Maximum size of the data to receive.
- * @return The amount of data returned or 0 if there was an error.
- */
-size_t SockServ::receiveData(Socket s, void* pData, size_t maxData) {
-	int rc = s.receive_cpp((uint8_t*)pData, maxData);
-	if (rc == -1) {
-		ESP_LOGE(LOG_TAG, "recv(): %s", strerror(errno));
-		return 0;
-	}
-	return rc;
-} // receiveData
-
-
-/**
- * @brief Send data from a string to any connected partners.
- *
- * @param[in] str A string from which sequence of bytes will be used to send to the partner.
- */
-void SockServ::sendData(std::string str) {
-	sendData((uint8_t *)str.data(), str.size());
-} // sendData
-
-
-/**
- * @brief Send data to any connected partners.
- *
- * @param[in] data A sequence of bytes to send to the partner.
- * @param[in] length The length of the sequence of bytes to send to the partner.
- */
-void SockServ::sendData(uint8_t* data, size_t length) {
-  for (auto it = m_clientSet.begin(); it != m_clientSet.end(); ++it) {
-  	(*it).send_cpp(data, length);
-  }
-} // sendData
-
-
-/**
- * @brief Set the port number to use.
- * @param port The port number to use.
- */
-void SockServ::setPort(uint16_t port) {
-	m_port = port;
-} // setPort
-
-/**
- * @brief Start listening for new partner connections.
- *
- * The port number on which we will listen is the one defined when the class was created.
- */
-void SockServ::start() {
-	assert(m_port != 0);
-	m_serverSocket.listen_cpp(m_port);
-	ESP_LOGD(LOG_TAG, "Now listening on port %d", m_port);
-	FreeRTOS::startTask(acceptTask, "acceptTask", this);
-} // start
-
-
-/**
- * @brief Stop listening for new partner connections.
- */
-void SockServ::stop() {
-} // stop
-
-
-Socket SockServ::waitForData(std::set<Socket>& socketSet) {
-	fd_set readSet;
-	int maxFd = -1;
-
-	for (	auto it = socketSet.begin(); it != socketSet.end(); ++it) {
-		FD_SET(it->getFD(), &readSet);
-		if (it->getFD() > maxFd) {
-			maxFd = it->getFD();
-		}
-	} // End for
-
-	int rc = ::select(
-		maxFd+1, // Number of sockets to scan
-		&readSet, // Set of read sockets
-		nullptr, // Set of write sockets
-		nullptr, // Set of exception sockets
-		nullptr // Timeout
-	);
-	if (rc == -1) {
-		ESP_LOGE(LOG_TAG, "Error with select");
-		Socket s;
-		return s;
-	}
-
-	for (	auto it = socketSet.begin(); it != socketSet.end(); ++it) {
-		if (FD_ISSET(it->getFD(), &readSet)) {
-			return *it;
-		}
-	} // End for
-	Socket s;
-	return s;
-}
-
-
-/**
- * @brief Wait for a client connection to be present.
- * Returns when a client connection is present.  This can block until a client connects
- * or can return immediately is there is already a client connection in existence.
- */
-Socket SockServ::waitForNewClient() {
-
-	m_clientSemaphore.wait("waitForClient");
-	Socket tempSocket;
-	xQueueReceive(m_acceptQueue, &tempSocket,portMAX_DELAY);
-	return tempSocket;
-} // waitForClient
-
-
diff --git a/components/cpp_utils/SockServ.h b/components/cpp_utils/SockServ.h
deleted file mode 100644
index 48524a1..0000000
--- a/components/cpp_utils/SockServ.h
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-#ifndef MAIN_SOCKSERV_H_
-#define MAIN_SOCKSERV_H_
-#include <stdint.h>
-#include <string>
-#include <set>
-#include "Socket.h"
-#include "FreeRTOS.h"
-#include <freertos/FreeRTOS.h>
-#include <freertos/queue.h>
-
-
-/**
- * @brief Provide a socket listener and the ability to send data to connected partners.
- *
- * We use this class to listen on a given socket and accept connections from partners.
- * When we call one of the sendData() methods, the data passed as parameters is then sent
- * to the connected partners.
- *
- * Here is an example code fragment that uses the class:
- *
- * @code{.cpp}
- * SockServ mySockServer = SockServ(9876);
- * mySockServer.start();
- *
- * // Later ...
- * mySockServer.sendData(data, dataLen);
- * @endcode
- *
- */
-
-class SockServ {
-private:
-	static void acceptTask(void*);
-	uint16_t m_port;
-	Socket   m_serverSocket;
-	FreeRTOS::Semaphore m_clientSemaphore;
-	std::set<Socket> m_clientSet;
-	QueueHandle_t m_acceptQueue;
-public:
-	SockServ(uint16_t port);
-	SockServ();
-	int    connectedCount();
-	void   disconnect(Socket s);
-	size_t receiveData(Socket s, void* pData, size_t maxData);
-	void   sendData(uint8_t* data, size_t length);
-	void   sendData(std::string str);
-	void   setPort(uint16_t port);
-	void   start();
-	void   stop();
-	Socket waitForData(std::set<Socket>& socketSet);
-	Socket waitForNewClient();
-};
-
-#endif /* MAIN_SOCKSERV_H_ */
diff --git a/components/cpp_utils/Socket.cpp b/components/cpp_utils/Socket.cpp
deleted file mode 100644
index a4b38a7..0000000
--- a/components/cpp_utils/Socket.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Socket.cpp
- *
- *  Created on: Mar 5, 2017
- *      Author: kolban
- */
-#include <iostream>
-#include <streambuf>
-#include <cstdio>
-#include <cstring>
-#include <cctype>
-#include <string>
-
-#include <sstream>
-
-#include <errno.h>
-#include <esp_log.h>
-#include <lwip/sockets.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <unistd.h>
-#include "GeneralUtils.h"
-#include "sdkconfig.h"
-#include "Socket.h"
-
-static const char* LOG_TAG = "Socket";
-
-Socket::Socket() {
-	m_sock = -1;
-}
-
-Socket::~Socket() {
-	//close_cpp(); // When the class instance has ended, delete the socket.
-}
-
-
-
-Socket Socket::accept_cpp() {
-	struct sockaddr addr;
-	getBind_cpp(&addr);
-	ESP_LOGD(LOG_TAG, "Accepting on %s", addressToString(&addr).c_str());
-	struct sockaddr_in clientAddress;
-	socklen_t clientAddressLength = sizeof(clientAddress);
-	int clientSockFD = ::accept(m_sock, (struct sockaddr *)&clientAddress, &clientAddressLength);
-	if (clientSockFD == -1) {
-		ESP_LOGE(LOG_TAG, "accept(): %s, m_sock=%d", strerror(errno), m_sock);
-		Socket newSocket;
-		return newSocket;
-	}
-	Socket newSocket;
-	newSocket.m_sock = clientSockFD;
-	return newSocket;
-}
-
-/**
- * @brief Convert a socket address to a string representation.
- * @param [in] addr The address to parse.
- * @return A string representation of the address.
- */
-std::string Socket::addressToString(struct sockaddr* addr) {
-	struct sockaddr_in *pInAddr = (struct sockaddr_in *)addr;
-	char temp[30];
-	char ip[20];
-	inet_ntop(AF_INET, &pInAddr->sin_addr, ip, sizeof(ip));
-	sprintf(temp, "%s [%d]", ip, ntohs(pInAddr->sin_port));
-	return std::string(temp);
-} // addressToString
-
-
-/**
- * @brief Bind an address/port to a socket.
- * Specify a port of 0 to have a local port allocated.
- * Specify an address of INADDR_ANY to use the local server IP.
- * @param [in] port Port number to bind.
- * @param [in] address Address to bind.
- * @return N/A
- */
-void Socket::bind_cpp(uint16_t port, uint32_t address) {
-	ESP_LOGD(LOG_TAG, "bind_cpp: port=%d, address=0x%x", port, address);
-	if (m_sock == -1) {
-		ESP_LOGE(LOG_TAG, "bind_cpp: Socket is not initialized.");
-	}
-	struct sockaddr_in serverAddress;
-	serverAddress.sin_family = AF_INET;
-	serverAddress.sin_addr.s_addr = htonl(address);
-	serverAddress.sin_port   = htons(port);
-	int rc = ::bind(m_sock, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
-	if (rc == -1) {
-		ESP_LOGE(LOG_TAG, "bind_cpp: bind[socket=%d]: %d: %s", m_sock, errno, strerror(errno));
-		return;
-	}
-} // bind_cpp
-
-
-/**
- * @brief Close the socket.
- *
- * @return N/A.
- */
-void Socket::close_cpp() {
-	ESP_LOGD(LOG_TAG, "close_cpp: m_sock=%d", m_sock);
-	if (m_sock != -1) {
-		::close(m_sock);
-	}
-	m_sock = -1;
-} // close_cpp
-
-
-/**
- * @brief Connect to a partner.
- *
- * @param [in] address The IP address of the partner.
- * @param [in] port The port number of the partner.
- * @return Success or failure of the connection.
- */
-int Socket::connect_cpp(struct in_addr address, uint16_t port) {
-	struct sockaddr_in serverAddress;
-	serverAddress.sin_family = AF_INET;
-	serverAddress.sin_addr   = address;
-	serverAddress.sin_port   = htons(port);
-	char msg[50];
-	inet_ntop(AF_INET, &address, msg, sizeof(msg));
-	ESP_LOGD(LOG_TAG, "Connecting to %s:[%d]", msg, port);
-	createSocket_cpp();
-	int rc = ::connect(m_sock, (struct sockaddr *)&serverAddress, sizeof(struct sockaddr_in));
-	if (rc == -1) {
-		ESP_LOGE(LOG_TAG, "connect_cpp: Error: %s", strerror(errno));
-		close_cpp();
-		return -1;
-	} else {
-		ESP_LOGD(LOG_TAG, "Connected to partner");
-		return 0;
-	}
-} // connect_cpp
-
-
-/**
- * @brief Connect to a partner.
- *
- * @param [in] strAddress The string representation of the IP address of the partner.
- * @param [in] port The port number of the partner.
- * @return Success or failure of the connection.
- */
-int Socket::connect_cpp(char* strAddress, uint16_t port) {
-	struct in_addr address;
-	inet_pton(AF_INET, (char *)strAddress, &address);
-	return connect_cpp(address, port);
-}
-
-
-/**
- * @brief Create the socket.
- * @param [in] isDatagram Set to true to create a datagram socket.  Default is false.
- * @return The socket descriptor.
- */
-int Socket::createSocket_cpp(bool isDatagram) {
-	if (isDatagram) {
-		m_sock = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	}
-	else {
-		m_sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	}
-	if (m_sock == -1) {
-		ESP_LOGE(LOG_TAG, "createSocket_cpp: socket: %d", errno);
-		return m_sock;
-	}
-	return m_sock;
-} // createSocket_cpp
-
-
-/**
- * @brief Get the bound address.
- * @param [out] pAddr The storage to hold the address.
- * @return N/A.
- */
-void Socket::getBind_cpp(struct sockaddr* pAddr) {
-	if (m_sock == -1) {
-		ESP_LOGE(LOG_TAG, "getBind_cpp: Socket is not initialized.");
-	}
-	socklen_t nameLen = sizeof(struct sockaddr);
-	::getsockname(m_sock, pAddr, &nameLen);
-} // getBind_cpp
-
-
-/**
- * @brief Get the underlying socket file descriptor.
- * @return The underlying socket file descriptor.
- */
-int Socket::getFD() const {
-	return m_sock;
-} // getFD
-
-
-bool Socket::isValid() {
-	return m_sock != -1;
-} // isValid
-
-/**
- * @brief Create a listening socket.
- * @param [in] port The port number to listen upon.
- * @param [in] isDatagram True if we are listening on a datagram.
- */
-void Socket::listen_cpp(uint16_t port, bool isDatagram) {
-	createSocket_cpp(isDatagram);
-	bind_cpp(port, 0);
-	int rc = ::listen(m_sock, 5);
-	if (rc == -1) {
-		ESP_LOGE(LOG_TAG, "listen_cpp: %s", strerror(errno));
-	}
-} // listen_cpp
-
-bool Socket::operator <(const Socket& other) const {
-	return m_sock < other.m_sock;
-}
-
-
-std::string Socket::readToDelim(std::string delim) {
-	std::string ret;
-	std::string part;
-	auto it = delim.begin();
-	while(1) {
-		uint8_t val;
-		int rc = receive_cpp(&val, 1);
-		if (rc == -1) {
-			return "";
-		}
-		if (rc == 0) {
-			return ret+part;
-		}
-		if (*it == val) {
-			part+= val;
-			++it;
-			if (it == delim.end()) {
-				return ret;
-			}
-		} else {
-			if (part.empty()) {
-				ret += part;
-				part.clear();
-				it = delim.begin();
-			}
-			ret += val;
-		}
-	} // While
-} // readToDelim
-
-
-
-/**
- * @brief Receive data from the partner.
- * Receive data from the socket partner.  If exact = false, we read as much data as
- * is available without blocking up to length.  If exact = true, we will block until
- * we have received exactly length bytes or there are no more bytes to read.
- * @param [in] data The buffer into which the received data will be stored.
- * @param [in] length The size of the buffer.
- * @param [in] exact Read exactly this amount.
- * @return The length of the data received or -1 on an error.
- */
-size_t Socket::receive_cpp(uint8_t* data, size_t length, bool exact) {
-	//ESP_LOGD(LOG_TAG, ">> receive_cpp: length: %d, exact: %d", length, exact);
-	if (exact == false) {
-		int rc = ::recv(m_sock, data, length, 0);
-		if (rc == -1) {
-			ESP_LOGE(LOG_TAG, "receive_cpp: %s", strerror(errno));
-		}
-		//GeneralUtils::hexDump(data, rc);
-		return rc;
-	}
-	size_t amountToRead = length;
-	while(amountToRead > 0) {
-		int rc = ::recv(m_sock, data, amountToRead, 0);
-		if (rc == -1) {
-			ESP_LOGE(LOG_TAG, "receive_cpp: %s", strerror(errno));
-			return 0;
-		}
-		if (rc == 0) {
-			break;
-		}
-		amountToRead -= rc;
-		data+= rc;
-	}
-	//GeneralUtils::hexDump(data, length);
-	return length;
-} // receive_cpp
-
-
-/**
- * @brief Receive data with the address.
- * @param [in] data The location where to store the data.
- * @param [in] length The size of the data buffer into which we can receive data.
- * @param [in] pAddr An area into which we can store the address of the partner.
- * @return The length of the data received.
- */
-int Socket::receiveFrom_cpp(uint8_t* data, size_t length,	struct sockaddr *pAddr) {
-	socklen_t addrLen = sizeof(struct sockaddr);
-	int rc = ::recvfrom(m_sock, data, length, 0, pAddr, &addrLen);
-	return rc;
-} // receiveFrom_cpp
-
-
-/**
- * @brief Send data to the partner.
- *
- * @param [in] data The buffer containing the data to send.
- * @param [in] length The length of data to be sent.
- * @return N/A.
- *
- */
-int Socket::send_cpp(const uint8_t* data, size_t length) const {
-	ESP_LOGD(LOG_TAG, "send_cpp: Raw binary of length: %d", length);
-	//GeneralUtils::hexDump(data, length);
-	int rc = ::send(m_sock, data, length, 0);
-	if (rc == -1) {
-		ESP_LOGE(LOG_TAG, "send: socket=%d, %s", m_sock, strerror(errno));
-	}
-	return rc;
-} // send_cpp
-
-
-/**
- * @brief Send a string to the partner.
- *
- * @param [in] value The string to send to the partner.
- * @return N/A.
- */
-int Socket::send_cpp(std::string value) const {
-	ESP_LOGD(LOG_TAG, "send_cpp: Binary of length: %d", value.length());
-	return send_cpp((uint8_t *)value.data(), value.size());
-} // send_cpp
-
-
-int Socket::send_cpp(uint16_t value) {
-	ESP_LOGD(LOG_TAG, "send_cpp: 16bit value: %.2x", value);
-	return send_cpp((uint8_t *)&value, sizeof(value));
-} // send_cpp
-
-int  Socket::send_cpp(uint32_t value) {
-	ESP_LOGD(LOG_TAG, "send_cpp: 32bit value: %.2x", value);
-	return send_cpp((uint8_t *)&value, sizeof(value));
-} // send_cpp
-
-
-/**
- * @brief Send data to a specific address.
- * @param [in] data The data to send.
- * @param [in] length The length of the data to send/
- * @param [in] pAddr The address to send the data.
- */
-void Socket::sendTo_cpp(const uint8_t* data, size_t length, struct sockaddr* pAddr) {
-	int rc = ::sendto(m_sock, data, length, 0, pAddr, sizeof(struct sockaddr));
-	if (rc == -1) {
-		ESP_LOGE(LOG_TAG, "sendto_cpp: socket=%d %s", m_sock, strerror(errno));
-	}
-} // sendTo_cpp
-
-/**
- * @brief Get the string representation of this socket
- * @return the string representation of the socket.
- */
-std::string Socket::toString() {
-	std::ostringstream oss;
-	oss << "fd: " << m_sock;
-	return oss.str();
-} // toString
-
-
-/**
- * @brief Create a socket input record streambuf
- * @param [in] socket The socket we will be reading from.
- * @param [in] dataLength The size of a record.
- * @param [in] bufferSize The size of the buffer we wish to allocate to hold data.
- */
-SocketInputRecordStreambuf::SocketInputRecordStreambuf(
-	Socket  socket,
-	size_t  dataLength,
-	size_t  bufferSize) {
-	m_socket     = socket;    // The socket we will be reading from
-	m_dataLength = dataLength; // The size of the record we wish to read.
-	m_bufferSize = bufferSize; // The size of the buffer used to hold data
-	m_sizeRead   = 0;          // The size of data read from the socket
-	m_buffer = new char[bufferSize]; // Create the buffer used to hold the data read from the socket.
-
-	setg(m_buffer, m_buffer, m_buffer); // Set the initial get buffer pointers to no data.
-} // SocketInputRecordStreambuf
-
-SocketInputRecordStreambuf::~SocketInputRecordStreambuf() {
-	delete[] m_buffer;
-} // ~SocketInputRecordStreambuf
-
-
-/**
- * @brief Handle the request to read data from the stream but we need more data from the source.
- *
- */
-SocketInputRecordStreambuf::int_type SocketInputRecordStreambuf::underflow() {
-	if (m_sizeRead >= m_dataLength) {
-		return EOF;
-	}
-	int bytesRead = m_socket.receive_cpp((uint8_t*)m_buffer, m_bufferSize, true);
-	if (bytesRead == 0) {
-		return EOF;
-	}
-	m_sizeRead += bytesRead;
-	setg(m_buffer, m_buffer, m_buffer + bytesRead);
-	return traits_type::to_int_type(*gptr());
-} // underflow
diff --git a/components/cpp_utils/Socket.h b/components/cpp_utils/Socket.h
deleted file mode 100644
index 3219b77..0000000
--- a/components/cpp_utils/Socket.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Socket.h
- *
- *  Created on: Mar 5, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_SOCKET_H_
-#define COMPONENTS_CPP_UTILS_SOCKET_H_
-
-#include <string>
-#include <iostream>
-#include <streambuf>
-#include <cstdio>
-#include <cstring>
-#include <lwip/inet.h>
-#include <lwip/sockets.h>
-
-
-/**
- * @brief Encapsulate a socket.
- *
- * Using this class we can connect to a partner TCP server.  Once connected, we can perform
- * send and receive requests to send and receive data.  We should not attempt to send or receive
- * until after a successful connect nor should we send or receive after closing the socket.
- */
-class Socket {
-public:
-	Socket();
-	virtual ~Socket();
-
-	Socket accept_cpp();
-	static std::string addressToString(struct sockaddr* addr);
-	void bind_cpp(uint16_t port, uint32_t address);
-	void close_cpp();
-	int  connect_cpp(struct in_addr address, uint16_t port);
-	int  connect_cpp(char* address, uint16_t port);
-	int  createSocket_cpp(bool isDatagram = false);
-	void getBind_cpp(struct sockaddr* pAddr);
-	int getFD() const;
-	bool isValid();
-	void listen_cpp(uint16_t port, bool isDatagram=false);
-	bool operator<(const Socket& other) const;
-	std::string readToDelim(std::string delim);
-	size_t  receive_cpp(uint8_t* data, size_t length, bool exact=false);
-	int  receiveFrom_cpp(uint8_t* data, size_t length, struct sockaddr* pAddr);
-	int send_cpp(std::string value) const;
-	int send_cpp(const uint8_t* data, size_t length) const;
-	int send_cpp(uint16_t value);
-	int send_cpp(uint32_t value);
-	void sendTo_cpp(const uint8_t* data, size_t length, struct sockaddr* pAddr);
-	std::string toString();
-
-
-private:
-	int m_sock;
-};
-
-class SocketInputRecordStreambuf : public std::streambuf {
-public:
-	SocketInputRecordStreambuf(Socket socket, size_t dataLength, size_t bufferSize=512);
-	~SocketInputRecordStreambuf();
-	int_type underflow();
-private:
-	char *m_buffer;
-	Socket  m_socket;
-	size_t  m_dataLength;
-	size_t  m_bufferSize;
-	size_t  m_sizeRead;
-};
-
-#endif /* COMPONENTS_CPP_UTILS_SOCKET_H_ */
diff --git a/components/cpp_utils/System.cpp b/components/cpp_utils/System.cpp
deleted file mode 100644
index 21a0b9b..0000000
--- a/components/cpp_utils/System.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * System.cpp
- *
- *  Created on: May 27, 2017
- *      Author: kolban
- */
-
-#include "System.h"
-#include <esp_system.h>
-
-System::System() {
-	// TODO Auto-generated constructor stub
-
-}
-
-System::~System() {
-	// TODO Auto-generated destructor stub
-}
-
-/**
- * @brief Get the information about the device.
- * @param [out] info The structure to be populated on return.
- * @return N/A.
- */
-void System::getChipInfo(esp_chip_info_t *info) {
-	::esp_chip_info(info);
-} // getChipInfo
-
-
-/**
- * @brief Retrieve the system wide free heap size.
- * @return The system wide free heap size.
- */
-uint32_t System::getFreeHeapSize() {
-	return esp_get_free_heap_size();
-} // getFreeHeapSize
-
-
-/**
- * @brief Retrieve the version of the ESP-IDF.
- * When an application is compiled, it is compiled against a version of the ESP-IDF.
- * This function returns that version.
- */
-std::string System::getIDFVersion() {
-	return std::string(::esp_get_idf_version());
-} // getIDFVersion
-
-
diff --git a/components/cpp_utils/System.h b/components/cpp_utils/System.h
deleted file mode 100644
index 4c08430..0000000
--- a/components/cpp_utils/System.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * System.h
- *
- *  Created on: May 27, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_SYSTEM_H_
-#define COMPONENTS_CPP_UTILS_SYSTEM_H_
-#include <stdint.h>
-#include <string>
-#include <esp_system.h>
-
-/**
- * @brief System wide functions.
- */
-class System {
-public:
-	System();
-	virtual ~System();
-	static void getChipInfo(esp_chip_info_t *info);
-	static uint32_t getFreeHeapSize();
-	static std::string getIDFVersion();
-};
-
-#endif /* COMPONENTS_CPP_UTILS_SYSTEM_H_ */
diff --git a/components/cpp_utils/TFTP.cpp b/components/cpp_utils/TFTP.cpp
deleted file mode 100644
index afd5cff..0000000
--- a/components/cpp_utils/TFTP.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * TFTP.cpp
- *
- * See also:
- * * https://tools.ietf.org/html/rfc1350
- *  Created on: May 21, 2017
- *      Author: kolban
- */
-
-#include "TFTP.h"
-#include <esp_log.h>
-#include <FreeRTOS.h>
-#include <GeneralUtils.h>
-#include <string>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <Socket.h>
-
-#include "sdkconfig.h"
-
-static char tag[] = "TFTP";
-
-enum opcode {
-	TFTP_OPCODE_RRQ   = 1, // Read request
-	TFTP_OPCODE_WRQ   = 2, // Write request
-	TFTP_OPCODE_DATA  = 3, // Data
-	TFTP_OPCODE_ACK   = 4, // Acknowledgement
-	TFTP_OPCODE_ERROR = 5  // Error
-};
-
-enum ERRORCODE {
-	ERROR_CODE_NOTDEFINED        = 0,
-	ERROR_CODE_FILE_NOT_FOUND    = 1,
-	ERROR_CODE_ACCESS_VIOLATION  = 2,
-	ERROR_CODE_NO_SPACE          = 3,
-	ERROR_CODE_ILLEGAL_OPERATION = 4,
-	ERROR_CODE_UNKNOWN_ID        = 5,
-	ERROR_CODE_FILE_EXISTS       = 6,
-	ERROR_CODE_UNKNOWN_USER      = 7
-};
-
-/**
- * Size of the TFTP data payload.
- */
-const int TFTP_DATA_SIZE=512;
-
-struct data_packet {
-	uint16_t blockNumber;
-	std::string data;
-};
-
-
-
-TFTP::TFTP() {
-	m_baseDir = "";
-}
-
-TFTP::~TFTP() {
-}
-
-/**
- * @brief Start a TFTP transaction.
- * @return N/A.
- */
-TFTP::TFTP_Transaction::TFTP_Transaction() {
-	m_baseDir  = "";
-	m_filename = "";
-	m_mode     = "";
-	m_opCode   = -1;
-} // TFTP_Transaction
-
-
-/**
- * @brief Process a client read request.
- * @return N/A.
- */
-
-void TFTP::TFTP_Transaction::processRRQ() {
-/*
- *   2 bytes     2 bytes     n bytes
- *  ----------------------------------
- * | Opcode |   Block #  |   Data     |
- *  ----------------------------------
- *
- */
-	FILE *file;
-	bool finished = false;
-
-	ESP_LOGD(tag, "Reading TFTP data from file: %s", m_filename.c_str());
-	std::string tmpName = m_baseDir + "/" + m_filename;
-	/*
-	struct stat buf;
-	if (stat(tmpName.c_str(), &buf) != 0) {
-		ESP_LOGE(tag, "Stat file: %s: %s", tmpName.c_str(), strerror(errno));
-		return;
-	}
-	int length = buf.st_size;
-	*/
-
-	int blockNumber = 1;
-
-	file = fopen(tmpName.c_str(), "r");
-	if (file == nullptr) {
-		ESP_LOGE(tag, "Failed to open file for reading: %s: %s", tmpName.c_str(), strerror(errno));
-		sendError(ERROR_CODE_FILE_NOT_FOUND, tmpName);
-		return;
-	}
-
-	uint8_t buf[TFTP_DATA_SIZE + 2 + 2]; // Buffer data size is packet size (512) + 2 bytes for opcode + 2 bytes for blocknumber.
-
-	*(uint16_t *)(&buf[0]) = htons(TFTP_OPCODE_DATA); // Set the op code to be DATA.
-	while(!finished) {
-		*(uint16_t *)(&buf[2]) = htons(blockNumber);
-
-		int sizeRead = fread(&buf[4], 1, TFTP_DATA_SIZE, file);
-
-		ESP_LOGD(tag, "Sending data to %s, blockNumber=%d, size=%d",
-				Socket::addressToString(&m_partnerAddress).c_str(), blockNumber, sizeRead);
-
-		m_partnerSocket.sendTo_cpp(buf, sizeRead+4, &m_partnerAddress);
-
-
-		if (sizeRead < TFTP_DATA_SIZE) {
-			finished = true;
-		} else {
-			waitForAck(blockNumber);
-		}
-		blockNumber++; // Increment the block number.
-	}
-	ESP_LOGD(tag, "File sent");
-} // processRRQ
-
-
-/**
- * @brief Process a client write request.
- * @return N/A.
- */
-void TFTP::TFTP_Transaction::processWRQ() {
-/*
- *        2 bytes    2 bytes       n bytes
- *        ---------------------------------
- * DATA  |  03   |   Block #  |    Data    |
- *        ---------------------------------
- * The opcode for data is 0x03 - TFTP_OPCODE_DATA
- */
-	struct recv_data {
-		uint16_t opCode;
-		uint16_t blockNumber;
-		uint8_t  data;
-	} *pRecv_data;
-
-	struct sockaddr recvAddr;
-	uint8_t dataBuffer[TFTP_DATA_SIZE + 2 + 2];
-	bool finished = false;
-
-	FILE *file;
-
-	ESP_LOGD(tag, "Writing TFTP data to file: %s", m_filename.c_str());
-	std::string tmpName = m_baseDir + "/" + m_filename;
-	file = fopen(tmpName.c_str(), "w");
-	if (file == nullptr) {
-		ESP_LOGE(tag, "Failed to open file for writing: %s: %s", tmpName.c_str(), strerror(errno));
-		return;
-	}
-	while(!finished) {
-		pRecv_data = (struct recv_data *)dataBuffer;
-		int receivedSize = m_partnerSocket.receiveFrom_cpp(dataBuffer, sizeof(dataBuffer), &recvAddr);
-		if (receivedSize == -1) {
-			ESP_LOGE(tag, "rc == -1 from receive_from");
-		}
-		struct data_packet dp;
-		dp.blockNumber = ntohs(pRecv_data->blockNumber);
-		dp.data = std::string((char *)&pRecv_data->data, receivedSize-4);
-		fwrite(dp.data.data(), dp.data.length(), 1, file);
-		sendAck(dp.blockNumber);
-		ESP_LOGD(tag, "Block size: %d", dp.data.length());
-		if (dp.data.length() < TFTP_DATA_SIZE) {
-			finished = true;
-		}
-	} // Finished
-	fclose(file);
-	m_partnerSocket.close_cpp();
-} // process
-
-
-/**
- * @brief Send an acknowledgment back to the partner.
- * A TFTP acknowledgment packet contains an opcode (4) and a block number.
- *
- * @param [in] blockNumber The block number to send.
- * @return N/A.
- */
-void TFTP::TFTP_Transaction::sendAck(uint16_t blockNumber) {
-	struct {
-		uint16_t opCode;
-		uint16_t blockNumber;
-	} ackData;
-
-	ackData.opCode      = htons(TFTP_OPCODE_ACK);
-	ackData.blockNumber = htons(blockNumber);
-
-	ESP_LOGD(tag, "Sending ack to %s, blockNumber=%d", Socket::addressToString(&m_partnerAddress).c_str(), blockNumber);
-	m_partnerSocket.sendTo_cpp((uint8_t *)&ackData, sizeof(ackData), &m_partnerAddress);
-} // sendAck
-
-
-/**
- * @brief Start being a TFTP server.
- *
- * This function does not return.
- *
- * @param [in] port The port number on which to listen.  The default is 69.
- * @return N/A.
- */
-void TFTP::start(uint16_t port) {
-/*
- * Loop forever.  At the start of the loop we block waiting for an incoming client request.
- * The requests that we are expecting are either a request to read a file from the server
- * or write a file to the server.  Once we have received a request we then call the appropriate
- * handler to handle that type of request.  When the request has been completed, we start again.
- */
-	ESP_LOGD(tag, "Starting TFTP::start() on port %d", port);
-	Socket serverSocket;
-	serverSocket.listen_cpp(port, true); // Create a listening socket that is a datagram.
-	while(true) {
-		// This would be a good place to start a transaction in the background.
-		TFTP_Transaction *pTFTPTransaction = new TFTP_Transaction();
-		pTFTPTransaction->setBaseDir(m_baseDir);
-		uint16_t receivedOpCode = pTFTPTransaction->waitForRequest(&serverSocket);
-		switch(receivedOpCode) {
-		// Handle the write request (client file upload)
-			case opcode::TFTP_OPCODE_WRQ: {
-				pTFTPTransaction->processWRQ();
-				break;
-			}
-
-		// Handle the read request (server file download)
-			case opcode::TFTP_OPCODE_RRQ: {
-				pTFTPTransaction->processRRQ();
-				break;
-			}
-		}
-		delete pTFTPTransaction;
-	} // End while loop
-} // run
-
-
-/**
- * @brief Set the base dir for file access.
- * If we are asked to put a file to the file system, this is the base relative directory.
- * @param baseDir Base directory for file access.
- * @return N/A.
- */
-void TFTP::TFTP_Transaction::setBaseDir(std::string baseDir) {
-	m_baseDir = baseDir;
-} // setBaseDir
-
-
-/**
- * @brief Set the base dir for file access.
- * If we are asked to put a file to the file system, this is the base relative directory.
- * @param baseDir Base directory for file access.
- * @return N/A.
- */
-void TFTP::setBaseDir(std::string baseDir) {
-	m_baseDir = baseDir;
-} // setBaseDir
-
-
-/**
- * @brief Wait for an acknowledgment from the client.
- * After having sent data to the client, we expect an acknowledment back from the client.
- * This function causes us to wait for an incoming acknowledgment.
- */
-void TFTP::TFTP_Transaction::waitForAck(uint16_t blockNumber) {
-	struct {
-		uint16_t opCode;
-		uint16_t blockNumber;
-	} ackData;
-
-	ESP_LOGD(tag, "TFTP: Waiting for an acknowledgment request");
-	int sizeRead = m_partnerSocket.receiveFrom_cpp((uint8_t *)&ackData, sizeof(ackData), &m_partnerAddress);
-	ESP_LOGD(tag, "TFTP: Received some data.");
-
-	if (sizeRead != sizeof(ackData)) {
-		ESP_LOGE(tag, "waitForAck: Received %d but expected %d", sizeRead, sizeof(ackData));
-		sendError(ERROR_CODE_NOTDEFINED, "Ack not correct size");
-		return;
-	}
-
-	ackData.opCode      = ntohs(ackData.opCode);
-	ackData.blockNumber = ntohs(ackData.blockNumber);
-
-	if (ackData.opCode != opcode::TFTP_OPCODE_ACK) {
-		ESP_LOGE(tag, "waitForAck: Received opcode %d but expected %d", ackData.opCode, opcode::TFTP_OPCODE_ACK);
-		return;
-	}
-
-	if (ackData.blockNumber != blockNumber) {
-		ESP_LOGE(tag, "waitForAck: Blocknumber received %d but expected %d", ackData.blockNumber, blockNumber);
-		return;
-	}
-} // waitForAck
-
-
-/**
- * @brief Wait for a client request.
- * A %TFTP server waits for requests to send or receive files.  A request can be
- * either WRQ (write request) which is a request from the client to write a new local
- * file or it can be a RRQ (read request) which is a request from the client to
- * read a local file.
- * @param pServerSocket The server socket on which to listen for client requests.
- * @return The op code received.
- */
-uint16_t TFTP::TFTP_Transaction::waitForRequest(Socket *pServerSocket) {
-/*
- *        2 bytes    string   1 byte     string   1 byte
- *        -----------------------------------------------
- * RRQ/  | 01/02 |  Filename  |   0  |    Mode    |   0  |
- * WRQ    -----------------------------------------------
- */
-	uint8_t buf[TFTP_DATA_SIZE];
-	size_t length = 100;
-
-	ESP_LOGD(tag, "TFTP: Waiting for a request");
-	pServerSocket->receiveFrom_cpp(buf, length, &m_partnerAddress);
-
-	// Save the filename, mode and op code.
-
-	m_filename = std::string((char *)(buf+2));
-	m_mode     = std::string((char *)(buf + 3 + m_filename.length()));
-	m_opCode   = ntohs(*(uint16_t *)buf);
-	switch(m_opCode) {
-
-		// Handle the Write Request command.
-		case TFTP_OPCODE_WRQ: {
-			m_partnerSocket.createSocket_cpp(true);
-			m_partnerSocket.bind_cpp(0, INADDR_ANY);
-			sendAck(0);
-			break;
-		}
-
-
-		// Handle the Read request command.
-		case TFTP_OPCODE_RRQ: {
-			m_partnerSocket.createSocket_cpp(true);
-			m_partnerSocket.bind_cpp(0, INADDR_ANY);
-			break;
-		}
-
-		default: {
-			ESP_LOGD(tag, "Un-handled opcode: %d", m_opCode);
-			break;
-		}
-	}
-	return m_opCode;
-} // waitForRequest
-
-/**
- * @brief Send an error indication to the client.
- * @param [in] code Error code to send to the client.
- * @param [in] message Explanation message.
- * @return N/A.
- */
-void TFTP::TFTP_Transaction::sendError(uint16_t code, std::string message) {
-/*
- *  2 bytes     2 bytes      string    1 byte
- *  -----------------------------------------
- * | Opcode |  ErrorCode |   ErrMsg   |   0  |
- *  -----------------------------------------
- */
-	int size = 2  + 2 + message.length() + 1;
-	uint8_t *buf = (uint8_t *)malloc(size);
-	*(uint16_t *)(&buf[0]) = htons(opcode::TFTP_OPCODE_ERROR);
-	*(uint16_t *)(&buf[2]) = htons(code);
-	strcpy((char *)(&buf[4]), message.c_str());
-	m_partnerSocket.sendTo_cpp(buf, size, &m_partnerAddress);
-	free(buf);
-} // sendError
diff --git a/components/cpp_utils/TFTP.h b/components/cpp_utils/TFTP.h
deleted file mode 100644
index 3f40bd2..0000000
--- a/components/cpp_utils/TFTP.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * TFTP.h
- *
- *  Created on: May 21, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_TFTP_H_
-#define COMPONENTS_CPP_UTILS_TFTP_H_
-#define TFTP_DEFAULT_PORT (69)
-#include <string>
-#include <Socket.h>
-/**
- * @brief A %TFTP server.
- *
- * The Trivial %File Transfer Protocol is a specification for simple file transfer
- * without the richness of implementation of full FTP.  It is very easy to implement
- * both a server and a client.  The protocol leverages UDP as opposed to connection
- * oriented (TCP).  The specification can be found <a href="https://tools.ietf.org/html/rfc1350">here</a>.
- *
- * Here is an example fragment which mounts a file system and then starts a %TFTP server
- * to provide access to its content.
- *
- * @code{.cpp}
- * FATFS_VFS fs("/spiflash", "storage");
- * fs.mount();
- *
- * TFTP tftp;
- * tftp.setBaseDir("/spiflash");
- * tftp.start();
- * @endcode
- *
- * On Linux, I recommend the <a href="https://linux.die.net/man/1/atftp">atftp</a> client.
- */
-class TFTP {
-public:
-	TFTP();
-	virtual ~TFTP();
-	void start(uint16_t port=TFTP_DEFAULT_PORT);
-	void setBaseDir(std::string baseDir);
-	/**
-	 * @brief Internal class for %TFTP processing.
-	 */
-	class TFTP_Transaction {
-	public:
-		TFTP_Transaction();
-		void processWRQ();
-		void processRRQ();
-		void sendAck(uint16_t blockNumber);
-		void sendError(uint16_t code, std::string message);
-		void setBaseDir(std::string baseDir);
-		void waitForAck(uint16_t blockNumber);
-		uint16_t waitForRequest(Socket *pServerSocket);
-	private:
-		/**
-		 * Socket on which the server will communicate with the client..
-		 */
-		Socket m_partnerSocket;
-		struct sockaddr m_partnerAddress;
-		uint16_t    m_opCode; // The last op code received.
-		std::string m_filename; // The name of the file.
-		std::string m_mode;
-		std::string m_baseDir; // The base directory.
-	};
-private:
-	std::string m_baseDir;
-};
-
-#endif /* COMPONENTS_CPP_UTILS_TFTP_H_ */
diff --git a/components/cpp_utils/Task.cpp b/components/cpp_utils/Task.cpp
deleted file mode 100644
index fe6ba2d..0000000
--- a/components/cpp_utils/Task.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Task.cpp
- *
- *  Created on: Mar 4, 2017
- *      Author: kolban
- */
-
-
-#include <esp_log.h>
-#include <freertos/FreeRTOS.h>
-#include <freertos/task.h>
-#include <string>
-
-#include "Task.h"
-#include "sdkconfig.h"
-
-static char tag[] = "Task";
-
-
-/**
- * @brief Create an instance of the task class.
- *
- * @param [in] taskName The name of the task to create.
- * @param [in] stackSize The size of the stack.
- * @return N/A.
- */
-Task::Task(std::string taskName, uint16_t stackSize) {
-	m_taskName  = taskName;
-	m_stackSize = stackSize;
-	m_taskData  = nullptr;
-	m_handle    = nullptr;
-} // Task
-
-Task::~Task() {
-} // ~Task
-
-/**
- * @brief Suspend the task for the specified milliseconds.
- *
- * @param [in] ms The delay time in milliseconds.
- * @return N/A.
- */
-
-void Task::delay(int ms) {
-	::vTaskDelay(ms/portTICK_PERIOD_MS);
-} // delay
-
-/**
- * Static class member that actually runs the target task.
- *
- * The code here will run on the task thread.
- * @param [in] pTaskInstance The task to run.
- */
-void Task::runTask(void* pTaskInstance) {
-	Task* pTask = (Task*)pTaskInstance;
-	ESP_LOGD(tag, ">> runTask: taskName=%s", pTask->m_taskName.c_str());
-	pTask->run(pTask->m_taskData);
-	pTask->stop();
-	ESP_LOGD(tag, "<< runTask: taskName=%s", pTask->m_taskName.c_str());
-} // runTask
-
-/**
- * @brief Start an instance of the task.
- *
- * @param [in] taskData Data to be passed into the task.
- * @return N/A.
- */
-void Task::start(void* taskData) {
-	if (m_handle != nullptr) {
-		ESP_LOGW(tag, "Task::start - There might be a task already running!");
-	}
-	m_taskData = taskData;
-	::xTaskCreate(&runTask, m_taskName.c_str(), m_stackSize, this, 5, &m_handle);
-} // start
-
-
-/**
- * @brief Stop the task.
- *
- * @return N/A.
- */
-void Task::stop() {
-	if (m_handle == nullptr) {
-		return;
-	}
-	xTaskHandle temp = m_handle;
-	m_handle = nullptr;
-	::vTaskDelete(temp);
-} // stop
-
-/**
- * @brief Set the stack size of the task.
- *
- * @param [in] stackSize The size of the stack for the task.
- * @return N/A.
- */
-void Task::setStackSize(uint16_t stackSize) {
-	m_stackSize = stackSize;
-} // setStackSize
diff --git a/components/cpp_utils/Task.h b/components/cpp_utils/Task.h
deleted file mode 100644
index 51e18fc..0000000
--- a/components/cpp_utils/Task.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Task.h
- *
- *  Created on: Mar 4, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_TASK_H_
-#define COMPONENTS_CPP_UTILS_TASK_H_
-#include <freertos/FreeRTOS.h>
-#include <freertos/task.h>
-#include <string>
-/**
- * @brief Encapsulate a runnable task.
- *
- * This class is designed to be subclassed with the method:
- *
- * @code{.cpp}
- * void run(void *data) { ... }
- * @endcode
- *
- * For example:
- *
- * @code{.cpp}
- * class CurlTestTask : public Task {
- *    void run(void *data) {
- *       // Do something
- *    }
- * };
- * @endcode
- *
- * implemented.
- */
-class Task {
-public:
-	Task(std::string taskName="Task", uint16_t stackSize=10000);
-	virtual ~Task();
-	void setStackSize(uint16_t stackSize);
-	void start(void* taskData=nullptr);
-	void stop();
-	/**
-	 * @brief Body of the task to execute.
-	 *
-	 * This function must be implemented in the subclass that represents the actual task to run.
-	 * When a task is started by calling start(), this is the code that is executed in the
-	 * newly created task.
-	 *
-	 * @param [in] data The data passed in to the newly started task.
-	 */
-	virtual void run(void *data) = 0; // Make run pure virtual
-	void delay(int ms);
-
-private:
-	xTaskHandle m_handle;
-	void*       m_taskData;
-	static void runTask(void *data);
-	std::string m_taskName;
-	uint16_t    m_stackSize;
-};
-
-#endif /* COMPONENTS_CPP_UTILS_TASK_H_ */
diff --git a/components/cpp_utils/U8G2.cpp b/components/cpp_utils/U8G2.cpp
deleted file mode 100644
index bb3fc70..0000000
--- a/components/cpp_utils/U8G2.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * U8G2.cpp
- *
- *  Created on: May 6, 2017
- *      Author: kolban
- */
-#include "sdkconfig.h"
-#ifdef CONFIG_U8G2_PRESENT
-#include "U8G2.h"
-#include <u8g2.h>
-extern "C" {
-#include <u8g2_esp32_hal.h>
-}
-U8G2::U8G2(gpio_num_t sda, gpio_num_t scl, int address) {
-	// TODO Auto-generated constructor stub
-	u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
-	u8g2_esp32_hal.sda = sda;
-	u8g2_esp32_hal.scl = scl;
-	u8g2_esp32_hal_init(u8g2_esp32_hal);
-
-	u8g2_Setup_ssd1306_128x32_univision_f(
-		&m_u8g2,
-		U8G2_R0,
-		//u8x8_byte_sw_i2c,
-		u8g2_esp32_msg_i2c_cb,
-		u8g2_esp32_msg_i2c_and_delay_cb);  // init u8g2 structure
-	u8x8_SetI2CAddress(&m_u8g2.u8x8,address << 1);
-}
-
-U8G2::~U8G2() {
-	// TODO Auto-generated destructor stub
-}
-
-#endif // CONFIG_U8G2_PRESENT
diff --git a/components/cpp_utils/U8G2.h b/components/cpp_utils/U8G2.h
deleted file mode 100644
index db57ba6..0000000
--- a/components/cpp_utils/U8G2.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * U8G2.h
- *
- *  Created on: May 6, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_U8G2_H_
-#define COMPONENTS_CPP_UTILS_U8G2_H_
-#include "sdkconfig.h"
-#ifdef CONFIG_U8G2_PRESENT
-#include <u8g2.h>
-#include <driver/gpio.h>
-#include <string>
-
-/**
- * @brief Wrapper for the U8G2 display driver library.
- */
-class U8G2 {
-public:
-	U8G2(gpio_num_t sda, gpio_num_t scl, int address);
-	virtual ~U8G2();
-	void clearBuffer() {
-		u8g2_ClearBuffer(&m_u8g2);
-	}
-
-	void drawBitmap(uint32_t x, uint32_t y, uint32_t cnt, uint32_t h, const uint8_t *bitmap) {
-		u8g2_DrawBitmap(&m_u8g2, x, y, cnt, h, bitmap);
-	}
-
-	void drawBox(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
-		u8g2_DrawBox(&m_u8g2, x, y, w, h);
-	}
-
-	void drawCircle(uint32_t x0, uint32_t y0, uint32_t rad, uint8_t opt) {
-		u8g2_DrawCircle(&m_u8g2, x0, y0,  rad, opt);
-	}
-
-	void drawDisc(uint32_t x0, uint32_t y0, uint32_t rad, uint8_t opt) {
-		u8g2_DrawDisc(&m_u8g2, x0, y0, rad, opt);
-	}
-
-	void drawEllipse(uint32_t x0, uint32_t y0, uint32_t rx, uint32_t ry, uint8_t opt) {
-		u8g2_DrawEllipse(&m_u8g2, x0, y0, rx, ry, opt);
-	}
-
-	void drawFilledEllipse(uint32_t x0, uint32_t y0, uint32_t rx, uint32_t ry, uint8_t opt) {
-		u8g2_DrawFilledEllipse(&m_u8g2, x0, y0, rx, ry, opt);
-	}
-
-	void drawFrame(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
-		u8g2_DrawFrame(&m_u8g2, x, y, w, h);
-	}
-
-	void drawGlyph(uint32_t x, uint32_t y, uint16_t encoding) {
-		u8g2_DrawGlyph(&m_u8g2, x, y, encoding);
-	}
-
-	void drawHLine(uint32_t x, uint32_t y, uint32_t w) {
-		u8g2_DrawHLine(&m_u8g2, x, y, w);
-	}
-	void drawLine(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1) {
-		u8g2_DrawLine(&m_u8g2, x0, y0, x1, y1);
-	}
-
-	void drawPixel(uint32_t x, uint32_t y) {
-		u8g2_DrawPixel(&m_u8g2, x, y);
-	}
-
-	void drawRBox(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t r)	{
-		u8g2_DrawRBox(&m_u8g2, x, y, w, h, r);
-	}
-
-	void drawRFrame(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t r) {
-		u8g2_DrawRFrame(&m_u8g2, x, y, w, h, r);
-	}
-
-
-	uint32_t drawStr(uint32_t x, uint32_t y, std::string s) {
-		return u8g2_DrawStr(&m_u8g2, x, y, s.c_str());
-	}
-
-	void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
-		u8g2_DrawTriangle(&m_u8g2, x0, y0, x1, y1, x2, y2);
-	}
-
-	u8g2_uint_t drawUTF8(uint32_t x, uint32_t y, std::string s) {
-		return u8g2_DrawUTF8(&m_u8g2, x, y, s.c_str());
-	}
-
-	void drawVLine(uint32_t x, uint32_t y, uint32_t h) {
-		u8g2_DrawVLine(&m_u8g2, x, y, h);
-	}
-
-	int8_t getAscent(void) {
-		return u8g2_GetAscent(&m_u8g2);
-	}
-
-	int8_t getDescent(void) {
-		return u8g2_GetDescent(&m_u8g2);
-	}
-
-	uint32_t getStrWidth(std::string s) {
-		return u8g2_GetStrWidth(&m_u8g2, s.c_str());
-	}
-
-	void initDisplay() {
-		u8g2_InitDisplay(&m_u8g2);
-	}
-	void sendBuffer() {
-		u8g2_SendBuffer(&m_u8g2);
-	}
-
-	void setFont(const uint8_t *font) {
-		u8g2_SetFont(&m_u8g2, font);
-	}
-	void setPowerSave(uint8_t is_enable) {
-		u8g2_SetPowerSave(&m_u8g2, is_enable); // wake up display
-	}
-
-private:
-	u8g2_t m_u8g2;
-};
-#endif // CONFIG_U8G2_PRESENT
-#endif /* COMPONENTS_CPP_UTILS_U8G2_H_ */
diff --git a/components/cpp_utils/WS2812.cpp b/components/cpp_utils/WS2812.cpp
deleted file mode 100644
index 64f3c82..0000000
--- a/components/cpp_utils/WS2812.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-#include <esp_log.h>
-#include <driver/rmt.h>
-#include <driver/gpio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdexcept>
-
-#include "GPIO.h"
-#include "sdkconfig.h"
-#include "WS2812.h"
-
-static char tag[] = "WS2812";
-
-/**
- * A NeoPixel is defined by 3 bytes ... red, green and blue.
- * Each byte is composed of 8 bits ... therefore a NeoPixel is 24 bits of data.
- * At the underlying level, 1 bit of NeoPixel data is one item (two levels)
- * This means that the number of items we need is:
- *
- * #pixels * 24
- *
- */
-
-/**
- * Set two levels of RMT output to the Neopixel value for a "1".
- * This is:
- * a logic 1 for 0.7us
- * a logic 0 for 0.6us
- */
-static void setItem1(rmt_item32_t *pItem) {
-	assert(pItem != nullptr);
-	pItem->level0    = 1;
-	pItem->duration0 = 10;
-	pItem->level1    = 0;
-	pItem->duration1 = 6;
-} // setItem1
-
-
-
-/**
- * Set two levels of RMT output to the Neopixel value for a "0".
- * This is:
- * a logic 1 for 0.35us
- * a logic 0 for 0.8us
- */
-static void setItem0(rmt_item32_t *pItem) {
-	assert(pItem != nullptr);
-	pItem->level0    = 1;
-	pItem->duration0 = 4;
-	pItem->level1    = 0;
-	pItem->duration1 = 8;
-} // setItem0
-
-
-/**
- * Add an RMT terminator into the RMT data.
- */
-static void setTerminator(rmt_item32_t *pItem) {
-	assert(pItem != nullptr);
-	pItem->level0    = 0;
-	pItem->duration0 = 0;
-	pItem->level1    = 0;
-	pItem->duration1 = 0;
-} // setTerminator
-
-/*
- * Internal function not exposed.  Get the pixel channel color from the channel
- * type which should be one of 'R', 'G' or 'B'.
- */
-static uint8_t getChannelValueByType(char type, pixel_t pixel) {
-	switch(type) {
-		case 'r':
-		case 'R':
-			return pixel.red;
-		case 'b':
-		case 'B':
-			return pixel.blue;
-		case 'g':
-		case 'G':
-			return pixel.green;
-	}
-	ESP_LOGW(tag, "Unknown color channel 0x%2x", type);
-	return 0;
-} // getChannelValueByType
-
-
-
-/**
- * @brief Construct a wrapper for the pixels.
- *
- * In order to drive the NeoPixels we need to supply some basic information.  This
- * includes the GPIO pin that is connected to the data-in (DIN) of the devices.
- * Since we also want to be able to drive a string of pixels, we need to tell the class
- * how many pixels are present in the string.
- *
-
- * @param [in] dinPin The GPIO pin used to drive the data.
- * @param [in] pixelCount The number of pixels in the strand.
- * @param [in] channel The RMT channel to use.  Defaults to RMT_CHANNEL_0.
- */
-WS2812::WS2812(gpio_num_t dinPin, uint16_t pixelCount, int channel) {
-	/*
-	if (pixelCount == 0) {
-		throw std::range_error("Pixel count was 0");
-	}
-	*/
-	assert(ESP32CPP::GPIO::inRange(dinPin));
-
-	this->pixelCount = pixelCount;
-	this->channel    = (rmt_channel_t)channel;
-
-	// The number of items is number of pixels * 24 bits per pixel + the terminator.
-	// Remember that an item is TWO RMT output bits ... for NeoPixels this is correct because
-	// on Neopixel bit is TWO bits of output ... the high value and the low value
-
-	this->items      = new rmt_item32_t[pixelCount * 24 + 1];
-	this->pixels     = new pixel_t[pixelCount];
-	this->colorOrder = (char *)"GRB";
-	clear();
-
-	rmt_config_t config;
-	config.rmt_mode                  = RMT_MODE_TX;
-	config.channel                   = this->channel;
-	config.gpio_num                  = dinPin;
-	config.mem_block_num             = 8-this->channel;
-	config.clk_div                   = 8;
-	config.tx_config.loop_en         = 0;
-	config.tx_config.carrier_en      = 0;
-	config.tx_config.idle_output_en  = 1;
-	config.tx_config.idle_level      = (rmt_idle_level_t)0;
-	config.tx_config.carrier_freq_hz = 10000;
-	config.tx_config.carrier_level   = (rmt_carrier_level_t)1;
-	config.tx_config.carrier_duty_percent = 50;
-
-
-	ESP_ERROR_CHECK(rmt_config(&config));
-	ESP_ERROR_CHECK(rmt_driver_install(this->channel, 0, 0));
-} // WS2812
-
-
-/**
- * @brief Show the current Neopixel data.
- *
- * Drive the LEDs with the values that were previously set.
- */
-void WS2812::show() {
-	auto pCurrentItem = this->items;
-
-	for (auto i=0; i<this->pixelCount; i++) {
-		uint32_t currentPixel =
-				(getChannelValueByType(this->colorOrder[0], this->pixels[i]) << 16) |
-				(getChannelValueByType(this->colorOrder[1], this->pixels[i]) << 8)  |
-				(getChannelValueByType(this->colorOrder[2], this->pixels[i]));
-
-		ESP_LOGD(tag, "Pixel value: %x", currentPixel);
-		for (int j=23; j>=0; j--) {
-			// We have 24 bits of data representing the red, green amd blue channels. The value of the
-			// 24 bits to output is in the variable current_pixel.  We now need to stream this value
-			// through RMT in most significant bit first.  To do this, we iterate through each of the 24
-			// bits from MSB to LSB.
-			if (currentPixel & (1<<j)) {
-				setItem1(pCurrentItem);
-			} else {
-				setItem0(pCurrentItem);
-			}
-			pCurrentItem++;
-		}
-	}
-	setTerminator(pCurrentItem); // Write the RMT terminator.
-
-	// Show the pixels.
-	ESP_ERROR_CHECK(rmt_write_items(this->channel, this->items, this->pixelCount*24, 1 /* wait till done */));
-} // show
-
-
-/**
- * @brief Set the color order of data sent to the LEDs.
- *
- * Data is sent to the WS2812s in a serial fashion.  There are 8 bits of data for each of the three
- * channel colors (red, green and blue).  The WS2812 LEDs typically expect the data to arrive in the
- * order of "green" then "red" then "blue".  However, this has been found to vary between some
- * models and manufacturers.  What this means is that some want "red", "green", "blue" and still others
- * have their own orders.  This function can be called to override the default ordering of "GRB".
- * We can specify
- * an alternate order by supply an alternate three character string made up of 'R', 'G' and 'B'
- * for example "RGB".
- */
-void WS2812::setColorOrder(char *colorOrder) {
-	if (colorOrder != nullptr && strlen(colorOrder) == 3) {
-		this->colorOrder = colorOrder;
-	}
-} // setColorOrder
-
-
-/**
- * @brief Set the given pixel to the specified color.
- *
- * The LEDs are not actually updated until a call to show().
- *
- * @param [in] index The pixel that is to have its color set.
- * @param [in] red The amount of red in the pixel.
- * @param [in] green The amount of green in the pixel.
- * @param [in] blue The amount of blue in the pixel.
- */
-void WS2812::setPixel(uint16_t index, uint8_t red, uint8_t green,	uint8_t blue) {
-	assert(index < pixelCount);
-
-	this->pixels[index].red   = red;
-	this->pixels[index].green = green;
-	this->pixels[index].blue  = blue;
-} // setPixel
-
-/**
- * @brief Set the given pixel to the specified color.
- *
- * The LEDs are not actually updated until a call to show().
- *
- * @param [in] index The pixel that is to have its color set.
- * @param [in] pixel The color value of the pixel.
- */
-void WS2812::setPixel(uint16_t index, pixel_t pixel) {
-	assert(index < pixelCount);
-	this->pixels[index] = pixel;
-} // setPixel
-
-
-/**
- * @brief Set the given pixel to the specified color.
- *
- * The LEDs are not actually updated until a call to show().
- *
- * @param [in] index The pixel that is to have its color set.
- * @param [in] pixel The color value of the pixel.
- */
-void WS2812::setPixel(uint16_t index, uint32_t pixel) {
-	assert(index < pixelCount);
-
-	this->pixels[index].red   = pixel & 0xff;
-	this->pixels[index].green = (pixel & 0xff00) >> 8;
-	this->pixels[index].blue  = (pixel & 0xff0000) >> 16;
-} // setPixel
-
-/**
- * @brief Set the given pixel to the specified HSB color.
- *
- * The LEDs are not actually updated until a call to show().
- *
- * @param [in] index The pixel that is to have its color set.
- * @param [in] hue The amount of hue in the pixel (0-360).
- * @param [in] saturation The amount of saturation in the pixel (0-255).
- * @param [in] brightness The amount of brightness in the pixel (0-255).
- */
-void WS2812::setHSBPixel(uint16_t index, uint16_t hue, uint8_t saturation,	uint8_t brightness) {
-    double sat_red;
-    double sat_green;
-    double sat_blue;
-    double ctmp_red;
-    double ctmp_green;
-    double ctmp_blue;
-    double new_red;
-    double new_green;
-    double new_blue;
-    double dSaturation=(double)saturation/255;
-    double dBrightness=(double)brightness/255;
-
-    assert(index < pixelCount);
-
-    if (hue < 120) {
-        sat_red = (120 - hue) / 60.0;
-        sat_green = hue / 60.0;
-        sat_blue = 0;
-    } else if (hue < 240) {
-        sat_red = 0;
-        sat_green = (240 - hue) / 60.0;
-        sat_blue = (hue - 120) / 60.0;
-    } else {
-        sat_red = (hue - 240) / 60.0;
-        sat_green = 0;
-        sat_blue = (360 - hue) / 60.0;
-    }
-
-    if (sat_red>1.0) {
-    	sat_red=1.0;
-    }
-    if (sat_green>1.0) {
-    	sat_green=1.0;
-    }
-    if (sat_blue>1.0) {
-    	sat_blue=1.0;
-    }
-
-    ctmp_red = 2 * dSaturation * sat_red + (1 - dSaturation);
-    ctmp_green = 2 * dSaturation * sat_green + (1 - dSaturation);
-    ctmp_blue = 2 * dSaturation * sat_blue + (1 - dSaturation);
-
-    if (dBrightness < 0.5) {
-    	new_red = dBrightness * ctmp_red;
-    	new_green = dBrightness * ctmp_green;
-    	new_blue = dBrightness * ctmp_blue;
-    } else {
-    	new_red = (1 - dBrightness) * ctmp_red + 2 * dBrightness - 1;
-    	new_green = (1 - dBrightness) * ctmp_green + 2 * dBrightness - 1;
-    	new_blue = (1 - dBrightness) * ctmp_blue + 2 * dBrightness - 1;
-    }
-
-    this->pixels[index].red   = (uint8_t)(new_red*255);
-    this->pixels[index].green = (uint8_t)(new_green*255);
-    this->pixels[index].blue  = (uint8_t)(new_blue*255);
-} // setHSBPixel
-
-/**
- * @brief Clear all the pixel colors.
- *
- * This sets all the pixels to off which is no brightness for all of the color channels.
- * The LEDs are not actually updated until a call to show().
- */
-void WS2812::clear() {
-	for (auto i=0; i<this->pixelCount; i++) {
-		this->pixels[i].red   = 0;
-		this->pixels[i].green = 0;
-		this->pixels[i].blue  = 0;
-	}
-} // clear
-
-/**
- * @brief Class instance destructor.
- */
-WS2812::~WS2812() {
-	delete this->items;
-	delete this->pixels;
-} // ~WS2812()
diff --git a/components/cpp_utils/WS2812.h b/components/cpp_utils/WS2812.h
deleted file mode 100644
index f599c1b..0000000
--- a/components/cpp_utils/WS2812.h
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-#ifndef MAIN_WS2812_H_
-#define MAIN_WS2812_H_
-#include <stdint.h>
-#include <driver/rmt.h>
-#include <driver/gpio.h>
-
-/**
- * @brief A data type representing the color of a pixel.
- */
-typedef struct {
-	/**
-	 * @brief The red component of the pixel.
-	 */
-	uint8_t red;
-	/**
-	 * @brief The green component of the pixel.
-	 */
-	uint8_t green;
-	/**
-	 * @brief The blue component of the pixel.
-	 */
-	uint8_t blue;
-} pixel_t;
-
-
-/**
- * @brief Driver for WS2812/NeoPixel data.
- *
- * NeoPixels or WS2812s are LED devices that can illuminate in arbitrary colors with
- * 8 bits of data for each of the red, green and blue channels.  These devices can be
- * daisy chained together to produce a string of LEDs.  If we call each LED instance
- * a pixel, then when we want to set the value of a string of pixels, we need to supply
- * the data for all the pixels.  This class encapsulates setting the color value for
- * an individual pixel within the string and, once you have set up all the desired colors,
- * you can then set all the pixels in a show() operation.  The class hides from you
- * the underlying details needed to drive the devices.
- *
- * @code{.cpp}
- * WS2812 ws2812 = WS2812(
- *   16, // Pin
- *   8   // Pixel count
- * );
- * ws2812.setPixel(0, 128, 0, 0);
- * ws2812.show();
- * @endcode
- */
-class WS2812 {
-public:
-	WS2812(gpio_num_t gpioNum, uint16_t pixelCount, int channel=RMT_CHANNEL_0);
-	void show();
-	void setColorOrder(char *order);
-	void setPixel(uint16_t index, uint8_t red, uint8_t green, uint8_t blue);
-	void setPixel(uint16_t index, pixel_t pixel);
-	void setPixel(uint16_t index, uint32_t pixel);
-	void setHSBPixel(uint16_t index, uint16_t hue, uint8_t saturation, uint8_t brightness);
-	void clear();
-	virtual ~WS2812();
-private:
-	char          *colorOrder;
-	uint16_t       pixelCount;
-	rmt_channel_t  channel;
-	rmt_item32_t  *items;
-	pixel_t       *pixels;
-};
-
-#endif /* MAIN_WS2812_H_ */
diff --git a/components/cpp_utils/WebServer.cpp b/components/cpp_utils/WebServer.cpp
deleted file mode 100644
index 9a2696e..0000000
--- a/components/cpp_utils/WebServer.cpp
+++ /dev/null
@@ -1,847 +0,0 @@
-/*
- * WebServer.cpp
- *
- *  Created on: May 19, 2017
- *      Author: kolban
- */
-#include <sstream>
-#include <iostream>
-#include <vector>
-#include <map>
-#include <regex>
-#include "sdkconfig.h"
-#ifdef CONFIG_MONGOOSE_PRESENT
-#define MG_ENABLE_HTTP_STREAMING_MULTIPART 1
-#define MG_ENABLE_FILESYSTEM 1
-#include "WebServer.h"
-#include <esp_log.h>
-#include <mongoose.h>
-#include <string>
-
-
-static char tag[] = "WebServer";
-
-struct WebServerUserData {
-	WebServer *pWebServer;
-	WebServer::HTTPMultiPart *pMultiPart;
-	WebServer::WebSocketHandler *pWebSocketHandler;
-	void *originalUserData;
-};
-
-/**
- * @brief Convert a Mongoose event type to a string.
- * @param [in] event The received event type.
- * @return The string representation of the event.
- */
-static std::string mongoose_eventToString(int event) {
-	switch (event) {
-	case MG_EV_CONNECT:
-		return "MG_EV_CONNECT";
-	case MG_EV_ACCEPT:
-		return "MG_EV_ACCEPT";
-	case MG_EV_CLOSE:
-		return "MG_EV_CLOSE";
-	case MG_EV_SEND:
-		return "MG_EV_SEND";
-	case MG_EV_RECV:
-		return "MG_EV_RECV";
-	case MG_EV_POLL:
-		return "MG_EV_POLL";
-	case MG_EV_TIMER:
-		return "MG_EV_TIMER";
-	case MG_EV_HTTP_PART_DATA:
-		return "MG_EV_HTTP_PART_DATA";
-	case MG_EV_HTTP_MULTIPART_REQUEST:
-		return "MG_EV_HTTP_MULTIPART_REQUEST";
-	case MG_EV_HTTP_PART_BEGIN:
-		return "MG_EV_HTTP_PART_BEGIN";
-	case MG_EV_HTTP_PART_END:
-		return "MG_EV_HTTP_PART_END";
-	case MG_EV_HTTP_MULTIPART_REQUEST_END:
-		return "MG_EV_HTTP_MULTIPART_REQUEST_END";
-	case MG_EV_HTTP_REQUEST:
-		return "MG_EV_HTTP_REQUEST";
-	case MG_EV_HTTP_REPLY:
-		return "MG_EV_HTTP_REPLY";
-	case MG_EV_HTTP_CHUNK:
-		return "MG_EV_HTTP_CHUNK";
-	case MG_EV_MQTT_CONNACK:
-		return "MG_EV_MQTT_CONNACK";
-	case MG_EV_MQTT_CONNECT:
-		return "MG_EV_MQTT_CONNECT";
-	case MG_EV_MQTT_DISCONNECT:
-		return "MG_EV_MQTT_DISCONNECT";
-	case MG_EV_MQTT_PINGREQ:
-		return "MG_EV_MQTT_PINGREQ";
-	case MG_EV_MQTT_PINGRESP:
-		return "MG_EV_MQTT_PINGRESP";
-	case MG_EV_MQTT_PUBACK:
-		return "MG_EV_MQTT_PUBACK";
-	case MG_EV_MQTT_PUBCOMP:
-		return "MG_EV_MQTT_PUBCOMP";
-	case MG_EV_MQTT_PUBLISH:
-		return "MG_EV_MQTT_PUBLISH";
-	case MG_EV_MQTT_PUBREC:
-		return "MG_EV_MQTT_PUBREC";
-	case MG_EV_MQTT_PUBREL:
-		return "MG_EV_MQTT_PUBREL";
-	case MG_EV_MQTT_SUBACK:
-		return "MG_EV_MQTT_SUBACK";
-	case MG_EV_MQTT_SUBSCRIBE:
-		return "MG_EV_MQTT_SUBSCRIBE";
-	case MG_EV_MQTT_UNSUBACK:
-		return "MG_EV_MQTT_UNSUBACK";
-	case MG_EV_MQTT_UNSUBSCRIBE:
-		return "MG_EV_MQTT_UNSUBSCRIBE";
-	case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST:
-		return "MG_EV_WEBSOCKET_HANDSHAKE_REQUEST";
-	case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
-		return "MG_EV_WEBSOCKET_HANDSHAKE_DONE";
-	case MG_EV_WEBSOCKET_FRAME:
-		return "MG_EV_WEBSOCKET_FRAME";
-	case MG_EV_WEBSOCKET_CONTROL_FRAME:
-		return "MG_EV_WEBSOCKET_CONTROL_FRAME";
-	}
-	std::ostringstream s;
-	s << "Unknown event: " << event;
-	return s.str();
-} //eventToString
-
-/**
- * @brief Convert a Mongoose string type to a string.
- * @param [in] mgStr The Mongoose string.
- * @return A std::string representation of the Mongoose string.
- */
-static std::string mgStrToString(struct mg_str mgStr) {
-	return std::string(mgStr.p, mgStr.len);
-} // mgStrToStr
-
-static void dumpHttpMessage(struct http_message *pHttpMessage) {
-	ESP_LOGD(tag, "HTTP Message");
-	ESP_LOGD(tag, "Message: %s", mgStrToString(pHttpMessage->message).c_str());
-	ESP_LOGD(tag, "URI: %s", mgStrToString(pHttpMessage->uri).c_str());
-}
-
-/*
-static struct mg_str uploadFileNameHandler(struct mg_connection *mgConnection, struct mg_str fname) {
-	ESP_LOGD(tag, "uploadFileNameHandler: %s", mgStrToString(fname).c_str());
-	return fname;
-}
-*/
-
-/**
- * @brief Mongoose event handler.
- * The event handler is called when an event occurs associated with the WebServer
- * listening network connection.
- *
- * @param [in] mgConnection The network connection associated with the event.
- * @param [in] event The type of event.
- * @param [in] eventData Data associated with the event.
- * @return N/A.
- */
-static void mongoose_event_handler_web_server(
-	struct mg_connection *mgConnection, // The network connection associated with the event.
-	int event, // The type of event.
-	void *eventData // Data associated with the event.
-) {
-	if (event == MG_EV_POLL) {
-		return;
-	}
-	ESP_LOGD(tag, "Event: %s [%d]", mongoose_eventToString(event).c_str(), mgConnection->sock);
-	switch (event) {
-		case MG_EV_HTTP_REQUEST: {
-			struct http_message *message = (struct http_message *) eventData;
-			dumpHttpMessage(message);
-
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			WebServer *pWebServer = pWebServerUserData->pWebServer;
-			pWebServer->processRequest(mgConnection, message);
-			break;
-		} // MG_EV_HTTP_REQUEST
-
-		case MG_EV_HTTP_MULTIPART_REQUEST: {
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			ESP_LOGD(tag, "User_data address 0x%d", (uint32_t)pWebServerUserData);
-			WebServer *pWebServer = pWebServerUserData->pWebServer;
-			if (pWebServer->m_pMultiPartFactory == nullptr) {
-				return;
-			}
-			WebServer::HTTPMultiPart *pMultiPart = pWebServer->m_pMultiPartFactory->newInstance();
-			struct WebServerUserData *p2 = new WebServerUserData();
-			ESP_LOGD(tag, "New User_data address 0x%d", (uint32_t)p2);
-			p2->originalUserData    = pWebServerUserData;
-			p2->pWebServer          = pWebServerUserData->pWebServer;
-			p2->pMultiPart          = pMultiPart;
-			p2->pWebSocketHandler   = nullptr;
-			mgConnection->user_data = p2;
-			//struct http_message *message = (struct http_message *) eventData;
-			//dumpHttpMessage(message);
-			break;
-		} // MG_EV_HTTP_MULTIPART_REQUEST
-
-		case MG_EV_HTTP_MULTIPART_REQUEST_END: {
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			if (pWebServerUserData->pMultiPart != nullptr) {
-				delete pWebServerUserData->pMultiPart;
-				pWebServerUserData->pMultiPart = nullptr;
-			}
-			mgConnection->user_data = pWebServerUserData->originalUserData;
-			delete pWebServerUserData;
-			WebServer::HTTPResponse httpResponse = WebServer::HTTPResponse(mgConnection);
-			httpResponse.setStatus(200);
-			httpResponse.sendData("");
-			break;
-		} // MG_EV_HTTP_MULTIPART_REQUEST_END
-
-		case MG_EV_HTTP_PART_BEGIN: {
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			struct mg_http_multipart_part *part = (struct mg_http_multipart_part *)eventData;
-			ESP_LOGD(tag, "file_name: \"%s\", var_name: \"%s\", status: %d, user_data: 0x%d",
-					part->file_name, part->var_name, part->status, (uint32_t)part->user_data);
-			if (pWebServerUserData->pMultiPart != nullptr) {
-				pWebServerUserData->pMultiPart->begin(std::string(part->var_name), std::string(part->file_name));
-			}
-			break;
-		} // MG_EV_HTTP_PART_BEGIN
-
-		case MG_EV_HTTP_PART_DATA: {
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			struct mg_http_multipart_part *part = (struct mg_http_multipart_part *)eventData;
-			ESP_LOGD(tag, "file_name: \"%s\", var_name: \"%s\", status: %d, user_data: 0x%d",
-					part->file_name, part->var_name, part->status, (uint32_t)part->user_data);
-			if (pWebServerUserData->pMultiPart != nullptr) {
-				pWebServerUserData->pMultiPart->data(mgStrToString(part->data));
-			}
-			break;
-		} // MG_EV_HTTP_PART_DATA
-
-		case MG_EV_HTTP_PART_END: {
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			struct mg_http_multipart_part *part = (struct mg_http_multipart_part *)eventData;
-			ESP_LOGD(tag, "file_name: \"%s\", var_name: \"%s\", status: %d, user_data: 0x%d",
-					part->file_name, part->var_name, part->status, (uint32_t)part->user_data);
-			if (pWebServerUserData->pMultiPart != nullptr) {
-				pWebServerUserData->pMultiPart->end();
-			}
-			break;
-		} // MG_EV_HTTP_PART_END
-
-		case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: {
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			WebServer *pWebServer = pWebServerUserData->pWebServer;
-			if (pWebServer->m_pWebSocketHandlerFactory != nullptr) {
-				if (pWebServerUserData->pWebSocketHandler != nullptr) {
-					ESP_LOGD(tag, "Warning: MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: pWebSocketHandler was NOT null");
-				}
-				struct WebServerUserData *p2 = new WebServerUserData();
-				ESP_LOGD(tag, "New User_data address 0x%d", (uint32_t)p2);
-				p2->originalUserData    = pWebServerUserData;
-				p2->pWebServer          = pWebServerUserData->pWebServer;
-				p2->pWebSocketHandler = pWebServer->m_pWebSocketHandlerFactory->newInstance();
-				mgConnection->user_data = p2;
-			} else {
-				ESP_LOGD(tag, "We received a WebSocket request but we have no handler factory!");
-			}
-			break;
-		} // MG_EV_WEBSOCKET_HANDSHAKE_REQUEST
-
-		case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			if (pWebServerUserData->pWebSocketHandler == nullptr) {
-				ESP_LOGE(tag, "Error: MG_EV_WEBSOCKET_FRAME: pWebSocketHandler is null");
-				return;
-			}
-			pWebServerUserData->pWebSocketHandler->onCreated();
-			break;
-		} // MG_EV_WEBSOCKET_HANDSHAKE_DONE
-
-
-		/*
-		 * When we receive a MG_EV_WEBSOCKET_FRAME then we have received a chunk of data over the network.
-		 * Our goal will be to send this to the web socket handler (if one exists).
-		 */
-		case MG_EV_WEBSOCKET_FRAME: {
-			struct WebServerUserData *pWebServerUserData = (struct WebServerUserData *)mgConnection->user_data;
-			if (pWebServerUserData->pWebSocketHandler == nullptr) {
-				ESP_LOGE(tag, "Error: MG_EV_WEBSOCKET_FRAME: pWebSocketHandler is null");
-				return;
-			}
-			struct websocket_message *ws_message = (websocket_message *)eventData;
-			ESP_LOGD(tag, "Received data length: %d", ws_message->size);
-			pWebServerUserData->pWebSocketHandler->onMessage(std::string((char *)ws_message->data, ws_message->size));
-			break;
-		} // MG_EV_WEBSOCKET_FRAME
-
-	} // End of switch
-} // End of mongoose_event_handler
-
-
-/**
- * @brief Constructor.
- */
-WebServer::WebServer() {
-	m_rootPath                 = "";
-	m_pMultiPartFactory        = nullptr;
-	m_pWebSocketHandlerFactory = nullptr;
-} // WebServer
-
-
-WebServer::~WebServer() {
-}
-
-
-/**
- * @brief Get the current root path.
- * @return The current root path.
- */
-std::string WebServer::getRootPath() {
-	return m_rootPath;
-} // getRootPath
-
-
-/**
- * @brief Register a handler for a path.
- *
- * When a browser request arrives, the request will contain a method (GET, POST, etc) and a path
- * to be accessed.  Using this method we can register a regular expression and, if the incoming method
- * and path match the expression, the corresponding handler will be called.
- *
- * Example:
- * @code{.cpp}
- * static void handle_REST_WiFi(WebServer::HTTPRequest *pRequest, WebServer::HTTPResponse *pResponse) {
- *    ...
- * }
- *
- * webServer.addPathHandler("GET", "\\/ESP32\\/WiFi", handle_REST_WiFi);
- * @endcode
- *
- * @param [in] method The method being used for access ("GET", "POST" etc).
- * @param [in] pathExpr The path being accessed.
- * @param [in] handler The callback function to be invoked when a request arrives.
- */
-void WebServer::addPathHandler(std::string method, std::string pathExpr, void (*handler)(WebServer::HTTPRequest *pHttpRequest, WebServer::HTTPResponse *pHttpResponse)) {
-	m_pathHandlers.push_back(PathHandler(method, pathExpr, handler));
-} // addPathHandler
-
-
-/**
- * @brief Run the web server listening at the given port.
- *
- * This function does not return.
- *
- * @param [in] port The port number of which to listen.
- * @return N/A.
- */
-void WebServer::start(uint16_t port) {
-	ESP_LOGD(tag, "WebServer task starting");
-	struct mg_mgr mgr;
-	mg_mgr_init(&mgr, NULL);
-
-	std::stringstream stringStream;
-	stringStream << ':' << port;
-	struct mg_connection *mgConnection = mg_bind(&mgr, stringStream.str().c_str(), mongoose_event_handler_web_server);
-
-	if (mgConnection == NULL) {
-		ESP_LOGE(tag, "No connection from the mg_bind()");
-		vTaskDelete(NULL);
-		return;
-	}
-
-	struct WebServerUserData *pWebServerUserData = new WebServerUserData();
-	pWebServerUserData->pWebServer = this;
-	pWebServerUserData->pMultiPart = nullptr;
-	mgConnection->user_data        = pWebServerUserData; // Save the WebServer instance reference in user_data.
-	ESP_LOGD(tag, "start: User_data address 0x%d", (uint32_t)pWebServerUserData);
-	mg_set_protocol_http_websocket(mgConnection);
-
-	ESP_LOGD(tag, "WebServer listening on port %d", port);
-	while (1) {
-		mg_mgr_poll(&mgr, 2000);
-	}
-} // run
-
-
-/**
- * @brief Set the multi part factory.
- * @param [in] pMultiPart A pointer to the multi part factory.
- */
-void WebServer::setMultiPartFactory(HTTPMultiPartFactory *pMultiPartFactory) {
-	m_pMultiPartFactory = pMultiPartFactory;
-}
-
-
-/**
- * @brief Set the root path for URL file mapping.
- *
- * When a browser requests a file, it uses the address form:
- *
- * @code{.unparsed}
- * http://<host>:<port>/<path>
- * @endcode
- *
- * The path part can be considered the path to where the file should be retrieved on the
- * file system available to the web server.  Typically, we want a directory structure on the file
- * system to host the web served files and not expose the whole file system.  Using this method
- * we specify the root directory from which the files will be served.
- *
- * @param [in] path The root path on the file system.
- * @return N/A.
- */
-void WebServer::setRootPath(std::string path) {
-	m_rootPath = path;
-} // setRootPath
-
-
-/**
- * @brief Register the factory for creating web socket handlers.
- *
- * @param [in] pWebSocketHandlerFactory The instance that will create WebSocketHandlers.
- * @return N/A.
- */
-void WebServer::setWebSocketHandlerFactory(WebSocketHandlerFactory* pWebSocketHandlerFactory) {
-	m_pWebSocketHandlerFactory = pWebSocketHandlerFactory;
-} // setWebSocketHandlerFactory
-
-
-/**
- * @brief Constructor.
- * @param [in] nc The network connection for the response.
- */
-WebServer::HTTPResponse::HTTPResponse(struct mg_connection* nc) {
-	m_nc = nc;
-	m_status = 200;
-	m_dataSent = false;
-} // HTTPResponse
-
-
-/**
- * @brief Add a header to the response.
- * @param [in] name The name of the header.
- * @param [in] value The value of the header.
- */
-void WebServer::HTTPResponse::addHeader(std::string name, std::string value) {
-	m_headers[name] = value;
-} // addHeader
-
-
-/**
- * @brief Send data to the HTTP caller.
- * Send the data to the HTTP caller.  No further data should be sent after this call.
- * @param [in] data The data to be sent to the HTTP caller.
- * @return N/A.
- */
-void WebServer::HTTPResponse::sendData(std::string data) {
-	sendData((uint8_t *)data.data(), data.length());
-} // sendData
-
-
-/**
- * @brief Send data to the HTTP caller.
- * Send the data to the HTTP caller.  No further data should be sent after this call.
- * @param [in] pData The data to be sent to the HTTP caller.
- * @param [in] length The length of the data to be sent.
- * @return N/A.
- */
-void WebServer::HTTPResponse::sendData(uint8_t *pData, size_t length) {
-	if (m_dataSent) {
-		ESP_LOGE(tag, "HTTPResponse: Data already sent!  Attempt to send again/more.");
-		return;
-	}
-	m_dataSent = true;
-
-	std::map<std::string, std::string>::iterator iter;
-	std::string headers;
-
-	for (iter = m_headers.begin(); iter != m_headers.end(); iter++) {
-		if (headers.length() == 0) {
-			headers = iter->first + ": " + iter->second;
-		} else {
-			headers = "; " + iter->first + "=" + iter->second;
-		}
-	}
-	mg_send_head(m_nc, m_status, length, headers.c_str());
-	mg_send(m_nc, pData, length);
-	m_nc->flags |= MG_F_SEND_AND_CLOSE;
-} // sendData
-
-
-/**
- * @brief Set the headers to be sent in the HTTP response.
- * @param [in] headers The complete set of headers to send to the caller.
- * @return N/A.
- */
-void WebServer::HTTPResponse::setHeaders(std::map<std::string, std::string> headers) {
-	m_headers = headers;
-} // setHeaders
-
-
-/**
- * @brief Get the current root path.
- * @return The current root path.
- */
-std::string WebServer::HTTPResponse::getRootPath() {
-	return m_rootPath;
-} // getRootPath
-
-
-/**
- * @brief Set the root path for URL file mapping.
- * @param [in] path The root path on the file system.
- * @return N/A.
- */
-void WebServer::HTTPResponse::setRootPath(std::string path) {
-	m_rootPath = path;
-} // setRootPath
-
-
-/**
- * @brief Set the status value in the HTTP response.
- *
- * The default if not set is 200.
- * @param [in] status The HTTP status code sent to the caller.
- * @return N/A.
- */
-void WebServer::HTTPResponse::setStatus(int status) {
-	m_status = status;
-} // setStatus
-
-
-/**
- * @brief Process an incoming HTTP request.
- *
- * We look at the path of the request and see if it has a matching path handler.  If it does,
- * we invoke the handler function.  If it does not, we try and find a file on the file system
- * that would resolve to the path.
- *
- * @param [in] mgConnection The network connection on which the request was received.
- * @param [in] message The message representing the request.
- */
-void WebServer::processRequest(struct mg_connection *mgConnection, struct http_message* message) {
-	std::string uri = mgStrToString(message->uri);
-	ESP_LOGD(tag, "WebServer::processRequest: Matching: %s", uri.c_str());
-	HTTPResponse httpResponse = HTTPResponse(mgConnection);
-	httpResponse.setRootPath(getRootPath());
-
-	/*
-	 * Iterate through each of the path handlers looking for a match with the method and specified path.
-	 */
-	std::vector<PathHandler>::iterator it;
-	for (it = m_pathHandlers.begin(); it != m_pathHandlers.end(); ++it) {
-		if ((*it).match(mgStrToString(message->method), uri)) {
-			HTTPRequest httpRequest(message);
-			(*it).invoke(&httpRequest, &httpResponse);
-			ESP_LOGD(tag, "Found a match!!");
-			return;
-		}
-	} // End of examine path handlers.
-
-	// Because we reached here, it means that we did NOT match a handler.  Now we want to attempt
-	// to retrieve the corresponding file content.
-	std::string filePath = httpResponse.getRootPath() + uri;
-	ESP_LOGD(tag, "Opening file: %s", filePath.c_str());
-	FILE *file = fopen(filePath.c_str(), "r");
-	if (file != nullptr) {
-		fseek(file, 0L, SEEK_END);
-		size_t length = ftell(file);
-		fseek(file, 0L, SEEK_SET);
-		uint8_t *pData = (uint8_t *)malloc(length);
-		fread(pData, length, 1, file);
-		fclose(file);
-		httpResponse.sendData(pData, length);
-		free(pData);
-	} else {
-		// Handle unable to open file
-		httpResponse.setStatus(404); // Not found
-		httpResponse.sendData("");
-	}
-} // processRequest
-
-
-/**
- * @brief Construct an instance of a PathHandler.
- *
- * @param [in] method The method to be matched.
- * @param [in] pathPattern The path pattern to be matched.
- * @param [in] webServerRequestHandler The request handler to be called.
- */
-WebServer::PathHandler::PathHandler(std::string method, std::string pathPattern, void (*webServerRequestHandler)(WebServer::HTTPRequest *pHttpRequest, WebServer::HTTPResponse *pHttpResponse)) {
-	m_method         = method;
-	m_pattern        = std::regex(pathPattern);
-	m_requestHandler = webServerRequestHandler;
-} // PathHandler
-
-
-/**
- * @brief Determine if the path matches.
- *
- * @param [in] method The method to be matched.
- * @param [in] path The path to be matched.
- * @return True if the path matches.
- */
-bool WebServer::PathHandler::match(std::string method, std::string path) {
-	//ESP_LOGD(tag, "match: %s with %s", m_pattern.c_str(), path.c_str());
-	if (method != m_method) {
-		return false;
-	}
-	return std::regex_search(path, m_pattern);
-} // match
-
-
-/**
- * @brief Invoke the handler.
- * @param [in] request An object representing the request.
- * @param [in] response An object representing the response.
- * @return N/A.
- */
-void WebServer::PathHandler::invoke(WebServer::HTTPRequest* request, WebServer::HTTPResponse *response) {
-	m_requestHandler(request, response);
-} // invoke
-
-
-/**
- * @brief Create an HTTPRequest instance.
- * When mongoose received an HTTP request, we want to encapsulate that to hide the
- * mongoose complexities.  We create an instance of this class to hide those.
- * @param [in] message The description of the underlying Mongoose message.
- */
-WebServer::HTTPRequest::HTTPRequest(struct http_message* message) {
-	m_message = message;
-} // HTTPRequest
-
-
-/**
- * @brief Get the body of the request.
- * When an HTTP request is either PUT or POST then it may contain a payload that is also
- * known as the body.  This method returns that payload (if it exists).
- * @return The body of the request.
- */
-std::string WebServer::HTTPRequest::getBody() {
-	return mgStrToString(m_message->body);
-} // getBody
-
-
-/**
- * @brief Get the method of the request.
- * An HTTP request contains a request method which is one of GET, PUT, POST, etc.
- * @return The method of the request.
- */
-std::string WebServer::HTTPRequest::getMethod() {
-	return mgStrToString(m_message->method);
-} // getMethod
-
-
-/**
- * @brief Get the path of the request.
- * The path of an HTTP request is the portion of the URL that follows the hostname/port pair
- * but does not include any query parameters.
- * @return The path of the request.
- */
-std::string WebServer::HTTPRequest::getPath() {
-	return mgStrToString(m_message->uri);
-} // getPath
-
-#define STATE_NAME 0
-#define STATE_VALUE 1
-/**
- * @brief Get the query part of the request.
- * The query is a set of name = value pairs.  The return is a map keyed by the name items.
- *
- * @return The query part of the request.
- */
-std::map<std::string, std::string> WebServer::HTTPRequest::getQuery() {
-	// Walk through all the characters in the query string maintaining a simple state machine
-	// that lets us know what we are parsing.
-	std::map<std::string, std::string> queryMap;
-	std::string queryString = mgStrToString(m_message->query_string);
-	int i=0;
-
-	/*
-	 * We maintain a simple state machine with states of:
-	 * * STATE_NAME - We are parsing a name.
-	 * * STATE_VALUE - We are parsing a value.
-	 */
-	int state = STATE_NAME;
-	std::string name = "";
-	std::string value;
-	// Loop through each character in the query string.
-	for (i=0; i<queryString.length(); i++) {
-		char currentChar = queryString[i];
-		if (state == STATE_NAME) {
-			if (currentChar != '=') {
-				name += currentChar;
-			} else {
-				state = STATE_VALUE;
-				value = "";
-			}
-		} // End state = STATE_NAME
-		else if (state == STATE_VALUE) {
-			if (currentChar != '&') {
-				value += currentChar;
-			} else {
-				//ESP_LOGD(tag, "name=%s, value=%s", name.c_str(), value.c_str());
-				queryMap[name] = value;
-				state = STATE_NAME;
-				name = "";
-			}
-		} // End state = STATE_VALUE
-	} // End for loop
-	if (state == STATE_VALUE) {
-		//ESP_LOGD(tag, "name=%s, value=%s", name.c_str(), value.c_str());
-		queryMap[name] = value;
-	}
-	return queryMap;
-} // getQuery
-
-
-/**
- * @brief Return the constituent parts of the path.
- * If we imagine a path as composed of parts separated by slashes, then this function
- * returns a vector composed of the parts.  For example:
- *
- * ```
- * /x/y/z
- * ```
- * will break out to:
- *
- * ```
- * path[0] = ""
- * path[1] = "x"
- * path[2] = "y"
- * path[3] = "z"
- * ```
- *
- * @return A vector of the constituent parts of the path.
- */
-std::vector<std::string> WebServer::HTTPRequest::pathSplit() {
-	std::istringstream stream(getPath());
-	std::vector<std::string> ret;
-	std::string pathPart;
-	while(std::getline(stream, pathPart, '/')) {
-		ret.push_back(pathPart);
-	}
-	// Debug
-	for (int i=0; i<ret.size(); i++) {
-		ESP_LOGD(tag, "part[%d]: %s", i, ret[i].c_str());
-	}
-	return ret;
-} // pathSplit
-
-/**
- * @brief Indicate the beginning of a multipart part.
- * An HTTP Multipart form is where each of the fields in the form are broken out into distinct
- * sections.  We commonly see this with file uploads.
- * @param [in] varName The name of the form variable.
- * @param [in] fileName The name of the file being uploaded (may not be present).
- * @return N/A.
- */
-void WebServer::HTTPMultiPart::begin(std::string varName, std::string fileName) {
-	ESP_LOGD(tag, "WebServer::HTTPMultiPart::begin(varName=\"%s\", fileName=\"%s\")",
-		varName.c_str(), fileName.c_str());
-} // WebServer::HTTPMultiPart::begin
-
-
-/**
- * @brief Indicate the end of a multipart part.
- * This will eventually be called after a corresponding begin().
- * @return N/A.
- */
-void WebServer::HTTPMultiPart::end() {
-	ESP_LOGD(tag, "WebServer::HTTPMultiPart::end()");
-} // WebServer::HTTPMultiPart::end
-
-
-/**
- * @brief Indicate the arrival of data of a multipart part.
- * This will be called after a begin() and it may be called many times.  Each
- * call will result in more data.  The end of the data will be indicated by a call to end().
- * @param [in] data The data received in this callback.
- * @return N/A.
- */
-void WebServer::HTTPMultiPart::data(std::string data) {
-	ESP_LOGD(tag, "WebServer::HTTPMultiPart::data(), length=%d", data.length());
-} // WebServer::HTTPMultiPart::data
-
-
-/**
- * @brief Indicate the end of all the multipart parts.
- * @return N/A.
- */
-void WebServer::HTTPMultiPart::multipartEnd() {
-	ESP_LOGD(tag, "WebServer::HTTPMultiPart::multipartEnd()");
-} // WebServer::HTTPMultiPart::multipartEnd
-
-
-/**
- * @brief Indicate the start of all the multipart parts.
- * @return N/A.
- */
-void WebServer::HTTPMultiPart::multipartStart() {
-	ESP_LOGD(tag, "WebServer::HTTPMultiPart::multipartStart()");
-} // WebServer::HTTPMultiPart::multipartStart
-
-
-/**
- * @brief Indicate that a new WebSocket instance has been created.
- * @return N/A.
- */
-void WebServer::WebSocketHandler::onCreated() {
-
-} // onCreated
-
-
-/**
- * @brief Indicate that a new message has been received.
- * @param [in] message The message received from the client.
- * @return N/A.
- */
-void WebServer::WebSocketHandler::onMessage(std::string message){
-
-} // onMessage
-
-/**
- * @brief Indicate that the client has closed the WebSocket.
- * @return N/A
- */
-void WebServer::WebSocketHandler::onClosed() {
-
-} // onClosed
-
-
-/**
- * @brief Send data down the WebSocket
- * @param [in] message The message to send down the socket.
- * @return N/A.
- */
-void WebServer::WebSocketHandler::sendData(std::string message) {
-	ESP_LOGD(tag, "WebSocketHandler::sendData(length=%d)", message.length());
-	mg_send_websocket_frame(m_mgConnection,
-	   WEBSOCKET_OP_BINARY | WEBSOCKET_OP_CONTINUE,
-	   message.data(), message.length());
-} // sendData
-
-/**
- * @brief Send data down the WebSocket
- * @param [in] data The message to send down the socket.
- * @param [in] size The size of the message
- * @return N/A.
- */
-void WebServer::WebSocketHandler::sendData(uint8_t *data, uint32_t size) {
-	mg_send_websocket_frame(m_mgConnection,
-	   WEBSOCKET_OP_BINARY | WEBSOCKET_OP_CONTINUE,
-	   data, size);
-} // sendData
-
-
-/**
- * @brief Close the WebSocket from the web server end.
- * Previously a client has connected to us and created a WebSocket.  By making this call we are
- * declaring that the socket should be closed from the server end.
- * @return N/A.
- */
-void WebServer::WebSocketHandler::close() {
-	mg_send_websocket_frame(m_mgConnection, WEBSOCKET_OP_CLOSE, nullptr, 0);
-} // close
-
-
-
-#endif // CONFIG_MONGOOSE_PRESENT
diff --git a/components/cpp_utils/WebServer.h b/components/cpp_utils/WebServer.h
deleted file mode 100644
index adbba78..0000000
--- a/components/cpp_utils/WebServer.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * WebServer.h
- *
- *  Created on: May 19, 2017
- *      Author: kolban
- */
-
-#ifndef CPP_UTILS_WEBSERVER_H_
-#define CPP_UTILS_WEBSERVER_H_
-#include <string>
-#include <vector>
-#include <regex>
-#include <map>
-#include "sdkconfig.h"
-#ifdef CONFIG_MONGOOSE_PRESENT
-#include <mongoose.h>
-
-
-
-class WebServer;
-
-/**
- * @brief %WebServer built on Mongoose.
- *
- * A web server.
- */
-class WebServer {
-public:
-	/**
-	 * @brief Request wrapper for an HTTP request.
-	 */
-	class HTTPRequest {
-		public:
-			HTTPRequest(struct http_message* message);
-			std::string getMethod();
-			std::string getPath();
-			std::map<std::string, std::string> getQuery();
-			std::string getBody();
-			std::vector<std::string> pathSplit();
-		private:
-			struct http_message* m_message;
-	}; // HTTPRequest
-
-	/**
-	 * @brief Response wrapper for an HTTP response.
-	 */
-	class HTTPResponse {
-		public:
-			HTTPResponse(struct mg_connection *nc);
-			void addHeader(std::string name, std::string value);
-			std::string getRootPath();
-			void setStatus(int status);
-			void setHeaders(std::map<std::string, std::string>  headers);
-			void sendData(std::string data);
-			void sendData(uint8_t *pData, size_t length);
-			void setRootPath(std::string path);
-		private:
-			struct mg_connection *m_nc;
-			std::string m_rootPath;
-			int m_status;
-			std::map<std::string, std::string> m_headers;
-			bool m_dataSent;
-	}; // HTTPResponse
-
-	/**
-	 * @brief Handler for a Multipart.
-	 *
-	 * This class is usually subclassed to provide your own implementation.  Typically
-	 * a factory is implemented based on HTTPMultiPartFactory that creates instances.  This
-	 * is then registered with the WebServer.  When done, when ever the WebServer receives multi
-	 * part requests, this handler for Multipart is called.  The call sequence is usually:
-	 * ~~~
-	 * multipartStart
-	 * begin
-	 * data*
-	 * end
-	 * begin
-	 * data*
-	 * end
-	 * ...
-	 * multipartEnd
-	 * ~~~
-	 *
-	 * There can be multiple begin, data, data, ..., end groups.
-	 */
-	class HTTPMultiPart {
-	public:
-		virtual ~HTTPMultiPart() {
-		};
-		virtual void begin(std::string varName, std::string fileName);
-		virtual void end();
-		virtual void data(std::string data);
-		virtual void multipartEnd();
-		virtual void multipartStart();
-	}; // HTTPMultiPart
-
-	/**
-	 * @brief Factory for creating Multipart instances.
-	 * This class is meant to be implemented to provide a constructor for a custom
-	 * HTTPMultiPart instance.
-	 * @code{.cpp}
-	 * class MyMultiPart : public WebServer::HTTPMultiPart {
-	 * public:
-	 *   void begin(std::string varName,	std::string fileName) {
-	 *     ESP_LOGD(tag, "MyMultiPart begin(): varName=%s, fileName=%s",
-	 *     varName.c_str(), fileName.c_str());
-	 *   }
-	 *
-	 *   void end() {
-	 *     ESP_LOGD(tag, "MyMultiPart end()");
-	 *   }
-	 *
-	 *   void data(std::string data) {
-	 *     ESP_LOGD(tag, "MyMultiPart data(): length=%d", data.length());
-	 *   }
-	 *
-	 *   void multipartEnd() {
-	 *     ESP_LOGD(tag, "MyMultiPart multipartEnd()");
-	 *   }
-	 *
-	 *   void multipartStart() {
-	 *     ESP_LOGD(tag, "MyMultiPart multipartStart()");
-	 *   }
-	 * };
-	 *
-	 * class MyMultiPartFactory : public WebServer::HTTPMultiPartFactory {
-	 *   WebServer::HTTPMultiPart *createNew() {
-	 *     return new MyMultiPart();
-	 *   }
-	 * };
-	 * @endcode
-	 */
-	class HTTPMultiPartFactory {
-	public:
-		/**
-		 * @brief Create a new HTTPMultiPart instance.
-		 * @return A new HTTPMultiPart instance.
-		 */
-		virtual HTTPMultiPart *newInstance() = 0;
-	};
-
-	/**
-	 * @brief The handler for path matching.
-	 *
-	 */
-	class PathHandler {
-		public:
-			PathHandler(std::string method, std::string pathPattern,  void (*webServerRequestHandler)(WebServer::HTTPRequest *pHttpRequest, WebServer::HTTPResponse *pHttpResponse));
-			bool match(std::string method, std::string path);
-			void invoke(HTTPRequest *request, HTTPResponse *response);
-		private:
-			std::string m_method;
-			std::regex m_pattern;
-			void (*m_requestHandler)(WebServer::HTTPRequest *pHttpRequest, WebServer::HTTPResponse *pHttpResponse);
-	}; // PathHandler
-
-	/**
-	 * @brief A WebSocket handler for handling WebSockets.
-	 */
-	class WebSocketHandler {
-	public:
-		void onCreated();
-		virtual void onMessage(std::string message);
-		void onClosed();
-		void sendData(std::string message);
-		void sendData(uint8_t *data, uint32_t size);
-		void close();
-	private:
-		struct mg_connection *m_mgConnection;
-	};
-
-	class WebSocketHandlerFactory {
-	public:
-		virtual WebSocketHandler *newInstance() = 0;
-	};
-
-	WebServer();
-	virtual ~WebServer();
-	void addPathHandler(std::string method, std::string pathExpr, void (*webServerRequestHandler)(WebServer::HTTPRequest *pHttpRequest, WebServer::HTTPResponse *pHttpResponse) );
-	std::string getRootPath();
-	void setMultiPartFactory(HTTPMultiPartFactory *pMultiPartFactory);
-	void setRootPath(std::string path);
-	void setWebSocketHandlerFactory(WebSocketHandlerFactory *pWebSocketHandlerFactory);
-	void start(unsigned short port = 80);
-	void processRequest(struct mg_connection *mgConnection, struct http_message *message);
-	HTTPMultiPartFactory *m_pMultiPartFactory;
-	WebSocketHandlerFactory *m_pWebSocketHandlerFactory;
-private:
-	std::string m_rootPath;
-	std::vector<PathHandler> m_pathHandlers;
-};
-
-#endif // CONFIG_MONGOOSE_PRESENT
-#endif /* CPP_UTILS_WEBSERVER_H_ */
diff --git a/components/cpp_utils/WebSocket.cpp b/components/cpp_utils/WebSocket.cpp
deleted file mode 100644
index 61192ef..0000000
--- a/components/cpp_utils/WebSocket.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * WebSocket.cpp
- *
- *  Created on: Sep 2, 2017
- *      Author: kolban
- */
-
-#include <sstream>
-#include "WebSocket.h"
-#include "Task.h"
-#include "GeneralUtils.h"
-#include <esp_log.h>
-
-extern "C" {
-	extern uint16_t lwip_ntohs(uint16_t);
-	extern uint32_t lwip_ntohl(uint32_t);
-	extern uint16_t lwip_htons(uint16_t);
-	extern uint32_t lwip_htonl(uint32_t);
-}
-static const char* LOG_TAG = "WebSocket";
-
-// WebSocket op codes as found in a WebSocket frame.
-static const int OPCODE_CONTINUE = 0x00;
-static const int OPCODE_TEXT     = 0x01;
-static const int OPCODE_BINARY   = 0x02;
-static const int OPCODE_CLOSE    = 0x08;
-static const int OPCODE_PING     = 0x09;
-static const int OPCODE_PONG     = 0x0a;
-
-
-// Structure definition for the WebSocket frame.
-struct Frame {
-	// Byte 0
-	uint8_t opCode : 4; // [7:4]
-	uint8_t rsv3   : 1; // [3]
-	uint8_t rsv2   : 1; // [2]
-	uint8_t rsv1   : 1; // [1]
-	uint8_t fin    : 1; // [0]
-
-	// Byte 1
-	uint8_t len    : 7; // [7:1]
-	uint8_t mask   : 1; // [0]
-};
-
-
-/**
- * @brief Dump the content of the WebSocket frame for debugging.
- * @param [in] frame The frame to dump.
- */
-static void dumpFrame(Frame frame) {
-	std::ostringstream oss;
-	oss << "Fin: " << (int)frame.fin << ", OpCode: " << (int)frame.opCode;
-	switch(frame.opCode) {
-		case OPCODE_BINARY: {
-			oss << " BINARY";
-			break;
-		}
-		case OPCODE_CONTINUE: {
-			oss << " CONTINUE";
-			break;
-		}
-		case OPCODE_CLOSE: {
-			oss << " CLOSE";
-			break;
-		}
-		case OPCODE_PING: {
-			oss << " PING";
-			break;
-		}
-		case OPCODE_PONG: {
-			oss << " PONG";
-			break;
-		}
-		case OPCODE_TEXT: {
-			oss << " TEXT";
-			break;
-		}
-		default: {
-			oss << " Unknown";
-			break;
-		}
-	}
-	oss << ", Mask: " << (int)frame.mask << ", len: " << (int)frame.len;
-	ESP_LOGD(LOG_TAG, "WebSocket frame: %s", oss.str().c_str());
-} // dumpFrame
-
-
-/**
- * @brief A task that will watch web socket inputs.
- *
- * When a WebSocket is created it is created by the client requesting an HTTP protocol changed to WebSockets.
- * After the original Socket has been flagged as being a WebSocket, we must now start watching that socket for
- * incoming asynchronous events.  We spawn a task to do this.  This is the implementation of that task.
- */
-class WebSocketReader: public Task {
-public:
-	WebSocketReader() {
-		m_end = false;
-	}
-	void end() {
-		m_end = true;
-	}
-private:
-	bool m_end;
-	/**
-	 * @brief Loop over the web socket waiting for new input.
-	 * @param [in] data A pointer to an instance of the WebSocket.
-	 */
-	void run(void* data) {
-		WebSocket* pWebSocket = (WebSocket*) data;
-		ESP_LOGD("WebSocketReader", "WebSocketReader Task started, socket: %s", pWebSocket->getSocket().toString().c_str());
-
-		Socket peerSocket = pWebSocket->getSocket();
-
-		Frame frame;
-		while(1) {
-			if (m_end) {
-				break;
-			}
-			ESP_LOGD("WebSocketReader", "Waiting on socket data for socket %s", peerSocket.toString().c_str());
-			int length = peerSocket.receive_cpp((uint8_t*)&frame, sizeof(frame), true); // Read exact
-			if (length != sizeof(frame)) {
-				ESP_LOGD(LOG_TAG, "Socket read error");
-				pWebSocket->close_cpp();
-				return;
-			}
-			ESP_LOGD("WebSocketReader", "Received data from web socket.  Length: %d", length);
-			dumpFrame(frame);
-
-			// The following section parses the WebSocket frame.
-			uint32_t payloadLen = 0;
-			uint8_t  mask[4];
-			if (frame.len < 126) {
-				payloadLen = frame.len;
-			} else if (frame.len == 126) {
-				uint16_t tempLen;
-				peerSocket.receive_cpp((uint8_t*)&tempLen, sizeof(tempLen), true);
-				payloadLen = ntohs(tempLen);
-			} else if (frame.len == 127) {
-				uint64_t tempLen;
-				peerSocket.receive_cpp((uint8_t*)&tempLen, sizeof(tempLen), true);
-				payloadLen = ntohl((uint32_t)tempLen);
-			}
-			if (frame.mask == 1) {
-				peerSocket.receive_cpp(mask, sizeof(mask), true);
-			}
-
-			if (payloadLen == 0) {
-				ESP_LOGD("WebSocketReader", "Web socket payload is not present");
-			} else {
-				ESP_LOGD("WebSocketReader", "Web socket payload, length=%d:", payloadLen);
-			}
-
-			WebSocketHandler *pWebSocketHandler = pWebSocket->getHandler();
-			switch(frame.opCode) {
-				case OPCODE_TEXT:
-				case OPCODE_BINARY: {
-					if (pWebSocketHandler != nullptr) {
-						WebSocketInputRecordStreambuf streambuf(pWebSocket->getSocket(), payloadLen, frame.mask==1?mask:nullptr);
-						pWebSocketHandler->onMessage(&streambuf);
-						//streambuf.discard();
-					}
-					break;
-				}
-
-				case OPCODE_CLOSE: {
-					pWebSocket->m_receivedClose = true;
-					if (pWebSocketHandler != nullptr) {
-						pWebSocketHandler->onClose();
-						pWebSocket->close_cpp();
-					}
-					break;
-				}
-
-				case OPCODE_CONTINUE: {
-					break;
-				}
-
-				case OPCODE_PING: {
-					break;
-				}
-
-				case OPCODE_PONG: {
-					break;
-				}
-
-
-				default: {
-						ESP_LOGD("WebSocketReader", "Unknown opcode: %d", frame.opCode);
-					break;
-				}
-			} // Switch opCode
-
-		} // While (1)
-		ESP_LOGD("WebSocketReader", "<< run");
-	} // run
-}; // WebSocketReader
-
-
-/**
- * @brief The default onClose handler.
- * If no over-riding handler is provided for the "close" event, this method is called.
- */
-void WebSocketHandler::onClose() {
-	ESP_LOGD("WebSocketHandler", ">> WebSocketHandler:onClose()");
-} // onClose
-
-
-/**
- * @brief The default onData handler.
- * If no over-riding handler is provided for the "message" event, this method is called.
- * A particularly useful pattern for using onMessage is:
- * ```
- * std::stringstream buffer;
- * buffer << pWebSocketInputRecordStreambuf;
- * ```
- * This will read the whole message into the string stream.
- */
-void WebSocketHandler::onMessage(WebSocketInputRecordStreambuf* pWebSocketInputRecordStreambuf) {
-	ESP_LOGD("WebSocketHandler", ">> onMessage")
-} // onData
-
-
-/**
- * @brief The default onError handler.
- * If no over-riding handler is provided for the "error" event, this method is called.
- */
-void WebSocketHandler::onError(std::string error) {
-	ESP_LOGD("WebSocketHandler", ">> WebSocketHandler:onError()");
-} // onError
-
-
-WebSocket::WebSocket(Socket socket) {
-	m_receivedClose     = false;
-	m_sentClose         = false;
-	m_socket            = socket;
-	m_pWebSockerReader  = new WebSocketReader();
-	m_pWebSocketHandler = nullptr;
-} // WebSocket
-
-
-WebSocket::~WebSocket() {
-	m_pWebSockerReader->stop();
-	delete m_pWebSockerReader;
-} // ~WebSocket
-
-
-/**
- * @brief Close the Web socket
- */
-void WebSocket::close_cpp(uint16_t status, std::string message) {
-	ESP_LOGD(LOG_TAG, ">> close_cpp(): status: %d, message: %s", status, message.c_str());
-	if (m_sentClose) {
-		m_socket.close_cpp();
-		m_pWebSockerReader->end();
-		return;
-	}
-	m_sentClose = true;
-
-	Frame frame;
-	frame.fin    = 1;
-	frame.rsv1   = 0;
-	frame.rsv2   = 0;
-	frame.rsv3   = 0;
-	frame.opCode = OPCODE_CLOSE;
-	frame.mask   = 0;
-	frame.len = message.length() + 2;
-	int rc = m_socket.send_cpp((uint8_t *)&frame, sizeof(frame));
-	if (rc > 0) {
-		rc = m_socket.send_cpp(status);
-	}
-	if (rc > 0) {
-		m_socket.send_cpp(message);
-	}
-	if (m_receivedClose || rc == 0 || rc == -1) {
-		m_socket.close_cpp();
-		m_pWebSockerReader->end();
-	}
-} // close_cpp
-
-
-/**
- * @brief Get the current WebSocketHandler
- * A web socket handler is a user registered class instance that is called when an incoming
- * event received over the network needs to be handled by user code.
- */
-WebSocketHandler* WebSocket::getHandler() {
-	return m_pWebSocketHandler;
-} // getHandler
-
-
-/**
- * @brief Get the underlying socket for the websocket.
- * @return The socket associated with the Web socket.
- */
-Socket WebSocket::getSocket() {
-	return m_socket;
-} // getSocket
-
-
-/**
- * @brief Send data down the web socket
- * See the WebSocket spec (RFC6455) section "6.1 Sending Data".
- * We build a WebSocket frame, send the frame followed by the data.
- * @param [in] data The data to send down the WebSocket.
- * @param [in] sendType The type of payload.  Either SEND_TYPE_TEXT or SEND_TYPE_BINARY.
- */
-void WebSocket::send_cpp(std::string data, uint8_t sendType) {
-	ESP_LOGD(LOG_TAG, ">> send_cpp: Length: %d", data.length());
-	Frame frame;
-	frame.fin    = 1;
-	frame.rsv1   = 0;
-	frame.rsv2   = 0;
-	frame.rsv3   = 0;
-	frame.opCode = sendType==SEND_TYPE_TEXT?OPCODE_TEXT:OPCODE_BINARY;
-	frame.mask   = 0;
-	if (data.length() < 126) {
-		frame.len = data.length();
-		m_socket.send_cpp((uint8_t *)&frame, sizeof(frame));
-	} else {
-		frame.len = 126;
-		m_socket.send_cpp((uint8_t *)&frame, sizeof(frame));
-		m_socket.send_cpp((uint16_t)data.length());
-	}
-	m_socket.send_cpp((uint8_t*)data.data(), data.length());
-	ESP_LOGD(LOG_TAG, "<< send_cpp");
-} // send_cpp
-
-
-/**
- * @brief Set the Web socket handler associated with this Websocket.
- *
- * This will be the user supplied code that will be invoked to process incoming WebSocket
- * events.  An instance of WebSocketHandler is passed in.
- *
- */
-void WebSocket::setHandler(WebSocketHandler *pHandler) {
-	m_pWebSocketHandler = pHandler;
-} // setHandler
-
-
-/**
- * @brief Start the WebSocket reader reading the socket.
- * When we have a new web socket, we want to start watching for new incoming events.  This
- * function starts that activity.  We want to have control over when we start watching.
- */
-void WebSocket::startReader() {
-	ESP_LOGD(LOG_TAG, ">> startReader: Socket: %s", m_socket.toString().c_str());
-	m_pWebSockerReader->start(this);
-} // startReader
-
-
-/**
- * @brief Create a Web Socket input record streambuf
- * @param [in] socket The socket we will be reading from.
- * @param [in] dataLength The size of a record.
- * @param [in] bufferSize The size of the buffer we wish to allocate to hold data.
- */
-WebSocketInputRecordStreambuf::WebSocketInputRecordStreambuf(
-	Socket   socket,
-	size_t   dataLength,
-	uint8_t *pMask,
-	size_t   bufferSize) {
-	m_socket     = socket;    // The socket we will be reading from
-	m_dataLength = dataLength; // The size of the record we wish to read.
-	m_pMask      = pMask;
-	m_bufferSize = bufferSize; // The size of the buffer used to hold data
-	m_sizeRead   = 0;          // The size of data read from the socket
-	m_buffer = new char[bufferSize]; // Create the buffer used to hold the data read from the socket.
-
-	setg(m_buffer, m_buffer, m_buffer); // Set the initial get buffer pointers to no data.
-} // WebSocketInputRecordStreambuf
-
-
-/**
- * @brief Destructor
- */
-WebSocketInputRecordStreambuf::~WebSocketInputRecordStreambuf() {
-	delete[] m_buffer;
-	discard();
-} // ~WebSocketInputRecordStreambuf
-
-
-/**
- * @brief Discard data for the record that has not yet been read.
- *
- * We are working on a logical fixed length record in a socket stream.  This means that we know in advance
- * how big the record should be.  If we have read some data from the stream and no longer wish to consume
- * any further, we have to discard the remaining bytes in the stream before we can get to process the
- * next record.  This function discards the remainder of the data.
- *
- * For example, if our record size is 1000 bytes and we have read 700 bytes and determine that we no
- * longer need to continue, we can't just stop.  There are still 300 bytes in the socket stream that
- * need to be consumed/discarded before we can move on to the next record.
- */
-void WebSocketInputRecordStreambuf::discard() {
-	uint8_t byte;
-	ESP_LOGD("WebSocketInputRecordStreambuf", ">> discard: Discarding %d bytes", m_dataLength - m_sizeRead);
-	while(m_sizeRead < m_dataLength) {
-		m_socket.receive_cpp(&byte, 1);
-		m_sizeRead++;
-	}
-	ESP_LOGD("WebSocketInputRecordStreambuf", "<< discard");
-} // discard
-
-
-/**
- * @brief Get the size of the expected record.
- * @return The size of the expected record.
- */
-size_t WebSocketInputRecordStreambuf::getRecordSize() {
-	return m_dataLength;
-} // getRecordSize
-
-
-/**
- * @brief Handle the request to read data from the stream but we need more data from the source.
- *
- */
-WebSocketInputRecordStreambuf::int_type WebSocketInputRecordStreambuf::underflow() {
-	ESP_LOGD("WebSocketInputRecordStreambuf", ">> underflow");
-	if (m_sizeRead >= getRecordSize()) {
-		ESP_LOGD("WebSocketInputRecordStreambuf", "<< underflow: Already read maximum");
-		return EOF;
-	}
-
-	// We wish to refill the buffer.  We want to read data from the socket.  We want to read either
-	// the size of the buffer to fill it or the maximum number of bytes remaining to be read.
-	// We will choose which ever is smaller as the number of bytes to read into the buffer.
-	int remainingBytes = getRecordSize()-m_sizeRead;
-	size_t sizeToRead;
-	if (remainingBytes < m_bufferSize) {
-		sizeToRead = remainingBytes;
-	} else {
-		sizeToRead = m_bufferSize;
-	}
-
-	ESP_LOGD("WebSocketInputRecordStreambuf", "- getting next buffer of data; size request: %d", sizeToRead);
-	int bytesRead = m_socket.receive_cpp((uint8_t*)m_buffer, sizeToRead, true);
-	if (bytesRead == 0) {
-		ESP_LOGD("WebSocketInputRecordStreambuf", "<< underflow: Read 0 bytes");
-		return EOF;
-	}
-
-	if (m_pMask != nullptr) {
-		for (int i=0; i<bytesRead; i++) {
-			m_buffer[i] = m_buffer[i] ^ m_pMask[(m_sizeRead+i)%4];
-		}
-	}
-
-	m_sizeRead += bytesRead;
-	setg(m_buffer, m_buffer, m_buffer + bytesRead);
-	ESP_LOGD("WebSocketInputRecordStreambuf", "<< underflow - got %d more bytes", bytesRead);
-	return traits_type::to_int_type(*gptr());
-} // underflow
-
-WebSocketHandler::~WebSocketHandler() {
-}
diff --git a/components/cpp_utils/WebSocket.h b/components/cpp_utils/WebSocket.h
deleted file mode 100644
index dc17f18..0000000
--- a/components/cpp_utils/WebSocket.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * WebSocket.h
- *
- *  Created on: Sep 2, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_WEBSOCKET_H_
-#define COMPONENTS_WEBSOCKET_H_
-#include <string>
-#include "Socket.h"
-class WebSocketReader;
-
-// +-------------------------------+
-// | WebSocketInputRecordStreambuf |
-// +-------------------------------+
-class WebSocketInputRecordStreambuf : public std::streambuf {
-public:
-	WebSocketInputRecordStreambuf(
-		Socket   socket,
-		size_t   dataLength,
-		uint8_t* pMask=nullptr,
-		size_t   bufferSize=2048);
-	~WebSocketInputRecordStreambuf();
-	int_type underflow();
-	void discard();
-	size_t getRecordSize();
-private:
-	char*    m_buffer;
-	Socket   m_socket;
-	size_t   m_dataLength;
-	size_t   m_bufferSize;
-	size_t   m_sizeRead;
-	uint8_t* m_pMask;
-};
-
-
-// +------------------+
-// | WebSocketHandler |
-// +------------------+
-class WebSocketHandler {
-public:
-	virtual ~WebSocketHandler();
-	virtual void onClose();
-	virtual void onMessage(WebSocketInputRecordStreambuf *pWebSocketInputRecordStreambuf);
-	virtual void onError(std::string error);
-};
-
-
-// +-----------+
-// | WebSocket |
-// +-----------+
-class WebSocket {
-private:
-	friend class WebSocketReader;
-	friend class HttpServerTask;
-	void              startReader();
-	bool              m_receivedClose; // True when we have received a close request.
-	bool              m_sentClose;     // True when we have sent a close request.
-	Socket            m_socket;        // Partner socket.
-	WebSocketHandler *m_pWebSocketHandler;
-	WebSocketReader  *m_pWebSockerReader;
-
-public:
-	static const uint16_t CLOSE_NORMAL_CLOSURE        = 1000;
-	static const uint16_t CLOSE_GOING_AWAY            = 1001;
-	static const uint16_t CLOSE_PROTOCOL_ERROR        = 1002;
-	static const uint16_t CLOSE_CANNOT_ACCEPT         = 1003;
-	static const uint16_t CLOSE_NO_STATUS_CODE        = 1005;
-	static const uint16_t CLOSE_CLOSED_ABNORMALLY     = 1006;
-	static const uint16_t CLOSE_NOT_CONSISTENT        = 1007;
-	static const uint16_t CLOSE_VIOLATED_POLICY       = 1008;
-	static const uint16_t CLOSE_TOO_BIG               = 1009;
-	static const uint16_t CLOSE_NO_EXTENSION          = 1010;
-	static const uint16_t CLOSE_UNEXPECTED_CONDITION  = 1011;
-	static const uint16_t CLOSE_SERVICE_RESTART       = 1012;
-	static const uint16_t CLOSE_TRY_AGAIN_LATER       = 1013;
-	static const uint16_t CLOSE_TLS_HANDSHAKE_FAILURE = 1015;
-
-	static const uint8_t SEND_TYPE_BINARY = 0x01;
-	static const uint8_t SEND_TYPE_TEXT   = 0x02;
-
-	WebSocket(Socket socket);
-	virtual ~WebSocket();
-
-	void              close_cpp(uint16_t status=CLOSE_NORMAL_CLOSURE, std::string message = "");
-	WebSocketHandler* getHandler();
-	Socket            getSocket();
-	void              send_cpp(std::string data, uint8_t sendType = SEND_TYPE_BINARY);
-	void              setHandler(WebSocketHandler *handler);
-}; // WebSocket
-
-#endif /* COMPONENTS_WEBSOCKET_H_ */
diff --git a/components/cpp_utils/WebSocketFileTransfer.cpp b/components/cpp_utils/WebSocketFileTransfer.cpp
deleted file mode 100644
index 2ada459..0000000
--- a/components/cpp_utils/WebSocketFileTransfer.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * WebSocketFileTransfer.cpp
- *
- *  Created on: Sep 9, 2017
- *      Author: kolban
- */
-#include <sstream>
-#include <fstream>
-#include <esp_log.h>
-#include <sys/stat.h>
-#include "JSON.h"
-static const char* LOG_TAG = "WebSocketFileTransfer";
-
-#include "WebSocketFileTransfer.h"
-
-#undef close
-
-WebSocketFileTransfer::WebSocketFileTransfer() {
-	m_fileName   = "";
-	m_length     = 0;
-	m_pWebSocket = nullptr;
-}
-
-WebSocketFileTransfer::~WebSocketFileTransfer() {
-	// TODO Auto-generated destructor stub
-}
-
-
-// Hide the class in an un-named namespace
-namespace {
-
-class FileTransferWebSocketHandler : public WebSocketHandler {
-public:
-	FileTransferWebSocketHandler() {
-		m_fileName     = "";
-		m_fileLength   = 0;
-		m_sizeReceived = 0;
-		m_active       = false;
-	}
-
-private:
-	std::string   m_fileName;      // The name of the file we are receiving.
-	uint32_t      m_fileLength;    // We may optionally receive a file length.
-	uint32_t      m_sizeReceived;  // The size of the data actually received so far.
-	bool          m_active;        // Are we actively processing a file.
-	std::ofstream m_ofStream;
-
-	virtual void onMessage(WebSocketInputRecordStreambuf* pWebSocketInputRecordStreambuf) {
-		ESP_LOGD("FileTransferWebSocketHandler", ">> onMessage");
-		if (!m_active) {
-			std::stringstream buffer;
-			buffer << pWebSocketInputRecordStreambuf;
-			ESP_LOGD("FileTransferWebSocketHandler", "Data read: %s", buffer.str().c_str());
-			JsonObject jo = JSON::parseObject(buffer.str());
-			m_fileName    = jo.getString("name");
-			if (jo.hasItem("length")) {
-				m_fileLength  = jo.getInt("length");
-			}
-			std::string fileName = "/spiflash/" + m_fileName;
-			if (m_fileName.length() > 0 && m_fileName.substr(m_fileName.size()-1)=="/") {
-				ESP_LOGD("FileTransferWebSocketHandler", "Is a directory!!");
-				fileName = fileName.substr(0, fileName.size()-1);
-				struct stat statbuf;
-				if (stat(fileName.c_str(), &statbuf) == 0) {
-					if (S_ISREG(statbuf.st_mode)) {
-						ESP_LOGE("FileTransferWebSocketHandler", "File already exists and is a file not a directory!");
-					}
-				}
-				if (mkdir(fileName.c_str(), 0) != 0) {
-					ESP_LOGE("FileTransferWebSocketHandler", "Failed to make directory \"%s\", error: %s", fileName.c_str(), strerror(errno));
-				}
-			} else {
-				m_ofStream.open(fileName, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
-				if (!m_ofStream.is_open()) {
-					ESP_LOGE("FileTransferWebSocketHandler", "Failed to open file %s", m_fileName.c_str());
-				}
-			}
-			m_active      = true;
-			ESP_LOGD("FileTransferWebSocketHandler", "Filename: %s, length: %d", fileName.c_str(), m_fileLength);
-		} else {
-			// We are about to receive a chunk of file
-			m_ofStream << pWebSocketInputRecordStreambuf;
-			/*
-			std::stringstream bufferStream;
-			bufferStream << pWebSocketInputRecordStreambuf;
-			m_sizeReceived += bufferStream.str().length();
-			ESP_LOGD("FileTransferWebSocketHandler", "Received %d bytes of file data", bufferStream.str().length());
-			if (m_fileLength > 0 && m_sizeReceived > m_fileLength) {
-				ESP_LOGD("FileTransferWebSocketHandler",
-					"ERROR: Received a total of %d bytes when only %d bytes expected!", m_sizeReceived, m_fileLength);
-			}
-			*/
-		}
-	} // onMessage
-
-
-	virtual void onClose() {
-		ESP_LOGD("FileTransferWebSocketHandler", ">> onClose: fileName: %s, sizeReceived: %d", m_fileName.c_str(), m_sizeReceived);
-		if (m_fileLength > 0 && m_sizeReceived != m_fileLength) {
-			ESP_LOGD("FileTransferWebSocketHandler",
-				"ERROR: Transfer finished but we received total of %d bytes and expected %d bytes!", m_sizeReceived, m_fileLength);
-		}
-		m_ofStream.close();
-	} // onClose
-}; // FileTransferWebSocketHandler
-
-} // End un-named namespace
-
-void WebSocketFileTransfer::start(WebSocket* pWebSocket) {
-	ESP_LOGD(LOG_TAG, ">> start");
-	pWebSocket->setHandler(new FileTransferWebSocketHandler());
-} // start
diff --git a/components/cpp_utils/WebSocketFileTransfer.h b/components/cpp_utils/WebSocketFileTransfer.h
deleted file mode 100644
index d3db986..0000000
--- a/components/cpp_utils/WebSocketFileTransfer.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * WebSocketFileTransfer.h
- *
- *  Created on: Sep 9, 2017
- *      Author: kolban
- */
-
-#ifndef COMPONENTS_CPP_UTILS_WEBSOCKETFILETRANSFER_H_
-#define COMPONENTS_CPP_UTILS_WEBSOCKETFILETRANSFER_H_
-#include <string>
-#include "WebSocket.h"
-
-class WebSocketFileTransfer {
-private:
-	std::string   m_fileName;
-	size_t        m_length;
-	WebSocket*    m_pWebSocket;
-public:
-	WebSocketFileTransfer();
-	virtual ~WebSocketFileTransfer();
-	void     start(WebSocket *pWebSocket);
-};
-
-#endif /* COMPONENTS_CPP_UTILS_WEBSOCKETFILETRANSFER_H_ */
diff --git a/components/cpp_utils/WiFi.cpp b/components/cpp_utils/WiFi.cpp
deleted file mode 100644
index a207f95..0000000
--- a/components/cpp_utils/WiFi.cpp
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * WiFi.cpp
- *
- *  Created on: Feb 25, 2017
- *      Author: kolban
- */
-
-//#define _GLIBCXX_USE_C99
-#include <string>
-#include <sstream>
-#include <iomanip>
-#include "sdkconfig.h"
-
-
-#include "WiFi.h"
-#include <esp_event.h>
-#include <esp_event_loop.h>
-#include <esp_log.h>
-#include <esp_system.h>
-#include <esp_wifi.h>
-#include <freertos/FreeRTOS.h>
-#include <nvs_flash.h>
-#include <lwip/dns.h>
-#include <lwip/netdb.h>
-#include <lwip/sockets.h>
-
-#include <string.h>
-#include <Task.h>
-
-
-
-static char tag[]= "WiFi";
-
-
-/*
-static void setDNSServer(char *ip) {
-	ip_addr_t dnsserver;
-	ESP_LOGD(tag, "Setting DNS[%d] to %s", 0, ip);
-	inet_pton(AF_INET, ip, &dnsserver);
-	ESP_LOGD(tag, "ip of DNS is %.8x", *(uint32_t *)&dnsserver);
-	dns_setserver(0, &dnsserver);
-}
-*/
-
-
-WiFi::WiFi() {
-	ip      = "";
-	gw      = "";
-	netmask = "";
-	wifiEventHandler = new WiFiEventHandler();
-}
-
-
-/**
- * @brief Add a reference to a DNS server.
- *
- * Here we define a server that will act as a DNS server.  We can add two DNS
- * servers in total.  The first will be the primary, the second will be the backup.
- * The public Google DNS servers are "8.8.8.8" and "8.8.4.4".
- *
- * For example:
- *
- * @code{.cpp}
- * wifi.addDNSServer("8.8.8.8");
- * wifi.addDNSServer("8.8.4.4");
- * @endcode
- *
- * @param [in] ip The IP address of the DNS Server.
- * @return N/A.
- */
-void WiFi::addDNSServer(std::string ip) {
-	ip_addr_t dnsserver;
-	ESP_LOGD(tag, "Setting DNS[%d] to %s", m_dnsCount, ip.c_str());
-	inet_pton(AF_INET, ip.c_str(), &dnsserver);
-	::dns_setserver(m_dnsCount, &dnsserver);
-	m_dnsCount++;
-} // addDNSServer
-
-/**
- * @brief Connect to an external access point.
- *
- * The event handler will be called back with the outcome of the connection.
- *
- * @param[in] ssid The network SSID of the access point to which we wish to connect.
- * @param[in] password The password of the access point to which we wish to connect.
- * @return N/A.
- */
-void WiFi::connectAP(std::string ssid, std::string password){
-	::nvs_flash_init();
-	::tcpip_adapter_init();
-	if (ip.length() > 0 && gw.length() > 0 && netmask.length() > 0) {
-		::tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); // Don't run a DHCP client
-		tcpip_adapter_ip_info_t ipInfo;
-
-		inet_pton(AF_INET, ip.data(), &ipInfo.ip);
-		inet_pton(AF_INET, gw.data(), &ipInfo.gw);
-		inet_pton(AF_INET, netmask.data(), &ipInfo.netmask);
-		::tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
-	}
-
-
-	ESP_ERROR_CHECK( esp_event_loop_init(wifiEventHandler->getEventHandler(), wifiEventHandler));
-	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
-	ESP_ERROR_CHECK(::esp_wifi_init(&cfg));
-	ESP_ERROR_CHECK(::esp_wifi_set_storage(WIFI_STORAGE_RAM));
-	ESP_ERROR_CHECK(::esp_wifi_set_mode(WIFI_MODE_STA));
-	wifi_config_t sta_config;
-	::memset(&sta_config, 0, sizeof(sta_config));
-	::memcpy(sta_config.sta.ssid, ssid.data(), ssid.size());
-	::memcpy(sta_config.sta.password, password.data(), password.size());
-	sta_config.sta.bssid_set = 0;
-	ESP_ERROR_CHECK(::esp_wifi_set_config(WIFI_IF_STA, &sta_config));
-	ESP_ERROR_CHECK(::esp_wifi_start());
-
-	ESP_ERROR_CHECK(::esp_wifi_connect());
-} // connectAP
-
-
-/**
- * @brief Dump diagnostics to the log.
- */
-void WiFi::dump() {
-	ESP_LOGD(tag, "WiFi Dump");
-	ESP_LOGD(tag, "---------");
-	char ipAddrStr[30];
-	ip_addr_t ip = ::dns_getserver(0);
-	inet_ntop(AF_INET, &ip, ipAddrStr, sizeof(ipAddrStr));
-	ESP_LOGD(tag, "DNS Server[0]: %s", ipAddrStr);
-} // dump
-
-/**
- * @brief Get the AP IP Info.
- * @return The AP IP Info.
- */
-tcpip_adapter_ip_info_t WiFi::getApIpInfo() {
-	tcpip_adapter_ip_info_t ipInfo;
-	tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ipInfo);
-	return ipInfo;
-} // getApIpInfo
-
-
-
-/**
- * @brief Get the MAC address of the AP interface.
- * @return The MAC address of the AP interface.
- */
-std::string WiFi::getApMac() {
-	uint8_t mac[6];
-	esp_wifi_get_mac(WIFI_IF_AP, mac);
-	std::stringstream s;
-	s << std::hex << std::setfill('0') << std::setw(2) << (int) mac[0] << ':' << (int) mac[1] << ':' << (int) mac[2] << ':' << (int) mac[3] << ':' << (int) mac[4] << ':' << (int) mac[5];
-	return s.str();
-} // getApMac
-
-
-/**
- * @brief Get the AP SSID.
- * @return The AP SSID.
- */
-std::string WiFi::getApSSID() {
-	wifi_config_t conf;
-	esp_wifi_get_config(WIFI_IF_AP, &conf);
-	return std::string((char *)conf.sta.ssid);
-} // getApSSID
-
-
-/**
- * @brief Lookup an IP address by host name.
- *
- * @param [in] hostName The hostname to resolve.
- *
- * @return The IP address of the host or 0.0.0.0 if not found.
- */
-struct in_addr WiFi::getHostByName(std::string hostName) {
-	struct in_addr retAddr;
-	struct hostent *he = gethostbyname(hostName.c_str());
-	if (he == nullptr) {
-		retAddr.s_addr = 0;
-		ESP_LOGD(tag, "Unable to resolve %s - %d", hostName.c_str(), h_errno);
-	} else {
-		retAddr = *(struct in_addr *)(he->h_addr_list[0]);
-		//ESP_LOGD(tag, "resolved %s to %.8x", hostName, *(uint32_t *)&retAddr);
-
-	}
-	return retAddr;
-} // getHostByName
-
-
-/**
- * @brief Get the WiFi Mode.
- * @return The WiFi Mode.
- */
-std::string WiFi::getMode() {
-	wifi_mode_t mode;
-	esp_wifi_get_mode(&mode);
-	switch(mode) {
-		case WIFI_MODE_NULL:
-			return "WIFI_MODE_NULL";
-		case WIFI_MODE_STA:
-			return "WIFI_MODE_STA";
-		case WIFI_MODE_AP:
-			return "WIFI_MODE_AP";
-		case WIFI_MODE_APSTA:
-			return "WIFI_MODE_APSTA";
-		default:
-			return "unknown";
-	}
-} // getMode
-
-
-/**
- * @brief Get the STA IP Info.
- * @return The STA IP Info.
- */
-tcpip_adapter_ip_info_t WiFi::getStaIpInfo() {
-	tcpip_adapter_ip_info_t ipInfo;
-	tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
-	return ipInfo;
-} // getStaIpInfo
-
-
-/**
- * @brief Get the MAC address of the STA interface.
- * @return The MAC address of the STA interface.
- */
-std::string WiFi::getStaMac() {
-	uint8_t mac[6];
-	esp_wifi_get_mac(WIFI_IF_STA, mac);
-	std::stringstream s;
-	s << std::hex << std::setfill('0') << std::setw(2) << (int) mac[0] << ':' << (int) mac[1] << ':' << (int) mac[2] << ':' << (int) mac[3] << ':' << (int) mac[4] << ':' << (int) mac[5];
-	return s.str();
-} // getStaMac
-
-
-/**
- * @brief Get the STA SSID.
- * @return The STA SSID.
- */
-std::string WiFi::getStaSSID() {
-	wifi_config_t conf;
-	esp_wifi_get_config(WIFI_IF_STA, &conf);
-	return std::string((char *)conf.ap.ssid);
-} // getStaSSID
-
-
-/**
- * @brief Perform a WiFi scan looking for access points.
- *
- * An access point scan is performed and a vector of WiFi access point records
- * is built and returned with one record per found scan instance.  The scan is
- * performed in a blocking fashion and will not return until the set of scanned
- * access points has been built.
- *
- * @return A vector of WiFiAPRecord instances.
- */
-std::vector<WiFiAPRecord> WiFi::scan() {
-	::nvs_flash_init();
-	::tcpip_adapter_init();
-	ESP_ERROR_CHECK(esp_event_loop_init(wifiEventHandler->getEventHandler(), wifiEventHandler));
-	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
-	ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
-	ESP_ERROR_CHECK(::esp_wifi_set_storage(WIFI_STORAGE_RAM));
-	ESP_ERROR_CHECK(::esp_wifi_set_mode(WIFI_MODE_STA));
-	ESP_ERROR_CHECK( esp_wifi_start() );
-	wifi_scan_config_t conf;
-	memset(&conf, 0, sizeof(conf));
-	conf.show_hidden = true;
-	esp_err_t rc = ::esp_wifi_scan_start(&conf, true);
-	if (rc != ESP_OK) {
-		ESP_LOGE(tag, "esp_wifi_scan_start: %d", rc);
-	}
-	uint16_t apCount;
-	rc = ::esp_wifi_scan_get_ap_num(&apCount);
-	ESP_LOGD(tag, "Count of found access points: %d", apCount);
-    wifi_ap_record_t *list =
-      (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);
-    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, list));
-    std::vector<WiFiAPRecord> apRecords;
-    for (auto i=0; i<apCount; i++) {
-    	WiFiAPRecord wifiAPRecord;
-    	memcpy(wifiAPRecord.m_bssid, list[i].bssid, 6);
-    	wifiAPRecord.m_ssid = std::string((char *)list[i].ssid);
-    	wifiAPRecord.m_authMode = list[i].authmode;
-    	apRecords.push_back(wifiAPRecord);
-    }
-    free(list);
-    return apRecords;
-} // scan
-
-
-/**
- * @brief Start being an access point.
- *
- * @param[in] ssid The SSID to use to advertize for stations.
- * @param[in] password The password to use for station connections.
- * @return N/A.
- */
-void WiFi::startAP(std::string ssid, std::string password) {
-	::nvs_flash_init();
-	::tcpip_adapter_init();
-	ESP_ERROR_CHECK(esp_event_loop_init(wifiEventHandler->getEventHandler(), wifiEventHandler));
-	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
-	ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
-	ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
-	ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) );
-	wifi_config_t apConfig;
-	::memset(&apConfig, 0, sizeof(apConfig));
-	::memcpy(apConfig.ap.ssid, ssid.data(), ssid.size());
-	apConfig.ap.ssid_len = 0;
-	::memcpy(apConfig.ap.password, password.data(), password.size());
-	apConfig.ap.channel = 0;
-	apConfig.ap.authmode = WIFI_AUTH_OPEN;
-	apConfig.ap.ssid_hidden = 0;
-	apConfig.ap.max_connection = 4;
-	apConfig.ap.beacon_interval = 100;
-	ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &apConfig) );
-	ESP_ERROR_CHECK( esp_wifi_start() );
-} // startAP
-
-
-/**
- * @brief Set the IP info used when connecting as a station to an external access point.
- *
- * Do not call this method if we are being an access point ourselves.
- *
- * For example, prior to calling `connectAP()` we could invoke:
- *
- * @code{.cpp}
- * myWifi.setIPInfo("192.168.1.99", "192.168.1.1", "255.255.255.0");
- * @endcode
- *
- * @param [in] ip IP address value.
- * @param [in] gw Gateway value.
- * @param [in] netmask Netmask value.
- * @return N/A.
- */
-void WiFi::setIPInfo(std::string ip, std::string gw, std::string netmask) {
-	this->ip = ip;
-	this->gw = gw;
-	this->netmask = netmask;
-} // setIPInfo
-
-
-/**
- * @brief Return a string representation of the WiFi access point record.
- *
- * @return A string representation of the WiFi access point record.
- */
-std::string WiFiAPRecord::toString() {
-	std::string auth;
-	switch(getAuthMode()) {
-	case WIFI_AUTH_OPEN:
-		auth = "WIFI_AUTH_OPEN";
-		break;
-	case WIFI_AUTH_WEP:
-		auth = "WIFI_AUTH_WEP";
-		break;
-	case WIFI_AUTH_WPA_PSK:
-		auth = "WIFI_AUTH_WPA_PSK";
-		break;
-	case WIFI_AUTH_WPA2_PSK:
-		auth = "WIFI_AUTH_WPA2_PSK";
-		break;
-	case WIFI_AUTH_WPA_WPA2_PSK:
-		auth = "WIFI_AUTH_WPA_WPA2_PSK";
-		break;
-	default:
-		auth = "<unknown>";
-		break;
-	}
-	std::stringstream s;
-	s<< "ssid: " << m_ssid << ", auth: " << auth << ", rssi: " << m_rssi;
-	return s.str();
-} // toString
-
-MDNS::MDNS() {
-	ESP_ERROR_CHECK(mdns_init(TCPIP_ADAPTER_IF_STA, &m_mdns_server));
-}
-
-MDNS::~MDNS() {
-	if (m_mdns_server != nullptr) {
-		mdns_free(m_mdns_server);
-	}
-	m_mdns_server = nullptr;
-}
-
-/**
- * @brief Define the service for mDNS.
- *
- * @param [in] service
- * @param [in] proto
- * @param [in] port
- * @return N/A.
- */
-void MDNS::serviceAdd(std::string service, std::string proto, uint16_t port) {
-	ESP_ERROR_CHECK(mdns_service_add(m_mdns_server, service.c_str(), proto.c_str(), port));
-} // serviceAdd
-
-
-void MDNS::serviceInstanceSet(std::string service, std::string proto, std::string instance) {
-	ESP_ERROR_CHECK(mdns_service_instance_set(m_mdns_server, service.c_str(), proto.c_str(), instance.c_str()));
-} // serviceInstanceSet
-
-
-void MDNS::servicePortSet(std::string service, std::string proto, uint16_t port) {
-	ESP_ERROR_CHECK(mdns_service_port_set(m_mdns_server, service.c_str(), proto.c_str(), port));
-} // servicePortSet
-
-
-void MDNS::serviceRemove(std::string service, std::string proto) {
-	ESP_ERROR_CHECK(mdns_service_remove(m_mdns_server, service.c_str(), proto.c_str()));
-} // serviceRemove
-
-
-/**
- * @brief Set the mDNS hostname.
- *
- * @param [in] hostname The host name to set against the mDNS.
- * @return N/A.
- */
-void MDNS::setHostname(std::string hostname) {
-	ESP_ERROR_CHECK(mdns_set_hostname(m_mdns_server,hostname.c_str()));
-} // setHostname
-
-
-/**
- * @brief Set the mDNS instance.
- *
- * @param [in] instance The instance name to set against the mDNS.
- * @return N/A.
- */
-void MDNS::setInstance(std::string instance) {
-	ESP_ERROR_CHECK(mdns_set_instance(m_mdns_server, instance.c_str()));
-} // setInstance
diff --git a/components/cpp_utils/WiFi.h b/components/cpp_utils/WiFi.h
deleted file mode 100644
index 979c04f..0000000
--- a/components/cpp_utils/WiFi.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * WiFi.h
- *
- *  Created on: Feb 25, 2017
- *      Author: kolban
- */
-
-#ifndef MAIN_WIFI_H_
-#define MAIN_WIFI_H_
-#include "sdkconfig.h"
-
-#include <string>
-#include <vector>
-#include <mdns.h>
-#include "WiFiEventHandler.h"
-
-/**
- * @brief Manage mDNS server.
- */
-class MDNS {
-public:
-	MDNS();
-	~MDNS();
-	void serviceAdd(std::string service, std::string proto, uint16_t port);
-	void serviceInstanceSet(std::string service, std::string proto, std::string instance);
-	void servicePortSet(std::string service, std::string proto, uint16_t port);
-	void serviceRemove(std::string service, std::string proto);
-	void setHostname(std::string hostname);
-	void setInstance(std::string instance);
-private:
-	mdns_server_t *m_mdns_server = nullptr;
-};
-
-class WiFiAPRecord {
-public:
-	friend class WiFi;
-
-	/**
-	 * @brief Get the auth mode.
-	 * @return The auth mode.
-	 */
-	wifi_auth_mode_t getAuthMode() {
-		return m_authMode;
-	}
-
-	/**
-	 * @brief Get the RSSI.
-	 * @return the RSSI.
-	 */
-	int8_t getRSSI() {
-		return m_rssi;
-	}
-
-	/**
-	 * @brief Get the SSID.
-	 * @return the SSID.
-	 */
-	std::string getSSID() {
-		return m_ssid;
-	}
-
-	std::string toString();
-
-private:
-	uint8_t m_bssid[6];
-	int8_t m_rssi;
-	std::string m_ssid;
-	wifi_auth_mode_t m_authMode;
-};
-
-/**
- * @brief %WiFi driver.
- *
- * Encapsulate control of %WiFi functions.
- *
- * Here is an example fragment that illustrates connecting to an access point.
- * @code{.cpp}
- * #include <WiFi.h>
- * #include <WiFiEventHandler.h>
- *
- * class TargetWiFiEventHandler: public WiFiEventHandler {
- *    esp_err_t staGotIp(system_event_sta_got_ip_t event_sta_got_ip) {
- *       ESP_LOGD(tag, "MyWiFiEventHandler(Class): staGotIp");
- *       // Do something ...
- *       return ESP_OK;
- *    }
- * };
- *
- * WiFi wifi;
- *
- * TargetWiFiEventHandler *eventHandler = new TargetWiFiEventHandler();
- * wifi.setWifiEventHandler(eventHandler);
- * wifi.connectAP("myssid", "mypassword");
- * @endcode
- */
-class WiFi {
-private:
-	std::string      ip;
-	std::string      gw;
-	std::string      netmask;
-	WiFiEventHandler *wifiEventHandler;
-
-public:
-	WiFi();
-	void addDNSServer(std::string ip);
-	struct in_addr getHostByName(std::string hostName);
-	void connectAP(std::string ssid, std::string passwd);
-	void dump();
-	static std::string getApMac();
-	static tcpip_adapter_ip_info_t getApIpInfo();
-	static std::string getApSSID();
-	static std::string getMode();
-	static tcpip_adapter_ip_info_t getStaIpInfo();
-	static std::string getStaMac();
-	static std::string getStaSSID();
-	std::vector<WiFiAPRecord> scan();
-	void startAP(std::string ssid, std::string passwd);
-	void setIPInfo(std::string ip, std::string gw, std::string netmask);
-
-
-
-
-
-	/**
-	 * Set the event handler to use to process detected events.
-	 * @param[in] wifiEventHandler The class that will be used to process events.
-	 */
-	void setWifiEventHandler(WiFiEventHandler *wifiEventHandler) {
-		this->wifiEventHandler = wifiEventHandler;
-	}
-private:
-	int m_dnsCount=0;
-	//char *m_dnsServer = nullptr;
-
-};
-
-#endif /* MAIN_WIFI_H_ */
diff --git a/components/cpp_utils/WiFiEventHandler.cpp b/components/cpp_utils/WiFiEventHandler.cpp
deleted file mode 100644
index 1c454d5..0000000
--- a/components/cpp_utils/WiFiEventHandler.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * WiFiEventHandler.cpp
- *
- *  Created on: Feb 25, 2017
- *      Author: kolban
- */
-
-#include "WiFiEventHandler.h"
-#include <esp_event.h>
-#include <esp_event_loop.h>
-#include <esp_wifi.h>
-#include <esp_err.h>
-#include <esp_log.h>
-#include "sdkconfig.h"
-
-static char tag[] = "WiFiEventHandler";
-
-/**
- * @brief The entry point into the event handler.
- * Examine the event passed into the handler controller by the WiFi subsystem and invoke
- * the corresponding handler.
- * @param [in] ctx
- * @param [in] event
- * @return ESP_OK if the event was handled otherwise an error.
- */
-esp_err_t WiFiEventHandler::eventHandler(void *ctx, system_event_t *event) {
-	ESP_LOGD(tag, "eventHandler called");
-	WiFiEventHandler *pWiFiEventHandler = (WiFiEventHandler *)ctx;
-	if (ctx == nullptr) {
-		ESP_LOGD(tag, "No context");
-		return ESP_OK;
-	}
-	esp_err_t rc = ESP_OK;
-	switch(event->event_id) {
-
-		case SYSTEM_EVENT_AP_START:
-			rc =  pWiFiEventHandler->apStart();
-			break;
-		case SYSTEM_EVENT_AP_STOP:
-			rc =  pWiFiEventHandler->apStop();
-			break;
-		case SYSTEM_EVENT_STA_CONNECTED:
-			rc =  pWiFiEventHandler->staConnected();
-			break;
-		case SYSTEM_EVENT_STA_DISCONNECTED:
-			rc =  pWiFiEventHandler->staDisconnected();
-			break;
-		case SYSTEM_EVENT_STA_GOT_IP:
-			rc = pWiFiEventHandler->staGotIp(event->event_info.got_ip);
-			break;
-		case SYSTEM_EVENT_STA_START:
-			rc =  pWiFiEventHandler->staStart();
-			break;
-		case SYSTEM_EVENT_STA_STOP:
-			rc =  pWiFiEventHandler->staStop();
-			break;
-		case SYSTEM_EVENT_WIFI_READY:
-			rc =  pWiFiEventHandler->wifiReady();
-			break;
-		default:
-			break;
-	}
-	if (pWiFiEventHandler->nextHandler != nullptr) {
-		printf("Found a next handler\n");
-		rc = eventHandler(pWiFiEventHandler->nextHandler, event);
-	} else {
-		//printf("NOT Found a next handler\n");
-	}
-	return rc;
-}
-
-WiFiEventHandler::WiFiEventHandler() {
-}
-
-
-/**
- * @brief Get the event handler.
- * Retrieve the event handler function to be passed to the ESP-IDF event handler system.
- * @return The event handler function.
- */
-system_event_cb_t WiFiEventHandler::getEventHandler() {
-	return eventHandler;
-} // getEventHandler
-
-
-/**
- * @brief Handle the Station Got IP event.
- * Handle having received/assigned an IP address when we are a station.
- * @param [in] event_sta_got_ip The Station Got IP event.
- * @return An indication of whether or not we processed the event successfully.
- */
-esp_err_t WiFiEventHandler::staGotIp(system_event_sta_got_ip_t event_sta_got_ip) {
-	ESP_LOGD(tag, "default staGotIp");
-	return ESP_OK;
-} // staGotIp
-
-/**
- * @brief Handle the Access Point started event.
- * Handle an indication that the ESP32 has started being an access point.
- * @return An indication of whether or not we processed the event successfully.
- */
-esp_err_t WiFiEventHandler::apStart() {
-	ESP_LOGD(tag, "default apStart");
-	return ESP_OK;
-} // apStart
-
-/**
- * @brief Handle the Access Point stop event.
- * Handle an indication that the ESP32 has stopped being an access point.
- * @return An indication of whether or not we processed the event successfully.
- */
-esp_err_t WiFiEventHandler::apStop() {
-	ESP_LOGD(tag, "default apStop");
-	return ESP_OK;
-} // apStop
-
-esp_err_t WiFiEventHandler::wifiReady() {
-	ESP_LOGD(tag, "default wifiReady");
-	return ESP_OK;
-} // wifiReady
-
-esp_err_t WiFiEventHandler::staStart() {
-	ESP_LOGD(tag, "default staStart");
-	return ESP_OK;
-} // staStart
-
-esp_err_t WiFiEventHandler::staStop() {
-	ESP_LOGD(tag, "default staStop");
-	return ESP_OK;
-} // staStop
-
-esp_err_t WiFiEventHandler::staConnected() {
-	ESP_LOGD(tag, "default staConnected");
-	return ESP_OK;
-} // staConnected
-
-esp_err_t WiFiEventHandler::staDisconnected() {
-	ESP_LOGD(tag, "default staDisconnected");
-	return ESP_OK;
-} // staDisconnected
-
-esp_err_t WiFiEventHandler::apStaConnected() {
-	ESP_LOGD(tag, "default apStaConnected");
-	return ESP_OK;
-} // apStaConnected
-
-esp_err_t WiFiEventHandler::apStaDisconnected() {
-	ESP_LOGD(tag, "default apStaDisconnected");
-	return ESP_OK;
-} // apStaDisconnected
-
-WiFiEventHandler::~WiFiEventHandler() {
-	if (nextHandler != nullptr) {
-		delete nextHandler;
-	}
-} // ~WiFiEventHandler
diff --git a/components/cpp_utils/WiFiEventHandler.h b/components/cpp_utils/WiFiEventHandler.h
deleted file mode 100644
index 9bfb7e1..0000000
--- a/components/cpp_utils/WiFiEventHandler.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * WiFiEventHandler.h
- *
- *  Created on: Feb 25, 2017
- *      Author: kolban
- *
- * A WiFiEventHandler defines a class that has methods that will be called back when a WiFi event is
- * detected.
- *
- * Typically this class is subclassed to provide implementations for the callbacks we want to handle.
- *
- * class MyHandler: public WiFiEventHandler {
- *   esp_err_t apStart() {
- *      ESP_LOGD(tag, "MyHandler(Class): apStart");
- *      return ESP_OK;
- *   }
- * }
- *
- * WiFi wifi;
- * MyHandler *eventHandler = new MyHandler();
- * wifi.setWifiEventHandler(eventHandler);
- * wifi.startAP("MYSSID", "password");
- *
- * The overridable functions are:
- * * esp_err_t apStaConnected()
- * * esp_err_t apStaDisconnected()
- * * esp_err_t apStart()
- * * esp_err_t apStop()
- * * esp_err_t staConnected()
- * * esp_err_t staDisconnected()
- * * esp_err_t staGotIp(system_event_sta_got_ip_t event_sta_got_ip)
- * * esp_err_t staStart()
- * * esp_err_t staStop()
- * * esp_err_t wifiReady()
- */
-
-#ifndef MAIN_WIFIEVENTHANDLER_H_
-#define MAIN_WIFIEVENTHANDLER_H_
-#include <esp_event.h>
-#include <esp_event_loop.h>
-
-/**
- * @brief %WiFi state event handler.
- *
- * Here is an example class that implements all the virtual functions that can be called
- * for events:
- *
- * @code{.cpp}
- * MyHandler::MyHandler() {
- * }
- *
- * MyHandler::~MyHandler() {
- * }
- *
- * esp_err_t MyHandler::apStart() {
- *   return ESP_OK;
- * }
- *
- * esp_err_t MyHandler::staConnected() {
- *   return ESP_OK;
- * }
- *
- * esp_err_t MyHandler::staDisconnected() {
- *   return ESP_OK;
- * }
- *
- * esp_err_t MyHandler::staStart() {
- *   return ESP_OK;
- * }
- *
- * esp_err_t MyHandler::staGotIp(system_event_sta_got_ip_t event_sta_got_ip) {
- *   return ESP_OK;
- * }
- *
- * esp_err_t MyHandler::wifiReady() {
- *   return ESP_OK;
- * }
- * @endcode
- */
-class WiFiEventHandler {
-public:
-	WiFiEventHandler();
-	virtual ~WiFiEventHandler();
-	system_event_cb_t getEventHandler();
-	virtual esp_err_t apStaConnected();
-	virtual esp_err_t apStaDisconnected();
-	virtual esp_err_t apStart();
-	virtual esp_err_t apStop();
-	virtual esp_err_t staConnected();
-	virtual esp_err_t staDisconnected();
-	virtual esp_err_t staGotIp(system_event_sta_got_ip_t event_sta_got_ip);
-	virtual esp_err_t staStart();
-	virtual esp_err_t staStop();
-	virtual esp_err_t wifiReady();
-
-	/**
-	 * Get the next WiFi event handler in the chain, if there is one.
-	 * @return The next WiFi event handler in the chain or nullptr if there is none.
-	 */
-	WiFiEventHandler *getNextHandler() {
-		return nextHandler;
-	}
-
-	/**
-	 * Set the next WiFi event handler in the chain.
-	 * @param [in] nextHandler The next WiFi event handler in the chain.
-	 */
-	void setNextHandler(WiFiEventHandler* nextHandler) {
-		this->nextHandler = nextHandler;
-	}
-
-private:
-	WiFiEventHandler *nextHandler = nullptr;
-	static esp_err_t eventHandler(void *ctx, system_event_t *event);
-};
-
-#endif /* MAIN_WIFIEVENTHANDLER_H_ */
diff --git a/components/cpp_utils/component.mk b/components/cpp_utils/component.mk
deleted file mode 100644
index 6952ed5..0000000
--- a/components/cpp_utils/component.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# Main component makefile.
-#
-# This Makefile can be left empty. By default, it will take the sources in the 
-# src/ directory, compile them and link them into lib(subdirectory_name).a 
-# in the build directory. This behaviour is entirely configurable,
-# please read the ESP-IDF documents if you need to do this.
-COMPONENT_ADD_INCLUDEDIRS=.
-
-## Uncomment the following line if we have an implementation of libcurl available to us.
-##CXXFLAGS+=-DESP_HAVE_CURL
-
-## Uncomment the following line to enable exception handling 
-#CXXFLAGS+=-fexceptions
-#CXXFLAGS+= -std=c++11
\ No newline at end of file
diff --git a/components/cpp_utils/mainpage.dox b/components/cpp_utils/mainpage.dox
deleted file mode 100644
index 3597471..0000000
--- a/components/cpp_utils/mainpage.dox
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * @mainpage ESP32 C++ Utility Classes
- * The ESP-IDF is the C language based libraries and functions available for working with the ESP32
- * device.  This ESP-IDF component provides a set of C++ classes that encapsulate and extend *some* of the
- * functions.
- *
- * The Github repository is [https://github.com/nkolban/esp32-snippets](https://github.com/nkolban/esp32-snippets).
- */
\ No newline at end of file
diff --git a/components/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino b/components/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino
deleted file mode 100644
index ed7fbf0..0000000
--- a/components/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * A BLE client example that is rich in capabilities.
- */
-
-#include "BLEDevice.h"
-//#include "BLEScan.h"
-
-// The remote service we wish to connect to.
-static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");
-// The characteristic of the remote service we are interested in.
-static BLEUUID    charUUID("0d563a58-196a-48ce-ace2-dfec78acc814");
-
-static BLEAddress *pServerAddress;
-static boolean doConnect = false;
-static boolean connected = false;
-static BLERemoteCharacteristic* pRemoteCharacteristic;
-
-static void notifyCallback(
-  BLERemoteCharacteristic* pBLERemoteCharacteristic,
-  uint8_t* pData,
-  size_t length,
-  bool isNotify) {
-    Serial.print("Notify callback for characteristic ");
-    Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
-    Serial.print(" of data length ");
-    Serial.println(length);
-}
-
-bool connectToServer(BLEAddress pAddress) {
-    Serial.print("Forming a connection to ");
-    Serial.println(pAddress.toString().c_str());
-    
-    BLEClient*  pClient  = BLEDevice::createClient();
-    Serial.println(" - Created client");
-
-    // Connect to the remove BLE Server.
-    pClient->connect(pAddress);
-    Serial.println(" - Connected to server");
-
-    // Obtain a reference to the service we are after in the remote BLE server.
-    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
-    if (pRemoteService == nullptr) {
-      Serial.print("Failed to find our service UUID: ");
-      Serial.println(serviceUUID.toString().c_str());
-      return false;
-    }
-
-
-    // Obtain a reference to the characteristic in the service of the remote BLE server.
-    pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
-    if (pRemoteCharacteristic == nullptr) {
-      Serial.print("Failed to find our characteristic UUID: ");
-      Serial.println(charUUID.toString().c_str());
-      return false;
-    }
-
-    // Read the value of the characteristic.
-    std::string value = pRemoteCharacteristic->readValue();
-    Serial.print("The characteristic value was: ");
-    Serial.println(value.c_str());
-
-    pRemoteCharacteristic->registerForNotify(notifyCallback);
-}
-/**
- * Scan for BLE servers and find the first one that advertises the service we are looking for.
- */
-class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
- /**
-   * Called for each advertising BLE server.
-   */
-  void onResult(BLEAdvertisedDevice advertisedDevice) {
-    Serial.print("BLE Advertised Device found: ");
-    Serial.println(advertisedDevice.toString().c_str());
-
-    // We have found a device, let us now see if it contains the service we are looking for.
-    if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) {
-
-      // 
-      Serial.print("Found our device!  address: "); 
-      advertisedDevice.getScan()->stop();
-
-      pServerAddress = new BLEAddress(advertisedDevice.getAddress());
-      doConnect = true;
-
-    } // Found our server
-  } // onResult
-}; // MyAdvertisedDeviceCallbacks
-
-
-void setup() {
-  Serial.begin(115200);
-  Serial.println("Starting Arduino BLE Client application...");
-  BLEDevice::init("");
-
-  // Retrieve a Scanner and set the callback we want to use to be informed when we
-  // have detected a new device.  Specify that we want active scanning and start the
-  // scan to run for 30 seconds.
-  BLEScan* pBLEScan = BLEDevice::getScan();
-  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
-  pBLEScan->setActiveScan(true);
-  pBLEScan->start(30);
-} // End of setup.
-
-
-// This is the Arduino main loop function.
-void loop() {
-
-  // If the flag "doConnect" is true then we have scanned for and found the desired
-  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are 
-  // connected we set the connected flag to be true.
-  if (doConnect == true) {
-    if (connectToServer(*pServerAddress)) {
-      Serial.println("We are now connected to the BLE Server.");
-      connected = true;
-    } else {
-      Serial.println("We have failed to connect to the server; there is nothin more we will do.");
-    }
-    doConnect = false;
-  }
-
-  // If we are connected to a peer BLE Server, update the characteristic each time we are reached
-  // with the current time since boot.
-  if (connected) {
-    String newValue = "Time since boot: " + String(millis()/1000);
-    Serial.println("Setting new characteristic value to \"" + newValue + "\"");
-    
-    // Set the characteristic's value to be the array of bytes that is actually a string.
-    pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
-  }
-  
-  delay(1000); // Delay a second between loops.
-} // End of loop
diff --git a/components/cpp_utils/tests/BLETests/Arduino/BLE_notify/BLE_notify.ino b/components/cpp_utils/tests/BLETests/Arduino/BLE_notify/BLE_notify.ino
deleted file mode 100644
index 44506c2..0000000
--- a/components/cpp_utils/tests/BLETests/Arduino/BLE_notify/BLE_notify.ino
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-    Video: https://www.youtube.com/watch?v=oCMOYS71NIU
-    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
-    Ported to Arduino ESP32 by Evandro Copercini
-
-   Create a BLE server that, once we receive a connection, will send periodic notifications.
-   The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
-   And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8
-
-   The design of creating the BLE server is:
-   1. Create a BLE Server
-   2. Create a BLE Service
-   3. Create a BLE Characteristic on the Service
-   4. Create a BLE Descriptor on the characteristic
-   5. Start the service.
-   6. Start advertising.
-
-   A connect hander associated with the server starts a background task that performs notification
-   every couple of seconds.
-*/
-#include <BLEDevice.h>
-#include <BLEServer.h>
-#include <BLEUtils.h>
-#include <BLE2902.h>
-
-BLECharacteristic *pCharacteristic;
-bool deviceConnected = false;
-uint8_t value = 0;
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
-#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
-
-
-class MyServerCallbacks: public BLEServerCallbacks {
-    void onConnect(BLEServer* pServer) {
-      deviceConnected = true;
-    };
-
-    void onDisconnect(BLEServer* pServer) {
-      deviceConnected = false;
-    }
-};
-
-
-
-void setup() {
-  Serial.begin(115200);
-
-  // Create the BLE Device
-  BLEDevice::init("MyESP32");
-
-  // Create the BLE Server
-  BLEServer *pServer = new BLEServer();
-  pServer->setCallbacks(new MyServerCallbacks());
-
-  // Create the BLE Service
-  BLEService *pService = pServer->createService(SERVICE_UUID);
-
-  // Create a BLE Characteristic
-  pCharacteristic = pService->createCharacteristic(
-                      CHARACTERISTIC_UUID,
-                      BLECharacteristic::PROPERTY_READ   |
-                      BLECharacteristic::PROPERTY_WRITE  |
-                      BLECharacteristic::PROPERTY_NOTIFY |
-                      BLECharacteristic::PROPERTY_INDICATE
-                    );
-
-  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
-  // Create a BLE Descriptor
-  pCharacteristic->addDescriptor(new BLE2902());
-
-  // Start the service
-  pService->start();
-
-  // Start advertising
-  pServer->getAdvertising()->start();
-  Serial.println("Waiting a client connection to notify...");
-}
-
-void loop() {
-
-  if (deviceConnected) {
-    Serial.printf("*** NOTIFY: %d ***\n", value);
-    pCharacteristic->setValue(&value, 1);
-    pCharacteristic->notify();
-    //pCharacteristic->indicate();
-    value++;
-  }
-  delay(2000);
-}
\ No newline at end of file
diff --git a/components/cpp_utils/tests/BLETests/Arduino/BLE_scan/BLE_scan.ino b/components/cpp_utils/tests/BLETests/Arduino/BLE_scan/BLE_scan.ino
deleted file mode 100644
index ef7d892..0000000
--- a/components/cpp_utils/tests/BLETests/Arduino/BLE_scan/BLE_scan.ino
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-   Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
-   Ported to Arduino ESP32 by Evandro Copercini
-*/
-
-#include <BLEDevice.h>
-#include <BLEUtils.h>
-#include <BLEScan.h>
-#include <BLEAdvertisedDevice.h>
-
-int scanTime = 30; //In seconds
-
-class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
-    void onResult(BLEAdvertisedDevice advertisedDevice) {
-      Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
-    }
-};
-
-void setup() {
-  Serial.begin(115200);
-  Serial.println("Scanning...");
-
-  BLEDevice::init("");
-  BLEScan* pBLEScan = BLEDevice::getScan(); //create new scan
-  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
-  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
-  BLEScanResults foundDevices = pBLEScan->start(scanTime);
-  Serial.print("Devices found: ");
-  Serial.println(foundDevices.getCount());
-  Serial.println("Scan done!");
-}
-
-void loop() {
-  // put your main code here, to run repeatedly:
-  delay(2000);
-}
\ No newline at end of file
diff --git a/components/cpp_utils/tests/BLETests/Arduino/BLE_server/BLE_server.ino b/components/cpp_utils/tests/BLETests/Arduino/BLE_server/BLE_server.ino
deleted file mode 100644
index 45ebf99..0000000
--- a/components/cpp_utils/tests/BLETests/Arduino/BLE_server/BLE_server.ino
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
-    Ported to Arduino ESP32 by Evandro Copercini
-*/
-
-#include <BLEDevice.h>
-#include <BLEUtils.h>
-#include <BLEServer.h>
-
-BLEDevice ble;
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
-#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
-
-void setup() {
-  Serial.begin(115200);
-  Serial.println("Starting BLE work!");
-
-  ble.init("MyESP32");
-  BLEServer *pServer = new BLEServer();
-  BLEService *pService = pServer->createService(SERVICE_UUID);
-  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
-                                         CHARACTERISTIC_UUID,
-                                         BLECharacteristic::PROPERTY_READ |
-                                         BLECharacteristic::PROPERTY_WRITE
-                                       );
-
-  pCharacteristic->setValue("Hello World says Neil");
-  pService->start();
-  BLEAdvertising *pAdvertising = pServer->getAdvertising();
-  pAdvertising->start();
-  Serial.println("Characteristic defined! Now you can read it in your phone!");
-}
-
-void loop() {
-  // put your main code here, to run repeatedly:
-  delay(2000);
-}
\ No newline at end of file
diff --git a/components/cpp_utils/tests/BLETests/Arduino/BLE_uart/BLE_uart.ino b/components/cpp_utils/tests/BLETests/Arduino/BLE_uart/BLE_uart.ino
deleted file mode 100644
index a8ab2d7..0000000
--- a/components/cpp_utils/tests/BLETests/Arduino/BLE_uart/BLE_uart.ino
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-    Video: https://www.youtube.com/watch?v=oCMOYS71NIU
-    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
-    Ported to Arduino ESP32 by Evandro Copercini
-
-   Create a BLE server that, once we receive a connection, will send periodic notifications.
-   The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
-   Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE" 
-   Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with  "NOTIFY"
-
-   The design of creating the BLE server is:
-   1. Create a BLE Server
-   2. Create a BLE Service
-   3. Create a BLE Characteristic on the Service
-   4. Create a BLE Descriptor on the characteristic
-   5. Start the service.
-   6. Start advertising.
-
-   In this example rxValue is the data received (only accessible inside that function).
-   And txValue is the data to be sent, in this example just a byte incremented every second. 
-*/
-#include <BLEDevice.h>
-#include <BLEServer.h>
-#include <BLEUtils.h>
-#include <BLE2902.h>
-
-BLECharacteristic *pCharacteristic;
-bool deviceConnected = false;
-uint8_t txValue = 0;
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
-#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
-#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
-
-
-class MyServerCallbacks: public BLEServerCallbacks {
-    void onConnect(BLEServer* pServer) {
-      deviceConnected = true;
-    };
-
-    void onDisconnect(BLEServer* pServer) {
-      deviceConnected = false;
-    }
-};
-
-class MyCallbacks: public BLECharacteristicCallbacks {
-    void onWrite(BLECharacteristic *pCharacteristic) {
-      std::string rxValue = pCharacteristic->getValue();
-
-      if (rxValue.length() > 0) {
-        Serial.println("*********");
-        Serial.print("Received Value: ");
-        for (int i = 0; i < rxValue.length(); i++)
-          Serial.print(rxValue[i]);
-
-        Serial.println();
-        Serial.println("*********");
-      }
-    }
-};
-
-
-void setup() {
-  Serial.begin(115200);
-
-  // Create the BLE Device
-  BLEDevice::init("UART Service");
-
-  // Create the BLE Server
-  BLEServer *pServer = new BLEServer();
-  pServer->setCallbacks(new MyServerCallbacks());
-
-  // Create the BLE Service
-  BLEService *pService = pServer->createService(SERVICE_UUID);
-
-  // Create a BLE Characteristic
-  pCharacteristic = pService->createCharacteristic(
-                      CHARACTERISTIC_UUID_TX,
-                      BLECharacteristic::PROPERTY_NOTIFY
-                    );
-                      
-  pCharacteristic->addDescriptor(new BLE2902());
-
-  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
-                                         CHARACTERISTIC_UUID_RX,
-                                         BLECharacteristic::PROPERTY_WRITE
-                                       );
-
-  pCharacteristic->setCallbacks(new MyCallbacks());
-
-  // Start the service
-  pService->start();
-
-  // Start advertising
-  pServer->getAdvertising()->start();
-  Serial.println("Waiting a client connection to notify...");
-}
-
-void loop() {
-
-  if (deviceConnected) {
-    Serial.printf("*** Sent Value: %d ***\n", txValue);
-    pCharacteristic->setValue(&txValue, 1);
-    pCharacteristic->notify();
-    txValue++;
-  }
-  delay(1000);
-}
diff --git a/components/cpp_utils/tests/BLETests/Arduino/BLE_write/BLE_write.ino b/components/cpp_utils/tests/BLETests/Arduino/BLE_write/BLE_write.ino
deleted file mode 100644
index ed5ebc6..0000000
--- a/components/cpp_utils/tests/BLETests/Arduino/BLE_write/BLE_write.ino
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
-    Ported to Arduino ESP32 by Evandro Copercini
-*/
-
-#include <BLEDevice.h>
-#include <BLEUtils.h>
-#include <BLEServer.h>
-
-BLEDevice ble;
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
-#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
-
-
-class MyCallbacks: public BLECharacteristicCallbacks {
-    void onWrite(BLECharacteristic *pCharacteristic) {
-      std::string value = pCharacteristic->getValue();
-
-      if (value.length() > 0) {
-        Serial.println("*********");
-        Serial.print("New value: ");
-        for (int i = 0; i < value.length(); i++)
-          Serial.print(value[i]);
-
-        Serial.println();
-        Serial.println("*********");
-      }
-    }
-};
-
-void setup() {
-  Serial.begin(115200);
-
-  Serial.println("1- Download and install an BLE scanner app in your phone");
-  Serial.println("2- Scan for BLE devices in the app");
-  Serial.println("3- Connect to MyESP32");
-  Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
-  Serial.println("5- See the magic =)");
-
-  //ble.begin("MyESP32");
-  ble.init("MyESP32");
-  BLEServer *pServer = new BLEServer();
-
-  BLEService *pService = pServer->createService(SERVICE_UUID);
-
-  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
-                                         CHARACTERISTIC_UUID,
-                                         BLECharacteristic::PROPERTY_READ |
-                                         BLECharacteristic::PROPERTY_WRITE
-                                       );
-
-  pCharacteristic->setCallbacks(new MyCallbacks());
-
-  pCharacteristic->setValue("Hello World");
-  pService->start();
-
-  BLEAdvertising *pAdvertising = pServer->getAdvertising();
-  pAdvertising->start();
-}
-
-void loop() {
-  // put your main code here, to run repeatedly:
-  delay(2000);
-}
\ No newline at end of file
diff --git a/components/cpp_utils/tests/BLETests/README.md b/components/cpp_utils/tests/BLETests/README.md
deleted file mode 100644
index dd2fc4b..0000000
--- a/components/cpp_utils/tests/BLETests/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Sample C++ BLE fragments
-Here we find a set of C++ BLE samples illustrating different aspects of the C++ BLE library. 
\ No newline at end of file
diff --git a/components/cpp_utils/tests/BLETests/Sample-MLE-15.cpp b/components/cpp_utils/tests/BLETests/Sample-MLE-15.cpp
deleted file mode 100644
index 5e5b2d2..0000000
--- a/components/cpp_utils/tests/BLETests/Sample-MLE-15.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "BLEUtils.h"
-#include "BLEScan.h"
-#include <esp_log.h>
-#include <string>
-
-#include "BLEDevice.h"
-#include "BLEAdvertisedDevice.h"
-#include "BLEClient.h"
-#include "sdkconfig.h"
-#include "Task.h"
-
-static const char LOG_TAG[] = "Sample-MLE-15";
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-
-
-static BLEUUID serviceUUID((uint16_t)0x1802);
-static BLEUUID    charUUID((uint16_t)0x2a06);
-static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify) {
-
-}
-
-class MyClient: public Task {
-	void run(void *data) {
-		BLEAddress* pAddress = (BLEAddress *)data;
-		BLEClient*  pClient = BLEDevice::createClient();
-
-
-		pClient->connect(*pAddress);
-		pClient->getServices();
-
-		BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
-		if (pRemoteService == nullptr) {
-			ESP_LOGD(LOG_TAG, "Failed to find our service UUID: %s", serviceUUID.toString().c_str());
-			return;
-		}
-
-		pRemoteService->getCharacteristics();
-		BLERemoteCharacteristic* pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
-		if (pRemoteCharacteristic == nullptr) {
-			ESP_LOGD(LOG_TAG, "Failed to find our characteristic UUID: %s", charUUID.toString().c_str());
-			return;
-		}
-		pRemoteCharacteristic->readValue();
-
-		pRemoteCharacteristic->writeValue("123");
-		pRemoteCharacteristic->registerForNotify(notifyCallback);
-		pClient->disconnect();
-
-		ESP_LOGD(LOG_TAG, "%s", pClient->toString().c_str());
-		ESP_LOGD(LOG_TAG, "-- End of task");
-	}
-};
-
-
-
-static void run() {
-	ESP_LOGD(LOG_TAG, "MLE-15 sample starting");
-	BLEDevice::init("");
-	BLEClient*  pClient = BLEDevice::createClient();
-
-
-	pClient->connect(BLEAddress("ff:ff:45:19:14:80"));
-	BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
-	if (pRemoteService == nullptr) {
-		ESP_LOGD(LOG_TAG, "Failed to find our service UUID: %s", serviceUUID.toString().c_str());
-		return;
-	}
-
-	BLERemoteCharacteristic* pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
-	if (pRemoteCharacteristic == nullptr) {
-		ESP_LOGD(LOG_TAG, "Failed to find our characteristic UUID: %s", charUUID.toString().c_str());
-		return;
-	}
-
-	pRemoteCharacteristic->writeValue((uint8_t)1);
-
-	//BLEClient *pClient = BLE::createClient();
-	//pClient->setClientCallbacks(new MyClientCallbacks());
-	//pClient->connect(BLEAddress("00:00:00:00:00:00"));
-
-}
-
-void Sample_MLE_15(void)
-{
-	run();
-} // app_main
diff --git a/components/cpp_utils/tests/BLETests/Sample1.cpp b/components/cpp_utils/tests/BLETests/Sample1.cpp
deleted file mode 100644
index 88f6b3d..0000000
--- a/components/cpp_utils/tests/BLETests/Sample1.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "BLEUtils.h"
-#include "BLEServer.h"
-#include <esp_log.h>
-#include <string>
-
-#include "BLEDevice.h"
-#include "sdkconfig.h"
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
-#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
-
-static void run() {
-	BLEDevice::init("MYDEVICE");
-
-	BLEServer *pServer = new BLEServer();
-
-	BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID));
-
-	BLECharacteristic *pCharacteristic = pService->createCharacteristic(
-		BLEUUID(CHARACTERISTIC_UUID),
-		BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
-	);
-
-	pCharacteristic->setValue("Hello World says Neil");
-
-	pService->start();
-
-	BLEAdvertising *pAdvertising = pServer->getAdvertising();
-	pAdvertising->start();
-}
-
-void Sample1(void)
-{
-	run();
-} // app_main
diff --git a/components/cpp_utils/tests/BLETests/SampleClient.cpp b/components/cpp_utils/tests/BLETests/SampleClient.cpp
deleted file mode 100644
index 31a65bd..0000000
--- a/components/cpp_utils/tests/BLETests/SampleClient.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * Create a sample BLE client that connects to a BLE server and then retrieves the current
- * characteristic value.  It will then periodically update the value of the characteristic on the
- * remote server with the current time since boot.
- */
-#include <esp_log.h>
-#include <string>
-#include <sstream>
-#include <sys/time.h>
-#include "BLEDevice.h"
-
-#include "BLEAdvertisedDevice.h"
-#include "BLEClient.h"
-#include "BLEScan.h"
-#include "BLEUtils.h"
-#include "Task.h"
-
-#include "sdkconfig.h"
-
-static const char* LOG_TAG = "SampleClient";
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-// The remote service we wish to connect to.
-static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");
-// The characteristic of the remote service we are interested in.
-static BLEUUID    charUUID("0d563a58-196a-48ce-ace2-dfec78acc814");
-
-
-/**
- * Become a BLE client to a remote BLE server.  We are passed in the address of the BLE server
- * as the input parameter when the task is created.
- */
-class MyClient: public Task {
-	void run(void* data) {
-		BLEAddress* pAddress = (BLEAddress*)data;
-		BLEClient*  pClient  = BLEDevice::createClient();
-
-		// Connect to the remove BLE Server.
-		pClient->connect(*pAddress);
-
-		// Obtain a reference to the service we are after in the remote BLE server.
-		BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
-		if (pRemoteService == nullptr) {
-			ESP_LOGD(LOG_TAG, "Failed to find our service UUID: %s", serviceUUID.toString().c_str());
-			return;
-		}
-
-
-		// Obtain a reference to the characteristic in the service of the remote BLE server.
-		BLERemoteCharacteristic* pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
-		if (pRemoteCharacteristic == nullptr) {
-			ESP_LOGD(LOG_TAG, "Failed to find our characteristic UUID: %s", charUUID.toString().c_str());
-			return;
-		}
-
-		// Read the value of the characteristic.
-		std::string value = pRemoteCharacteristic->readValue();
-		ESP_LOGD(LOG_TAG, "The characteristic value was: %s", value.c_str());
-
-		while(1) {
-			// Set a new value of the characteristic
-			ESP_LOGD(LOG_TAG, "Setting the new value");
-			std::ostringstream stringStream;
-			struct timeval tv;
-			gettimeofday(&tv, nullptr);
-			stringStream << "Time since boot: " << tv.tv_sec;
-			pRemoteCharacteristic->writeValue(stringStream.str());
-
-			FreeRTOS::sleep(1000);
-		}
-
-		pClient->disconnect();
-
-		ESP_LOGD(LOG_TAG, "%s", pClient->toString().c_str());
-		ESP_LOGD(LOG_TAG, "-- End of task");
-	} // run
-}; // MyClient
-
-
-/**
- * Scan for BLE servers and find the first one that advertises the service we are looking for.
- */
-class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
-	/**
-	 * Called for each advertising BLE server.
-	 */
-	void onResult(BLEAdvertisedDevice advertisedDevice) {
-		ESP_LOGD(LOG_TAG, "Advertised Device: %s", advertisedDevice.toString().c_str());
-
-		if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) {
-			advertisedDevice.getScan()->stop();
-
-			ESP_LOGD(LOG_TAG, "Found our device!  address: %s", advertisedDevice.getAddress().toString().c_str());
-			MyClient* pMyClient = new MyClient();
-			pMyClient->setStackSize(18000);
-			pMyClient->start(new BLEAddress(*advertisedDevice.getAddress().getNative()));
-		} // Found our server
-	} // onResult
-}; // MyAdvertisedDeviceCallbacks
-
-
-/**
- * Perform the work of a sample BLE client.
- */
-void SampleClient(void) {
-	ESP_LOGD(LOG_TAG, "Scanning sample starting");
-	BLEDevice::init("");
-	BLEScan *pBLEScan = BLEDevice::getScan();
-	pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
-	pBLEScan->setActiveScan(true);
-	pBLEScan->start(30);
-} // SampleClient
diff --git a/components/cpp_utils/tests/BLETests/SampleClient_Notify.cpp b/components/cpp_utils/tests/BLETests/SampleClient_Notify.cpp
deleted file mode 100644
index 5ebdbf4..0000000
--- a/components/cpp_utils/tests/BLETests/SampleClient_Notify.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * Create a sample BLE client that connects to a BLE server and then waits for server generated
- * notifications and logs them when they arrive.
- */
-#include <esp_log.h>
-#include <string>
-#include <sstream>
-#include <sys/time.h>
-#include "BLEDevice.h"
-
-#include "BLEAdvertisedDevice.h"
-#include "BLEClient.h"
-#include "BLEScan.h"
-#include "BLEUtils.h"
-#include "Task.h"
-
-#include "sdkconfig.h"
-
-static const char* LOG_TAG = "SampleClient_Notify";
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-// The remote service we wish to connect to.
-static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");
-// The characteristic of the remote service we are interested in.
-static BLEUUID    charUUID("0d563a58-196a-48ce-ace2-dfec78acc814");
-
-static void notifyCallback(
-	BLERemoteCharacteristic* pBLERemoteCharacteristic,
-	uint8_t* pData,
-	size_t length,
-	bool isNotify) {
-		ESP_LOGD(LOG_TAG, "Notify callback for characteristic %s of data length %d",
-				pBLERemoteCharacteristic->getUUID().toString().c_str(), length);
-}
-
-/**
- * Become a BLE client to a remote BLE server.  We are passed in the address of the BLE server
- * as the input parameter when the task is created.
- */
-class MyClient: public Task {
-	void run(void* data) {
-		BLEAddress* pAddress = (BLEAddress*)data;
-		BLEClient*  pClient  = BLEDevice::createClient();
-
-		// Connect to the remove BLE Server.
-		pClient->connect(*pAddress);
-
-		// Obtain a reference to the service we are after in the remote BLE server.
-		BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
-		if (pRemoteService == nullptr) {
-			ESP_LOGD(LOG_TAG, "Failed to find our service UUID: %s", serviceUUID.toString().c_str());
-			return;
-		}
-
-
-		// Obtain a reference to the characteristic in the service of the remote BLE server.
-		BLERemoteCharacteristic* pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
-		if (pRemoteCharacteristic == nullptr) {
-			ESP_LOGD(LOG_TAG, "Failed to find our characteristic UUID: %s", charUUID.toString().c_str());
-			return;
-		}
-
-		// Read the value of the characteristic.
-		std::string value = pRemoteCharacteristic->readValue();
-		ESP_LOGD(LOG_TAG, "The characteristic value was: %s", value.c_str());
-
-		pRemoteCharacteristic->registerForNotify(notifyCallback);
-
-		ESP_LOGD(LOG_TAG, "%s", pClient->toString().c_str());
-		ESP_LOGD(LOG_TAG, "-- End of task");
-	} // run
-}; // MyClient
-
-
-/**
- * Scan for BLE servers and find the first one that advertises the service we are looking for.
- */
-class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
-	/**
-	 * Called for each advertising BLE server.
-	 */
-	void onResult(BLEAdvertisedDevice advertisedDevice) {
-		ESP_LOGD(LOG_TAG, "Advertised Device: %s", advertisedDevice.toString().c_str());
-
-		if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) {
-			advertisedDevice.getScan()->stop();
-
-			ESP_LOGD(LOG_TAG, "Found our device!  address: %s", advertisedDevice.getAddress().toString().c_str());
-			MyClient* pMyClient = new MyClient();
-			pMyClient->setStackSize(18000);
-			pMyClient->start(new BLEAddress(*advertisedDevice.getAddress().getNative()));
-		} // Found our server
-	} // onResult
-}; // MyAdvertisedDeviceCallbacks
-
-
-/**
- * Perform the work of a sample BLE client.
- */
-void SampleClient_Notify(void) {
-	ESP_LOGD(LOG_TAG, "SampleClient_Notify starting");
-	BLEDevice::init("");
-	BLEScan *pBLEScan = BLEDevice::getScan();
-	pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
-	pBLEScan->setActiveScan(true);
-	pBLEScan->start(30);
-} // SampleClient
diff --git a/components/cpp_utils/tests/BLETests/SampleNotify.cpp b/components/cpp_utils/tests/BLETests/SampleNotify.cpp
deleted file mode 100644
index 738aacb..0000000
--- a/components/cpp_utils/tests/BLETests/SampleNotify.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Create a BLE server that, once we receive a connection, will send periodic notifications.
- * The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
- * And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8
- *
- * The design of creating the BLE server is:
- * 1. Create a BLE Server
- * 2. Create a BLE Service
- * 3. Create a BLE Characteristic on the Service
- * 4. Create a BLE Descriptor on the characteristic
- * 5. Start the service.
- * 6. Start advertising.
- *
- * A connect hander associated with the server starts a background task that performs notification
- * every couple of seconds.
- *
- * @author: Neil Kolban, July 2017
- *
- */
-#include "sdkconfig.h"
-
-#include <esp_log.h>
-#include <string>
-#include <sstream>
-#include <sys/time.h>
-#include "BLEDevice.h"
-
-#include "BLEServer.h"
-#include "BLEUtils.h"
-#include "BLE2902.h"
-#include "Task.h"
-
-
-static char LOG_TAG[] = "SampleNotify";
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
-#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
-
-BLECharacteristic *pCharacteristic;
-
-class MyNotifyTask: public Task {
-	void run(void *data) {
-		uint8_t value = 0;
-		while(1) {
-			delay(2000);
-			ESP_LOGD(LOG_TAG, "*** NOTIFY: %d ***", value);
-			pCharacteristic->setValue(&value, 1);
-			pCharacteristic->notify();
-			//pCharacteristic->indicate();
-			value++;
-		} // While 1
-	} // run
-}; // MyNotifyTask
-
-MyNotifyTask *pMyNotifyTask;
-
-class MyServerCallbacks: public BLEServerCallbacks {
-	void onConnect(BLEServer* pServer) {
-		pMyNotifyTask->start();
-	};
-
-	void onDisconnect(BLEServer* pServer) {
-		pMyNotifyTask->stop();
-	}
-};
-
-static void run() {
-	pMyNotifyTask = new MyNotifyTask();
-	pMyNotifyTask->setStackSize(8000);
-
-	// Create the BLE Device
-	BLEDevice::init("MYDEVICE");
-
-	// Create the BLE Server
-	BLEServer *pServer = new BLEServer();
-	pServer->setCallbacks(new MyServerCallbacks());
-
-	// Create the BLE Service
-	BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID));
-
-	// Create a BLE Characteristic
-	pCharacteristic = pService->createCharacteristic(
-		BLEUUID(CHARACTERISTIC_UUID),
-		BLECharacteristic::PROPERTY_READ   |
-		BLECharacteristic::PROPERTY_WRITE  |
-		BLECharacteristic::PROPERTY_NOTIFY |
-		BLECharacteristic::PROPERTY_INDICATE
-	);
-
-	// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
-	// Create a BLE Descriptor
-	pCharacteristic->addDescriptor(new BLE2902());
-
-	// Start the service
-	pService->start();
-
-	// Start advertising
-	pServer->getAdvertising()->start();
-}
-
-void SampleNotify(void)
-{
-	run();
-} // app_main
diff --git a/components/cpp_utils/tests/BLETests/SampleRead.cpp b/components/cpp_utils/tests/BLETests/SampleRead.cpp
deleted file mode 100644
index e030785..0000000
--- a/components/cpp_utils/tests/BLETests/SampleRead.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Create a BLE Server that when it receive a read request from a BLE client for the value
- * of a characteristic will have the BLECharacteristicCallback invoked in its onRead() method.
- * This can be then used to set the value of the corresponding characteristic which will then
- * be returned back to the client.
- */
-#include "BLEUtils.h"
-#include "BLEServer.h"
-#include <esp_log.h>
-#include <string>
-#include <sys/time.h>
-#include <sstream>
-#include "BLEDevice.h"
-
-#include "sdkconfig.h"
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
-#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
-
-static uint8_t  SERVICE_UUID_BIN[] = {0x4f, 0xaf, 0xc2, 0x01, 0x1f, 0xb5, 0x45, 0x9e, 0x8f, 0xcc, 0xc5, 0xc9, 0xc3, 0x31, 0x91, 0x4b};
-
-class MyCallbackHandler: public BLECharacteristicCallbacks {
-	void onRead(BLECharacteristic *pCharacteristic) {
-		struct timeval tv;
-		gettimeofday(&tv, nullptr);
-		std::ostringstream os;
-		os << "Time: " << tv.tv_sec;
-		pCharacteristic->setValue(os.str());
-	}
-};
-
-static void run() {
-	BLEDevice::init("MYDEVICE");
-	BLEServer *pServer = new BLEServer();
-
-	BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID_BIN, 16, true));
-
-	BLECharacteristic *pCharacteristic = pService->createCharacteristic(
-		BLEUUID(CHARACTERISTIC_UUID),
-		BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
-	);
-
-	pCharacteristic->setCallbacks(new MyCallbackHandler());
-
-	pCharacteristic->setValue("Hello World");
-
-	pService->start();
-
-	BLEAdvertising *pAdvertising = pServer->getAdvertising();
-	pAdvertising->start();
-}
-
-void SampleRead(void)
-{
-	run();
-} // app_main
diff --git a/components/cpp_utils/tests/BLETests/SampleScan.cpp b/components/cpp_utils/tests/BLETests/SampleScan.cpp
deleted file mode 100644
index 299bf5b..0000000
--- a/components/cpp_utils/tests/BLETests/SampleScan.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Perform scanning for BLE advertised servers.
- */
-#include "BLEUtils.h"
-#include "BLEScan.h"
-#include <esp_log.h>
-#include <string>
-
-#include "BLEDevice.h"
-#include "BLEAdvertisedDevice.h"
-#include "sdkconfig.h"
-
-static const char LOG_TAG[] = "SampleScan";
-
-class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
-	void onResult(BLEAdvertisedDevice advertisedDevice) {
-		ESP_LOGD(LOG_TAG, "Advertised Device: %s", advertisedDevice.toString().c_str());
-	}
-};
-
-static void run() {
-	ESP_LOGD(LOG_TAG, "Scanning sample starting");
-	BLEDevice::init("");
-	BLEScan* pBLEScan = BLEDevice::getScan();
-	pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
-	pBLEScan->setActiveScan(true);
-	BLEScanResults scanResults = pBLEScan->start(30);
-	ESP_LOGD(LOG_TAG, "We found %d devices", scanResults.getCount());
-	ESP_LOGD(LOG_TAG, "Scanning sample ended");
-}
-
-void SampleScan(void)
-{
-	run();
-} // app_main
diff --git a/components/cpp_utils/tests/BLETests/SampleServer.cpp b/components/cpp_utils/tests/BLETests/SampleServer.cpp
deleted file mode 100644
index ad44d05..0000000
--- a/components/cpp_utils/tests/BLETests/SampleServer.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Create a new BLE server.
- */
-#include "BLEUtils.h"
-#include "BLEServer.h"
-#include "BLE2902.h"
-#include <esp_log.h>
-#include <string>
-#include <Task.h>
-#include "BLEDevice.h"
-
-#include "sdkconfig.h"
-
-static char LOG_TAG[] = "SampleServer";
-
-class MainBLEServer: public Task {
-	void run(void *data) {
-		ESP_LOGD(LOG_TAG, "Starting BLE work!");
-
-		BLEDevice::init("MYDEVICE");
-		BLEServer* pServer = new BLEServer();
-
-		BLEService* pService = pServer->createService(BLEUUID((uint16_t)0x1234));
-
-		BLECharacteristic* pCharacteristic = pService->createCharacteristic(
-			BLEUUID((uint16_t)0x99AA),
-			BLECharacteristic::PROPERTY_BROADCAST | BLECharacteristic::PROPERTY_READ  |
-			BLECharacteristic::PROPERTY_NOTIFY    | BLECharacteristic::PROPERTY_WRITE |
-			BLECharacteristic::PROPERTY_INDICATE
-		);
-
-
-		pCharacteristic->setValue("Hello World!");
-
-		BLE2902* p2902Descriptor = new BLE2902();
-		p2902Descriptor->setNotifications(true);
-		pCharacteristic->addDescriptor(p2902Descriptor);
-
-		pService->start();
-
-		BLEAdvertising* pAdvertising = pServer->getAdvertising();
-		pAdvertising->setServiceUUID(pService->getUUID().to128());
-		pAdvertising->start();
-
-		ESP_LOGD(LOG_TAG, "Advertising started!");
-		delay(1000000);
-	}
-};
-
-
-void SampleServer(void)
-{
-	esp_log_level_set("*", ESP_LOG_DEBUG);
-	MainBLEServer* pMainBleServer = new MainBLEServer();
-	pMainBleServer->setStackSize(20000);
-	pMainBleServer->start();
-
-} // app_main
diff --git a/components/cpp_utils/tests/BLETests/SampleWrite.cpp b/components/cpp_utils/tests/BLETests/SampleWrite.cpp
deleted file mode 100644
index 47616dd..0000000
--- a/components/cpp_utils/tests/BLETests/SampleWrite.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Create a BLE Server such that when a client connects and requests a change to the characteristic
- * value, the callback associated with the server will be invoked such that the server can perform
- * some action based on the new value.  The action in this sample is merely to log the new value to
- * the console.
- */
-#include "BLEUtils.h"
-#include "BLEServer.h"
-#include <esp_log.h>
-#include <string>
-#include <sys/time.h>
-#include <sstream>
-#include "BLEDevice.h"
-
-#include "sdkconfig.h"
-
-static char LOG_TAG[] = "SampleWrite";
-
-// See the following for generating UUIDs:
-// https://www.uuidgenerator.net/
-
-#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
-#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
-
-class MyCallbacks: public BLECharacteristicCallbacks {
-	void onWrite(BLECharacteristic *pCharacteristic) {
-		std::string value = pCharacteristic->getValue();
-		if (value.length() > 0) {
-				ESP_LOGD(LOG_TAG, "*********");
-				ESP_LOGD(LOG_TAG, "New value: %.2x", value[0]);
-				ESP_LOGD(LOG_TAG, "*********");
-			}
-		}
-};
-
-
-static void run() {
-	BLEDevice::init("MYDEVICE");
-	BLEServer *pServer = new BLEServer();
-
-	BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID));
-
-	BLECharacteristic *pCharacteristic = pService->createCharacteristic(
-		BLEUUID(CHARACTERISTIC_UUID),
-		BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
-	);
-
-	pCharacteristic->setCallbacks(new MyCallbacks());
-
-	pCharacteristic->setValue("Hello World");
-
-	pService->start();
-
-	BLEAdvertising *pAdvertising = pServer->getAdvertising();
-	pAdvertising->start();
-}
-
-
-void SampleWrite(void)
-{
-	run();
-} // app_main
diff --git a/components/cpp_utils/tests/BLETests/main.cpp b/components/cpp_utils/tests/BLETests/main.cpp
deleted file mode 100644
index 1ddedb2..0000000
--- a/components/cpp_utils/tests/BLETests/main.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Main file for running the BLE samples.
- */
-extern "C" {
-	void app_main(void);
-}
-
-
-// The list of sample entry points.
-void SampleServer(void);
-void Sample1(void);
-void SampleRead(void);
-void SampleWrite(void);
-void SampleScan(void);
-void SampleNotify(void);
-void SampleClient_Notify(void);
-void SampleClient(void);
-void Sample_MLE_15(void);
-
-
-//
-// Un-comment ONE of the following
-//            ---
-void app_main(void) {
-	//SampleServer();
-	//Sample1();
-	//SampleRead();
-	//SampleWrite();
-	//SampleScan();
-	//SampleNotify();
-	//SampleClient();
-	SampleClient_Notify();
-	//Sample_MLE_15();
-} // app_main
diff --git a/components/cpp_utils/tests/MFRC522/DumpInfo.cpp b/components/cpp_utils/tests/MFRC522/DumpInfo.cpp
deleted file mode 100644
index 87aca27..0000000
--- a/components/cpp_utils/tests/MFRC522/DumpInfo.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * --------------------------------------------------------------------------------------------------------------------
- * Example sketch/program showing how to read data from a PICC to serial.
- * --------------------------------------------------------------------------------------------------------------------
- * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
- *
- * Example sketch/program showing how to read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
- * Reader on the Arduino SPI interface.
- *
- * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
- * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
- * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
- * will show the ID/UID, type and any data blocks it can read. Note: you may see "Timeout in communication" messages
- * when removing the PICC from reading distance too early.
- *
- * If your reader supports it, this sketch/program will read all the PICCs presented (that is: multiple tag reading).
- * So if you stack two or more PICCs on top of each other and present them to the reader, it will first output all
- * details of the first and then the next PICC. Note that this may take some time as all data blocks are dumped, so
- * keep the PICCs at reading distance until complete.
- *
- * @license Released into the public domain.
- *
- */
-
-#include <MFRC522.h>
-#include <esp_log.h>
-static const char LOG_TAG[] = "DumpInfo";
-
-MFRC522 mfrc522;  // Create MFRC522 instance
-
-
-void dumpInfo() {
-	mfrc522.PCD_Init();		// Init MFRC522
-	mfrc522.PCD_DumpVersionToSerial();	// Show details of PCD - MFRC522 Card Reader details
-	ESP_LOGD(LOG_TAG, "Scan PICC to see UID, SAK, type, and data blocks...");
-	while(1) {
-		// Look for new cards
-		if ( ! mfrc522.PICC_IsNewCardPresent()) {
-			continue;
-		}
-
-		// Select one of the cards
-		if ( ! mfrc522.PICC_ReadCardSerial()) {
-			continue;
-		}
-
-		// Dump debug info about the card; PICC_HaltA() is automatically called
-		mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
-	}
-}
diff --git a/components/cpp_utils/tests/MFRC522/main.cpp b/components/cpp_utils/tests/MFRC522/main.cpp
deleted file mode 100644
index bfe00f9..0000000
--- a/components/cpp_utils/tests/MFRC522/main.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <stdio.h>
-#include <Task.h>
-extern void dumpInfo();
-
-
-extern "C" {
-	void app_main();
-}
-
-class MyTask: public Task {
-	void run(void* data) {
-		int count = 0;
-		/*
-		while(1) {
-			printf("count: %d\n", count);
-			count++;
-			vTaskDelay(1000/portTICK_PERIOD_MS);
-		}
-		*/
-		/*
-		char* x = "hello";
-		uint32_t i = 0;
-		printf("Hello world!");
-		printf("Hello world! again!");
-		char* p = (char*) i;
-		*p = 123;
-		*p */
-		dumpInfo();
-		printf("Done\n");
-	}
-};
-
-void app_main() {
-	MyTask* pMyTask = new MyTask();
-	pMyTask->setStackSize(20000);
-	pMyTask->start();
-
-}
diff --git a/components/cpp_utils/tests/task_i2c_scanner.cpp b/components/cpp_utils/tests/task_i2c_scanner.cpp
deleted file mode 100644
index 9e6fc2b..0000000
--- a/components/cpp_utils/tests/task_i2c_scanner.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <esp_log.h>
-#include <FreeRTOS.h>
-#include <Task.h>
-#include <I2C.h>
-
-#include "sdkconfig.h"
-
-#define SDA_PIN 25
-#define SCL_PIN 26
-
-//static char tag[] = "task_cpp_utils";
-
-class I2CScanner: public Task {
-	void run(void *data) override {
-		I2C i2c;
-		i2c.init((gpio_num_t)SDA_PIN, (gpio_num_t)SCL_PIN);
-		i2c.scan();
-	} // End run
-};
-
-
-static I2CScanner i2cScanner = I2CScanner();
-
-void task_i2c_scanner(void *ignore) {
-	i2cScanner.start();
-	FreeRTOS::deleteTask();
-}
diff --git a/components/cpp_utils/tests/task_mdns.cpp b/components/cpp_utils/tests/task_mdns.cpp
deleted file mode 100644
index cd2c41f..0000000
--- a/components/cpp_utils/tests/task_mdns.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <esp_log.h>
-#include <WiFiEventHandler.h>
-#include <WiFi.h>
-#include <FreeRTOS.h>
-#include <string>
-#include <stdio.h>
-#include <Task.h>
-
-#include "sdkconfig.h"
-
-static char tag[] = "task_mdns";
-
-class TargetWiFiEventHandler: public WiFiEventHandler {
-	 esp_err_t staGotIp(system_event_sta_got_ip_t event_sta_got_ip) {
-			ESP_LOGD(tag, "MyWiFiEventHandler(Class): staGotIp");
-			MDNS *mdns = new MDNS();
-			mdns->setHostname("HHHH");
-			mdns->setInstance("IIII");
-			mdns->serviceAdd("_test", "_tcp", 80);
-			return ESP_OK;
-	 }
-};
-
-class MDNSTask: public Task {
-	void run(void *data) override {
-
-		WiFi wifi;
-		TargetWiFiEventHandler *eventHandler = new TargetWiFiEventHandler();
-		wifi.setWifiEventHandler(eventHandler);
-		wifi.connectAP("sweetie", "l16wint!");
-	} // End run
-};
-
-
-static MDNSTask myTask = MDNSTask();
-
-void task_mdns(void *ignore) {
-	myTask.setStackSize(8000);
-	myTask.start();
-	FreeRTOS::deleteTask();
-}
diff --git a/components/cpp_utils/tests/test_max7219.cpp b/components/cpp_utils/tests/test_max7219.cpp
deleted file mode 100644
index 9ba12fd..0000000
--- a/components/cpp_utils/tests/test_max7219.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <esp_log.h>
-#include <FreeRTOS.h>
-#include <SPI.h>
-#include <string>
-#include <stdio.h>
-#include <Task.h>
-#include "MAX7219.h"
-
-#include "sdkconfig.h"
-
-//static char tag[] = "task_cpp_utils";
-
-
-
-class TestMAX7219: public Task {
-	void test8x8(MAX7219 &max7219) {
-		int dir=1;
-		int y=0;
-		while(1) {
-			for (auto x=0; x<8; x++) {
-				for (auto i=0; i<8; i++) {
-					max7219.setLed(x, y, true);
-					FreeRTOS::sleep(100);
-					max7219.setLed(x, y, false);
-					y=y+dir;
-				}
-				dir = -dir;
-				y=y+dir;
-			}
-		}
-	}
-
-	void test7SegDisplay(MAX7219 &max7219) {
-		int i=0;
-		while(1) {
-			max7219.setNumber(i);
-			i++;
-			FreeRTOS::sleep(100);
-		}
-	}
-
-	void run(void *data) override {
-		SPI spi;
-		spi.init();
-
-		MAX7219 max7219 = MAX7219(&spi, 1);
-		max7219.shutdown(false);
-		max7219.setIntensity(4);
-		//test7SegDisplay(max7219);
-		test8x8(max7219);
-
-	} // End run
-};
-
-
-static TestMAX7219 testMAX7219 = TestMAX7219();
-
-void task_max7219(void *ignore) {
-	testMAX7219.start();
-	FreeRTOS::deleteTask();
-}
diff --git a/components/cpp_utils/tests/test_rest.cpp b/components/cpp_utils/tests/test_rest.cpp
deleted file mode 100644
index 4ee38f4..0000000
--- a/components/cpp_utils/tests/test_rest.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Test the REST API client.
- */
-#include <curl/curl.h>
-#include <esp_log.h>
-#include <RESTClient.h>
-#include <string>
-#include <Task.h>
-#include <WiFi.h>
-#include <WiFiEventHandler.h>
-
-#include "sdkconfig.h"
-
-static char tag[] = "test_rest";
-
-extern "C" {
-	void app_main(void);
-}
-
-
-static WiFi *wifi;
-
-
-class CurlTestTask: public Task {
-	void run(void *data) {
-		ESP_LOGD(tag, "Testing curl ...");
-		RESTClient client;
-
-		/**
-		 * Test POST
-		 */
-
-		RESTTimings *timings = client.getTimings();
-
-		client.setURL("https://httpbin.org/post");
-		client.addHeader("Content-Type", "application/json");
-		client.post("hello world!");
-		ESP_LOGD(tag, "Result: %s", client.getResponse().c_str());
-		timings->refresh();
-		ESP_LOGD(tag, "timings: %s", timings->toString().c_str());
-
-		printf("Tests done\n");
-		return;
-	}
-};
-
-static CurlTestTask *curlTestTask;
-
-class MyWiFiEventHandler: public WiFiEventHandler {
-
-	esp_err_t staGotIp(system_event_sta_got_ip_t event_sta_got_ip) {
-		ESP_LOGD(tag, "MyWiFiEventHandler(Class): staGotIp");
-
-		curlTestTask = new CurlTestTask();
-		curlTestTask->setStackSize(12000);
-		curlTestTask->start();
-
-		return ESP_OK;
-	}
-};
-
-
-void app_main(void) {
-	ESP_LOGD(tag, "app_main: libcurl starting");
-	MyWiFiEventHandler *eventHandler = new MyWiFiEventHandler();
-
-	wifi = new WiFi();
-	wifi->setWifiEventHandler(eventHandler);
-
-	wifi->connectAP("sweetie", "l16wint!");
-}
diff --git a/components/cpp_utils/tests/test_rest_ifttt.cpp b/components/cpp_utils/tests/test_rest_ifttt.cpp
deleted file mode 100644
index da1dfa6..0000000
--- a/components/cpp_utils/tests/test_rest_ifttt.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Test the REST API client.
- */
-#include <curl/curl.h>
-#include <esp_log.h>
-#include <IFTTT.h>
-#include <RESTClient.h>
-#include <string>
-#include <Task.h>
-#include <WiFi.h>
-#include <WiFiEventHandler.h>
-
-#include "sdkconfig.h"
-
-static char tag[] = "test_rest";
-
-extern "C" {
-	void app_main(void);
-}
-
-
-static WiFi *wifi;
-
-class IFTTTTestTask: public Task {
-	void run(void *data) {
-		IFTTT iftt = IFTTT("dG-QmEUwCUyBBLHm1owPtq");
-		iftt.trigger("test", "A", "BCD", "Val3");
-		ESP_LOGD(tag, "trigger done!");
-	}
-};
-
-
-class MyWiFiEventHandler: public WiFiEventHandler {
-
-	esp_err_t staGotIp(system_event_sta_got_ip_t event_sta_got_ip) {
-		ESP_LOGD(tag, "MyWiFiEventHandler(Class): staGotIp");
-
-
-		IFTTTTestTask *pTestTask= new IFTTTTestTask();
-		pTestTask->setStackSize(12000);
-		pTestTask->start();
-		return ESP_OK;
-	}
-};
-
-
-void app_main(void) {
-	ESP_LOGD(tag, "app_main: libcurl starting");
-	MyWiFiEventHandler *eventHandler = new MyWiFiEventHandler();
-
-	wifi = new WiFi();
-	wifi->setWifiEventHandler(eventHandler);
-
-	wifi->connectAP("sweetie", "l16wint!");
-}
diff --git a/main/MeasureTask.cpp b/main/MeasureTask.cpp
deleted file mode 100644
index a15fc63..0000000
--- a/main/MeasureTask.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-
-#include "MeasureTask.h"
-
-#include <BME280.h>
-
-
-void MeasureTask::run(void *data) {
-    BME280 bme280 = BME280();
-    bme280.setDebug(false);
-    bme280.init();
-
-    while (1) {
-        bme280_reading_data sensor_data = bme280.readSensorData();
-
-        printf("Temperature: %.2foC, Humidity: %.2f%%, Pressure: %.2fPa\n",
-               (double) sensor_data.temperature,
-               (double) sensor_data.humidity,
-               (double) sensor_data.pressure
-        );
-
-        vTaskDelay(1000 / portTICK_PERIOD_MS);
-    }
-} // End run
diff --git a/main/MeasureTask.h b/main/MeasureTask.h
deleted file mode 100644
index ee1fc75..0000000
--- a/main/MeasureTask.h
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#ifndef ESP32_BME280_MEASURETASK_H
-#define ESP32_BME280_MEASURETASK_H
-
-#include <Task.h>
-
-#include "sdkconfig.h"
-
-
-class MeasureTask: public Task {
-public:
-    using Task::Task;
-
-    void run(void *data) override;
-};
-
-
-#endif //ESP32_BME280_MEASURETASK_H
diff --git a/main/component.mk b/main/component.mk
deleted file mode 100644
index 44bd2b5..0000000
--- a/main/component.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-#
-# Main Makefile. This is basically the same as a component makefile.
-#
diff --git a/main/main.cpp b/main/main.cpp
deleted file mode 100644
index 185123c..0000000
--- a/main/main.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <esp_log.h>
-#include <string>
-#include <FreeRTOS.h>
-#include "MeasureTask.h"
-
-#include "sdkconfig.h"
-
-static char LOG_TAG[] = "BME280_main";
-
-extern "C" {
-	void app_main(void);
-}
-
-static MeasureTask measureTask("Measure");
-
-void app_main(void)
-{
-    ESP_LOGI(LOG_TAG, "ESP32 Measure starting up...");
-
-    measureTask.start();
-    FreeRTOS::deleteTask();
-}
diff --git a/reference b/reference
deleted file mode 100644
index c0ab220..0000000
--- a/reference
+++ /dev/null
@@ -1,112 +0,0 @@
-Calibration
-T1 = {uint16_t} 27958
-T2 = {int16_t} 26133
-T3 = {int16_t} 50
-
-P1 = {uint16_t} 37458
-P2 = {int16_t} -11022
-P3 = {int16_t} 3024
-P4 = {int16_t} 7566
-P5 = {int16_t} -168
-P6 = {int16_t} -7
-P7 = {int16_t} 9900
-P8 = {int16_t} -10230
-P9 = {int16_t} 4285
-
-H1 = {uint8_t} 75
-H2 = {int16_t} 357
-H3 = {uint8_t} 0
-H4 = {int16_t} 331
-H5 = {int16_t} 0
-H6 = {int8_t} 30
-
-
-D (1389) bme280: T1: 27958, T2: 26133, T3: 50
-D (1389) bme280: P1: 37458, P2: -11022, P3: 3024, P4: 7566, P5: -168, P6: -7, P7: 9900, P8: -10230, P9: 4285
-
-
-
-Temp:
-adc_T = 8414784
-adc_T >> 4 = 525924
-var1 = 125356
-var2 = 17
-fine_t = 125373
-T = 2449
-result = 24.49
-
-Humidity:
-t_fine = 125284
-adc_H = 31718
-v_x1_u32r = 48484
-v_x1_u32r = 245895162
-v_x1_u32r = 243833028
-v_x1_u32r = 243833028
-v_x1_u32r = 243833028
-h = 59529
-result = 58.1337891
-
-Pressure
-t_fine = 125207
-adc_P = 5250784
-adc_P >> 4 = 328174
-var1 = -2793
-var2 = -54605943
-var2 = 61447522185
-var2 = 260027228014473
-var1 = 126185238344
-var1 = 614262126
-p = 720402
-p = 6547613350
-var1 = 81580595
-var2 = -127758188
-p = 25554633
-result = 99822.7812
-
-
-
-
-
-
-dig_T1 = {uint16_t} 27958
-dig_T2 = {int16_t} 26133
-dig_T3 = {int16_t} 50
-dig_P1 = {uint16_t} 37458
-dig_P2 = {int16_t} -11022
-dig_P3 = {int16_t} 3024
-dig_P4 = {int16_t} 7566
-dig_P5 = {int16_t} -168
-dig_P6 = {int16_t} -7
-dig_P7 = {int16_t} 9900
-dig_P8 = {int16_t} -10230
-dig_P9 = {int16_t} 4285
-dig_H1 = {uint8_t} 75 'K'
-dig_H2 = {int16_t} 357
-dig_H3 = {uint8_t} 0 '\000'
-dig_H4 = {int16_t} 331
-dig_H5 = {int16_t} 0
-dig_H6 = {int8_t} 30 '\036'
-
-
-
-
-dig_T1 = {uint16_t} 27958
-dig_T2 = {int16_t} 26133
-dig_T3 = {int16_t} 50
-dig_P1 = {uint16_t} 37458
-dig_P2 = {int16_t} -11022
-dig_P3 = {int16_t} 3024
-dig_P4 = {int16_t} 7566
-dig_P5 = {int16_t} -168
-dig_P6 = {int16_t} -7
-dig_P7 = {int16_t} 9900
-dig_P8 = {int16_t} -10230
-dig_P9 = {int16_t} 4285
-dig_H1 = {uint8_t} 75 'K'
-dig_H2 = {int16_t} 357
-dig_H3 = {uint8_t} 0 '\000'
-dig_H4 = {int16_t} 331
-dig_H5 = {int16_t} 0
-dig_H6 = {int8_t} 30 '\036'
-
-
diff --git a/sdkconfig b/sdkconfig
deleted file mode 100644
index 5fb6664..0000000
--- a/sdkconfig
+++ /dev/null
@@ -1,452 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# Espressif IoT Development Framework Configuration
-#
-
-#
-# SDK tool configuration
-#
-CONFIG_TOOLPREFIX="xtensa-esp32-elf-"
-CONFIG_PYTHON="python"
-CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y
-
-#
-# Bootloader config
-#
-CONFIG_LOG_BOOTLOADER_LEVEL_NONE=
-CONFIG_LOG_BOOTLOADER_LEVEL_ERROR=
-CONFIG_LOG_BOOTLOADER_LEVEL_WARN=
-CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
-CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG=
-CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE=
-CONFIG_LOG_BOOTLOADER_LEVEL=3
-
-#
-# Security features
-#
-CONFIG_SECURE_BOOT_ENABLED=
-CONFIG_FLASH_ENCRYPTION_ENABLED=
-
-#
-# Serial flasher config
-#
-CONFIG_ESPTOOLPY_PORT="/dev/cu.SLAB_USBtoUART"
-CONFIG_ESPTOOLPY_BAUD_115200B=
-CONFIG_ESPTOOLPY_BAUD_230400B=
-CONFIG_ESPTOOLPY_BAUD_921600B=y
-CONFIG_ESPTOOLPY_BAUD_2MB=
-CONFIG_ESPTOOLPY_BAUD_OTHER=
-CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
-CONFIG_ESPTOOLPY_BAUD=921600
-CONFIG_ESPTOOLPY_COMPRESSED=y
-CONFIG_FLASHMODE_QIO=
-CONFIG_FLASHMODE_QOUT=
-CONFIG_FLASHMODE_DIO=y
-CONFIG_FLASHMODE_DOUT=
-CONFIG_ESPTOOLPY_FLASHMODE="dio"
-CONFIG_ESPTOOLPY_FLASHFREQ_80M=
-CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
-CONFIG_ESPTOOLPY_FLASHFREQ_26M=
-CONFIG_ESPTOOLPY_FLASHFREQ_20M=
-CONFIG_ESPTOOLPY_FLASHFREQ="40m"
-CONFIG_ESPTOOLPY_FLASHSIZE_1MB=
-CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y
-CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
-CONFIG_ESPTOOLPY_FLASHSIZE_8MB=
-CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
-CONFIG_ESPTOOLPY_FLASHSIZE="2MB"
-CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
-CONFIG_ESPTOOLPY_BEFORE_RESET=y
-CONFIG_ESPTOOLPY_BEFORE_NORESET=
-CONFIG_ESPTOOLPY_BEFORE="default_reset"
-CONFIG_ESPTOOLPY_AFTER_RESET=y
-CONFIG_ESPTOOLPY_AFTER_NORESET=
-CONFIG_ESPTOOLPY_AFTER="hard_reset"
-CONFIG_MONITOR_BAUD_9600B=
-CONFIG_MONITOR_BAUD_57600B=
-CONFIG_MONITOR_BAUD_115200B=y
-CONFIG_MONITOR_BAUD_230400B=
-CONFIG_MONITOR_BAUD_921600B=
-CONFIG_MONITOR_BAUD_2MB=
-CONFIG_MONITOR_BAUD_OTHER=
-CONFIG_MONITOR_BAUD_OTHER_VAL=115200
-CONFIG_MONITOR_BAUD=115200
-
-#
-# Partition Table
-#
-CONFIG_PARTITION_TABLE_SINGLE_APP=y
-CONFIG_PARTITION_TABLE_TWO_OTA=
-CONFIG_PARTITION_TABLE_CUSTOM=
-CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
-CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000
-CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv"
-CONFIG_APP_OFFSET=0x10000
-
-#
-# Compiler options
-#
-CONFIG_OPTIMIZATION_LEVEL_DEBUG=y
-CONFIG_OPTIMIZATION_LEVEL_RELEASE=
-CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
-CONFIG_OPTIMIZATION_ASSERTIONS_SILENT=
-CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=
-
-#
-# Component config
-#
-
-#
-# Application Level Tracing
-#
-CONFIG_ESP32_APPTRACE_DEST_TRAX=
-CONFIG_ESP32_APPTRACE_DEST_NONE=y
-CONFIG_ESP32_APPTRACE_ENABLE=
-CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
-
-#
-# FreeRTOS SystemView Tracing
-#
-CONFIG_AWS_IOT_SDK=
-CONFIG_BT_ENABLED=
-CONFIG_BT_RESERVE_DRAM=0
-
-#
-# C++ settings
-#
-CONFIG_LIBCURL_PRESENT=
-CONFIG_U8G2_PRESENT=
-CONFIG_MONGOOSE_PRESENT=
-
-#
-# ESP32-specific
-#
-CONFIG_ESP32_DEFAULT_CPU_FREQ_80=
-CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y
-CONFIG_ESP32_DEFAULT_CPU_FREQ_240=
-CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160
-CONFIG_MEMMAP_SMP=y
-CONFIG_SPIRAM_SUPPORT=
-CONFIG_MEMMAP_TRACEMEM=
-CONFIG_MEMMAP_TRACEMEM_TWOBANKS=
-CONFIG_ESP32_TRAX=
-CONFIG_TRACEMEM_RESERVE_DRAM=0x0
-CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=
-CONFIG_ESP32_ENABLE_COREDUMP_TO_UART=
-CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y
-CONFIG_ESP32_ENABLE_COREDUMP=
-CONFIG_TWO_UNIVERSAL_MAC_ADDRESS=
-CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y
-CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4
-CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
-CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096
-CONFIG_MAIN_TASK_STACK_SIZE=4096
-CONFIG_IPC_TASK_STACK_SIZE=1024
-CONFIG_TIMER_TASK_STACK_SIZE=4096
-CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
-CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=
-CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR=
-CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF=
-CONFIG_NEWLIB_STDIN_LINE_ENDING_LF=
-CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y
-CONFIG_NEWLIB_NANO_FORMAT=
-CONFIG_CONSOLE_UART_DEFAULT=y
-CONFIG_CONSOLE_UART_CUSTOM=
-CONFIG_CONSOLE_UART_NONE=
-CONFIG_CONSOLE_UART_NUM=0
-CONFIG_CONSOLE_UART_BAUDRATE=115200
-CONFIG_ULP_COPROC_ENABLED=
-CONFIG_ULP_COPROC_RESERVE_MEM=0
-CONFIG_ESP32_PANIC_PRINT_HALT=
-CONFIG_ESP32_PANIC_PRINT_REBOOT=
-CONFIG_ESP32_PANIC_SILENT_REBOOT=
-CONFIG_ESP32_PANIC_GDBSTUB=y
-CONFIG_ESP32_DEBUG_OCDAWARE=y
-CONFIG_INT_WDT=y
-CONFIG_INT_WDT_TIMEOUT_MS=300
-CONFIG_INT_WDT_CHECK_CPU1=y
-CONFIG_TASK_WDT=y
-CONFIG_TASK_WDT_PANIC=
-CONFIG_TASK_WDT_TIMEOUT_S=5
-CONFIG_TASK_WDT_CHECK_IDLE_TASK=y
-CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
-CONFIG_BROWNOUT_DET=y
-CONFIG_BROWNOUT_DET_LVL_SEL_0=y
-CONFIG_BROWNOUT_DET_LVL_SEL_1=
-CONFIG_BROWNOUT_DET_LVL_SEL_2=
-CONFIG_BROWNOUT_DET_LVL_SEL_3=
-CONFIG_BROWNOUT_DET_LVL_SEL_4=
-CONFIG_BROWNOUT_DET_LVL_SEL_5=
-CONFIG_BROWNOUT_DET_LVL_SEL_6=
-CONFIG_BROWNOUT_DET_LVL_SEL_7=
-CONFIG_BROWNOUT_DET_LVL=0
-CONFIG_ESP32_TIME_SYSCALL_USE_RTC=
-CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y
-CONFIG_ESP32_TIME_SYSCALL_USE_FRC1=
-CONFIG_ESP32_TIME_SYSCALL_USE_NONE=
-CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
-CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL=
-CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
-CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
-CONFIG_ESP32_XTAL_FREQ_40=y
-CONFIG_ESP32_XTAL_FREQ_26=
-CONFIG_ESP32_XTAL_FREQ_AUTO=
-CONFIG_ESP32_XTAL_FREQ=40
-CONFIG_DISABLE_BASIC_ROM_CONSOLE=
-CONFIG_NO_BLOBS=
-
-#
-# Wi-Fi
-#
-CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
-CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
-CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=
-CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y
-CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1
-CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32
-CONFIG_ESP32_WIFI_AMPDU_ENABLED=y
-CONFIG_ESP32_WIFI_TX_BA_WIN=6
-CONFIG_ESP32_WIFI_RX_BA_WIN=6
-CONFIG_ESP32_WIFI_NVS_ENABLED=y
-
-#
-# PHY
-#
-CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
-CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION=
-CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
-CONFIG_ESP32_PHY_MAX_TX_POWER=20
-
-#
-# Ethernet
-#
-CONFIG_DMA_RX_BUF_NUM=10
-CONFIG_DMA_TX_BUF_NUM=10
-CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE=
-CONFIG_EMAC_TASK_PRIORITY=20
-
-#
-# FAT Filesystem support
-#
-CONFIG_FATFS_CODEPAGE_ASCII=y
-CONFIG_FATFS_CODEPAGE_437=
-CONFIG_FATFS_CODEPAGE_720=
-CONFIG_FATFS_CODEPAGE_737=
-CONFIG_FATFS_CODEPAGE_771=
-CONFIG_FATFS_CODEPAGE_775=
-CONFIG_FATFS_CODEPAGE_850=
-CONFIG_FATFS_CODEPAGE_852=
-CONFIG_FATFS_CODEPAGE_855=
-CONFIG_FATFS_CODEPAGE_857=
-CONFIG_FATFS_CODEPAGE_860=
-CONFIG_FATFS_CODEPAGE_861=
-CONFIG_FATFS_CODEPAGE_862=
-CONFIG_FATFS_CODEPAGE_863=
-CONFIG_FATFS_CODEPAGE_864=
-CONFIG_FATFS_CODEPAGE_865=
-CONFIG_FATFS_CODEPAGE_866=
-CONFIG_FATFS_CODEPAGE_869=
-CONFIG_FATFS_CODEPAGE_932=
-CONFIG_FATFS_CODEPAGE_936=
-CONFIG_FATFS_CODEPAGE_949=
-CONFIG_FATFS_CODEPAGE_950=
-CONFIG_FATFS_CODEPAGE=1
-CONFIG_FATFS_MAX_LFN=255
-
-#
-# FreeRTOS
-#
-CONFIG_FREERTOS_UNICORE=
-CONFIG_FREERTOS_CORETIMER_0=y
-CONFIG_FREERTOS_CORETIMER_1=
-CONFIG_FREERTOS_HZ=100
-CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
-CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE=
-CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL=
-CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
-CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=
-CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
-CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
-CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y
-CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE=
-CONFIG_FREERTOS_ASSERT_DISABLE=
-CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG=
-CONFIG_ENABLE_MEMORY_DEBUG=
-CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024
-CONFIG_FREERTOS_ISR_STACKSIZE=1536
-CONFIG_FREERTOS_LEGACY_HOOKS=
-CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
-CONFIG_SUPPORT_STATIC_ALLOCATION=
-CONFIG_TIMER_TASK_PRIORITY=1
-CONFIG_TIMER_TASK_STACK_DEPTH=2048
-CONFIG_TIMER_QUEUE_LENGTH=10
-CONFIG_FREERTOS_DEBUG_INTERNALS=
-
-#
-# Heap memory debugging
-#
-CONFIG_HEAP_POISONING_DISABLED=y
-CONFIG_HEAP_POISONING_LIGHT=
-CONFIG_HEAP_POISONING_COMPREHENSIVE=
-CONFIG_HEAP_TRACING=
-
-#
-# Log output
-#
-CONFIG_LOG_DEFAULT_LEVEL_NONE=
-CONFIG_LOG_DEFAULT_LEVEL_ERROR=
-CONFIG_LOG_DEFAULT_LEVEL_WARN=
-CONFIG_LOG_DEFAULT_LEVEL_INFO=
-CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
-CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=
-CONFIG_LOG_DEFAULT_LEVEL=4
-CONFIG_LOG_COLORS=y
-
-#
-# LWIP
-#
-CONFIG_L2_TO_L3_COPY=
-CONFIG_LWIP_MAX_SOCKETS=10
-CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX=0
-CONFIG_LWIP_SO_REUSE=
-CONFIG_LWIP_SO_RCVBUF=
-CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
-CONFIG_LWIP_IP_FRAG=
-CONFIG_LWIP_IP_REASSEMBLY=
-
-#
-# TCP
-#
-CONFIG_TCP_MAXRTX=12
-CONFIG_TCP_SYNMAXRTX=6
-CONFIG_TCP_MSS=1436
-CONFIG_TCP_MSL=60000
-CONFIG_TCP_SND_BUF_DEFAULT=5744
-CONFIG_TCP_WND_DEFAULT=5744
-CONFIG_TCP_RECVMBOX_SIZE=6
-CONFIG_TCP_QUEUE_OOSEQ=y
-CONFIG_TCP_OVERSIZE_MSS=y
-CONFIG_TCP_OVERSIZE_QUARTER_MSS=
-CONFIG_TCP_OVERSIZE_DISABLE=
-
-#
-# UDP
-#
-CONFIG_UDP_RECVMBOX_SIZE=6
-CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y
-CONFIG_TCPIP_TASK_STACK_SIZE=2560
-CONFIG_PPP_SUPPORT=
-
-#
-# ICMP
-#
-CONFIG_LWIP_MULTICAST_PING=
-CONFIG_LWIP_BROADCAST_PING=
-
-#
-# mbedTLS
-#
-CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384
-CONFIG_MBEDTLS_DEBUG=
-CONFIG_MBEDTLS_HARDWARE_AES=y
-CONFIG_MBEDTLS_HARDWARE_MPI=
-CONFIG_MBEDTLS_HARDWARE_SHA=
-CONFIG_MBEDTLS_HAVE_TIME=y
-CONFIG_MBEDTLS_HAVE_TIME_DATE=
-CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
-CONFIG_MBEDTLS_TLS_SERVER_ONLY=
-CONFIG_MBEDTLS_TLS_CLIENT_ONLY=
-CONFIG_MBEDTLS_TLS_DISABLED=
-CONFIG_MBEDTLS_TLS_SERVER=y
-CONFIG_MBEDTLS_TLS_CLIENT=y
-CONFIG_MBEDTLS_TLS_ENABLED=y
-
-#
-# TLS Key Exchange Methods
-#
-CONFIG_MBEDTLS_PSK_MODES=
-CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
-CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
-CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y
-CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y
-CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y
-CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y
-CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y
-CONFIG_MBEDTLS_SSL_RENEGOTIATION=y
-CONFIG_MBEDTLS_SSL_PROTO_SSL3=
-CONFIG_MBEDTLS_SSL_PROTO_TLS1=y
-CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y
-CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
-CONFIG_MBEDTLS_SSL_PROTO_DTLS=
-CONFIG_MBEDTLS_SSL_ALPN=y
-CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y
-
-#
-# Symmetric Ciphers
-#
-CONFIG_MBEDTLS_AES_C=y
-CONFIG_MBEDTLS_CAMELLIA_C=
-CONFIG_MBEDTLS_DES_C=
-CONFIG_MBEDTLS_RC4_DISABLED=y
-CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT=
-CONFIG_MBEDTLS_RC4_ENABLED=
-CONFIG_MBEDTLS_BLOWFISH_C=
-CONFIG_MBEDTLS_XTEA_C=
-CONFIG_MBEDTLS_CCM_C=y
-CONFIG_MBEDTLS_GCM_C=y
-CONFIG_MBEDTLS_RIPEMD160_C=
-
-#
-# Certificates
-#
-CONFIG_MBEDTLS_PEM_PARSE_C=y
-CONFIG_MBEDTLS_PEM_WRITE_C=y
-CONFIG_MBEDTLS_X509_CRL_PARSE_C=y
-CONFIG_MBEDTLS_X509_CSR_PARSE_C=y
-CONFIG_MBEDTLS_ECP_C=y
-CONFIG_MBEDTLS_ECDH_C=y
-CONFIG_MBEDTLS_ECDSA_C=y
-CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y
-CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y
-CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
-
-#
-# OpenSSL
-#
-CONFIG_OPENSSL_DEBUG=
-CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
-CONFIG_OPENSSL_ASSERT_EXIT=
-
-#
-# PThreads
-#
-CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
-CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=2048
-
-#
-# SPI Flash driver
-#
-CONFIG_SPI_FLASH_ENABLE_COUNTERS=
-CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
-
-#
-# tcpip adapter
-#
-CONFIG_IP_LOST_TIMER_INTERVAL=120
-
-#
-# Wear Levelling
-#
-CONFIG_WL_SECTOR_SIZE_512=
-CONFIG_WL_SECTOR_SIZE_4096=y
-CONFIG_WL_SECTOR_SIZE=4096
-- 
GitLab