import React, { useState, useEffect } from "react"; import { ThemeProvider, Box, Select, MenuItem, IconButton, TextField, Typography } from '@mui/material'; import PlayArrowIcon from '@mui/icons-material/PlayArrow'; import PauseIcon from '@mui/icons-material/Pause'; import CleaningServicesIcon from '@mui/icons-material/CleaningServices'; import DronecanLogo from './image/dronecan_logo.png'; import { toYaml } from './dronecan/message_format_utils'; import theme from './theme'; import './css/subscriber.css'; const SubscriberWindow = () => { const [messages, setMessages] = useState([]); const [messageRate, setMessageRate] = useState(0); const [totalRX, setTotalRX] = useState(0); const [maxMessageCount, setMaxMessageCount] = useState(5); const [rxTimestamp, setRxTimestamp] = useState(0); const [selectedMessageName, setSelectedMessageName] = useState(""); const [recordingSet, setRecordingSet] = useState([]); const [displayRecordText, setDisplayRecordText] = useState(""); const [recording, setRecording] = useState(true); if (window.opener === null) { return "Not Allowed To Open Directly"; } useEffect(() => { const localNode = window.opener.localNode; const handleMessageUpdate = (transfer) => { if (transfer.payload.name === selectedMessageName && recording) { setTotalRX(totalRX + 1); } if (messages.indexOf(transfer.payload.name) === -1) { messages.push(transfer.payload.name); setMessages(messages); setRxTimestamp(Date.now()); } if (recording && transfer.payload.name === selectedMessageName) { recordingSet.push(transfer); setRecordingSet(recordingSet.slice(-maxMessageCount)); } if (transfer.payload.name === selectedMessageName) { setRxTimestamp(Date.now()); } let recordingSetText = ""; let rate = 0; let tsDiffs = 0; let lastTransferTs; recordingSet.map((transfer, index) => { if (index > 0) { tsDiffs += transfer.tsMonotonic - lastTransferTs } lastTransferTs = transfer.tsMonotonic; if (index > 0 && index === recordingSet.length - 1) { rate = 1 / (tsDiffs / (recordingSet.length - 1)) setMessageRate(rate); } const msg = transfer.payload; const msgObj = msg.toObj(); let destNodeText = "All"; if (transfer.destNodeId && transfer.destNodeId !== 0) { destNodeText = `${transfer.destNodeId}`; } recordingSetText += `### Message from ${transfer.sourceNodeId} to ${destNodeText} ts_mono=${transfer.tsMonotonic.toFixed(15)} ts_real=${transfer.tsReal.toFixed(15)} \n`; recordingSetText += toYaml(msgObj); recordingSetText += "\n"; }) setDisplayRecordText(recordingSetText); }; localNode.on('message', handleMessageUpdate); return () => { localNode.off('message', handleMessageUpdate); }; }); const updateMaxMessageCount = (event) => { if (event.target.value < 1) { setMaxMessageCount(1); } else if (event.target.value > 100) { setMaxMessageCount(100); } else { setMaxMessageCount(event.target.value); } }; const handleSelectChange = (event) => { if (event.target.value !== selectedMessageName) { handleClean(); } setSelectedMessageName(event.target.value); }; const handleClean = () => { setRecordingSet([]); setTotalRX(0); setMessageRate(0); }; useEffect(() => { const availableMessages = messages; if (!selectedMessageName && availableMessages.length > 0) { setSelectedMessageName(availableMessages[0]); } }, [rxTimestamp]); const availableMessages = messages; return ( DroneCAN setRecording(!recording)}> {recording ? : } RX: {totalRX} Rates(Hz): {messageRate.toFixed(0)} Max: