Add station-only WiFi UDP bridge with eight authenticated peers
This commit is contained in:
1 parent
7bc3aeb234
commit
5e25faa3d0
45 files changed
+2699
-35
No files matched your search
@@ -2,17 +2,20 @@
|
||||
|
||||
// Included by the infrastructure main files after the mesh and transport objects.
|
||||
#include <helpers/WirelessControl.h>
|
||||
#if defined(ESP32) && (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || (defined(MESH_PRIMARY_ESPNOW) && MESH_PRIMARY_ESPNOW))
|
||||
#if defined(ESP32) && (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_UDP_BRIDGE) || (defined(MESH_PRIMARY_ESPNOW) && MESH_PRIMARY_ESPNOW))
|
||||
#include <WiFi.h>
|
||||
#include <helpers/esp32/WiFiRadioPolicy.h>
|
||||
#endif
|
||||
|
||||
class InfrastructureWirelessBackend : public mesh::wireless::Backend {
|
||||
bool wifi_saved_ = false, resume_web_ = false, resume_mqtt_ = false;
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
bool resume_udp_ = false;
|
||||
#endif
|
||||
public:
|
||||
uint8_t available() const override {
|
||||
uint8_t mask = 0;
|
||||
#if defined(ESP32) && (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE))
|
||||
#if defined(ESP32) && (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_UDP_BRIDGE))
|
||||
mask |= mesh::wireless::WiFi;
|
||||
#endif
|
||||
#if defined(WITH_ESPNOW_BRIDGE) || (defined(MESH_PRIMARY_ESPNOW) && MESH_PRIMARY_ESPNOW)
|
||||
@@ -31,6 +34,9 @@ public:
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (the_mesh.isMqttBridgeRunning()) mask |= mesh::wireless::WiFi;
|
||||
#endif
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if (the_mesh.isUDPBridgeNetworkEnabled()) mask |= mesh::wireless::WiFi;
|
||||
#endif
|
||||
#ifdef WITH_ESPNOW_BRIDGE
|
||||
if (the_mesh.isEspNowBridgeRunning()) mask |= mesh::wireless::EspNow;
|
||||
#endif
|
||||
@@ -56,7 +62,7 @@ public:
|
||||
}
|
||||
mesh::wireless::Result set(uint8_t service, bool on) override {
|
||||
using mesh::wireless::Result;
|
||||
#if defined(ESP32) && (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE))
|
||||
#if defined(ESP32) && (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_UDP_BRIDGE))
|
||||
if (service == mesh::wireless::WiFi) {
|
||||
if (!on) {
|
||||
if (board.isOTAUpdateRunning()) {
|
||||
@@ -69,9 +75,15 @@ public:
|
||||
#endif
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
resume_mqtt_ = the_mesh.isMqttBridgeRunning();
|
||||
#endif
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
resume_udp_ = the_mesh.isUDPBridgeConfigured();
|
||||
#endif
|
||||
wifi_saved_ = true;
|
||||
}
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if (!the_mesh.setUDPBridgeNetworkState(false)) return Result::Failed;
|
||||
#endif
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (!the_mesh.setMqttBridgeState(false)) return Result::Failed;
|
||||
#endif
|
||||
@@ -97,8 +109,13 @@ public:
|
||||
}
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (the_mesh.isWebConfigStopping()) return Result::Pending;
|
||||
if (resume_web_ || (!wifi_saved_ && !(enabled() & mesh::wireless::WiFi))
|
||||
|| (wifi_saved_ && !resume_web_ && !resume_mqtt_)) {
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
const bool udp_station_requested = resume_udp_ || (!wifi_saved_ && the_mesh.isUDPBridgeConfigured());
|
||||
#else
|
||||
const bool udp_station_requested = false;
|
||||
#endif
|
||||
if (resume_web_ || (!udp_station_requested && ((!wifi_saved_ && !(enabled() & mesh::wireless::WiFi))
|
||||
|| (wifi_saved_ && !resume_web_ && !resume_mqtt_)))) {
|
||||
char reply[160];
|
||||
if (!the_mesh.startWebConfig(false, reply)) return Result::Failed;
|
||||
}
|
||||
@@ -111,6 +128,11 @@ public:
|
||||
) {
|
||||
if (!the_mesh.setMqttBridgeState(true)) return Result::Failed;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if ((resume_udp_ || (!wifi_saved_ && the_mesh.isUDPBridgeConfigured()))
|
||||
&& !the_mesh.setUDPBridgeNetworkState(true)) return Result::Failed;
|
||||
resume_udp_ = false;
|
||||
#endif
|
||||
wifi_saved_ = resume_web_ = resume_mqtt_ = false;
|
||||
return (enabled() & mesh::wireless::WiFi) ? Result::Done : Result::Failed;
|
||||
|
||||
@@ -6,12 +6,16 @@
|
||||
#if defined(ESP32_PLATFORM)
|
||||
#include <helpers/esp32/BootFileSystem.h>
|
||||
#include <helpers/WiFiNetworkPowerPolicy.h>
|
||||
#if defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) \
|
||||
#if defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) || defined(WITH_UDP_BRIDGE) \
|
||||
|| defined(LIGHTWEIGHT_WIFI_OTA) || (defined(ADMIN_PASSWORD) && !defined(DISABLE_WIFI_OTA))
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WITH_UDP_BRIDGE)
|
||||
#include <helpers/esp32/WiFiCredentials.h>
|
||||
#include <helpers/esp32/WiFiStationPolicy.h>
|
||||
#endif
|
||||
#include <helpers/UsbLogging.h>
|
||||
#include <helpers/MorseLoopPolicy.h>
|
||||
#include <helpers/HilStartupTrace.h>
|
||||
@@ -763,7 +767,7 @@ uint8_t MyMesh::handleAnonClockReq(const mesh::Identity& sender, uint32_t sender
|
||||
if (isEspNowBridgeRunning()) reply_data[8] |= 0x03; // ESP-NOW may run alongside UART
|
||||
#endif
|
||||
#elif WITH_ESPNOW_BRIDGE
|
||||
if (isBridgeRunning()) reply_data[8] |= 0x03; // is bridge, type ESP-NOW
|
||||
if (isEspNowBridgeRunning()) reply_data[8] |= 0x03; // is bridge, type ESP-NOW
|
||||
#endif
|
||||
if (_prefs.disable_fwd) { // is this repeater currently disabled
|
||||
reply_data[8] |= 0x80; // is disabled
|
||||
@@ -1237,6 +1241,9 @@ void MyMesh::logRxRaw(float snr, float rssi, const uint8_t raw[], int len) {
|
||||
}
|
||||
|
||||
void MyMesh::logRx(mesh::Packet *pkt, int len, float score) {
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if (_prefs.bridge_pkt_src == 1 && isUDPBridgeRunning()) udp_bridge->sendPacket(pkt);
|
||||
#endif
|
||||
#ifdef DISPLAY_ACTIVITY_DASHBOARD
|
||||
// Count valid, parsed RF packets before role-level filtering. The dashboard
|
||||
// intentionally reflects radio activity, including packets this role later
|
||||
@@ -1292,6 +1299,9 @@ void MyMesh::logRx(mesh::Packet *pkt, int len, float score) {
|
||||
}
|
||||
|
||||
void MyMesh::logTx(mesh::Packet *pkt, int len) {
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if (_prefs.bridge_pkt_src == 0 && isUDPBridgeRunning()) udp_bridge->sendPacket(pkt);
|
||||
#endif
|
||||
#if defined(WITH_MQTT_NEIGHBORS)
|
||||
if (neighbor_discover_active && pkt == neighbor_discover_request
|
||||
&& neighbor_discover_next < neighbor_discover_count) {
|
||||
@@ -3885,6 +3895,9 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
||||
// load persisted prefs
|
||||
mesh::hilStartupTrace("mesh_prefs_begin");
|
||||
_cli.loadPrefs(_fs);
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
udp_bridge_settings.begin(_fs);
|
||||
#endif
|
||||
mesh::hilStartupTrace("mesh_prefs_ready");
|
||||
mesh::hilStartupTrace("mesh_management_begin");
|
||||
_cli.beginManagement(*this, _fs);
|
||||
@@ -4049,6 +4062,9 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
||||
#if defined(WITH_ESPNOW_BRIDGE) \
|
||||
&& (defined(WITH_MQTT_BRIDGE) || defined(WITH_RS232_BRIDGE))
|
||||
if (_prefs.espnow_bridge_enabled) setEspNowBridgeState(true);
|
||||
#endif
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
serviceUDPBridge();
|
||||
#endif
|
||||
mesh::hilStartupTrace("mesh_bridge_ready");
|
||||
|
||||
@@ -11531,6 +11547,11 @@ bool MyMesh::startWebConfigImpl(bool force_ap, char* reply, bool automatic_setup
|
||||
|| (!mqtt_bridge->isRunning() && !mqtt_bridge->isStopping()));
|
||||
#endif
|
||||
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
// The portal may switch to AP/setup mode synchronously. Close the station
|
||||
// socket before that transition; saved UDP intent resumes in a later STA loop.
|
||||
if (udp_bridge) udp_bridge->serviceNetwork(false);
|
||||
#endif
|
||||
bool started;
|
||||
if (force_ap) {
|
||||
started = _webconfig->startSetupMode(reply);
|
||||
@@ -13497,6 +13518,10 @@ void __attribute__((noinline)) MyMesh::servicePostMeshLoop() {
|
||||
expireRecentRepeatersIfDue();
|
||||
#endif
|
||||
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
// The UDP socket belongs to this loop and follows station/OTA ownership.
|
||||
serviceUDPBridge();
|
||||
#endif
|
||||
#if defined(WITH_MQTT_BRIDGE)
|
||||
// MQTT owns TLS on Core 0; the radio loop only reaps an acknowledged stop.
|
||||
if (mqtt_bridge && mqtt_bridge->isRunning()) mqtt_bridge->loop();
|
||||
@@ -13550,11 +13575,18 @@ void __attribute__((noinline)) MyMesh::servicePostMeshLoop() {
|
||||
// duty-limited channel) is lost when the flash spins the loop and reboots.
|
||||
drainOutbound(OTA_TX_DRAIN_TIMEOUT_MS);
|
||||
const bool mqtt_was_running = mqtt_bridge && mqtt_bridge->isRunning();
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
const bool udp_was_enabled = isUDPBridgeNetworkEnabled();
|
||||
setUDPBridgeNetworkState(false);
|
||||
#endif
|
||||
#ifdef WITH_ESPNOW_BRIDGE
|
||||
const bool espnow_was_running = espnow_bridge.isRunning();
|
||||
#endif
|
||||
auto resume_paused_bridges = [&]() {
|
||||
if (mqtt_was_running) setMqttBridgeState(true);
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if (udp_was_enabled) setUDPBridgeNetworkState(true);
|
||||
#endif
|
||||
#ifdef WITH_ESPNOW_BRIDGE
|
||||
if (espnow_was_running) setEspNowBridgeState(true);
|
||||
#endif
|
||||
@@ -14194,14 +14226,173 @@ bool MyMesh::startNeighborDiscover(char* reply) {
|
||||
}
|
||||
#endif // WITH_MQTT_NEIGHBORS
|
||||
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
bool MyMesh::ensureUDPBridge() {
|
||||
if (!udp_bridge) {
|
||||
udp_bridge = new (std::nothrow) UDPBridge(
|
||||
&_prefs, _mgr, getRTCClock(), &udp_bridge_settings.prefs());
|
||||
if (!udp_bridge) return false;
|
||||
configureBridgeFilter(udp_bridge);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MyMesh::isUDPBridgeNetworkEnabled() const {
|
||||
if (!udp_bridge_settings.healthy() || !udp_bridge_settings.prefs().enabled
|
||||
|| udp_network_paused || mesh::wireless::control().masterOff()
|
||||
|| mesh::wireless::control().pendingDisable(mesh::wireless::WiFi)
|
||||
|| mesh::wireless::control().blocked(mesh::wireless::WiFi)) return false;
|
||||
const size_t secret_length = strnlen(_prefs.bridge_secret, sizeof(_prefs.bridge_secret));
|
||||
if (secret_length == 0 || secret_length >= sizeof(_prefs.bridge_secret)) return false;
|
||||
for (const auto& peer : udp_bridge_settings.prefs().peers) {
|
||||
if (peer.enabled()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MyMesh::setUDPBridgeNetworkState(bool enabled) {
|
||||
udp_network_paused = !enabled;
|
||||
udp_station_retry_at = 0;
|
||||
if (!enabled) {
|
||||
if (udp_bridge) udp_bridge->serviceNetwork(false);
|
||||
mesh::wifi::networkPower().setHold(mesh::wifi::NetworkPowerHold::UdpBridge, false);
|
||||
} else {
|
||||
serviceUDPBridge();
|
||||
}
|
||||
return true; // Saved intent may wait for WiFi, credentials or OTA ownership.
|
||||
}
|
||||
|
||||
bool MyMesh::setUDPBridgePrefs(const mesh::bridge::udp::Prefs& value) {
|
||||
if (!mesh::bridge::udp::validPrefs(value)) return false;
|
||||
// Allocate before committing enabled intent. A failed allocation must not
|
||||
// report a working saved change or disturb the old socket and preferences.
|
||||
const bool had_transport = udp_bridge != nullptr;
|
||||
if (value.enabled && !ensureUDPBridge()) return false;
|
||||
if (!udp_bridge_settings.setPrefs(value)) {
|
||||
if (!udp_bridge_settings.healthy()) setUDPBridgeNetworkState(false);
|
||||
if (!had_transport) { delete udp_bridge; udp_bridge = nullptr; }
|
||||
return false;
|
||||
}
|
||||
if (udp_bridge) udp_bridge->end();
|
||||
if (!value.enabled) {
|
||||
delete udp_bridge;
|
||||
udp_bridge = nullptr;
|
||||
}
|
||||
udp_station_retry_at = 0;
|
||||
udp_network_paused = false;
|
||||
serviceUDPBridge();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MyMesh::formatUDPBridgeStatus(char* reply, size_t capacity) {
|
||||
if (!reply || !capacity) return;
|
||||
const auto& prefs = udp_bridge_settings.prefs();
|
||||
uint8_t peers = 0;
|
||||
for (const auto& peer : prefs.peers) if (peer.enabled()) ++peers;
|
||||
const size_t secret_length = strnlen(_prefs.bridge_secret, sizeof(_prefs.bridge_secret));
|
||||
const auto& control = mesh::wireless::control();
|
||||
const char* reason = !udp_bridge_settings.healthy() ? "prefs-error"
|
||||
: !prefs.enabled ? "off"
|
||||
: control.masterOff() || control.pendingDisable(mesh::wireless::WiFi)
|
||||
|| control.blocked(mesh::wireless::WiFi) ? "wifi-paused"
|
||||
: _cli.getBoard()->isOTAUpdateRunning() ? "ota-paused"
|
||||
: udp_network_paused ? "paused"
|
||||
: !secret_length || secret_length >= sizeof(_prefs.bridge_secret) ? "no-secret"
|
||||
: !peers ? "no-peers"
|
||||
: (WiFi.getMode() & WIFI_AP) ? "ap-mode"
|
||||
: WiFi.getMode() != WIFI_STA || WiFi.status() != WL_CONNECTED
|
||||
|| static_cast<uint32_t>(WiFi.localIP()) == 0 ? "disconnected"
|
||||
: !udp_bridge ? "no-memory" : nullptr;
|
||||
const auto ip = WiFi.localIP();
|
||||
const uint32_t address = static_cast<uint32_t>(ip);
|
||||
const auto* octets = reinterpret_cast<const uint8_t*>(&address);
|
||||
if (reason) {
|
||||
snprintf(reply, capacity, "> %s ip=%u.%u.%u.%u port=%u peers=%u", reason,
|
||||
octets[0], octets[1], octets[2], octets[3], unsigned(prefs.port), unsigned(peers));
|
||||
} else {
|
||||
udp_bridge->formatStatus(reply, capacity);
|
||||
}
|
||||
}
|
||||
|
||||
void MyMesh::formatUDPBridgeStats(const char* page, char* reply, size_t capacity) {
|
||||
if (udp_bridge) udp_bridge->formatStats(page, reply, capacity);
|
||||
else snprintf(reply, capacity, "> off; no UDP bridge counters allocated");
|
||||
}
|
||||
|
||||
bool MyMesh::sendUDPBridgeTest(uint8_t peer_index, uint32_t nonce) {
|
||||
serviceUDPBridge();
|
||||
return udp_bridge && udp_bridge->sendTest(peer_index, nonce);
|
||||
}
|
||||
|
||||
bool MyMesh::resetUDPBridgeStats() {
|
||||
if (udp_bridge) udp_bridge->resetStats();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MyMesh::serviceUDPBridge() {
|
||||
const bool requested = isUDPBridgeNetworkEnabled()
|
||||
&& !_cli.getBoard()->isOTAUpdateRunning();
|
||||
// MQTT's broker outage clock does not describe this independent LAN bridge.
|
||||
// Publish a separate hold before asking its worker to resume a parked STA.
|
||||
mesh::wifi::networkPower().setHold(mesh::wifi::NetworkPowerHold::UdpBridge, requested);
|
||||
if (!requested) {
|
||||
if (udp_bridge) udp_bridge->serviceNetwork(false);
|
||||
return;
|
||||
}
|
||||
if (!ensureUDPBridge()) return;
|
||||
wifi_mode_t sdk_mode = WIFI_MODE_NULL;
|
||||
const bool station_ready = WiFi.getMode() == WIFI_STA
|
||||
&& esp_wifi_get_mode(&sdk_mode) == ESP_OK && sdk_mode == WIFI_MODE_STA
|
||||
&& WiFi.status() == WL_CONNECTED && static_cast<uint32_t>(WiFi.localIP()) != 0;
|
||||
udp_bridge->serviceNetwork(station_ready, static_cast<uint32_t>(WiFi.localIP()),
|
||||
static_cast<uint32_t>(WiFi.subnetMask()));
|
||||
if (station_ready) {
|
||||
udp_bridge->loop();
|
||||
return;
|
||||
}
|
||||
// An AP, setup portal, OTA uploader or MQTT worker owns its WiFi lifecycle.
|
||||
// UDP may share its connected station, but never reconnects underneath it.
|
||||
if (!mesh::wifi::stationMutationAllowed()) return;
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (isWebConfigActive() || isWebConfigStopping()) return;
|
||||
#endif
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (mqtt_bridge && (mqtt_bridge->isRunning() || mqtt_bridge->isStopping())) return;
|
||||
#endif
|
||||
if (!millisHasNowPassed(udp_station_retry_at)) return;
|
||||
udp_station_retry_at = millis() + 15000U;
|
||||
mesh::wifi::Credentials credentials;
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
const auto* legacy = _cli.getObserverPrefs();
|
||||
const auto state = mesh::wifi::resolveCredentials(credentials,
|
||||
legacy ? legacy->wifi_ssid : nullptr, legacy ? legacy->wifi_password : nullptr,
|
||||
legacy ? legacy->wifi_power_save : mesh::wifi::kDefaultPowerSave);
|
||||
#else
|
||||
const auto state = mesh::wifi::resolveCredentials(credentials);
|
||||
#endif
|
||||
if (state != mesh::wifi::CredentialState::Ready) return;
|
||||
WiFi.persistent(false);
|
||||
if (!WiFi.mode(WIFI_STA) || mesh::wifi::applyProtocolMask(WIFI_IF_STA) != ESP_OK) return;
|
||||
mesh::wifi::setStationAutoReconnect(true);
|
||||
mesh::wifi::beginStation(credentials.ssid, credentials.password);
|
||||
const uint8_t power_save = mesh::wifi::effectivePowerSave(credentials.power_save, false,
|
||||
mesh::wifi::espNowChannelConstrained());
|
||||
esp_wifi_set_ps(power_save == mesh::wifi::kPowerSaveNone ? WIFI_PS_NONE
|
||||
: power_save == mesh::wifi::kPowerSaveMax ? WIFI_PS_MAX_MODEM : WIFI_PS_MIN_MODEM);
|
||||
}
|
||||
#endif
|
||||
|
||||
// To check if there is pending work
|
||||
#if defined(ESP32_PLATFORM)
|
||||
void MyMesh::serviceIdleWiFi() {
|
||||
#if (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) \
|
||||
#if (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) || defined(WITH_UDP_BRIDGE) \
|
||||
|| defined(LIGHTWEIGHT_WIFI_OTA) || (defined(ADMIN_PASSWORD) && !defined(DISABLE_WIFI_OTA))) \
|
||||
&& (!defined(MESH_PRIMARY_ESPNOW) || !MESH_PRIMARY_ESPNOW) \
|
||||
&& (!defined(MESH_ESPNOW_RADIO) || !MESH_ESPNOW_RADIO)
|
||||
if (_cli.getBoard()->isOTAUpdateRunning()) return;
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if (isUDPBridgeNetworkEnabled()) return;
|
||||
#endif
|
||||
if (mesh::wifi::networkPower().foregroundActive()) return;
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (isWebConfigActive() && (!mesh::wifi::networkPower().backgroundSuspended()
|
||||
@@ -14247,6 +14438,9 @@ mesh::powerdiag::Mask MyMesh::pendingWorkReason() const {
|
||||
// probe additional hardware or change which work keeps the MCU awake.
|
||||
if (!canIdleDualRadio()) return mask(Reason::DualRadio);
|
||||
if (hasPendingOtaApply()) return mask(Reason::Ota);
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if (isUDPBridgeRunning()) return mask(Reason::Bridge);
|
||||
#endif
|
||||
#if defined(ESP32_PLATFORM)
|
||||
if (mesh::wifi::networkPower().foregroundActive()) return mask(Reason::Network);
|
||||
#endif
|
||||
@@ -14255,7 +14449,7 @@ mesh::powerdiag::Mask MyMesh::pendingWorkReason() const {
|
||||
|| _webconfig->isNetworkForegroundActive(millis()))) return mask(Reason::Network);
|
||||
#endif
|
||||
#if defined(ESP32_PLATFORM) \
|
||||
&& (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) \
|
||||
&& (defined(WITH_WEBCONFIG) || defined(WITH_MQTT_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) || defined(WITH_UDP_BRIDGE) \
|
||||
|| defined(LIGHTWEIGHT_WIFI_OTA) || (defined(ADMIN_PASSWORD) && !defined(DISABLE_WIFI_OTA))) \
|
||||
&& (!defined(MESH_PRIMARY_ESPNOW) || !MESH_PRIMARY_ESPNOW) \
|
||||
&& (!defined(MESH_ESPNOW_RADIO) || !MESH_ESPNOW_RADIO)
|
||||
|
||||
@@ -75,6 +75,11 @@
|
||||
#define WITH_BRIDGE
|
||||
#endif
|
||||
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
#include "helpers/bridges/UDPBridge.h"
|
||||
#include "helpers/UDPBridgeSettings.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
#include "helpers/bridges/MQTTBridge.h"
|
||||
#define WITH_BRIDGE
|
||||
@@ -629,6 +634,22 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks
|
||||
ESPNowBridge bridge;
|
||||
uint32_t shared_espnow_retry_at = 0;
|
||||
#endif
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
mesh::bridge::udp::Settings udp_bridge_settings;
|
||||
UDPBridge* udp_bridge = nullptr;
|
||||
uint32_t udp_station_retry_at = 0;
|
||||
bool udp_network_paused = false;
|
||||
void serviceUDPBridge();
|
||||
bool ensureUDPBridge();
|
||||
const mesh::bridge::udp::Prefs* getUDPBridgePrefs() const override {
|
||||
return &udp_bridge_settings.prefs();
|
||||
}
|
||||
bool setUDPBridgePrefs(const mesh::bridge::udp::Prefs& value) override;
|
||||
void formatUDPBridgeStatus(char* reply, size_t capacity) override;
|
||||
void formatUDPBridgeStats(const char* page, char* reply, size_t capacity) override;
|
||||
bool sendUDPBridgeTest(uint8_t peer_index, uint32_t nonce) override;
|
||||
bool resetUDPBridgeStats() override;
|
||||
#endif
|
||||
#ifdef WITH_BRIDGE
|
||||
AbstractBridge* activeBridge() {
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
@@ -651,6 +672,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks
|
||||
#endif
|
||||
|
||||
#if defined(WITH_ESPNOW_BRIDGE)
|
||||
#if !defined(WITH_MQTT_BRIDGE) && !defined(WITH_RS232_BRIDGE)
|
||||
bool isEspNowBridgeRunning() override { return bridge.isRunning(); }
|
||||
#endif
|
||||
ESPNowBridge& diagnosticEspNowBridge() {
|
||||
#if defined(WITH_MQTT_BRIDGE) || defined(WITH_RS232_BRIDGE)
|
||||
return espnow_bridge;
|
||||
@@ -1099,8 +1123,19 @@ protected:
|
||||
bool sendClientReply(ClientInfo* client, mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size);
|
||||
|
||||
public:
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
bool setUDPBridgeNetworkState(bool enabled) override;
|
||||
bool isUDPBridgeNetworkEnabled() const override;
|
||||
bool isUDPBridgeConfigured() const { return udp_bridge_settings.prefs().enabled != 0; }
|
||||
bool isUDPBridgeRunning() const { return udp_bridge && udp_bridge->isRunning(); }
|
||||
#endif
|
||||
MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables);
|
||||
~MyMesh() { delete[] flood_packet_filters; }
|
||||
~MyMesh() {
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
delete udp_bridge;
|
||||
#endif
|
||||
delete[] flood_packet_filters;
|
||||
}
|
||||
MyMesh(const MyMesh&) = delete;
|
||||
MyMesh& operator=(const MyMesh&) = delete;
|
||||
|
||||
@@ -1489,6 +1524,9 @@ public:
|
||||
#endif
|
||||
|
||||
bool isBridgeRunning() const override {
|
||||
#ifdef WITH_UDP_BRIDGE
|
||||
if (isUDPBridgeRunning()) return true;
|
||||
#endif
|
||||
#if defined(WITH_MQTT_BRIDGE)
|
||||
return (mqtt_bridge && mqtt_bridge->isRunning())
|
||||
#ifdef WITH_ESPNOW_BRIDGE
|
||||
|
||||
Reference in new issue
Block a user