File size: 5,014 Bytes
02eac4b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/env node
/**
 * Basic Consumer Example - LeRobot Arena
 * 
 * This example demonstrates:
 * - Connecting to an existing room as a consumer
 * - Receiving joint updates and state sync
 * - Setting up callbacks
 * - Getting current state
 */

import { RoboticsConsumer } from '../dist/robotics/index.js';
import { createInterface } from 'readline';

async function main() {
  console.log('πŸ€– LeRobot Arena Basic Consumer Example πŸ€–');

  // Get room ID from user
  const rl = createInterface({
    input: process.stdin,
    output: process.stdout
  });

  const roomId = await new Promise((resolve) => {
    rl.question('Enter room ID to connect to: ', (answer) => {
      rl.close();
      resolve(answer.trim());
    });
  });

  if (!roomId) {
    console.error('❌ Room ID is required!');
    return;
  }

  // Create consumer client
  const consumer = new RoboticsConsumer('http://localhost:8000');

  // Track received updates
  let updateCount = 0;
  let stateCount = 0;
  const receivedUpdates = [];
  const receivedStates = [];

  // Set up callbacks
  consumer.onJointUpdate((joints) => {
    updateCount++;
    console.log(`πŸ“₯ [${updateCount}] Joint update: ${joints.length} joints`);
    
    // Show joint details
    joints.forEach(joint => {
      console.log(`    ${joint.name}: ${joint.value}${joint.speed ? ` (speed: ${joint.speed})` : ''}`);
    });
    
    receivedUpdates.push(joints);
  });

  consumer.onStateSync((state) => {
    stateCount++;
    console.log(`πŸ“Š [${stateCount}] State sync: ${Object.keys(state).length} joints`);
    
    // Show state details
    Object.entries(state).forEach(([name, value]) => {
      console.log(`    ${name}: ${value}`);
    });
    
    receivedStates.push(state);
  });

  consumer.onError((errorMsg) => {
    console.error('❌ Consumer error:', errorMsg);
  });

  consumer.onConnected(() => {
    console.log('βœ… Consumer connected!');
  });

  consumer.onDisconnected(() => {
    console.log('πŸ‘‹ Consumer disconnected!');
  });

  try {
    // Connect to the room
    console.log(`\nπŸ”Œ Connecting to room ${roomId}...`);
    const success = await consumer.connect(roomId, 'demo-consumer');
    
    if (!success) {
      console.error('❌ Failed to connect to room!');
      console.log('πŸ’‘ Make sure the room exists and the server is running');
      return;
    }

    console.log(`βœ… Connected to room ${roomId} as consumer`);

    // Show connection info
    const info = consumer.getConnectionInfo();
    console.log('\nπŸ“Š Connection Info:');
    console.log(`  Room ID: ${info.room_id}`);
    console.log(`  Role: ${info.role}`);
    console.log(`  Participant ID: ${info.participant_id}`);

    // Get initial state
    console.log('\nπŸ“‹ Getting initial state...');
    const initialState = await consumer.getStateSyncAsync();
    console.log('Initial state:', Object.keys(initialState).length, 'joints');
    
    if (Object.keys(initialState).length > 0) {
      Object.entries(initialState).forEach(([name, value]) => {
        console.log(`  ${name}: ${value}`);
      });
    } else {
      console.log('  (Empty - no joints set yet)');
    }

    // Listen for updates
    console.log('\nπŸ‘‚ Listening for updates for 60 seconds...');
    console.log('   (Producer can send commands during this time)');
    
    const startTime = Date.now();
    const duration = 60000; // 60 seconds

    // Show periodic status
    const statusInterval = setInterval(() => {
      const elapsed = Date.now() - startTime;
      const remaining = Math.max(0, duration - elapsed);
      
      if (remaining > 0) {
        console.log(`\nπŸ“Š Status (${Math.floor(remaining / 1000)}s remaining):`);
        console.log(`   Updates received: ${updateCount}`);
        console.log(`   State syncs received: ${stateCount}`);
      }
    }, 10000); // Every 10 seconds

    await new Promise(resolve => setTimeout(resolve, duration));
    clearInterval(statusInterval);

    // Show final summary
    console.log('\nπŸ“Š Final Summary:');
    console.log(`   Total updates received: ${updateCount}`);
    console.log(`   Total state syncs received: ${stateCount}`);
    
    // Get final state
    const finalState = await consumer.getStateSyncAsync();
    console.log('\nπŸ“‹ Final state:');
    if (Object.keys(finalState).length > 0) {
      Object.entries(finalState).forEach(([name, value]) => {
        console.log(`  ${name}: ${value}`);
      });
    } else {
      console.log('  (Empty)');
    }

    console.log('\nβœ… Basic consumer example completed!');

  } catch (error) {
    console.error('❌ Error:', error.message);
  } finally {
    // Always disconnect
    if (consumer.isConnected()) {
      console.log('\n🧹 Disconnecting...');
      await consumer.disconnect();
    }
    console.log('πŸ‘‹ Goodbye!');
  }
}

// Handle Ctrl+C gracefully
process.on('SIGINT', () => {
  console.log('\n\nπŸ‘‹ Received SIGINT, shutting down gracefully...');
  process.exit(0);
});

main().catch(console.error);