import React, { useState, useEffect, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { useToast } from '@/hooks/use-toast'; import { generateSensorData, generateMotorData } from '@/lib/mockData'; import VisualizerPanel from '@/components/control/VisualizerPanel'; import MetricsPanel from '@/components/control/MetricsPanel'; import CommandBar from '@/components/control/CommandBar'; const Index = () => { const [command, setCommand] = useState(''); const [activeTab, setActiveTab] = useState<'SENSORS' | 'MOTORS'>('SENSORS'); const [isVoiceActive, setIsVoiceActive] = useState(true); const [showCamera, setShowCamera] = useState(false); const [hasPermissions, setHasPermissions] = useState(false); const [micLevel, setMicLevel] = useState(0); const [sensorData, setSensorData] = useState([]); const [motorData, setMotorData] = useState([]); const { toast } = useToast(); const navigate = useNavigate(); const videoRef = useRef(null); const streamRef = useRef(null); useEffect(() => { let audioContext: AudioContext | null = null; const getPermissions = async () => { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); streamRef.current = stream; if (videoRef.current) { videoRef.current.srcObject = stream; } setHasPermissions(true); const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext; if (AudioContextClass) { audioContext = new AudioContextClass(); const analyser = audioContext.createAnalyser(); const source = audioContext.createMediaStreamSource(stream); source.connect(analyser); let animationFrameId: number; const dataArray = new Uint8Array(analyser.frequencyBinCount); const updateMicLevel = () => { if (audioContext?.state === 'closed') return; analyser.getByteFrequencyData(dataArray); const average = dataArray.reduce((a, b) => a + b) / dataArray.length; setMicLevel(average); animationFrameId = requestAnimationFrame(updateMicLevel); }; updateMicLevel(); return () => { cancelAnimationFrame(animationFrameId); audioContext?.close(); }; } } catch (error) { console.error("Permission to access media devices was denied.", error); } }; let cleanup: (() => void) | undefined; getPermissions().then(returnedCleanup => { cleanup = returnedCleanup; }); return () => { if (streamRef.current) { streamRef.current.getTracks().forEach(track => track.stop()); } cleanup?.(); }; }, []); useEffect(() => { const interval = setInterval(() => { setSensorData(prev => [...prev, generateSensorData()].slice(-50)); setMotorData(prev => [...prev, generateMotorData()].slice(-50)); }, 100); return () => clearInterval(interval); }, []); const handleSendCommand = () => { if (command.trim()) { toast({ title: "Command Sent", description: `Robot command: "${command}"`, }); setCommand(''); } }; const handleGoBack = () => { navigate('/'); }; const handleEndSession = () => { if (streamRef.current) { streamRef.current.getTracks().forEach(track => track.stop()); } toast({ title: "Session Ended", description: "Robot control session terminated safely.", variant: "destructive", }); navigate('/'); }; return (
); }; export default Index;