mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 22:02:17 +01:00
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:
parent
c4472ba8e8
commit
e47381b19e
5 changed files with 72 additions and 11 deletions
|
|
@ -180,8 +180,8 @@ bool ESPNetwork::changeAP(const uint8_t *bssid, const int32_t channel) {
|
||||||
void ESPNetwork::emitSockets() {
|
void ESPNetwork::emitSockets() {
|
||||||
this->emitHeap();
|
this->emitHeap();
|
||||||
if(this->needsBroadcast ||
|
if(this->needsBroadcast ||
|
||||||
(this->connType == conn_types_t::wifi && rssiNeedsEmit(WiFi.RSSI(), this->lastRSSI, WiFi.channel(), this->lastChannel,
|
(this->connType == conn_types_t::wifi &&
|
||||||
millis() - this->lastRSSIEmit, RSSI_EMIT_MIN_DBM, RSSI_EMIT_MIN_MS))) {
|
this->rssiBroadcast.due(WiFi.RSSI(), WiFi.channel(), millis(), RSSI_EMIT_MIN_DBM, RSSI_EMIT_MIN_MS))) {
|
||||||
this->emitSockets(255);
|
this->emitSockets(255);
|
||||||
sockEmit.loop();
|
sockEmit.loop();
|
||||||
this->needsBroadcast = false;
|
this->needsBroadcast = false;
|
||||||
|
|
@ -209,9 +209,7 @@ void ESPNetwork::emitSockets(uint8_t num) {
|
||||||
json->addElem("channel", (int32_t)this->channel);
|
json->addElem("channel", (int32_t)this->channel);
|
||||||
json->endObject();
|
json->endObject();
|
||||||
sockEmit.endEmit(num);
|
sockEmit.endEmit(num);
|
||||||
this->lastRSSI = WiFi.RSSI();
|
this->rssiBroadcast.sent(num == 255, WiFi.RSSI(), WiFi.channel(), millis());
|
||||||
this->lastChannel = WiFi.channel();
|
|
||||||
this->lastRSSIEmit = millis();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JsonSockEvent *json = sockEmit.beginEmit("wifiStrength");
|
JsonSockEvent *json = sockEmit.beginEmit("wifiStrength");
|
||||||
|
|
@ -229,9 +227,7 @@ void ESPNetwork::emitSockets(uint8_t num) {
|
||||||
json->addElem("fullduplex", false);
|
json->addElem("fullduplex", false);
|
||||||
json->endObject();
|
json->endObject();
|
||||||
sockEmit.endEmit(num);
|
sockEmit.endEmit(num);
|
||||||
this->lastRSSI = -100;
|
this->rssiBroadcast.sent(num == 255, -100, -1, millis());
|
||||||
this->lastChannel = -1;
|
|
||||||
this->lastRSSIEmit = millis();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// A broadcast comes from emitSockets(), which has already sent memStatus.
|
// A broadcast comes from emitSockets(), which has already sent memStatus.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
#ifndef ESPNetwork_h
|
#ifndef ESPNetwork_h
|
||||||
#define ESPNetwork_h
|
#define ESPNetwork_h
|
||||||
|
|
@ -21,9 +22,7 @@ class ESPNetwork {
|
||||||
protected:
|
protected:
|
||||||
unsigned long lastEmit = 0;
|
unsigned long lastEmit = 0;
|
||||||
unsigned long lastMDNS = 0;
|
unsigned long lastMDNS = 0;
|
||||||
unsigned long lastRSSIEmit = 0;
|
RssiBroadcast rssiBroadcast;
|
||||||
int lastRSSI = 0;
|
|
||||||
int lastChannel = 0;
|
|
||||||
int linkSpeed = 0;
|
int linkSpeed = 0;
|
||||||
bool _connecting = false;
|
bool _connecting = false;
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -135,3 +135,12 @@ bool rssiNeedsEmit(int rssi, int lastRssi, int channel, int lastChannel, uint32_
|
||||||
int delta = rssi > lastRssi ? rssi - lastRssi : lastRssi - rssi;
|
int delta = rssi > lastRssi ? rssi - lastRssi : lastRssi - rssi;
|
||||||
return delta >= minDelta && sinceLastMs >= minMs;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,15 @@ struct rebootDelay_t {
|
||||||
// otherwise only for an RSSI change of at least minDelta dBm and not more often
|
// otherwise only for an RSSI change of at least minDelta dBm and not more often
|
||||||
// than every minMs.
|
// than every minMs.
|
||||||
bool rssiNeedsEmit(int rssi, int lastRssi, int channel, int lastChannel, uint32_t sinceLastMs, int minDelta, uint32_t 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 {
|
class Timestamp {
|
||||||
char _timeBuffer[128];
|
char _timeBuffer[128];
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,49 @@ static void test_rssiNeedsEmit_either_direction() {
|
||||||
TEST_ASSERT_TRUE(rssiNeedsEmit(-73, -70, 6, 6, 10000, 3, 10000));
|
TEST_ASSERT_TRUE(rssiNeedsEmit(-73, -70, 6, 6, 10000, 3, 10000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* RssiBroadcast
|
||||||
|
********************************************************************/
|
||||||
|
static RssiBroadcast broadcastAt(int rssi, int channel, uint32_t at) {
|
||||||
|
RssiBroadcast b;
|
||||||
|
b.sent(true, rssi, channel, at);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
static void test_rssiBroadcast_client_emit_keeps_baseline() {
|
||||||
|
// A new client gets the current RSSI right as it drops 5 dBm. The clients
|
||||||
|
// already connected must still get the change.
|
||||||
|
RssiBroadcast b = broadcastAt(-60, 6, 0);
|
||||||
|
b.sent(false, -65, 6, 20000);
|
||||||
|
TEST_ASSERT_EQUAL_INT(-60, b.rssi);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(0, b.at);
|
||||||
|
TEST_ASSERT_TRUE(b.due(-65, 6, 20000, 3, 10000));
|
||||||
|
}
|
||||||
|
static void test_rssiBroadcast_broadcast_moves_baseline() {
|
||||||
|
RssiBroadcast b = broadcastAt(-60, 6, 0);
|
||||||
|
b.sent(true, -65, 6, 20000);
|
||||||
|
TEST_ASSERT_EQUAL_INT(-65, b.rssi);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(20000, b.at);
|
||||||
|
// Measured from the new baseline and too soon after it.
|
||||||
|
TEST_ASSERT_FALSE(b.due(-66, 6, 40000, 3, 10000));
|
||||||
|
TEST_ASSERT_FALSE(b.due(-70, 6, 25000, 3, 10000));
|
||||||
|
TEST_ASSERT_TRUE(b.due(-70, 6, 30000, 3, 10000));
|
||||||
|
}
|
||||||
|
static void test_rssiBroadcast_channel_change_is_due() {
|
||||||
|
RssiBroadcast b = broadcastAt(-60, 6, 1000);
|
||||||
|
TEST_ASSERT_TRUE(b.due(-60, 11, 1000, 3, 10000));
|
||||||
|
}
|
||||||
|
static void test_rssiBroadcast_client_emit_on_disconnect_keeps_baseline() {
|
||||||
|
RssiBroadcast b = broadcastAt(-60, 6, 0);
|
||||||
|
b.sent(false, -100, -1, 5000);
|
||||||
|
TEST_ASSERT_EQUAL_INT(6, b.channel);
|
||||||
|
TEST_ASSERT_FALSE(b.due(-60, 6, 5000, 3, 10000));
|
||||||
|
}
|
||||||
|
static void test_rssiBroadcast_hold_off_across_millis_wrap() {
|
||||||
|
RssiBroadcast b = broadcastAt(-60, 6, 0xFFFFF000u);
|
||||||
|
TEST_ASSERT_FALSE(b.due(-70, 6, 0x00001000u, 3, 10000)); // 8192ms later
|
||||||
|
TEST_ASSERT_TRUE(b.due(-70, 6, 0x00002000u, 3, 10000)); // 12288ms later
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
@ -228,5 +271,10 @@ int main(int argc, char **argv) {
|
||||||
RUN_TEST(test_rssiNeedsEmit_real_change_after_interval_emits);
|
RUN_TEST(test_rssiNeedsEmit_real_change_after_interval_emits);
|
||||||
RUN_TEST(test_rssiNeedsEmit_real_change_too_soon_waits);
|
RUN_TEST(test_rssiNeedsEmit_real_change_too_soon_waits);
|
||||||
RUN_TEST(test_rssiNeedsEmit_either_direction);
|
RUN_TEST(test_rssiNeedsEmit_either_direction);
|
||||||
|
RUN_TEST(test_rssiBroadcast_client_emit_keeps_baseline);
|
||||||
|
RUN_TEST(test_rssiBroadcast_broadcast_moves_baseline);
|
||||||
|
RUN_TEST(test_rssiBroadcast_channel_change_is_due);
|
||||||
|
RUN_TEST(test_rssiBroadcast_client_emit_on_disconnect_keeps_baseline);
|
||||||
|
RUN_TEST(test_rssiBroadcast_hold_off_across_millis_wrap);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue