You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(client): add MqttClient.probe() endpoint diagnostics API
Introduces a one-shot connectivity probe so consumer "Test Connection"
affordances can classify endpoint failures without spinning up a full
client lifecycle.
API surface (commonMain):
- `MqttClient.Companion.probe(endpoint, timeoutMs, configure)` — suspend
extension that performs a CONNECT/CONNACK against a transient
`MqttConnection`, then tears it down. Never throws for connectivity
errors; cancellation is propagated.
- `ProbeResult` sealed class — Success / Rejected / DnsFailure /
TcpFailure / TlsFailure / Timeout / Other.
- `ProbeServerInfo` — curated public projection of broker CONNACK
properties (assignedClientIdentifier, serverKeepAliveSeconds,
maximumQosOrdinal, retainAvailable, …) so we don't leak the internal
MqttProperties shape.
- `DEFAULT_PROBE_TIMEOUT_MS = 5_000`.
Implementation notes:
- Probe forces `autoReconnect = false` and defaults `clientId = ""` /
`cleanStart = true` / `keepAliveSeconds = 0`.
- Cleanup runs under `NonCancellable` so disconnect/transport.close
fire even if the caller is cancelling.
- Failure classifier matches on cause-chain class simpleName + message
substrings (KMP-safe; no java.* / android.* references) and treats
the internal `MqttConnectionException` (no cause) as a `Rejected`
outcome carrying the broker's reason code and serverReference.
- `MqttClient` companion promoted from `private` to `public` so the
extension function can attach to it; companion constants stay private.
Tests: 10 new cases in `ProbeApiTest` driving every ProbeResult arm via
`FakeTransport` — including timeout, external cancellation, and the
USE_ANOTHER_SERVER redirect path.
Baseline: spotlessCheck detekt allTests apiCheck koverVerify all green;
library.api regenerated with the new public surface.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: library/api/jvm/library.api
+130Lines changed: 130 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -59,6 +59,7 @@ public final class org/meshtastic/mqtt/ConnectionState$Reconnecting : org/meshta
59
59
}
60
60
61
61
public final class org/meshtastic/mqtt/MqttClient {
62
+
public static final field Companion Lorg/meshtastic/mqtt/MqttClient$Companion;
62
63
public fun <init> (Lorg/meshtastic/mqtt/MqttConfig;Lkotlinx/coroutines/CoroutineScope;)V
63
64
public synthetic fun <init> (Lorg/meshtastic/mqtt/MqttConfig;Lkotlinx/coroutines/CoroutineScope;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
64
65
public final fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -78,6 +79,9 @@ public final class org/meshtastic/mqtt/MqttClient {
78
79
public final fun unsubscribe ([Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
79
80
}
80
81
82
+
public final class org/meshtastic/mqtt/MqttClient$Companion {
83
+
}
84
+
81
85
public final class org/meshtastic/mqtt/MqttClientKt {
82
86
public static final fun MqttClient (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function1;)Lorg/meshtastic/mqtt/MqttClient;
83
87
public static synthetic fun MqttClient$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/meshtastic/mqtt/MqttClient;
@@ -314,6 +318,132 @@ public final class org/meshtastic/mqtt/MqttMessage {
314
318
public fun toString ()Ljava/lang/String;
315
319
}
316
320
321
+
public final class org/meshtastic/mqtt/ProbeKt {
322
+
public static final field DEFAULT_PROBE_TIMEOUT_MS J
323
+
public static final fun probe (Lorg/meshtastic/mqtt/MqttClient$Companion;Lorg/meshtastic/mqtt/MqttEndpoint;JLkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
324
+
public static synthetic fun probe$default (Lorg/meshtastic/mqtt/MqttClient$Companion;Lorg/meshtastic/mqtt/MqttEndpoint;JLkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
325
+
}
326
+
327
+
public abstract class org/meshtastic/mqtt/ProbeResult {
328
+
}
329
+
330
+
public final class org/meshtastic/mqtt/ProbeResult$DnsFailure : org/meshtastic/mqtt/ProbeResult {
331
+
public fun <init> (Ljava/lang/Throwable;)V
332
+
public final fun component1 ()Ljava/lang/Throwable;
333
+
public final fun copy (Ljava/lang/Throwable;)Lorg/meshtastic/mqtt/ProbeResult$DnsFailure;
334
+
public static synthetic fun copy$default (Lorg/meshtastic/mqtt/ProbeResult$DnsFailure;Ljava/lang/Throwable;ILjava/lang/Object;)Lorg/meshtastic/mqtt/ProbeResult$DnsFailure;
335
+
public fun equals (Ljava/lang/Object;)Z
336
+
public final fun getCause ()Ljava/lang/Throwable;
337
+
public fun hashCode ()I
338
+
public fun toString ()Ljava/lang/String;
339
+
}
340
+
341
+
public final class org/meshtastic/mqtt/ProbeResult$Other : org/meshtastic/mqtt/ProbeResult {
342
+
public fun <init> (Ljava/lang/Throwable;)V
343
+
public final fun component1 ()Ljava/lang/Throwable;
344
+
public final fun copy (Ljava/lang/Throwable;)Lorg/meshtastic/mqtt/ProbeResult$Other;
345
+
public static synthetic fun copy$default (Lorg/meshtastic/mqtt/ProbeResult$Other;Ljava/lang/Throwable;ILjava/lang/Object;)Lorg/meshtastic/mqtt/ProbeResult$Other;
346
+
public fun equals (Ljava/lang/Object;)Z
347
+
public final fun getCause ()Ljava/lang/Throwable;
348
+
public fun hashCode ()I
349
+
public fun toString ()Ljava/lang/String;
350
+
}
351
+
352
+
public final class org/meshtastic/mqtt/ProbeResult$Rejected : org/meshtastic/mqtt/ProbeResult {
353
+
public fun <init> (Lorg/meshtastic/mqtt/ReasonCode;Ljava/lang/String;Ljava/lang/String;)V
354
+
public synthetic fun <init> (Lorg/meshtastic/mqtt/ReasonCode;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
355
+
public final fun component1 ()Lorg/meshtastic/mqtt/ReasonCode;
356
+
public final fun component2 ()Ljava/lang/String;
357
+
public final fun component3 ()Ljava/lang/String;
358
+
public final fun copy (Lorg/meshtastic/mqtt/ReasonCode;Ljava/lang/String;Ljava/lang/String;)Lorg/meshtastic/mqtt/ProbeResult$Rejected;
359
+
public static synthetic fun copy$default (Lorg/meshtastic/mqtt/ProbeResult$Rejected;Lorg/meshtastic/mqtt/ReasonCode;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/meshtastic/mqtt/ProbeResult$Rejected;
360
+
public fun equals (Ljava/lang/Object;)Z
361
+
public final fun getMessage ()Ljava/lang/String;
362
+
public final fun getReasonCode ()Lorg/meshtastic/mqtt/ReasonCode;
363
+
public final fun getServerReference ()Ljava/lang/String;
364
+
public fun hashCode ()I
365
+
public fun toString ()Ljava/lang/String;
366
+
}
367
+
368
+
public final class org/meshtastic/mqtt/ProbeResult$Success : org/meshtastic/mqtt/ProbeResult {
369
+
public fun <init> (Lorg/meshtastic/mqtt/ProbeServerInfo;)V
370
+
public final fun component1 ()Lorg/meshtastic/mqtt/ProbeServerInfo;
371
+
public final fun copy (Lorg/meshtastic/mqtt/ProbeServerInfo;)Lorg/meshtastic/mqtt/ProbeResult$Success;
372
+
public static synthetic fun copy$default (Lorg/meshtastic/mqtt/ProbeResult$Success;Lorg/meshtastic/mqtt/ProbeServerInfo;ILjava/lang/Object;)Lorg/meshtastic/mqtt/ProbeResult$Success;
373
+
public fun equals (Ljava/lang/Object;)Z
374
+
public final fun getServerInfo ()Lorg/meshtastic/mqtt/ProbeServerInfo;
375
+
public fun hashCode ()I
376
+
public fun toString ()Ljava/lang/String;
377
+
}
378
+
379
+
public final class org/meshtastic/mqtt/ProbeResult$TcpFailure : org/meshtastic/mqtt/ProbeResult {
380
+
public fun <init> (Ljava/lang/Throwable;)V
381
+
public final fun component1 ()Ljava/lang/Throwable;
382
+
public final fun copy (Ljava/lang/Throwable;)Lorg/meshtastic/mqtt/ProbeResult$TcpFailure;
383
+
public static synthetic fun copy$default (Lorg/meshtastic/mqtt/ProbeResult$TcpFailure;Ljava/lang/Throwable;ILjava/lang/Object;)Lorg/meshtastic/mqtt/ProbeResult$TcpFailure;
384
+
public fun equals (Ljava/lang/Object;)Z
385
+
public final fun getCause ()Ljava/lang/Throwable;
386
+
public fun hashCode ()I
387
+
public fun toString ()Ljava/lang/String;
388
+
}
389
+
390
+
public final class org/meshtastic/mqtt/ProbeResult$Timeout : org/meshtastic/mqtt/ProbeResult {
391
+
public fun <init> (J)V
392
+
public final fun component1 ()J
393
+
public final fun copy (J)Lorg/meshtastic/mqtt/ProbeResult$Timeout;
394
+
public static synthetic fun copy$default (Lorg/meshtastic/mqtt/ProbeResult$Timeout;JILjava/lang/Object;)Lorg/meshtastic/mqtt/ProbeResult$Timeout;
395
+
public fun equals (Ljava/lang/Object;)Z
396
+
public final fun getDurationMs ()J
397
+
public fun hashCode ()I
398
+
public fun toString ()Ljava/lang/String;
399
+
}
400
+
401
+
public final class org/meshtastic/mqtt/ProbeResult$TlsFailure : org/meshtastic/mqtt/ProbeResult {
402
+
public fun <init> (Ljava/lang/Throwable;)V
403
+
public final fun component1 ()Ljava/lang/Throwable;
404
+
public final fun copy (Ljava/lang/Throwable;)Lorg/meshtastic/mqtt/ProbeResult$TlsFailure;
405
+
public static synthetic fun copy$default (Lorg/meshtastic/mqtt/ProbeResult$TlsFailure;Ljava/lang/Throwable;ILjava/lang/Object;)Lorg/meshtastic/mqtt/ProbeResult$TlsFailure;
406
+
public fun equals (Ljava/lang/Object;)Z
407
+
public final fun getCause ()Ljava/lang/Throwable;
408
+
public fun hashCode ()I
409
+
public fun toString ()Ljava/lang/String;
410
+
}
411
+
412
+
public final class org/meshtastic/mqtt/ProbeServerInfo {
413
+
public fun <init> ()V
414
+
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;)V
415
+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
416
+
public final fun component1 ()Ljava/lang/String;
417
+
public final fun component10 ()Ljava/lang/Integer;
418
+
public final fun component11 ()Ljava/lang/String;
419
+
public final fun component12 ()Ljava/lang/String;
420
+
public final fun component2 ()Ljava/lang/Integer;
421
+
public final fun component3 ()Ljava/lang/Integer;
422
+
public final fun component4 ()Ljava/lang/Boolean;
423
+
public final fun component5 ()Ljava/lang/Boolean;
424
+
public final fun component6 ()Ljava/lang/Boolean;
425
+
public final fun component7 ()Ljava/lang/Boolean;
426
+
public final fun component8 ()Ljava/lang/Long;
427
+
public final fun component9 ()Ljava/lang/Integer;
428
+
public final fun copy (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;)Lorg/meshtastic/mqtt/ProbeServerInfo;
429
+
public static synthetic fun copy$default (Lorg/meshtastic/mqtt/ProbeServerInfo;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/meshtastic/mqtt/ProbeServerInfo;
430
+
public fun equals (Ljava/lang/Object;)Z
431
+
public final fun getAssignedClientIdentifier ()Ljava/lang/String;
432
+
public final fun getMaximumPacketSize ()Ljava/lang/Long;
433
+
public final fun getMaximumQosOrdinal ()Ljava/lang/Integer;
434
+
public final fun getReceiveMaximum ()Ljava/lang/Integer;
435
+
public final fun getResponseInformation ()Ljava/lang/String;
436
+
public final fun getRetainAvailable ()Ljava/lang/Boolean;
437
+
public final fun getServerKeepAliveSeconds ()Ljava/lang/Integer;
438
+
public final fun getServerReference ()Ljava/lang/String;
439
+
public final fun getSharedSubscriptionAvailable ()Ljava/lang/Boolean;
440
+
public final fun getSubscriptionIdentifiersAvailable ()Ljava/lang/Boolean;
441
+
public final fun getTopicAliasMaximum ()Ljava/lang/Integer;
442
+
public final fun getWildcardSubscriptionAvailable ()Ljava/lang/Boolean;
443
+
public fun hashCode ()I
444
+
public fun toString ()Ljava/lang/String;
445
+
}
446
+
317
447
public final class org/meshtastic/mqtt/PublishProperties {
318
448
public fun <init> ()V
319
449
public fun <init> (Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Lkotlinx/io/bytestring/ByteString;ZLjava/util/List;Ljava/util/List;)V
0 commit comments