diff --git a/docs/software/plugins/StoreRequestPlugin.md b/docs/software/plugins/StoreRequestPlugin.md index 239a00de..571ac4ed 100644 --- a/docs/software/plugins/StoreRequestPlugin.md +++ b/docs/software/plugins/StoreRequestPlugin.md @@ -1,6 +1,21 @@ # About + This is a work in progress and is not yet available. +The Store Request Plugin is an implementation of a Store and Forward system to enable resilient messaging in the event that a client device is disconnected from the main network. + +Because of the increased network traffic for this overhead, it's not adviced to use this if you are duty cycle limited for your airtime usage nor is it adviced to use this for SF12. # Running notes +This will only work on nodes that are designated as a Router. + +Initial Requirements: + +* Must be installed on a router node. +* * This is an artificial limitation, but is in place to enforce best practices. +* * Router nodes are intended to be always online. If this plugin misses any messages, the reliability of the stored messages will be reduced +* Esp32 Processor based device with external PSRAM. (tbeam v1.0 and tbeamv1.1, maybe others) + +Initial Features +* \ No newline at end of file diff --git a/src/plugins/StoreForwardPlugin.cpp b/src/plugins/StoreForwardPlugin.cpp new file mode 100644 index 00000000..c40c3510 --- /dev/null +++ b/src/plugins/StoreForwardPlugin.cpp @@ -0,0 +1,148 @@ +#include "StoreForwardPlugin.h" +#include "MeshService.h" +#include "NodeDB.h" +#include "RTC.h" +#include "Router.h" +#include "configuration.h" +#include + +#include + +#define STORE_RECORDS 10 +#define BYTES_PER_RECORDS 512 + +struct sfRecord +{ + uint8_t bytes[BYTES_PER_RECORDS]; + uint32_t timestamp; // Time the packet was received +}; + +struct sfRecord records[STORE_RECORDS]; + +#define STOREFORWARDPLUGIN_ENABLED 1 + +StoreForwardPlugin *storeForwardPlugin; +StoreForwardPluginRadio *storeForwardPluginRadio; + +StoreForwardPlugin::StoreForwardPlugin() : concurrency::OSThread("SerialPlugin") {} + +// char serialStringChar[Constants_DATA_PAYLOAD_LEN]; + +int32_t StoreForwardPlugin::runOnce() +{ +#ifndef NO_ESP32 + + if (STOREFORWARDPLUGIN_ENABLED) { + + if (firstTime) { + + // Interface with the serial peripheral from in here. + DEBUG_MSG("Initializing Store & Forward Plugin\n"); + + // Router + if (radioConfig.preferences.is_router) { + if (ESP.getPsramSize()) { + if (ESP.getFreePsram() <= 1024 * 1024) { + // Do the startup here + + } else { + DEBUG_MSG("Device has less than 1M of PSRAM free. Aborting startup.\n"); + DEBUG_MSG("Store & Forward Plugin - Aborting Startup.\n"); + + return (INT32_MAX); + } + + } else { + DEBUG_MSG("Device doesn't have PSRAM.\n"); + DEBUG_MSG("Store & Forward Plugin - Aborting Startup.\n"); + + return (INT32_MAX); + } + + // Non-Router + } else { + + } + + storeForwardPluginRadio = new StoreForwardPluginRadio(); + + firstTime = 0; + + } else { + // TBD + } + + return (10); + } else { + DEBUG_MSG("Store & Forward Plugin - Disabled\n"); + + return (INT32_MAX); + } + +#endif +} + +MeshPacket *StoreForwardPluginRadio::allocReply() +{ + + auto reply = allocDataPacket(); // Allocate a packet for sending + + return reply; +} + +void StoreForwardPluginRadio::sendPayload(NodeNum dest, bool wantReplies) +{ + MeshPacket *p = allocReply(); + p->to = dest; + p->decoded.want_response = wantReplies; + + //p->want_ack = SERIALPLUGIN_ACK; + + // p->decoded.data.payload.size = strlen(serialStringChar); // You must specify how many bytes are in the reply + // memcpy(p->decoded.data.payload.bytes, serialStringChar, p->decoded.data.payload.size); + + service.sendToMesh(p); +} + +bool StoreForwardPluginRadio::handleReceived(const MeshPacket &mp) +{ +#ifndef NO_ESP32 + + if (STOREFORWARDPLUGIN_ENABLED) { + + auto &p = mp.decoded.data; + // DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n", + // nodeDB.getNodeNum(), mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes); + + if (mp.from == nodeDB.getNodeNum()) { + + /* + * If radioConfig.preferences.serialplugin_echo is true, then echo the packets that are sent out back to the TX + * of the serial interface. + */ + if (radioConfig.preferences.serialplugin_echo) { + + // For some reason, we get the packet back twice when we send out of the radio. + // TODO: need to find out why. + if (lastRxID != mp.id) { + lastRxID = mp.id; + // DEBUG_MSG("* * Message came this device\n"); + // Serial2.println("* * Message came this device"); + Serial2.printf("%s", p.payload.bytes); + } + } + + } else { + // DEBUG_MSG("* * Message came from the mesh\n"); + // Serial2.println("* * Message came from the mesh"); + Serial2.printf("%s", p.payload.bytes); + } + + } else { + DEBUG_MSG("Serial Plugin Disabled\n"); + } + +#endif + + return true; // Let others look at this message also if they want +} diff --git a/src/plugins/StoreForwardPlugin.h b/src/plugins/StoreForwardPlugin.h new file mode 100644 index 00000000..e9dac9b4 --- /dev/null +++ b/src/plugins/StoreForwardPlugin.h @@ -0,0 +1,54 @@ +#pragma once + +#include "SinglePortPlugin.h" +#include "concurrency/OSThread.h" +#include "configuration.h" +#include +#include + +class StoreForwardPlugin : private concurrency::OSThread +{ + bool firstTime = 1; + + public: + StoreForwardPlugin(); + + protected: + virtual int32_t runOnce(); +}; + +extern StoreForwardPlugin *storeForwardPlugin; + +/* + * Radio interface for SerialPlugin + * + */ +class StoreForwardPluginRadio : public SinglePortPlugin +{ + uint32_t lastRxID; + + public: + /* + TODO: Switch this to PortNum_SERIAL_APP once the change is able to be merged back here + from the main code. + */ + + // SerialPluginRadio() : SinglePortPlugin("SerialPluginRadio", PortNum_TEXT_MESSAGE_APP) {} + StoreForwardPluginRadio() : SinglePortPlugin("SerialPluginRadio", PortNum_SERIAL_APP) {} + + /** + * Send our payload into the mesh + */ + void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); + + protected: + virtual MeshPacket *allocReply(); + + /** Called to handle a particular incoming message + + @return true if you've guaranteed you've handled this message and no other handlers should be considered for it + */ + virtual bool handleReceived(const MeshPacket &mp); +}; + +extern StoreForwardPluginRadio *storeForwardPluginRadio; \ No newline at end of file