Files
firmware/src/modules/NodeInfoModule.h
T
James Rich b65fa9505c Send admin-made owner changes and admin NodeInfo requests past the routine throttle
An admin set_owner announced the new name through the routine NodeInfo path, so a rename made within
30 minutes of the last NodeInfo never went out - and the reboot set_owner schedules inherits that
throttle from the persisted transmit history. Inside an edit transaction nothing was sent at all.
The change is now announced on the 60 s interactive gate once it is saved, at commit for a
transaction.

A signed NodeInfo request from a node holding a live PKC admin session is likewise answered on the
60 s gate, past the 30 minute floor and the 12 h per-requester suppression.
2026-10-30 13:59:44 -05:00

74 lines
3.0 KiB
C++

#pragma once
#include "ProtobufModule.h"
#include <map>
/**
* NodeInfo module for sending/receiving NodeInfos into the mesh
*/
class NodeInfoModule : public ProtobufModule<meshtastic_User>, private concurrency::OSThread
{
/// The id of the last packet we sent, to allow us to cancel it if we make something fresher
PacketId prevPacketId = 0;
uint32_t currentGeneration = 0;
public:
/** Constructor
* name is for debugging output
*/
NodeInfoModule();
/**
* Send our NodeInfo into the mesh. True only when a packet was handed to the router.
*/
bool sendOurNodeInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0,
bool _shorterTimeout = false);
/**
* Schedule an immediate NodeInfo periodic check.
* Used when external conditions change (for example time source quality).
*/
void triggerImmediateNodeInfoCheck();
#ifdef PIO_UNIT_TESTING
/// Test-only reads of the routine-broadcast countdown a send re-arms. concurrency::OSThread is a
/// private base, so only this class can reach it - a test shim cannot.
unsigned long broadcastCountdownMsForTests() const { return interval; }
void armBroadcastCountdownForTests(unsigned long ms) { setIntervalFromNow(ms); }
/// The deadline the scheduler actually reads. interval alone cannot tell a deadline moved to
/// now from one recomputed off a stale last_run, which is the regression worth catching.
unsigned long broadcastDeadlineMsForTests() const { return _cached_next_run; }
/// Pretend the periodic thread last ran ageMs ago, so those two deadlines differ by ageMs.
void ageLastRunForTests(unsigned long ageMs) { runned(millis() - ageMs); }
#endif
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
*/
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *p) override;
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
* so that subclasses can (optionally) send a response back to the original sender. */
virtual meshtastic_MeshPacket *allocReply() override;
/** Does our periodic broadcast */
virtual int32_t runOnce() override;
private:
bool shorterTimeout = false;
/// Set across sendOurNodeInfo()'s own allocReply(), so the transmit stamp waits for an accepted send.
bool deferHistoryStamp = false;
bool suppressReplyForCurrentRequest = false;
/// The request came from a node holding a remote admin session, so it is answered on the interactive path.
bool adminRequestForCurrentRequest = false;
/// Sender -> uptime seconds (Time::getUptimeSecs()) at our last reply. Seconds, not millis:
/// the suppression window is hours wide. See handleReceivedProtobuf().
std::map<NodeNum, uint32_t> lastNodeInfoSeen;
void pruneLastNodeInfoCache();
};
extern NodeInfoModule *nodeInfoModule;