* Repeater/Room server: new diagnostics, stats.n_full_events now repurposed to 'err_events' (bit flags)

* new Radio::isInRecvMode() method
This commit is contained in:
Scott Powell
2025-05-13 15:38:10 +10:00
parent 62a5115cc9
commit 177dd90ca1
8 changed files with 46 additions and 9 deletions

View File

@@ -91,7 +91,7 @@ struct RepeaterStats {
uint32_t total_up_time_secs;
uint32_t n_sent_flood, n_sent_direct;
uint32_t n_recv_flood, n_recv_direct;
uint16_t n_full_events;
uint16_t err_events; // was 'n_full_events'
int16_t last_snr; // x 4
uint16_t n_direct_dups, n_flood_dups;
};
@@ -195,7 +195,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
stats.n_sent_direct = getNumSentDirect();
stats.n_recv_flood = getNumRecvFlood();
stats.n_recv_direct = getNumRecvDirect();
stats.n_full_events = getNumFullEvents();
stats.err_events = _err_flags;
stats.last_snr = (int16_t)(radio_driver.getLastSNR() * 4);
stats.n_direct_dups = ((SimpleMeshTables *)getTables())->getNumDirectDups();
stats.n_flood_dups = ((SimpleMeshTables *)getTables())->getNumFloodDups();

View File

