Spaces:
Running
Running
File size: 5,581 Bytes
18b0fa5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
<script lang="ts">
import * as Dialog from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import * as Card from "@/components/ui/card";
import * as Alert from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { toast } from "svelte-sonner";
import { robotManager } from "$lib/robot/RobotManager.svelte";
import { getWebSocketBaseUrl } from "$lib/utils/config";
import type { Robot } from "$lib/robot/Robot.svelte";
interface Props {
open: boolean;
robot: Robot | null;
}
let { open = $bindable(), robot }: Props = $props();
// Get URLs from configuration
const wsBaseUrl = getWebSocketBaseUrl();
// Master connection functions
async function connectDemoSequences() {
if (!robot) return;
try {
await robotManager.connectDemoSequences(robot.id);
} catch (err) {
toast.error("Failed to Connect Demo Sequences", {
description: `Could not connect demo sequences: ${err}`
});
console.error(err);
}
}
async function connectRemoteServerMaster() {
if (!robot) return;
try {
const config: import("$lib/types/robotDriver").MasterDriverConfig = {
type: "remote-server",
url: wsBaseUrl,
apiKey: undefined,
pollInterval: 100
};
await robotManager.connectMaster(robot.id, config);
} catch (err) {
toast.error("Failed to Connect Remote Server", {
description: `Could not connect remote server: ${err}`
});
console.error(err);
}
}
async function connectUSBMaster() {
if (!robot) return;
try {
await robotManager.connectUSBMaster(robot.id, {
pollInterval: 200,
smoothing: true
});
} catch (err) {
toast.error("Failed to Connect USB Master", {
description: `Could not connect USB master: ${err}`
});
console.error(err);
}
}
async function disconnectMaster() {
if (!robot) return;
try {
await robotManager.disconnectMaster(robot.id);
} catch (err) {
toast.error("Failed to Disconnect Master", {
description: `Could not disconnect master: ${err}`
});
console.error(err);
}
}
</script>
<Dialog.Root bind:open>
<Dialog.Content
class="max-h-[80vh] max-w-xl overflow-y-auto border-slate-600 bg-slate-900 text-slate-100"
>
<Dialog.Header class="pb-3">
<Dialog.Title class="flex items-center gap-2 text-lg font-bold text-slate-100">
<span class="icon-[mdi--account-supervisor] size-5 text-green-400"></span>
Master Connection
</Dialog.Title>
<Dialog.Description class="text-sm text-slate-400">
Configure master sources for robot {robot?.id}
</Dialog.Description>
</Dialog.Header>
{#if robot}
<div class="space-y-4">
<!-- Current Status - Compact -->
<div
class="flex items-center justify-between rounded-lg border border-green-500/30 bg-green-900/20 p-3"
>
<div class="flex items-center gap-2">
<span class="icon-[mdi--speak] size-4 text-green-400"></span>
<span class="text-sm font-medium text-green-300">Master Status</span>
</div>
{#if robot.controlState.hasActiveMaster}
<Badge variant="default" class="bg-green-600 text-xs">
{robot.controlState.masterName}
</Badge>
{:else}
<Badge variant="outline" class="text-xs text-slate-400">None Connected</Badge>
{/if}
</div>
<!-- Master Controls -->
<Card.Root class="border-green-500/30 bg-green-500/5">
<Card.Header>
<Card.Title class="flex items-center gap-2 text-base text-green-200">
<span class="icon-[mdi--account-supervisor] size-4"></span>
Connection Options
</Card.Title>
</Card.Header>
<Card.Content class="space-y-2">
{#if robot.controlState.hasActiveMaster}
<div class="rounded-lg border border-green-500/30 bg-green-900/20 p-2">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-green-300">
{robot.controlState.masterName}
</p>
<p class="text-xs text-green-400/70">Currently active</p>
</div>
<Button
variant="destructive"
size="sm"
onclick={disconnectMaster}
class="h-7 px-2 text-xs"
>
<span class="icon-[mdi--close-circle] mr-1 size-3"></span>
Disconnect
</Button>
</div>
</div>
{:else}
<div class="space-y-2">
<Button
variant="secondary"
onclick={connectDemoSequences}
class="h-8 w-full bg-orange-600 text-sm text-white hover:bg-orange-700"
>
<span class="icon-[mdi--play-circle] mr-2 size-4"></span>
Demo Sequences
</Button>
<Button
variant="secondary"
onclick={connectRemoteServerMaster}
class="h-8 w-full bg-purple-600 text-sm text-white hover:bg-purple-700"
>
<span class="icon-[mdi--cloud] mr-2 size-4"></span>
Remote Server
</Button>
<Button
variant="secondary"
onclick={connectUSBMaster}
class="h-8 w-full bg-blue-600 text-sm text-white hover:bg-blue-700"
>
<span class="icon-[mdi--usb] mr-2 size-4"></span>
USB Master
</Button>
</div>
{/if}
</Card.Content>
</Card.Root>
<!-- Quick Info -->
<div class="rounded border border-slate-700 bg-slate-800/30 p-2 text-xs text-slate-500">
<span class="icon-[mdi--information] mr-1 size-3"></span>
Masters are input sources. Only one can be active at a time.
</div>
</div>
{/if}
</Dialog.Content>
</Dialog.Root>
|