fix(network): migrate to mqtt-client 0.4.0 (IP-literal TLS fix) (#5895)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
James Rich
2026-06-22 09:06:37 -05:00
committed by GitHub
parent ca3fdba88a
commit ba9319c2df
4 changed files with 28 additions and 3 deletions

View File

@@ -43,7 +43,10 @@ import org.meshtastic.mqtt.ConnectionState
import org.meshtastic.mqtt.MqttClient
import org.meshtastic.mqtt.MqttException
import org.meshtastic.mqtt.ProbeResult
import org.meshtastic.mqtt.plus
import org.meshtastic.mqtt.probe
import org.meshtastic.mqtt.transport.tcp.TcpTransportFactory
import org.meshtastic.mqtt.transport.ws.WebSocketTransportFactory
import org.meshtastic.proto.MqttClientProxyMessage
import org.meshtastic.proto.ToRadio
import kotlin.uuid.Uuid
@@ -136,6 +139,8 @@ class MqttManagerImpl(
val endpoint = resolveEndpoint(address, tlsEnabled)
val result =
MqttClient.probe(endpoint = endpoint) {
// probe() requires a transportFactory in 0.4.0 (errors otherwise); mirror the live client.
transportFactory = TcpTransportFactory() + WebSocketTransportFactory()
// Per-connection random suffix: myId identifies the node (and is null →
// "unknown" before the node record loads), so two probes can collide on one
// client-id and evict each other (SESSION_TAKEN_OVER). See MQTTRepositoryImpl.

View File

@@ -35,7 +35,15 @@ kotlin {
implementation(projects.core.ble)
implementation(libs.okio)
api(libs.meshtastic.mqtt.client)
// mqtt-client 0.4.0 splits into BOM + core + transport modules. `api` (not `implementation`)
// because :core:data and :desktopApp consume org.meshtastic.mqtt.* types transitively through
// this module. Both transports are registered: transport-tcp (tcp://-/ssl://, default) +
// transport-ws (user-entered ws://-/wss://), composed with `+` at the client config sites.
// No platform() on the KMP commonMain handler; reach the BOM through project.dependencies.
api(project.dependencies.platform(libs.meshtastic.mqtt.client.bom))
api(libs.meshtastic.mqtt.client.core)
api(libs.meshtastic.mqtt.client.transport.tcp)
api(libs.meshtastic.mqtt.client.transport.ws)
implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.atomicfu)
implementation(libs.ktor.client.core)

View File

@@ -51,6 +51,9 @@ import org.meshtastic.mqtt.MqttLogLevel
import org.meshtastic.mqtt.MqttMessage
import org.meshtastic.mqtt.QoS
import org.meshtastic.mqtt.packet.Subscription
import org.meshtastic.mqtt.plus
import org.meshtastic.mqtt.transport.tcp.TcpTransportFactory
import org.meshtastic.mqtt.transport.ws.WebSocketTransportFactory
import org.meshtastic.proto.ModuleConfig
import org.meshtastic.proto.MqttClientProxyMessage
import kotlin.concurrent.Volatile
@@ -321,6 +324,9 @@ private class DefaultMqttClientSession(private val delegate: MqttClient) : MqttC
private fun defaultMqttClientFactory(setup: MqttClientSetup): MqttClientSession = DefaultMqttClientSession(
MqttClient(setup.ownerId) {
// mqtt-client 0.4.0 makes transport a required SPI: the client throws at connect if unset.
// Register TCP/TLS (the default) + WebSocket (for user-entered ws://-/wss:// brokers).
transportFactory = TcpTransportFactory() + WebSocketTransportFactory()
keepAliveSeconds = MQTT_KEEPALIVE_SECONDS
autoReconnect = true
username = setup.mqttConfig?.username

View File

@@ -95,7 +95,7 @@ osmdroid-android = "6.1.20"
spotless = "8.7.0"
vico = "3.2.3"
kable = "0.43.1"
mqttastic = "0.3.8"
mqttastic = "0.4.0"
jmdns = "3.6.3"
qrcode-kotlin = "4.5.0"
takpacket-sdk = "0.7.0"
@@ -264,7 +264,13 @@ markdown-renderer-android = { module = "com.mikepenz:multiplatform-markdown-rend
material = { module = "com.google.android.material:material", version = "1.14.0" }
kable-core = { module = "com.juul.kable:kable-core", version.ref = "kable" }
meshtastic-mqtt-client = { module = "org.meshtastic:mqtt-client", version.ref = "mqttastic" }
# mqtt-client 0.4.0 split the monolith into a BOM + core + per-transport modules. The BOM pins the
# versions, so core/transport stay versionless. Both transports are wired: transport-tcp (tcp://-/ssl://,
# the default) and transport-ws (for user-entered ws://-/wss:// broker addresses).
meshtastic-mqtt-client-bom = { module = "org.meshtastic:mqtt-client-bom", version.ref = "mqttastic" }
meshtastic-mqtt-client-core = { module = "org.meshtastic:mqtt-client-core" }
meshtastic-mqtt-client-transport-tcp = { module = "org.meshtastic:mqtt-client-transport-tcp" }
meshtastic-mqtt-client-transport-ws = { module = "org.meshtastic:mqtt-client-transport-ws" }
jserialcomm = { module = "com.fazecast:jSerialComm", version.ref = "jserialcomm" }
okio = { module = "com.squareup.okio:okio", version.ref = "okio" }