File size: 9,724 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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# LeRobot Arena JavaScript/TypeScript Client

A modern TypeScript/JavaScript client library for LeRobot Arena robotics system, providing real-time communication for robot control and monitoring.

## Features

- πŸ€– **Producer/Consumer Pattern**: Control robots as producer, monitor as consumer
- πŸ”„ **Real-time Communication**: WebSocket-based bidirectional communication
- πŸ“‘ **REST API Support**: Complete CRUD operations for rooms and state
- 🎯 **Type Safety**: Full TypeScript support with comprehensive type definitions
- 🚨 **Safety Features**: Emergency stop functionality built-in
- πŸ”§ **Modular Design**: Import only what you need
- πŸ§ͺ **Well Tested**: Comprehensive test suite with Bun test

## Installation

```bash
# Install the package (when published)
npm install lerobot-arena-client

# Or for local development
git clone <repository>
cd client/js
bun install
bun run build
```

## Quick Start

### Producer (Robot Controller)

```typescript
import { RoboticsProducer, createProducerClient } from 'lerobot-arena-client';

// Method 1: Manual setup
const producer = new RoboticsProducer('http://localhost:8000');
const roomId = await producer.createRoom();
await producer.connect(roomId);

// Method 2: Factory function (recommended)
const producer = await createProducerClient('http://localhost:8000');

// Send robot commands
await producer.sendJointUpdate([
  { name: 'shoulder', value: 45.0 },
  { name: 'elbow', value: -30.0 }
]);

// Send complete state
await producer.sendStateSync({
  base: 0.0,
  shoulder: 45.0,
  elbow: -30.0,
  wrist: 0.0
});

// Emergency stop
await producer.sendEmergencyStop('Safety stop triggered');
```

### Consumer (Robot Monitor)

```typescript
import { RoboticsConsumer, createConsumerClient } from 'lerobot-arena-client';

// Connect to existing room
const consumer = await createConsumerClient(roomId, 'http://localhost:8000');

// Set up event listeners
consumer.onJointUpdate((joints) => {
  console.log('Joints updated:', joints);
});

consumer.onStateSync((state) => {
  console.log('State synced:', state);
});

consumer.onError((error) => {
  console.error('Error:', error);
});

// Get current state
const currentState = await consumer.getStateSyncAsync();
```

## API Reference

### Core Classes

#### `RoboticsClientCore`
Base class providing common functionality:

```typescript
// REST API methods
await client.listRooms();
await client.createRoom(roomId?);
await client.deleteRoom(roomId);
await client.getRoomInfo(roomId);
await client.getRoomState(roomId);

// Connection management
await client.connectToRoom(roomId, role, participantId?);
await client.disconnect();
client.isConnected();
client.getConnectionInfo();

// Utility
await client.sendHeartbeat();
```

#### `RoboticsProducer`
Producer-specific functionality:

```typescript
const producer = new RoboticsProducer('http://localhost:8000');

// Connection
await producer.connect(roomId, participantId?);

// Commands
await producer.sendJointUpdate(joints);
await producer.sendStateSync(state);
await producer.sendEmergencyStop(reason?);

// Static factory
const producer = await RoboticsProducer.createAndConnect(baseUrl, roomId?, participantId?);
```

#### `RoboticsConsumer`
Consumer-specific functionality:

```typescript
const consumer = new RoboticsConsumer('http://localhost:8000');

// Connection
await consumer.connect(roomId, participantId?);

// Data access
await consumer.getStateSyncAsync();

// Event callbacks
consumer.onJointUpdate(callback);
consumer.onStateSync(callback);
consumer.onError(callback);
consumer.onConnected(callback);
consumer.onDisconnected(callback);

// Static factory
const consumer = await RoboticsConsumer.createAndConnect(roomId, baseUrl, participantId?);
```

### Factory Functions

```typescript
import { createClient, createProducerClient, createConsumerClient } from 'lerobot-arena-client';

// Generic factory
const client = createClient('producer', 'http://localhost:8000');

// Specialized factories (auto-connect)
const producer = await createProducerClient('http://localhost:8000', roomId?, participantId?);
const consumer = await createConsumerClient(roomId, 'http://localhost:8000', participantId?);
```

### Type Definitions

```typescript
interface JointData {
  name: string;
  value: number;
  speed?: number;
}

interface RoomInfo {
  id: string;
  participants: {
    producer: string | null;
    consumers: string[];
    total: number;
  };
  joints_count: number;
  has_producer?: boolean;
  active_consumers?: number;
}

interface RoomState {
  room_id: string;
  joints: Record<string, number>;
  participants: {
    producer: string | null;
    consumers: string[];
    total: number;
  };
  timestamp: string;
}

type ParticipantRole = 'producer' | 'consumer';
type MessageType = 'joint_update' | 'state_sync' | 'heartbeat' | 'emergency_stop' | 'joined' | 'error';
```

## Examples

The `examples/` directory contains complete working examples:

### Running Examples

```bash
# Build the library first
bun run build

# Run producer example
node examples/basic-producer.js

# Run consumer example (in another terminal)
node examples/basic-consumer.js
```

### Example Files

- **`basic-producer.js`**: Complete producer workflow
- **`basic-consumer.js`**: Interactive consumer example
- **`room-management.js`**: REST API operations
- **`producer-consumer-demo.js`**: Full integration demo

## Development

### Prerequisites

- [Bun](https://bun.sh/) >= 1.0.0
- LeRobot Arena server running on `http://localhost:8000`

### Setup

```bash
# Clone and install
git clone <repository>
cd client/js
bun install

# Development build (watch mode)
bun run dev

# Production build
bun run build

# Run tests
bun test

# Type checking
bun run typecheck

# Linting
bun run lint
bun run lint:fix
```

### Testing

The library includes comprehensive tests:

```bash
# Run all tests
bun test

# Run specific test files
bun test tests/producer.test.ts
bun test tests/consumer.test.ts
bun test tests/integration.test.ts
bun test tests/rest-api.test.ts

# Run tests with coverage
bun test --coverage
```

### Project Structure

```
client/js/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.ts              # Main entry point
β”‚   β”œβ”€β”€ robotics/
β”‚   β”‚   β”œβ”€β”€ index.ts          # Robotics module exports
β”‚   β”‚   β”œβ”€β”€ types.ts          # TypeScript type definitions
β”‚   β”‚   β”œβ”€β”€ core.ts           # Base client class
β”‚   β”‚   β”œβ”€β”€ producer.ts       # Producer client
β”‚   β”‚   β”œβ”€β”€ consumer.ts       # Consumer client
β”‚   β”‚   └── factory.ts        # Factory functions
β”‚   β”œβ”€β”€ video/               # Video module (placeholder)
β”‚   └── audio/               # Audio module (placeholder)
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ producer.test.ts      # Producer tests
β”‚   β”œβ”€β”€ consumer.test.ts      # Consumer tests
β”‚   β”œβ”€β”€ integration.test.ts   # Integration tests
β”‚   └── rest-api.test.ts      # REST API tests
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ basic-producer.js     # Producer example
β”‚   β”œβ”€β”€ basic-consumer.js     # Consumer example
β”‚   └── README.md            # Examples documentation
β”œβ”€β”€ dist/                    # Built output
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ vite.config.ts
└── README.md
```

## Error Handling

The client provides comprehensive error handling:

```typescript
// Connection errors
try {
  await producer.connect(roomId);
} catch (error) {
  console.error('Connection failed:', error.message);
}

// Operation errors
producer.onError((error) => {
  console.error('Producer error:', error);
});

// Network timeouts
const options = { timeout: 10000 }; // 10 seconds
const client = new RoboticsProducer('http://localhost:8000', options);
```

## Configuration

### Client Options

```typescript
interface ClientOptions {
  timeout?: number;           // Request timeout (default: 5000ms)
  reconnect_attempts?: number; // Auto-reconnect attempts (default: 3)
  heartbeat_interval?: number; // Heartbeat interval (default: 30000ms)
}

const producer = new RoboticsProducer('http://localhost:8000', {
  timeout: 10000,
  reconnect_attempts: 5,
  heartbeat_interval: 15000
});
```

## Troubleshooting

### Common Issues

1. **Connection Failed**: Ensure the server is running on `http://localhost:8000`
2. **Import Errors**: Make sure you've built the library (`bun run build`)
3. **Room Not Found**: Check that the room ID exists
4. **Permission Denied**: Only one producer per room is allowed
5. **WebSocket Errors**: Check firewall settings and network connectivity

### Debug Mode

Enable detailed logging:

```typescript
// Set up detailed error handling
producer.onError((error) => {
  console.error('Detailed error:', error);
});

// Monitor connection events
producer.onConnected(() => console.log('Connected'));
producer.onDisconnected(() => console.log('Disconnected'));
```

### Performance Tips

- Use the factory functions for simpler setup
- Batch joint updates when possible
- Monitor connection state before sending commands
- Implement proper cleanup in your applications

## Contributing

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/amazing-feature`
3. Make your changes and add tests
4. Run the test suite: `bun test`
5. Commit your changes: `git commit -m 'Add amazing feature'`
6. Push to the branch: `git push origin feature/amazing-feature`
7. Open a Pull Request

## License

MIT License - see LICENSE file for details

## Support

- πŸ“š [Documentation](./examples/README.md)
- πŸ› [Issue Tracker](https://github.com/lerobot-arena/lerobot-arena/issues)
- πŸ’¬ [Discussions](https://github.com/lerobot-arena/lerobot-arena/discussions)