npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xiboplayer/xmr

v0.7.15

Published

XMR WebSocket client for real-time Xibo CMS commands

Readme

@xiboplayer/xmr

XMR WebSocket client for real-time Xibo CMS push commands.

Overview

Listens for push commands from the CMS over WebSocket with automatic reconnection:

  • 13 command handlers -- collectNow, screenshot, changeLayout, overlayLayout, revertToSchedule, purgeAll, commandAction, triggerWebhook, dataUpdate, rekeyAction, criteriaUpdate, currentGeoLocation, licenceCheck
  • Auto-reconnect -- exponential backoff (5s base, up to 10 attempts), resumes on next collection cycle
  • Intentional shutdown -- clean disconnect without triggering reconnection
  • Dual-path geo-location -- CMS can push coordinates or request the player to report its position

Architecture

CMS (Push)                     XmrWrapper                    PlayerCore
    |                              |                              |
    +--- WebSocket message ------> xmr.on('collectNow') -------> player.collect()
    +--- WebSocket message ------> xmr.on('changeLayout') -----> player.changeLayout()
    +--- WebSocket message ------> xmr.on('screenshot') -------> player.captureScreenshot()
    +--- WebSocket message ------> xmr.on('purgeAll') ---------> player.purgeAll()
    |                              |                              |
    +--- disconnect -------------> scheduleReconnect() ---------> [5s, 10s, 15s, ...]
    +--- reconnect --------------> xmr.on('connected') --------> updateStatus('XMR connected')

Installation

npm install @xiboplayer/xmr

Usage

import { XmrWrapper } from '@xiboplayer/xmr';

const xmr = new XmrWrapper(config, player);

// Start connection (from RegisterDisplay result)
const success = await xmr.start(xmrWebSocketAddress, xmrCmsKey);

if (success) {
  console.log('XMR connected - real-time commands active');
} else {
  console.log('XMR failed - falling back to polling mode');
}

// Check status
xmr.isConnected(); // true/false

// Stop cleanly
await xmr.stop();

Commands

| Command | Payload | Action | |---------|---------|--------| | collectNow | -- | Trigger immediate XMDS collection cycle | | screenShot / screenshot | -- | Capture and upload display screenshot | | changeLayout | { layoutId, duration?, downloadRequired?, changeMode? } | Switch to specific layout | | overlayLayout | { layoutId, duration?, downloadRequired? } | Push overlay on top | | revertToSchedule | -- | Return to normal scheduled content | | purgeAll | -- | Clear all cached files and re-download | | commandAction | { commandCode, commands? } | Execute player command (HTTP only in browser) | | triggerWebhook | { triggerCode } | Fire a webhook trigger action | | dataUpdate | -- | Force refresh data connectors | | rekeyAction | -- | Rotate RSA key pair and re-register | | criteriaUpdate | data | Update display criteria, trigger collection | | currentGeoLocation | { latitude?, longitude? } | Push coordinates or request location report | | licenceCheck | -- | No-op for Linux clients |

Reconnection

  • Base delay: 5 seconds, linear increase (5s, 10s, 15s, ...)
  • Max attempts: 10 per disconnect event
  • After max: stops trying until next collection cycle calls start() again
  • Intentional stop: stop() sets a flag that prevents reconnection on disconnect

API Reference

Constructor

new XmrWrapper(config, player)

| Parameter | Type | Description | |-----------|------|-------------| | config | Object | Player config with hardwareKey, xmrChannel | | player | Object | PlayerCore instance with command methods |

Methods

| Method | Returns | Description | |--------|---------|-------------| | start(xmrUrl, cmsKey) | Promise<boolean> | Connect to XMR WebSocket | | stop() | Promise<void> | Disconnect cleanly (no reconnect) | | isConnected() | boolean | Check connection status | | send(action, data) | Promise<boolean> | Send message to CMS |

Dependencies

  • @xiboplayer/utils -- logger

No external XMR dependencies. The native XmrClient (xmr-client.js) replaces the upstream @xibosignage/xibo-communication-framework, providing a complete implementation with generic action dispatch and zero third-party dependencies (no luxon, no nanoevents).

Upstream comparison

| Feature | upstream [email protected] | native XmrClient | |---------|------------------------------------------------|---------------------| | collectNow | hardcoded | generic dispatch | | screenShot | hardcoded | generic dispatch | | licenceCheck | hardcoded | generic dispatch | | criteriaUpdate | hardcoded | generic dispatch | | commandAction (showStatusWindow) | hardcoded, splits commandCode | generic dispatch (full message) | | commandAction (forceUpdateChromeOS) | hardcoded, splits commandCode | generic dispatch (full message) | | commandAction (currentGeoLocation) | hardcoded, splits commandCode | generic dispatch (full message) | | commandAction (other) | missing -- console.error('unknown action') | generic dispatch (full message) | | changeLayout | missing -- console.error('unknown action') | generic dispatch | | overlayLayout | missing -- console.error('unknown action') | generic dispatch | | revertToSchedule | missing -- console.error('unknown action') | generic dispatch | | purgeAll | missing -- console.error('unknown action') | generic dispatch | | triggerWebhook | missing -- console.error('unknown action') | generic dispatch | | dataUpdate | missing -- console.error('unknown action') | generic dispatch | | rekeyAction | missing -- console.error('unknown action') | generic dispatch | | Any future CMS action | requires library update | works automatically | | TTL check | luxon DateTime.fromISO().plus() (68KB) | native Date.parse() (0KB) | | Event emitter | nanoevents (external) | built-in Map<Set> (0KB) | | Bundle size impact | ~70KB (luxon + nanoevents + framework) | ~2KB | | Reconnect interval | 60s setInterval | 60s setInterval (same) | | isActive() check | 15min silence threshold | 15min silence threshold (same) | | Init handshake | {type:'init', key, channel} | {type:'init', key, channel} (same) | | Heartbeat handling | "H" → update lastMessageAt | "H" → update lastMessageAt (same) |


xiboplayer.org · Part of the XiboPlayer SDK