Node.js如何定时获取屏幕平均色同步控制Yeelight智能灯泡
问题根因
问题出在setInterval的回调参数声明上:你给setInterval的回调定义了形参light,这个形参会覆盖外层detected事件回调中拿到的正常灯泡实例,且调用setInterval时没有传入对应实参,导致回调内部的light是undefined,自然无法调用setRGB方法。
最简修复方案
直接删除setInterval回调里多余的light形参,复用外层作用域的有效灯泡实例即可,同时把间隔时间改成你需要的2000毫秒:
const screenshot = require("screenshot-desktop"); const average = require("image-average-color"); const Lookup = require("node-yeelight-wifi").Lookup; let look = new Lookup(); look.on("detected", async (light) => { if (light.id == "mybulb") { // 仅修改这里:删掉回调的(light)形参,时间改成2000 setInterval(() => { screenshot() .then((img) => { average(img, (err, color) => { if (err) throw err; light .setRGB(color) .then(() => { console.log("success"); }) .catch((error) => { console.log("failed", error); }); }); }) .catch((err) => { console.log(err); }); }, 2000); } });
优化版方案(推荐)
可以通过async/await改写避免回调地狱,同时加执行锁避免前一次任务未完成、下一次任务就触发导致的调用堆积:
const screenshot = require("screenshot-desktop"); const average = require("image-average-color"); const Lookup = require("node-yeelight-wifi").Lookup; let look = new Lookup(); // 执行锁,避免任务重复触发 let isTaskRunning = false; look.on("detected", async (light) => { if (light.id == "mybulb") { setInterval(async () => { if (isTaskRunning) return; isTaskRunning = true; try { const img = await screenshot(); // 把回调形式的average转为Promise调用 const color = await new Promise((resolve, reject) => { average(img, (err, color) => err ? reject(err) : resolve(color)); }); // 如果average返回的是rgba格式,取前三个值传给setRGB即可:color.slice(0,3) await light.setRGB(color); console.log("success"); } catch (err) { console.log("执行出错:", err); } finally { // 不管成功失败都释放锁 isTaskRunning = false; } }, 2000); } });
内容的提问来源于stack exchange,提问作者kutaykurt
相关产品推荐
相关产品推荐

