- created a class used to manage the EEPROM space allocation
- added authorization via a shared secret
This commit is contained in:
parent
7cca98106d
commit
2c44f8b873
9 changed files with 377 additions and 114 deletions
|
@ -7,6 +7,16 @@
|
|||
"vector": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"random": "cpp",
|
||||
"memory": "cpp"
|
||||
"memory": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"tuple": "cpp",
|
||||
"fstream": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"ostream": "cpp",
|
||||
"numeric": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"utility": "cpp"
|
||||
}
|
||||
}
|
83
vscode/OmobiLEDdisplayBluetooth/include/EepromManager.h
Normal file
83
vscode/OmobiLEDdisplayBluetooth/include/EepromManager.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
#ifndef EEPROM_MANAGER
|
||||
#define EEPROM_MANAGER
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
|
||||
class EepromUnit;
|
||||
|
||||
class EepromManager final
|
||||
{
|
||||
public:
|
||||
explicit EepromManager();
|
||||
|
||||
friend class EepromUnit;
|
||||
|
||||
/*!
|
||||
* \brief Function to register / allocate a part of the EEPROM
|
||||
*
|
||||
* This function ALWAYS has to be called in THE SAME ORDER for each unit.
|
||||
* Otherwise THE DATA WILL BE LOST!!
|
||||
*/
|
||||
EepromUnit *registerEempromUnit(size_t size);
|
||||
|
||||
private:
|
||||
int currentAddressEnding;
|
||||
|
||||
template <typename T>
|
||||
const T &writeToEeprom(int address, size_t size, const T &t)
|
||||
{
|
||||
Serial.println("Writing at: " + String(address) + " size: " + String(sizeof(T)));
|
||||
|
||||
if (sizeof(T) > size) {
|
||||
Serial.println("Error writing: Size should be: " + String(size));
|
||||
return t;
|
||||
}
|
||||
|
||||
const T &res = EEPROM.put(address, t);
|
||||
Serial.println("Eeprom commit returned: " + String(EEPROM.commit()));
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T &readFromEeprom(int address, size_t size, T &t)
|
||||
{
|
||||
Serial.println("Reading at: " + String(address) + " size: " + String(sizeof(T)));
|
||||
|
||||
if (sizeof(T) > size) {
|
||||
Serial.println("Error reading: Size should be: " + String(size));
|
||||
return t;
|
||||
}
|
||||
|
||||
T &res = EEPROM.get(address, t);
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
class EepromUnit final
|
||||
{
|
||||
public:
|
||||
friend class EepromManager;
|
||||
|
||||
template <typename T>
|
||||
const T &write(const T &t)
|
||||
{
|
||||
return this->manager->writeToEeprom(this->address, this->size, t);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T &read(T &t)
|
||||
{
|
||||
return this->manager->readFromEeprom(this->address, this->size, t);
|
||||
};
|
||||
|
||||
private:
|
||||
explicit EepromUnit(EepromManager *manager, int address, size_t size);
|
||||
|
||||
EepromManager *manager;
|
||||
int address;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#endif // EEPROM_MANAGER
|
|
@ -5,7 +5,7 @@
|
|||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_NeoMatrix.h>
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#include <EEPROM.h>
|
||||
#include <EepromManager.h>
|
||||
#include "esp_task_wdt.h"
|
||||
|
||||
class LedDisplayController
|
||||
|
@ -52,6 +52,7 @@ public:
|
|||
void loop();
|
||||
|
||||
// modifiers for the internal text sets
|
||||
bool registerEepromUnit(EepromManager* eepromManager);
|
||||
String getTextSetParameter(int index, DisplayTextSetParameter parameter);
|
||||
GetSetTextSetParameterExitCode setTextSetParameter(int index, DisplayTextSetParameter parameter, String value);
|
||||
|
||||
|
@ -105,8 +106,9 @@ private:
|
|||
sets_t text_sets;
|
||||
|
||||
// storage control
|
||||
EepromUnit* eepromUnit;
|
||||
GetSetTextSetParameterExitCode getSetTextSetParameter(int index, DisplayTextSetParameter parameter, String *value, bool set = false);
|
||||
void storeTextSets();
|
||||
bool storeTextSets();
|
||||
bool loadTextSets();
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "mbedtls/md.h"
|
||||
#include "EepromManager.h"
|
||||
#include "BluetoothLeUartServer.h"
|
||||
#include "LedDisplayController.h"
|
||||
|
||||
|
@ -37,15 +39,32 @@ private:
|
|||
enum OmobiDisplayStatusCode
|
||||
{
|
||||
Success = 200,
|
||||
Unauthorized = 401,
|
||||
InternalError = 500,
|
||||
DisplayControllerError = 501
|
||||
};
|
||||
|
||||
unsigned long lastKeepAlive;
|
||||
const int maximumKeepAliveDelay = 10000;
|
||||
bool sessionAuthorized;
|
||||
|
||||
LedDisplayController *ledDisplayController;
|
||||
BluetoothLeUartServer *bleServer;
|
||||
typedef struct {
|
||||
char deviceName[50];
|
||||
char deviceCode[5];
|
||||
char valid[3];
|
||||
} DisplayProperties;
|
||||
|
||||
DisplayProperties properties;
|
||||
|
||||
EepromManager* eepromManager;
|
||||
EepromUnit* eepromUnit;
|
||||
LedDisplayController* ledDisplayController;
|
||||
BluetoothLeUartServer* bleServer;
|
||||
|
||||
bool loadProperties();
|
||||
bool storeProperties();
|
||||
|
||||
String sha256(String payload);
|
||||
};
|
||||
|
||||
#endif // OMOBI_LED_DISPLAY
|
|
@ -11,6 +11,8 @@
|
|||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32doit-devkit-v1
|
||||
board_upload.flash_size=4MB
|
||||
board_upload.maximum_size=4194304
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
Wire
|
||||
|
|
|
@ -58,6 +58,10 @@ void BluetoothLeUartServer::sendData(String data)
|
|||
|
||||
void BluetoothLeUartServer::onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param)
|
||||
{
|
||||
// only allow one device
|
||||
if(this->deviceConnected)
|
||||
return this->bleServer->disconnect(param->connect.conn_id);
|
||||
|
||||
this->deviceConnected = true;
|
||||
this->deviceConnectionId = param->connect.conn_id;
|
||||
|
||||
|
|
29
vscode/OmobiLEDdisplayBluetooth/src/EepromManager.cpp
Normal file
29
vscode/OmobiLEDdisplayBluetooth/src/EepromManager.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include "EepromManager.h"
|
||||
|
||||
EepromManager::EepromManager()
|
||||
{
|
||||
this->currentAddressEnding = 4;
|
||||
EEPROM.begin(4000);
|
||||
}
|
||||
|
||||
EepromUnit *EepromManager::registerEempromUnit(size_t size)
|
||||
{
|
||||
Serial.println("Registering new EepromUnit with size: " + String(size) + " at " + String(this->currentAddressEnding));
|
||||
// create a new Unit at the current address ending
|
||||
EepromUnit *newUnit = new EepromUnit(this, this->currentAddressEnding, size);
|
||||
// move the new address ending
|
||||
this->currentAddressEnding += size;
|
||||
return newUnit;
|
||||
}
|
||||
|
||||
|
||||
// --------------
|
||||
// - EepromUnit -
|
||||
// --------------
|
||||
|
||||
EepromUnit::EepromUnit(EepromManager *manager, int address, size_t size)
|
||||
{
|
||||
this->manager = manager;
|
||||
this->address = address;
|
||||
this->size = size;
|
||||
}
|
|
@ -4,6 +4,7 @@ LedDisplayController *ledDisplayControllerGlobal = nullptr;
|
|||
|
||||
LedDisplayController::LedDisplayController(Adafruit_NeoMatrix *matrix)
|
||||
{
|
||||
this->eepromUnit = nullptr;
|
||||
ledDisplayControllerGlobal = this;
|
||||
this->loadTextSets();
|
||||
|
||||
|
@ -47,6 +48,15 @@ void LedDisplayController::loop()
|
|||
}
|
||||
}
|
||||
|
||||
bool LedDisplayController::registerEepromUnit(EepromManager *eepromManager)
|
||||
{
|
||||
if (this->eepromUnit != nullptr)
|
||||
return false;
|
||||
|
||||
this->eepromUnit = eepromManager->registerEempromUnit(sizeof(sets_t));
|
||||
return this->loadTextSets();
|
||||
}
|
||||
|
||||
String LedDisplayController::getTextSetParameter(int index, DisplayTextSetParameter parameter)
|
||||
{
|
||||
if (index < 0 || index > this->maximumTextSets || parameter < 0 || parameter >= DisplayTextSetParameterCount)
|
||||
|
@ -194,13 +204,14 @@ LedDisplayController::GetSetTextSetParameterExitCode LedDisplayController::getSe
|
|||
switch (parameter)
|
||||
{
|
||||
case TextParameter:
|
||||
if (set) {
|
||||
if(*value == "")
|
||||
if (set)
|
||||
{
|
||||
if (*value == "")
|
||||
// delete the index
|
||||
for (int i = index; i < this->maximumTextSets; i++)
|
||||
{
|
||||
if(i > this->maximumTextSets - 1)
|
||||
this->text_sets.sets[i] = this->text_sets.sets[i+1];
|
||||
if (i > this->maximumTextSets - 1)
|
||||
this->text_sets.sets[i] = this->text_sets.sets[i + 1];
|
||||
else
|
||||
this->text_sets.sets[i] = this->defaultTextSet;
|
||||
}
|
||||
|
@ -294,32 +305,39 @@ LedDisplayController::GetSetTextSetParameterExitCode LedDisplayController::getSe
|
|||
}
|
||||
}
|
||||
|
||||
void LedDisplayController::storeTextSets()
|
||||
bool LedDisplayController::storeTextSets()
|
||||
{
|
||||
// write conf to EEPROM
|
||||
EEPROM.begin(sizeof(sets_t));
|
||||
//for (size_t i = 0 ; i < DISP_STRUCT_SIZE ; i++)
|
||||
//{
|
||||
// EEPROM.write(i, 0);
|
||||
//}
|
||||
strncpy(text_sets.valid, "OK", sizeof(text_sets.valid));
|
||||
EEPROM.put(0, text_sets);
|
||||
EEPROM.commit();
|
||||
EEPROM.end();
|
||||
Serial.println("Storing Text Sets...");
|
||||
if (this->eepromUnit == nullptr) {
|
||||
Serial.println("ERROR");
|
||||
return false;
|
||||
}
|
||||
|
||||
strncpy(this->text_sets.valid, "OK", sizeof(this->text_sets.valid));
|
||||
this->eepromUnit->write(this->text_sets);
|
||||
Serial.println("OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LedDisplayController::loadTextSets()
|
||||
{
|
||||
bool rc = false;
|
||||
sets_t buf = {};
|
||||
|
||||
Serial.println("Loading Text Sets...");
|
||||
|
||||
if (this->eepromUnit != nullptr)
|
||||
{
|
||||
// read conf from EEPROM
|
||||
EEPROM.begin(sizeof(sets_t));
|
||||
EEPROM.get(0, buf);
|
||||
EEPROM.end();
|
||||
this->eepromUnit->read(buf);
|
||||
}
|
||||
|
||||
Serial.println("Loaded text sets: valid: " + String(buf.valid));
|
||||
|
||||
if (strcmp(buf.valid, "OK") == 0)
|
||||
{
|
||||
rc = true;
|
||||
memcpy(&text_sets, &buf, sizeof(text_sets));
|
||||
memcpy(&text_sets, &buf, sizeof(sets_t));
|
||||
Serial.println("OK");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -327,18 +345,14 @@ bool LedDisplayController::loadTextSets()
|
|||
|
||||
sets_t defaultTextSets;
|
||||
|
||||
strncpy(defaultTextSets.valid, "OK", sizeof(defaultTextSets.valid));
|
||||
|
||||
for (int i = 0; i < this->maximumTextSets; i++)
|
||||
{
|
||||
defaultTextSets.sets[i] = this->defaultTextSet;
|
||||
}
|
||||
|
||||
this->text_sets = defaultTextSets;
|
||||
this->storeTextSets();
|
||||
memcpy(&text_sets, &defaultTextSets, sizeof(sets_t));
|
||||
return this->storeTextSets();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
#include "OmobiLedDisplay.h"
|
||||
#include "esp_gatts_api.h"
|
||||
|
||||
OmobiLedDisplay::OmobiLedDisplay(String deviceName, Adafruit_NeoMatrix *ledDisplayMatrix)
|
||||
{
|
||||
this->lastKeepAlive = -1;
|
||||
this->sessionAuthorized = false;
|
||||
|
||||
// init eeprom manager
|
||||
this->eepromManager = new EepromManager();
|
||||
|
||||
// init led display controller
|
||||
this->ledDisplayController = new LedDisplayController(ledDisplayMatrix);
|
||||
this->ledDisplayController->setTextSetParameter(0, LedDisplayController::ActiveParameter, "true");
|
||||
this->ledDisplayController->registerEepromUnit(this->eepromManager);
|
||||
|
||||
// init ble server
|
||||
this->bleServer = new BluetoothLeUartServer(deviceName, "92fecb20-1406-426a-afa5-cd5c1f306462", "92fecb21-1406-426a-afa5-cd5c1f306462", "92fecb22-1406-426a-afa5-cd5c1f306462");
|
||||
this->bleServer = new BluetoothLeUartServer("Omobi Display", "92fecb20-1406-426a-afa5-cd5c1f306462", "92fecb21-1406-426a-afa5-cd5c1f306462", "92fecb22-1406-426a-afa5-cd5c1f306462");
|
||||
this->bleServer->setCallbacks(this);
|
||||
|
||||
this->eepromUnit = this->eepromManager->registerEempromUnit(sizeof(DisplayProperties));
|
||||
this->loadProperties();
|
||||
}
|
||||
|
||||
void OmobiLedDisplay::loop() {
|
||||
if(millis() - lastKeepAlive > this->maximumKeepAliveDelay) {
|
||||
void OmobiLedDisplay::loop()
|
||||
{
|
||||
if (millis() - lastKeepAlive > this->maximumKeepAliveDelay)
|
||||
{
|
||||
this->lastKeepAlive = millis();
|
||||
this->bleServer->disconnectCurrentDevice();
|
||||
}
|
||||
|
@ -23,13 +31,16 @@ void OmobiLedDisplay::loop() {
|
|||
|
||||
void OmobiLedDisplay::onDeviceConnectedChanged(bool deviceConnected)
|
||||
{
|
||||
if (deviceConnected) {
|
||||
if (deviceConnected)
|
||||
{
|
||||
Serial.println("Device connected");
|
||||
this->lastKeepAlive = millis();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
Serial.println("Device disconnected");
|
||||
this->lastKeepAlive = -1;
|
||||
this->sessionAuthorized = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +52,7 @@ void OmobiLedDisplay::onDataReceived(String dataString)
|
|||
DeserializationError error = deserializeJson(requestDoc, dataString);
|
||||
|
||||
// return on error
|
||||
if(error != DeserializationError::Ok)
|
||||
if (error != DeserializationError::Ok)
|
||||
return;
|
||||
|
||||
// get reuqest data
|
||||
|
@ -54,8 +65,32 @@ void OmobiLedDisplay::onDataReceived(String dataString)
|
|||
OmobiDisplayStatusCode replyStatus = InternalError;
|
||||
JsonObject replyData = replyDoc.createNestedObject("data");
|
||||
|
||||
if (requestHeader != AuthorizeSessionCommand && !this->sessionAuthorized)
|
||||
replyStatus = Unauthorized;
|
||||
else
|
||||
switch (requestHeader)
|
||||
{
|
||||
case AuthorizeSessionCommand:
|
||||
{
|
||||
if (this->sessionAuthorized)
|
||||
{
|
||||
replyStatus = Success;
|
||||
}
|
||||
else if (requestData["secret"] == this->sha256(this->properties.deviceCode))
|
||||
{
|
||||
replyStatus = Success;
|
||||
this->sessionAuthorized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
replyStatus = Unauthorized;
|
||||
this->sessionAuthorized = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// for future use: add some variables of the display
|
||||
}
|
||||
|
||||
case KeepAliveCommand:
|
||||
{
|
||||
replyStatus = Success;
|
||||
|
@ -71,7 +106,7 @@ void OmobiLedDisplay::onDataReceived(String dataString)
|
|||
if (this->ledDisplayController->getTextSetParameter(textSetIndex, LedDisplayController::TextParameter) == "")
|
||||
continue;
|
||||
|
||||
//Serial.println("Adding index " + String(textSetIndex) + " with text: " + this->ledDisplayController->getTextSetParameter(textSetIndex, LedDisplayController::TextParameter));
|
||||
Serial.println("Adding index " + String(textSetIndex) + " with text: " + this->ledDisplayController->getTextSetParameter(textSetIndex, LedDisplayController::TextParameter));
|
||||
|
||||
// if a set isn't empty, go through all parameters
|
||||
for (int textSetParameter = 0; textSetParameter < LedDisplayController::DisplayTextSetParameterCount; textSetParameter++)
|
||||
|
@ -142,3 +177,68 @@ void OmobiLedDisplay::onDataReceived(String dataString)
|
|||
serializeJson(replyDoc, json);
|
||||
this->bleServer->sendData(json);
|
||||
}
|
||||
|
||||
bool OmobiLedDisplay::loadProperties()
|
||||
{
|
||||
if (this->eepromUnit == nullptr)
|
||||
return false;
|
||||
|
||||
DisplayProperties buf = {};
|
||||
|
||||
// read conf from EEPROM
|
||||
this->eepromUnit->read(buf);
|
||||
|
||||
if (strcmp(buf.valid, "OK") == 0)
|
||||
{
|
||||
memcpy(&this->properties, &buf, sizeof(DisplayProperties));
|
||||
}
|
||||
else
|
||||
{
|
||||
// There was an error reading the properties -> rebuild with default values!
|
||||
DisplayProperties defaultProperties{
|
||||
"Omobi Led Display",
|
||||
"1234",
|
||||
"OK"};
|
||||
|
||||
memcpy(&this->properties, &defaultProperties, sizeof(DisplayProperties));
|
||||
this->storeProperties();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OmobiLedDisplay::storeProperties()
|
||||
{
|
||||
if (this->eepromUnit == nullptr)
|
||||
return false;
|
||||
|
||||
strncpy(this->properties.valid, "OK", sizeof(this->properties.valid));
|
||||
this->eepromUnit->write(this->properties);
|
||||
return true;
|
||||
}
|
||||
|
||||
String OmobiLedDisplay::sha256(String payload)
|
||||
{
|
||||
byte shaResult[32];
|
||||
mbedtls_md_context_t ctx;
|
||||
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
|
||||
const size_t payloadLength = strlen(payload.c_str());
|
||||
mbedtls_md_init(&ctx);
|
||||
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
|
||||
mbedtls_md_starts(&ctx);
|
||||
mbedtls_md_update(&ctx, (const unsigned char *)payload.c_str(), payloadLength);
|
||||
mbedtls_md_finish(&ctx, shaResult);
|
||||
mbedtls_md_free(&ctx);
|
||||
|
||||
String resultString = "";
|
||||
|
||||
for (int i = 0; i < sizeof(shaResult); i++)
|
||||
{
|
||||
char str[3];
|
||||
|
||||
sprintf(str, "%02x", (int)shaResult[i]);
|
||||
resultString += str;
|
||||
}
|
||||
|
||||
return resultString;
|
||||
}
|
Loading…
Reference in a new issue