mesh sending and receving now much more real

This commit is contained in:
geeksville
2020-02-02 12:45:32 -08:00
parent 4051bf8465
commit 9aed5056ad
10 changed files with 352 additions and 268 deletions

View File

@@ -8,148 +8,8 @@
#include <pb_encode.h>
#include <pb_decode.h>
#include "mesh.pb.h"
#include "MeshRadio.h"
#include "TypedQueue.h"
#include "MemoryPool.h"
#include "MeshService.h"
/*
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were alloced with new).
After a packet ptr is removed from the queue and processed it should be deleted. (eventually we should move sent packets into a 'sentToPhone' queue
of packets we can delete just as soon as we are sure the phone has acked those packets - when the phone writes to FromNum)
mesh - an instance of Mesh class. Which manages the interface to the mesh radio library, reception of packets from other nodes, arbitrating to select
a node number and keeping the current nodedb.
typedef in32_t NodeNum;
class NodeInfo {
position;
last_seen
user
};
class NodeDB {
NodeNum provisionalNodeNum; // if we are trying to find a node num this is our current attempt
NodeNum ourNodeNum; // -1 if not yet found
HashMap<NodeNum, NodeInfo> nodes;
public:
/// don't do mesh based algoritm for node id assignment (initially) - instead just store in flash - possibly even in the initial alpha release do this hack
/// if returns false, that means our node should send a DenyNodeNum response. If true, we think the number is okay for use
// bool handleWantNodeNum(NodeNum n);
void handleDenyNodeNum(NodeNum FIXME read mesh proto docs, perhaps picking a random node num is not a great idea
and instead we should use a special 'im unconfigured node number' and include our desired node number in the wantnum message. the
unconfigured node num would only be used while initially joining the mesh so low odds of conflicting (especially if we randomly select
from a small number of nodenums which can be used temporarily for this operation). figure out what the lower level
mesh sw does if it does conflict? would it be better for people who are replying with denynode num to just broadcast their denial?)
};
*/
#define MAX_PACKETS 32 // max number of packets which can be in flight (either queued from reception or queued for sending)
#define MAX_RX_TOPHONE 16 // max number of packets which can be waiting for delivery to android
/// A temporary buffer used for sending packets, sized to hold the biggest buffer we might need
static uint8_t outbuf[MeshPacket_size];
/**
* Top level app for this service. keeps the mesh, the radio config and the queue of received packets.
*
*/
class MeshService
{
MemoryPool<MeshPacket> packetPool;
/// received packets waiting for the phone to process them
/// FIXME, change to a DropOldestQueue and keep a count of the number of dropped packets to ensure
/// we never hang because android hasn't been there in a while
PointerQueue<MeshPacket> toPhoneQueue;
/// Packets which have just arrived from the radio, ready to be processed by this service and possibly
/// forwarded to the phone. Note: not using yet - seeing if I can just handle everything asap in handleFromRadio
// PointerQueue<MeshPacket> fromRadioQueue;
public:
MeshService() : packetPool(MAX_PACKETS), toPhoneQueue(MAX_RX_TOPHONE) {
}
/// Do idle processing (mostly processing messages which have been queued from the radio)
// void loop() { }
/**
* handle an incoming MeshPacket from the radio, update DB state and queue it for the phone
*/
void handleFromRadio(NodeNum from, NodeNum to, const uint8_t *buf, size_t len) {
MeshPacket *p = packetPool.allocZeroed();
assert(p);
pb_istream_t stream = pb_istream_from_buffer(buf, len);
if (!pb_decode(&stream, MeshPacket_fields, p) || !p->has_payload)
{
Serial.printf("Error: can't decode MeshPacket %s\n", PB_GET_ERROR(&stream));
}
else
{
// FIXME - update DB state based on payload and show recevied texts
toPhoneQueue.enqueue(p);
}
}
/// Given a ToRadio buffer parse it and properly handle it (setup radio, owner or send packet into the mesh)
void handleToRadio(std::string s)
{
static ToRadio r; // new ToRadio(); FIXME dynamically allocate
pb_istream_t stream = pb_istream_from_buffer((const uint8_t *)s.c_str(), s.length());
if (!pb_decode(&stream, ToRadio_fields, &r))
{
Serial.printf("Error: can't decode ToRadio %s\n", PB_GET_ERROR(&stream));
}
else
{
switch (r.which_variant)
{
case ToRadio_packet_tag:
sendToMesh(r.variant.packet);
break;
default:
Serial.println("Error: unexpected ToRadio variant");
break;
}
}
}
private:
/// Send a packet into the mesh
void sendToMesh(const MeshPacket &p)
{
assert(p.has_payload);
pb_ostream_t stream = pb_ostream_from_buffer(outbuf, sizeof(outbuf));
if (!pb_encode(&stream, MeshPacket_fields, &p))
{
Serial.printf("Error: can't encode MeshPacket %s\n", PB_GET_ERROR(&stream));
}
else
{
assert(radio.sendTo(p.to, outbuf, stream.bytes_written) == ERRNO_OK);
}
}
};
MeshService service;
static BLECharacteristic meshFromRadioCharacteristic("8ba2bcc2-ee02-4a55-a531-c525c5e454d5", BLECharacteristic::PROPERTY_READ);
static BLECharacteristic meshToRadioCharacteristic("f75c76d2-129e-4dad-a1dd-7866124401e7", BLECharacteristic::PROPERTY_WRITE);