fix: only let wifiStrength broadcasts move the RSSI baseline

The emit to a newly connected client also stored the RSSI and time, which
restarted the 10s hold-off and hid a real change from the clients already
connected.  The baseline moves into RssiBroadcast, which ignores
per-client emits, with unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-12 18:34:45 +02:00
parent c4472ba8e8
commit e47381b19e
5 changed files with 72 additions and 11 deletions

View file

@ -180,8 +180,8 @@ bool ESPNetwork::changeAP(const uint8_t *bssid, const int32_t channel) {
void ESPNetwork::emitSockets() {
this->emitHeap();
if(this->needsBroadcast ||
(this->connType == conn_types_t::wifi && rssiNeedsEmit(WiFi.RSSI(), this->lastRSSI, WiFi.channel(), this->lastChannel,
millis() - this->lastRSSIEmit, RSSI_EMIT_MIN_DBM, RSSI_EMIT_MIN_MS))) {
(this->connType == conn_types_t::wifi &&
this->rssiBroadcast.due(WiFi.RSSI(), WiFi.channel(), millis(), RSSI_EMIT_MIN_DBM, RSSI_EMIT_MIN_MS))) {
this->emitSockets(255);
sockEmit.loop();
this->needsBroadcast = false;
@ -209,9 +209,7 @@ void ESPNetwork::emitSockets(uint8_t num) {
json->addElem("channel", (int32_t)this->channel);
json->endObject();
sockEmit.endEmit(num);
this->lastRSSI = WiFi.RSSI();
this->lastChannel = WiFi.channel();
this->lastRSSIEmit = millis();
this->rssiBroadcast.sent(num == 255, WiFi.RSSI(), WiFi.channel(), millis());
}
else {
JsonSockEvent *json = sockEmit.beginEmit("wifiStrength");
@ -229,9 +227,7 @@ void ESPNetwork::emitSockets(uint8_t num) {
json->addElem("fullduplex", false);
json->endObject();
sockEmit.endEmit(num);
this->lastRSSI = -100;
this->lastChannel = -1;
this->lastRSSIEmit = millis();
this->rssiBroadcast.sent(num == 255, -100, -1, millis());
}
}
// A broadcast comes from emitSockets(), which has already sent memStatus.

View file

@ -1,5 +1,6 @@
#include <Arduino.h>
#include <WiFi.h>
#include "Utils.h"
#ifndef ESPNetwork_h
#define ESPNetwork_h
@ -21,9 +22,7 @@ class ESPNetwork {
protected:
unsigned long lastEmit = 0;
unsigned long lastMDNS = 0;
unsigned long lastRSSIEmit = 0;
int lastRSSI = 0;
int lastChannel = 0;
RssiBroadcast rssiBroadcast;
int linkSpeed = 0;
bool _connecting = false;
public:

View file

@ -135,3 +135,12 @@ bool rssiNeedsEmit(int rssi, int lastRssi, int channel, int lastChannel, uint32_
int delta = rssi > lastRssi ? rssi - lastRssi : lastRssi - rssi;
return delta >= minDelta && sinceLastMs >= minMs;
}
bool RssiBroadcast::due(int rssi, int channel, uint32_t now, int minDelta, uint32_t minMs) const {
return rssiNeedsEmit(rssi, this->rssi, channel, this->channel, now - this->at, minDelta, minMs);
}
void RssiBroadcast::sent(bool broadcast, int rssi, int channel, uint32_t now) {
if(!broadcast) return;
this->rssi = rssi;
this->channel = channel;
this->at = now;
}

View file

@ -60,6 +60,15 @@ struct rebootDelay_t {
// otherwise only for an RSSI change of at least minDelta dBm and not more often
// than every minMs.
bool rssiNeedsEmit(int rssi, int lastRssi, int channel, int lastChannel, uint32_t sinceLastMs, int minDelta, uint32_t minMs);
// What the last wifiStrength broadcast told every client. Only broadcasts
// move it: an emit to one new client tells the others nothing.
struct RssiBroadcast {
int rssi = 0;
int channel = 0;
uint32_t at = 0; // millis() of the last broadcast.
bool due(int rssi, int channel, uint32_t now, int minDelta, uint32_t minMs) const;
void sent(bool broadcast, int rssi, int channel, uint32_t now);
};
class Timestamp {
char _timeBuffer[128];