* 'main' of https://github.com/xJARiD/MeshCore-EastMesh:
  docs: updated release notes for waev
  feat(mqtt): add Waev broker

# Conflicts:
#	release-notes.yml
This commit is contained in:
prabathbr committed 2026-06-26 12:21:21 +10:00
commit b2365c4ac0
8 files changed
+86 -13

No files matched your search

+1 -1
View File
@@ -80,7 +80,7 @@ bool MQTTPrefsStore::load(FILESYSTEM* fs, MQTTPrefs& prefs) {
prefs.custom_transport = 0;
}
prefs.status_interval_ms = kFixedStatusIntervalMs;
prefs.enabled_mask &= 0x1F;
prefs.enabled_mask &= 0x3F;
if (!prefs.brokers_migrated) {
// LetsMesh is retired. Clear any saved EU/US selections once so dead brokers
// stop retrying; the endpoints remain re-selectable afterwards.
+14 -9
View File
@@ -128,14 +128,16 @@ void logMqttMemorySnapshot(const char*, const char* = nullptr) {
}
const MQTTUplink::BrokerSpec MQTTUplink::kBrokerSpecs[kBrokerCount] = {
{"eastmesh-au", "eastmesh-au", "mqtt2.eastmesh.au", "wss://mqtt2.eastmesh.au:443/mqtt", kEastmeshBit, false},
{"meshmapper", "meshmapper", "mqtt.meshmapper.net", "wss://mqtt.meshmapper.net:443/mqtt", kMeshmapperBit, false},
{"eastmesh-au", "eastmesh-au", "mqtt2.eastmesh.au", "wss://mqtt2.eastmesh.au:443/mqtt", kEastmeshBit, false, 0},
{"meshmapper", "meshmapper", "mqtt.meshmapper.net", "wss://mqtt.meshmapper.net:443/mqtt", kMeshmapperBit, false, 0},
// waev enforces a shorter max token lifetime than the curated default; match its documented config.
{"waev", "waev", "mqtt.waev.app", "wss://mqtt.waev.app:443/mqtt", kWaevBit, false, 3600},
// Retired: LetsMesh is no longer maintained. Kept selectable for legacy nodes; new nodes should use meshmapper.
{"letsmesh-eu", "letsmesh-eu", "mqtt-eu-v1.letsmesh.net", "wss://mqtt-eu-v1.letsmesh.net:443/mqtt",
kLetsmeshEuBit, false},
kLetsmeshEuBit, false, 0},
{"letsmesh-us", "letsmesh-us", "mqtt-us-v1.letsmesh.net", "wss://mqtt-us-v1.letsmesh.net:443/mqtt",
kLetsmeshUsBit, false},
{"custom", "custom", nullptr, nullptr, kCustomBit, true},
kLetsmeshUsBit, false, 0},
{"custom", "custom", nullptr, nullptr, kCustomBit, true, 0},
};
MQTTUplink::MQTTUplink(mesh::RTCClock& rtc, mesh::LocalIdentity& identity)
@@ -202,7 +204,8 @@ const char* MQTTUplink::brokerCaCert(const BrokerSpec& spec) {
if (spec.bit == kEastmeshBit || spec.bit == kMeshmapperBit) {
return mqtt_ca_certs::kEastmeshIsrgRootX1Pem; // Let's Encrypt ISRG Root X1
}
return mqtt_ca_certs::kLetsmeshWe1Pem;
// waev (mqtt.waev.app) presents a Google Trust Services WE1 chain, same issuer as LetsMesh.
return mqtt_ca_certs::kLetsmeshWe1Pem; // Google Trust Services WE1
}
const char* MQTTUplink::brokerHost(const BrokerState& broker) const {
@@ -572,7 +575,8 @@ bool MQTTUplink::refreshToken(BrokerState& broker) {
}
}
time_t expires_at = now + kTokenLifetimeSecs;
time_t ttl = broker.spec->token_ttl_secs != 0 ? static_cast<time_t>(broker.spec->token_ttl_secs) : kTokenLifetimeSecs;
time_t expires_at = now + ttl;
const char* owner = _prefs.owner_public_key[0] ? _prefs.owner_public_key : nullptr;
const char* email = _prefs.owner_email[0] ? _prefs.owner_email : nullptr;
if (!JWTHelper::createAuthToken(*_identity, brokerHost(broker), now, expires_at, broker.token, kBrokerTokenSize,
@@ -583,8 +587,9 @@ bool MQTTUplink::refreshToken(BrokerState& broker) {
return false;
}
broker.token_expires_at = expires_at;
MQTT_LOG("%s token ready exp=%lu owner=%s email=%s", broker.spec->label,
static_cast<unsigned long>(expires_at), owner != nullptr ? "yes" : "no", email != nullptr ? "yes" : "no");
MQTT_LOG("%s token ready exp=%lu ttl=%ld owner=%s email=%s", broker.spec->label,
static_cast<unsigned long>(expires_at), static_cast<long>(ttl),
owner != nullptr ? "yes" : "no", email != nullptr ? "yes" : "no");
return true;
}
+6 -2
View File
@@ -89,6 +89,9 @@ private:
const char* uri;
uint8_t bit;
bool custom;
// Per-broker JWT lifetime in seconds; 0 = use the default kTokenLifetimeSecs. waev enforces a
// shorter max token lifetime than the curated default, so it gets its own (matches its config).
uint32_t token_ttl_secs;
};
struct BrokerState {
@@ -131,9 +134,10 @@ private:
static constexpr uint8_t kLetsmeshUsBit = 0x04;
static constexpr uint8_t kCustomBit = 0x08;
static constexpr uint8_t kMeshmapperBit = 0x10;
static constexpr uint8_t kBrokerMask = 0x1F;
static constexpr uint8_t kWaevBit = 0x20;
static constexpr uint8_t kBrokerMask = 0x3F;
static constexpr uint8_t kMaxEnabledBrokers = 2;
static constexpr size_t kBrokerCount = 5;
static constexpr size_t kBrokerCount = 6;
static const BrokerSpec kBrokerSpecs[kBrokerCount];
static bool isUnsetIataValue(const char* iata);
static const char* brokerCaCert(const BrokerSpec& spec);
+4 -1
View File
@@ -977,12 +977,13 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
</div>
<input id="mqttEastmeshAu" class="visually-hidden" type="checkbox" tabindex="-1" aria-hidden="true">
<input id="mqttMeshmapper" class="visually-hidden" type="checkbox" tabindex="-1" aria-hidden="true">
<input id="mqttWaev" class="visually-hidden" type="checkbox" tabindex="-1" aria-hidden="true">
<input id="mqttLetsmeshEu" class="visually-hidden" type="checkbox" tabindex="-1" aria-hidden="true">
<input id="mqttLetsmeshUs" class="visually-hidden" type="checkbox" tabindex="-1" aria-hidden="true">
<input id="mqttCustom" class="visually-hidden" type="checkbox" tabindex="-1" aria-hidden="true">
<div class="broker-group wide" id="mqttCustomConfig" style="display:none">
<div class="broker-group-title">Custom MQTT settings</div>
<div class="broker-grid">
<div class="broker-grid single">
<div class="broker-card">
<div class="field-card">
<label class="label" for="mqttCustomEndpoint">Host:Port</label>
@@ -2732,6 +2733,7 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
const MQTT_BROKERS = [
{ key:"eastmesh-au", input:"mqttEastmeshAu", label:"EastMesh AU", set:"set mqtt.eastmesh-au" },
{ key:"meshmapper", input:"mqttMeshmapper", label:"MeshMapper", set:"set mqtt.meshmapper" },
{ key:"waev", input:"mqttWaev", label:"Waev", set:"set mqtt.waev" },
{ key:"custom", input:"mqttCustom", label:"Custom", set:"set mqtt.custom", custom:true },
{ key:"letsmesh-eu", input:"mqttLetsmeshEu", label:"LetsMesh EU (retired)", set:"set mqtt.letsmesh-eu" },
{ key:"letsmesh-us", input:"mqttLetsmeshUs", label:"LetsMesh US (retired)", set:"set mqtt.letsmesh-us" }
@@ -3261,6 +3263,7 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
() => loadField("get mqtt.email", "mqttEmail", null, quiet),
() => loadBrokerState("get mqtt.eastmesh-au", "mqttEastmeshAu", quiet),
() => loadBrokerState("get mqtt.meshmapper", "mqttMeshmapper", quiet),
() => loadBrokerState("get mqtt.waev", "mqttWaev", quiet),
() => loadBrokerState("get mqtt.letsmesh-eu", "mqttLetsmeshEu", quiet),
() => loadBrokerState("get mqtt.letsmesh-us", "mqttLetsmeshUs", quiet),
() => loadBrokerState("get mqtt.custom", "mqttCustom", quiet),