- finished implementing protocol
- some changes and cleanup
This commit is contained in:
parent
ce6d436c85
commit
d74da783b3
9 changed files with 506 additions and 353 deletions
|
@ -5,6 +5,8 @@
|
|||
"deque": "cpp",
|
||||
"string": "cpp",
|
||||
"vector": "cpp",
|
||||
"unordered_map": "cpp"
|
||||
"unordered_map": "cpp",
|
||||
"random": "cpp",
|
||||
"memory": "cpp"
|
||||
}
|
||||
}
|
|
@ -9,6 +9,42 @@
|
|||
|
||||
class BluetoothLeUartServerCallbacks;
|
||||
|
||||
/*!
|
||||
* \brief The BluetoothLeUartServer class can be used to connect to another Bluetooth LE device (like an Android phone) effordlessly.
|
||||
*
|
||||
* Example use
|
||||
* \code
|
||||
* #include <Arduino.h>
|
||||
* #include "OmobiLedDisplay.h"
|
||||
*
|
||||
* BluetoothLeUartServer* server;
|
||||
*
|
||||
* class MyCallbacks : public BluetoothLeUartServerCallbacks
|
||||
* {
|
||||
* virtual void onDeviceConnectedChanged(bool deviceConnected)
|
||||
* {
|
||||
* Serial.println("Device connected changed");
|
||||
* };
|
||||
* virtual void onDataReceived(String data)
|
||||
* {
|
||||
* Serial.println("Got some data: " + data);
|
||||
* };
|
||||
* };
|
||||
*
|
||||
* void setup()
|
||||
* {
|
||||
* server = new BluetoothLeUartServer("OmobiLedDisplay1", "6e400001-b5a3-f393-e0a9-e50e24dcca9e", "6e400002-b5a3-f393-e0a9-e50e24dcca9e", "6e400003-b5a3-f393-e0a9-e50e24dcca9e");
|
||||
* server->setCallbacks(new MyCallbacks());
|
||||
* }
|
||||
*
|
||||
* void loop()
|
||||
* {
|
||||
* if(server->getDeviceConnected())
|
||||
* server->sendData("PING");
|
||||
* delay(1000);
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
class BluetoothLeUartServer : protected BLEServerCallbacks, protected BLECharacteristicCallbacks
|
||||
{
|
||||
|
||||
|
@ -34,15 +70,18 @@ protected:
|
|||
void onWrite(BLECharacteristic *rxCharacteristic) override;
|
||||
|
||||
private:
|
||||
// service and characteristic UUIDs
|
||||
const char *uartServiceUUID;
|
||||
const char *rxUUID;
|
||||
const char *txUUID;
|
||||
|
||||
// BLE Objects
|
||||
BLEServer *bleServer;
|
||||
BLEService *bleService;
|
||||
BLECharacteristic *txCharacteristic;
|
||||
BLECharacteristic *rxCharacteristic;
|
||||
|
||||
// helpers
|
||||
bool deviceConnected = false;
|
||||
BluetoothLeUartServerCallbacks *callbacks;
|
||||
};
|
||||
|
|
|
@ -11,87 +11,105 @@
|
|||
class LedDisplayController
|
||||
{
|
||||
public:
|
||||
explicit LedDisplayController(const byte pin);
|
||||
explicit LedDisplayController(Adafruit_NeoMatrix *matrix);
|
||||
~LedDisplayController();
|
||||
|
||||
enum text_align_t
|
||||
{
|
||||
TEXTLEFT,
|
||||
TEXTCENTER,
|
||||
TEXTRIGHT
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
AlignRight
|
||||
};
|
||||
|
||||
enum set_param_index_t
|
||||
enum DisplayTextSetParameter
|
||||
{
|
||||
PTEXT,
|
||||
PTIME,
|
||||
PCOLOR,
|
||||
PALIGN,
|
||||
PSCROLL,
|
||||
PSCROLL_RUNS,
|
||||
PACTIVE
|
||||
TextParameter = 0,
|
||||
ActiveParameter,
|
||||
RuntimeParameter,
|
||||
ColorParameter,
|
||||
AlignmentParameter,
|
||||
ScrollParameter,
|
||||
ScrollSpeedParameter,
|
||||
ScrollCountParameter,
|
||||
IndexParameter,
|
||||
DisplayTextSetParameterCount
|
||||
};
|
||||
|
||||
static const uint16_t text_nr_sets = 2;
|
||||
static const uint16_t MAX_TXT_LENGTH = 256;
|
||||
static const int nr_param_names = 7;
|
||||
|
||||
typedef struct text_set_t
|
||||
enum GetSetTextSetParameterExitCode
|
||||
{
|
||||
char text[MAX_TXT_LENGTH];
|
||||
uint16_t time_ms;
|
||||
uint16_t color;
|
||||
text_align_t align;
|
||||
bool text_scroll;
|
||||
uint16_t text_scroll_pass;
|
||||
bool active;
|
||||
} text_set_t;
|
||||
Success,
|
||||
InvalidParameterError,
|
||||
ParameterNotWritableError,
|
||||
ValueOutOfRangeError,
|
||||
IndexOutOfRangeError,
|
||||
ValueIsNullptrError,
|
||||
InternalError
|
||||
};
|
||||
|
||||
typedef struct sets_t
|
||||
{
|
||||
text_set_t sets[text_nr_sets];
|
||||
char valid[3];
|
||||
} sets_t;
|
||||
static const uint16_t MaximumTextSets = 6;
|
||||
static const uint16_t MaximumTextLength = 256;
|
||||
|
||||
void disp_update();
|
||||
void loop();
|
||||
|
||||
void setTexts(sets_t texts);
|
||||
sets_t getTexts();
|
||||
// modifiers for the internal text sets
|
||||
String getTextSetParameter(int index, DisplayTextSetParameter parameter);
|
||||
GetSetTextSetParameterExitCode setTextSetParameter(int index, DisplayTextSetParameter parameter, String value);
|
||||
|
||||
uint16_t Color(uint8_t r, uint8_t g, uint8_t b);
|
||||
// brightness control
|
||||
int getBrightness();
|
||||
bool setBrightness(int brightness);
|
||||
|
||||
private:
|
||||
|
||||
// matrix objects
|
||||
TaskHandle_t displayUpdateTask;
|
||||
|
||||
Adafruit_NeoMatrix *matrix;
|
||||
|
||||
const String set_param_name[nr_param_names] = {"text_", "time_", "color_", "align_", "scroll_", "scroll_runs_", "active_"};
|
||||
const uint16_t DISP_STRUCT_SIZE = sizeof(sets_t);
|
||||
sets_t text_sets;
|
||||
|
||||
// matrix variables
|
||||
uint16_t text_curr_nr;
|
||||
uint32_t text_set_starttime;
|
||||
|
||||
int text_pos;
|
||||
unsigned int text_pass;
|
||||
unsigned int textpixel;
|
||||
|
||||
int disp_brightness;
|
||||
bool disp_show;
|
||||
|
||||
void storeDisplaySet();
|
||||
bool loadDisplaySet();
|
||||
|
||||
void disp_scroll_text();
|
||||
void disp_switch_text();
|
||||
void disp_start_set();
|
||||
// matrix control
|
||||
void disp_init();
|
||||
void show_matrix(const char *text, int pos, uint16_t color);
|
||||
String get_paramstring_from_struct(String name);
|
||||
void set_param_to_struct(String name, String value);
|
||||
String getset_param_at_struct(String name, String value, bool set);
|
||||
void disp_start_set();
|
||||
void disp_scroll_text();
|
||||
void show_matrix(const char *text, int pos, const char *color);
|
||||
uint16_t colorFromHex(String hex);
|
||||
|
||||
// storage structs
|
||||
typedef struct text_set_t
|
||||
{
|
||||
char text[MaximumTextLength];
|
||||
bool active;
|
||||
uint16_t runtime;
|
||||
char color[7];
|
||||
text_align_t alignment;
|
||||
bool scroll;
|
||||
int scrollSpeed;
|
||||
uint16_t scrollCount;
|
||||
} text_set_t;
|
||||
|
||||
typedef struct sets_t
|
||||
{
|
||||
text_set_t sets[MaximumTextSets];
|
||||
char valid[3];
|
||||
} sets_t;
|
||||
|
||||
// storage variables
|
||||
sets_t text_sets;
|
||||
|
||||
// storage control
|
||||
GetSetTextSetParameterExitCode getSetTextSetParameter(int index, DisplayTextSetParameter parameter, String *value, bool set = false);
|
||||
void storeTextSets();
|
||||
bool loadTextSets();
|
||||
};
|
||||
|
||||
// function for updater task on core 0
|
||||
void updateDisplayGlobal(void *);
|
||||
extern LedDisplayController *ledDisplayControllerGlobal;
|
||||
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
#include "BluetoothLeUartServer.h"
|
||||
#include "LedDisplayController.h"
|
||||
|
||||
class OmobiLedDisplay : protected BluetoothLeUartServerCallbacks {
|
||||
class OmobiLedDisplay : protected BluetoothLeUartServerCallbacks
|
||||
{
|
||||
|
||||
public:
|
||||
explicit OmobiLedDisplay(String deviceName, const byte ledPin);
|
||||
explicit OmobiLedDisplay(String deviceName, Adafruit_NeoMatrix *ledDisplayMatrix);
|
||||
|
||||
// befriend for callbacks
|
||||
friend class BluetoothLeUartServer;
|
||||
|
@ -20,6 +21,22 @@ protected:
|
|||
void onDataReceived(String data) override;
|
||||
|
||||
private:
|
||||
enum OmobiDisplayCommand
|
||||
{
|
||||
GetAllTextSetsCommand = 10,
|
||||
GetTextSetParameterCommand = 11,
|
||||
GetDisplayBrightnessCommand = 12,
|
||||
SetTextSetParameterCommand = 20,
|
||||
SetDisplayBrightnessCommand = 21
|
||||
};
|
||||
|
||||
enum OmobiDisplayStatusCode
|
||||
{
|
||||
Success = 200,
|
||||
InternalError = 500,
|
||||
DisplayControllerError = 501
|
||||
};
|
||||
|
||||
LedDisplayController *ledDisplayController;
|
||||
BluetoothLeUartServer *bleServer;
|
||||
};
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
|
|
@ -57,7 +57,8 @@ void BluetoothLeUartServer::sendData(String data)
|
|||
void BluetoothLeUartServer::onConnect(BLEServer *pServer)
|
||||
{
|
||||
this->deviceConnected = true;
|
||||
if (this->callbacks != nullptr) {
|
||||
if (this->callbacks != nullptr)
|
||||
{
|
||||
this->callbacks->onDeviceConnectedChanged(this->deviceConnected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
|
||||
LedDisplayController *ledDisplayControllerGlobal = nullptr;
|
||||
|
||||
LedDisplayController::LedDisplayController(const byte pin)
|
||||
LedDisplayController::LedDisplayController(Adafruit_NeoMatrix *matrix)
|
||||
{
|
||||
ledDisplayControllerGlobal = this;
|
||||
this->loadTextSets();
|
||||
|
||||
this->matrix = new Adafruit_NeoMatrix(8, 8, 1, 1, pin,
|
||||
NEO_TILE_TOP + NEO_TILE_LEFT + NEO_TILE_ROWS + NEO_TILE_PROGRESSIVE +
|
||||
NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS + NEO_TILE_PROGRESSIVE,
|
||||
NEO_GRB + NEO_KHZ800);
|
||||
|
||||
this->matrix = matrix;
|
||||
this->matrix->begin();
|
||||
this->matrix->setTextWrap(false);
|
||||
this->matrix->setBrightness(40);
|
||||
|
@ -19,6 +16,7 @@ LedDisplayController::LedDisplayController(const byte pin)
|
|||
text_set_starttime = 0;
|
||||
text_pass = 0;
|
||||
textpixel = 0;
|
||||
disp_brightness = 5;
|
||||
disp_show = false;
|
||||
|
||||
this->disp_init();
|
||||
|
@ -27,7 +25,11 @@ LedDisplayController::LedDisplayController(const byte pin)
|
|||
xTaskCreatePinnedToCore(updateDisplayGlobal, "DisplayUpdateTask", 10000, NULL, 1, &displayUpdateTask, 0);
|
||||
}
|
||||
|
||||
void LedDisplayController::disp_update()
|
||||
// --------------------
|
||||
// - Public functions -
|
||||
// --------------------
|
||||
|
||||
void LedDisplayController::loop()
|
||||
{
|
||||
if (this->disp_show)
|
||||
{
|
||||
|
@ -36,7 +38,7 @@ void LedDisplayController::disp_update()
|
|||
{
|
||||
if (text_sets.sets[text_curr_nr].text != '\0')
|
||||
{
|
||||
if (text_sets.sets[text_curr_nr].text_scroll)
|
||||
if (text_sets.sets[text_curr_nr].scroll)
|
||||
{
|
||||
disp_scroll_text();
|
||||
}
|
||||
|
@ -45,6 +47,39 @@ void LedDisplayController::disp_update()
|
|||
}
|
||||
}
|
||||
|
||||
String LedDisplayController::getTextSetParameter(int index, DisplayTextSetParameter parameter)
|
||||
{
|
||||
if (index < 0 || index > this->MaximumTextSets || parameter < 0 || parameter >= DisplayTextSetParameterCount)
|
||||
return "";
|
||||
|
||||
String value = "";
|
||||
this->getSetTextSetParameter(index, parameter, &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
LedDisplayController::GetSetTextSetParameterExitCode LedDisplayController::setTextSetParameter(int index, DisplayTextSetParameter parameter, String value)
|
||||
{
|
||||
return this->getSetTextSetParameter(index, parameter, &value, true);
|
||||
}
|
||||
|
||||
int LedDisplayController::getBrightness()
|
||||
{
|
||||
return this->disp_brightness;
|
||||
}
|
||||
|
||||
bool LedDisplayController::setBrightness(int brightness)
|
||||
{
|
||||
if (brightness < 0 || brightness > 10)
|
||||
return false;
|
||||
this->disp_brightness = brightness;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// - Matrix control -
|
||||
// ------------------
|
||||
|
||||
void LedDisplayController::disp_init()
|
||||
{
|
||||
text_curr_nr = 0;
|
||||
|
@ -54,6 +89,50 @@ void LedDisplayController::disp_init()
|
|||
disp_show = true;
|
||||
}
|
||||
|
||||
void LedDisplayController::disp_start_set()
|
||||
{
|
||||
if ((0 == text_set_starttime) ||
|
||||
(text_sets.sets[text_curr_nr].text == '\0') ||
|
||||
text_sets.sets[text_curr_nr].active == false ||
|
||||
((text_sets.sets[text_curr_nr].scroll == false) && (text_sets.sets[text_curr_nr].runtime > 0) && ((millis() - text_set_starttime) >= text_sets.sets[text_curr_nr].runtime)) ||
|
||||
((text_sets.sets[text_curr_nr].scroll == true) && (text_sets.sets[text_curr_nr].scrollCount > 0) && (text_pass >= text_sets.sets[text_curr_nr].scrollCount)) ||
|
||||
(((text_sets.sets[text_curr_nr].scrollCount == 0) || text_sets.sets[text_curr_nr].scroll == false) && (text_sets.sets[text_curr_nr].runtime == 0) && ((millis() - text_set_starttime) >= 10000)))
|
||||
{
|
||||
//Serial.printf("[%lu] Meet start set condition. Curr set is %d. \n", millis(), text_curr_nr);
|
||||
if (0 < text_set_starttime || text_sets.sets[text_curr_nr].text == '\0' || text_sets.sets[text_curr_nr].active == false)
|
||||
text_curr_nr++;
|
||||
if (text_curr_nr == MaximumTextSets)
|
||||
text_curr_nr = 0;
|
||||
text_pass = 0;
|
||||
if (text_sets.sets[text_curr_nr].text != '\0' && text_sets.sets[text_curr_nr].active == true)
|
||||
{
|
||||
//Serial.printf("[%lu] Set %d. Runtime %d. Text:'%s'\n", millis(), text_curr_nr, text_sets.sets[text_curr_nr].runtime, text_sets.sets[text_curr_nr].text);
|
||||
this->matrix->fillScreen(0);
|
||||
textpixel = 6 * strlen(text_sets.sets[text_curr_nr].text);
|
||||
switch (text_sets.sets[text_curr_nr].alignment)
|
||||
{
|
||||
case AlignLeft:
|
||||
text_pos = 0;
|
||||
break;
|
||||
case AlignRight:
|
||||
text_pos = this->matrix->width();
|
||||
break;
|
||||
case AlignCenter:
|
||||
text_pos = this->matrix->width() - textpixel;
|
||||
text_pos = text_pos / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
show_matrix(text_sets.sets[text_curr_nr].text, text_pos, text_sets.sets[text_curr_nr].color);
|
||||
text_set_starttime = millis();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Serial.printf("[%lu] Don't meet start set condition. Text is: %s. Active is: %d\n", millis(), text_sets.sets[text_curr_nr].text, text_sets.sets[text_curr_nr].active);
|
||||
}
|
||||
}
|
||||
|
||||
void LedDisplayController::disp_scroll_text()
|
||||
{
|
||||
this->matrix->fillScreen(0);
|
||||
|
@ -63,58 +142,15 @@ void LedDisplayController::disp_scroll_text()
|
|||
{
|
||||
text_pos = this->matrix->width();
|
||||
text_pass++;
|
||||
Serial.printf("Pass[%d] - set nr %d, Text: '%s' \n", text_pass, text_curr_nr, text_sets.sets[text_curr_nr].text);
|
||||
//Serial.printf("Pass[%d] - set nr %d, Text: '%s' \n", text_pass, text_curr_nr, text_sets.sets[text_curr_nr].text);
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
|
||||
void LedDisplayController::disp_start_set()
|
||||
void LedDisplayController::show_matrix(const char *text, int pos, const char *color)
|
||||
{
|
||||
if ((0 == text_set_starttime) ||
|
||||
(text_sets.sets[text_curr_nr].text == '\0') ||
|
||||
text_sets.sets[text_curr_nr].active == false ||
|
||||
((text_sets.sets[text_curr_nr].text_scroll == false) && (text_sets.sets[text_curr_nr].time_ms > 0) && ((millis() - text_set_starttime) >= text_sets.sets[text_curr_nr].time_ms)) ||
|
||||
((text_sets.sets[text_curr_nr].text_scroll == true) && (text_sets.sets[text_curr_nr].text_scroll_pass > 0) && (text_pass >= text_sets.sets[text_curr_nr].text_scroll_pass)) ||
|
||||
(((text_sets.sets[text_curr_nr].text_scroll_pass == 0) || text_sets.sets[text_curr_nr].text_scroll == false) && (text_sets.sets[text_curr_nr].time_ms == 0) && ((millis() - text_set_starttime) >= 10000)))
|
||||
{
|
||||
//Serial.printf("[%lu] Meet start set condition. Curr set is %d. \n", millis(), text_curr_nr);
|
||||
if (0 < text_set_starttime || text_sets.sets[text_curr_nr].text == '\0' || text_sets.sets[text_curr_nr].active == false)
|
||||
text_curr_nr++;
|
||||
if (text_curr_nr == text_nr_sets)
|
||||
text_curr_nr = 0;
|
||||
text_pass = 0;
|
||||
if (text_sets.sets[text_curr_nr].text != '\0' && text_sets.sets[text_curr_nr].active == true)
|
||||
{
|
||||
Serial.printf("[%lu] Set %d. Runtime %d. Text:'%s'\n", millis(), text_curr_nr, text_sets.sets[text_curr_nr].time_ms, text_sets.sets[text_curr_nr].text);
|
||||
this->matrix->fillScreen(0);
|
||||
textpixel = 6 * strlen(text_sets.sets[text_curr_nr].text);
|
||||
switch (text_sets.sets[text_curr_nr].align)
|
||||
{
|
||||
case TEXTLEFT:
|
||||
text_pos = 0;
|
||||
break;
|
||||
case TEXTRIGHT:
|
||||
text_pos = this->matrix->width();
|
||||
break;
|
||||
case TEXTCENTER:
|
||||
text_pos = this->matrix->width() - textpixel;
|
||||
text_pos = text_pos / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
show_matrix(text_sets.sets[text_curr_nr].text, text_pos, text_sets.sets[text_curr_nr].color);
|
||||
text_set_starttime = millis();
|
||||
}
|
||||
}
|
||||
else {
|
||||
//Serial.printf("[%lu] Don't meet start set condition. Text is: %s. Active is: %d\n", millis(), text_sets.sets[text_curr_nr].text, text_sets.sets[text_curr_nr].active);
|
||||
}
|
||||
}
|
||||
|
||||
void LedDisplayController::show_matrix(const char *text, int pos, uint16_t color)
|
||||
{
|
||||
Serial.printf("TEXT: %s (pos=%d, color=%d)\n", text, pos, color);
|
||||
this->matrix->setTextColor(color);
|
||||
//Serial.printf("TEXT: %s (pos=%d, color=%d)\n", text, pos, this->colorFromHex(String(color)));
|
||||
this->matrix->setTextColor(this->colorFromHex(String(color)));
|
||||
this->matrix->setCursor(pos, 0);
|
||||
this->matrix->print(text);
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
@ -122,10 +158,135 @@ void LedDisplayController::show_matrix(const char *text, int pos, uint16_t color
|
|||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
|
||||
void LedDisplayController::storeDisplaySet()
|
||||
uint16_t LedDisplayController::colorFromHex(String hex)
|
||||
{
|
||||
|
||||
hex.replace("#", "");
|
||||
|
||||
long number = (long)strtol(&hex[0], NULL, 16);
|
||||
int r = number >> 16;
|
||||
int g = number >> 8 & 0xFF;
|
||||
int b = number & 0xFF;
|
||||
|
||||
//Serial.println("Color is: " + hex + " rgb are: r: " + r + " b: " + b + " g: " + g);
|
||||
|
||||
return this->matrix->Color(r, g, b);
|
||||
}
|
||||
|
||||
// -------------------
|
||||
// - Storage control -
|
||||
// -------------------
|
||||
|
||||
LedDisplayController::GetSetTextSetParameterExitCode LedDisplayController::getSetTextSetParameter(int index, DisplayTextSetParameter parameter, String *value, bool set)
|
||||
{
|
||||
if (parameter < 0 || parameter >= DisplayTextSetParameterCount)
|
||||
return InvalidParameterError;
|
||||
else if (index < 0 || index >= this->MaximumTextSets)
|
||||
return IndexOutOfRangeError;
|
||||
else if (value == nullptr)
|
||||
return ValueIsNullptrError;
|
||||
else if (strcmp(this->text_sets.valid, "OK") != 0)
|
||||
return InternalError;
|
||||
|
||||
text_set_t *currentTextSet = &this->text_sets.sets[index];
|
||||
String returnValue = "";
|
||||
|
||||
switch (parameter)
|
||||
{
|
||||
case TextParameter:
|
||||
if (set)
|
||||
strncpy(currentTextSet->text, value->c_str(), sizeof(currentTextSet->text));
|
||||
else
|
||||
returnValue = String(currentTextSet->text);
|
||||
break;
|
||||
|
||||
case ActiveParameter:
|
||||
if (set)
|
||||
currentTextSet->active = *value == "true";
|
||||
else
|
||||
returnValue = currentTextSet->active ? "true" : "false";
|
||||
break;
|
||||
|
||||
case RuntimeParameter:
|
||||
if (set)
|
||||
currentTextSet->runtime = value->toInt();
|
||||
else
|
||||
returnValue = String(currentTextSet->runtime);
|
||||
break;
|
||||
|
||||
case ColorParameter:
|
||||
if (set)
|
||||
strncpy(currentTextSet->color, value->c_str(), sizeof(currentTextSet->color));
|
||||
else
|
||||
returnValue = String(currentTextSet->color);
|
||||
break;
|
||||
|
||||
case AlignmentParameter:
|
||||
if (set)
|
||||
{
|
||||
if (value->toInt() < 0 || value->toInt() > AlignRight)
|
||||
return ValueOutOfRangeError;
|
||||
currentTextSet->alignment = text_align_t(value->toInt());
|
||||
}
|
||||
else
|
||||
returnValue = String(currentTextSet->alignment);
|
||||
break;
|
||||
|
||||
case ScrollParameter:
|
||||
if (set)
|
||||
currentTextSet->scroll = *value == "true";
|
||||
else
|
||||
returnValue = currentTextSet->scroll ? "true" : "false";
|
||||
break;
|
||||
|
||||
case ScrollSpeedParameter:
|
||||
if (set)
|
||||
{
|
||||
if (value->toInt() < 0 || value->toInt() > 10)
|
||||
return ValueOutOfRangeError;
|
||||
currentTextSet->scrollSpeed = value->toInt();
|
||||
}
|
||||
else
|
||||
returnValue = String(currentTextSet->scrollSpeed);
|
||||
break;
|
||||
|
||||
case ScrollCountParameter:
|
||||
if (set)
|
||||
{
|
||||
if (value->toInt() < 0)
|
||||
return ValueOutOfRangeError;
|
||||
currentTextSet->scrollCount = value->toInt();
|
||||
}
|
||||
else
|
||||
returnValue = String(currentTextSet->scrollCount);
|
||||
break;
|
||||
|
||||
case IndexParameter:
|
||||
if (set)
|
||||
return ParameterNotWritableError;
|
||||
else
|
||||
returnValue = String(index);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (set)
|
||||
{
|
||||
this->storeTextSets();
|
||||
return Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = returnValue;
|
||||
return Success;
|
||||
}
|
||||
}
|
||||
|
||||
void LedDisplayController::storeTextSets()
|
||||
{
|
||||
// write conf to EEPROM
|
||||
EEPROM.begin(DISP_STRUCT_SIZE);
|
||||
EEPROM.begin(sizeof(sets_t));
|
||||
//for (size_t i = 0 ; i < DISP_STRUCT_SIZE ; i++)
|
||||
//{
|
||||
// EEPROM.write(i, 0);
|
||||
|
@ -136,12 +297,12 @@ void LedDisplayController::storeDisplaySet()
|
|||
EEPROM.end();
|
||||
}
|
||||
|
||||
bool LedDisplayController::loadDisplaySet()
|
||||
bool LedDisplayController::loadTextSets()
|
||||
{
|
||||
bool rc = false;
|
||||
sets_t buf = {};
|
||||
// read conf from EEPROM
|
||||
EEPROM.begin(DISP_STRUCT_SIZE);
|
||||
EEPROM.begin(sizeof(sets_t));
|
||||
EEPROM.get(0, buf);
|
||||
EEPROM.end();
|
||||
if (strcmp(buf.valid, "OK") == 0)
|
||||
|
@ -151,108 +312,44 @@ bool LedDisplayController::loadDisplaySet()
|
|||
}
|
||||
else
|
||||
{
|
||||
memset(&text_sets, 0, sizeof(text_sets));
|
||||
// There was an error reading the sets -> rebuild with default values!
|
||||
|
||||
sets_t defaultTextSets;
|
||||
|
||||
strncpy(defaultTextSets.valid, "OK", sizeof(defaultTextSets.valid));
|
||||
|
||||
for (int i = 0; i < this->MaximumTextSets; i++)
|
||||
{
|
||||
text_set_t defaultTextSet{
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"",
|
||||
AlignCenter,
|
||||
false,
|
||||
0,
|
||||
0};
|
||||
|
||||
defaultTextSets.sets[i] = defaultTextSet;
|
||||
}
|
||||
|
||||
this->text_sets = defaultTextSets;
|
||||
this->storeTextSets();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
String LedDisplayController::get_paramstring_from_struct(String name)
|
||||
{
|
||||
return (getset_param_at_struct(name, "", false));
|
||||
}
|
||||
|
||||
void LedDisplayController::set_param_to_struct(String name, String value)
|
||||
{
|
||||
getset_param_at_struct(name, value, true);
|
||||
}
|
||||
|
||||
String LedDisplayController::getset_param_at_struct(String name, String value, bool set)
|
||||
{
|
||||
String name_value = "";
|
||||
int name_setnr_index = name.lastIndexOf("_");
|
||||
int name_setnr = -1;
|
||||
int name_index = -1;
|
||||
String name_name = "unknown";
|
||||
if (name_setnr_index > 0)
|
||||
{
|
||||
name_setnr = name.substring(name_setnr_index + 1).toInt();
|
||||
name_name = name.substring(0, name_setnr_index + 1);
|
||||
|
||||
for (int pnr = 0; pnr < nr_param_names; pnr++)
|
||||
{
|
||||
if (name_name == set_param_name[pnr])
|
||||
{
|
||||
name_index = pnr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Serial.printf("Param: (name=%s,set=%d, index=%d) %s = %s \n", name_name.c_str(), name_setnr, name_index, name.c_str(), value.c_str());
|
||||
if (name_index != -1 && name_setnr != -1 && name_name != "unknown")
|
||||
{
|
||||
name_value += name_name + String(name_setnr) + "=";
|
||||
switch (name_index)
|
||||
{
|
||||
case PCOLOR:
|
||||
//if (true == set)
|
||||
//text_sets.sets[name_setnr].color = (unint16_t)value.toInt();
|
||||
name_value += String(text_sets.sets[name_setnr].color);
|
||||
break;
|
||||
case PTEXT:
|
||||
if (true == set)
|
||||
snprintf((char *)text_sets.sets[name_setnr].text, MAX_TXT_LENGTH, value.c_str());
|
||||
name_value += String(text_sets.sets[name_setnr].text);
|
||||
break;
|
||||
case PTIME:
|
||||
if (true == set)
|
||||
text_sets.sets[name_setnr].time_ms = value.toInt() * 1000;
|
||||
name_value += String(text_sets.sets[name_setnr].time_ms / 1000);
|
||||
break;
|
||||
case PSCROLL:
|
||||
if (true == set)
|
||||
text_sets.sets[name_setnr].text_scroll = (value == "true") ? true : false;
|
||||
name_value += String(text_sets.sets[name_setnr].text_scroll);
|
||||
break;
|
||||
case PACTIVE:
|
||||
if (true == set)
|
||||
text_sets.sets[name_setnr].active = (value == "true") ? true : false;
|
||||
name_value += String(text_sets.sets[name_setnr].active);
|
||||
break;
|
||||
case PALIGN:
|
||||
if (true == set)
|
||||
text_sets.sets[name_setnr].align = (text_align_t)value.toInt();
|
||||
name_value += String(text_sets.sets[name_setnr].align);
|
||||
break;
|
||||
case PSCROLL_RUNS:
|
||||
if (true == set)
|
||||
text_sets.sets[name_setnr].text_scroll_pass = value.toInt();
|
||||
name_value += String(text_sets.sets[name_setnr].text_scroll_pass);
|
||||
break;
|
||||
}
|
||||
//Serial.printf("get/set %s\n", name_value.c_str());
|
||||
}
|
||||
}
|
||||
return (name_value);
|
||||
}
|
||||
|
||||
void LedDisplayController::setTexts(sets_t texts) {
|
||||
this->text_sets = texts;
|
||||
this->storeDisplaySet();
|
||||
}
|
||||
|
||||
LedDisplayController::sets_t LedDisplayController::getTexts() {
|
||||
return this->text_sets;
|
||||
}
|
||||
|
||||
uint16_t LedDisplayController::Color(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return this->matrix->Color(r,g,b);
|
||||
}
|
||||
// ----------
|
||||
// - Extern -
|
||||
// ----------
|
||||
|
||||
void updateDisplayGlobal(void *)
|
||||
{
|
||||
for(;;) {
|
||||
for (;;)
|
||||
{
|
||||
esp_task_wdt_reset();
|
||||
delay(1);
|
||||
ledDisplayControllerGlobal->disp_update();
|
||||
ledDisplayControllerGlobal->loop();
|
||||
}
|
||||
}
|
|
@ -1,17 +1,12 @@
|
|||
|
||||
#include "OmobiLedDisplay.h"
|
||||
|
||||
OmobiLedDisplay::OmobiLedDisplay(String deviceName, const byte ledPin)
|
||||
OmobiLedDisplay::OmobiLedDisplay(String deviceName, Adafruit_NeoMatrix *ledDisplayMatrix)
|
||||
{
|
||||
this->ledDisplayController = new LedDisplayController(ledPin);
|
||||
|
||||
this->ledDisplayController->setTexts(LedDisplayController::sets_t{
|
||||
{// TEXT , SHOWTIME, COLOR, ALIGNMENT, SCROLL, SCROLLNR, ACTIVE
|
||||
{"itsblue", 5000, ledDisplayController->Color(0, 0, 255), LedDisplayController::TEXTCENTER, false, 1, true},
|
||||
{"", 0, ledDisplayController->Color(0, 0, 255), LedDisplayController::TEXTCENTER, false, 4, false}
|
||||
},
|
||||
"OK"});
|
||||
// init led display controller
|
||||
this->ledDisplayController = new LedDisplayController(ledDisplayMatrix);
|
||||
this->ledDisplayController->setTextSetParameter(0, LedDisplayController::ActiveParameter, "true");
|
||||
|
||||
// init ble server
|
||||
this->bleServer = new BluetoothLeUartServer(deviceName, "6e400001-b5a3-f393-e0a9-e50e24dcca9e", "6e400002-b5a3-f393-e0a9-e50e24dcca9e", "6e400003-b5a3-f393-e0a9-e50e24dcca9e");
|
||||
this->bleServer->setCallbacks(this);
|
||||
}
|
||||
|
@ -20,121 +15,109 @@ void OmobiLedDisplay::onDeviceConnectedChanged(bool deviceConnected)
|
|||
{
|
||||
if (deviceConnected)
|
||||
Serial.println("Device connected");
|
||||
else
|
||||
Serial.println("Device disconnected");
|
||||
}
|
||||
|
||||
void OmobiLedDisplay::onDataReceived(String data)
|
||||
void OmobiLedDisplay::onDataReceived(String dataString)
|
||||
{
|
||||
if (data.startsWith("GET_TEXTS"))
|
||||
// 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");
|
||||
|
||||
switch (requestHeader)
|
||||
{
|
||||
const size_t capacity = JSON_ARRAY_SIZE(LedDisplayController::text_nr_sets) + LedDisplayController::text_nr_sets * (JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(8));
|
||||
case GetAllTextSetsCommand:
|
||||
{
|
||||
// cycle through all text sets
|
||||
for (int textSetIndex = 0; textSetIndex < LedDisplayController::MaximumTextSets; textSetIndex++)
|
||||
{
|
||||
if (this->ledDisplayController->getTextSetParameter(textSetIndex, LedDisplayController::TextParameter) == "")
|
||||
continue;
|
||||
|
||||
//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++)
|
||||
{
|
||||
// send each parameter to the client
|
||||
const size_t capacity = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 200;
|
||||
DynamicJsonDocument doc(capacity);
|
||||
|
||||
for (int i = 0; i < LedDisplayController::text_nr_sets; i++)
|
||||
{
|
||||
LedDisplayController::text_set_t textSet = this->ledDisplayController->getTexts().sets[i];
|
||||
JsonObject doc_0 = doc.createNestedObject();
|
||||
doc_0["active"] = textSet.active;
|
||||
doc_0["alignment"] = textSet.align;
|
||||
doc["header"] = GetTextSetParameterCommand;
|
||||
|
||||
JsonObject doc_0_color = doc_0.createNestedObject("color");
|
||||
doc_0_color["r"] = 0;
|
||||
doc_0_color["g"] = 0;
|
||||
doc_0_color["b"] = 0;
|
||||
|
||||
doc_0["runtime"] = textSet.time_ms;
|
||||
doc_0["scroll"] = textSet.text_scroll;
|
||||
doc_0["scrollCount"] = textSet.text_scroll_pass;
|
||||
doc_0["scrollSpeed"] = 5;
|
||||
doc_0["text"] = textSet.text;
|
||||
}
|
||||
JsonObject data = doc.createNestedObject("data");
|
||||
data["index"] = textSetIndex;
|
||||
data["parameter"] = textSetParameter;
|
||||
data["value"] = this->ledDisplayController->getTextSetParameter(
|
||||
textSetIndex,
|
||||
LedDisplayController::DisplayTextSetParameter(textSetParameter));
|
||||
|
||||
String json;
|
||||
serializeJson(doc, json);
|
||||
this->bleServer->sendData("GET_TEXTS:" + json);
|
||||
this->bleServer->sendData(json);
|
||||
}
|
||||
}
|
||||
else if (data.startsWith("SET_TEXTS:"))
|
||||
{
|
||||
const size_t capacity = JSON_ARRAY_SIZE(LedDisplayController::text_nr_sets) + LedDisplayController::text_nr_sets * JSON_OBJECT_SIZE(8) + 270;
|
||||
DynamicJsonDocument doc(capacity);
|
||||
|
||||
data.replace("SET_TEXTS:", "");
|
||||
Serial.println("Got new SET TEXT:" + data);
|
||||
// TODO: handle Error!
|
||||
DeserializationError err = deserializeJson(doc, data);
|
||||
replyStatus = Success;
|
||||
replyData["maximumTextSets"] = LedDisplayController::MaximumTextSets;
|
||||
replyData["maximumTextLength"] = LedDisplayController::MaximumTextLength;
|
||||
|
||||
Serial.println("deserialization result: " + String(err.c_str()));
|
||||
|
||||
if(err != DeserializationError::Ok)
|
||||
return;
|
||||
|
||||
JsonArray textsArray = doc.as<JsonArray>();
|
||||
|
||||
LedDisplayController::sets_t textSets;
|
||||
strncpy(textSets.valid, "OK", sizeof(textSets.valid));
|
||||
|
||||
for (int i = 0; i < textsArray.size(); i++)
|
||||
{
|
||||
Serial.println(" | Processing index " + String(i));
|
||||
|
||||
if (i >= LedDisplayController::text_nr_sets)
|
||||
break;
|
||||
|
||||
JsonObject textObject = textsArray[i].as<JsonObject>();
|
||||
|
||||
if(
|
||||
!textObject.containsKey("text") ||
|
||||
!textObject.containsKey("runtime") ||
|
||||
//!textObject.containsKey("color") ||
|
||||
!textObject.containsKey("scroll") ||
|
||||
!textObject.containsKey("scrollCount") ||
|
||||
!textObject.containsKey("active") ||
|
||||
!textObject.containsKey("alignment")
|
||||
)
|
||||
continue;
|
||||
|
||||
LedDisplayController::text_set_t textSet;
|
||||
|
||||
const char* text = textObject["text"];
|
||||
strncpy(textSet.text, text, sizeof(textSet.text));
|
||||
|
||||
uint16_t runtime = textObject["runtime"];
|
||||
textSet.time_ms = runtime;
|
||||
|
||||
//JsonObject colorObject = textObject["color"].as<JsonObject>();
|
||||
//uint16_t color = this->ledDisplayController->Color(colorObject["r"], colorObject["color"]["g"], colorObject["color"]["b"]);
|
||||
//textSet.color = color;
|
||||
|
||||
bool scroll = textObject["scroll"];
|
||||
textSet.text_scroll = scroll;
|
||||
|
||||
uint16_t scrollCount = textObject["scrollCount"];
|
||||
textSet.text_scroll_pass = scrollCount;
|
||||
|
||||
bool active = textObject["active"];
|
||||
textSet.active = active;
|
||||
|
||||
int alignment = textObject["alignment"];
|
||||
textSet.align = LedDisplayController::text_align_t(alignment);
|
||||
|
||||
Serial.println(
|
||||
" | Got set: text: " + String(textSet.text) +
|
||||
" time: " + String(textSet.time_ms) +
|
||||
" color: " + String(textSet.color) +
|
||||
" scroll: " + String(textSet.text_scroll) +
|
||||
" scrollCount: " + String(textSet.text_scroll_pass) +
|
||||
" active: " + String(textSet.active)
|
||||
);
|
||||
|
||||
|
||||
textSets.sets[i] = textSet;
|
||||
}
|
||||
case GetDisplayBrightnessCommand:
|
||||
{
|
||||
replyData["displayBrightness"] = this->ledDisplayController->getBrightness();
|
||||
replyStatus = Success;
|
||||
break;
|
||||
}
|
||||
|
||||
this->ledDisplayController->setTexts(textSets);
|
||||
case SetTextSetParameterCommand:
|
||||
{
|
||||
int index = requestData["index"];
|
||||
int parameter = requestData["parameter"];
|
||||
String value = requestData["value"];
|
||||
|
||||
this->bleServer->sendData("SET_TEXTS:OK");
|
||||
LedDisplayController::GetSetTextSetParameterExitCode res = this->ledDisplayController->setTextSetParameter(index, LedDisplayController::DisplayTextSetParameter(parameter), value);
|
||||
|
||||
if (res == LedDisplayController::Success)
|
||||
replyStatus = Success;
|
||||
else
|
||||
{
|
||||
replyStatus = DisplayControllerError;
|
||||
replyData["displayControllerError"] = res;
|
||||
}
|
||||
else if (data.startsWith("GET_BRIGHTNESS"))
|
||||
this->bleServer->sendData("GET_BRIGHTNESS:5");
|
||||
else if (data.startsWith("SET_BRIGHTNESS:"))
|
||||
this->bleServer->sendData("SET_BRIGHTNESS:OK");
|
||||
|
||||
break;
|
||||
}
|
||||
case SetDisplayBrightnessCommand:
|
||||
{
|
||||
this->ledDisplayController->setBrightness(requestData["displayBrightness"]);
|
||||
replyStatus = Success;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// reply to the client
|
||||
replyDoc["status"] = replyStatus;
|
||||
String json;
|
||||
serializeJson(replyDoc, json);
|
||||
this->bleServer->sendData(json);
|
||||
}
|
|
@ -1,33 +1,31 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
//#include "BluetoothLeUartServer.h"
|
||||
#include "OmobiLedDisplay.h"
|
||||
|
||||
#define PIN 4
|
||||
|
||||
OmobiLedDisplay *display;
|
||||
|
||||
class MyCallbacks : public BluetoothLeUartServerCallbacks {
|
||||
virtual void onDeviceConnectedChanged(bool deviceConnected) {
|
||||
Serial.println("Device connected changed");
|
||||
};
|
||||
virtual void onDataReceived(String data) {
|
||||
Serial.println("Got some data: " + data);
|
||||
};
|
||||
};
|
||||
|
||||
//BluetoothLeUartServer* server;
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.printf("Los\n");
|
||||
|
||||
display = new OmobiLedDisplay("OmobiLedDisplay1", PIN);
|
||||
//server = new BluetoothLeUartServer("OmobiLedDisplay1", "6e400001-b5a3-f393-e0a9-e50e24dcca9e", "6e400002-b5a3-f393-e0a9-e50e24dcca9e", "6e400003-b5a3-f393-e0a9-e50e24dcca9e");
|
||||
//server->setCallbacks(new MyCallbacks());
|
||||
Adafruit_NeoMatrix *displayMatrix = new Adafruit_NeoMatrix(
|
||||
8,
|
||||
8,
|
||||
1,
|
||||
1,
|
||||
PIN,
|
||||
NEO_TILE_TOP + NEO_TILE_LEFT + NEO_TILE_ROWS + NEO_TILE_PROGRESSIVE +
|
||||
NEO_MATRIX_TOP + NEO_MATRIX_LEFT + NEO_MATRIX_ROWS + NEO_TILE_PROGRESSIVE,
|
||||
NEO_GRB + NEO_KHZ800);
|
||||
|
||||
// create our display
|
||||
display = new OmobiLedDisplay("OmobiLedDisplay1", displayMatrix);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// nothing to do in loop
|
||||
delay(1000);
|
||||
}
|
Loading…
Reference in a new issue