Program Listing for File KPServer.hpp¶
↰ Return to documentation for file (src/KPServer.hpp)
#pragma once
#include <WiFi101.h>
#include <KPFoundation.hpp>
#include <KPServerRequest.hpp>
#include <KPServerResponse.hpp>
#include <vector>
#include <functional>
#define HTTP_GET "GET"
#define HTTP_POST "POST"
using EndPointCallback = std::function<void(Request &, Response &)>;
struct RequestHandler {
const char * path;
const char * method;
EndPointCallback callback;
RequestHandler() {}
RequestHandler(const char * path, const char * method, EndPointCallback callback)
: path(path),
method(method),
callback(callback) {}
};
class KPServer : public KPComponent {
public:
const char * ssid;
const char * pass;
uint8_t status = WL_IDLE_STATUS;
bool isRunning = false;
std::vector<RequestHandler> handlers;
WiFiServer server;
const size_t TCP_LIMIT = 1400;
KPServer(const char * name, const char * ssid, const char * pass, const size_t tcp_limit = 1400)
: KPComponent(name),
ssid(ssid),
pass(pass),
server(80),
TCP_LIMIT(tcp_limit) {}
void setup() override {
WiFi.setPins(8, 7, 4, 2);
WiFi.lowPowerMode();
}
void begin() {
while ((status = WiFi.beginAP(ssid, pass)) != WL_AP_LISTENING) {
println("WiFi AP Mode Failed to Initialize");
println("Try again in ");
for (char i = 3; i > 0; i++) {
println(i);
delay(1000);
}
}
isRunning = true;
}
void update() override {
if (!isRunning) {
return;
}
// WiFi status has changed
if (status != WiFi.status()) {
if ((status = WiFi.status()) == WL_AP_CONNECTED) {
byte remoteMac[6];
println("Device connected to AP");
print("MAC Address: ");
printMacAddress(WiFi.APClientMacAddress(remoteMac));
server.begin();
} else {
println("Device disconnected from AP");
}
}
// Short circuit if client is not connected
if (status != WL_AP_CONNECTED) {
return;
}
WiFiClient client = server.available();
if (client && client.connected() && client.available()) {
constexpr const int size = 4095;
char httpRequest[size + 1] = {0};
auto count = 0;
while (client.available()) {
httpRequest[count++] = client.read();
}
if (strstr(httpRequest, "Content-Length:")) {
delay(10);
while (client.available()) {
httpRequest[count++] = client.read();
}
}
// Construct a request object and handle accordingly
client.flush();
Request request(httpRequest, client);
handleRequest(request);
}
}
void on(const char * path, const char * method, EndPointCallback callback) {
handlers.push_back(RequestHandler(path, method, callback));
}
void get(const char * path, EndPointCallback callback) {
on(path, HTTP_GET, callback);
}
void post(const char * path, EndPointCallback callback) {
on(path, HTTP_POST, callback);
}
void serveStaticFile(const char * path, const char * filepath, KPDataStoreInterface & store,
const char * contentType) {
on(path, HTTP_GET, [=, &store](Request & req, Response & res) {
constexpr int size = 1400;
char buffer[size]{0};
res.setHeader("Content-Type", contentType);
while (store.loadContentOfFile(filepath, buffer, size)) {
res.send(buffer);
}
res.end();
});
}
//===========================================================
// [+_+] Search for the coresponding request handler and call the callback function
//===========================================================
void handleRequest(Request & req) {
WiFiClient & client = req.client;
Response res(client, TCP_LIMIT);
// Preflight
if (strcmp(req.method, "OPTIONS") == 0) {
// client.println("Access-Control-Allow-Origin: *");
return;
}
for (auto & handler : handlers) {
if (strcmp(handler.path, req.path) == 0 && strcmp(handler.method, req.method) == 0) {
// println("Routing to", handler.path);
// printFreeRam();
handler.callback(req, res);
return;
}
}
res.notFound();
}
void printWiFiStatus() {
// SSID:
println("SSID: ", WiFi.SSID());
// IP address:
IPAddress ip = WiFi.localIP();
println("IP Address: ", ip);
// Signal strength:
long rssi = WiFi.RSSI();
println("Signal strength (RSSI): ", rssi, "dBM");
// Address:
println("Web Browser: http://", ip);
}
void printMacAddress(byte mac[]) {
for (int i = 5; i >= 0; i--) {
if (mac[i] < 16) {
print("0");
}
Serial.print(mac[i], HEX);
if (i > 0) {
print(":");
}
}
println();
}
};