Merge pull request #562 from geeksville/dev

Dev
1.2-legacy
Kevin Hester 2020-12-15 17:00:42 +08:00 zatwierdzone przez GitHub
commit cc127f7dad
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
20 zmienionych plików z 262 dodań i 71 usunięć

Wyświetl plik

@ -9,10 +9,11 @@ For app cleanup:
* DONE check build guide
* DONE write devapi user guide
* DONE update android code: https://developer.android.com/topic/libraries/view-binding/migration
* only do wantReplies once per packet type, if we change network settings force it again
* make gpio watch work, use thread and setup
* DONE test GPIO watch
* DONE set --set-chan-fast, --set-chan-default
* writeup docs on gpio
* DONE make python ping command
* DONE make hello world example service
* make python ping command
* DONE have python tool check max packet size before sending to device
* DONE if request was sent reliably, send reply reliably
* DONE require a recent python api to talk to these new device loads
@ -20,8 +21,8 @@ For app cleanup:
* DONE fix handleIncomingPosition
* DONE move want_replies handling into plugins
* DONE on android for received positions handle either old or new positions / user messages
* on android side send old or new positions as needed / user messages
* test python side handle new position/user messages
* DONE on android side send old or new positions as needed / user messages
* DONE test python side handle new position/user messages
* DONE make a gpio example. --gpiowrb 4 1, --gpiord 0x444, --gpiowatch 0x3ff
* DONE fix position sending to use new plugin
* DONE Add SinglePortNumPlugin - as the new most useful baseclass
@ -31,6 +32,7 @@ For app cleanup:
* DONE test that position, text messages and user info work properly with new android app and old device code
* do UDP tunnel
* fix the RTC drift bug
* only do wantReplies once per packet type, if we change network settings force it again
* move python ping functionality into device, reply with rxsnr info
* use channels for gpio security https://github.com/meshtastic/Meshtastic-device/issues/104
* generate autodocs

Wyświetl plik

@ -49,6 +49,11 @@ The easiest way to get started is:
* Rebuild with your new messaging goodness and install on the device
* Use the [meshtastic commandline tool](https://github.com/meshtastic/Meshtastic-python) to send a packet to your board "meshtastic --dest 1234 --ping"
## Threading
It is very common that you would like your plugin to be invoked periodically.
We use a crude/basic cooperative threading system to allow this on any of our supported platforms. Simply inherit from OSThread and implement runOnce(). See the OSThread [documentation](/src/concurrency/OSThread.h) for more details. For an example consumer of this API see RemoteHardwarePlugin::runOnce.
## Picking a port number
For any new 'apps' that run on the device or via sister apps on phones/PCs they should pick and use a unique 'portnum' for their application.

2
proto

@ -1 +1 @@
Subproject commit d0868e366bc8f8d9b7ed1d1c5a80cac0de9dc956
Subproject commit e0df97118b3dc8105c9c8dbd59e9bb8cd859b1bb

Wyświetl plik

@ -170,7 +170,7 @@ bool DSRRouter::weAreInRoute(const RouteDiscovery &route)
**/
void DSRRouter::updateRoutes(const RouteDiscovery &route, bool isRequest)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented updateRoutes\n");
}
/**
@ -178,7 +178,7 @@ void DSRRouter::updateRoutes(const RouteDiscovery &route, bool isRequest)
*/
void DSRRouter::sendRouteReply(const RouteDiscovery &route, NodeNum toAppend)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented sendRoute\n");
}
/**
@ -188,7 +188,7 @@ void DSRRouter::sendRouteReply(const RouteDiscovery &route, NodeNum toAppend)
*/
NodeNum DSRRouter::getNextHop(NodeNum dest)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented getNextHop\n");
return 0;
}
@ -198,7 +198,7 @@ NodeNum DSRRouter::getNextHop(NodeNum dest)
*/
void DSRRouter::resendRouteRequest(const MeshPacket *p)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented resendRoute\n");
}
/**
@ -208,7 +208,7 @@ void DSRRouter::resendRouteRequest(const MeshPacket *p)
*/
void DSRRouter::addRoute(NodeNum dest, NodeNum forwarder, uint8_t numHops)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented addRoute\n");
}
/**
@ -216,7 +216,7 @@ void DSRRouter::addRoute(NodeNum dest, NodeNum forwarder, uint8_t numHops)
*/
void DSRRouter::removeRoute(NodeNum dest)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented removeRoute\n");
}
/**
@ -224,7 +224,7 @@ void DSRRouter::removeRoute(NodeNum dest)
*/
void DSRRouter::sendNextHop(NodeNum n, const MeshPacket *p)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented sendNextHop\n");
}
/**
@ -232,7 +232,7 @@ void DSRRouter::sendNextHop(NodeNum n, const MeshPacket *p)
*/
void DSRRouter::sendRouteError(const MeshPacket *p, RouteError err)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented sendRouteError\n");
}
/** make a copy of p, start discovery, but only if we don't
@ -241,5 +241,5 @@ void DSRRouter::sendRouteError(const MeshPacket *p, RouteError err)
*/
void DSRRouter::startDiscovery(NodeNum dest)
{
DEBUG_MSG("FIXME not implemented");
DEBUG_MSG("FIXME not implemented startDiscovery\n");
}

