From 203906b822539ae70a599faf3e75956903f708f4 Mon Sep 17 00:00:00 2001 From: rosen1710 Date: Sun, 7 Jul 2024 20:36:31 +0300 Subject: [PATCH 1/5] Get all packets endpoint added --- tinyGS/src/ConfigManager/ConfigManager.cpp | 45 ++++++++++++++++++++-- tinyGS/src/ConfigManager/ConfigManager.h | 1 + tinyGS/src/Radio/Radio.cpp | 2 + tinyGS/src/Status.h | 3 ++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/tinyGS/src/ConfigManager/ConfigManager.cpp b/tinyGS/src/ConfigManager/ConfigManager.cpp index 4b9d4534..ff48fef3 100644 --- a/tinyGS/src/ConfigManager/ConfigManager.cpp +++ b/tinyGS/src/ConfigManager/ConfigManager.cpp @@ -83,6 +83,7 @@ ConfigManager::ConfigManager() #endif }) { + // server.on("/get_all", [this] { handleGetAll(); }); server.on(ROOT_URL, [this] { handleRoot(); }); server.on(CONFIG_URL, [this] { handleConfig(); }); server.on(DASHBOARD_URL, [this] { handleDashboard(); }); @@ -127,6 +128,44 @@ ConfigManager::ConfigManager() addParameterGroup(&groupAdvanced); } +void ConfigManager::handleGetAll() +{ + // // -- Let IotWebConf2 test and handle captive portal requests. + // if (handleCaptivePortal()) + // { + // // -- Captive portal request were already served. + // return; + // } + + // if (getState() == IOTWEBCONF_STATE_ONLINE) + // { + // // -- Authenticate + // if (!server.authenticate(IOTWEBCONF_ADMIN_USER_NAME, getApPasswordParameter()->valueBuffer)) + // { + // IOTWEBCONF_DEBUG_LINE(F("Requesting authentication.")); + // server.requestAuthentication(); + // return; + // } + // } + + String string = String(FPSTR("{\"message\":\"Packets were fetched successfully\",\"packets\":[")); + for (size_t i = 0; i < status.allPackets.size(); i++) + { + string += "{\"time\":\"" + status.allPackets.at(i).time + + "\",\"rssi\":" + status.allPackets.at(i).rssi + + ",\"snr\":" + status.allPackets.at(i).snr + + ",\"frequencyerror\":" + status.allPackets.at(i).frequencyerror + + ",\"crc_error\":" + status.allPackets.at(i).crc_error + + "}"; + if (i < status.allPackets.size() - 1) + { + string += ","; + } + } + string += "]}"; + server.send(200, "application/json; charset=UTF-8", string); +} + void ConfigManager::handleRoot() { // -- Let IotWebConf2 test and handle captive portal requests. @@ -149,7 +188,7 @@ void ConfigManager::handleRoot() s.replace("{v}", FPSTR(TITLE_TEXT)); - server.sendHeader("Content-Length", String(s.length())); + // server.sendHeader("Content-Length", String(s.length())); server.send(200, "text/html; charset=UTF-8", s); } @@ -256,7 +295,7 @@ void ConfigManager::handleDashboard() s.replace("{v}", FPSTR(TITLE_TEXT)); - server.sendHeader("Content-Length", String(s.length())); + // server.sendHeader("Content-Length", String(s.length())); server.send(200, "text/html; charset=UTF-8", s); } @@ -443,7 +482,7 @@ void ConfigManager::handleRestart() s.replace("{v}", FPSTR(TITLE_TEXT)); - server.sendHeader("Content-Length", String(s.length())); + // server.sendHeader("Content-Length", String(s.length())); server.send(200, "text/html; charset=UTF-8", s); delay(100); ESP.restart(); diff --git a/tinyGS/src/ConfigManager/ConfigManager.h b/tinyGS/src/ConfigManager/ConfigManager.h index ebfe35fb..e8adfe8c 100644 --- a/tinyGS/src/ConfigManager/ConfigManager.h +++ b/tinyGS/src/ConfigManager/ConfigManager.h @@ -236,6 +236,7 @@ class ConfigManager : public IotWebConf2 }; ConfigManager(); + void handleGetAll(); void handleRoot(); void handleDashboard(); void handleRefreshConsole(); diff --git a/tinyGS/src/Radio/Radio.cpp b/tinyGS/src/Radio/Radio.cpp index a3cae365..85c960fd 100644 --- a/tinyGS/src/Radio/Radio.cpp +++ b/tinyGS/src/Radio/Radio.cpp @@ -296,6 +296,8 @@ uint8_t Radio::listen() status.lastPacketInfo.snr = newPacketInfo.snr; status.lastPacketInfo.frequencyerror = newPacketInfo.frequencyerror; + status.allPackets.push_back(newPacketInfo); + // print RSSI (Received Signal Strength Indicator) Log::console(PSTR("[%s] RSSI:\t\t%f dBm\n[%s] SNR:\t\t%f dB\n[%s] Frequency error:\t%f Hz"), moduleNameString, status.lastPacketInfo.rssi, diff --git a/tinyGS/src/Status.h b/tinyGS/src/Status.h index a6df4738..7f891fa2 100644 --- a/tinyGS/src/Status.h +++ b/tinyGS/src/Status.h @@ -24,6 +24,8 @@ #ifndef Status_h #define Status_h +#include + struct PacketInfo { String time = "Waiting"; float rssi = 0; @@ -73,6 +75,7 @@ struct Status { bool radio_ready = false; int16_t radio_error = 0; PacketInfo lastPacketInfo; + std::vector allPackets; ModemInfo modeminfo; float satPos[2] = {0, 0}; uint8_t remoteTextFrameLength[4] = {0, 0, 0, 0}; From bc1b6d173723ea433cb1fe319f209ca3498510f4 Mon Sep 17 00:00:00 2001 From: Rosen Marinov Date: Mon, 8 Jul 2024 15:56:08 +0300 Subject: [PATCH 2/5] Added endpoint for radioBegin --- tinyGS/src/ConfigManager/ConfigManager.cpp | 34 ++++++++++------------ tinyGS/src/ConfigManager/ConfigManager.h | 3 +- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/tinyGS/src/ConfigManager/ConfigManager.cpp b/tinyGS/src/ConfigManager/ConfigManager.cpp index ff48fef3..8e940beb 100644 --- a/tinyGS/src/ConfigManager/ConfigManager.cpp +++ b/tinyGS/src/ConfigManager/ConfigManager.cpp @@ -83,7 +83,8 @@ ConfigManager::ConfigManager() #endif }) { - // server.on("/get_all", [this] { handleGetAll(); }); + server.on("/radioBegin", [this] { handleRadioBegin(); }); + server.on("/packets", [this] { handleGetAllPackets(); }); server.on(ROOT_URL, [this] { handleRoot(); }); server.on(CONFIG_URL, [this] { handleConfig(); }); server.on(DASHBOARD_URL, [this] { handleDashboard(); }); @@ -128,26 +129,20 @@ ConfigManager::ConfigManager() addParameterGroup(&groupAdvanced); } -void ConfigManager::handleGetAll() +void ConfigManager::handleRadioBegin() { - // // -- Let IotWebConf2 test and handle captive portal requests. - // if (handleCaptivePortal()) - // { - // // -- Captive portal request were already served. - // return; - // } - - // if (getState() == IOTWEBCONF_STATE_ONLINE) - // { - // // -- Authenticate - // if (!server.authenticate(IOTWEBCONF_ADMIN_USER_NAME, getApPasswordParameter()->valueBuffer)) - // { - // IOTWEBCONF_DEBUG_LINE(F("Requesting authentication.")); - // server.requestAuthentication(); - // return; - // } - // } + if (Radio::getInstance().begin() == 0) + { + server.send(200, "application/json; charset=UTF-8", "{\"message\":\"Radio begun successfully\"}"); + Log::console(PSTR("Radio begun successfully")); + return; + } + server.send(200, "application/json; charset=UTF-8", "{\"message\":\"An error occurred while trying to start the Radio\"}"); + Log::console(PSTR("An error occurred while trying to start the Radio")); +} +void ConfigManager::handleGetAllPackets() +{ String string = String(FPSTR("{\"message\":\"Packets were fetched successfully\",\"packets\":[")); for (size_t i = 0; i < status.allPackets.size(); i++) { @@ -164,6 +159,7 @@ void ConfigManager::handleGetAll() } string += "]}"; server.send(200, "application/json; charset=UTF-8", string); + Log::console(PSTR("Endpoint /packets was requested and handled successfully")); } void ConfigManager::handleRoot() diff --git a/tinyGS/src/ConfigManager/ConfigManager.h b/tinyGS/src/ConfigManager/ConfigManager.h index e8adfe8c..0f83343e 100644 --- a/tinyGS/src/ConfigManager/ConfigManager.h +++ b/tinyGS/src/ConfigManager/ConfigManager.h @@ -236,7 +236,8 @@ class ConfigManager : public IotWebConf2 }; ConfigManager(); - void handleGetAll(); + void handleRadioBegin(); + void handleGetAllPackets(); void handleRoot(); void handleDashboard(); void handleRefreshConsole(); From 9e8f083ca2f5d9857139111d766575bae4fe4169 Mon Sep 17 00:00:00 2001 From: Rosen Marinov Date: Tue, 9 Jul 2024 16:22:35 +0300 Subject: [PATCH 3/5] Improved log on receiving radio message --- .vscode/settings.json | 40 +++++++++++++++++++++- tinyGS/src/ConfigManager/ConfigManager.cpp | 10 ++++-- tinyGS/src/Radio/Radio.cpp | 31 +++++++++++++---- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e25c8a46..0d507e75 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,44 @@ "vector": "cpp", "memory": "cpp", "random": "cpp", - "initializer_list": "cpp" + "initializer_list": "cpp", + "atomic": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp" } } \ No newline at end of file diff --git a/tinyGS/src/ConfigManager/ConfigManager.cpp b/tinyGS/src/ConfigManager/ConfigManager.cpp index 8e940beb..202f0a8c 100644 --- a/tinyGS/src/ConfigManager/ConfigManager.cpp +++ b/tinyGS/src/ConfigManager/ConfigManager.cpp @@ -131,10 +131,16 @@ ConfigManager::ConfigManager() void ConfigManager::handleRadioBegin() { + if (!Radio::getInstance().isReady()) + { + server.send(200, "application/json; charset=UTF-8", "{\"message\":\"Radio is not ready to begin\"}"); + Log::console(PSTR("Radio is not ready to begin")); + return; + } if (Radio::getInstance().begin() == 0) { - server.send(200, "application/json; charset=UTF-8", "{\"message\":\"Radio begun successfully\"}"); - Log::console(PSTR("Radio begun successfully")); + server.send(200, "application/json; charset=UTF-8", "{\"message\":\"Radio begun successfully after /radioBegin request\"}"); + Log::console(PSTR("Radio begun successfully after /radioBegin request")); return; } server.send(200, "application/json; charset=UTF-8", "{\"message\":\"An error occurred while trying to start the Radio\"}"); diff --git a/tinyGS/src/Radio/Radio.cpp b/tinyGS/src/Radio/Radio.cpp index 85c960fd..e4050edf 100644 --- a/tinyGS/src/Radio/Radio.cpp +++ b/tinyGS/src/Radio/Radio.cpp @@ -38,6 +38,23 @@ bool noisyInterrupt = false; bool allow_decode=true; +std::string hexToASCII(std::string hex) +{ + std::string ascii = ""; + for (size_t i = 0; i < hex.length(); i += 2) + { + // extract two characters from hex string + std::string part = hex.substr(i, 2); + + // change it into base 16 and typecast as the character + char ch = (char) strtol(part.c_str(), nullptr, 16); + + // add this char to final ASCII string + ascii += ch; + } + return ascii; +} + Radio::Radio() #if CONFIG_IDF_TARGET_ESP32S3 : spi(HSPI) @@ -309,20 +326,22 @@ uint8_t Radio::listen() // read optional data Log::console(PSTR("Packet (%u bytes):"), respLen); uint16_t buffSize = respLen * 2 + 1; - if (buffSize > 255) - buffSize = 255; + // if (buffSize > 255) + // buffSize = 255; char *byteStr = new char[buffSize]; for (int i = 0; i < respLen; i++) { sprintf(byteStr + i * 2 % (buffSize - 1), "%02x", respFrame[i]); - if (i * 2 % buffSize == buffSize - 3 || i == respLen - 1) - Log::console(PSTR("%s"), byteStr); // print before the buffer is going to loop back + if (i * 2 % buffSize == buffSize - 3 || i == respLen - 1) { + Log::console(PSTR("\tEncoded: %s"), byteStr); // print before the buffer is going to loop back + } } + Log::console(PSTR("\tDecoded: %s"), hexToASCII(std::string(byteStr)).c_str()); delete[] byteStr; - if (allow_decode){ + if (allow_decode) { String modo=status.modeminfo.modem_mode; - if (modo=="FSK"){ + if (modo=="FSK") { int bytes_sincro=0; for (int i=0;i Date: Wed, 10 Jul 2024 16:25:28 +0300 Subject: [PATCH 4/5] Added option for sending radio messages + included message in the /packets endpoint response --- tinyGS/src/ConfigManager/ConfigManager.cpp | 12 ++++++- tinyGS/src/Radio/Radio.cpp | 42 +++++++++++++--------- tinyGS/src/Status.h | 4 ++- tinyGS/tinyGS.ino | 5 +-- 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/tinyGS/src/ConfigManager/ConfigManager.cpp b/tinyGS/src/ConfigManager/ConfigManager.cpp index 202f0a8c..003f3462 100644 --- a/tinyGS/src/ConfigManager/ConfigManager.cpp +++ b/tinyGS/src/ConfigManager/ConfigManager.cpp @@ -153,6 +153,8 @@ void ConfigManager::handleGetAllPackets() for (size_t i = 0; i < status.allPackets.size(); i++) { string += "{\"time\":\"" + status.allPackets.at(i).time + + "\",\"encoded_message\":\"" + status.allPackets.at(i).encoded_message + + "\",\"decoded_message\":\"" + status.allPackets.at(i).decoded_message + "\",\"rssi\":" + status.allPackets.at(i).rssi + ",\"snr\":" + status.allPackets.at(i).snr + ",\"frequencyerror\":" + status.allPackets.at(i).frequencyerror @@ -345,7 +347,15 @@ void ConfigManager::handleRefreshConsole() } else { - Log::console(PSTR("%s"), F("Command still not supported in web serial console!")); + // Log::console(PSTR("%s"), F("Command still not supported in web serial console!")); + if (Radio::getInstance().sendTx((uint8_t *) svalue.c_str(), strlen(svalue.c_str())) == 0) + { + Log::console(PSTR("%s"), F("Message was sent successfully")); + } + else + { + Log::console(PSTR("%s"), F("An error occurred while sending the message!")); + } } } diff --git a/tinyGS/src/Radio/Radio.cpp b/tinyGS/src/Radio/Radio.cpp index e4050edf..c3407945 100644 --- a/tinyGS/src/Radio/Radio.cpp +++ b/tinyGS/src/Radio/Radio.cpp @@ -289,12 +289,12 @@ uint8_t Radio::listen() { // store time of the last packet received: timeinfo = localtime(¤ttime); - String thisTime = ""; - if (timeinfo->tm_hour < 10) - { - thisTime = thisTime + " "; - } // add leading space if required - thisTime = String(timeinfo->tm_hour) + ":"; + String thisTime = String(timeinfo->tm_mday) + "/" + String(timeinfo->tm_mon + 1) + "/" + String(timeinfo->tm_year + 1900) + " "; + // if (timeinfo->tm_hour < 10) + // { + // thisTime = thisTime + " "; + // } // add leading space if required + thisTime = thisTime + String(timeinfo->tm_hour) + ":"; if (timeinfo->tm_min < 10) { thisTime = thisTime + "0"; @@ -313,32 +313,40 @@ uint8_t Radio::listen() status.lastPacketInfo.snr = newPacketInfo.snr; status.lastPacketInfo.frequencyerror = newPacketInfo.frequencyerror; - status.allPackets.push_back(newPacketInfo); - // print RSSI (Received Signal Strength Indicator) - Log::console(PSTR("[%s] RSSI:\t\t%f dBm\n[%s] SNR:\t\t%f dB\n[%s] Frequency error:\t%f Hz"), - moduleNameString, status.lastPacketInfo.rssi, - moduleNameString, status.lastPacketInfo.snr, - moduleNameString, status.lastPacketInfo.frequencyerror); + Log::console(PSTR("[%s] RSSI:\t\t%f dBm\n\t [%s] SNR:\t\t%f dB\n\t [%s] Frequency error:\t%f Hz"), + moduleNameString, status.lastPacketInfo.rssi, + moduleNameString, status.lastPacketInfo.snr, + moduleNameString, status.lastPacketInfo.frequencyerror + ); if (state == RADIOLIB_ERR_NONE && respLen > 0) { // read optional data - Log::console(PSTR("Packet (%u bytes):"), respLen); + // Log::console(PSTR("Packet (%u bytes):"), respLen); + uint16_t buffSize = respLen * 2 + 1; // if (buffSize > 255) // buffSize = 255; + char *byteStr = new char[buffSize]; for (int i = 0; i < respLen; i++) { sprintf(byteStr + i * 2 % (buffSize - 1), "%02x", respFrame[i]); - if (i * 2 % buffSize == buffSize - 3 || i == respLen - 1) { - Log::console(PSTR("\tEncoded: %s"), byteStr); // print before the buffer is going to loop back - } + // if (i * 2 % buffSize == buffSize - 3 || i == respLen - 1) { + // Log::console(PSTR("\tEncoded: %s"), byteStr); // print before the buffer is going to loop back + // } } - Log::console(PSTR("\tDecoded: %s"), hexToASCII(std::string(byteStr)).c_str()); + + status.lastPacketInfo.encoded_message = byteStr; + status.lastPacketInfo.decoded_message = hexToASCII(std::string(byteStr)).c_str(); + + // Log::console(PSTR("\tDecoded: %s"), hexToASCII(std::string(byteStr)).c_str()); + Log::console(PSTR("Packet (%u bytes):\n\t - Encoded: %s\n\t - Decoded: %s"), respLen, byteStr, status.lastPacketInfo.decoded_message.c_str()); delete[] byteStr; + status.allPackets.push_back(status.lastPacketInfo); + if (allow_decode) { String modo=status.modeminfo.modem_mode; if (modo=="FSK") { diff --git a/tinyGS/src/Status.h b/tinyGS/src/Status.h index 7f891fa2..c76cd6fd 100644 --- a/tinyGS/src/Status.h +++ b/tinyGS/src/Status.h @@ -28,9 +28,11 @@ struct PacketInfo { String time = "Waiting"; + String encoded_message = ""; + String decoded_message = ""; float rssi = 0; float snr = 0; - float frequencyerror = 0; // Hz + float frequencyerror = 0; // Hz bool crc_error = false; }; diff --git a/tinyGS/tinyGS.ino b/tinyGS/tinyGS.ino index ea480350..8197d922 100644 --- a/tinyGS/tinyGS.ino +++ b/tinyGS/tinyGS.ino @@ -314,9 +314,10 @@ void handleSerial() // function to print controls void printControls() { - Log::console(PSTR("------------- Controls -------------")); + Log::console(PSTR("----------------- Controls -----------------")); Log::console(PSTR("!e - erase board config and reset")); Log::console(PSTR("!b - reboot the board")); Log::console(PSTR("!p - send test packet to nearby stations (to check transmission)")); - Log::console(PSTR("------------------------------------")); + Log::console(PSTR(" - send packet with custom message")); + Log::console(PSTR("--------------------------------------------")); } \ No newline at end of file From e1ec9429914bf2069009bfe4349efb7949a518cf Mon Sep 17 00:00:00 2001 From: Rosen Marinov Date: Thu, 11 Jul 2024 16:42:03 +0300 Subject: [PATCH 5/5] AllPackets bug fix --- tinyGS/src/Radio/Radio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tinyGS/src/Radio/Radio.cpp b/tinyGS/src/Radio/Radio.cpp index c3407945..588a2e12 100644 --- a/tinyGS/src/Radio/Radio.cpp +++ b/tinyGS/src/Radio/Radio.cpp @@ -345,8 +345,6 @@ uint8_t Radio::listen() Log::console(PSTR("Packet (%u bytes):\n\t - Encoded: %s\n\t - Decoded: %s"), respLen, byteStr, status.lastPacketInfo.decoded_message.c_str()); delete[] byteStr; - status.allPackets.push_back(status.lastPacketInfo); - if (allow_decode) { String modo=status.modeminfo.modem_mode; if (modo=="FSK") { @@ -438,6 +436,8 @@ uint8_t Radio::listen() noisyInterrupt = false; + status.allPackets.push_back(status.lastPacketInfo); + // put module back to listen mode startRx();