-
-
Save zombrodo/e3fd9e987caeac67141e701cb49465c8 to your computer and use it in GitHub Desktop.
HID controller for WoW
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ----------------------------------------------------------------------------- | |
// Screenshot | |
// ----------------------------------------------------------------------------- | |
const exec = require("child_process").exec; | |
const Jimp = require("jimp"); | |
function tempPath() { | |
return "/tmp/healthbar-screenshot.png"; | |
} | |
const dimensions = [1009, 893, 240, 1]; | |
async function captureScreenshot() { | |
const filepath = tempPath(); | |
const command = [ | |
"screencapture", "-x", "-R", dimensions.join(), "-t", "png", filepath | |
].join(" "); | |
return new Promise((resolve, reject) => { | |
exec(command, (err => { | |
if (err) { | |
reject(err); | |
} | |
resolve(); | |
})) | |
}); | |
} | |
function kindaEquals(a, b) { | |
return Math.abs(a - b) < 5 | |
} | |
function coloursEqual(a, b) { | |
return kindaEquals(a.r, b.r) && kindaEquals(a.g, b.g) && kindaEquals(a.b, b.b); | |
} | |
function findRatio(image, healthy) { | |
const length = image.getWidth(); | |
let ratio = 0; | |
for(let x = 0; x < length; x++) { | |
if (coloursEqual(healthy, Jimp.intToRGBA(image.getPixelColor(x, 0)))) { | |
ratio++; | |
} | |
} | |
return ratio / length; | |
} | |
async function analysePicture() { | |
const filepath = tempPath(); | |
const image = await Jimp.read(filepath); | |
const health = Jimp.intToRGBA(image.getPixelColor(0, 0)); | |
return findRatio(image, health); | |
} | |
// ----------------------------------------------------------------------------- | |
// Keyboard | |
// ----------------------------------------------------------------------------- | |
const HID = require("node-hid"); | |
const VENDOR_ID = 0x3434; | |
const PRODUCT_ID = 0x0311; | |
const COMMAND_START = 0x00; | |
const BACKLIGHT_CONFIG_SET_VALUE = 0x07; | |
const QMK_RGBLIGHT = 0x83; | |
function padArray(input) { | |
const result = new Array(33).fill(0); | |
input.forEach((b, i) => result[i] = b); | |
return result; | |
} | |
const green = 64 | |
const red = 0; | |
function lerp(a, b, t) { | |
return a + (b - a) * t; | |
} | |
function connectDevice() { | |
const device = new HID.HID(VENDOR_ID, PRODUCT_ID); | |
return device | |
} | |
function setColour(device, ratio) { | |
const hue = lerp(red, green, ratio); | |
try { | |
const command = [COMMAND_START, BACKLIGHT_CONFIG_SET_VALUE, QMK_RGBLIGHT, hue, 0xff]; | |
const padded = padArray(command); | |
device.write(padded.slice(0, padded.length - 1)) | |
} catch(err) { | |
console.error(err); | |
} | |
} | |
// ----------------------------------------------------------------------------- | |
// Entrypoint | |
// ----------------------------------------------------------------------------- | |
async function iteration(device) { | |
await captureScreenshot(); | |
const ratio = await analysePicture(); | |
setColour(device, ratio) | |
} | |
function run() { | |
const device = connectDevice(); | |
process.on("SIGINT", () => { | |
device.close(); | |
process.exit(); | |
}); | |
setInterval(async () => { | |
await iteration(device); | |
}, 1000) | |
} | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment