#1614 - WiFi Tx Power

This commit is contained in:
proddy
2024-02-11 10:32:33 +01:00
parent 12f0120afd
commit fea63b0d52
15 changed files with 377 additions and 275 deletions

View File

@@ -1,5 +1,7 @@
#include <NetworkSettingsService.h>
#include "../../src/emsesp_stub.hpp"
using namespace std::placeholders; // for `_1` etc
NetworkSettingsService::NetworkSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
@@ -7,7 +9,8 @@ NetworkSettingsService::NetworkSettingsService(AsyncWebServer * server, FS * fs,
, _fsPersistence(NetworkSettings::read, NetworkSettings::update, this, fs, NETWORK_SETTINGS_FILE)
, _lastConnectionAttempt(0) {
addUpdateHandler([&](const String & originId) { reconfigureWiFiConnection(); }, false);
WiFi.onEvent(std::bind(&NetworkSettingsService::WiFiEvent, this, _1));
// wifi event callbacks
WiFi.onEvent(std::bind(&NetworkSettingsService::WiFiEvent, this, _1, _2));
}
void NetworkSettingsService::begin() {
@@ -83,31 +86,282 @@ void NetworkSettingsService::manageSTA() {
} else {
WiFi.begin(_state.ssid.c_str(), _state.password.c_str());
}
// set power after wifi is startet, fixed value for C3_V1
// if (WiFi.isConnected()) {
#ifdef BOARD_C3_MINI_V1
// v1 needs this value, see https://github.com/emsesp/EMS-ESP32/pull/620#discussion_r993173979
WiFi.setTxPower(WIFI_POWER_8_5dBm); // https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi
#else
// esp_wifi_set_max_tx_power(_state.tx_power * 4);
// TODO make it dynamic
WiFi.setTxPower((wifi_power_t)(_state.tx_power * 4));
#endif
// }
// Set thw Wifi Tx power
setWiFiPower();
} else { // not connected but STA-mode active => disconnect
reconfigureWiFiConnection();
}
}
// handles if wifi stopped
void NetworkSettingsService::WiFiEvent(WiFiEvent_t event) {
if (event == ARDUINO_EVENT_WIFI_STA_STOP) {
// set the Tx WiFi power
// based of RSSI (signal strength) and copied from Tasmota's WiFiSetTXpowerBasedOnRssi() function with is copied from espEasy
void NetworkSettingsService::setWiFiPower() {
// hardcode Tx power for Wemos CS Mini v1
// v1 needs this value, see https://github.com/emsesp/EMS-ESP32/pull/620#discussion_r993173979
// https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi
#ifdef BOARD_C3_MINI_V1
WiFi.setTxPower(WIFI_POWER_8_5dBm);
return;
#endif
auto set_power = _state.tx_power; // get user settings. 0 means auto
// If Auto set the TxPower based on the RSSI (signal strength)
if (set_power == 0) {
// Range ESP32 : 2dBm - 20dBm
// 802.11b - wifi1
// 802.11a - wifi2
// 802.11g - wifi3
// 802.11n - wifi4
// 802.11ac - wifi5
// 802.11ax - wifi6
int max_tx_pwr = MAX_TX_PWR_DBM_n; // assume wifi4
int threshold = WIFI_SENSITIVITY_n;
threshold += 30; // Margin in dBm * 10 on top of threshold
// Assume AP sends with max set by ETSI standard.
// 2.4 GHz: 100 mWatt (20 dBm)
// US and some other countries allow 1000 mW (30 dBm)
int rssi = WiFi.RSSI() * 10;
int newrssi = rssi - 200; // We cannot send with over 20 dBm, thus it makes no sense to force higher TX power all the time.
int min_tx_pwr = 0;
if (newrssi < threshold) {
min_tx_pwr = threshold - newrssi;
}
if (min_tx_pwr > max_tx_pwr) {
min_tx_pwr = max_tx_pwr;
}
set_power = min_tx_pwr / 10; // this is the recommended power setting to use
}
// use the user setting, which is a value from WiFIGeneric.h
// WIFI_POWER_19_5dBm = 78,// 19.5dBm
// WIFI_POWER_19dBm = 76,// 19dBm
// WIFI_POWER_18_5dBm = 74,// 18.5dBm
// WIFI_POWER_17dBm = 68,// 17dBm
// WIFI_POWER_15dBm = 60,// 15dBm
// WIFI_POWER_13dBm = 52,// 13dBm
// WIFI_POWER_11dBm = 44,// 11dBm
// WIFI_POWER_8_5dBm = 34,// 8.5dBm
// WIFI_POWER_7dBm = 28,// 7dBm
// WIFI_POWER_5dBm = 20,// 5dBm
// WIFI_POWER_2dBm = 8,// 2dBm
// WIFI_POWER_MINUS_1dBm = -4// -1dBm
wifi_power_t p = WIFI_POWER_2dBm;
if (set_power > 19)
p = WIFI_POWER_19_5dBm;
else if (set_power > 18)
p = WIFI_POWER_18_5dBm;
else if (set_power >= 17)
p = WIFI_POWER_17dBm;
else if (set_power >= 15)
p = WIFI_POWER_15dBm;
else if (set_power >= 13)
p = WIFI_POWER_13dBm;
else if (set_power >= 11)
p = WIFI_POWER_11dBm;
else if (set_power >= 8)
p = WIFI_POWER_8_5dBm;
else if (set_power >= 7)
p = WIFI_POWER_7dBm;
else if (set_power >= 5)
p = WIFI_POWER_5dBm;
WiFi.setTxPower(p);
}
// start the multicast UDP service so EMS-ESP is discoverable via .local
void NetworkSettingsService::mDNS_start() const {
#ifndef EMSESP_STANDALONE
MDNS.end();
if (_state.enableMDNS) {
if (!MDNS.begin(emsesp::EMSESP::system_.hostname().c_str())) {
emsesp::EMSESP::logger().warning("Failed to start mDNS responder service");
return;
}
std::string address_s = emsesp::EMSESP::system_.hostname() + ".local";
MDNS.addService("http", "tcp", 80); // add our web server and rest API
MDNS.addService("telnet", "tcp", 23); // add our telnet console
MDNS.addServiceTxt("http", "tcp", "version", EMSESP_APP_VERSION);
MDNS.addServiceTxt("http", "tcp", "address", address_s.c_str());
emsesp::EMSESP::logger().info("mDNS responder service started");
}
#else
if (_state.enableMDNS) {
EMSESP::logger().info("mDNS responder service started");
}
#endif
}
const char * NetworkSettingsService::disconnectReason(uint8_t code) {
#ifndef EMSESP_STANDALONE
switch (code) {
case WIFI_REASON_UNSPECIFIED: // = 1,
return "unspecified";
case WIFI_REASON_AUTH_EXPIRE: // = 2,
return "auth expire";
case WIFI_REASON_AUTH_LEAVE: // = 3,
return "auth leave";
case WIFI_REASON_ASSOC_EXPIRE: // = 4,
return "assoc expired";
case WIFI_REASON_ASSOC_TOOMANY: // = 5,
return "assoc too many";
case WIFI_REASON_NOT_AUTHED: // = 6,
return "not authenticated";
case WIFI_REASON_NOT_ASSOCED: // = 7,
return "not assoc";
case WIFI_REASON_ASSOC_LEAVE: // = 8,
return "assoc leave";
case WIFI_REASON_ASSOC_NOT_AUTHED: // = 9,
return "assoc not authed";
case WIFI_REASON_DISASSOC_PWRCAP_BAD: // = 10,
return "disassoc powerCAP bad";
case WIFI_REASON_DISASSOC_SUPCHAN_BAD: // = 11,
return "disassoc supchan bad";
case WIFI_REASON_IE_INVALID: // = 13,
return "IE invalid";
case WIFI_REASON_MIC_FAILURE: // = 14,
return "MIC failure";
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: // = 15,
return "4way handshake timeout";
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: // = 16,
return "group key-update timeout";
case WIFI_REASON_IE_IN_4WAY_DIFFERS: // = 17,
return "IE in 4way differs";
case WIFI_REASON_GROUP_CIPHER_INVALID: // = 18,
return "group cipher invalid";
case WIFI_REASON_PAIRWISE_CIPHER_INVALID: // = 19,
return "pairwise cipher invalid";
case WIFI_REASON_AKMP_INVALID: // = 20,
return "AKMP invalid";
case WIFI_REASON_UNSUPP_RSN_IE_VERSION: // = 21,
return "unsupported RSN_IE version";
case WIFI_REASON_INVALID_RSN_IE_CAP: // = 22,
return "invalid RSN_IE_CAP";
case WIFI_REASON_802_1X_AUTH_FAILED: // = 23,
return "802 X1 auth failed";
case WIFI_REASON_CIPHER_SUITE_REJECTED: // = 24,
return "cipher suite rejected";
case WIFI_REASON_BEACON_TIMEOUT: // = 200,
return "beacon timeout";
case WIFI_REASON_NO_AP_FOUND: // = 201,
return "no AP found";
case WIFI_REASON_AUTH_FAIL: // = 202,
return "auth fail";
case WIFI_REASON_ASSOC_FAIL: // = 203,
return "assoc fail";
case WIFI_REASON_HANDSHAKE_TIMEOUT: // = 204,
return "handshake timeout";
case WIFI_REASON_CONNECTION_FAIL: // 205,
return "connection fail";
case WIFI_REASON_AP_TSF_RESET: // 206,
return "AP tsf reset";
case WIFI_REASON_ROAMING: // 207,
return "roaming";
case WIFI_REASON_ASSOC_COMEBACK_TIME_TOO_LONG: // 208,
return "assoc comeback time too long";
case WIFI_REASON_SA_QUERY_TIMEOUT: // 209,
return "sa query timeout";
default:
return "unknown";
}
#endif
return "";
}
// handles both WiFI and Ethernet
void NetworkSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
#ifndef EMSESP_STANDALONE
switch (event) {
case ARDUINO_EVENT_WIFI_STA_STOP:
if (_stopping) {
_lastConnectionAttempt = 0;
_stopping = false;
}
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
emsesp::EMSESP::logger().warning("WiFi disconnected. Reason: %s (%d)",
disconnectReason(info.wifi_sta_disconnected.reason),
info.wifi_sta_disconnected.reason); // IDF 4.0
emsesp::EMSESP::system_.has_ipv6(false);
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
char result[10];
emsesp::EMSESP::logger().info("WiFi connected with IP=%s, hostname=%s, TxPower=%s",
WiFi.localIP().toString().c_str(),
WiFi.getHostname(),
emsesp::Helpers::render_value(result, (double)(WiFi.getTxPower() / 4), 1));
mDNS_start();
break;
case ARDUINO_EVENT_ETH_START:
ETH.setHostname(emsesp::EMSESP::system_.hostname().c_str());
// configure for static IP
if (_state.staticIPConfig) {
ETH.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2);
}
break;
case ARDUINO_EVENT_ETH_GOT_IP:
// prevent double calls
if (!emsesp::EMSESP::system_.ethernet_connected()) {
emsesp::EMSESP::logger().info("Ethernet connected with IP=%s, speed %d Mbps", ETH.localIP().toString().c_str(), ETH.linkSpeed());
emsesp::EMSESP::system_.ethernet_connected(true);
mDNS_start();
}
break;
case ARDUINO_EVENT_ETH_DISCONNECTED:
emsesp::EMSESP::logger().warning("Ethernet disconnected");
emsesp::EMSESP::system_.ethernet_connected(false);
emsesp::EMSESP::system_.has_ipv6(false);
break;
case ARDUINO_EVENT_ETH_STOP:
emsesp::EMSESP::logger().info("Ethernet stopped");
emsesp::EMSESP::system_.ethernet_connected(false);
emsesp::EMSESP::system_.has_ipv6(false);
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
if (_state.enableIPv6) {
WiFi.enableIpV6();
}
break;
case ARDUINO_EVENT_ETH_CONNECTED:
if (_state.enableIPv6) {
ETH.enableIpV6();
}
break;
// IPv6 specific
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
case ARDUINO_EVENT_ETH_GOT_IP6:
if (emsesp::EMSESP::system_.ethernet_connected()) {
emsesp::EMSESP::logger().info("Ethernet connected with IPv6=%s, speed %d Mbps", ETH.localIPv6().toString().c_str(), ETH.linkSpeed());
} else {
emsesp::EMSESP::logger().info("WiFi connected with IPv6=%s, hostname=%s", WiFi.localIPv6().toString().c_str(), WiFi.getHostname());
}
mDNS_start();
emsesp::EMSESP::system_.has_ipv6(true);
break;
default:
break;
}
// if (!_stopping && (event == ARDUINO_EVENT_WIFI_STA_LOST_IP || event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED)) {
// reconfigureWiFiConnection();
// }
#endif
}