@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 +170 -0
- package/docs/README.md +360 -0
- package/docs/XMR_COMMANDS.md +303 -0
- package/docs/XMR_TESTING.md +509 -0
- package/package.json +36 -0
- package/src/index.js +2 -0
- package/src/test-utils.js +132 -0
- package/src/xmr-wrapper.js +359 -0
- package/src/xmr-wrapper.test.js +737 -0
- package/vitest.config.js +35 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# XMR Supported Commands
|
|
2
|
+
|
|
3
|
+
This document lists all CMS commands supported by the XMR (Xibo Message Relay) integration in the Xibo player.
|
|
4
|
+
|
|
5
|
+
## Command Reference
|
|
6
|
+
|
|
7
|
+
### collectNow
|
|
8
|
+
|
|
9
|
+
Triggers an immediate XMDS collection cycle.
|
|
10
|
+
|
|
11
|
+
**Event name**: `collectNow`
|
|
12
|
+
|
|
13
|
+
**Payload**: None
|
|
14
|
+
|
|
15
|
+
**Action**: Calls `player.collect()` to force an immediate sync with CMS
|
|
16
|
+
|
|
17
|
+
**Use case**: When CMS needs player to update its schedule immediately without waiting for the next collection interval
|
|
18
|
+
|
|
19
|
+
**Example**:
|
|
20
|
+
```javascript
|
|
21
|
+
// CMS sends via XMR
|
|
22
|
+
xmr.send('collectNow');
|
|
23
|
+
|
|
24
|
+
// Player receives and executes
|
|
25
|
+
await player.collect();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### screenShot / screenshot
|
|
31
|
+
|
|
32
|
+
Captures a screenshot of the current display and uploads it to CMS.
|
|
33
|
+
|
|
34
|
+
**Event names**: `screenShot`, `screenshot` (both supported)
|
|
35
|
+
|
|
36
|
+
**Payload**: None
|
|
37
|
+
|
|
38
|
+
**Action**: Calls `player.captureScreenshot()` to take and upload screenshot
|
|
39
|
+
|
|
40
|
+
**Use case**: Remote monitoring, verification that content is displaying correctly
|
|
41
|
+
|
|
42
|
+
**Example**:
|
|
43
|
+
```javascript
|
|
44
|
+
// CMS sends via XMR
|
|
45
|
+
xmr.send('screenShot');
|
|
46
|
+
|
|
47
|
+
// Player receives and executes
|
|
48
|
+
await player.captureScreenshot();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### changeLayout
|
|
54
|
+
|
|
55
|
+
Switches the display to a specific layout immediately.
|
|
56
|
+
|
|
57
|
+
**Event name**: `changeLayout`
|
|
58
|
+
|
|
59
|
+
**Payload**: `layoutId` (string) - The layout ID to switch to
|
|
60
|
+
|
|
61
|
+
**Action**: Calls `player.changeLayout(layoutId)` to immediately show the specified layout
|
|
62
|
+
|
|
63
|
+
**Use case**: Emergency content override, special announcements
|
|
64
|
+
|
|
65
|
+
**Example**:
|
|
66
|
+
```javascript
|
|
67
|
+
// CMS sends via XMR
|
|
68
|
+
xmr.send('changeLayout', 'layout-123');
|
|
69
|
+
|
|
70
|
+
// Player receives and executes
|
|
71
|
+
await player.changeLayout('layout-123');
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### licenceCheck
|
|
77
|
+
|
|
78
|
+
Validates the display license status.
|
|
79
|
+
|
|
80
|
+
**Event name**: `licenceCheck`
|
|
81
|
+
|
|
82
|
+
**Payload**: None
|
|
83
|
+
|
|
84
|
+
**Action**: No action required for open-source players
|
|
85
|
+
|
|
86
|
+
**Use case**: License validation for CMS-managed displays
|
|
87
|
+
|
|
88
|
+
**Example**:
|
|
89
|
+
```javascript
|
|
90
|
+
// CMS sends via XMR
|
|
91
|
+
xmr.send('licenceCheck');
|
|
92
|
+
|
|
93
|
+
// Player receives - no action needed for Linux
|
|
94
|
+
// Acknowledge license check
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### rekey
|
|
100
|
+
|
|
101
|
+
Triggers RSA key pair rotation for XMR encryption.
|
|
102
|
+
|
|
103
|
+
**Event name**: `rekey`
|
|
104
|
+
|
|
105
|
+
**Payload**: None
|
|
106
|
+
|
|
107
|
+
**Action**: TODO - Not yet implemented (for future XMR encryption)
|
|
108
|
+
|
|
109
|
+
**Use case**: Security - rotating encryption keys periodically
|
|
110
|
+
|
|
111
|
+
**Example**:
|
|
112
|
+
```javascript
|
|
113
|
+
// CMS sends via XMR
|
|
114
|
+
xmr.send('rekey');
|
|
115
|
+
|
|
116
|
+
// Player receives - future implementation
|
|
117
|
+
// Would generate new RSA key pair and send public key to CMS
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### criteriaUpdate (New in v0.0.6)
|
|
123
|
+
|
|
124
|
+
Updates display criteria and triggers immediate re-collection.
|
|
125
|
+
|
|
126
|
+
**Event name**: `criteriaUpdate`
|
|
127
|
+
|
|
128
|
+
**Payload**: Object with criteria data
|
|
129
|
+
|
|
130
|
+
**Action**: Calls `player.collect()` to fetch updated display criteria from CMS
|
|
131
|
+
|
|
132
|
+
**Use case**: When CMS changes display tags, criteria, or custom metadata
|
|
133
|
+
|
|
134
|
+
**Example**:
|
|
135
|
+
```javascript
|
|
136
|
+
// CMS sends via XMR
|
|
137
|
+
xmr.send('criteriaUpdate', { displayId: '123', criteria: 'new-criteria' });
|
|
138
|
+
|
|
139
|
+
// Player receives and re-collects
|
|
140
|
+
await player.collect(); // Gets new criteria from registerDisplay
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### currentGeoLocation (New in v0.0.6)
|
|
146
|
+
|
|
147
|
+
Reports current geographic location to CMS.
|
|
148
|
+
|
|
149
|
+
**Event name**: `currentGeoLocation`
|
|
150
|
+
|
|
151
|
+
**Payload**: Object with latitude/longitude (optional)
|
|
152
|
+
|
|
153
|
+
**Action**: Calls `player.reportGeoLocation(data)` if implemented
|
|
154
|
+
|
|
155
|
+
**Use case**: Location-based content delivery, asset tracking
|
|
156
|
+
|
|
157
|
+
**Example**:
|
|
158
|
+
```javascript
|
|
159
|
+
// CMS sends via XMR
|
|
160
|
+
xmr.send('currentGeoLocation', { latitude: 40.7128, longitude: -74.0060 });
|
|
161
|
+
|
|
162
|
+
// Player receives and reports location
|
|
163
|
+
if (player.reportGeoLocation) {
|
|
164
|
+
await player.reportGeoLocation(data);
|
|
165
|
+
} else {
|
|
166
|
+
console.warn('Geo location reporting not implemented');
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Note**: This command requires `player.reportGeoLocation()` to be implemented. Currently logs a warning if not available.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Connection Events
|
|
175
|
+
|
|
176
|
+
The XMR wrapper also emits internal connection events:
|
|
177
|
+
|
|
178
|
+
### connected
|
|
179
|
+
|
|
180
|
+
Fired when WebSocket connection is established.
|
|
181
|
+
|
|
182
|
+
**Action**:
|
|
183
|
+
- Sets `connected = true`
|
|
184
|
+
- Resets `reconnectAttempts = 0`
|
|
185
|
+
- Updates player status
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
### disconnected
|
|
190
|
+
|
|
191
|
+
Fired when WebSocket connection is lost.
|
|
192
|
+
|
|
193
|
+
**Action**:
|
|
194
|
+
- Sets `connected = false`
|
|
195
|
+
- Updates player status
|
|
196
|
+
- Schedules automatic reconnection (unless intentionally stopped)
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### error
|
|
201
|
+
|
|
202
|
+
Fired when WebSocket encounters an error.
|
|
203
|
+
|
|
204
|
+
**Action**:
|
|
205
|
+
- Logs error to console
|
|
206
|
+
- Does not affect connection state
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Command Implementation
|
|
211
|
+
|
|
212
|
+
All commands follow this pattern:
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
// 1. Register handler in setupEventHandlers()
|
|
216
|
+
this.xmr.on('commandName', async (data) => {
|
|
217
|
+
console.log('[XMR] Received commandName:', data);
|
|
218
|
+
try {
|
|
219
|
+
await this.player.performAction(data);
|
|
220
|
+
console.log('[XMR] commandName completed successfully');
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error('[XMR] commandName failed:', error);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Error Handling
|
|
228
|
+
|
|
229
|
+
All command handlers implement graceful error handling:
|
|
230
|
+
|
|
231
|
+
1. **Try/catch blocks** - All async operations wrapped in try/catch
|
|
232
|
+
2. **Logging** - Errors logged to console with context
|
|
233
|
+
3. **Non-blocking** - Errors don't crash the player
|
|
234
|
+
4. **Connection preservation** - Command failures don't disconnect XMR
|
|
235
|
+
|
|
236
|
+
## Testing
|
|
237
|
+
|
|
238
|
+
All commands are covered by comprehensive unit tests in `xmr-wrapper.test.js`:
|
|
239
|
+
|
|
240
|
+
- ✅ Command execution (happy path)
|
|
241
|
+
- ✅ Error handling (failure scenarios)
|
|
242
|
+
- ✅ Missing implementation warnings
|
|
243
|
+
- ✅ Multiple simultaneous commands
|
|
244
|
+
- ✅ Connection state preservation
|
|
245
|
+
|
|
246
|
+
Run tests with:
|
|
247
|
+
```bash
|
|
248
|
+
npm test
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Adding New Commands
|
|
252
|
+
|
|
253
|
+
To add support for a new XMR command:
|
|
254
|
+
|
|
255
|
+
1. **Add handler** in `setupEventHandlers()`:
|
|
256
|
+
```javascript
|
|
257
|
+
this.xmr.on('newCommand', async (data) => {
|
|
258
|
+
console.log('[XMR] Received newCommand:', data);
|
|
259
|
+
try {
|
|
260
|
+
await this.player.handleNewCommand(data);
|
|
261
|
+
console.log('[XMR] newCommand completed successfully');
|
|
262
|
+
} catch (error) {
|
|
263
|
+
console.error('[XMR] newCommand failed:', error);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
2. **Update documentation** (this file):
|
|
269
|
+
- Add command reference
|
|
270
|
+
- Document payload structure
|
|
271
|
+
- Provide usage example
|
|
272
|
+
|
|
273
|
+
3. **Add tests** in `xmr-wrapper.test.js`:
|
|
274
|
+
- Test happy path
|
|
275
|
+
- Test error handling
|
|
276
|
+
- Test edge cases
|
|
277
|
+
|
|
278
|
+
4. **Implement player method** (if needed):
|
|
279
|
+
```javascript
|
|
280
|
+
// In player-core.js or appropriate module
|
|
281
|
+
async handleNewCommand(data) {
|
|
282
|
+
// Implementation
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Version History
|
|
287
|
+
|
|
288
|
+
### v0.0.6 (Current)
|
|
289
|
+
- ✅ Added `criteriaUpdate` command
|
|
290
|
+
- ✅ Added `currentGeoLocation` command
|
|
291
|
+
- ✅ Intentional shutdown flag (no reconnect on stop)
|
|
292
|
+
- ✅ Comprehensive test suite (48 tests)
|
|
293
|
+
|
|
294
|
+
### v0.0.5 and earlier
|
|
295
|
+
- Basic commands: collectNow, screenShot, changeLayout, licenceCheck, rekey
|
|
296
|
+
- Connection lifecycle management
|
|
297
|
+
- Automatic reconnection with exponential backoff
|
|
298
|
+
|
|
299
|
+
## References
|
|
300
|
+
|
|
301
|
+
- **XMR Library**: @xibosignage/xibo-communication-framework
|
|
302
|
+
- **Xibo CMS**: https://xibosignage.com
|
|
303
|
+
- **XMR Protocol**: WebSocket-based push messaging
|