diff --git a/src/App.tsx b/src/App.tsx index 4268d88..47fa7b8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,10 +4,13 @@ import Preflight from './components/preflight'; import ServiceExample from './components/ServiceExample'; import { RosProvider } from './components/RosContext' +import RosNodeStatus from './components/RosNodeList'; + function App() { return ( +
diff --git a/src/components/RosNodeList.tsx b/src/components/RosNodeList.tsx new file mode 100644 index 0000000..4864242 --- /dev/null +++ b/src/components/RosNodeList.tsx @@ -0,0 +1,94 @@ +import React, { useState, useEffect } from 'react'; +import ROSLIB from 'roslib'; + +function RosNodeStatus() { +const expectedNodes = ['depth_driver', 'front_cam', 'hardsoft_compensator', + 'launch_ros_5783', 'magnetic_compensation_container', 'pid_controller', + 'pingpublisher', 'reset_localization_service', 'robot_state_publisher', + 'subjugator_localization', 'subjugator_path_planner', + 'subjugator_trajectory_planner', 'thrust_and_kill_board', 'thruster_manager', + 'transform_listener_impl_aaab08838300', 'vectornav', 'vn_sensor_msgs', + 'waterlinked_dvl_driver', '/rosapi', '/rosbridge_websocket']; + + const [runningNodes, setRunningNodes] = useState([]); + const rosBridgeUrl = `ws://${window.location.hostname}:9090` + useEffect(() => { + const ros = new ROSLIB.Ros({ + url: rosBridgeUrl + }); + + ros.on('connection', () => { + console.log('Successfully connected to ROS bridge server.'); + }); + + ros.on('error', (error) => { + console.error('Error connecting to ROS bridge server: ', error); + }); + + ros.on('close', () => { + console.log('Connection to ROS bridge server closed.'); + }); + + const intervalId = setInterval(() => { + ros.getNodes( + (nodes: string[]) => { + console.log('Fetched Nodes:', nodes); + setRunningNodes(nodes); + }, + (error) => { + console.error('Failed to get ROS nodes:', error); + } + ); + }, 2000); + + return () => { + clearInterval(intervalId); + ros.close(); + }; + }, []); + const greenNodes = runningNodes.filter(node => expectedNodes.includes(node)); + const redNodes = expectedNodes.filter(node => !runningNodes.includes(node)); + const yellowNodes = runningNodes.filter(node => !expectedNodes.includes(node)); + + return ( +
+ {/* Green Box */} +
+

Running

+
    + {greenNodes.length > 0 ? ( + greenNodes.map(node =>
  • {node}
  • ) + ) : ( +
  • None
  • + )} +
+
+ + {/* Red Box */} +
+

Missing

+
    + {redNodes.length > 0 ? ( + redNodes.map(node =>
  • {node}
  • ) + ) : ( +
  • None
  • + )} +
+
+ + {/* Yellow Box */} +
+

Unexpected

+
    + {yellowNodes.length > 0 ? ( + yellowNodes.map(node =>
  • {node}
  • ) + ) : ( +
  • None
  • + )} +
+
+
+ ); +} + +export default RosNodeStatus; \ No newline at end of file