Wyświetl plik

@ -38,8 +38,7 @@ void FloodingRouter::sniffReceived(const MeshPacket *p)
tosend->hop_limit--; // bump down the hop count
DEBUG_MSG("Rebroadcasting received floodmsg to neighbors, fr=0x%x,to=0x%x,id=%d,hop_limit=%d\n", p->from, p->to,
p->id, tosend->hop_limit);
printPacket("Rebroadcasting received floodmsg to neighbors", p);
// Note: we are careful to resend using the original senders node id
// We are careful not to call our hooked version of send() - because we don't want to check this again
Router::send(tosend);

Wyświetl plik

@ -5,6 +5,8 @@
std::vector<MeshPlugin *> *MeshPlugin::plugins;
const MeshPacket *MeshPlugin::currentRequest;
MeshPlugin::MeshPlugin(const char *_name) : name(_name)
{
// Can't trust static initalizer order, so we check each time
@ -25,23 +27,30 @@ MeshPlugin::~MeshPlugin()
void MeshPlugin::callPlugins(const MeshPacket &mp)
{
// DEBUG_MSG("In call plugins\n");
bool pluginFound = false;
for (auto i = plugins->begin(); i != plugins->end(); ++i) {
auto &pi = **i;
pi.currentRequest = &mp;
if (pi.wantPortnum(mp.decoded.data.portnum)) {
pluginFound = true;
bool handled = pi.handleReceived(mp);
// Possibly send replies (unless we are handling a locally generated message)
if (mp.decoded.want_response && mp.from != nodeDB.getNodeNum())
// Possibly send replies
if (mp.decoded.want_response)
pi.sendResponse(mp);
DEBUG_MSG("Plugin %s handled=%d\n", pi.name, handled);
if (handled)
break;
}
else {
DEBUG_MSG("Plugin %s not interested\n", pi.name);
}
pi.currentRequest = NULL;
}
if(!pluginFound)
DEBUG_MSG("No plugins interested in portnum=%d\n", mp.decoded.data.portnum);
}
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked

Wyświetl plik

@ -31,6 +31,15 @@ class MeshPlugin
protected:
const char *name;
/**
* 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.
*
* Note: this can be static because we are guaranteed to be processing only one
* plugin at a time.
*/
static const MeshPacket *currentRequest;
/**
* Initialize your plugin. This setup function is called once after all hardware and mesh protocol layers have
* been initialized

Wyświetl plik

@ -57,16 +57,24 @@ static uint8_t ourMacAddr[6];
*/
NodeNum displayedNodeNum;
/// A usable (but bigger) version of the channel name in the channelSettings object
const char *channelName;
/// A usable psk - which has been constructed based on the (possibly short psk) in channelSettings
static uint8_t activePSK[32];
static uint8_t activePSKSize;
/**
* Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs.
* The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why they
their nodes
* aren't talking to each other.
*
* This string is of the form "#name-XY".
* This string is of the form "#name-X".
*
* Where X is a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together.
* Y is not yet used but should eventually indicate 'speed/range' of the link
* Where X is either:
* (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together,
* OR (for the standard minimially secure PSKs) a number from 0 to 9.
*
* This function will also need to be implemented in GUI apps that talk to the radio.
*
@ -76,11 +84,19 @@ const char *getChannelName()
{
static char buf[32];
uint8_t code = 0;
for (int i = 0; i < channelSettings.psk.size; i++)
code ^= channelSettings.psk.bytes[i];
char suffix;
if(channelSettings.psk.size != 1) {
// We have a standard PSK, so generate a letter based hash.
uint8_t code = 0;
for (int i = 0; i < activePSKSize; i++)
code ^= activePSK[i];
snprintf(buf, sizeof(buf), "#%s-%c", channelSettings.name, 'A' + (code % 26));
suffix = 'A' + (code % 26);
} else {
suffix = '0' + channelSettings.psk.bytes[0];
}
snprintf(buf, sizeof(buf), "#%s-%c", channelName, suffix);
return buf;
}
@ -110,13 +126,62 @@ bool NodeDB::resetRadioConfig()
channelSettings.modem_config = ChannelSettings_ModemConfig_Bw125Cr48Sf4096; // slow and long range
channelSettings.tx_power = 0; // default
memcpy(&channelSettings.psk.bytes, defaultpsk, sizeof(channelSettings.psk));
channelSettings.psk.size = sizeof(defaultpsk);
strcpy(channelSettings.name, "Default");
uint8_t defaultpskIndex = 1;
channelSettings.psk.bytes[0] = defaultpskIndex;
channelSettings.psk.size = 1;
strcpy(channelSettings.name, "");
}
// Convert the old string "Default" to our new short representation
if(strcmp(channelSettings.name, "Default") == 0)
*channelSettings.name = '\0';
// Convert the short "" representation for Default into a usable string
channelName = channelSettings.name;
if(!*channelName) { // emptystring
// Per mesh.proto spec, if bandwidth is specified we must ignore modemConfig enum, we assume that in that case
// the app fucked up and forgot to set channelSettings.name
channelName = "Unset";
if(channelSettings.bandwidth == 0) switch(channelSettings.modem_config) {
case ChannelSettings_ModemConfig_Bw125Cr45Sf128:
channelName = "Medium"; break;
case ChannelSettings_ModemConfig_Bw500Cr45Sf128:
channelName = "ShortFast"; break;
case ChannelSettings_ModemConfig_Bw31_25Cr48Sf512:
channelName = "LongAlt"; break;
case ChannelSettings_ModemConfig_Bw125Cr48Sf4096:
channelName = "LongSlow"; break;
default:
channelName = "Invalid"; break;
}
}
// Convert any old usage of the defaultpsk into our new short representation.
if(channelSettings.psk.size == sizeof(defaultpsk) &&
memcmp(channelSettings.psk.bytes, defaultpsk, sizeof(defaultpsk)) == 0) {
*channelSettings.psk.bytes = 1;
channelSettings.psk.size = 1;
}
// Convert the short single byte variants of psk into variant that can be used more generally
memcpy(activePSK, channelSettings.psk.bytes, channelSettings.psk.size);
activePSKSize = channelSettings.psk.size;
if(activePSKSize == 1) {
uint8_t pskIndex = activePSK[0];
DEBUG_MSG("Expanding short PSK #%d\n", pskIndex);
if(pskIndex == 0)
activePSKSize = 0; // Turn off encryption
else {
memcpy(activePSK, defaultpsk, sizeof(defaultpsk));
activePSKSize = sizeof(defaultpsk);
// Bump up the last byte of PSK as needed
uint8_t *last = activePSK + sizeof(defaultpsk) - 1;
*last = *last + pskIndex - 1; // index of 1 means no change vs defaultPSK
}
}
// Tell our crypto engine about the psk
crypto->setKey(channelSettings.psk.size, channelSettings.psk.bytes);
crypto->setKey(activePSKSize, activePSK);
// temp hack for quicker testing
// devicestate.no_save = true;

Wyświetl plik

@ -13,6 +13,7 @@ extern MyNodeInfo &myNodeInfo;
extern RadioConfig &radioConfig;
extern ChannelSettings &channelSettings;
extern User &owner;
extern const char *channelName;
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
uint32_t sinceLastSeen(const NodeInfo *n);

Wyświetl plik

@ -96,9 +96,9 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
if (!available()) {
// DEBUG_MSG("getFromRadio, !available\n");
return false;
} else {
DEBUG_MSG("getFromRadio, state=%d\n", state);
}
}
DEBUG_MSG("getFromRadio, state=%d\n", state);
// In case we send a FromRadio packet
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
@ -162,6 +162,9 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_PACKETS:
// Do we have a message from the mesh?
if (packetForPhone) {
printPacket("phone downloaded packet", packetForPhone);
// Encapsulate as a FromRadio packet
fromRadioScratch.which_variant = FromRadio_packet_tag;
fromRadioScratch.variant.packet = *packetForPhone;

Wyświetl plik

@ -55,11 +55,11 @@ template <class T> class ProtobufPlugin : private SinglePortPlugin
// it would be better to update even if the message was destined to others.
auto &p = mp.decoded.data;
DEBUG_MSG("Received %s from=0x%0x, id=%d, payloadlen=%d\n", name, mp.from, mp.id, p.payload.size);
DEBUG_MSG("Received %s from=0x%0x, id=0x%x, payloadlen=%d\n", name, mp.from, mp.id, p.payload.size);
T scratch;
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch))
handleReceivedProtobuf(mp, scratch);
return handleReceivedProtobuf(mp, scratch);
return false; // Let others look at this message also if they want
}

Wyświetl plik

@ -123,7 +123,7 @@ void printPacket(const char *prefix, const MeshPacket *p)
auto &s = p->decoded;
switch (s.which_payload) {
case SubPacket_data_tag:
DEBUG_MSG(" Payload:Data");
DEBUG_MSG(" Portnum=%d", s.data.portnum);
break;
case SubPacket_position_tag:
DEBUG_MSG(" Payload:Position");
@ -262,10 +262,10 @@ void RadioInterface::applyModemConfig()
// If user has manually specified a channel num, then use that, otherwise generate one by hashing the name
int channel_num =
(channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelSettings.name)) % myRegion->numChannels;
(channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelName)) % myRegion->numChannels;
freq = myRegion->freq + myRegion->spacing * channel_num;
DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelSettings.name, channelSettings.modem_config, channel_num,
DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelName, channelSettings.modem_config, channel_num,
power);
DEBUG_MSG("Radio myRegion->freq: %f\n", myRegion->freq);
DEBUG_MSG("Radio myRegion->spacing: %f\n", myRegion->spacing);

Wyświetl plik

@ -92,7 +92,7 @@ void ReliableRouter::sendAckNak(bool isAck, NodeNum to, PacketId idFrom)
auto p = allocForSending();
p->hop_limit = 0; // Assume just immediate neighbors for now
p->to = to;
DEBUG_MSG("Sending an ack=0x%x,to=0x%x,idFrom=%d,id=%d\n", isAck, to, idFrom, p->id);
DEBUG_MSG("Sending an ack=0x%x,to=0x%x,idFrom=0x%x,id=0x%x\n", isAck, to, idFrom, p->id);
if (isAck) {
p->decoded.ack.success_id = idFrom;

Wyświetl plik

@ -93,19 +93,28 @@ MeshPacket *Router::allocForSending()
p->to = NODENUM_BROADCAST;
p->hop_limit = HOP_RELIABLE;
p->id = generatePacketId();
p->rx_time = getValidTime(RTCQualityFromNet); // Just in case we process the packet locally - make sure it has a valid timestamp
p->rx_time =
getValidTime(RTCQualityFromNet); // Just in case we process the packet locally - make sure it has a valid timestamp
return p;
}
ErrorCode Router::sendLocal(MeshPacket *p)
{
// No need to deliver externally if the destination is the local node
if (p->to == nodeDB.getNodeNum()) {
DEBUG_MSG("Enqueuing internal message for the receive queue\n");
printPacket("Enqueuing local", p);
fromRadioQueue.enqueue(p);
return ERRNO_OK;
} else
return send(p);
}
// If we are sending a broadcast, we also treat it as if we just received it ourself
// this allows local apps (and PCs) to see broadcasts sourced locally
if (p->to == NODENUM_BROADCAST) {
handleReceived(p);
}
return send(p);
}
/**

Wyświetl plik

@ -51,7 +51,7 @@ void getMacAddr(uint8_t *dmac)
NRF52Bluetooth *nrf52Bluetooth;
static bool bleOn = false;
static const bool enableBle = false; // Set to false for easier debugging
static const bool enableBle = true; // Set to false for easier debugging
void setBluetoothEnable(bool on)
{

Wyświetl plik

@ -10,9 +10,49 @@ RemoteHardwarePlugin remoteHardwarePlugin;
#define NUM_GPIOS 64
// Because (FIXME) we currently don't tell API clients status on sent messages
// we need to throttle our sending, so that if a gpio is bouncing up and down we
// don't generate more messages than the net can send. So we limit watch messages to
// a max of one change per 30 seconds
#define WATCH_INTERVAL_MSEC (30 * 1000)
/// Set pin modes for every set bit in a mask
static void pinModes(uint64_t mask, uint8_t mode) {
for (uint8_t i = 0; i < NUM_GPIOS; i++) {
if (mask & (1 << i)) {
pinMode(i, mode);
}
}
}
/// Read all the pins mentioned in a mask
static uint64_t digitalReads(uint64_t mask) {
uint64_t res = 0;
pinModes(mask, INPUT_PULLUP);
for (uint8_t i = 0; i < NUM_GPIOS; i++) {
uint64_t m = 1 << i;
if (mask & m) {
if (digitalRead(i))
res |= m;
}
}
return res;
}
RemoteHardwarePlugin::RemoteHardwarePlugin()
: ProtobufPlugin("remotehardware", PortNum_REMOTE_HARDWARE_APP, HardwareMessage_fields),
concurrency::OSThread("remotehardware")
{
}
bool RemoteHardwarePlugin::handleReceivedProtobuf(const MeshPacket &req, const HardwareMessage &p)
{
DEBUG_MSG("Received RemoteHardware typ=%d\n", p.typ);
switch (p.typ) {
case HardwareMessage_Type_WRITE_GPIOS:
// Print notification to LCD screen
@ -22,24 +62,17 @@ bool RemoteHardwarePlugin::handleReceivedProtobuf(const MeshPacket &req, const H
uint64_t mask = 1 << i;
if (p.gpio_mask & mask) {
digitalWrite(i, (p.gpio_value & mask) ? 1 : 0);
pinMode(i, OUTPUT);
}
}
pinModes(p.gpio_mask, OUTPUT);
break;
case HardwareMessage_Type_READ_GPIOS: {
// Print notification to LCD screen
screen->print("Read GPIOs\n");
uint64_t res = 0;
for (uint8_t i = 0; i < NUM_GPIOS; i++) {
uint64_t mask = 1 << i;
if (p.gpio_mask & mask) {
pinMode(i, INPUT_PULLUP);
if (digitalRead(i))
res |= (1 << i);
}
}
uint64_t res = digitalReads(p.gpio_mask);
// Send the reply
HardwareMessage reply = HardwareMessage_init_default;
@ -51,6 +84,15 @@ bool RemoteHardwarePlugin::handleReceivedProtobuf(const MeshPacket &req, const H
break;
}
case HardwareMessage_Type_WATCH_GPIOS: {
watchGpios = p.gpio_mask;
lastWatchMsec = 0; // Force a new publish soon
previousWatch = ~watchGpios; // generate a 'previous' value which is guaranteed to not match (to force an initial publish)
enabled = true; // Let our thread run at least once
DEBUG_MSG("Now watching GPIOs 0x%x\n", watchGpios);
break;
}
case HardwareMessage_Type_READ_GPIOS_REPLY:
case HardwareMessage_Type_GPIOS_CHANGED:
break; // Ignore - we might see our own replies
@ -59,5 +101,34 @@ bool RemoteHardwarePlugin::handleReceivedProtobuf(const MeshPacket &req, const H
DEBUG_MSG("Hardware operation %d not yet implemented! FIXME\n", p.typ);
break;
}
return true; // handled
}
int32_t RemoteHardwarePlugin::runOnce() {
if(watchGpios) {
uint32_t now = millis();
if(now - lastWatchMsec >= WATCH_INTERVAL_MSEC) {
uint64_t curVal = digitalReads(watchGpios);
if(curVal != previousWatch) {
previousWatch = curVal;
DEBUG_MSG("Broadcasting GPIOS 0x%x changed!\n", curVal);
// Something changed! Tell the world with a broadcast message
HardwareMessage reply = HardwareMessage_init_default;
reply.typ = HardwareMessage_Type_GPIOS_CHANGED;
reply.gpio_value = curVal;
MeshPacket *p = allocDataProtobuf(reply);
service.sendToMesh(p);
}
}
}
else {
// No longer watching anything - stop using CPU
enabled = false;
}
return 200; // Poll our GPIOs every 200ms (FIXME, make adjustable via protobuf arg)
}

Wyświetl plik

@ -1,17 +1,26 @@
#pragma once
#include "ProtobufPlugin.h"
#include "remote_hardware.pb.h"
#include "concurrency/OSThread.h"
/**
* A plugin that provides easy low-level remote access to device hardware.
*/
class RemoteHardwarePlugin : public ProtobufPlugin<HardwareMessage>
class RemoteHardwarePlugin : public ProtobufPlugin<HardwareMessage>, private concurrency::OSThread
{
/// The current set of GPIOs we've been asked to watch for changes
uint64_t watchGpios = 0;
/// The previously read value of watched pins
uint64_t previousWatch = 0;
/// The timestamp of our last watch event (we throttle watches to 1 change every 30 seconds)
uint32_t lastWatchMsec = 0;
public:
/** Constructor
* name is for debugging output
*/
RemoteHardwarePlugin() : ProtobufPlugin("remotehardware", PortNum_REMOTE_HARDWARE_APP, HardwareMessage_fields) {}
RemoteHardwarePlugin();
protected:
/** Called to handle a particular incoming message
@ -19,6 +28,16 @@ class RemoteHardwarePlugin : public ProtobufPlugin<HardwareMessage>
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
*/
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const HardwareMessage &p);
/**
* Periodically read the gpios we have been asked to WATCH, if they have changed,
* broadcast a message with the change information.
*
* The method that will be called each time our thread gets a chance to run
*
* Returns desired period for next invocation (or RUN_SAME for no change)
*/
virtual int32_t runOnce();
};
extern RemoteHardwarePlugin remoteHardwarePlugin;

Wyświetl plik

@ -1,6 +1,6 @@
#include "configuration.h"
#include "ReplyPlugin.h"
#include "MeshService.h"
#include "configuration.h"
#include "main.h"
#include <assert.h>
@ -8,8 +8,10 @@
// Create an a static instance of our plugin - this registers with the plugin system
ReplyPlugin replyPlugin;
bool ReplyPlugin::handleReceived(const MeshPacket &req)
MeshPacket *ReplyPlugin::allocReply()
{
assert(currentRequest); // should always be !NULL
auto req = *currentRequest;
auto &p = req.decoded.data;
// The incoming message is in p.payload
DEBUG_MSG("Received message from=0x%0x, id=%d, msg=%.*s\n", req.from, req.id, p.payload.size, p.payload.bytes);
@ -17,11 +19,9 @@ bool ReplyPlugin::handleReceived(const MeshPacket &req)
screen->print("Sending reply\n");
const char *replyStr = "Message Received";
auto reply = allocDataPacket(); // Allocate a packet for sending
auto reply = allocDataPacket(); // Allocate a packet for sending
reply->decoded.data.payload.size = strlen(replyStr); // You must specify how many bytes are in the reply
memcpy(reply->decoded.data.payload.bytes, replyStr, reply->decoded.data.payload.size);
setReplyTo(reply, req); // Set packet params so that this packet is marked as a reply to a previous request
service.sendToMesh(reply); // Queue the reply for sending
return true; // We handled it
return reply;
}

Wyświetl plik

@ -15,9 +15,8 @@ class ReplyPlugin : public SinglePortPlugin
protected:
/** 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
/** For reply plugin we do all of our processing in the (normally optional)
* want_replies handling
*/
virtual bool handleReceived(const MeshPacket &mp);
virtual MeshPacket *allocReply();
};

Wyświetl plik

@ -112,7 +112,7 @@ static const uint8_t AREF = PIN_AREF;
// #define PIN_GPS_WAKE 20 // CELL_CTRL in schematic? based on their example code
#define PIN_GPS_EN 7 // GPS_EN active high
#define PIN_VUSB_EN 21
// #define PIN_VUSB_EN 21
// LCD