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

@scooper4711/pixels-ble

v0.3.0

Published

Pixels dice BLE connection library

Readme

@scooper4711/pixels-ble

CI npm version Quality Gate Coverage License: MIT

A TypeScript library for communicating with Pixels electronic dice over Bluetooth Low Energy (Web Bluetooth API).

Features

  • Connect and manage multiple Pixels dice simultaneously
  • Real-time roll detection with face value conversion (D4–D100)
  • Battery level monitoring
  • Automatic reconnection with adaptive strategy (watch or poll with exponential backoff)
  • Typed event system for roll, status, and battery updates
  • Bring-your-own storage adapter for persistence
  • Dual build: ESM for bundlers, IIFE for script tags

Installation

npm install @scooper4711/pixels-ble

Quick Start

import { DiceManager, StorageAdapter, KnownDie } from '@scooper4711/pixels-ble';

// Provide a storage adapter (localStorage example)
const storage: StorageAdapter = {
  async load(): Promise<KnownDie[]> {
    return JSON.parse(localStorage.getItem('pixels-dice') ?? '[]');
  },
  async save(dice: KnownDie[]): Promise<void> {
    localStorage.setItem('pixels-dice', JSON.stringify(dice));
  },
};

const manager = new DiceManager(storage);

// Pair a new die (requires user gesture)
const pixel = await manager.requestPixel();

// Listen for rolls
pixel.addEventListener('roll', ({ face, dieType }) => {
  console.log(`Rolled a ${face} on a D${dieType}`);
});

// Listen for battery updates
pixel.addEventListener('battery', ({ level }) => {
  console.log(`Battery: ${level}%`);
});

// Blink the die green
await pixel.blink({ r: 0, g: 255, b: 0 });

API Reference

DiceManager

High-level manager for pairing, reconnecting, and tracking multiple dice.

| Method | Description | |--------|-------------| | requestPixel() | Pair a new die via the browser Bluetooth picker | | connectKnownDevices() | Reconnect previously paired dice using watchAdvertisements | | reconnect(systemId) | Manually trigger reconnection for a specific die | | forget(systemId) | Unpair and remove a die from storage | | getPixel(systemId) | Retrieve a Pixel instance by ID |

| Property | Description | |----------|-------------| | dice | ReadonlyMap<string, Pixel> of all known dice | | connectedDice | Array of currently connected Pixel instances |

Events (DiceManagerEvents):

| Event | Payload | |-------|---------| | dieAdded | PixelInfo | | dieRemoved | PixelInfo | | dieConnected | PixelInfo | | dieDisconnected | PixelInfo | | dieBatteryUpdate | { pixel: PixelInfo, level: number } |

Pixel

Represents a single connected Pixels die.

| Method | Description | |--------|-------------| | connect(timeoutMs?) | Establish GATT connection and subscribe to notifications | | disconnect() | Cleanly disconnect and stop monitoring | | blink({ r, g, b }) | Flash the die LEDs with the specified color | | startConnectionMonitoring() | Begin periodic connection health checks | | stopConnectionMonitoring() | Stop health checks |

| Property | Type | Description | |----------|------|-------------| | name | string | Die name from pairing | | systemId | string | Unique Bluetooth device ID | | dieType | number \| null | Face count (4, 6, 8, 10, 12, 20, 100) | | batteryLevel | number \| null | Last known battery percentage | | isConnected | boolean | Current connection state | | device | BluetoothDevice | Underlying Web Bluetooth device |

Events (PixelEvents):

| Event | Payload | |-------|---------| | roll | { face: number, dieType: number } | | status | { connected: boolean } | | battery | { level: number } |

EventEmitter<Events>

Typed event emitter base class used by both Pixel and DiceManager.

| Method | Description | |--------|-------------| | addEventListener(event, listener) | Subscribe to an event | | removeEventListener(event, listener) | Unsubscribe from an event |

Utility Exports

| Export | Description | |--------|-------------| | convertFaceValue(faceIndex, dieType) | Convert raw face index to display value | | attemptReconnection(device, pixel) | Low-level reconnection (auto-selects strategy) | | resetStrategy() | Reset the detected reconnection strategy | | getStrategy() | Get the current strategy ('watch', 'poll', or 'unknown') | | startMonitoring(pixel) | Start disconnect monitoring for a Pixel | | stopMonitoring(pixel) | Stop disconnect monitoring for a Pixel |

