Skip to content

hyperb1iss/blocksd

Repository files navigation


πŸ”Œ blocksd

Linux Daemon for ROLI Blocks Devices
✦ Topology · Keepalive · LED Control · Touch Events ✦

CI PyPI Python License

Features β€’ Install β€’ Usage β€’ External API β€’ Architecture β€’ Devices β€’ Development β€’ Docs β€’ Vision


ROLI Blocks devices need an active host-side handshake over MIDI SysEx to enter "API mode." Without it, they show a searching animation and eventually power off. There's no official Linux support.

blocksd implements the full ROLI Blocks protocol: device discovery, topology management, API mode keepalive, LED control, touch events, and device configuration. Your Blocks stay alive and useful on Linux.

✦ Features

Capability Description
πŸ”Œ API Mode Keepalive Periodic pings prevent the 5-second device timeout that kills API mode
πŸ—οΈ Topology Management Auto-discovers devices over USB, tracks DNA-connected blocks through master
🎭 Full State Machine Serial β†’ topology β†’ API activation β†’ ping loop, matching the C++ reference
πŸ’‘ LED Control Lightpad / Lightpad M RGB565 bitmap grid, CLI patterns (solid, gradient, rainbow, checkerboard)
πŸ‘† Touch & Button Events Normalized touch data (x/y/z/velocity) and button callbacks
βš™οΈ Device Config Read/write device settings (sensitivity, MIDI channel, scale, etc.)
πŸ”Š DAW Friendly ALSA multi-client, blocksd and your DAW share MIDI without conflict
πŸ›‘οΈ systemd Integration Type=notify service, watchdog heartbeat, udev rules for plug-and-play

πŸ“¦ Install

Quick Install

curl -fsSL https://raw.githubusercontent.com/hyperb1iss/blocksd/main/install.sh | bash

Installs blocksd, udev rules, and a systemd user service in one shot.

From PyPI

uv tool install blocksd
blocksd install    # sets up systemd service + udev rules

Arch Linux (AUR)

yay -S blocksd       # stable release
yay -S blocksd-git   # latest from main

From Source

git clone https://github.com/hyperb1iss/blocksd.git
cd blocksd
uv sync
uv run blocksd install

The install command sets up:

  • udev rules: proper permissions for ROLI USB devices (requires sudo)
  • systemd user service: auto-starts on login with watchdog monitoring
  • Security hardening: sandboxed with ProtectSystem=strict, NoNewPrivileges, etc.

⚑ Usage

Running the Daemon

# Foreground with verbose logging
blocksd run -v

# As a systemd service (after install)
systemctl --user start blocksd
systemctl --user status blocksd
journalctl --user -u blocksd -f

When running, you'll see devices connect:

INFO  blocksd ready, scanning for ROLI devices
INFO  Master serial: LKBC9PZSOH978HOE
INFO  Topology: 2 devices, 1 connections
INFO  ✨ Device connected: lumi_keys_block (LKBC9PZSOH978HOE), battery 31%
INFO  ✨ Device connected: lightpad_block_m (LPMJW6SWHSPD8H92), battery 31%

Device Status

# Quick scan, shows detected MIDI ports
blocksd status

# Full probe, connects to devices, shows type/serial/battery/version
blocksd status --probe

LED Control

Control the 15Γ—15 LED grid on Lightpad Block and Lightpad Block M:

blocksd led solid '#ff00ff'                          # solid color
blocksd led rainbow                                   # animated rainbow
blocksd led gradient ff0000 0000ff                    # horizontal gradient
blocksd led gradient ff0000 0000ff --vertical         # vertical gradient
blocksd led checkerboard ff0000 00ff00                # 2Γ—2 checkerboard
blocksd led checkerboard ff0000 00ff00 --size 3       # 3Γ—3 checkerboard
blocksd led off                                       # lights off

Device Configuration

Read and write device settings like velocity sensitivity, MIDI channel, scale mode, and more:

blocksd config list                    # show all known config IDs
blocksd config get 10                  # read velocity sensitivity
blocksd config set 10 50               # write velocity sensitivity

Web Dashboard

