Accessing Xbox controller events in Node.JS on a Raspberry Pi
For a recent side project I needed access to events from an Xbox controller plugged into a Raspberry Pi via node.js.
For Mac I had been using the brilliant node-xbox-controller module. It had worked well, but after many hours of fighting I could not get it to work on the debain based Raspbian operating system. In the end I narrowed the problem down to something not working in the hidapi layer or below.
In order to receive the events I instead used a userspace driver called xboxdrv coupled with the node-joystick module.
This results in raw joystick events being passed into node.js. Each event has a value, a type (number or axis) and a number.
From there, I mapped each button from the raw events, into handy names using a nested structure:
var type = { button: { 0: { 1: "a:press", 0: "a:up" }, 1: { 1: "b:press", 0: "b:up" }, 2: { 1: "x:press", 0: "x:up" }, 3: { 1: "y:press", 0: "y:up" }, 5: { 1: "rb:press", 0: "rb:up" }, 4: { 1: "lb:press", 0: "lb:up" }, 8: { 1: "xbox:press", 0: "xbox:up" }, 6: { 1: "back:press", 0: "back:up" }, 7: { 1: "start:press", 0: "start:up" } }, axis: { 7: { 32767: "ddown:press", '-32767': "dup:press" }, 6: { 32767: "dright:press", '-32767': "dleft:press" } } }
The map is accessed as a big flat array:
var eventIsMapped = function(event){ if (!event.init && type[event.type] && type[event.type][event.number] && type[event.type][event.number][event.value] ) { return type[event.type][event.number][event.value]; } else { return false; } }
This can then be used to drive further code from a single interface.
joystick.on('button', function(event) { var action = eventIsMapped(event) console.log(actions[action]()); });
And there we go! From there I have a separate map to go from controller buttons to actions on the hue lights. The code in use can be found on my github account