@xiboplayer/xmr 0.1.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +48 -0
- package/package.json +2 -2
- package/src/index.js +2 -0
- package/docs/README.md +0 -360
package/CHANGELOG.md
CHANGED
|
@@ -159,7 +159,7 @@ await xmr.stop(); // Clean shutdown, no reconnection
|
|
|
159
159
|
|
|
160
160
|
## Support
|
|
161
161
|
|
|
162
|
-
- **Documentation**: [
|
|
162
|
+
- **Documentation**: [README.md](./README.md)
|
|
163
163
|
- **GitHub Issues**: https://github.com/xibo/xibo-players/issues
|
|
164
164
|
- **Community**: https://community.xibo.org.uk
|
|
165
165
|
|
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# @xiboplayer/xmr
|
|
2
|
+
|
|
3
|
+
**XMR WebSocket client for real-time Xibo CMS commands.**
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Listens for push commands from the CMS over WebSocket with automatic reconnection:
|
|
8
|
+
|
|
9
|
+
- **collectNow** — trigger an immediate collection cycle
|
|
10
|
+
- **screenshot** — request a display screenshot
|
|
11
|
+
- **changeLayout** — switch to a specific layout
|
|
12
|
+
- **overlayLayout** — show an overlay layout
|
|
13
|
+
- **revertToSchedule** — return to the scheduled playlist
|
|
14
|
+
- **purgeAll** — clear all cached content
|
|
15
|
+
- **dataUpdate** — notify of updated widget data
|
|
16
|
+
- **triggerWebhook** — fire a webhook action
|
|
17
|
+
- **commandAction** — execute a shell command
|
|
18
|
+
- **criteriaUpdate** — update geo/criteria filters
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @xiboplayer/xmr
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
import { XmrClient } from '@xiboplayer/xmr';
|
|
30
|
+
|
|
31
|
+
const xmr = new XmrClient({
|
|
32
|
+
wsUrl: 'wss://your-cms.example.com/xmr',
|
|
33
|
+
channel: 'display-channel-key',
|
|
34
|
+
rsaKey: 'display-rsa-key',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
xmr.on('collectNow', () => player.collect());
|
|
38
|
+
xmr.on('screenshot', () => captureScreenshot());
|
|
39
|
+
xmr.connect();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Dependencies
|
|
43
|
+
|
|
44
|
+
- `@xiboplayer/utils` — logger, events
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
**Part of the [XiboPlayer SDK](https://github.com/linuxnow/xiboplayer)**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xiboplayer/xmr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "XMR WebSocket client for real-time Xibo CMS commands",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@xibosignage/xibo-communication-framework": "^0.0.6",
|
|
12
|
-
"@xiboplayer/utils": "0.
|
|
12
|
+
"@xiboplayer/utils": "0.3.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"vitest": "^2.0.0"
|
package/src/index.js
CHANGED
package/docs/README.md
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
# @xiboplayer/xmr Documentation
|
|
2
|
-
|
|
3
|
-
**XMR (Xibo Message Relay) WebSocket client for real-time CMS commands.**
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The XMR package provides WebSocket integration with Xibo CMS, enabling real-time push commands from CMS to player without polling.
|
|
8
|
-
|
|
9
|
-
### Key Features
|
|
10
|
-
|
|
11
|
-
- **Real-time commands**: Instant content updates via WebSocket
|
|
12
|
-
- **Automatic reconnection**: Exponential backoff with max 10 attempts
|
|
13
|
-
- **Connection management**: Handles disconnects, errors, and network issues
|
|
14
|
-
- **7 CMS commands**: collectNow, screenShot, changeLayout, criteriaUpdate, and more
|
|
15
|
-
- **Event-driven**: Clean event-based API for command handling
|
|
16
|
-
- **Memory efficient**: Proper cleanup of timers and event listeners
|
|
17
|
-
- **Production ready**: Comprehensive test suite with 48 test cases
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
npm install @xiboplayer/xmr
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Quick Start
|
|
26
|
-
|
|
27
|
-
```javascript
|
|
28
|
-
import { XmrWrapper } from '@xiboplayer/xmr';
|
|
29
|
-
|
|
30
|
-
// Create wrapper
|
|
31
|
-
const config = {
|
|
32
|
-
cmsAddress: 'https://cms.example.com',
|
|
33
|
-
hardwareKey: 'player-hw-key-123',
|
|
34
|
-
xmrChannel: 'player-channel' // Optional, defaults to player-{hardwareKey}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const player = {
|
|
38
|
-
collect: async () => { /* ... */ },
|
|
39
|
-
captureScreenshot: async () => { /* ... */ },
|
|
40
|
-
changeLayout: async (layoutId) => { /* ... */ },
|
|
41
|
-
reportGeoLocation: async (data) => { /* ... */ },
|
|
42
|
-
updateStatus: (status) => { /* ... */ }
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const xmr = new XmrWrapper(config, player);
|
|
46
|
-
|
|
47
|
-
// Start connection
|
|
48
|
-
const connected = await xmr.start('wss://cms.example.com:9505', 'cms-key-123');
|
|
49
|
-
|
|
50
|
-
if (connected) {
|
|
51
|
-
console.log('XMR connected');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Check connection status
|
|
55
|
-
if (xmr.isConnected()) {
|
|
56
|
-
console.log('Currently connected');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Stop connection
|
|
60
|
-
await xmr.stop();
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Supported Commands
|
|
64
|
-
|
|
65
|
-
### Core Commands
|
|
66
|
-
|
|
67
|
-
| Command | Description | Player Method |
|
|
68
|
-
|---------|-------------|---------------|
|
|
69
|
-
| `collectNow` | Force immediate XMDS sync | `player.collect()` |
|
|
70
|
-
| `screenShot` | Capture screenshot | `player.captureScreenshot()` |
|
|
71
|
-
| `changeLayout` | Switch to specific layout | `player.changeLayout(layoutId)` |
|
|
72
|
-
| `licenceCheck` | Validate license (no-op for Linux) | None |
|
|
73
|
-
| `rekey` | Rotate RSA keys | None (future) |
|
|
74
|
-
|
|
75
|
-
### New in v0.0.6
|
|
76
|
-
|
|
77
|
-
| Command | Description | Player Method |
|
|
78
|
-
|---------|-------------|---------------|
|
|
79
|
-
| `criteriaUpdate` | Update display criteria | `player.collect()` |
|
|
80
|
-
| `currentGeoLocation` | Report geo location | `player.reportGeoLocation(data)` |
|
|
81
|
-
|
|
82
|
-
See [XMR_COMMANDS.md](./XMR_COMMANDS.md) for complete command reference.
|
|
83
|
-
|
|
84
|
-
## Connection Lifecycle
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
┌──────────┐
|
|
88
|
-
│ start() │
|
|
89
|
-
└─────┬────┘
|
|
90
|
-
│
|
|
91
|
-
▼
|
|
92
|
-
┌──────────┐
|
|
93
|
-
┌─────│Connected │◄─────┐
|
|
94
|
-
│ └─────┬────┘ │
|
|
95
|
-
│ │ │
|
|
96
|
-
Network │ │Commands │Auto
|
|
97
|
-
Error │ │Flowing │Reconnect
|
|
98
|
-
│ │ │
|
|
99
|
-
▼ ▼ │
|
|
100
|
-
┌──────────┐ ┌──────────┐
|
|
101
|
-
│Disconnect│────────────│Reconnect │
|
|
102
|
-
└─────┬────┘ Backoff └──────────┘
|
|
103
|
-
│
|
|
104
|
-
│stop()
|
|
105
|
-
▼
|
|
106
|
-
┌──────────┐
|
|
107
|
-
│ Stopped │
|
|
108
|
-
└──────────┘
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### Reconnection Logic
|
|
112
|
-
|
|
113
|
-
- **Exponential backoff**: 5s, 10s, 15s, 20s, 25s, 30s, 35s, 40s, 45s, 50s
|
|
114
|
-
- **Max attempts**: 10 (then waits for next collection cycle)
|
|
115
|
-
- **Intentional shutdown**: No reconnect when `stop()` is called
|
|
116
|
-
- **Connection events**: `connected`, `disconnected`, `error`
|
|
117
|
-
|
|
118
|
-
## API Reference
|
|
119
|
-
|
|
120
|
-
### XmrWrapper
|
|
121
|
-
|
|
122
|
-
#### Constructor
|
|
123
|
-
|
|
124
|
-
```javascript
|
|
125
|
-
new XmrWrapper(config, player)
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
**Parameters**:
|
|
129
|
-
- `config` (Object): Player configuration
|
|
130
|
-
- `hardwareKey` (string): Player hardware key
|
|
131
|
-
- `xmrChannel` (string, optional): Custom channel ID
|
|
132
|
-
- `player` (Object): Player instance with command handlers
|
|
133
|
-
|
|
134
|
-
#### Methods
|
|
135
|
-
|
|
136
|
-
##### start(xmrUrl, cmsKey)
|
|
137
|
-
|
|
138
|
-
Start XMR connection.
|
|
139
|
-
|
|
140
|
-
```javascript
|
|
141
|
-
await xmr.start('wss://cms.example.com:9505', 'cms-key-123');
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
**Returns**: `Promise<boolean>` - True if connected, false if failed
|
|
145
|
-
|
|
146
|
-
##### stop()
|
|
147
|
-
|
|
148
|
-
Stop XMR connection and cancel reconnection.
|
|
149
|
-
|
|
150
|
-
```javascript
|
|
151
|
-
await xmr.stop();
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
##### isConnected()
|
|
155
|
-
|
|
156
|
-
Check connection status.
|
|
157
|
-
|
|
158
|
-
```javascript
|
|
159
|
-
const connected = xmr.isConnected();
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
**Returns**: `boolean`
|
|
163
|
-
|
|
164
|
-
##### send(action, data)
|
|
165
|
-
|
|
166
|
-
Send message to CMS (for future features).
|
|
167
|
-
|
|
168
|
-
```javascript
|
|
169
|
-
await xmr.send('customAction', { key: 'value' });
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
**Returns**: `Promise<boolean>` - True if sent successfully
|
|
173
|
-
|
|
174
|
-
### Player Interface
|
|
175
|
-
|
|
176
|
-
Your player object should implement these methods:
|
|
177
|
-
|
|
178
|
-
```javascript
|
|
179
|
-
{
|
|
180
|
-
// Required
|
|
181
|
-
collect: async () => Promise<void>,
|
|
182
|
-
captureScreenshot: async () => Promise<void>,
|
|
183
|
-
changeLayout: async (layoutId) => Promise<void>,
|
|
184
|
-
|
|
185
|
-
// Optional
|
|
186
|
-
reportGeoLocation: async (data) => Promise<void>,
|
|
187
|
-
updateStatus: (status) => void
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## Testing
|
|
192
|
-
|
|
193
|
-
### Run Tests
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
# Run all tests
|
|
197
|
-
npm test
|
|
198
|
-
|
|
199
|
-
# Watch mode
|
|
200
|
-
npm run test:watch
|
|
201
|
-
|
|
202
|
-
# Coverage report
|
|
203
|
-
npm run test:coverage
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### Test Coverage
|
|
207
|
-
|
|
208
|
-
- ✅ 48 test cases
|
|
209
|
-
- ✅ Constructor and initialization
|
|
210
|
-
- ✅ Connection lifecycle (start, stop, reconnect)
|
|
211
|
-
- ✅ All 7 CMS commands
|
|
212
|
-
- ✅ Error handling and edge cases
|
|
213
|
-
- ✅ Memory management and cleanup
|
|
214
|
-
|
|
215
|
-
See [XMR_TESTING.md](./XMR_TESTING.md) for comprehensive testing guide.
|
|
216
|
-
|
|
217
|
-
## Configuration
|
|
218
|
-
|
|
219
|
-
### From registerDisplay
|
|
220
|
-
|
|
221
|
-
XMR settings are typically received from CMS `registerDisplay` response:
|
|
222
|
-
|
|
223
|
-
```json
|
|
224
|
-
{
|
|
225
|
-
"settings": {
|
|
226
|
-
"xmrWebSocketAddress": "wss://cms.example.com:9505",
|
|
227
|
-
"xmrCmsKey": "abcdef123456",
|
|
228
|
-
"xmrChannel": "player-hw-key-123"
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
Use these values with `start()`:
|
|
234
|
-
|
|
235
|
-
```javascript
|
|
236
|
-
const { xmrWebSocketAddress, xmrCmsKey } = settings;
|
|
237
|
-
await xmr.start(xmrWebSocketAddress, xmrCmsKey);
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Custom Channel
|
|
241
|
-
|
|
242
|
-
Override default channel (player-{hardwareKey}):
|
|
243
|
-
|
|
244
|
-
```javascript
|
|
245
|
-
const config = {
|
|
246
|
-
hardwareKey: 'hw-123',
|
|
247
|
-
xmrChannel: 'custom-channel-name' // Use this instead
|
|
248
|
-
};
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
## Error Handling
|
|
252
|
-
|
|
253
|
-
All command handlers include error handling:
|
|
254
|
-
|
|
255
|
-
```javascript
|
|
256
|
-
this.xmr.on('collectNow', async () => {
|
|
257
|
-
console.log('[XMR] Received collectNow command');
|
|
258
|
-
try {
|
|
259
|
-
await this.player.collect();
|
|
260
|
-
console.log('[XMR] collectNow completed successfully');
|
|
261
|
-
} catch (error) {
|
|
262
|
-
console.error('[XMR] collectNow failed:', error);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
Errors don't:
|
|
268
|
-
- ❌ Crash the player
|
|
269
|
-
- ❌ Disconnect XMR
|
|
270
|
-
- ❌ Prevent other commands
|
|
271
|
-
|
|
272
|
-
They do:
|
|
273
|
-
- ✅ Log to console
|
|
274
|
-
- ✅ Preserve connection state
|
|
275
|
-
- ✅ Continue processing other commands
|
|
276
|
-
|
|
277
|
-
## Troubleshooting
|
|
278
|
-
|
|
279
|
-
### Connection Issues
|
|
280
|
-
|
|
281
|
-
**Problem**: XMR won't connect
|
|
282
|
-
|
|
283
|
-
**Solution**:
|
|
284
|
-
1. Verify XMR enabled in CMS settings
|
|
285
|
-
2. Check firewall allows port 9505
|
|
286
|
-
3. Verify `xmrWebSocketAddress` from registerDisplay
|
|
287
|
-
4. Check browser console for errors
|
|
288
|
-
|
|
289
|
-
### Commands Not Executing
|
|
290
|
-
|
|
291
|
-
**Problem**: collectNow sent but nothing happens
|
|
292
|
-
|
|
293
|
-
**Solution**:
|
|
294
|
-
1. Check `xmr.isConnected()` returns true
|
|
295
|
-
2. Verify player methods exist (`player.collect`, etc.)
|
|
296
|
-
3. Check console for command reception logs
|
|
297
|
-
4. Look for errors in command handler
|
|
298
|
-
|
|
299
|
-
### Reconnection Loops
|
|
300
|
-
|
|
301
|
-
**Problem**: Keeps reconnecting forever
|
|
302
|
-
|
|
303
|
-
**Solution**:
|
|
304
|
-
1. Verify XMR server is running
|
|
305
|
-
2. Check cmsKey is correct
|
|
306
|
-
3. Monitor `reconnectAttempts` counter
|
|
307
|
-
4. Manually stop: `await xmr.stop()`
|
|
308
|
-
|
|
309
|
-
See [XMR_TESTING.md](./XMR_TESTING.md#troubleshooting) for more.
|
|
310
|
-
|
|
311
|
-
## Dependencies
|
|
312
|
-
|
|
313
|
-
- `@xibosignage/xibo-communication-framework@^0.0.6` - Official XMR library
|
|
314
|
-
- `@xiboplayer/utils` - Logging and utilities
|
|
315
|
-
|
|
316
|
-
## Version History
|
|
317
|
-
|
|
318
|
-
### v0.9.0 (Current)
|
|
319
|
-
- ✅ Upgraded to @xibosignage/xibo-communication-framework@0.0.6
|
|
320
|
-
- ✅ Added `criteriaUpdate` command
|
|
321
|
-
- ✅ Added `currentGeoLocation` command
|
|
322
|
-
- ✅ Intentional shutdown flag (no reconnect on stop)
|
|
323
|
-
- ✅ Comprehensive test suite (48 tests)
|
|
324
|
-
- ✅ Complete documentation
|
|
325
|
-
|
|
326
|
-
### Previous Versions
|
|
327
|
-
- Basic XMR integration
|
|
328
|
-
- Core commands (collectNow, screenShot, changeLayout)
|
|
329
|
-
- Automatic reconnection
|
|
330
|
-
|
|
331
|
-
## Contributing
|
|
332
|
-
|
|
333
|
-
When adding new XMR commands:
|
|
334
|
-
|
|
335
|
-
1. Add event handler in `setupEventHandlers()`
|
|
336
|
-
2. Update [XMR_COMMANDS.md](./XMR_COMMANDS.md)
|
|
337
|
-
3. Add tests in `xmr-wrapper.test.js`
|
|
338
|
-
4. Implement player method if needed
|
|
339
|
-
|
|
340
|
-
See [XMR_TESTING.md](./XMR_TESTING.md#adding-new-commands) for details.
|
|
341
|
-
|
|
342
|
-
## Related Packages
|
|
343
|
-
|
|
344
|
-
- [@xiboplayer/core](../../core/docs/) - Player core orchestration
|
|
345
|
-
- [@xiboplayer/xmds](../../xmds/docs/) - XMDS SOAP client
|
|
346
|
-
- [@xiboplayer/schedule](../../schedule/docs/) - Schedule engine
|
|
347
|
-
|
|
348
|
-
## Support
|
|
349
|
-
|
|
350
|
-
- **GitHub Issues**: https://github.com/xibo/xibo-players/issues
|
|
351
|
-
- **Documentation**: [XMR_COMMANDS.md](./XMR_COMMANDS.md), [XMR_TESTING.md](./XMR_TESTING.md)
|
|
352
|
-
- **Xibo Community**: https://community.xibo.org.uk
|
|
353
|
-
|
|
354
|
-
---
|
|
355
|
-
|
|
356
|
-
**Package Version**: 0.9.0 | **XMR Library**: 0.0.6
|
|
357
|
-
|
|
358
|
-
## License
|
|
359
|
-
|
|
360
|
-
AGPL-3.0-or-later
|