fix(observer-logins): bare host in the firmware server line

Dutch-MeshCore firmware before merge 32dd8ad (2026-10-19) does not
accept a scheme in mqtt1.server: it builds <proto>://<host>:<port> with
proto from the port alone, so mqtt://host became mqtt://mqtt://host:1883.
Reported by an observer operator on the live instance.

The mail now writes the bare host and adds a scheme only when the port
would pick the wrong one (for example TLS on 8884), which needs firmware
from 2026-10-19 or later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
efitenandClaude Opus 5.5 committed 2026-10-25 21:48:08 +01:00
1 parent 25ae52e52f
commit cb9f4ff392
3 files changed
+33 -11

No files matched your search

+13 -2
View File
@@ -75,8 +75,9 @@ func (a *authService) observerCredentialsMail(u *users.User, username, password
// firmwareServer is the mqtt1.server value for the Dutch-MeshCore firmware.
// For a bare host the firmware picks the scheme from the port alone (8883
// mqtts, 443 wss, anything else mqtt), so the scheme is always given. The
// firmware then appends mqtt1.port itself.
// mqtts, 443 wss, anything else mqtt) and appends mqtt1.port itself. Firmware
// before the merge 32dd8ad (2026-10-19) does not accept a scheme in the
// server, so the host stays bare unless the port would pick the wrong scheme.
func firmwareServer(o observerLoginSettings) string {
scheme := "mqtt"
if o.transport == "websockets" {
@@ -85,5 +86,15 @@ func firmwareServer(o observerLoginSettings) string {
if o.tls {
scheme += "s"
}
inferred := "mqtt"
switch o.port {
case 8883:
inferred = "mqtts"
case 443:
inferred = "wss"
}
if scheme == inferred {
return o.host
}
return scheme + "://" + o.host
}
+15 -6
View File
@@ -59,20 +59,29 @@ password = "p<w>"`
// The firmware infers the scheme of a bare host from the port alone (8883
// mqtts, 443 wss, else mqtt: MQTTBridge.cpp setupSlot), so the mail always
// names the scheme the configured transport and TLS need.
// Firmware before the Dutch-MeshCore merge 32dd8ad (2026-10-19) does not parse a
// scheme in mqtt1.server and builds "<proto>://<host>:<port>" with proto taken
// from the port alone (8883 mqtts, 443 wss, else mqtt). A bare host works on
// both; the scheme is only written when the port would infer the wrong one.
func TestFirmwareServerScheme(t *testing.T) {
for _, c := range []struct {
port int
transport string
tls bool
want string
}{
{"tcp", false, "mqtt://mqtt.example.org"},
{"tcp", true, "mqtts://mqtt.example.org"},
{"websockets", false, "ws://mqtt.example.org"},
{"websockets", true, "wss://mqtt.example.org"},
{1883, "tcp", false, "mqtt.example.org"},
{8883, "tcp", true, "mqtt.example.org"},
{443, "websockets", true, "mqtt.example.org"},
{8884, "tcp", false, "mqtt.example.org"},
{8884, "tcp", true, "mqtts://mqtt.example.org"},
{8884, "websockets", false, "ws://mqtt.example.org"},
{8884, "websockets", true, "wss://mqtt.example.org"},
{8883, "tcp", false, "mqtt://mqtt.example.org"},
} {
o := observerLoginSettings{host: "mqtt.example.org", port: 8884, transport: c.transport, tls: c.tls}
o := observerLoginSettings{host: "mqtt.example.org", port: c.port, transport: c.transport, tls: c.tls}
if got := firmwareServer(o); got != c.want {
t.Errorf("%s tls=%v: got %q, want %q", c.transport, c.tls, got, c.want)
t.Errorf("port %d %s tls=%v: got %q, want %q", c.port, c.transport, c.tls, got, c.want)
}
}
}
+5 -3
View File
@@ -68,9 +68,11 @@ reverse proxy for everything except the broker.
The credentials mail holds the login in four forms: a meshcoretomqtt `[[broker]]` block, the
Dutch-MeshCore observer firmware commands, a Home Assistant meshcore-ha block, and the plain values. For the firmware the server
line always carries a scheme (`set mqtt1.server mqtts://mqtt.example.org`), because a bare host
makes the firmware choose the scheme from the port alone (8883 TLS, 443 secure websockets,
anything else plain MQTT).
line is the bare host (`set mqtt1.server mqtt.example.org`): the firmware chooses the scheme
from the port alone (8883 TLS, 443 secure websockets, anything else plain MQTT), and firmware
before 2026-10-19 does not accept a scheme in the server. Only when the port would pick the
wrong scheme (for example TLS on 8884) does the mail write one (`mqtts://mqtt.example.org`),
which needs firmware from 2026-10-19 or later.
Websockets: meshcoretomqtt connects with websocket path `/`, EMQX listens on `/mqtt` by
default. Match the listener path to your uploaders, or use `tcp`.