Skip to content
NodeJS API for Jaxcore Spin, the programmable dial remote control
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Jaxcore Spin

NodeJS library for Jaxcore Spin, the programmable wifi dial remote control.


npm install jaxcore-spin

Example Script

var Spin = require('jaxcore-spin');

Spin.connectAll(function (spin) {
	spin.on('spin', function (direction, position) {
		console.log('spin', direction, position);
	spin.on('knob', function (pushed) {
		console.log('knob', pushed);
	spin.on('button', function (pushed) {
		console.log('button', pushed);

Save as test.js and run:

node test.js

Then turn on your Jaxcore Spin device, configure it for your wifi network, and it will auto-connect to the test script and begin printing the log when the knob is spun, or the button or knob is pushed.

If you do not own a Jaxcore Spin, try the web-based Spin Simulator which will launch a simulation of the device and appear on the network using the same TCP/UDP protocol that the physical devices implement.


See the /examples directory for test scripts.

Also see:

  • Spin-Synth - an html5 audio keyboard controlled by the Spin

  • Spin-A-Sketch - an html5 canvas etch-a-sketch game controlled by two Spin devices

Static Methods

  • Spin.debug(on) -- turn on verbose debugging
  • Spin.create(device) -- factory method for instantiating Spin instances, use the device object provided by the scan, connectAll, connectOne, connectTo, connectUSB, or connectUSBDevice static methods

  • Spin.scan(callback) -- low level scan, receives pings from all Jaxcore Spin devices

Spin.scan(function(device, done, rescan) {
	console.log('received ping from ';

	var spin = Spin.create(device);
	spin.on('spin', function(direction) {
		console.log('spinning', direction);
  • Spin.connectAll(callback) -- greedily connect all Jaxcore Spins (wifi and usb), this is a short-hand version of using both scan() and connectUSB()
Spin.connectAll(function(spin) {
  • Spin.connectOne(callback) -- greedily connect only one Jaxcore Spin then stop scanning, after the device is disconnected or turned off this method will automatically connect next available Jaxcore Spin
Spin.connectOne(function(spin) {
  • Spin.connectTo(id, callback) - connect to a specific Jaxcore Spin by its unique ID
Spin.connectTo('D3F5A3DS80', function(spin) {
  • Spin.connectUSB(callback) -- connect any Spin devices connected by USB cable
Spin.connectUSB(function(spin) {
	console.log('connected by USB',, spin.usbDevice);
  • Spin.connectUSB(id, callback) -- connect a specific Spin device by USB
Spin.connectUSB('D3F5A3DS80', function(spin) {
	console.log('connected by USB',, spin.usbDevice);
  • Spin.connectUSBDevice(devicePath, callback) -- connect any Spin to a specific USB device path
Spin.connectUSBDevice('/dev/DFN199', function(spin) {
	console.log('connected by USB',, spin.usbDevice);

Spin Instance Methods

Method Arguments Description
connect() connect the Spin device, the Spin device will open a TCP communication channel to the Spin NodeJS server
disconnect() disconnect the Spin device from the Spin NodeJS server
isConnected() returns boolean whether the device is connected to the NodeJS Server
flash(color, repeat) color array RGB color array
repeat integer (0-3) number of times to repeat the flash
Flash all LEDs the same color, eg. spin.flash([0,255,0]) will flash green once for 2s
spin.flash([255,0,0],2) will flash red twice for 1s each
quickFlash(color) color array RGB color array flashes all LEDs for 200ms, eg spin.flash([255,255,0]]
quickFlashSingle(color, index) color array RGB color array
index integer the led to flash (0 to 23)
flash a single LED for 200ms, eg spin.quickFlashSingle([0,0,255],0)
lightsOn(color) color array RGB color array turns all LEDs on until they are specifically turned off
lightsOff() turns all LEDs off
setThrottle(throttle) throttle integer data rate limit in milliseconds, default is 20ms eg. spin.setThrottle(100) will restrict TCP communications to every 100ms
setBrightness(brightness) brightness integer 0 to 255 sets the LED brightness, all configured color patterns will be scaled by this brightness level
setRotateColors(mode, colorLeft, colorRight) mode integer 0,1,2
colorLeft array RGB color array, colorRight array RGB color array
configure the LED rotation pattern colors
rotate(direction, mode) direction integer 1 or -1
mode integer 0, 1, 2
shine the LED lights in a rotation pattern (eg. navigation)
setScaleColors(mode, colorLow, colorHigh, colorMid) mode integer 0,1,2
colorLow array RGB color array for below the scale() percent
colorHigh array RGB color array above the scale() percent
colorMid array RGB color array for the midpoint
configures the LED rotation pattern colors, eg. spin.setScaleColors(0,[255,0,0], [0,0,255], [255,255,255]) will set mode 0 to be red/blue with a white midpoint
scale(percent, mode) percent float percentage ratio 0.0 to 1.0
mode integer 0,1,2
shine the LED lights in a linear scale pattern (eg. volume bar)
sleep() immediately go to low-power sleep mode
delaySleep() delays sleep mode (same thing as pressing a button or spinning the knob)
setSleepEnabled(enabled) enabled boolean true for sleep mode, false for never sleep enables or disabled sleep mode
setSleepTimer(ms) ms integer number of milliseconds of inactivity sets amount of inactivity before the device goes into low-power sleep mode

Instance Method Examples

var Spin = require('jaxcore-spin');

Spin.connectAll(function(spin) {

	spin.setScaleColors(0,[255,0,0], [0,0,255], [255,255,255])

	// flash green when connected
	spin.on('connect', function() {
	// rotate the LEDs color depending on button/knob pushes
	spin.on('spin', function(direction) {
		if (spin.knobPushed) spin.rotate(direction, 1);
		if (spin.buttonPushed) spin.rotate(direction, 2);
		else spin.rotate(direction, 0);
  	// shine blue when the button is pushed
	spin.on('button', function(pushed) {
		if (pushed) {
		else {


All public properties are exposed in a ReactJS-style .state child property and can be read at any time or watched for in the events (below).

State Type Description
brightness integer brightness value between 0 and 255
buttonPushed boolean true when the button is pushed
buttonPushTime Date timestamp of when the button was last pushed
buttonReleaseTime Date timestamp of when the button was last released
buttonPushDuration integer elapsed time the knob has been pushed in milliseconds
buttonHold boolean true when the button has been held down for 2 seconds, configurable with setButtonHoldThreshold()
buttonHoldThreshold integer determines how long pushing the button activates the hold events, configurable with setButtonHoldThreshold()
connected boolean true when the devices is connected to a Spin NodeJS service
spinPosition integer absolute position index
spinDirection integer direction (1 or -1) rotated relative to the previous spin event
spinPreviousTime Date timestamp of the previous spin event
spinTime Date Date of the most recent spin event
knobPushed boolean true when the knob is pushed
knobPushTime Date timestamp of when the knob was last pushed
knobReleaseTime Date timestamp of when the knob was last released
knobPushDuration integer elapsed time the knob has been pushed in milliseconds
knobHold boolean true when the knob has been held down for 2 seconds, configurable with setKnobHoldThreshold()
knobHoldThreshold integer determines how long pushing the knob activates the hold events, configurable with setKnobHoldThreshold()
batteryVoltage integer battery voltage, typically between 2.7 and 4.2 Volts, shows as 5 Volts while charging
batteryPercent integer battery percentage as a ratio betwen 0.0 (2.7V minimum charge) and 1.0 (4.2V fully charged)
isCharging boolean true when the device is plugged into a USB charger
isCharged boolean true when the battery is fully charged (charging LED shines green)
sleepEnabled boolean true when the sleep mode is enabled, configurable with setSleepEnabled()
sleeping boolean true when the device has notified that has gone to sleep
sleepTimer integer sleep timer in milliseconds, configurable with setSleepTimer()
inactivityTime integer milliseconds since last activity

Properties Examples

var Spin = require('jaxcore-spin');

Spin.connectAll(function(spin) {

	spin.on('connected', function() {
		console.log('spin battery at '+ (Math.round(spin.state.batteryPercent*100*10)/10) + '%');
	spin.on('spin', function(direction) {
		console.log('spin position=' + spin.state.spinPosition);
  	spin.on('button', function(pushed) {
		if (!pushed) { // if released
			console.log('button held for ' + spin.state.buttonPushDuration + ' ms');


Event Parameters Description (emitted when)
connect the device has connected to the NodeJS spin service
battery batteryVoltage integer voltage between 2.7 and 4.2 or 5 while charging battery voltage has changed
disconnect the device has disconnected from the NodeJS spin service
knob pushed boolean knob is pushed or released
knob-hold knob is held for more than 2 seconds
knob-press knob is released after having been held for less than 2 seconds
knob-longpress knob is released after having been held for more than 2 seconds
button pushed boolean button is pushed or released
button-hold button is held for more than 2 seconds
button-press button is released after having been held for less than 2 seconds
button-longpress button is released after having been held for more than 2 seconds
charged charged boolean true when fully charged battery is fully charged or starts getting drawn down
charging charging boolean true while plugged in device has been plugged or unplugged from a USB charging port
settings-changed changes object hardware settings such as brightness, knobHoldThreshold, buttonHoldThreshold, sleepEnabled, or sleepTimer havechanged
sleep-warning the 15 second sleep warning (yellow flashes) has activated
sleeping device has entered sleep mode
spin direction integer (1 or -1) direct knob has been rotated
position integer absolute position index
the knob has been rotated
update changes object any property has been changed

Spin Buffer

Jaxcore Spin's resolution of 32 pulses per revolution is often too precise for many things you may want to do with the device, particularly when navigating menus. To reduce the resolution (ie. to slow the device down) the Spin Buffer can be used to absorb some of the spin events.

The Spin Buffer uses a combination of 3 types of buffer strategies (static, kinetic, and momentum) and a delay mechanism giving many ways to improve usability.

Spin Buffer API:

Create a spin buffer:

  • new Spin.Buffer( spin, bufferConfig )

spin: an instance of Spin() supplied by Spin.scan or Spin.connect() bufferConfig: sets alternative configuration options:

var bufferConfig = {
    staticTimeout: 2000,    // how many seconds of inactivity re-activates static buffer (default 3s)
    defaultDelay: 1000     // sets the default .delay() length of time in ms

Spin Buffer Methods

  • buffer.spin( direction, kineticBufferSize, staticBufferSize )

Updates the buffer and returns true if either the static or kinetic buffer has has been overflowed.

  • direction: is the direction parameter supplied from a spin event
  • kineticBufferSize: how many spin events to skip until the kinetic buffer is overflowed
  • staticBufferSize: how many spin events to skip before the static buffer is overflowed

The kinetic buffer is active while the Spin's knob is rotating in one direction. When the knob is idle for more than 2 seconds or it's direction of rotation is changed, the static buffer becomes active.


spin.on('spin', function (direction) {
    if (buffer.spin( direction, 4, 3 )) {
        /* your spin even handler code goes here */
  • buffer.delay( delayTime )

delayTimeamount of time in milliseconds to ignore spin events (optional, default is 500ms)

  • buffer.reset()

Resets the static buffer. This is the same as leaving the knob inactive for more than 3 seconds.

Spin Buffer Example:

var Spin = require('jaxcore-spin');
Spin.connectAll(function (spin) {
	var buffer = new Spin.Buffer(spin);
    spin.on('button', function(pushed) {
    	if (pushed) {
    		// reset static buffer when the button is pushed
    	else {
    	    // ignore all spin events for 2 seconds after releasing the button
	spin.on('spin', function (direction) {
		if (buffer.spin(direction, 1, 3)) {
			// kinetic buffer of 1 will skip every other spin event
			// static buffer of 3 will skip 3 spin events when changing directions or idle for 2s
		    console.log('spin', direction);
		else {

Momentum Timeout


You can’t perform that action at this time.