|
|
@ -2,33 +2,56 @@ |
|
|
|
#include <ESPmDNS.h> |
|
|
|
#include <AsyncTCP.h> |
|
|
|
#include <ESPAsyncWebServer.h> |
|
|
|
#include <Preferences.h> |
|
|
|
|
|
|
|
#include "shelf.h" |
|
|
|
|
|
|
|
#include "webserver.h" |
|
|
|
|
|
|
|
using namespace std; |
|
|
|
|
|
|
|
extern Shelf* shelf; |
|
|
|
extern volatile SemaphoreHandle_t xPreferencesSemaphore; |
|
|
|
|
|
|
|
Webserver::Webserver(void) |
|
|
|
: server(80) { |
|
|
|
} |
|
|
|
|
|
|
|
String processor(const String& var) |
|
|
|
{ |
|
|
|
if(var == "HELLO_FROM_TEMPLATE") |
|
|
|
return F("Hello world!"); |
|
|
|
if(var == "FACH0_NAME") |
|
|
|
return F("Hello world!"); |
|
|
|
if(var == "FACH1_NAME") |
|
|
|
return F("Hello world!"); |
|
|
|
if(var == "FACH2_NAME") |
|
|
|
return F("Hello world!"); |
|
|
|
if(var == "HELLO_FROM_TEMPLATE") |
|
|
|
return F("Hello world!"); |
|
|
|
|
|
|
|
if (var.startsWith("ITEM")) { |
|
|
|
int num = var.substring(4,5).toInt(); |
|
|
|
if (var.endsWith("_NAME")) { |
|
|
|
return shelf->item.at(num)->name; |
|
|
|
} else if (var.endsWith("_QUANTITY")) { |
|
|
|
return String(shelf->item.at(num)->quantity); |
|
|
|
} else if (var.endsWith("_PRICE")) { |
|
|
|
return String(shelf->item.at(num)->price); |
|
|
|
} |
|
|
|
} |
|
|
|
return String(); |
|
|
|
} |
|
|
|
|
|
|
|
void requestDispense(AsyncWebServerRequest *request) { |
|
|
|
if(request->hasParam("num")) { |
|
|
|
AsyncWebParameter* p = request->getParam("num"); |
|
|
|
const int num = atoi( p->value().c_str() ); |
|
|
|
shelf->dispense(num); |
|
|
|
} |
|
|
|
request->send(200, "text/plain", "OK"); |
|
|
|
} |
|
|
|
|
|
|
|
const char index_html[] PROGMEM = |
|
|
|
"<html><head><title>Vending Machine</title></head>" |
|
|
|
"<body><h1>Vending Machine</h1>" |
|
|
|
"<table><tr><td>%FACH0_NAME%</td><td>%FACH1_NAME%</td><td>%FACH2_NAME%</td></tr>" |
|
|
|
"<tr><td></td><td></td><td></td></tr></table>" |
|
|
|
"<html><head><title>Vending Machine</title><style>table, th, td { border: 2px solid black; }</style></head>" |
|
|
|
"<body><h1>Vending Machine</h1><table>" |
|
|
|
"<tr><td><strong>%ITEM0_NAME%</strong><br/><span style='text-align:left; float:left;'>%ITEM0_QUANTITY%</span><span style='text-align:right; float:right;'>%ITEM0_PRICE%</span></td><td><strong>%ITEM1_NAME%</strong><br/><span style='text-align:left; float:left;'>%ITEM1_QUANTITY%</span><span style='text-align:right; float:right;'>%ITEM1_PRICE%</span></td><td><strong>%ITEM2_NAME%</strong><br/><span style='text-align:left; float:left;'>%ITEM2_QUANTITY%</span><span style='text-align:right; float:right;'>%ITEM2_PRICE%</span></td></tr>" |
|
|
|
"<tr><td><a href=\"/dispense?num=0\">DISPENSE</a></td><td><a href=\"/dispense?num=1\">DISPENSE</a></td><td><a href=\"/dispense?num=2\">DISPENSE</a></td></tr>" |
|
|
|
"<tr><td><strong>%ITEM3_NAME%</strong><br/><span style='text-align:left; float:left;'>%ITEM3_QUANTITY%</span><span style='text-align:right; float:right;'>%ITEM3_PRICE%</span></td><td><strong>%ITEM4_NAME%</strong><br/><span style='text-align:left; float:left;'>%ITEM4_QUANTITY%</span><span style='text-align:right; float:right;'>%ITEM4_PRICE%</span></td><td><strong>%ITEM5_NAME%</strong><br/><span style='text-align:left; float:left;'>%ITEM5_QUANTITY%</span><span style='text-align:right; float:right;'>%ITEM5_PRICE%</span></td></tr>" |
|
|
|
"<tr><td><a href=\"/dispense?num=3\">DISPENSE</a></td><td><a href=\"/dispense?num=4\">DISPENSE</a></td><td><a href=\"/dispense?num=5\">DISPENSE</a></td></tr>" |
|
|
|
"</table><hr /><a href=\"/configure\">configure</a>" |
|
|
|
"</body></html>"; // large char array, tested with 14k
|
|
|
|
|
|
|
|
void Webserver::start(void) { |
|
|
@ -72,6 +95,56 @@ void Webserver::start(void) { |
|
|
|
request->send_P(200, "text/html", index_html, processor); |
|
|
|
}); |
|
|
|
|
|
|
|
server.on("/dispense", HTTP_GET, requestDispense); |
|
|
|
|
|
|
|
// Config
|
|
|
|
server.on("/configure", HTTP_GET, [](AsyncWebServerRequest *request){ |
|
|
|
AsyncResponseStream *response = request->beginResponseStream("text/html"); |
|
|
|
response->printf("<!DOCTYPE html><html><head><title>Vending Machine at %s</title></head><body>", request->url().c_str()); |
|
|
|
response->print("<form method='POST' action='/configure' enctype='multipart/form-data'>"); |
|
|
|
for(int i=0; i<shelf->num_items; i++) { |
|
|
|
response->printf("Item %u: ", i); |
|
|
|
response->printf("<input type='text' name='item%u_name' value='%s'>", i, shelf->item.at(i)->name); |
|
|
|
response->printf("<input type='text' name='item%u_quantity' value='%u'>", i, shelf->item.at(i)->quantity); |
|
|
|
response->printf("<input type='text' name='item%u_price' value='%u'>", i, shelf->item.at(i)->price); |
|
|
|
response->print("<hr />"); |
|
|
|
} |
|
|
|
response->print("<input type='submit' value='Update'></form>"); |
|
|
|
response->print("</body></html>"); |
|
|
|
request->send(response); |
|
|
|
}); |
|
|
|
server.on("/configure", HTTP_POST, [](AsyncWebServerRequest *request){ |
|
|
|
if (xSemaphoreTake(xPreferencesSemaphore, portMAX_DELAY) == pdTRUE) { |
|
|
|
Preferences preferences; |
|
|
|
preferences.begin("vending-items", false); |
|
|
|
for (int i=0; i<shelf->num_items; i++) { |
|
|
|
char buffer[50]; |
|
|
|
sprintf(buffer, "item%u_name", i); |
|
|
|
if(request->hasParam(buffer, true)) { |
|
|
|
AsyncWebParameter* p = request->getParam(buffer, true); |
|
|
|
const char* name = p->value().c_str(); |
|
|
|
preferences.putString(buffer, name); |
|
|
|
} |
|
|
|
sprintf(buffer, "item%u_quantity", i); |
|
|
|
if(request->hasParam(buffer, true)) { |
|
|
|
AsyncWebParameter* p = request->getParam(buffer, true); |
|
|
|
const int num = atoi( p->value().c_str() ); |
|
|
|
preferences.putUInt(buffer, num); |
|
|
|
} |
|
|
|
sprintf(buffer, "item%u_price", i); |
|
|
|
if(request->hasParam(buffer, true)) { |
|
|
|
AsyncWebParameter* p = request->getParam(buffer, true); |
|
|
|
const int price = atoi( p->value().c_str() ); |
|
|
|
preferences.putUInt(buffer, price); |
|
|
|
} |
|
|
|
} |
|
|
|
preferences.end(); |
|
|
|
xSemaphoreGive(xPreferencesSemaphore); |
|
|
|
shelf->reload(); |
|
|
|
} |
|
|
|
request->send(200, "text/html", "OK"); |
|
|
|
}); |
|
|
|
|
|
|
|
server.onNotFound([](AsyncWebServerRequest *request){ |
|
|
|
Serial.printf("NOT_FOUND: "); |
|
|
|
if(request->method() == HTTP_GET) |
|
|
|