Spaces:
Sleeping
Sleeping
| /** | |
| * Basic Producer Example - RobotHub TransportServer | |
| * | |
| * This example demonstrates: | |
| * - Creating a room with workspace support | |
| * - Connecting as a producer with workspace_id and room_id | |
| * - Sending joint updates and state sync | |
| * - Modern error handling and cleanup | |
| * - Enhanced user feedback | |
| */ | |
| import { RoboticsProducer } from '../dist/robotics/index.js'; | |
| async function main() { | |
| console.log('π€ RobotHub TransportServer Basic Producer Example π€'); | |
| console.log('π This example will create a room and demonstrate producer functionality\n'); | |
| // Create producer client | |
| const producer = new RoboticsProducer('http://localhost:8000'); | |
| // Track connection state | |
| let isConnected = false; | |
| let workspaceId = null; | |
| let roomId = null; | |
| // Set up event callbacks with enhanced feedback | |
| producer.onConnected(() => { | |
| isConnected = true; | |
| console.log('β Producer connected successfully!'); | |
| }); | |
| producer.onDisconnected(() => { | |
| isConnected = false; | |
| console.log('π Producer disconnected'); | |
| }); | |
| producer.onError((error) => { | |
| console.error('β Producer error:', error); | |
| }); | |
| try { | |
| // Create a room (returns both workspace_id and room_id) | |
| console.log('π¦ Creating new room...'); | |
| const roomInfo = await producer.createRoom(); | |
| workspaceId = roomInfo.workspaceId; | |
| roomId = roomInfo.roomId; | |
| console.log(`β Room created successfully!`); | |
| console.log(` Workspace ID: ${workspaceId}`); | |
| console.log(` Room ID: ${roomId}`); | |
| // Connect as producer with both workspace_id and room_id | |
| console.log('\nπ Connecting as producer...'); | |
| const success = await producer.connect(workspaceId, roomId, 'demo-producer'); | |
| if (!success) { | |
| console.error('β Failed to connect as producer!'); | |
| console.log('π‘ Make sure the server is running on http://localhost:8000'); | |
| return; | |
| } | |
| console.log(`β Connected to room successfully!`); | |
| // Show detailed connection info | |
| const info = producer.getConnectionInfo(); | |
| console.log('\nπ Connection Details:'); | |
| console.log(` Workspace ID: ${info.workspace_id}`); | |
| console.log(` Room ID: ${info.room_id}`); | |
| console.log(` Role: ${info.role}`); | |
| console.log(` Participant ID: ${info.participant_id}`); | |
| console.log(` Server URL: ${info.base_url}`); | |
| // Send initial state sync with enhanced feedback | |
| console.log('\nπ€ Sending initial robot state...'); | |
| const initialState = { | |
| base: 0.0, | |
| shoulder: 0.0, | |
| elbow: 0.0, | |
| wrist: 0.0, | |
| gripper: 0.0 | |
| }; | |
| await producer.sendStateSync(initialState); | |
| console.log('β Initial state sent:'); | |
| Object.entries(initialState).forEach(([joint, value]) => { | |
| console.log(` ${joint}: ${value}Β°`); | |
| }); | |
| // Simulate realistic robot movement sequence | |
| console.log('\nπ€ Simulating robot movement sequence...'); | |
| const movements = [ | |
| { | |
| joints: [{ name: 'base', value: 30.0 }], | |
| description: 'Rotate base to 30Β°', | |
| delay: 1500 | |
| }, | |
| { | |
| joints: [{ name: 'shoulder', value: 45.0 }], | |
| description: 'Raise shoulder to 45Β°', | |
| delay: 1200 | |
| }, | |
| { | |
| joints: [{ name: 'elbow', value: -30.0 }], | |
| description: 'Bend elbow to -30Β°', | |
| delay: 1000 | |
| }, | |
| { | |
| joints: [{ name: 'wrist', value: 15.0 }], | |
| description: 'Turn wrist to 15Β°', | |
| delay: 800 | |
| }, | |
| { | |
| joints: [{ name: 'gripper', value: 0.8 }], | |
| description: 'Close gripper to 80%', | |
| delay: 600 | |
| }, | |
| ]; | |
| for (let i = 0; i < movements.length; i++) { | |
| const movement = movements[i]; | |
| console.log(`\n Step ${i + 1}: ${movement.description}`); | |
| await producer.sendJointUpdate(movement.joints); | |
| console.log(` β Joint update sent: ${movement.joints.map(j => `${j.name}=${j.value}Β°`).join(', ')}`); | |
| // Wait between movements for realistic timing | |
| console.log(` β³ Waiting ${movement.delay}ms...`); | |
| await new Promise(resolve => setTimeout(resolve, movement.delay)); | |
| } | |
| // Send combined multi-joint update | |
| console.log('\nπ€ Sending combined multi-joint update...'); | |
| const combinedUpdate = [ | |
| { name: 'base', value: 90.0 }, | |
| { name: 'shoulder', value: 60.0 }, | |
| { name: 'elbow', value: -45.0 } | |
| ]; | |
| await producer.sendJointUpdate(combinedUpdate); | |
| console.log('β Combined update sent:'); | |
| combinedUpdate.forEach(joint => { | |
| console.log(` ${joint.name}: ${joint.value}Β°`); | |
| }); | |
| // Send final state sync | |
| console.log('\nπ€ Sending final state synchronization...'); | |
| const finalState = { | |
| base: 90.0, | |
| shoulder: 60.0, | |
| elbow: -45.0, | |
| wrist: 15.0, | |
| gripper: 0.8 | |
| }; | |
| await producer.sendStateSync(finalState); | |
| console.log('β Final state synchronized'); | |
| // Send heartbeat to verify connection | |
| console.log('\nπ Sending heartbeat...'); | |
| await producer.sendHeartbeat(); | |
| console.log('β Heartbeat sent - connection healthy'); | |
| // Demonstrate emergency stop | |
| console.log('\nπ¨ Testing emergency stop functionality...'); | |
| await producer.sendEmergencyStop('Demo emergency stop - testing safety protocols'); | |
| console.log('β Emergency stop sent successfully'); | |
| console.log('\nπ Basic producer example completed successfully!'); | |
| // Display connection info for consumers | |
| console.log('\nπ Connection Information for Consumers:'); | |
| console.log(` Workspace ID: ${workspaceId}`); | |
| console.log(` Room ID: ${roomId}`); | |
| console.log('\nπ‘ You can use these IDs with the consumer example to connect to this room'); | |
| // Keep running to allow consumers to connect | |
| console.log('\nβ³ Keeping producer alive for 30 seconds...'); | |
| console.log(' (Consumers can connect during this time using the IDs above)'); | |
| const keepAliveStart = Date.now(); | |
| const keepAliveDuration = 30000; | |
| // Show countdown | |
| const countdownInterval = setInterval(() => { | |
| const elapsed = Date.now() - keepAliveStart; | |
| const remaining = Math.max(0, keepAliveDuration - elapsed); | |
| if (remaining > 0) { | |
| process.stdout.write(`\r Time remaining: ${Math.ceil(remaining / 1000)}s `); | |
| } else { | |
| process.stdout.write('\r Time is up! \n'); | |
| clearInterval(countdownInterval); | |
| } | |
| }, 1000); | |
| await new Promise(resolve => setTimeout(resolve, keepAliveDuration)); | |
| clearInterval(countdownInterval); | |
| } catch (error) { | |
| console.error('\nβ Error occurred:', error.message); | |
| if (error.stack) { | |
| console.error('Stack trace:', error.stack); | |
| } | |
| } finally { | |
| // Always disconnect and cleanup | |
| console.log('\nπ§Ή Cleaning up resources...'); | |
| if (producer.isConnected()) { | |
| console.log(' Disconnecting from room...'); | |
| await producer.disconnect(); | |
| console.log(' β Disconnected successfully'); | |
| } | |
| // Delete the room to clean up server resources | |
| if (workspaceId && roomId) { | |
| try { | |
| console.log(' Deleting room...'); | |
| const deleted = await producer.deleteRoom(workspaceId, roomId); | |
| if (deleted) { | |
| console.log(` β Room deleted: ${roomId}`); | |
| } else { | |
| console.log(` β οΈ Room may have already been deleted: ${roomId}`); | |
| } | |
| } catch (error) { | |
| console.log(` β οΈ Could not delete room: ${error.message}`); | |
| } | |
| } | |
| console.log('\nπ Producer example finished. Goodbye!'); | |
| } | |
| } | |
| // Handle Ctrl+C gracefully | |
| process.on('SIGINT', async () => { | |
| console.log('\n\nπ Received interrupt signal (Ctrl+C)'); | |
| console.log('π§Ή Shutting down gracefully...'); | |
| process.exit(0); | |
| }); | |
| // Handle uncaught errors | |
| process.on('unhandledRejection', (error) => { | |
| console.error('\nβ Unhandled promise rejection:', error); | |
| process.exit(1); | |
| }); | |
| main().catch((error) => { | |
| console.error('\nπ₯ Fatal error:', error); | |
| process.exit(1); | |
| }); |