firmware/src/mesh/ProtobufPlugin.h

76 lines
2.9 KiB
C
Raw Normal View History

#pragma once
2020-12-05 02:14:15 +00:00
#include "SinglePortPlugin.h"
2020-12-03 08:48:44 +00:00
/**
* A base class for mesh plugins that assume that they are sending/receiving one particular protobuf based
* payload. Using one particular app ID.
*
* If you are using protobufs to encode your packets (recommended) you can use this as a baseclass for your plugin
* and avoid a bunch of boilerplate code.
*/
2021-02-17 05:06:23 +00:00
template <class T> class ProtobufPlugin : protected SinglePortPlugin
2020-12-03 08:48:44 +00:00
{
const pb_msgdesc_t *fields;
public:
/** Constructor
* name is for debugging output
*/
ProtobufPlugin(const char *_name, PortNum _ourPortNum, const pb_msgdesc_t *_fields)
2020-12-05 02:14:15 +00:00
: SinglePortPlugin(_name, _ourPortNum), fields(_fields)
2020-12-03 08:48:44 +00:00
{
}
protected:
/**
* Handle a received message, the data field in the message is already decoded and is provided
*
2021-02-17 11:04:41 +00:00
* In general decoded will always be !NULL. But in some special applications (where you have handling packets
* for multiple port numbers, decoding will ONLY be attempted for packets where the portnum matches our expected ourPortNum.
2020-12-03 08:48:44 +00:00
*/
2021-02-17 11:04:41 +00:00
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const T *decoded) = 0;
2020-12-03 08:48:44 +00:00
/**
* Return a mesh packet which has been preinited with a particular protobuf data payload and port number.
* You can then send this packet (after customizing any of the payload fields you might need) with
* service.sendToMesh()
*/
2020-12-07 02:18:11 +00:00
MeshPacket *allocDataProtobuf(const T &payload)
2020-12-03 08:48:44 +00:00
{
// Update our local node info with our position (even if we don't decide to update anyone else)
2020-12-07 02:18:11 +00:00
MeshPacket *p = allocDataPacket();
2020-12-03 08:48:44 +00:00
2021-02-17 05:06:23 +00:00
p->decoded.payload.size =
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), fields, &payload);
// DEBUG_MSG("did encode\n");
2020-12-03 08:48:44 +00:00
return p;
}
private:
/** 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)
{
// FIXME - we currently update position data in the DB only if the message was a broadcast or destined to us
// it would be better to update even if the message was destined to others.
2021-02-17 05:06:23 +00:00
auto &p = mp.decoded;
DEBUG_MSG("Received %s from=0x%0x, id=0x%x, portnum=%d, payloadlen=%d\n", name, mp.from, mp.id, p.portnum,
p.payload.size);
2020-12-03 08:48:44 +00:00
T scratch;
T *decoded = NULL;
if (mp.which_payloadVariant == MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
2021-03-05 03:44:45 +00:00
memset(&scratch, 0, sizeof(scratch));
2021-02-17 11:04:41 +00:00
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch))
decoded = &scratch;
else
DEBUG_MSG("Error decoding protobuf plugin!\n");
}
2020-12-03 08:48:44 +00:00
2021-02-17 11:04:41 +00:00
return handleReceivedProtobuf(mp, decoded);
2020-12-03 08:48:44 +00:00
}
};