HTTP REST API server for blink(1) USB LED notification devices.
Version 2 — rewritten from the ground up to match the full Blink1Control2 API surface, including named color patterns, multi-device support, and a Node.js library interface.
Supports plug and unplug of blink(1) while the server is running.
npx node-blink1-server
npx node-blink1-server 8080
npx node-blink1-server --port 8080 --host 0.0.0.0
npm install -g node-blink1-server
blink1-server # starts on localhost:8934
blink1-server 8080
blink1-server --port 8080 --host 0.0.0.0
git clone https://github.com/todbot/node-blink1-server.git
cd node-blink1-server
npm install
npm start # localhost:8934
npm start -- 8080 # port 8080
For production use or boot persistence, use pm2:
npm install -g pm2
pm2 start blink1-server -- --port 8934
pm2 startup # configure to start on boot
pm2 save
node-blink1 contains a native C++ addon. If you switch Node.js versions or use this package
inside an Electron app (which has its own ABI), you need to rebuild the native module:
npm run clean
npm install
When used inside an Electron app via a file: reference, rebuild against Electron's ABI instead:
./node_modules/.bin/electron-rebuild -f -w node-blink1
blink1-server [port]
blink1-server --port <port> --host <host>
| Option | Default | Description |
|---|---|---|
port (positional or --port) |
8934 |
HTTP port to listen on |
--host |
localhost |
Bind address (0.0.0.0 for all interfaces) |
All endpoints are HTTP GET. Query parameters use standard URL encoding.
| Parameter | Alias | Description |
|---|---|---|
rgb |
Hex color, e.g. %23ff00ff (URL-encoded #ff00ff) |
|
time |
Fade time in seconds (e.g. 0.5) |
|
millis |
Fade time in milliseconds (e.g. 500) — takes priority over time |
|
ledn |
LED number: 0 = all, 1 = top, 2 = bottom (default: 0) |
|
blink1_id |
id |
Device serial number to target (omit for default device) |
| Endpoint | Description |
|---|---|
GET /blink1 |
List connected device serial numbers and IFTTT key |
GET /blink1/id |
Same as above |
GET /blink1/enumerate |
Re-scan for devices, then list |
| Endpoint | Description |
|---|---|
GET /blink1/fadeToRGB?rgb=<hex>&time=<secs> |
Fade to a specific color |
GET /blink1/lastColor |
Return current color state |
GET /blink1/on |
Fade to white |
GET /blink1/off |
Fade to black (stops any playing pattern) |
GET /blink1/red |
Named color shortcuts |
GET /blink1/green |
|
GET /blink1/blue |
|
GET /blink1/cyan |
|
GET /blink1/yellow |
|
GET /blink1/magenta |
|
GET /blink1/random |
Random color |
GET /blink1/blink?rgb=<hex>&count=<n>&time=<secs> |
Blink N times |
A pattern is a named sequence of {color, time, ledn} steps. System patterns are built in;
user patterns are added via the API and persist in the config file (when a config file is provided).
| Endpoint | Query params | Description |
|---|---|---|
GET /blink1/patterns |
List all patterns | |
GET /blink1/pattern/queue |
List currently-playing pattern queue | |
GET /blink1/pattern/play |
pname or name |
Play a pattern by name |
GET /blink1/pattern/stop |
pname or name (optional) |
Stop a pattern, or all if omitted |
GET /blink1/pattern/add |
name, pattern |
Add a pattern from a pattern string |
GET /blink1/pattern/del |
name or id |
Delete a user pattern |
Pattern strings encode a repeating color sequence:
repeats,#color1,secs1,ledn1,#color2,secs2,ledn2,...
Examples:
3,#ff0000,0.3,0,#000000,0.3,0 # red blink 3x
0,#ff0000,0.5,1,#0000ff,0.5,2 # alternating red/blue forever (repeats=0)
These pattern names are interpreted directly without needing a pre-defined pattern:
| Name | Example | Description |
|---|---|---|
#rrggbb |
#ff00ff |
Fade to that hex color |
~off |
Stop all patterns and fade to black | |
~blink:<color>-<count> |
~blink:#ff0000-5 |
Blink color N times |
~blink:<color>-<count>-<secs> |
~blink:#ff0000-5-0.3 |
Blink with custom timing |
~pattern:<name>:<patternstr> |
~pattern:mypatt:3,#ff0000,0.3,0 |
Play an inline pattern |
$ blink1-server &
# Device info
$ curl 'http://localhost:8934/blink1'
{
"blink1_serialnums": [ "AB0026C1" ],
"blink1_id": "DEADBEEFAB0026C1",
"status": "blink1 id"
}
# Fade to blue over 2.5 seconds on LED 2
$ curl 'http://localhost:8934/blink1/fadeToRGB?rgb=%230000ff&time=2.5&ledn=2'
{
"blink1_serialnums": [ "AB0026C1" ],
"lastColor": "#0000ff",
"lastTime": 2.5,
"lastMillis": 2500,
"lastLedn": 2,
"cmd": "fadeToRGB",
"status": "success"
}
# Blink red 5 times
$ curl 'http://localhost:8934/blink1/blink?rgb=%23ff0000&count=5&time=0.3'
# Play a built-in pattern
$ curl 'http://localhost:8934/blink1/pattern/play?pname=red+flash'
# Add and play a custom pattern
$ curl 'http://localhost:8934/blink1/pattern/add?name=police&pattern=6,%23ff0000,0.3,1,%230000ff,0.3,2,%23000000,0.1,0'
$ curl 'http://localhost:8934/blink1/pattern/play?pname=police'
# Stop all patterns
$ curl 'http://localhost:8934/blink1/pattern/stop'
# Play a meta-pattern inline (no pre-defined pattern needed)
$ curl 'http://localhost:8934/blink1/pattern/play?pname=~blink:%23ff00ff-3-0.5'Three test suites, all using the built-in node:test runner (no extra dependencies).
npm test # unit + HTTP integration — no device needed
npm run test:hardware # hardware-in-the-loop — skips if no device found
node --test test/blink1Service.test.js # single file| Suite | File | Requires device |
|---|---|---|
| blink1Service unit | test/blink1Service.test.js |
No |
| patternsService unit | test/patternsService.test.js |
No |
| apiServer HTTP integration | test/apiServer.test.js |
No |
| Hardware-in-the-loop | test/blink1Hardware.test.js |
Yes (skipped if absent) |
The hardware suite actually lights up the device — run it in an environment where that's acceptable. It covers device detection, fadeToColor, pattern playback, writePatternToBlink1, and all color/blink/pattern HTTP endpoints end-to-end.
var createBlink1Server = require('node-blink1-server');
var server = createBlink1Server({
apiConfig: { port: 8934, host: 'localhost' },
blink1Config: { deviceRescan: true, enableGamma: false },
patternsConfig: { playingSerialize: false },
patterns: [], // array of saved user pattern objects
});
// The server object is an EventEmitter
server.on('status', function(s) { console.log(s.type, s.text); });
server.on('deviceUpdated', function() { /* blink1 list changed */ });
server.on('patternsChanged', function(patterns) { /* persist patterns array */ });
server.on('configChanged', function(key, val) { /* persist config value */ });
server.start();
// Access underlying service singletons directly if needed
server.blink1Service.fadeToColor(500, '#ff0000', 0);
server.patternsService.playPatternFrom('myapp', 'red flash');
server.apiServer.stop(function() { console.log('stopped'); });| Option | Type | Description |
|---|---|---|
apiConfig |
object | { port, host } — HTTP server config |
blink1Config |
object | { deviceRescan, enableGamma, blink1ToUse, hostId } |
patternsConfig |
object | { playingSerialize } — serialize pattern playback |
patterns |
Array | Saved user pattern objects to pre-load |
logger |
object | Optional logger with .msg() and .error() methods |
| Event | Arguments | Description |
|---|---|---|
status |
{type, source, id, text} |
Service status / error updates |
deviceUpdated |
blink(1) device list changed | |
patternsChanged |
patternsArray |
User patterns were saved or deleted |
configChanged |
key, value |
A config value changed (e.g. hostId) |
| Feature | v1 | v2 |
|---|---|---|
| Named patterns | No | Yes — play, stop, add, delete |
| Multi-device | No | Yes — blink1_id on all endpoints |
| Pattern persistence | No | Via patternsChanged event |
| Library API | No | Yes — createBlink1Server() factory |
| Config system | None | Plain objects / CLI args |
| Events | None | EventEmitter on server object |