Last active
March 5, 2018 15:57
-
-
Save biern/cead0c0a92cb766c5f04f1a17ea9c45e to your computer and use it in GitHub Desktop.
Yeelight Screen Ambience
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
'use strict'; | |
const Color = require("color"); | |
const Yeelight = require('node-yeelight-wifi'); | |
const robot = require('robotjs'); | |
const net = require('net'); | |
const os = require('os'); | |
const R = require('ramda'); | |
const SERVER_PORT = 32167; | |
const MY_IP = guessIP(); | |
const updateInterval = 100; | |
function run() { | |
const screenSize = robot.getScreenSize(); | |
const effectDuration = updateInterval * 3 / 4; | |
const sockets = []; | |
const bulbs = []; | |
const server = net.createServer((socket) => { | |
console.log('New socket connection'); | |
sockets.push(socket); | |
}); | |
server.listen(SERVER_PORT, '0.0.0.0'); | |
const look = new Yeelight.Lookup(); | |
look.on("detected", (light) => { | |
console.log(`New bulb detected: id ${light.id} name ${light.name}`); | |
bulbs.push(light); | |
light.sendCommand('set_music', [1, MY_IP, SERVER_PORT]); | |
}); | |
setInterval(() => { | |
const pixels = getScreenStrip(screenSize); | |
const ambience = getPixelsAmbience(pixels); | |
updateBulbs(sockets, bulbs, ambience, effectDuration); | |
}, updateInterval); | |
} | |
function updateBulbs(sockets, bulbs, { rgb, brightness }, duration) { | |
const rgbNumber = Color.rgb(rgb).rgbNumber(); | |
const brightnessPercent = brightness * 100; | |
for (let socket of sockets) { | |
for (let bulb of bulbs) { | |
sendCommand( | |
socket, bulb, "set_rgb", [rgbNumber, "smooth", duration]); | |
sendCommand( | |
socket, bulb, "set_bright", [brightnessPercent, "smooth", duration]); | |
} | |
} | |
} | |
function sendCommand(socket, bulb, method, params) { | |
const msg = { | |
id: bulb.id, | |
method, | |
params, | |
}; | |
socket.write(JSON.stringify(msg) + "\r\n"); | |
} | |
const easeOutQuad = (t) => t * (2 - t); | |
function getPixelsAmbience(pixels) { | |
let r = 0; | |
let g = 0; | |
let b = 0; | |
for (let pixel of pixels) { | |
r += pixel[0]; | |
g += pixel[1]; | |
b += pixel[2]; | |
} | |
r /= pixels.length; | |
g /= pixels.length; | |
b /= pixels.length; | |
const brightnessBase = ((r + g + b) / (3 * 255)); | |
const brightness = easeOutQuad(brightnessBase); | |
console.log('RGB:', [r, g, b]); | |
console.log('Brightness: ', brightness); | |
return { brightness, rgb: [r, g, b] }; | |
} | |
function getScreenStrip({ width, height }) { | |
const img = robot.screen.capture(0, height / 3, width, 5); | |
const count = 100; | |
const result = []; | |
for (let i = 0; i < count; i++) { | |
const hex = img.colorAt(Math.floor(img.width * (i / count)), 0); | |
result.push([ | |
parseInt(hex.slice(0, 2), 16), | |
parseInt(hex.slice(2, 4), 16), | |
parseInt(hex.slice(4, 6), 16), | |
]); | |
} | |
return result; | |
} | |
function guessIP() { | |
const external = R.pipe( | |
R.values, | |
R.unnest, | |
R.filter((iface) => 'IPv4' === iface.family && !iface.internal), | |
)(os.networkInterfaces()); | |
if (!external.length) { | |
throw new Error("No interfaces found"); | |
} | |
const ip = external[0].address; | |
console.log('Guessed host IP address', ip); | |
return ip; | |
} | |
run(); |
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
{ | |
"name": "yeelight", | |
"version": "1.0.0", | |
"description": "", | |
"main": "main.js", | |
"dependencies": { | |
"desktop-screenshot": "^0.1.1", | |
"node-yeelight-wifi": "^0.1.2", | |
"ramda": "^0.25.0", | |
"robotjs": "^0.4.7", | |
"yeelight.js": "^1.0.1" | |
}, | |
"devDependencies": {}, | |
"author": "Marcin Biernat", | |
"license": "MIT" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment