2020-02-03 17:13:19 +00:00
|
|
|
#pragma once
|
|
|
|
|
2020-08-12 18:04:03 +00:00
|
|
|
#include "Observer.h"
|
2020-02-03 17:13:19 +00:00
|
|
|
#include <Arduino.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "MeshTypes.h"
|
2020-06-28 04:19:49 +00:00
|
|
|
#include "NodeStatus.h"
|
2020-08-12 18:04:03 +00:00
|
|
|
#include "mesh-pb-constants.h"
|
2020-02-03 17:13:19 +00:00
|
|
|
|
2020-02-13 03:58:44 +00:00
|
|
|
extern DeviceState devicestate;
|
2020-02-07 17:36:15 +00:00
|
|
|
extern MyNodeInfo &myNodeInfo;
|
|
|
|
extern RadioConfig &radioConfig;
|
2020-02-11 19:56:48 +00:00
|
|
|
extern ChannelSettings &channelSettings;
|
2020-02-07 17:36:15 +00:00
|
|
|
extern User &owner;
|
2020-02-04 21:47:42 +00:00
|
|
|
|
2020-02-12 19:52:53 +00:00
|
|
|
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
|
|
|
uint32_t sinceLastSeen(const NodeInfo *n);
|
|
|
|
|
2020-02-04 05:03:20 +00:00
|
|
|
class NodeDB
|
|
|
|
{
|
2020-02-03 17:13:19 +00:00
|
|
|
// NodeNum provisionalNodeNum; // if we are trying to find a node num this is our current attempt
|
|
|
|
|
|
|
|
// A NodeInfo for every node we've seen
|
|
|
|
// Eventually use a smarter datastructure
|
|
|
|
// HashMap<NodeNum, NodeInfo> nodes;
|
2020-02-07 17:36:15 +00:00
|
|
|
// Note: these two references just point into our static array we serialize to/from disk
|
|
|
|
NodeInfo *nodes;
|
|
|
|
pb_size_t *numNodes;
|
2020-02-04 05:03:20 +00:00
|
|
|
|
2020-07-24 17:12:25 +00:00
|
|
|
uint32_t readPointer = 0;
|
2020-02-03 17:13:19 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
public:
|
|
|
|
bool updateGUI = false; // we think the gui should definitely be redrawn, screen will clear this once handled
|
2020-02-13 03:58:44 +00:00
|
|
|
NodeInfo *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI
|
2020-06-29 01:17:52 +00:00
|
|
|
Observable<const meshtastic::NodeStatus *> newStatus;
|
2020-02-13 03:58:44 +00:00
|
|
|
|
2020-02-03 17:13:19 +00:00
|
|
|
/// 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();
|
|
|
|
|
2020-02-04 17:00:17 +00:00
|
|
|
/// Called from service after app start, to do init which can only be done after OS load
|
|
|
|
void init();
|
|
|
|
|
2020-02-07 17:36:15 +00:00
|
|
|
/// write to flash
|
|
|
|
void saveToDisk();
|
|
|
|
|
2020-09-19 18:19:42 +00:00
|
|
|
/** Reinit radio config if needed, because either:
|
2020-10-06 01:43:00 +00:00
|
|
|
* a) sometimes a buggy android app might send us bogus settings or
|
2020-09-19 18:19:42 +00:00
|
|
|
* b) the client set factory_reset
|
2020-10-06 01:43:00 +00:00
|
|
|
*
|
2020-09-19 18:19:42 +00:00
|
|
|
* @return true if the config was completely reset, in that case, we should send it back to the client
|
|
|
|
*/
|
|
|
|
bool resetRadioConfig();
|
2020-03-30 23:05:28 +00:00
|
|
|
|
2020-02-03 17:13:19 +00:00
|
|
|
/// 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);
|
|
|
|
|
2020-12-03 08:48:44 +00:00
|
|
|
/** Update position info for this node based on received position data
|
|
|
|
*/
|
|
|
|
void updatePosition(uint32_t nodeId, const Position &p);
|
|
|
|
|
2020-02-18 00:32:51 +00:00
|
|
|
/// @return our node number
|
2020-02-04 21:47:42 +00:00
|
|
|
NodeNum getNodeNum() { return myNodeInfo.my_node_num; }
|
2020-02-03 17:13:19 +00:00
|
|
|
|
2020-02-11 18:51:45 +00:00
|
|
|
size_t getNumNodes() { return *numNodes; }
|
|
|
|
|
2020-02-03 17:13:19 +00:00
|
|
|
/// 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
|
2020-03-19 02:15:51 +00:00
|
|
|
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?)
|
2020-02-03 17:13:19 +00:00
|
|
|
*/
|
|
|
|
|
2020-02-04 05:03:20 +00:00
|
|
|
/// Called from bluetooth when the user wants to start reading the node DB from scratch.
|
|
|
|
void resetReadPointer() { readPointer = 0; }
|
|
|
|
|
|
|
|
/// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading
|
|
|
|
const NodeInfo *readNextInfo();
|
|
|
|
|
2020-02-08 20:42:54 +00:00
|
|
|
/// pick a provisional nodenum we hope no one is using
|
|
|
|
void pickNewNodeNum();
|
|
|
|
|
2020-02-03 17:13:19 +00:00
|
|
|
/// Find a node in our DB, return null for missing
|
|
|
|
NodeInfo *getNode(NodeNum n);
|
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
NodeInfo *getNodeByIndex(size_t x)
|
|
|
|
{
|
|
|
|
assert(x < *numNodes);
|
|
|
|
return &nodes[x];
|
|
|
|
}
|
2020-02-11 18:51:45 +00:00
|
|
|
|
2020-02-11 19:56:48 +00:00
|
|
|
/// Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
2020-02-12 19:52:53 +00:00
|
|
|
size_t getNumOnlineNodes();
|
2020-02-11 19:56:48 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
private:
|
2020-02-04 05:03:20 +00:00
|
|
|
/// Find a node in our DB, create an empty NodeInfo if missing
|
2020-02-03 17:13:19 +00:00
|
|
|
NodeInfo *getOrCreateNode(NodeNum n);
|
2020-02-07 17:36:15 +00:00
|
|
|
|
2020-06-28 04:19:49 +00:00
|
|
|
/// Notify observers of changes to the DB
|
2020-08-12 18:04:03 +00:00
|
|
|
void notifyObservers(bool forceUpdate = false)
|
|
|
|
{
|
2020-06-28 04:19:49 +00:00
|
|
|
// Notify observers of the current node state
|
2020-07-06 00:03:12 +00:00
|
|
|
const meshtastic::NodeStatus status = meshtastic::NodeStatus(getNumOnlineNodes(), getNumNodes(), forceUpdate);
|
2020-06-29 01:17:52 +00:00
|
|
|
newStatus.notifyObservers(&status);
|
2020-06-28 04:19:49 +00:00
|
|
|
}
|
|
|
|
|
2020-02-07 17:36:15 +00:00
|
|
|
/// read our db from flash
|
|
|
|
void loadFromDisk();
|
2020-06-16 22:02:11 +00:00
|
|
|
|
|
|
|
/// Reinit device state from scratch (not loading from disk)
|
|
|
|
void installDefaultDeviceState();
|
2020-02-03 17:13:19 +00:00
|
|
|
};
|
|
|
|
|
2020-05-22 00:21:44 +00:00
|
|
|
/**
|
|
|
|
* The node number the user is currently looking at
|
|
|
|
* 0 if none
|
|
|
|
*/
|
|
|
|
extern NodeNum displayedNodeNum;
|
|
|
|
|
2020-02-03 17:13:19 +00:00
|
|
|
extern NodeDB nodeDB;
|
2020-08-12 18:04:03 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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".
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* This function will also need to be implemented in GUI apps that talk to the radio.
|
|
|
|
*
|
|
|
|
* https://github.com/meshtastic/Meshtastic-device/issues/269
|
|
|
|
*/
|
2020-10-06 01:43:00 +00:00
|
|
|
const char *getChannelName();
|
|
|
|
|
|
|
|
#define PREF_GET(name, defaultVal) \
|
|
|
|
inline uint32_t getPref_##name() { return radioConfig.preferences.name ? radioConfig.preferences.name : (defaultVal); }
|
|
|
|
|
|
|
|
PREF_GET(send_owner_interval, 4)
|
|
|
|
PREF_GET(position_broadcast_secs, 15 * 60)
|
2020-10-14 00:53:12 +00:00
|
|
|
|
|
|
|
// Each time we wake into the DARK state allow 1 minute to send and receive BLE packets to the phone
|
|
|
|
PREF_GET(wait_bluetooth_secs, 60)
|
|
|
|
|
2020-10-06 01:43:00 +00:00
|
|
|
PREF_GET(screen_on_secs, 60)
|
|
|
|
PREF_GET(mesh_sds_timeout_secs, 2 * 60 * 60)
|
|
|
|
PREF_GET(phone_sds_timeout_sec, 2 * 60 * 60)
|
|
|
|
PREF_GET(sds_secs, 365 * 24 * 60 * 60)
|
2020-10-14 00:53:12 +00:00
|
|
|
|
|
|
|
// We default to sleeping (with bluetooth off for 5 minutes at a time). This seems to be a good tradeoff between
|
|
|
|
// latency for the user sending messages and power savings because of not having to run (expensive) ESP32 bluetooth
|
|
|
|
PREF_GET(ls_secs, 5 * 60)
|
|
|
|
|
2020-10-06 01:43:00 +00:00
|
|
|
PREF_GET(phone_timeout_secs, 15 * 60)
|
|
|
|
PREF_GET(min_wake_secs, 10)
|