| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937 |
- // FlipperHTTP.h for flipper-http.ino
- #include <WiFi.h>
- #include <HTTPClient.h>
- #include <WiFiClientSecure.h>
- #include "SPIFFS.h"
- #include <ArduinoJson.h>
- #include <Arduino.h>
- #include <ArduinoHttpClient.h>
- #define B_PIN 4 // Blue
- #define G_PIN 5 // Green
- #define R_PIN 6 // Red
- #define ON LOW
- #define OFF HIGH
- class FlipperHTTP
- {
- public:
- // Constructor
- FlipperHTTP()
- {
- }
- // Main methods for flipper-http.ino
- void setup();
- void loop();
- // HTTP Methods
- String get(String url);
- String get(String url, const char *headerKeys[], const char *headerValues[], int headerSize);
- String post(String url, String payload);
- String post(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize);
- String put(String url, String payload);
- String put(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize);
- String delete_request(String url, String payload);
- String delete_request(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize);
- // Save and Load settings to and from SPIFFS
- bool saveWifiSettings(String data);
- bool loadWifiSettings();
- // Connect to Wifi using the loaded SSID and Password
- bool connectToWifi();
- // Check if the Dev Board is connected to Wifi
- bool isConnectedToWifi() { return WiFi.status() == WL_CONNECTED; }
- // Read serial data until newline character
- String readSerialLine();
- // Clear serial buffer to avoid any residual data
- void clearSerialBuffer()
- {
- while (Serial.available() > 0)
- {
- Serial.read();
- }
- }
- // Turn on and off the LED
- void ledAction(int pin = G_PIN, int timeout = 250)
- {
- digitalWrite(pin, ON);
- delay(timeout);
- digitalWrite(pin, OFF);
- delay(timeout);
- }
- // Display LED sequence when Wifi Board is first connected to the Flipper
- void ledStart()
- {
- pinMode(B_PIN, OUTPUT); // Set Blue Pin mode as output
- pinMode(G_PIN, OUTPUT); // Set Green Pin mode as output
- pinMode(R_PIN, OUTPUT); // Set Red Pin mode as output
- digitalWrite(B_PIN, OFF);
- digitalWrite(R_PIN, OFF);
- ledAction();
- ledAction();
- ledAction();
- }
- // Starting LED (Green only)
- void ledStatus()
- {
- digitalWrite(B_PIN, OFF);
- digitalWrite(R_PIN, OFF);
- digitalWrite(G_PIN, ON);
- }
- // Turn off all LEDs
- void ledOff()
- {
- digitalWrite(B_PIN, OFF);
- digitalWrite(G_PIN, OFF);
- digitalWrite(R_PIN, OFF);
- }
- private:
- const char *settingsFilePath = "/flipper-http.json"; // Path to the settings file in the SPIFFS file system
- char loadedSSID[64] = {0}; // Variable to store SSID
- char loadedPassword[64] = {0}; // Variable to store password
- bool readSerialSettings(String receivedData, bool connectAfterSave);
- };
- // Connect to Wifi using the loaded SSID and Password
- bool FlipperHTTP::connectToWifi()
- {
- if (String(loadedSSID) == "" || String(loadedPassword) == "")
- {
- Serial.println("[ERROR] WiFi SSID or Password is empty.");
- return false;
- }
- WiFi.disconnect(true); // Ensure WiFi is disconnected before reconnecting
- WiFi.begin(loadedSSID, loadedPassword);
- int i = 0;
- while (!this->isConnectedToWifi() && i < 20)
- {
- delay(500);
- i++;
- Serial.print(".");
- }
- Serial.println(); // Move to next line after dots
- if (this->isConnectedToWifi())
- {
- Serial.println("[SUCCESS] Successfully connected to Wifi.");
- return true;
- }
- else
- {
- Serial.println("[ERROR] Failed to connect to Wifi.");
- return false;
- }
- }
- // Save Wifi settings to SPIFFS
- bool FlipperHTTP::saveWifiSettings(String jsonData)
- {
- File file = SPIFFS.open(settingsFilePath, FILE_WRITE);
- if (!file)
- {
- Serial.println("[ERROR] Failed to open file for writing.");
- return false;
- }
- file.print(jsonData);
- file.close();
- Serial.println("[SUCCESS] Settings saved to SPIFFS.");
- return true;
- }
- // Load Wifi settings from SPIFFS
- bool FlipperHTTP::loadWifiSettings()
- {
- File file = SPIFFS.open(settingsFilePath, FILE_READ);
- if (!file)
- {
- Serial.println("[ERROR] Failed to open file for reading.");
- return "";
- }
- // Read the entire file content
- String fileContent = file.readString();
- file.close();
- return fileContent;
- }
- String FlipperHTTP::readSerialLine()
- {
- String receivedData = "";
- while (Serial.available() > 0)
- {
- char incomingChar = Serial.read();
- if (incomingChar == '\n')
- {
- break;
- }
- receivedData += incomingChar;
- delay(1); // Minimal delay to allow buffer to fill
- }
- receivedData.trim(); // Remove any leading/trailing whitespace
- return receivedData;
- }
- bool FlipperHTTP::readSerialSettings(String receivedData, bool connectAfterSave)
- {
- DynamicJsonDocument doc(1024);
- DeserializationError error = deserializeJson(doc, receivedData);
- if (error)
- {
- Serial.print("[ERROR] Failed to parse JSON: ");
- Serial.println(error.c_str());
- return false;
- }
- // Extract values from JSON
- if (doc.containsKey("ssid") && doc.containsKey("password"))
- {
- strlcpy(loadedSSID, doc["ssid"], sizeof(loadedSSID));
- strlcpy(loadedPassword, doc["password"], sizeof(loadedPassword));
- }
- else
- {
- Serial.println("[ERROR] JSON does not contain ssid and password.");
- return false;
- }
- // Save to SPIFFS
- if (!this->saveWifiSettings(receivedData))
- {
- Serial.println("[ERROR] Failed to save settings to file.");
- return false;
- }
- // Attempt to reconnect with new settings
- if (connectAfterSave && this->connectToWifi())
- {
- Serial.println("[SUCCESS] Connected to the new Wifi network.");
- }
- else
- {
- Serial.println("[WARNING] Saved settings but failed to connect.");
- }
- return true;
- }
- String FlipperHTTP::get(String url)
- {
- WiFiClientSecure client;
- client.setInsecure(); // Bypass certificate validation
- HTTPClient http;
- String payload = "";
- if (http.begin(client, url))
- {
- int httpCode = http.GET();
- if (httpCode > 0)
- {
- payload = http.getString();
- http.end();
- return payload;
- }
- else
- {
- Serial.print("[ERROR] GET Request Failed, error: ");
- Serial.println(http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- else
- {
- Serial.println("[ERROR] Unable to connect to the server.");
- }
- // Clear serial buffer to avoid any residual data
- this->clearSerialBuffer();
- return payload;
- }
- String FlipperHTTP::get(String url, const char *headerKeys[], const char *headerValues[], int headerSize)
- {
- WiFiClientSecure client;
- client.setInsecure(); // Bypass certificate
- HTTPClient http;
- String payload = "";
- http.collectHeaders(headerKeys, headerSize);
- if (http.begin(client, url))
- {
- for (int i = 0; i < headerSize; i++)
- {
- http.addHeader(headerKeys[i], headerValues[i]);
- }
- int httpCode = http.GET();
- if (httpCode > 0)
- {
- payload = http.getString();
- http.end();
- return payload;
- }
- else
- {
- Serial.print("[ERROR] GET Request Failed, error: ");
- Serial.println(http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- else
- {
- Serial.println("[ERROR] Unable to connect to the server.");
- }
- // Clear serial buffer to avoid any residual data
- this->clearSerialBuffer();
- return payload;
- }
- String FlipperHTTP::delete_request(String url, String payload)
- {
- WiFiClientSecure client;
- client.setInsecure(); // Bypass certificate
- HTTPClient http;
- String response = "";
- if (http.begin(client, url))
- {
- int httpCode = http.sendRequest("DELETE", payload);
- if (httpCode > 0)
- {
- response = http.getString();
- http.end();
- return response;
- }
- else
- {
- Serial.print("[ERROR] DELETE Request Failed, error: ");
- Serial.println(http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- else
- {
- Serial.println("[ERROR] Unable to connect to the server.");
- }
- // Clear serial buffer to avoid any residual data
- this->clearSerialBuffer();
- return response;
- }
- String FlipperHTTP::delete_request(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize)
- {
- WiFiClientSecure client;
- client.setInsecure(); // Bypass certificate
- HTTPClient http;
- String response = "";
- http.collectHeaders(headerKeys, headerSize);
- if (http.begin(client, url))
- {
- for (int i = 0; i < headerSize; i++)
- {
- http.addHeader(headerKeys[i], headerValues[i]);
- }
- int httpCode = http.sendRequest("DELETE", payload);
- if (httpCode > 0)
- {
- response = http.getString();
- http.end();
- return response;
- }
- else
- {
- Serial.print("[ERROR] DELETE Request Failed, error: ");
- Serial.println(http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- else
- {
- Serial.println("[ERROR] Unable to connect to the server.");
- }
- // Clear serial buffer to avoid any residual data
- this->clearSerialBuffer();
- return response;
- }
- String FlipperHTTP::post(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize)
- {
- WiFiClientSecure client;
- client.setInsecure(); // Bypass certificate
- HTTPClient http;
- String response = "";
- http.collectHeaders(headerKeys, headerSize);
- if (http.begin(client, url))
- {
- for (int i = 0; i < headerSize; i++)
- {
- http.addHeader(headerKeys[i], headerValues[i]);
- }
- int httpCode = http.POST(payload);
- if (httpCode > 0)
- {
- response = http.getString();
- http.end();
- return response;
- }
- else
- {
- Serial.print("[ERROR] POST Request Failed, error: ");
- Serial.println(http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- else
- {
- Serial.println("[ERROR] Unable to connect to the server.");
- }
- // Clear serial buffer to avoid any residual data
- this->clearSerialBuffer();
- return response;
- }
- String FlipperHTTP::post(String url, String payload)
- {
- WiFiClientSecure client;
- client.setInsecure(); // Bypass certificate
- HTTPClient http;
- String response = "";
- if (http.begin(client, url))
- {
- int httpCode = http.POST(payload);
- if (httpCode > 0)
- {
- response = http.getString();
- http.end();
- return response;
- }
- else
- {
- Serial.print("[ERROR] POST Request Failed, error: ");
- Serial.println(http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- else
- {
- Serial.println("[ERROR] Unable to connect to the server.");
- }
- // Clear serial buffer to avoid any residual data
- this->clearSerialBuffer();
- return response;
- }
- String FlipperHTTP::put(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize)
- {
- WiFiClientSecure client;
- client.setInsecure(); // Bypass certificate
- HTTPClient http;
- String response = "";
- http.collectHeaders(headerKeys, headerSize);
- if (http.begin(client, url))
- {
- for (int i = 0; i < headerSize; i++)
- {
- http.addHeader(headerKeys[i], headerValues[i]);
- }
- int httpCode = http.PUT(payload);
- if (httpCode > 0)
- {
- response = http.getString();
- http.end();
- return response;
- }
- else
- {
- Serial.print("[ERROR] PUT Request Failed, error: ");
- Serial.println(http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- else
- {
- Serial.println("[ERROR] Unable to connect to the server.");
- }
- // Clear serial buffer to avoid any residual data
- this->clearSerialBuffer();
- return response;
- }
- String FlipperHTTP::put(String url, String payload)
- {
- WiFiClientSecure client;
- client.setInsecure(); // Bypass certificate
- HTTPClient http;
- String response = "";
- if (http.begin(client, url))
- {
- int httpCode = http.PUT(payload);
- if (httpCode > 0)
- {
- response = http.getString();
- http.end();
- return response;
- }
- else
- {
- Serial.print("[ERROR] PUT Request Failed, error: ");
- Serial.println(http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- else
- {
- Serial.println("[ERROR] Unable to connect to the server.");
- }
- // Clear serial buffer to avoid any residual data
- this->clearSerialBuffer();
- return response;
- }
- void FlipperHTTP::setup()
- {
- Serial.begin(115200);
- // Initialize SPIFFS
- if (!SPIFFS.begin(true))
- {
- Serial.println("[ERROR] SPIFFS initialization failed.");
- ESP.restart();
- }
- this->ledStart();
- Serial.flush();
- }
- void FlipperHTTP::loop()
- {
- // Check if there's incoming serial data
- if (Serial.available() > 0)
- {
- // Read the incoming serial data until newline
- String _data = this->readSerialLine();
- if (_data.length() == 0)
- {
- // No complete command received
- return;
- }
- this->ledStatus();
- // Ping/Pong to see if board/flipper is connected
- if (_data.startsWith("[PING]"))
- {
- Serial.println("[PONG]");
- }
- // Handle [WIFI/SAVE] command
- else if (_data.startsWith("[WIFI/SAVE]"))
- {
- // Extract JSON data by removing the command part
- String jsonData = _data.substring(strlen("[WIFI/SAVE]"));
- jsonData.trim(); // Remove any leading/trailing whitespace
- // Parse and save the settings
- if (this->readSerialSettings(jsonData, true))
- {
- Serial.println("[SUCCESS] Wifi settings saved.");
- }
- else
- {
- Serial.println("[ERROR] Failed to save Wifi settings.");
- }
- }
- // Handle [WIFI/CONNECT] command
- else if (_data == "[WIFI/CONNECT]")
- {
- // Check if WiFi is already connected
- if (!this->isConnectedToWifi())
- {
- // Attempt to connect to Wifi
- if (this->connectToWifi())
- {
- Serial.println("[SUCCESS] Connected to Wifi.");
- }
- else
- {
- Serial.println("[ERROR] Failed to connect to Wifi.");
- }
- }
- else
- {
- Serial.println("[INFO] Already connected to Wifi.");
- }
- }
- // Handle [WIFI/DISCONNECT] command
- else if (_data == "[WIFI/DISCONNECT]")
- {
- WiFi.disconnect(true);
- Serial.println("[DISCONNECTED] Wifi has been disconnected.");
- }
- // Handle [GET] command
- else if (_data.startsWith("[GET]"))
- {
- if (!this->isConnectedToWifi() && !this->connectToWifi())
- {
- Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
- this->ledOff();
- return;
- }
- // Extract URL by removing the command part
- String url = _data.substring(strlen("[GET]"));
- url.trim();
- // GET request
- String getData = this->get(url);
- if (getData != "")
- {
- Serial.println("[GET/SUCCESS] GET request successful.");
- Serial.println(getData);
- Serial.flush();
- Serial.println();
- Serial.println("[GET/END]");
- }
- else
- {
- Serial.println("[ERROR] GET request failed or returned empty data.");
- }
- }
- // Handle [GET/HTTP] command
- else if (_data.startsWith("[GET/HTTP]"))
- {
- if (!this->isConnectedToWifi() && !this->connectToWifi())
- {
- Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
- this->ledOff();
- return;
- }
- // Extract the JSON by removing the command part
- String jsonData = _data.substring(strlen("[GET/HTTP]"));
- jsonData.trim();
- DynamicJsonDocument doc(1024);
- DeserializationError error = deserializeJson(doc, jsonData);
- if (error)
- {
- Serial.print("[ERROR] Failed to parse JSON.");
- this->ledOff();
- return;
- }
- // Extract values from JSON
- if (!doc.containsKey("url"))
- {
- Serial.println("[ERROR] JSON does not contain url.");
- this->ledOff();
- return;
- }
- String url = doc["url"];
- // Extract headers if available
- const char *headerKeys[10];
- const char *headerValues[10];
- int headerSize = 0;
- if (doc.containsKey("headers"))
- {
- JsonObject headers = doc["headers"];
- for (JsonPair header : headers)
- {
- headerKeys[headerSize] = header.key().c_str();
- headerValues[headerSize] = header.value();
- headerSize++;
- }
- }
- // GET request
- String getData = this->get(url, headerKeys, headerValues, headerSize);
- if (getData != "")
- {
- Serial.println("[GET/SUCCESS] GET request successful.");
- Serial.println(getData);
- Serial.flush();
- Serial.println();
- Serial.println("[GET/END]");
- }
- else
- {
- Serial.println("[ERROR] GET request failed or returned empty data.");
- }
- }
- // Handle [POST/HTTP] command
- else if (_data.startsWith("[POST/HTTP]"))
- {
- if (!this->isConnectedToWifi() && !this->connectToWifi())
- {
- Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
- this->ledOff();
- return;
- }
- // Extract the JSON by removing the command part
- String jsonData = _data.substring(strlen("[POST/HTTP]"));
- jsonData.trim();
- DynamicJsonDocument doc(1024);
- DeserializationError error = deserializeJson(doc, jsonData);
- if (error)
- {
- Serial.print("[ERROR] Failed to parse JSON.");
- this->ledOff();
- return;
- }
- // Extract values from JSON
- if (!doc.containsKey("url") || !doc.containsKey("payload"))
- {
- Serial.println("[ERROR] JSON does not contain url or payload.");
- this->ledOff();
- return;
- }
- String url = doc["url"];
- String payload = doc["payload"];
- // Extract headers if available
- const char *headerKeys[10];
- const char *headerValues[10];
- int headerSize = 0;
- if (doc.containsKey("headers"))
- {
- JsonObject headers = doc["headers"];
- for (JsonPair header : headers)
- {
- headerKeys[headerSize] = header.key().c_str();
- headerValues[headerSize] = header.value();
- headerSize++;
- }
- }
- // POST request
- String postData = this->post(url, payload, headerKeys, headerValues, headerSize);
- if (postData != "")
- {
- Serial.println("[POST/SUCCESS] POST request successful.");
- Serial.println(postData);
- Serial.flush();
- Serial.println();
- Serial.println("[POST/END]");
- }
- else
- {
- Serial.println("[ERROR] POST request failed or returned empty data.");
- }
- }
- // Handle [PUT/HTTP] command
- else if (_data.startsWith("[PUT/HTTP]"))
- {
- if (!this->isConnectedToWifi() && !this->connectToWifi())
- {
- Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
- this->ledOff();
- return;
- }
- // Extract the JSON by removing the command part
- String jsonData = _data.substring(strlen("[PUT/HTTP]"));
- jsonData.trim();
- DynamicJsonDocument doc(1024);
- DeserializationError error = deserializeJson(doc, jsonData);
- if (error)
- {
- Serial.print("[ERROR] Failed to parse JSON.");
- this->ledOff();
- return;
- }
- // Extract values from JSON
- if (!doc.containsKey("url") || !doc.containsKey("payload"))
- {
- Serial.println("[ERROR] JSON does not contain url or payload.");
- this->ledOff();
- return;
- }
- String url = doc["url"];
- String payload = doc["payload"];
- // Extract headers if available
- const char *headerKeys[10];
- const char *headerValues[10];
- int headerSize = 0;
- if (doc.containsKey("headers"))
- {
- JsonObject headers = doc["headers"];
- for (JsonPair header : headers)
- {
- headerKeys[headerSize] = header.key().c_str();
- headerValues[headerSize] = header.value();
- headerSize++;
- }
- }
- // PUT request
- String putData = this->put(url, payload, headerKeys, headerValues, headerSize);
- if (putData != "")
- {
- Serial.println("[PUT/SUCCESS] PUT request successful.");
- Serial.println(putData);
- Serial.flush();
- Serial.println();
- Serial.println("[PUT/END]");
- }
- else
- {
- Serial.println("[ERROR] PUT request failed or returned empty data.");
- }
- }
- // Handle [DELETE/HTTP] command
- else if (_data.startsWith("[DELETE/HTTP]"))
- {
- if (!this->isConnectedToWifi() && !this->connectToWifi())
- {
- Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
- this->ledOff();
- return;
- }
- // Extract the JSON by removing the command part
- String jsonData = _data.substring(strlen("[DELETE/HTTP]"));
- jsonData.trim();
- DynamicJsonDocument doc(1024);
- DeserializationError error = deserializeJson(doc, jsonData);
- if (error)
- {
- Serial.print("[ERROR] Failed to parse JSON.");
- this->ledOff();
- return;
- }
- // Extract values from JSON
- if (!doc.containsKey("url") || !doc.containsKey("payload"))
- {
- Serial.println("[ERROR] JSON does not contain url or payload.");
- this->ledOff();
- return;
- }
- String url = doc["url"];
- String payload = doc["payload"];
- // Extract headers if available
- const char *headerKeys[10];
- const char *headerValues[10];
- int headerSize = 0;
- if (doc.containsKey("headers"))
- {
- JsonObject headers = doc["headers"];
- for (JsonPair header : headers)
- {
- headerKeys[headerSize] = header.key().c_str();
- headerValues[headerSize] = header.value();
- headerSize++;
- }
- }
- // DELETE request
- String deleteData = this->delete_request(url, payload, headerKeys, headerValues, headerSize);
- if (deleteData != "")
- {
- Serial.println("[DELETE/SUCCESS] DELETE request successful.");
- Serial.println(deleteData);
- Serial.flush();
- Serial.println();
- Serial.println("[DELETE/END]");
- }
- else
- {
- Serial.println("[ERROR] DELETE request failed or returned empty data.");
- }
- }
- this->ledOff();
- }
- }
|