@xiboplayer/xmr
v0.2.0
Published
XMR WebSocket client for real-time Xibo CMS commands
Maintainers
Readme
@xiboplayer/xmr Documentation
XMR (Xibo Message Relay) WebSocket client for real-time CMS commands.
Overview
The XMR package provides WebSocket integration with Xibo CMS, enabling real-time push commands from CMS to player without polling.
Key Features
- Real-time commands: Instant content updates via WebSocket
- Automatic reconnection: Exponential backoff with max 10 attempts
- Connection management: Handles disconnects, errors, and network issues
- 7 CMS commands: collectNow, screenShot, changeLayout, criteriaUpdate, and more
- Event-driven: Clean event-based API for command handling
- Memory efficient: Proper cleanup of timers and event listeners
- Production ready: Comprehensive test suite with 48 test cases
Installation
npm install @xiboplayer/xmrQuick Start
import { XmrWrapper } from '@xiboplayer/xmr';
// Create wrapper
const config = {
cmsAddress: 'https://cms.example.com',
hardwareKey: 'player-hw-key-123',
xmrChannel: 'player-channel' // Optional, defaults to player-{hardwareKey}
};
const player = {
collect: async () => { /* ... */ },
captureScreenshot: async () => { /* ... */ },
changeLayout: async (layoutId) => { /* ... */ },
reportGeoLocation: async (data) => { /* ... */ },
updateStatus: (status) => { /* ... */ }
};
const xmr = new XmrWrapper(config, player);
// Start connection
const connected = await xmr.start('wss://cms.example.com:9505', 'cms-key-123');
if (connected) {
console.log('XMR connected');
}
// Check connection status
if (xmr.isConnected()) {
console.log('Currently connected');
}
// Stop connection
await xmr.stop();Supported Commands
Core Commands
| Command | Description | Player Method |
|---------|-------------|---------------|
| collectNow | Force immediate XMDS sync | player.collect() |
| screenShot | Capture screenshot | player.captureScreenshot() |
| changeLayout | Switch to specific layout | player.changeLayout(layoutId) |
| licenceCheck | Validate license (no-op for Linux) | None |
| rekey | Rotate RSA keys | None (future) |
New in v0.0.6
| Command | Description | Player Method |
|---------|-------------|---------------|
| criteriaUpdate | Update display criteria | player.collect() |
| currentGeoLocation | Report geo location | player.reportGeoLocation(data) |
See XMR_COMMANDS.md for complete command reference.
Connection Lifecycle
┌──────────┐
│ start() │
└─────┬────┘
│
▼
┌──────────┐
┌─────│Connected │◄─────┐
│ └─────┬────┘ │
│ │ │
Network │ │Commands │Auto
Error │ │Flowing │Reconnect
│ │ │
▼ ▼ │
┌──────────┐ ┌──────────┐
│Disconnect│────────────│Reconnect │
└─────┬────┘ Backoff └──────────┘
│
│stop()
▼
┌──────────┐
│ Stopped │
└──────────┘Reconnection Logic
- Exponential backoff: 5s, 10s, 15s, 20s, 25s, 30s, 35s, 40s, 45s, 50s
- Max attempts: 10 (then waits for next collection cycle)
- Intentional shutdown: No reconnect when
stop()is called - Connection events:
connected,disconnected,error
API Reference
XmrWrapper
Constructor
new XmrWrapper(config, player)Parameters:
config(Object): Player configurationhardwareKey(string): Player hardware keyxmrChannel(string, optional): Custom channel ID
player(Object): Player instance with command handlers
Methods
start(xmrUrl, cmsKey)
Start XMR connection.
await xmr.start('wss://cms.example.com:9505', 'cms-key-123');Returns: Promise<boolean> - True if connected, false if failed
stop()
Stop XMR connection and cancel reconnection.
await xmr.stop();isConnected()
Check connection status.
const connected = xmr.isConnected();Returns: boolean
send(action, data)
Send message to CMS (for future features).
await xmr.send('customAction', { key: 'value' });Returns: Promise<boolean> - True if sent successfully
Player Interface
Your player object should implement these methods:
{
// Required
collect: async () => Promise<void>,
captureScreenshot: async () => Promise<void>,
changeLayout: async (layoutId) => Promise<void>,
// Optional
reportGeoLocation: async (data) => Promise<void>,
updateStatus: (status) => void
}Testing
Run Tests
# Run all tests
npm test
# Watch mode
npm run test:watch
# Coverage report
npm run test:coverageTest Coverage
- ✅ 48 test cases
- ✅ Constructor and initialization
- ✅ Connection lifecycle (start, stop, reconnect)
- ✅ All 7 CMS commands
- ✅ Error handling and edge cases
- ✅ Memory management and cleanup
See XMR_TESTING.md for comprehensive testing guide.
Configuration
From registerDisplay
XMR settings are typically received from CMS registerDisplay response:
{
"settings": {
"xmrWebSocketAddress": "wss://cms.example.com:9505",
"xmrCmsKey": "abcdef123456",
"xmrChannel": "player-hw-key-123"
}
}Use these values with start():
const { xmrWebSocketAddress, xmrCmsKey } = settings;
await xmr.start(xmrWebSocketAddress, xmrCmsKey);Custom Channel
Override default channel (player-{hardwareKey}):
const config = {
hardwareKey: 'hw-123',
xmrChannel: 'custom-channel-name' // Use this instead
};Error Handling
All command handlers include error handling:
this.xmr.on('collectNow', async () => {
console.log('[XMR] Received collectNow command');
try {
await this.player.collect();
console.log('[XMR] collectNow completed successfully');
} catch (error) {
console.error('[XMR] collectNow failed:', error);
}
});Errors don't:
- ❌ Crash the player
- ❌ Disconnect XMR
- ❌ Prevent other commands
They do:
- ✅ Log to console
- ✅ Preserve connection state
- ✅ Continue processing other commands
Troubleshooting
Connection Issues
Problem: XMR won't connect
Solution:
- Verify XMR enabled in CMS settings
- Check firewall allows port 9505
- Verify
xmrWebSocketAddressfrom registerDisplay - Check browser console for errors
Commands Not Executing
Problem: collectNow sent but nothing happens
Solution:
- Check
xmr.isConnected()returns true - Verify player methods exist (
player.collect, etc.) - Check console for command reception logs
- Look for errors in command handler
Reconnection Loops
Problem: Keeps reconnecting forever
Solution:
- Verify XMR server is running
- Check cmsKey is correct
- Monitor
reconnectAttemptscounter - Manually stop:
await xmr.stop()
See XMR_TESTING.md for more.
Dependencies
@xibosignage/xibo-communication-framework@^0.0.6- Official XMR library@xiboplayer/utils- Logging and utilities
Version History
v0.9.0 (Current)
- ✅ Upgraded to @xibosignage/[email protected]
- ✅ Added
criteriaUpdatecommand - ✅ Added
currentGeoLocationcommand - ✅ Intentional shutdown flag (no reconnect on stop)
- ✅ Comprehensive test suite (48 tests)
- ✅ Complete documentation
Previous Versions
- Basic XMR integration
- Core commands (collectNow, screenShot, changeLayout)
- Automatic reconnection
Contributing
When adding new XMR commands:
- Add event handler in
setupEventHandlers() - Update XMR_COMMANDS.md
- Add tests in
xmr-wrapper.test.js - Implement player method if needed
See XMR_TESTING.md for details.
Related Packages
- @xiboplayer/core - Player core orchestration
- @xiboplayer/xmds - XMDS SOAP client
- @xiboplayer/schedule - Schedule engine
Support
- GitHub Issues: https://github.com/xibo/xibo-players/issues
- Documentation: XMR_COMMANDS.md, XMR_TESTING.md
- Xibo Community: https://community.xibo.org.uk
Package Version: 0.9.0 | XMR Library: 0.0.6
License
AGPL-3.0-or-later
