#ifndef __WEBAPI_PLUGIN__ #define __WEBAPI_PLUGIN__ #include #include #include #include "config.h" #include "utils_print.h" #include "utils_web.h" #include #include using namespace std; using namespace std::placeholders; // TODO headerfile // FIXME constants class WebApi : public Plugin { private: Network *network; public: AsyncWebServer *server; AsyncWebSocket *ws; SprocketMessage currentMessage; int broadcast; WebApi(AsyncWebServer *_server, int _broadcast = 0) { server = _server; broadcast = _broadcast; Update.runAsync(true); } void activate(Scheduler *_scheduler, Network *_network) { network = _network; ws = new AsyncWebSocket("/ws"); ws->onEvent(bind(&WebApi::onWsEvent, this, _1, _2, _3, _4, _5, _6)); server->addHandler(ws); server->on("/api", HTTP_POST, bind(&WebApi::postRequestHandler, this, _1)); server->on("/update", HTTP_GET, bind(&WebApi::simpleFirmwareUploadFormvoid, this, _1)); server->on("/update", HTTP_POST, bind(&WebApi::onFirmwareUpdateRequest, this, _1), bind(&WebApi::onFirmwareUpload, this, _1, _2, _3, _4, _5, _6)); } void postRequestHandler(AsyncWebServerRequest *request) { PRINT_MSG(Serial, SPROCKET_TYPE, "POST WebApi"); currentMessage.topic = WebUtils::getRequestParameterOrDefault(request, "topic", ""); currentMessage.payload = WebUtils::getRequestParameterOrDefault(request, "payload", ""); currentMessage.broadcast = atoi(WebUtils::getRequestParameterOrDefault(request, "broadcast", "0").c_str()); String msg = currentMessage.toJsonString(); publish(currentMessage.topic, currentMessage.payload); if (currentMessage.broadcast) { network->broadcast(msg); } request->send(200, "text/plain", msg); } void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { // FIXME to limitted if (type == WS_EVT_DATA) { String frame = WebUtils::parseFrameAsString(type, arg, data, len, 0); dispatch(0, frame); } } void simpleFirmwareUploadFormvoid(AsyncWebServerRequest *request) { request->send(200, "text/html", "
"); } void onFirmwareUpdateRequest(AsyncWebServerRequest *request) { bool hasError = !Update.hasError(); AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", hasError ? "OK" : "FAIL"); response->addHeader("Connection", "close"); request->send(response); publish("esp/reboot", String(hasError)); } void onFirmwareUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) { if (!index) { PRINT_MSG(Serial, SPROCKET_TYPE, "Update Start %s", filename.c_str()); Update.runAsync(true); if (!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000)) { Update.printError(Serial); } } if (!Update.hasError()) { if (Update.write(data, len) != len) { Update.printError(Serial); } } if (final) { if (Update.end(true)) { PRINT_MSG(Serial, SPROCKET_TYPE, "Update Success with %uB", index + len); } else { Update.printError(Serial); } } } void dispatch(uint32_t from, String &msg) { currentMessage.fromJsonString(msg); if (currentMessage.valid) { currentMessage.from = from; publish(currentMessage.topic, currentMessage.payload); if (broadcast) { network->broadcast(msg); } } } }; #endif