blocksd ui                             # launch web UI on http://localhost:9010
blocksd ui --port 8080                 # custom port

Opens a real-time dashboard showing connected devices, topology, battery status, and LED state. Uses WebSocket for live updates.

Service Management

blocksd install                        # install systemd service + udev rules
blocksd install --no-udev              # skip udev rules
blocksd install --no-enable            # install but don't auto-start
blocksd uninstall                      # remove everything

πŸ”Œ External API

blocksd exposes two APIs for external integration:

Unix Socket: low-latency IPC for local clients (e.g. Hypercolor)

  • Socket path: $XDG_RUNTIME_DIR/blocksd/blocksd.sock
  • Fallback path: /tmp/blocksd/blocksd.sock
  • One socket supports both control messages and high-rate LED frame writes

WebSocket: browser and network clients (used by blocksd ui)

  • Default: ws://localhost:9010/ws
  • Binary LED frame writes + JSON device events

The quick rules:

  • Use discover first to get the device uid
  • Only stream frames to devices advertising nonzero grid_width and grid_height in discovery
  • Use the fixed-size binary frame protocol for animation and streaming
  • Treat frame_ack.accepted=false or binary ack 0x00 as a rejected write: this usually means the device is not ready yet, the uid is gone, or the payload was malformed
  • Once a device is live, frame writes are coalesced daemon-side to the latest target state instead of surfacing host-visible β€œbusy” backpressure
  • Prefer a separate subscription socket if you also want events; outbound NDJSON events and 1-byte binary frame acks share the same connection

See the API reference for the full protocol reference, examples, and Hypercolor-oriented integration notes.

πŸ—οΈ Architecture

blocksd
β”œβ”€β”€ daemon.py                 asyncio main loop, sd_notify, signal handling
β”‚   └── TopologyManager       polls MIDI ports every 1.5s
β”‚       └── DeviceGroup       per-USB lifecycle + touch/button/config events
β”‚           └── MidiConnection    python-rtmidi wrapper (SysEx I/O)
β”œβ”€β”€ protocol/                 pure protocol logic (no I/O, fully testable)
β”‚   β”œβ”€β”€ constants.py          enums, headers, bit sizes
β”‚   β”œβ”€β”€ checksum.py           SysEx checksum algorithm
β”‚   β”œβ”€β”€ packing.py            7-bit pack/unpack (LSB-first)
β”‚   β”œβ”€β”€ builder.py            host β†’ device packet construction
β”‚   β”œβ”€β”€ decoder.py            device β†’ host packet parsing
β”‚   β”œβ”€β”€ serial.py             serial number request/parse
β”‚   β”œβ”€β”€ data_change.py        SharedDataChange diff encoder
β”‚   └── remote_heap.py        ACK-tracked heap manager for live updates
β”œβ”€β”€ device/
β”‚   β”œβ”€β”€ models.py             BlockType, DeviceInfo, TouchEvent, ButtonEvent
β”‚   β”œβ”€β”€ config_ids.py         known configuration item IDs
β”‚   β”œβ”€β”€ registry.py           serial prefix β†’ device type mapping
β”‚   └── connection.py         rtmidi ↔ asyncio bridge
β”œβ”€β”€ led/
β”‚   β”œβ”€β”€ bitmap.py             RGB565 LED grid (15Γ—15 Lightpad)
β”‚   └── patterns.py           solid, gradient, rainbow, checkerboard
β”œβ”€β”€ littlefoot/
β”‚   β”œβ”€β”€ opcodes.py            LittleFoot VM opcode definitions
β”‚   β”œβ”€β”€ assembler.py          bytecode assembler with label support
β”‚   └── programs.py           BitmapLEDProgram (94-byte repaint)
β”œβ”€β”€ topology/
β”‚   β”œβ”€β”€ detector.py           MIDI port scanning
β”‚   β”œβ”€β”€ device_group.py       connection lifecycle (the big one)
β”‚   └── manager.py            orchestrates DeviceGroups
β”œβ”€β”€ api/
β”‚   β”œβ”€β”€ server.py             Unix socket + WebSocket servers
β”‚   β”œβ”€β”€ protocol.py           NDJSON + binary frame wire protocol
β”‚   β”œβ”€β”€ events.py             event broadcaster (device/touch/button/config)
β”‚   β”œβ”€β”€ websocket.py          RFC 6455 frame codec
β”‚   └── http.py               HTTP parser + static file serving
β”œβ”€β”€ web/                      web dashboard (Vite build output)
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ schema.py             DaemonConfig (Pydantic)
β”‚   └── loader.py             TOML config file parsing
β”œβ”€β”€ sdnotify.py               lightweight systemd notification (no deps)
└── cli/
    β”œβ”€β”€ app.py                Typer commands (run, status --probe)
    β”œβ”€β”€ led.py                LED pattern commands (solid, rainbow, etc.)
    β”œβ”€β”€ config.py             device config get/set/list
    └── install.py            systemd/udev setup

