sforkowany z mirror/meshtastic-firmware
add beginnings of nodedb
rodzic
e6535f5504
commit
d11b023c85
7
TODO.md
7
TODO.md
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
|
@ -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]))
|
Ładowanie…
Reference in New Issue