Skip to content

Fleet & auto-reconnect

Once a device is saved, the SDK remembers it, reconnects it when it comes back into range, and lets you manage it — all as reactive state and declarative policy. This guide covers the saved-device list, per-device actions, the derived reconnect toast, and the provider-level fleet policy.

useSavedDevices() is the data source for a “My devices” screen: the saved devices in deterministic fleet order, plus a hydration flag so you can render a skeleton before persisted state has loaded from storage.

import { useSavedDevices } from '@rogue/console-sdk';
function MyDevices() {
const { devices, isHydrated } = useSavedDevices();
if (!isHydrated) return <Skeleton />;
if (devices.length === 0) return <EmptyState />;
return devices.map((device) => <SavedDeviceRow key={device.id} device={device} />);
}

Saved is just a facet of the one Device record — this is useDevices({ saved: true }) with a hydration flag, not a second list to reconcile against the discovered one.

useDeviceActions(deviceId) collapses the whole legacy five-function blocklist protocol into three verbs, each keyed by one device. All three are bare verbs that never reject — a failure routes to state and the error reporter, so an onPress={forget} handler can never float an unhandled rejection.

import { useDeviceActions } from '@rogue/console-sdk';
function SavedDeviceRow({ device }: { device: Device }) {
const { disconnect, forget, setAutoReconnect } = useDeviceActions(device.id);
return (
<Row>
<Text>{device.displayName}</Text>
<Switch value={device.autoReconnect} onValueChange={setAutoReconnect} />
{device.isConnected && <Button title="Disconnect" onPress={() => disconnect()} />}
<Button title="Forget" onPress={forget} />
</Row>
);
}
  • disconnect() — a deliberate disconnect. It suppresses auto-reconnect for the rest of the session; pass { autoReconnect: false } to also persist the per-device opt-out.
  • forget() — removes persistence and auto-reconnect eligibility.
  • setAutoReconnect(enabled) — the whole protocol, now one boolean.

Passing null/undefined as the id is legal and yields dev-warned no-op actions, so you can call the hook unconditionally even before a device is selected.

This is the benchmark the SDK was built to hit: the ninety lines of event-to-state adaptation the app used to write become one hook. useAutoReconnect() derives “recently reconnected” from connection provenance — a ready connection whose via is 'auto-reconnect' that you have not acknowledged — never from a stored event. isSettling deletes the last reason to poll for settling.

import { useAutoReconnect } from '@rogue/console-sdk';
function AutoReconnectToast() {
const { recentlyReconnected, acknowledge } = useAutoReconnect();
if (recentlyReconnected.length === 0) return null;
const names = recentlyReconnected.map((r) => r.device.displayName).join(', ');
return (
<Toast onDismiss={() => acknowledge()}>
Reconnected to {names}
</Toast>
);
}

Mount that once near your root and reconnections announce themselves. Each ReconnectedEntry carries the reconnected device, the epoch ms at, and a duringWorkout flag. acknowledge(id?) drops one device from the feed (omit the id to clear all) with no stored event to manage.

The same hook exposes the global switch:

const { enabled, setEnabled, isSettling } = useAutoReconnect();
<Switch value={enabled} onValueChange={setEnabled} />;
{isSettling && <Text>Reconnecting…</Text>}

The old MDM flag-and-blocklist choreography becomes provider config. Set it once on createConsoleConfig(); the engine enforces it.

import { createConsoleConfig } from '@rogue/console-sdk';
const config = createConsoleConfig({
fleet: {
maxDevices: 4, // max simultaneously connected
onePerModality: true, // one machine per modality
connectTimeoutMs: 15_000,
autoReconnect: {
enabled: true,
duringWorkout: true, // reconnect mid-workout for session devices
},
autoScan: {
enabled: true,
cooldownMs: 15_000, // pause between background scans
inWorkoutCooldownMultiplier: 3, // scan more often during a workout
postDisconnectDebounceMs: 3_000, // debounce the post-drop rescan
},
},
});

Every field is optional and shown here at its default. onePerModality: true is what surfaces the connect/modality-conflict error covered in Connecting devices; maxDevices is what surfaces connect/device-limit. Auto-scan scheduling is the machinery that lets auto-reconnect find a device that comes back into range without you running any timers.