@xiboplayer/xmr 0.1.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 ADDED
@@ -0,0 +1,170 @@
1
+ # Changelog
2
+
3
+ All notable changes to @xiboplayer/xmr will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.9.0] - 2026-02-10
9
+
10
+ ### Added
11
+
12
+ - **Upgraded to @xibosignage/xibo-communication-framework@0.0.6**
13
+ - Latest XMR library with improved stability
14
+ - Better WebSocket connection handling
15
+
16
+ - **New Commands**
17
+ - `criteriaUpdate`: Updates display criteria and triggers re-collection
18
+ - `currentGeoLocation`: Reports geographic location to CMS
19
+
20
+ - **Intentional Shutdown Flag**
21
+ - Prevents automatic reconnection when `stop()` is called
22
+ - Distinguishes between network errors and intentional disconnects
23
+ - Cleaner shutdown behavior
24
+
25
+ - **Comprehensive Test Suite**
26
+ - 48 test cases covering all functionality
27
+ - Constructor and initialization tests
28
+ - Connection lifecycle tests (start, stop, reconnect)
29
+ - All 7 CMS command tests with error handling
30
+ - Reconnection logic with exponential backoff
31
+ - Memory management and cleanup tests
32
+ - Edge cases (simultaneous commands, rapid cycles)
33
+
34
+ - **Complete Documentation**
35
+ - Updated README.md with full API reference
36
+ - XMR_COMMANDS.md: Complete command reference
37
+ - XMR_TESTING.md: Comprehensive testing guide
38
+ - Usage examples and troubleshooting
39
+
40
+ - **Test Utilities**
41
+ - test-utils.js with mock helpers
42
+ - createSpy(), createMockPlayer(), createMockConfig()
43
+ - waitFor() and wait() async helpers
44
+
45
+ - **Vitest Configuration**
46
+ - vitest.config.js for package-specific settings
47
+ - Node environment (no DOM needed)
48
+ - Coverage thresholds (80% lines, functions, statements)
49
+
50
+ ### Changed
51
+
52
+ - **Command Handler Documentation**
53
+ - Updated header comments with all supported commands
54
+ - Listed both `screenShot` and `screenshot` aliases
55
+ - Documented new v0.0.6 commands
56
+
57
+ - **Error Handling**
58
+ - All commands now have graceful error handling
59
+ - Errors logged but don't crash player
60
+ - Connection state preserved across command failures
61
+
62
+ ### Fixed
63
+
64
+ - **Reconnection on Stop**
65
+ - Fixed issue where `stop()` would trigger reconnection
66
+ - Added `intentionalShutdown` flag to prevent unwanted reconnects
67
+ - Proper cleanup of reconnection timers on stop
68
+
69
+ - **Memory Leaks**
70
+ - Ensured timers are cleared on stop
71
+ - Proper event listener management
72
+ - Garbage collection-friendly shutdown
73
+
74
+ ## [0.8.0] - 2025-XX-XX
75
+
76
+ ### Initial Implementation
77
+
78
+ - Basic XMR wrapper for @xibosignage/xibo-communication-framework
79
+ - Core commands: collectNow, screenShot, changeLayout, licenceCheck, rekey
80
+ - Automatic reconnection with exponential backoff
81
+ - Connection lifecycle management
82
+ - Event-based command handling
83
+
84
+ ## Upgrade Guide
85
+
86
+ ### From 0.8.x to 0.9.0
87
+
88
+ **No breaking changes.** This is a feature release with new commands and improvements.
89
+
90
+ 1. **Update dependency**:
91
+ ```bash
92
+ npm install @xiboplayer/xmr@0.9.0
93
+ ```
94
+
95
+ 2. **Optional: Implement new commands**:
96
+ ```javascript
97
+ // Add to your player class (optional)
98
+ async reportGeoLocation(data) {
99
+ // Your implementation
100
+ }
101
+ ```
102
+
103
+ 3. **Enjoy new features**:
104
+ - `criteriaUpdate` works automatically (triggers collect)
105
+ - `currentGeoLocation` logs warning if not implemented
106
+ - Better shutdown behavior (no reconnect loops)
107
+
108
+ ## Testing
109
+
110
+ Run the test suite to verify the upgrade:
111
+
112
+ ```bash
113
+ cd packages/xmr
114
+ npm test
115
+ ```
116
+
117
+ All 48 tests should pass.
118
+
119
+ ## Migration Notes
120
+
121
+ ### No Breaking Changes
122
+
123
+ The v0.9.0 release is fully backward compatible with v0.8.x. All existing code will continue to work without modification.
124
+
125
+ ### New Optional Features
126
+
127
+ If you want to use the new commands:
128
+
129
+ 1. **criteriaUpdate**: No action needed, works automatically
130
+ 2. **currentGeoLocation**: Implement `player.reportGeoLocation(data)` method
131
+
132
+ ### Improved Behavior
133
+
134
+ The intentional shutdown flag improves shutdown behavior:
135
+
136
+ **Before (v0.8.x)**:
137
+ ```javascript
138
+ await xmr.stop(); // Would trigger reconnection!
139
+ ```
140
+
141
+ **After (v0.9.0)**:
142
+ ```javascript
143
+ await xmr.stop(); // Clean shutdown, no reconnection
144
+ ```
145
+
146
+ ## Dependencies
147
+
148
+ ### Updated
149
+
150
+ - `@xibosignage/xibo-communication-framework`: ^0.0.5 → ^0.0.6
151
+
152
+ ### Added
153
+
154
+ - `vitest`: ^2.0.0 (dev dependency)
155
+
156
+ ### Unchanged
157
+
158
+ - `@xiboplayer/utils`: file:../utils
159
+
160
+ ## Support
161
+
162
+ - **Documentation**: [docs/README.md](./docs/README.md)
163
+ - **GitHub Issues**: https://github.com/xibo/xibo-players/issues
164
+ - **Community**: https://community.xibo.org.uk
165
+
166
+ ---
167
+
168
+ [Unreleased]: https://github.com/xibo/xibo-players/compare/v0.9.0...HEAD
169
+ [0.9.0]: https://github.com/xibo/xibo-players/releases/tag/v0.9.0
170
+ [0.8.0]: https://github.com/xibo/xibo-players/releases/tag/v0.8.0
package/docs/README.md ADDED
@@ -0,0 +1,360 @@
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