2017-10-19 15:43:39 +00:00
|
|
|
#include "ESPUI.h"
|
2017-10-16 13:00:53 +00:00
|
|
|
#include <ESPAsyncWebServer.h>
|
2017-05-18 22:05:32 +00:00
|
|
|
#include <functional>
|
|
|
|
|
2017-10-16 13:00:53 +00:00
|
|
|
// Handle Websockets Communication
|
2017-11-13 15:10:56 +00:00
|
|
|
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
|
|
|
|
AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
|
|
|
switch (type) {
|
|
|
|
case WS_EVT_DISCONNECT:
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.printf("Disconnected!\n");
|
2017-11-13 15:10:56 +00:00
|
|
|
break;
|
|
|
|
case WS_EVT_CONNECT: {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println("Connected");
|
2017-11-13 15:10:56 +00:00
|
|
|
ESPUI.jsonDom(client);
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println("JSON Data Sent to Client!");
|
2017-11-13 15:10:56 +00:00
|
|
|
} break;
|
|
|
|
case WS_EVT_DATA:
|
|
|
|
String msg = "";
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
msg += (char)data[i];
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
2017-11-13 15:10:56 +00:00
|
|
|
if (msg.startsWith("bdown:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(6).toInt()];
|
|
|
|
c->callback(*c, B_DOWN);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("bup:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(4).toInt()];
|
|
|
|
c->callback(*c, B_UP);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("pfdown:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(7).toInt()];
|
|
|
|
c->callback(*c, P_FOR_DOWN);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("pfup:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(5).toInt()];
|
|
|
|
c->callback(*c, P_FOR_UP);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("pldown:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(7).toInt()];
|
|
|
|
c->callback(*c, P_LEFT_DOWN);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("plup:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(5).toInt()];
|
|
|
|
c->callback(*c, P_LEFT_UP);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("prdown:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(7).toInt()];
|
|
|
|
c->callback(*c, P_RIGHT_DOWN);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("prup:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(5).toInt()];
|
|
|
|
c->callback(*c, P_RIGHT_UP);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("pbdown:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(7).toInt()];
|
|
|
|
c->callback(*c, P_BACK_DOWN);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("pbup:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(5).toInt()];
|
|
|
|
c->callback(*c, P_BACK_UP);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("pcdown:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(7).toInt()];
|
|
|
|
c->callback(*c, P_CENTER_DOWN);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("pcup:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(5).toInt()];
|
|
|
|
c->callback(*c, P_CENTER_UP);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("sactive:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(8).toInt()];
|
2017-11-13 15:10:56 +00:00
|
|
|
ESPUI.updateSwitcher(c->id, true);
|
2017-11-14 11:09:52 +00:00
|
|
|
c->callback(*c, S_ACTIVE);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else if (msg.startsWith("sinactive:")) {
|
2017-11-14 11:09:52 +00:00
|
|
|
Control *c = ESPUI.controls[msg.substring(10).toInt()];
|
2017-11-13 15:10:56 +00:00
|
|
|
ESPUI.updateSwitcher(c->id, false);
|
2017-11-14 11:09:52 +00:00
|
|
|
c->callback(*c, S_INACTIVE);
|
2017-11-13 15:10:56 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
2017-10-16 22:10:48 +00:00
|
|
|
|
2017-11-14 11:09:52 +00:00
|
|
|
void ESPUIClass::label(const char *label, int color, String value) {
|
2017-11-13 15:10:56 +00:00
|
|
|
if (labelExists(label)) {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println("UI ERROR: Element " + String(label) +
|
|
|
|
" exists, skipping creating element!");
|
2017-11-13 15:10:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Control *newL = new Control();
|
2017-10-19 11:46:47 +00:00
|
|
|
newL->type = UI_LABEL;
|
|
|
|
newL->label = label;
|
2017-11-14 11:09:52 +00:00
|
|
|
newL->color = color;
|
2017-11-13 15:10:56 +00:00
|
|
|
if (value != "")
|
|
|
|
newL->value = value; // Init with labeltext
|
|
|
|
else
|
|
|
|
newL->value = String(label);
|
2017-10-19 11:46:47 +00:00
|
|
|
newL->callback = NULL;
|
2017-11-13 15:10:56 +00:00
|
|
|
newL->id = cIndex;
|
2017-10-19 11:46:47 +00:00
|
|
|
controls[cIndex] = newL;
|
|
|
|
cIndex++;
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
|
|
|
|
2017-11-14 11:09:52 +00:00
|
|
|
void ESPUIClass::button(const char *label, void (*callBack)(Control, int), int color,
|
|
|
|
String value) {
|
2017-11-13 15:10:56 +00:00
|
|
|
if (labelExists(label)) {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println("UI ERROR: Element " + String(label) +
|
|
|
|
" exists, skipping creating element!");
|
2017-11-13 15:10:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Control *newB = new Control();
|
2017-10-19 11:46:47 +00:00
|
|
|
newB->type = UI_BUTTON;
|
|
|
|
newB->label = label;
|
2017-11-14 11:09:52 +00:00
|
|
|
newB->color = color;
|
2017-11-13 16:22:02 +00:00
|
|
|
|
|
|
|
if (value != "")
|
|
|
|
newB->value = value; // Init with labeltext
|
|
|
|
else
|
|
|
|
newB->value = String(label);
|
|
|
|
|
2017-10-16 23:10:29 +00:00
|
|
|
newB->callback = callBack;
|
2017-11-13 15:10:56 +00:00
|
|
|
newB->id = cIndex;
|
2017-10-19 11:46:47 +00:00
|
|
|
controls[cIndex] = newB;
|
|
|
|
cIndex++;
|
2017-10-16 13:00:53 +00:00
|
|
|
}
|
2017-10-19 11:46:47 +00:00
|
|
|
|
2017-11-14 11:09:52 +00:00
|
|
|
void ESPUIClass::switcher(const char *label, bool startState,
|
|
|
|
void (*callBack)(Control, int), int color) {
|
2017-11-13 15:10:56 +00:00
|
|
|
if (labelExists(label)) {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println("UI ERROR: Element " + String(label) +
|
|
|
|
" exists, skipping creating element!");
|
2017-11-13 15:10:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Control *newS = new Control();
|
2017-10-19 11:46:47 +00:00
|
|
|
newS->type = UI_SWITCHER;
|
|
|
|
newS->label = label;
|
2017-11-14 11:09:52 +00:00
|
|
|
newS->color = color;
|
2017-10-19 15:30:32 +00:00
|
|
|
newS->value = String(startState);
|
2017-10-19 11:46:47 +00:00
|
|
|
newS->callback = callBack;
|
2017-11-13 15:10:56 +00:00
|
|
|
newS->id = cIndex;
|
2017-10-19 11:46:47 +00:00
|
|
|
controls[cIndex] = newS;
|
|
|
|
cIndex++;
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
|
|
|
|
2017-11-14 11:09:52 +00:00
|
|
|
void ESPUIClass::pad(const char *label, bool center,
|
|
|
|
void (*callBack)(Control, int), int color) {
|
2017-11-13 15:10:56 +00:00
|
|
|
if (labelExists(label)) {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println("UI ERROR: Element " + String(label) +
|
|
|
|
" exists, skipping creating element!");
|
2017-11-13 15:10:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Control *newP = new Control();
|
|
|
|
if (center)
|
|
|
|
newP->type = UI_CPAD;
|
|
|
|
else
|
|
|
|
newP->type = UI_PAD;
|
2017-10-19 11:46:47 +00:00
|
|
|
newP->label = label;
|
2017-11-14 11:09:52 +00:00
|
|
|
newP->color = color;
|
2017-10-19 11:46:47 +00:00
|
|
|
newP->callback = callBack;
|
2017-11-13 15:10:56 +00:00
|
|
|
newP->id = cIndex;
|
2017-10-19 11:46:47 +00:00
|
|
|
controls[cIndex] = newP;
|
|
|
|
cIndex++;
|
|
|
|
}
|
2017-05-18 22:05:32 +00:00
|
|
|
|
2017-11-13 15:10:56 +00:00
|
|
|
void ESPUIClass::print(int id, String value) {
|
|
|
|
if (id < cIndex && controls[id]->type == UI_LABEL) {
|
2017-10-19 15:30:32 +00:00
|
|
|
controls[id]->value = value;
|
2017-10-19 11:46:47 +00:00
|
|
|
String json;
|
|
|
|
StaticJsonBuffer<200> jsonBuffer;
|
2017-11-13 15:10:56 +00:00
|
|
|
JsonObject &root = jsonBuffer.createObject();
|
2017-10-19 11:46:47 +00:00
|
|
|
root["type"] = UPDATE_LABEL;
|
2017-10-19 15:30:32 +00:00
|
|
|
root["value"] = value;
|
|
|
|
root["id"] = String(id);
|
2017-05-18 22:05:32 +00:00
|
|
|
root.printTo(json);
|
2017-10-19 11:46:47 +00:00
|
|
|
this->ws->textAll(json);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println(String("Error: ") + String(id) + String(" is no label"));
|
2017-10-19 15:30:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-13 15:10:56 +00:00
|
|
|
void ESPUIClass::print(String label, String value) {
|
|
|
|
if (!labelExists(label)) {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println("UI ERROR: Element does not " + String(label) +
|
|
|
|
" exist, cannot update!");
|
2017-11-13 15:10:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
print(getIdByLabel(label), value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ESPUIClass::updateSwitcher(int id, bool nValue) {
|
|
|
|
if (id < cIndex && controls[id]->type == UI_SWITCHER) {
|
|
|
|
controls[id]->value = nValue ? 1 : 0;
|
2017-10-19 15:30:32 +00:00
|
|
|
String json;
|
|
|
|
StaticJsonBuffer<200> jsonBuffer;
|
2017-11-13 15:10:56 +00:00
|
|
|
JsonObject &root = jsonBuffer.createObject();
|
2017-10-19 15:30:32 +00:00
|
|
|
root["type"] = UPDATE_SWITCH;
|
2017-11-13 15:10:56 +00:00
|
|
|
root["value"] = nValue ? 1 : 0;
|
2017-10-19 15:30:32 +00:00
|
|
|
root["id"] = String(id);
|
|
|
|
root.printTo(json);
|
|
|
|
this->ws->textAll(json);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println(String("Error: ") + String(id) +
|
|
|
|
String(" is no switcher"));
|
2017-11-13 15:10:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ESPUIClass::updateSwitcher(String label, bool nValue) {
|
|
|
|
if (!labelExists(label)) {
|
|
|
|
if (debug)
|
2017-11-14 11:09:52 +00:00
|
|
|
Serial.println("UI ERROR: Element does not " + String(label) +
|
|
|
|
" exist, cannot update!");
|
2017-11-13 15:10:56 +00:00
|
|
|
return;
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
2017-11-13 15:10:56 +00:00
|
|
|
updateSwitcher(getIdByLabel(label), nValue);
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
2017-10-19 11:46:47 +00:00
|
|
|
|
2017-11-13 15:10:56 +00:00
|
|
|
int ESPUIClass::getIdByLabel(String label) {
|
|
|
|
for (int i = 0; i < cIndex; i++) {
|
|
|
|
if (String(controls[i]->label) == label)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1; // failed, nonexistant
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ESPUIClass::labelExists(String label) {
|
|
|
|
for (int i = 0; i < cIndex; i++) {
|
2017-11-14 11:09:52 +00:00
|
|
|
if (String(controls[i]->label) == label)
|
|
|
|
return true;
|
2017-11-13 15:10:56 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2017-05-18 22:05:32 +00:00
|
|
|
|
2017-10-16 22:10:48 +00:00
|
|
|
// Convert & Transfer Arduino elements to JSON elements
|
2017-11-13 15:10:56 +00:00
|
|
|
void ESPUIClass::jsonDom(AsyncWebSocketClient *client) {
|
|
|
|
for (int i = -1; i < cIndex; i++) {
|
2017-05-18 22:05:32 +00:00
|
|
|
String json;
|
2017-10-19 11:46:47 +00:00
|
|
|
StaticJsonBuffer<200> jsonBuffer;
|
2017-11-13 15:10:56 +00:00
|
|
|
JsonObject &root = jsonBuffer.createObject();
|
|
|
|
if (i == -1) {
|
2017-10-19 11:46:47 +00:00
|
|
|
root["type"] = UI_TITEL;
|
|
|
|
root["label"] = String(ui_title);
|
2017-11-13 15:10:56 +00:00
|
|
|
} else {
|
2017-10-19 11:46:47 +00:00
|
|
|
root["type"] = controls[i]->type;
|
|
|
|
root["label"] = String(controls[i]->label);
|
2017-10-19 15:30:32 +00:00
|
|
|
root["value"] = String(controls[i]->value);
|
2017-11-14 11:09:52 +00:00
|
|
|
root["color"] = String(controls[i]->color);
|
2017-10-19 11:46:47 +00:00
|
|
|
root["id"] = String(i);
|
|
|
|
}
|
|
|
|
root.printTo(json);
|
2017-10-16 22:10:48 +00:00
|
|
|
client->text(json);
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
|
|
|
}
|
2017-10-16 22:10:48 +00:00
|
|
|
|
2017-11-13 15:10:56 +00:00
|
|
|
void ESPUIClass::begin(const char *_title) {
|
2017-10-19 11:46:47 +00:00
|
|
|
ui_title = _title;
|
2017-10-16 22:10:48 +00:00
|
|
|
server = new AsyncWebServer(80);
|
|
|
|
ws = new AsyncWebSocket("/ws");
|
2017-10-19 11:46:47 +00:00
|
|
|
SPIFFS.begin();
|
2017-10-16 22:10:48 +00:00
|
|
|
ws->onEvent(onWsEvent);
|
|
|
|
server->addHandler(ws);
|
|
|
|
server->serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm");
|
2017-10-16 13:00:53 +00:00
|
|
|
|
2017-11-13 15:10:56 +00:00
|
|
|
// Heap for general Servertest
|
|
|
|
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
|
2017-10-16 13:00:53 +00:00
|
|
|
request->send(200, "text/plain", String(ESP.getFreeHeap()));
|
|
|
|
});
|
|
|
|
|
2017-11-13 15:10:56 +00:00
|
|
|
server->onNotFound(
|
|
|
|
[](AsyncWebServerRequest *request) { request->send(404); });
|
2017-10-16 13:00:53 +00:00
|
|
|
|
|
|
|
server->begin();
|
2017-11-14 11:09:52 +00:00
|
|
|
if (debug)
|
|
|
|
Serial.println("UI Initialized");
|
2017-05-18 22:05:32 +00:00
|
|
|
}
|
|
|
|
|
2017-10-19 15:43:39 +00:00
|
|
|
ESPUIClass ESPUI;
|