#include "OmobiLedDisplay.h" //OmobiLedDisplay::OmobiLedDisplay(String deviceName, Adafruit_NeoMatrix *ledDisplayMatrix) void OmobiLedDisplay::loop() { if (millis() - lastKeepAlive > this->maximumKeepAliveDelay) { this->lastKeepAlive = millis(); this->bleServer->disconnectCurrentDevice(); } } void OmobiLedDisplay::onDeviceConnectedChanged(bool deviceConnected) { if (deviceConnected) { Serial.println("Device connected"); this->lastKeepAlive = millis(); } else { Serial.println("Device disconnected"); this->lastKeepAlive = -1; this->sessionAuthorized = false; } } void OmobiLedDisplay::onDataReceived(String dataString) { // process JSON const size_t capacity = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 200; DynamicJsonDocument requestDoc(capacity); DeserializationError error = deserializeJson(requestDoc, dataString); // return on error if (error != DeserializationError::Ok) return; // get reuqest data OmobiDisplayCommand requestHeader = requestDoc["header"]; JsonObject requestData = requestDoc["data"]; // prepare reply data DynamicJsonDocument replyDoc(capacity); replyDoc["header"] = requestHeader; OmobiDisplayStatusCode replyStatus = InternalError; JsonObject replyData = replyDoc.createNestedObject("data"); if (requestHeader > KeepAliveCommand && !this->sessionAuthorized) replyStatus = Unauthorized; else switch (requestHeader) { case AuthenticateCommand: { String combinedCode = String(this->properties.deviceCode); //this->bleServer->getDeviceAddress() + String(this->properties.deviceCode); String secret = this->sha256(combinedCode); if (this->sessionAuthorized) { replyStatus = Success; } else if (requestData["secret"] == secret) { 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; this->lastKeepAlive = millis(); break; } case GetAllTextSetsCommand: { replyStatus = Success; replyData["maximumTextSets"] = LedDisplayController::maximumTextSets; replyData["maximumTextLength"] = LedDisplayController::maximumTextLength; break; } case GetDisplayBrightnessCommand: { replyData["displayBrightness"] = this->ledDisplayController->getBrightness(); replyData["automaticBrightnessAdjustment"] = this->ledDisplayController->getAutomaticBrightnessAdjustment(); replyStatus = Success; break; } case GetTextSetParameterCommand: { int index = requestData["index"]; LedDisplayController::DisplayTextSetParameter parameter = requestData["parameter"]; // send each parameter to the client replyData["index"] = index; replyData["parameter"] = parameter; replyStatus = Success; replyData["value"] = this->ledDisplayController->getTextSetParameter( index, parameter); Serial.println("sending parameter: " + String(parameter) + " with value: '" + this->ledDisplayController->getTextSetParameter( index, parameter) + "'"); break; } case SetTextSetParameterCommand: { int index = requestData["index"]; int parameter = requestData["parameter"]; String value = requestData["value"]; LedDisplayController::GetSetTextSetParameterExitCode res = this->ledDisplayController->setTextSetParameter(index, LedDisplayController::DisplayTextSetParameter(parameter), value); if (res == LedDisplayController::Success) replyStatus = Success; else { replyStatus = DisplayControllerError; replyData["displayControllerError"] = res; } break; } case SetDisplayBrightnessCommand: { this->ledDisplayController->setBrightness(requestData["displayBrightness"]); this->ledDisplayController->setAutomaticBrightnessAdjustment(requestData["automaticBrightnessAdjustment"]); replyStatus = Success; break; } case SetDisplayCodeCommand: { String code = requestData["displayCode"]; if(code.length() != 4) { replyStatus = BadRequestError; break; } strncpy(this->properties.deviceCode, code.c_str(), sizeof(this->properties.deviceCode)); this->storeProperties(); replyStatus = Success; break; } case SetDisplayNameCommand: { String name = requestData["displayName"]; if(name.length() <= 0) { replyStatus = BadRequestError; break; } strncpy(this->properties.deviceName, name.c_str(), sizeof(this->properties.deviceName)); this->storeProperties(); replyStatus = Success; break; } default: break; } // reply to the client replyDoc["status"] = replyStatus; String json; serializeJson(replyDoc, json); Serial.println("Primary JSON: '" + 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; }