@@ -138,7 +138,7 @@ struct ServerStats {
uint32_t total_up_time_secs;
uint32_t n_sent_flood, n_sent_direct;
uint32_t n_recv_flood, n_recv_direct;
uint16_t n_full_events;
uint16_t err_events; // was 'n_full_events'
int16_t last_snr; // x 4
uint16_t n_direct_dups, n_flood_dups;
uint16_t n_posted, n_post_push;
@@ -301,7 +301,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
stats.n_sent_direct = getNumSentDirect();
stats.n_recv_flood = getNumRecvFlood();
stats.n_recv_direct = getNumRecvDirect();
stats.n_full_events = getNumFullEvents();
stats.err_events = _err_flags;
stats.last_snr = (int16_t)(radio_driver.getLastSNR() * 4);
stats.n_direct_dups = ((SimpleMeshTables *)getTables())->getNumDirectDups();
stats.n_flood_dups = ((SimpleMeshTables *)getTables())->getNumFloodDups();

View File

@@ -13,7 +13,7 @@ namespace mesh {
void Dispatcher::begin() {
n_sent_flood = n_sent_direct = 0;
n_recv_flood = n_recv_direct = 0;
n_full_events = 0;
_err_flags = 0;
_radio->begin();
}
@@ -34,6 +34,18 @@ uint32_t Dispatcher::getCADFailMaxDuration() const {
}
void Dispatcher::loop() {
// check for radio 'stuck' in mode other than Rx
bool is_recv = _radio->isInRecvMode();
if (is_recv != prev_isrecv_mode) {
prev_isrecv_mode = is_recv;
if (!is_recv) {
radio_nonrx_start = _ms->getMillis();
}
}
if (!is_recv && _ms->getMillis() - radio_nonrx_start > 8000) { // radio has not been in Rx mode for 8 seconds!
_err_flags |= ERR_EVENT_STARTRX_TIMEOUT;
}
if (outbound) { // waiting for outbound send to be completed
if (_radio->isSendComplete()) {
long t = _ms->getMillis() - outbound_start;
@@ -199,6 +211,8 @@ void Dispatcher::checkSend() {
}
if (_ms->getMillis() - cad_busy_start > getCADFailMaxDuration()) {
_err_flags |= ERR_EVENT_CAD_TIMEOUT;
MESH_DEBUG_PRINTLN("%s Dispatcher::checkSend(): CAD busy max duration reached!", getLogDateTime());
// channel activity has gone on too long... (Radio might be in a bad state)
// force the pending transmit below...
@@ -264,7 +278,7 @@ void Dispatcher::checkSend() {
Packet* Dispatcher::obtainNewPacket() {
auto pkt = _mgr->allocNew(); // TODO: zero out all fields
if (pkt == NULL) {
n_full_events++;
_err_flags |= ERR_EVENT_FULL;
} else {
pkt->payload_len = pkt->path_len = 0;
pkt->_snr = 0;

View File

@@ -56,6 +56,8 @@ public:
*/
virtual void onSendFinished() = 0;
virtual bool isInRecvMode() const = 0;
/**
* \returns true if the radio is currently mid-receive of a packet.
*/
@@ -91,6 +93,10 @@ typedef uint32_t DispatcherAction;
#define ACTION_RETRANSMIT(pri) (((uint32_t)1 + (pri))<<24)
#define ACTION_RETRANSMIT_DELAYED(pri, _delay) ((((uint32_t)1 + (pri))<<24) | (_delay))
#define ERR_EVENT_FULL (1 << 0)
#define ERR_EVENT_CAD_TIMEOUT (1 << 1)
#define ERR_EVENT_STARTRX_TIMEOUT (1 << 2)
/**
* \brief The low-level task that manages detecting incoming Packets, and the queueing
* and scheduling of outbound Packets.
@@ -100,9 +106,10 @@ class Dispatcher {
unsigned long outbound_expiry, outbound_start, total_air_time;
unsigned long next_tx_time;
unsigned long cad_busy_start;
unsigned long radio_nonrx_start;
bool prev_isrecv_mode;
uint32_t n_sent_flood, n_sent_direct;
uint32_t n_recv_flood, n_recv_direct;
uint32_t n_full_events;
void processRecvPacket(Packet* pkt);
@@ -110,12 +117,16 @@ protected:
PacketManager* _mgr;
Radio* _radio;
MillisecondClock* _ms;
uint16_t _err_flags;
Dispatcher(Radio& radio, MillisecondClock& ms, PacketManager& mgr)
: _radio(&radio), _ms(&ms), _mgr(&mgr)
{
outbound = NULL; total_air_time = 0; next_tx_time = 0;
cad_busy_start = 0;
_err_flags = 0;
radio_nonrx_start = 0;
prev_isrecv_mode = true;
}
virtual DispatcherAction onRecvPacket(Packet* pkt) = 0;
@@ -145,7 +156,6 @@ public:
uint32_t getNumSentDirect() const { return n_sent_direct; }
uint32_t getNumRecvFlood() const { return n_recv_flood; }
uint32_t getNumRecvDirect() const { return n_recv_direct; }
uint32_t getNumFullEvents() const { return n_full_events; }
// helper methods
bool millisHasNowPassed(unsigned long timestamp) const;

View File

@@ -44,6 +44,10 @@ void RadioLibWrapper::startRecv() {
}
}
bool RadioLibWrapper::isInRecvMode() const {
return (state & ~STATE_INT_READY) == STATE_RX;
}
int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) {
if (state & STATE_INT_READY) {
int len = _radio->getPacketLength();

View File

@@ -22,6 +22,7 @@ public:
bool startSendRaw(const uint8_t* bytes, int len) override;
bool isSendComplete() override;
void onSendFinished() override;
bool isInRecvMode() const override;
uint32_t getPacketsRecv() const { return n_recv; }
uint32_t getPacketsSent() const { return n_sent; }

View File

@@ -5,7 +5,7 @@
static uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static esp_now_peer_info_t peerInfo;
static bool is_send_complete = false;
static volatile bool is_send_complete = false;
static esp_err_t last_send_result;
static uint8_t rx_buf[256];
static uint8_t last_rx_len = 0;
@@ -44,6 +44,8 @@ void ESPNOWRadio::init() {
peerInfo.channel = 0;
peerInfo.encrypt = false;
is_send_complete = true;
// Add peer
if (esp_now_add_peer(&peerInfo) == ESP_OK) {
ESPNOW_DEBUG_PRINTLN("init success");
@@ -86,6 +88,11 @@ bool ESPNOWRadio::isSendComplete() {
return is_send_complete;
}
void ESPNOWRadio::onSendFinished() {
is_send_complete = true;
}
bool ESPNOWRadio::isInRecvMode() const {
return is_send_complete; // if NO send in progress, then we're in Rx mode
}
float ESPNOWRadio::getLastRSSI() const { return 0; }

View File

@@ -15,6 +15,7 @@ public:
bool startSendRaw(const uint8_t* bytes, int len) override;
bool isSendComplete() override;
void onSendFinished() override;
bool isInRecvMode() const override;
uint32_t getPacketsRecv() const { return n_recv; }
uint32_t getPacketsSent() const { return n_sent; }