Add new MQTT presets for Mesh Core CA and update compile-time defaults

- Introduced two new MQTT presets: `meshcore-ca-1` and `meshcore-ca-2`.
- Updated documentation to reflect compile-time configuration options for MQTT defaults, including slot presets, IATA, and timezone settings.
- Removed legacy default MQTT settings from the code, now relying on the new configuration approach.
This commit is contained in:
Adam Gessaman
2026-05-24 12:50:55 -07:00
parent 3f5ddcac4c
commit d669d4dbd4
6 changed files with 139 additions and 62 deletions
+32 -4
View File
@@ -109,6 +109,8 @@ The MQTT bridge uses a slot-based architecture with up to 6 concurrent connectio
| `meshat.se` | mqtts://mqtt.meshat.se:8883 | Username/password (fixed in firmware) | MQTT over TLS |
| `eastidahomesh` | wss://broker.eastidahomesh.net:443 | None | WSS |
| `coloradomesh` | wss://mqtt.meshcore.coloradomesh.org:1883 | JWT (Ed25519) | WSS |
| `meshcore-ca-1` | mqtt1.meshcore.ca:443 | JWT (Ed25519) | WSS |
| `meshcore-ca-2` | mqtt2.meshcore.ca:443 | JWT (Ed25519) | WSS |
| `custom` | User-configured | Username/Password | MQTT or WSS |
| `none` | (disabled) | — | — |
@@ -207,11 +209,37 @@ You can flash the merged firmware using either the web flasher or the command li
- `MQTT_WIFI_TX_POWER` - WiFi TX power level (default: `WIFI_POWER_11dBm`)
- ~~`MQTT_WIFI_POWER_SAVE_DEFAULT`~~ - Removed; all builds now default to `none` (no power save)
#### Compile-time fresh-install defaults (`src/helpers/MQTTDefaults.h`)
Optional PlatformIO `build_flags` override defaults written when `/mqtt_prefs` is first created. They do **not** change existing saved prefs on upgrade or reflash (unless `/mqtt_prefs` is erased).
| Macro | Default | Notes |
|-------|---------|-------|
| `MQTT_DEFAULT_SLOT1_PRESET` … `MQTT_DEFAULT_SLOT6_PRESET` | slots 12: `analyzer-us` / `analyzer-eu`; slots 36: `none` | Must be a built-in preset name, `none`, or `custom` |
| `MQTT_DEFAULT_IATA` | (empty) | e.g. `'"YYZ"'` |
| `MQTT_DEFAULT_TIMEZONE` | (empty) | e.g. `'"America/Toronto"'` |
| `MQTT_DEFAULT_TIMEZONE_OFFSET` | `0` | Fallback hours when TZ string is empty |
Example community build:
```ini
build_flags =
-D MQTT_DEFAULT_SLOT1_PRESET='"meshcore-ca-1"'
-D MQTT_DEFAULT_SLOT2_PRESET='"meshcore-ca-2"'
-D MQTT_DEFAULT_IATA='"YYZ"'
-D MQTT_DEFAULT_TIMEZONE='"America/Toronto"'
-D MQTT_DEFAULT_TIMEZONE_OFFSET=-5
```
WiFi SSID/password are not compile-time configurable (operators set them per device via CLI).
Legacy `get mqtt.analyzer_us` / `set mqtt.analyzer_us` still refer to the preset name `analyzer-us`, not “whatever slot 1 default is”.
## Default Configuration
The MQTT bridge comes with the following defaults for fresh installs:
The MQTT bridge comes with the following defaults for fresh installs (unless overridden by the macros above):
- **Origin**: Device name (set automatically from `set name`)
- **IATA**: (blank — must be configured for MeshCore-style topic presets such as Analyzer and TennMesh)
- **IATA**: (blank — must be configured for MeshCore-style topic presets such as Analyzer and TennMesh, unless `MQTT_DEFAULT_IATA` is set at build time)
- **Status Messages**: Enabled
- **Packet Messages**: Enabled
- **Raw Messages**: Disabled
@@ -224,8 +252,8 @@ The MQTT bridge comes with the following defaults for fresh installs:
- **WiFi SSID**: (blank — must be configured)
- **WiFi Password**: (blank — optional for open networks)
- **WiFi Power Save**: `none` (no power save)
- **Timezone**: (blank — uses UTC until configured)
- **Timezone Offset**: 0 (fallback, no offset)
- **Timezone**: (blank — uses UTC until configured, unless `MQTT_DEFAULT_TIMEZONE` is set at build time)
- **Timezone Offset**: 0 (fallback, no offset, unless `MQTT_DEFAULT_TIMEZONE_OFFSET` is set)
- **Repeat (forwarding)**: On (set `repeat off` for receive-only observers)
## CLI Commands
+2 -18
View File
@@ -979,29 +979,13 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
_prefs.gps_interval = 0;
_prefs.advert_loc_policy = ADVERT_LOC_PREFS;
// MQTT defaults (mqtt_origin empty => effective origin follows node_name at publish time)
// MQTT slot/IATA/timezone defaults come from /mqtt_prefs via loadPrefs (see MQTTDefaults.h)
_prefs.mqtt_origin[0] = '\0';
StrHelper::strncpy(_prefs.mqtt_iata, "SEA", sizeof(_prefs.mqtt_iata));
_prefs.mqtt_status_enabled = 1; // enabled
_prefs.mqtt_packets_enabled = 1; // enabled
_prefs.mqtt_raw_enabled = 0; // disabled
_prefs.mqtt_tx_enabled = 2; // advert: own adverts only (matches MQTTPrefs default)
_prefs.mqtt_rx_enabled = 1; // RX packets enabled by default
_prefs.mqtt_status_interval = 300000; // 5 minutes
// WiFi defaults
// WiFi defaults (user-configured via CLI; placeholders until set)
StrHelper::strncpy(_prefs.wifi_ssid, "ssid_here", sizeof(_prefs.wifi_ssid));
StrHelper::strncpy(_prefs.wifi_password, "password_here", sizeof(_prefs.wifi_password));
// Timezone defaults (Pacific Time with DST support)
StrHelper::strncpy(_prefs.timezone_string, "America/Los_Angeles", sizeof(_prefs.timezone_string));
_prefs.timezone_offset = -8; // fallback
// MQTT slot presets (analyzer-us and analyzer-eu enabled by default)
StrHelper::strncpy(_prefs.mqtt_slot_preset[0], "analyzer-us", sizeof(_prefs.mqtt_slot_preset[0]));
StrHelper::strncpy(_prefs.mqtt_slot_preset[1], "analyzer-eu", sizeof(_prefs.mqtt_slot_preset[1]));
StrHelper::strncpy(_prefs.mqtt_slot_preset[2], "none", sizeof(_prefs.mqtt_slot_preset[2]));
_prefs.adc_multiplier = 0.0f; // 0.0f means use default board multiplier
#if defined(USE_SX1262) || defined(USE_SX1268)
+3 -19
View File
@@ -692,28 +692,12 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
_prefs.bridge_baud = 115200; // baud rate
_prefs.bridge_channel = 1; // channel 1
// MQTT defaults (same as repeater; empty mqtt_origin follows node_name when publishing)
// MQTT slot/IATA/timezone defaults come from /mqtt_prefs via loadPrefs (see MQTTDefaults.h)
_prefs.mqtt_origin[0] = '\0';
StrHelper::strncpy(_prefs.mqtt_iata, "SEA", sizeof(_prefs.mqtt_iata));
_prefs.mqtt_status_enabled = 1; // enabled
_prefs.mqtt_packets_enabled = 1; // enabled
_prefs.mqtt_raw_enabled = 0; // disabled
_prefs.mqtt_tx_enabled = 2; // advert: own adverts only (matches MQTTPrefs default)
_prefs.mqtt_rx_enabled = 1; // RX packets enabled by default
_prefs.mqtt_status_interval = 300000; // 5 minutes
// WiFi defaults (same as repeater)
// WiFi defaults (user-configured via CLI; placeholders until set)
StrHelper::strncpy(_prefs.wifi_ssid, "ssid_here", sizeof(_prefs.wifi_ssid));
StrHelper::strncpy(_prefs.wifi_password, "password_here", sizeof(_prefs.wifi_password));
// Timezone defaults (same as repeater - Pacific Time with DST support)
StrHelper::strncpy(_prefs.timezone_string, "America/Los_Angeles", sizeof(_prefs.timezone_string));
_prefs.timezone_offset = -8; // fallback
// MQTT slot presets (analyzer-us and analyzer-eu enabled by default)
StrHelper::strncpy(_prefs.mqtt_slot_preset[0], "analyzer-us", sizeof(_prefs.mqtt_slot_preset[0]));
StrHelper::strncpy(_prefs.mqtt_slot_preset[1], "analyzer-eu", sizeof(_prefs.mqtt_slot_preset[1]));
StrHelper::strncpy(_prefs.mqtt_slot_preset[2], "none", sizeof(_prefs.mqtt_slot_preset[2]));
next_post_idx = 0;
next_client_idx = 0;
+2 -19
View File
@@ -17,6 +17,7 @@
#endif
#ifdef WITH_MQTT_BRIDGE
#include "bridges/MQTTBridge.h"
#include "MQTTDefaults.h"
// Helper function to calculate total size of MQTT fields for file format compatibility
// Uses NodePrefs struct to get accurate field sizes
@@ -449,25 +450,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
#ifdef WITH_MQTT_BRIDGE
// Set default values for MQTT preferences (used when file doesn't exist or is corrupted)
static void setMQTTPrefsDefaults(MQTTPrefs* prefs) {
memset(prefs, 0, sizeof(MQTTPrefs));
// Set sensible defaults matching MQTTBridge expectations
prefs->mqtt_status_enabled = 1; // enabled by default
prefs->mqtt_packets_enabled = 1; // enabled by default
prefs->mqtt_raw_enabled = 0; // disabled by default
prefs->mqtt_tx_enabled = 2; // advert: own adverts only, by default
prefs->mqtt_rx_enabled = 1; // RX packets enabled by default
prefs->mqtt_status_interval = 300000; // 5 minutes default
// Slot presets: analyzer-us and analyzer-eu enabled by default, rest = none
strncpy(prefs->mqtt_slot_preset[0], "analyzer-us", sizeof(prefs->mqtt_slot_preset[0]) - 1);
prefs->mqtt_slot_preset[0][sizeof(prefs->mqtt_slot_preset[0]) - 1] = '\0';
strncpy(prefs->mqtt_slot_preset[1], "analyzer-eu", sizeof(prefs->mqtt_slot_preset[1]) - 1);
prefs->mqtt_slot_preset[1][sizeof(prefs->mqtt_slot_preset[1]) - 1] = '\0';
for (int i = 2; i < MAX_MQTT_SLOTS; i++) {
strncpy(prefs->mqtt_slot_preset[i], "none", sizeof(prefs->mqtt_slot_preset[i]) - 1);
prefs->mqtt_slot_preset[i][sizeof(prefs->mqtt_slot_preset[i]) - 1] = '\0';
}
prefs->wifi_power_save = 1; // Default to none (0=min, 1=none, 2=max)
// String fields are already zero-initialized by memset
applyMQTTDefaults(prefs);
}
void CommonCLI::loadMQTTPrefs(FILESYSTEM* fs) {
+98
View File
@@ -0,0 +1,98 @@
#pragma once
#ifdef WITH_MQTT_BRIDGE
#include <string.h>
#include <MeshCore.h>
#include "CommonCLI.h"
#include "MQTTPresets.h"
// Compile-time defaults for fresh /mqtt_prefs (override via platformio build_flags).
// Example:
// -D MQTT_DEFAULT_SLOT1_PRESET='"meshcore-ca-1"'
// -D MQTT_DEFAULT_IATA='"YYZ"'
// -D MQTT_DEFAULT_TIMEZONE='"America/Toronto"'
// -D MQTT_DEFAULT_TIMEZONE_OFFSET=-5
#ifndef MQTT_DEFAULT_SLOT1_PRESET
#define MQTT_DEFAULT_SLOT1_PRESET "analyzer-us"
#endif
#ifndef MQTT_DEFAULT_SLOT2_PRESET
#define MQTT_DEFAULT_SLOT2_PRESET "analyzer-eu"
#endif
#ifndef MQTT_DEFAULT_SLOT3_PRESET
#define MQTT_DEFAULT_SLOT3_PRESET "none"
#endif
#ifndef MQTT_DEFAULT_SLOT4_PRESET
#define MQTT_DEFAULT_SLOT4_PRESET "none"
#endif
#ifndef MQTT_DEFAULT_SLOT5_PRESET
#define MQTT_DEFAULT_SLOT5_PRESET "none"
#endif
#ifndef MQTT_DEFAULT_SLOT6_PRESET
#define MQTT_DEFAULT_SLOT6_PRESET "none"
#endif
#ifndef MQTT_DEFAULT_IATA
#define MQTT_DEFAULT_IATA ""
#endif
#ifndef MQTT_DEFAULT_TIMEZONE
#define MQTT_DEFAULT_TIMEZONE ""
#endif
#ifndef MQTT_DEFAULT_TIMEZONE_OFFSET
#define MQTT_DEFAULT_TIMEZONE_OFFSET 0
#endif
static inline void mqttDefaultSlotPreset(char* dest, size_t dest_size, const char* preset) {
const char* resolved = MQTT_PRESET_NONE;
if (preset && preset[0] != '\0') {
if (strcmp(preset, MQTT_PRESET_NONE) == 0 ||
strcmp(preset, MQTT_PRESET_CUSTOM) == 0 ||
findMQTTPreset(preset) != nullptr) {
resolved = preset;
} else {
MESH_DEBUG_PRINTLN("MQTT: invalid default preset '%s', using none", preset);
}
}
strncpy(dest, resolved, dest_size - 1);
dest[dest_size - 1] = '\0';
}
static inline void applyMQTTDefaults(MQTTPrefs* prefs) {
memset(prefs, 0, sizeof(MQTTPrefs));
prefs->mqtt_status_enabled = 1;
prefs->mqtt_packets_enabled = 1;
prefs->mqtt_raw_enabled = 0;
prefs->mqtt_tx_enabled = 2;
prefs->mqtt_rx_enabled = 1;
prefs->mqtt_status_interval = 300000;
prefs->wifi_power_save = 1;
mqttDefaultSlotPreset(prefs->mqtt_slot_preset[0], sizeof(prefs->mqtt_slot_preset[0]),
MQTT_DEFAULT_SLOT1_PRESET);
mqttDefaultSlotPreset(prefs->mqtt_slot_preset[1], sizeof(prefs->mqtt_slot_preset[1]),
MQTT_DEFAULT_SLOT2_PRESET);
mqttDefaultSlotPreset(prefs->mqtt_slot_preset[2], sizeof(prefs->mqtt_slot_preset[2]),
MQTT_DEFAULT_SLOT3_PRESET);
mqttDefaultSlotPreset(prefs->mqtt_slot_preset[3], sizeof(prefs->mqtt_slot_preset[3]),
MQTT_DEFAULT_SLOT4_PRESET);
mqttDefaultSlotPreset(prefs->mqtt_slot_preset[4], sizeof(prefs->mqtt_slot_preset[4]),
MQTT_DEFAULT_SLOT5_PRESET);
mqttDefaultSlotPreset(prefs->mqtt_slot_preset[5], sizeof(prefs->mqtt_slot_preset[5]),
MQTT_DEFAULT_SLOT6_PRESET);
if (MQTT_DEFAULT_IATA[0] != '\0') {
strncpy(prefs->mqtt_iata, MQTT_DEFAULT_IATA, sizeof(prefs->mqtt_iata) - 1);
prefs->mqtt_iata[sizeof(prefs->mqtt_iata) - 1] = '\0';
}
if (MQTT_DEFAULT_TIMEZONE[0] != '\0') {
strncpy(prefs->timezone_string, MQTT_DEFAULT_TIMEZONE, sizeof(prefs->timezone_string) - 1);
prefs->timezone_string[sizeof(prefs->timezone_string) - 1] = '\0';
}
prefs->timezone_offset = MQTT_DEFAULT_TIMEZONE_OFFSET;
}
#endif // WITH_MQTT_BRIDGE
+2 -2
View File
@@ -119,8 +119,8 @@ static const MQTTPresetDef MQTT_PRESETS[MQTT_PRESET_COUNT] = {
{ "coloradomesh", "wss://mqtt.meshcore.coloradomesh.org:1883","mqtt.meshcore.coloradomesh.org", ISRG_ROOT_X1, MQTT_AUTH_JWT, MQTT_TOPIC_MESHCORE, 0, true, 55, nullptr, nullptr },
{ "dutchmeshcore-1", "wss://collector1.dutchmeshcore.nl:443/mqtt", "collector1.dutchmeshcore.nl", GTS_ROOT_R4, MQTT_AUTH_JWT, MQTT_TOPIC_MESHCORE, 0, true, 55, nullptr, nullptr },
{ "dutchmeshcore-2", "wss://collector2.dutchmeshcore.nl:443/mqtt", "collector2.dutchmeshcore.nl", GTS_ROOT_R4, MQTT_AUTH_JWT, MQTT_TOPIC_MESHCORE, 0, true, 55, nullptr, nullptr },
{ "meshcore-ca-1", "wss://mqtt1.meshcore.ca:443/mqtt", "mqtt1.meshcore.ca", ISRG_ROOT_X1, MQTT_AUTH_JWT, MQTT_TOPIC_MESHCORE, 0, true, 55, nullptr, nullptr },
{ "meshcore-ca-2", "wss://mqtt2.meshcore.ca:443/mqtt", "mqtt2.meshcore.ca", ISRG_ROOT_X1, MQTT_AUTH_JWT, MQTT_TOPIC_MESHCORE, 0, true, 55, nullptr, nullptr },
{ "meshcore-ca-1", "wss://mqtt1.meshcore.ca:443/mqtt", "mqtt1.meshcore.ca", ISRG_ROOT_X1, MQTT_AUTH_JWT, MQTT_TOPIC_MESHCORE, 0, true, 55, nullptr, nullptr },
{ "meshcore-ca-2", "wss://mqtt2.meshcore.ca:443/mqtt", "mqtt2.meshcore.ca", ISRG_ROOT_X1, MQTT_AUTH_JWT, MQTT_TOPIC_MESHCORE, 0, true, 55, nullptr, nullptr },
};
// Find a preset by name, returns nullptr if not found