diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index aec256e..351017b 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,4 +1,5 @@ import Layout from '@/components/Layout'; +import { Toaster } from "react-hot-toast"; import type { Metadata } from "next"; import MosaicDashboardClient from "./MosaicDashboardClient"; @@ -11,6 +12,7 @@ export default function Dashboard() { return ( + ); -} \ No newline at end of file +} diff --git a/src/components/VideoCustomPresetForm.tsx b/src/components/VideoCustomPresetForm.tsx index 9fc3e87..96dfe8f 100644 --- a/src/components/VideoCustomPresetForm.tsx +++ b/src/components/VideoCustomPresetForm.tsx @@ -39,7 +39,6 @@ const VideoCustomPresetForm: React.FC = ({ onSubmit }) => const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); const preset: VideoOutRequest = { - num_sources: sources.length, sources, }; onSubmit(preset); diff --git a/src/components/VideoPresetsPanel.tsx b/src/components/VideoPresetsPanel.tsx index e00677a..ff1cd78 100644 --- a/src/components/VideoPresetsPanel.tsx +++ b/src/components/VideoPresetsPanel.tsx @@ -1,70 +1,24 @@ "use client"; -import React from "react"; -import { VideoOutRequest } from "./panels/VideoControls"; +import React, { useEffect, useState } from "react"; +import { VideoOutRequest, VideoSource } from "./panels/VideoControls"; +import ROSLIB from "roslib"; +import { useROS } from "@/ros/ROSContext"; interface VideoPresetsPanelProps { onPresetSelect: (presetName: string, preset: VideoOutRequest) => void; } +type VideoPreset = { + name: string; + sources: VideoSource[]; +} + const VideoPresetsPanel: React.FC = ({ onPresetSelect, }) => { - const presets: { name: string; preset: VideoOutRequest }[] = [ - { - name: "Drive", - preset: { - num_sources: 1, - sources: [{ name: "Drive", width: 100, height: 100, origin_x: 0, origin_y: 0 }], - }, - }, - { - name: "EEF", - preset: { - num_sources: 1, - sources: [{ name: "EndEffector", width: 100, height: 100, origin_x: 0, origin_y: 0 }], - }, - }, - { - name: "Science", - preset: { - num_sources: 4, - sources: [ - { name: "Microscope", width: 50, height: 50, origin_x: 0, origin_y: 0 }, - { name: "Strip", width: 50, height: 50, origin_x: 50, origin_y: 0 }, - { name: "Benedict", width: 50, height: 50, origin_x: 0, origin_y: 50 }, - { name: "HCL", width: 50, height: 50, origin_x: 50, origin_y: 50 }, - ], - }, - }, - { - name: "Belly", - preset: { - num_sources: 1, - sources: [{ name: "Bottom", width: 100, height: 100, origin_x: 0, origin_y: 0 }], - }, - }, - { - name: "Drive + EEF", - preset: { - num_sources: 2, - sources: [ - { name: "Drive", width: 100, height: 100, origin_x: 0, origin_y: 0 }, - { name: "EndEffector", width: 30, height: 30, origin_x: 70, origin_y: 0 }, - ], - }, - }, - { - name: "EEF + Drive", - preset: { - num_sources: 2, - sources: [ - { name: "EndEffector", width: 100, height: 100, origin_x: 0, origin_y: 0 }, - { name: "Drive", width: 30, height: 30, origin_x: 70, origin_y: 0 }, - ], - }, - }, - ]; + const { ros, connectionStatus: rosStatus } = useROS(); + const [presets, setPresets] = useState([]); const buttonStyle = (): React.CSSProperties => ({ border: "1px solid #444", @@ -76,6 +30,24 @@ const VideoPresetsPanel: React.FC = ({ whiteSpace: "nowrap", }); + useEffect(() => { + if (!ros) { + console.error("ROS connection is not established."); + return; + } + const getPresetsClient = new ROSLIB.Service({ + ros: ros, + name: "/list_presets", + serviceType: "interfaces/srv/GetPresets", + }); + + const request = new ROSLIB.ServiceRequest({}); + getPresetsClient.callService(request, (response) => { + if (response) { + setPresets(response.presets); + } + }); + }, [ros]); return (
= ({ gap: "0.5rem", }} > - {presets.map(({ name, preset }) => ( + {presets.map(({ name, sources }) => ( diff --git a/src/components/panels/VideoControls.tsx b/src/components/panels/VideoControls.tsx index ca1c735..c8540b7 100644 --- a/src/components/panels/VideoControls.tsx +++ b/src/components/panels/VideoControls.tsx @@ -5,6 +5,7 @@ import ROSLIB from "roslib"; import { useROS } from "@/ros/ROSContext"; import VideoPresetsPanel from "../VideoPresetsPanel"; import RtpStats from "../RtpStats"; +import toast from "react-hot-toast"; export interface VideoSource { name: string; @@ -15,7 +16,6 @@ export interface VideoSource { } export interface VideoOutRequest { - num_sources: number; sources: VideoSource[]; } @@ -23,9 +23,6 @@ interface VideoOutResponse { success: boolean; } -interface VideoOutResponse { - success: boolean; -} const VideoControls: React.FC = () => { const { ros, connectionStatus: rosStatus } = useROS(); @@ -63,7 +60,9 @@ const VideoControls: React.FC = () => { startVideoSrv.callService( new ROSLIB.ServiceRequest(camRequest), (response: VideoOutResponse) => { - console.log(response.success ? "Success" : "Failed"); + if (!response.success) { + toast.error("Failed to select preset: " + presetName) + } }, ); }; @@ -78,6 +77,7 @@ const VideoControls: React.FC = () => { topic.publish(new ROSLIB.Message({})); console.log("Stream restart triggered"); }; + const callVideoCaptureService = (serviceName: string, filename: string = "") => { if (!ros || rosStatus !== "connected") return; @@ -288,4 +288,4 @@ const VideoControls: React.FC = () => { ); }; -export default VideoControls; \ No newline at end of file +export default VideoControls;