Skip to content

Instantly share code, notes, and snippets.

@aetheryx
Last active May 2, 2020 14:24
Show Gist options
  • Save aetheryx/5e4b79e0edbdc1db3d53f765f2aad0cb to your computer and use it in GitHub Desktop.
Save aetheryx/5e4b79e0edbdc1db3d53f765f2aad0cb to your computer and use it in GitHub Desktop.
arctis-7-tasmota; a small application to map the ChatMix slider on the SteelSeries Arctis 7 to a smart bulb running Tasmota (https://youtu.be/X5MLXNftdC4)
const HID = require('node-hid');
const mqtt = require('mqtt');
const config = {
/**
* The amount of times (per second) your headset gets polled.
* Higher = smoother, but more battery-hungry.
* In my experience setting this higher than 100 will cause your headset, Windows, or both to shit themselves.
*/
pollingRate: 10,
/**
* Change this to your Tasmota MQTT broker IP.
*/
brokerIP: '192.168.178.20'
};
const constants = {
VENDOR_ID: 0x1038,
PRODUCT_ID: 0x12AD,
USAGE_ID: 0x202,
POLL_PAYLOAD: [ 0x06, 0x24 ],
DIMMER_COMMAND: 'cmnd/bulb/Dimmer'
};
console.log(
'='.repeat(80) + '\n\n' +
' '.repeat(32) + 'arctis-7-tasmota' + '\n\n' +
'A small application to map the ChatMix slider on the SteelSeries Arctis 7\n' +
'to a smart bulb running Tasmota (https://github.com/arendst/Sonoff-Tasmota).\n' +
'Use at your own risk; albeit unlikely, I\'m not liable for any bricked devices.\n' +
'You can see a short preview here: https://youtu.be/X5MLXNftdC4\n\n' +
'='.repeat(80) + '\n\n'
);
const deviceData = HID.devices()
.find(device => (
device.vendorId === constants.VENDOR_ID &&
device.productId === constants.PRODUCT_ID &&
(process.platform !== 'win32' ^ (device.usage === constants.USAGE_ID))
));
if (!deviceData) {
console.error('Unable to detect an Arctis 7 plugged in. Exiting...');
process.exit(1);
}
const device = new HID.HID(deviceData.path);
const client = mqtt.connect(`tcp://${config.brokerIP}`);
client.on('connect', () => {
console.log('Established connection with MQTT broker');
});
let oldValue = -1;
device.on('data', (payload) => {
if (oldValue === -1) {
console.log('Successfully polling position at', config.pollingRate, 'Hz');
}
const getValue = (offset) => (payload.readInt8(offset) / -64) * 100;
const [ game, chat ] = [ 2, 3 ].map(getValue);
const newValue = Math.abs(game || chat);
if (newValue !== oldValue) {
client.publish(
constants.DIMMER_COMMAND,
(oldValue = newValue).toString()
);
}
});
setInterval(() => {
try {
device.write(constants.POLL_PAYLOAD);
} catch (err) {
if (err.message === 'Cannot write to HID device') {
console.error(
'Failed at writing payload to device.',
'Try:\n',
' - Ensuring your polling rate isn\'t too high\n',
' - Ensuring you\'re running under sudo if you\'re not on Windows\n',
' - Ensuring your device is detected properly by SSE\n',
' - Turning your headset off, plugging the wireless transmitter out and back in, then turning your headset back on',
' - Reinstalling the device drivers entirely (including the 50 trillion entries under Windows\' Device Manager)',
);
} else {
console.error(err);
}
process.exit(1);
}
}, 1000 / config.pollingRate);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment