Initial implementation of Bluetooth toy control app
Next.js app with a browser-side buttplug/buttplug-wasm control layer (server never touches real-time device commands), SQLite storage via Drizzle, single-secret auth, recordings/replay with device remapping, a usage stats dashboard, Docker deployment, and Gitea CI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W8WkFF5ppURBAB918593Eb
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import type { RecordingDeviceSlot } from "@/lib/db/schema";
|
||||
import type { ConnectedDeviceInfo } from "./types";
|
||||
|
||||
export interface DeviceRemapEntry {
|
||||
slotLabel: string;
|
||||
recordedBleName: string;
|
||||
matchedDeviceIndex: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Best-effort name match from a recording's saved device slots to the
|
||||
* currently-connected devices. Web Bluetooth exposes no stable hardware id
|
||||
* across sessions, so this is inherently approximate: two devices sharing an
|
||||
* identical advertised name are indistinguishable and must be disambiguated
|
||||
* manually in the remap UI - this isn't a bug, it's a hard BLE limitation.
|
||||
*/
|
||||
export function autoMapDeviceSlots(
|
||||
slots: RecordingDeviceSlot[],
|
||||
connectedDevices: ConnectedDeviceInfo[],
|
||||
): DeviceRemapEntry[] {
|
||||
const usedIndexes = new Set<number>();
|
||||
|
||||
return slots.map((slot) => {
|
||||
const normalizedSlotName = slot.recordedBleName.trim().toLowerCase();
|
||||
|
||||
const exact = connectedDevices.find(
|
||||
(d) => !usedIndexes.has(d.index) && d.name.trim().toLowerCase() === normalizedSlotName,
|
||||
);
|
||||
const partial =
|
||||
exact ??
|
||||
connectedDevices.find(
|
||||
(d) =>
|
||||
!usedIndexes.has(d.index) &&
|
||||
(d.name.toLowerCase().includes(normalizedSlotName) ||
|
||||
normalizedSlotName.includes(d.name.toLowerCase())),
|
||||
);
|
||||
|
||||
if (partial) usedIndexes.add(partial.index);
|
||||
|
||||
return {
|
||||
slotLabel: slot.slotLabel,
|
||||
recordedBleName: slot.recordedBleName,
|
||||
matchedDeviceIndex: partial?.index ?? null,
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user