From 5c8d34b51695ad88d4196754d53a32fd356baa06 Mon Sep 17 00:00:00 2001 From: Tomas Williston <60055436+TomasWilliston@users.noreply.github.com> Date: Mon, 3 Aug 2026 05:00:54 -0400 Subject: [PATCH 1/2] Add options to control morse code detection from the morse transmission panel. --- .../panels/MorseTransmissionPanel.tsx | 153 +++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/src/components/panels/MorseTransmissionPanel.tsx b/src/components/panels/MorseTransmissionPanel.tsx index 535d46d..fc2087b 100644 --- a/src/components/panels/MorseTransmissionPanel.tsx +++ b/src/components/panels/MorseTransmissionPanel.tsx @@ -3,17 +3,23 @@ import React, { useEffect, useRef, useState } from 'react'; import ROSLIB from 'roslib'; import { useROS } from '@/ros/ROSContext'; +type DetectionType = 'NONE' | 'MORSE' | string; + const MorseTransmissionPanel: React.FC = () => { const { ros } = useROS(); const [message, setMessage] = useState(''); const [lastSent, setLastSent] = useState(null); + const [detectionType, setDetectionType] = useState(null); + const [updating, setUpdating] = useState(false); + const [status, setStatus] = useState(null); const topicRef = useRef(null); useEffect(() => { if (!ros) { topicRef.current = null; + setDetectionType(null); return; } @@ -33,6 +39,88 @@ const MorseTransmissionPanel: React.FC = () => { }; }, [ros]); + const refreshDetectionType = () => { + if (!ros) return; + + const service = new ROSLIB.Service({ + ros, + name: '/detect_node/get_parameters', + serviceType: 'rcl_interfaces/srv/GetParameters', + }); + + const request = new ROSLIB.ServiceRequest({ + names: ['detection_type'], + }); + + service.callService(request, (result: any) => { + const value = result.values?.[0]; + if (!value || value.type !== 4) { + setStatus('Failed to read detection_type'); + return; + } + setDetectionType(value.string_value ?? 'NONE'); + }); + }; + + useEffect(() => { + refreshDetectionType(); + }, [ros]); + + const setDetectParameter = ( + name: string, + value: { type: number; string_value?: string; bool_value?: boolean }, + onSuccess?: () => void, + ) => { + if (!ros) return; + + setUpdating(true); + setStatus(null); + + const service = new ROSLIB.Service({ + ros, + name: '/detect_node/set_parameters', + serviceType: 'rcl_interfaces/srv/SetParameters', + }); + + const request = new ROSLIB.ServiceRequest({ + parameters: [{ name, value }], + }); + + service.callService(request, (result: any) => { + const parameterResult = result.results?.[0]; + const success = parameterResult?.successful ?? false; + const reason = parameterResult?.reason ?? ''; + + setUpdating(false); + + if (!success) { + setStatus(reason || `Failed to set ${name}`); + if (name === 'detection_type') refreshDetectionType(); + return; + } + + onSuccess?.(); + setStatus(`Set ${name} successfully`); + }); + }; + + const handleMorseToggle = (enabled: boolean) => { + const mode = enabled ? 'MORSE' : 'NONE'; + setDetectParameter( + 'detection_type', + { type: 4, string_value: mode }, + () => setDetectionType(mode), + ); + }; + + const setCalibrate = () => { + setDetectParameter('calibrate', { type: 1, bool_value: true }); + }; + + const setStartDetection = () => { + setDetectParameter('start_detection', { type: 1, bool_value: true }); + }; + const send = () => { if (!topicRef.current || !message) return; topicRef.current.publish(new ROSLIB.Message({ data: message })); @@ -44,6 +132,9 @@ const MorseTransmissionPanel: React.FC = () => { }; const disabled = !ros; + const detectDisabled = disabled || updating || detectionType === null; + const morseEnabled = detectionType === 'MORSE'; + const morseActionsDisabled = detectDisabled || !morseEnabled; return (
@@ -62,7 +153,33 @@ const MorseTransmissionPanel: React.FC = () => {
+
+
Detection Options
+
+ + + +
+
+ {lastSent &&
Last sent: {lastSent}
} + {status &&
{status}
}