Protocol Pipeline

Host                                          Device
 β”‚                                              β”‚
 β”‚  ── Serial Dump Request ──────────────────►  β”‚
 β”‚  ◄─────────────────── Serial Response ────  β”‚
 β”‚  ── Request Topology ─────────────────────►  β”‚
 β”‚  ◄───────────────────── Topology ─────────  β”‚
 β”‚  ── endAPIMode + beginAPIMode ────────────►  β”‚
 β”‚  ◄──────────────────── Packet ACK ────────  β”‚
 β”‚                                              β”‚
 β”‚  ── Ping (400ms master / 1666ms DNA) ─────► β”‚  ← keepalive loop
 β”‚  ◄──────────────────── Packet ACK ────────  β”‚
 β”‚                                              β”‚
 β”‚  ── SharedDataChange (LED data) ──────────► β”‚  ← heap writes
 β”‚  ◄──────────────────── Packet ACK ────────  β”‚

Supported Devices

Device USB PID Serial Prefix Status
Lightpad Block / M 0x0900 LPB / LPM βœ… Tested
LUMI Keys Block 0x0E00 LKB βœ… Tested
Seaboard Block 0x0700 SBB πŸ”² Untested
Live Block β€” LIC πŸ”² Untested
Loop Block β€” LOC πŸ”² Untested
Developer Control Block β€” DCB πŸ”² Untested
Touch Block β€” TCB πŸ”² Untested
Seaboard RISE 25/49 0x0200 / 0x0210 β€” πŸ”² Untested

Bitmap LED streaming is currently exposed for Lightpad Block / Lightpad Block M only. Other devices are still discoverable and supported by the topology/API state machine, but they do not advertise a bitmap frame surface.

πŸ§ͺ Development

See CONTRIBUTING.md for the full development guide.

uv sync                        # install all dependencies
uv run pytest                  # run tests
uv run ruff check .            # lint
uv run ruff format --check .   # format check
uv run ty check                # type check

πŸ—ΊοΈ Roadmap

See VISION.md for the full vision, use cases, and ideas beyond music.

  • Protocol Core: 7-bit packing, checksum, SysEx builder/decoder
  • Device Discovery: MIDI port scanning, serial number parsing
  • Topology Management: multi-device tracking, DNA connections
  • API Mode Keepalive: full state machine with correct ping timing
  • Remote Heap Manager: ACK tracking, retransmission, heap state sync
  • LittleFoot Programs: bytecode assembler, BitmapLEDProgram upload
  • CLI LED Commands: blocksd led solid #ff00ff, blocksd led rainbow
  • Touch/Button Events: normalized callbacks with full velocity data
  • Config Commands: read/write device settings via CLI
  • sd_notify Integration: Type=notify service with watchdog heartbeat
  • CI/CD: GitHub Actions, PyPI publishing, automated releases
  • D-Bus Interface: IPC for external applications
  • Hypercolor Integration: ROLI Blocks as an RGB device backend

βš–οΈ License

ISC


Star on GitHub Β Β  Ko-fi

If blocksd keeps your Blocks alive, give us a ⭐ or support the project

✦ Built with obsession by Hyperbliss Technologies ✦

About

Linux daemon for ROLI Blocks devices β€” topology, keepalive, LED control

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors