From 859d6daa9e88eadb10093088bbd5358202b7c207 Mon Sep 17 00:00:00 2001 From: zzzz Date: Sun, 5 May 2024 20:43:56 +0200 Subject: [PATCH] POST requests and basic app lifecycle implemented --- src/SmartDisplay.cpp | 4 +-- src/SmartDisplay.hpp | 4 +-- src/TeaData.hpp | 21 +++++++++++++ src/TeaNetworking.cpp | 69 ++++++++++++++++++++++++++++++++++++------- src/TeaNetworking.hpp | 10 +++++-- src/main.cpp | 58 ++++++++++++++++++++++++++++++------ src/main.hpp | 4 ++- 7 files changed, 144 insertions(+), 26 deletions(-) create mode 100644 src/TeaData.hpp diff --git a/src/SmartDisplay.cpp b/src/SmartDisplay.cpp index 921e200..22438da 100644 --- a/src/SmartDisplay.cpp +++ b/src/SmartDisplay.cpp @@ -5,7 +5,7 @@ SmartDisplay::SmartDisplay(Adafruit_SSD1306 *display) m_display = display; } -void SmartDisplay::printTeaConfigScreen(const char *teaName, int steepingSeconds, int editDir) +void SmartDisplay::printTeaConfigScreen(String teaName, int steepingSeconds, int editDir) { m_display->clearDisplay(); m_display->setTextColor(WHITE); @@ -36,7 +36,7 @@ void SmartDisplay::printTeaConfigScreen(const char *teaName, int steepingSeconds m_display->display(); } -void SmartDisplay::printTeaSteepingProgressScreen(const char *teaName, int steepingSeconds) +void SmartDisplay::printTeaSteepingProgressScreen(String teaName, int steepingSeconds) { m_display->clearDisplay(); m_display->setTextColor(WHITE); diff --git a/src/SmartDisplay.hpp b/src/SmartDisplay.hpp index 16834bc..bb7bd6b 100644 --- a/src/SmartDisplay.hpp +++ b/src/SmartDisplay.hpp @@ -5,9 +5,9 @@ class SmartDisplay { public: SmartDisplay(Adafruit_SSD1306 *display); - void printTeaConfigScreen(const char* teaName, int steepingSeconds, int editDir); + void printTeaConfigScreen(String teaName, int steepingSeconds, int editDir); void printAddNewTeaScreen(); - void printTeaSteepingProgressScreen(const char *teaName, int steepingSeconds); + void printTeaSteepingProgressScreen(String teaName, int steepingSeconds); void printWaitForRFIDScreen(); private: Adafruit_SSD1306 *m_display; diff --git a/src/TeaData.hpp b/src/TeaData.hpp new file mode 100644 index 0000000..15fd808 --- /dev/null +++ b/src/TeaData.hpp @@ -0,0 +1,21 @@ +#pragma once +#include + +struct TeaData +{ +public: + TeaData(String teaName, String rfidCode, int waterTemp, int steepingSeconds) + { + m_teaName = teaName; + m_rfidCode = rfidCode; + m_waterTemp = waterTemp; + m_steepingSeconds = steepingSeconds; + } + TeaData() {} + +public: + String m_teaName; + String m_rfidCode; + int m_waterTemp; + int m_steepingSeconds; +}; \ No newline at end of file diff --git a/src/TeaNetworking.cpp b/src/TeaNetworking.cpp index 5aaa8d5..5eddc05 100644 --- a/src/TeaNetworking.cpp +++ b/src/TeaNetworking.cpp @@ -40,23 +40,23 @@ void TeaNetworking::init(const char *ssid, const char *password) Serial.print(asctime(&timeinfo)); } -String TeaNetworking::httpsGETRequest(const char *serverName) +JSONVar TeaNetworking::httpsGETRequest(String serverName) { WiFiClientSecure client; String payload = "{}"; // wait for WiFi connection - if ((WiFi.status() == WL_CONNECTED)) + if (WiFi.status() == WL_CONNECTED) { // Create a list of certificates with the server certificate X509List cert(IRG_Root_X1); client.setTrustAnchors(&cert); - HTTPClient https; + HTTPClient http; Serial.print("[HTTPS] begin...\n"); - if (https.begin(client, serverName)) + if (http.begin(client, serverName)) { // HTTPS Serial.print("[HTTPS] GET...\n"); // start connection and send HTTP header - int httpCode = https.GET(); + int httpCode = http.GET(); // httpCode will be negative on error if (httpCode > 0) { @@ -65,21 +65,70 @@ String TeaNetworking::httpsGETRequest(const char *serverName) // file found at server if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { - payload = https.getString(); + payload = http.getString(); Serial.println(payload); } } else { - Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str()); + Serial.printf("[HTTPS] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); } - https.end(); + http.end(); } else { Serial.printf("[HTTPS] Unable to connect\n"); } } - JSONVar jsonData = JSON.parse(payload); - return jsonData; + return JSON.parse(payload); +} + +void TeaNetworking::httpsPOSTRequest(String serverName, String data) +{ + WiFiClientSecure client; + // wait for WiFi connection + if ((WiFi.status() == WL_CONNECTED)) + { + // Create a list of certificates with the server certificate + X509List cert(IRG_Root_X1); + client.setTrustAnchors(&cert); + HTTPClient http; + Serial.print("[HTTPS] begin...\n"); + // http.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); + if (http.begin(client, serverName)) + { // HTTPS + // Send HTTPS POST request + http.addHeader("Content-Type", "application/json"); + int httpCode = http.POST(data); + // httpCode will be negative on error + if (httpCode > 0) + { + // HTTP header has been send and Server response header has been handled + Serial.printf("[HTTPS] POST... code: %d\n", httpCode); + } + else + { + Serial.printf("[HTTPS] POST... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + http.end(); + } + else + { + Serial.printf("[HTTPS] Unable to connect\n"); + } + } +} + +String TeaNetworking::createTeaData( + String teaName, + String rfidCode, + int waterTemp, + int steepingSeconds) +{ + JSONVar teaData; + teaData["teaname"] = teaName; + teaData["rfidcode"] = rfidCode; + teaData["watertemp"] = waterTemp; + teaData["steepingseconds"] = steepingSeconds; + return JSONVar::stringify(teaData); } \ No newline at end of file diff --git a/src/TeaNetworking.hpp b/src/TeaNetworking.hpp index 5de4a77..ba064d2 100644 --- a/src/TeaNetworking.hpp +++ b/src/TeaNetworking.hpp @@ -9,6 +9,12 @@ class TeaNetworking { public: void init(const char *ssid, const char *password); - String httpsGETRequest(const char *serverName); - bool wifiConnected(){return WiFi.status() == WL_CONNECTED;} + JSONVar httpsGETRequest(String serverName); + void httpsPOSTRequest(String serverName, String data); + bool wifiConnected() { return WiFi.status() == WL_CONNECTED; } + String createTeaData( + String teaname, + String rfidcode, + int watertemp, + int steepingseconds); }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 825cd44..fb6582c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,7 +23,9 @@ SmartDisplay smartDisplay(&display); TeaNetworking teaNet; // networking -const char *shuttleServer = "https://ias-tea-axum.shuttleapp.rs/alltea"; +String shuttleServer = "https://ias-tea-axum.shuttleapp.rs"; + +TeaData currentTea; enum State { @@ -33,7 +35,7 @@ enum State STEEPING_IN_PROGRESS, NETWORKING_DEBUG, }; -State state = State::NETWORKING_DEBUG; +State state = State::WAIT_FOR_RFID_SCAN; void setup() { @@ -79,9 +81,14 @@ void loop() state = WAIT_FOR_RFID_SCAN; break; } - JSONVar myObject = teaNet.httpsGETRequest(shuttleServer); - Serial.println(myObject); + JSONVar jsonData = teaNet.httpsGETRequest(shuttleServer + "/alltea"); + Serial.println("JSON:"); + Serial.println(jsonData[2]["teaname"]); delay(2000); + + String payload = teaNet.createTeaData("Unnamed Tea", "g8OhgB5", 90, 180); + teaNet.httpsPOSTRequest("https://ias-tea-axum.shuttleapp.rs/addtea", payload); + state = WAIT_FOR_RFID_SCAN; break; } @@ -96,14 +103,19 @@ void loop() if (!mfrc522.PICC_ReadCardSerial()) return; - // Show some details of the PICC (that is: the tag/card) // UID is a unique four hex pairs, e.g. E6 67 2A 12 - Serial.print(F("Card UID:")); + Serial.print("Card UID:"); oled_dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); + serial_dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); display.println(); display.display(); delay(1000); + Serial.println(); + Serial.print("String UID:"); + String uid = string_dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size); + Serial.println(uid); + // Halt PICC mfrc522.PICC_HaltA(); @@ -111,13 +123,27 @@ void loop() display.display(); delay(1000); + JSONVar result = teaNet.httpsGETRequest(shuttleServer + "/teabyrfid/" + uid); + Serial.print("Result:"); + Serial.println(result); + + if (JSONVar::stringify(result) == "null") + { + Serial.print("TEA DOES NOT EXIST YET!"); + String payload = teaNet.createTeaData("Unnamed Tea", uid, 90, 180); + teaNet.httpsPOSTRequest("https://ias-tea-axum.shuttleapp.rs/addtea", payload); + result = teaNet.httpsGETRequest(shuttleServer + "/teabyrfid/" + uid); + } + + currentTea = TeaData(result["teaname"], result["rfidcode"], result["watertemp"], result["steepingSeconds"]); + state = State::DISPLAY_SCANNED_TEA_CONFIG; break; } case DISPLAY_SCANNED_TEA_CONFIG: { - int dir = smartDial.smoothEdit(&steepingSeconds, 0, 120); - smartDisplay.printTeaConfigScreen("Premium Earl Grey", steepingSeconds, dir); + int dir = smartDial.smoothEdit(¤tTea.m_steepingSeconds, 0, 6000); + smartDisplay.printTeaConfigScreen(currentTea.m_teaName, currentTea.m_steepingSeconds, dir); // change state if start pressed if (isBtnPressed()) @@ -137,7 +163,7 @@ void loop() if (teaTimer.isSteeping()) { auto r = teaTimer.remainingSteepTimeSeconds(); - smartDisplay.printTeaSteepingProgressScreen("Premium Earl Grey", r); + smartDisplay.printTeaSteepingProgressScreen(currentTea.m_teaName, r); } else { @@ -163,6 +189,20 @@ bool isBtnPressed() return digitalRead(TOUCH_BTN_PIN) == HIGH; } +/** + * Helper routine to dump a byte array as hex values to a string. + */ +String string_dump_byte_array(byte *buffer, byte bufferSize) +{ + String result = ""; + for (byte i = 0; i < bufferSize; i++) + { + result += (buffer[i] < 0x10 ? " 0" : " "); + result += String(buffer[i], HEX); + } + result.replace(" ", ""); + return result; +} /** * Helper routine to dump a byte array as hex values to Serial. */ diff --git a/src/main.hpp b/src/main.hpp index 50480b0..cf6213b 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -14,6 +14,7 @@ #include "SmartDial.hpp" #include "SmartDisplay.hpp" #include "TeaNetworking.hpp" +#include "TeaData.hpp" bool toggle_led(void *); void printMsg(const String &s); @@ -21,4 +22,5 @@ void printMsg(unsigned long l); bool isBtnPressed(); void serial_dump_byte_array(byte *buffer, byte bufferSize); -void oled_dump_byte_array(byte *buffer, byte bufferSize); \ No newline at end of file +void oled_dump_byte_array(byte *buffer, byte bufferSize); +String string_dump_byte_array(byte *buffer, byte bufferSize); \ No newline at end of file