2020-11-28 04:10:19 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "mesh/MeshTypes.h"
|
2021-03-17 17:44:42 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#ifndef NO_SCREEN
|
2021-02-21 21:46:46 +00:00
|
|
|
#include <OLEDDisplay.h>
|
|
|
|
#include <OLEDDisplayUi.h>
|
2021-03-17 17:44:42 +00:00
|
|
|
#endif
|
|
|
|
|
2020-11-28 04:10:19 +00:00
|
|
|
/** A baseclass for any mesh "plugin".
|
|
|
|
*
|
|
|
|
* A plugin allows you to add new features to meshtastic device code, without needing to know messaging details.
|
|
|
|
*
|
|
|
|
* A key concept for this is that your plugin should use a particular "portnum" for each message type you want to receive
|
|
|
|
* and handle.
|
|
|
|
*
|
|
|
|
* Interally we use plugins to implement the core meshtastic text messaging and gps position sharing features. You
|
|
|
|
* can use these classes as examples for how to write your own custom plugin. See here: (FIXME)
|
|
|
|
*/
|
|
|
|
class MeshPlugin
|
|
|
|
{
|
2021-03-11 02:01:57 +00:00
|
|
|
static std::vector<MeshPlugin *> *plugins;
|
2020-11-28 04:10:19 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
/** Constructor
|
|
|
|
* name is for debugging output
|
|
|
|
*/
|
|
|
|
MeshPlugin(const char *_name);
|
|
|
|
|
|
|
|
virtual ~MeshPlugin();
|
|
|
|
|
2020-11-28 05:51:51 +00:00
|
|
|
/** For use only by MeshService
|
|
|
|
*/
|
|
|
|
static void callPlugins(const MeshPacket &mp);
|
|
|
|
|
2021-02-21 21:46:46 +00:00
|
|
|
static std::vector<MeshPlugin *> GetMeshPluginsWithUIFrames();
|
2021-03-17 17:44:42 +00:00
|
|
|
#ifndef NO_SCREEN
|
2021-02-21 21:46:46 +00:00
|
|
|
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
|
2021-03-17 17:44:42 +00:00
|
|
|
#endif
|
2020-11-28 05:51:51 +00:00
|
|
|
protected:
|
2020-12-03 08:48:44 +00:00
|
|
|
const char *name;
|
|
|
|
|
2021-03-11 02:01:57 +00:00
|
|
|
/* Most plugins only care about packets that are destined for their node (i.e. broadcasts or has their node as the specific
|
|
|
|
recipient) But some plugs might want to 'sniff' packets that are merely being routed (passing through the current node). Those
|
|
|
|
plugins can set this to true and their handleReceived() will be called for every packet.
|
2021-02-17 05:06:23 +00:00
|
|
|
*/
|
|
|
|
bool isPromiscuous = false;
|
|
|
|
|
2021-03-11 02:01:57 +00:00
|
|
|
/** If a bound channel name is set, we will only accept received packets that come in on that channel.
|
|
|
|
* A special exception (FIXME, not sure if this is a good idea) - packets that arrive on the local interface
|
|
|
|
* are allowed on any channel (this lets the local user do anything).
|
|
|
|
*
|
|
|
|
* We will send responses on the same channel that the request arrived on.
|
|
|
|
*/
|
|
|
|
const char *boundChannel = NULL;
|
|
|
|
|
2020-12-13 04:57:37 +00:00
|
|
|
/**
|
|
|
|
* If this plugin is currently handling a request currentRequest will be preset
|
|
|
|
* to the packet with the request. This is mostly useful for reply handlers.
|
2021-03-11 02:01:57 +00:00
|
|
|
*
|
2020-12-13 04:57:37 +00:00
|
|
|
* Note: this can be static because we are guaranteed to be processing only one
|
|
|
|
* plugin at a time.
|
|
|
|
*/
|
|
|
|
static const MeshPacket *currentRequest;
|
|
|
|
|
2020-11-28 04:10:19 +00:00
|
|
|
/**
|
|
|
|
* Initialize your plugin. This setup function is called once after all hardware and mesh protocol layers have
|
|
|
|
* been initialized
|
|
|
|
*/
|
2020-11-28 05:25:03 +00:00
|
|
|
virtual void setup();
|
2020-11-28 04:10:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return true if you want to receive the specified portnum
|
|
|
|
*/
|
2021-02-17 11:04:41 +00:00
|
|
|
virtual bool wantPacket(const MeshPacket *p) = 0;
|
2020-11-28 04:10:19 +00:00
|
|
|
|
|
|
|
/** 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) { return false; }
|
2020-12-05 03:15:06 +00:00
|
|
|
|
|
|
|
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
2020-12-07 02:18:11 +00:00
|
|
|
* so that subclasses can (optionally) send a response back to the original sender. */
|
|
|
|
virtual MeshPacket *allocReply() { return NULL; }
|
|
|
|
|
2021-02-21 21:46:46 +00:00
|
|
|
/***
|
|
|
|
* @return true if you want to be alloced a UI screen frame
|
|
|
|
*/
|
|
|
|
virtual bool wantUIFrame() { return false; }
|
|
|
|
|
2020-12-07 02:18:11 +00:00
|
|
|
private:
|
2021-03-05 03:44:45 +00:00
|
|
|
/**
|
2021-03-11 02:01:57 +00:00
|
|
|
* If any of the current chain of plugins has already sent a reply, it will be here. This is useful to allow
|
2021-03-05 03:44:45 +00:00
|
|
|
* the RoutingPlugin to avoid sending redundant acks
|
|
|
|
*/
|
|
|
|
static MeshPacket *currentReply;
|
2021-03-11 02:01:57 +00:00
|
|
|
friend class ReliableRouter;
|
2021-03-05 03:44:45 +00:00
|
|
|
|
2020-12-07 02:18:11 +00:00
|
|
|
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
|
|
|
* so that subclasses can (optionally) send a response back to the original sender. This method calls allocReply()
|
|
|
|
* to generate the reply message, and if !NULL that message will be delivered to whoever sent req
|
2020-12-05 03:15:06 +00:00
|
|
|
*/
|
2020-12-07 02:18:11 +00:00
|
|
|
void sendResponse(const MeshPacket &req);
|
|
|
|
};
|
|
|
|
|
2021-03-11 02:01:57 +00:00
|
|
|
/** set the destination and packet parameters of packet p intended as a reply to a particular "to" packet
|
2020-12-07 02:18:11 +00:00
|
|
|
* This ensures that if the request packet was sent reliably, the reply is sent that way as well.
|
2021-03-11 02:01:57 +00:00
|
|
|
*/
|
2020-12-07 02:18:11 +00:00
|
|
|
void setReplyTo(MeshPacket *p, const MeshPacket &to);
|