jmri-client
v4.1.1
Published
WebSocket client for JMRI with real-time updates and throttle control - works in both Node.js and browsers
Maintainers
Readme
jmri-client
WebSocket client for JMRI with real-time updates and full throttle control.
Features
- ✅ WebSocket-based - Real-time bidirectional communication
- ✅ Event-driven - Subscribe to power changes, throttle updates, and more
- ✅ Full Throttle Control - Speed (0.0-1.0), direction, and functions (F0-F28)
- ✅ Browser & Node.js - Works in browsers and Node.js with auto-detection
- ✅ Mock Mode - Test and demo without JMRI hardware
- ✅ Auto-reconnection - Exponential backoff with jitter
- ✅ Heartbeat monitoring - Automatic ping/pong keepalive
- ✅ TypeScript - Full type definitions included
- ✅ Dual module support - ESM and CommonJS
- ✅ Extensible - Subclass
JmriClientto add support for additional JMRI object types
Installation
npm install jmri-clientRequirements: Node.js 18+
Quick Start
import { JmriClient, PowerState } from 'jmri-client';
// Create client
const client = new JmriClient({
host: 'jmri.local',
port: 12080
});
// Listen for events
client.on('connected', () => console.log('Connected!'));
client.on('power:changed', (state) => {
const stateStr = state === PowerState.ON ? 'ON' :
state === PowerState.OFF ? 'OFF' : 'UNKNOWN';
console.log('Power:', stateStr);
});
// Control power
await client.powerOn();
// Acquire and control a throttle
const throttleId = await client.acquireThrottle({ address: 3 });
await client.setThrottleSpeed(throttleId, 0.5); // 50% speed
await client.setThrottleDirection(throttleId, true); // Forward
await client.setThrottleFunction(throttleId, 'F0', true); // Headlight on
// Clean up
await client.releaseThrottle(throttleId);
await client.disconnect();Documentation
- API Reference - Complete API documentation
- Browser Usage - Using jmri-client in web browsers
- Examples - Common usage patterns
- Mock Mode - Testing without hardware
- Migration Guide - Upgrading from v2.x
- Troubleshooting - Common issues and solutions
Key Concepts
Event-Driven Architecture
Subscribe to real-time updates from JMRI:
client.on('connected', () => { });
client.on('disconnected', (reason) => { });
client.on('power:changed', (state) => { });
client.on('throttle:updated', (id, data) => { });Throttle Control
Full control of DCC locomotives:
const throttle = await client.acquireThrottle({ address: 3 });
await client.setThrottleSpeed(throttle, 0.5);
await client.setThrottleDirection(throttle, true);
await client.setThrottleFunction(throttle, 'F0', true);
await client.releaseThrottle(throttle);Auto-Reconnection
Automatically reconnects with exponential backoff:
client.on('reconnecting', (attempt, delay) => {
console.log(`Reconnecting attempt ${attempt} in ${delay}ms`);
});Extending JmriClient
JmriClient exposes its wsClient as protected, so you can subclass it to add support for JMRI object types not yet built in (e.g., sensors, lights, routes, blocks):
import { JmriClient } from 'jmri-client';
import type { PartialClientOptions } from 'jmri-client';
class MyExtendedClient extends JmriClient {
constructor(options?: PartialClientOptions) {
super(options);
// this.wsClient is available — use it to send/receive JMRI JSON messages
this.wsClient.on('update', (message: any) => {
if (message.type === 'sensor') {
this.emit('sensor:changed', message.data.name, message.data.state);
}
});
}
async listSensors() {
const response = await this.wsClient.request({ type: 'sensor', method: 'list' });
return Array.isArray(response?.data)
? response.data.map((r: any) => r.data ?? r)
: [];
}
}WebSocketClient is also exported for direct use if you need it. See its send(), request(), and on('update', ...) API for low-level messaging.
Testing
Unit Tests (no hardware required):
npm testMock Mode Demo (no hardware required):
npm run demo:mockFunctional Test (requires JMRI hardware):
npm run functional⚠️ Safety: Includes automatic power-off on exit, errors, and Ctrl+C.
See Mock Mode Guide and Testing Guide for complete instructions.
Contributing
Issues and pull requests welcome! Please see the GitHub repository.
License
MIT

