add beginnings of nodedb

1.2-legacy
geeksville 2020-02-03 09:13:19 -08:00
rodzic e6535f5504
commit d11b023c85
8 zmienionych plików z 194 dodań i 51 usunięć

Wyświetl plik

@ -2,6 +2,9 @@
* have MeshService keep a node DB by sniffing user messages * have MeshService keep a node DB by sniffing user messages
* have meshservice send location data on mesh (if device has a GPS) * have meshservice send location data on mesh (if device has a GPS)
* implement getCurrentTime() - set based off gps but then updated locally
* confirm second device receives that gps message and updates device db
* switch to my gui layout manager
* have a state machine return the correct FromRadio packet to the phone, it isn't always going to be a MeshPacket. Do a notify on fromnum to force the radio to read our state machine generated packets * have a state machine return the correct FromRadio packet to the phone, it isn't always going to be a MeshPacket. Do a notify on fromnum to force the radio to read our state machine generated packets
* send my_node_num when phone sends WantsNodes * send my_node_num when phone sends WantsNodes
* make jtag work on second board * make jtag work on second board
@ -10,8 +13,8 @@
# Medium priority # Medium priority
* save our node db (and any rx packets waiting for phone) to flash * save our node db (and any rx packets waiting for phone) to flash - see DeviceState protobuf
* send correct hw vendor in the bluetooth info * send correct hw vendor in the bluetooth info - needed so the android app can update different radio models
* use https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/ association sleep pattern to save power - but see https://github.com/espressif/esp-idf/issues/2070 * use https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/ association sleep pattern to save power - but see https://github.com/espressif/esp-idf/issues/2070
* correctly map nodeids to nodenums, currently we just do a proof of concept by always doing a broadcast * correctly map nodeids to nodenums, currently we just do a proof of concept by always doing a broadcast
* add interrupt detach/sleep mode config to lora radio so we can enable deepsleep without panicing * add interrupt detach/sleep mode config to lora radio so we can enable deepsleep without panicing

Wyświetl plik

@ -7,27 +7,15 @@
#include <pb_decode.h> #include <pb_decode.h>
#include "MeshRadio.h" #include "MeshRadio.h"
#include "configuration.h" #include "configuration.h"
#include "NodeDB.h"
// Change to 434.0 or other frequency, must match RX's freq! // Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 915.0 #define RF95_FREQ 915.0
/**
* get our starting (provisional) nodenum from flash. But check first if anyone else is using it, by trying to send a message to it (arping)
*/
NodeNum getDesiredNodeNum()
{
uint8_t dmac[6];
esp_efuse_mac_get_default(dmac);
// FIXME not the right way to guess node numes
uint8_t r = dmac[5];
assert(r != 0xff); // It better not be the broadcast address
return r;
}
MeshRadio::MeshRadio(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest) MeshRadio::MeshRadio(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &_rxDest)
: rf95(NSS_GPIO, DIO0_GPIO), : rf95(NSS_GPIO, DIO0_GPIO),
manager(rf95, getDesiredNodeNum()), manager(rf95, nodeDB.getNodeNum()),
pool(_pool), pool(_pool),
rxDest(_rxDest), rxDest(_rxDest),
txQueue(MAX_TX_QUEUE) txQueue(MAX_TX_QUEUE)

Wyświetl plik

@ -5,13 +5,9 @@
#include "MemoryPool.h" #include "MemoryPool.h"
#include "mesh.pb.h" #include "mesh.pb.h"
#include "PointerQueue.h" #include "PointerQueue.h"
#include "MeshTypes.h"
#define NODENUM_BROADCAST 255
#define ERRNO_OK 0
#define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER
typedef int ErrorCode;
typedef uint8_t NodeNum;
#define MAX_TX_QUEUE 8 // max number of packets which can be waiting for transmission #define MAX_TX_QUEUE 8 // max number of packets which can be waiting for transmission

Wyświetl plik

@ -4,9 +4,10 @@
#include <pb_encode.h> #include <pb_encode.h>
#include <pb_decode.h> #include <pb_decode.h>
#include "mesh.pb.h" #include "mesh-pb-constants.h"
#include "MeshService.h" #include "MeshService.h"
#include "MeshBluetoothService.h" #include "MeshBluetoothService.h"
#include "NodeDB.h"
/* /*
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone. receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
@ -17,40 +18,13 @@ of packets we can delete just as soon as we are sure the phone has acked those p
mesh - an instance of Mesh class. Which manages the interface to the mesh radio library, reception of packets from other nodes, arbitrating to select 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. 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?)
};
*/ */
MeshService service; MeshService service;
#define MAX_PACKETS 32 // max number of packets which can be in flight (either queued from reception or queued for sending) #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
#define MAX_RX_FROMRADIO 4 // max number of packets destined to our queue, we dispatch packets quickly so it doesn't need to be big #define MAX_RX_FROMRADIO 4 // max number of packets destined to our queue, we dispatch packets quickly so it doesn't need to be big
MeshService::MeshService() MeshService::MeshService()
@ -60,6 +34,7 @@ MeshService::MeshService()
fromNum(0), fromNum(0),
radio(packetPool, fromRadioQueue) radio(packetPool, fromRadioQueue)
{ {
// assert(MAX_RX_TOPHONE == 32); // FIXME, delete this, just checking my clever macro
} }
void MeshService::init() void MeshService::init()

13
src/MeshTypes.h 100644
Wyświetl plik

@ -0,0 +1,13 @@
#pragma once
// low level types
#include <Arduino.h>
typedef uint8_t NodeNum;
#define NODENUM_BROADCAST 255
#define ERRNO_OK 0
#define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER
typedef int ErrorCode;

102
src/NodeDB.cpp 100644
Wyświetl plik

@ -0,0 +1,102 @@
#include <Arduino.h>
#include <assert.h>
#include <pb_encode.h>
#include <pb_decode.h>
#include "mesh-pb-constants.h"
#include "NodeDB.h"
NodeDB nodeDB;
/**
* get our starting (provisional) nodenum from flash. But check first if anyone else is using it, by trying to send a message to it (arping)
*/
static NodeNum getDesiredNodeNum()
{
uint8_t dmac[6];
esp_efuse_mac_get_default(dmac);
// FIXME not the right way to guess node numes
uint8_t r = dmac[5];
assert(r != 0xff); // It better not be the broadcast address
return r;
}
NodeDB::NodeDB() : ourNodeNum(getDesiredNodeNum()), numNodes(0)
{
}
/// return number msecs since 1970
uint64_t getCurrentTime() {
return 4403; // FIXME
}
/// given a subpacket sniffed from the network, update our DB state
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
void NodeDB::updateFrom(const MeshPacket &mp)
{
if (mp.has_payload)
{
const SubPacket &p = mp.payload;
Serial.printf("Update DB node %x for %d\n", mp.from, p.which_variant);
if (p.which_variant != SubPacket_want_node_tag) // we don't create nodeinfo records for someone that is just trying to claim a nodenum
{
int oldNumNodes = numNodes;
NodeInfo *info = getOrCreateNode(mp.from);
if (oldNumNodes != numNodes)
updateGUI = true; // we just created a nodeinfo
info->last_seen.msecs = getCurrentTime();
info->has_last_seen = true;
switch (p.which_variant)
{
case SubPacket_position_tag:
info->position = p.variant.position;
info->has_position = true;
updateGUIforNode = info;
break;
case SubPacket_user_tag:
info->user = p.variant.user;
info->has_user = true;
updateGUIforNode = info;
break;
default:
break; // Ignore other packet types
}
}
}
}
/// Find a node in our DB, return null for missing
NodeInfo *NodeDB::getNode(NodeNum n)
{
for (int i = 0; i < numNodes; i++)
if (nodes[i].num == n)
return &nodes[i];
return NULL;
}
/// Find a node in our DB, create an empty NodeInfo if missing
NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
{
NodeInfo *info = getNode(n);
if (!n)
{
// add the node
assert(numNodes < MAX_NUM_NODES);
info = &nodes[numNodes++];
// everything is missing except the nodenum
memset(info, 0, sizeof(*info));
info->num = n;
}
return info;
}

52
src/NodeDB.h 100644
Wyświetl plik

@ -0,0 +1,52 @@
#pragma once
#include <Arduino.h>
#include <assert.h>
#include "mesh-pb-constants.h"
#include "MeshTypes.h"
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
// A NodeInfo for every node we've seen
// Eventually use a smarter datastructure
// HashMap<NodeNum, NodeInfo> nodes;
NodeInfo nodes[MAX_NUM_NODES];
int numNodes;
bool updateGUI; // we think the gui should definitely be redrawn
NodeInfo *updateGUIforNode; // if currently showing this node, we think you should update the GUI
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
NodeDB();
/// given a subpacket sniffed from the network, update our DB state
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
void updateFrom(const MeshPacket &p);
NodeNum getNodeNum() { return ourNodeNum; }
/// 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?)
*/
private:
/// Find a node in our DB, return null for missing
NodeInfo *getNode(NodeNum n);
/// Find a node in our DB, create an empty NodeInfo if missing
NodeInfo *getOrCreateNode(NodeNum n);
};
extern NodeDB nodeDB;

Wyświetl plik

@ -0,0 +1,14 @@
#pragma once
#include "mesh.pb.h"
// this file defines constants which come from mesh.options
// Tricky macro to let you find the sizeof a type member
#define member_size(type, member) sizeof(((type *)0)->member)
/// max number of packets which can be waiting for delivery to android - note, this value comes from mesh.options protobuf
#define MAX_RX_TOPHONE (member_size(DeviceState, receive_queue) / member_size(DeviceState, receive_queue[0]))
/// max number of nodes allowed in the mesh
#define MAX_NUM_NODES (member_size(DeviceState, node_db) / member_size(DeviceState, node_db[0]))