Interfaces

interface StorageAdapter {
  load(): Promise<KnownDie[]>;
  save(dice: KnownDie[]): Promise<void>;
}

interface KnownDie {
  name: string;
  systemId: string;
  dieType: number | null;
  lastConnected: number;
}

Protocol Coverage

This library implements a subset of the Pixels dice BLE protocol. The full protocol defines 60+ message types spanning animation programming, telemetry streaming, hardware testing, calibration, and more.

Implemented messages:

| Message | Direction | Purpose | |---------|-----------|---------| | WhoAreYou (1) | → Die | Request die identity and capabilities | | IAmADie (2) | ← Die | Die type, firmware info, battery level | | RollState (3) | ← Die | Roll events (rolling, settled, face index) | | Blink (29) | → Die | Flash LEDs with a specified color | | RequestBatteryLevel (33) | → Die | Request current battery percentage | | BatteryLevel (34) | ← Die | Battery level response |

Not yet implemented:

| Category | Messages | Reason | |----------|----------|--------| | Animation transfer | TransferAnimationSet, BulkSetup, BulkData, PlayAnimation, StopAnimation, StopAllAnimations | Complex multi-packet transfer protocol; not needed for roll detection use cases | | Telemetry | Telemetry, RequestTelemetry | Accelerometer streaming is heavy bandwidth; useful for physics apps but out of scope for this library's primary purpose | | Settings management | TransferSettings, ProgramDefaultParameters, SetCurrentBehavior, SetDesignAndColor | Modifies on-die profiles; risky to expose without the full animation framework | | Calibration | Calibrate, CalibrateFace | Factory/advanced use only | | RSSI | RequestRssi, Rssi | Signal strength has limited utility for consumers | | Temperature | RequestTemperature, Temperature | Niche diagnostic use | | Hardware testing | TestHardware, ClearSettings | Development/factory tooling | | Power | PowerOperation, Discharge, SetBatteryControllerMode | Safety concern — exposing power control without guardrails | | Naming | SetName, SetNameAck | Low priority; die names rarely change after initial setup |

The protocol layer (src/ble/protocol.ts) is designed for incremental extension. Adding support for a new message type requires only a constant, a parser function, and a case in the message dispatcher. See docs/DESIGN.md for the step-by-step guide.

Browser Support

This library requires the Web Bluetooth API. Supported environments:

| Browser | Support | |---------|---------| | Chrome (desktop) | Full support | | Chrome (Android) | Full support | | Edge | Full support | | Opera | Full support | | Firefox | Not supported | | Safari | Not supported |

The watchAdvertisements API (used for automatic reconnection) has more limited support. The library falls back to poll-based reconnection when unavailable.

Build Outputs

| Path | Format | Use Case | |------|--------|----------| | dist/esm/index.js | ESM | Bundlers (webpack, Vite, Rollup) | | dist/umd/index.global.js | IIFE | Script tags (exposes window.PixelsBLE) | | dist/types/index.d.ts | TypeScript declarations | Type checking and editor support |

Script Tag Usage

<script src="https://unpkg.com/@scooper4711/pixels-ble/dist/umd/index.global.js"></script>
<script>
  const { DiceManager, Pixel } = PixelsBLE;
</script>

Development

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Type check
npm run lint

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feat/my-feature)
  3. Commit your changes using Conventional Commits
  4. Push to your branch and open a Pull Request

All PRs must pass CI (lint, test, build) before merge.

Acknowledgements

This library was inspired by and derived from the BLE communication code in the Pixels Roll20 Chrome Extension, originally created by Olivier Basille and the GameWithPixels team, and further developed by jbmowgli. The protocol constants, message parsing approach, and characteristic discovery pattern trace their lineage to those projects.

Thanks to the Pixels team at Systemic Games for designing dice with an open BLE protocol and publishing reference implementations across multiple platforms.

License

MIT — Copyright (c) 2025 scooper4711