UNPKG

@wanderxjtu/homebridge-yeelighter

Version:

Yeelight support for Homebridge with particular support of ceiling lights

150 lines 4.55 kB
"use strict"; /** * Yeelight Device Handling. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Device = exports.EMPTY_DEVICEINFO = void 0; const node_events_1 = require("node:events"); const node_net_1 = __importDefault(require("node:net")); exports.EMPTY_DEVICEINFO = { location: "", id: "", model: "string", support: "string", power: false, bright: 0, color_mode: -1, ct: 0, rgb: "string", hue: 0, sat: 0, host: "string", port: 0, debug: false, trackedAttributes: [], fw_ver: "0,0.0", name: "string", }; /** * Handles the connection to a concrete Yee light. */ class Device extends node_events_1.EventEmitter { constructor(info) { super(); this.rest = ""; this.info = info; this.debug = this.info.debug || false; this.connected = false; this.forceDisconnect = false; } connect() { try { this.forceDisconnect = false; this.socket = new node_net_1.default.Socket({ allowHalfOpen: false }); this.bindSocket(); this.socket.connect({ host: this.info.host, port: this.info.port }, () => { this.didConnect(); this.emit("connected"); }); } catch (error) { this.socketClosed(error); } } disconnect(forceDisconnect = true) { var _a; this.forceDisconnect = forceDisconnect; this.connected = false; (_a = this.socket) === null || _a === void 0 ? void 0 : _a.destroy(); delete this.socket; this.emit("disconnected"); if (this.forceDisconnect && this.retryTimer) { clearTimeout(this.retryTimer); delete this.retryTimer; } } bindSocket() { var _a, _b, _c; (_a = this.socket) === null || _a === void 0 ? void 0 : _a.on("data", data => { this.didReceiveResponse(data); }); (_b = this.socket) === null || _b === void 0 ? void 0 : _b.on("error", error => { this.emit("socketError", error); this.socketClosed(error); }); (_c = this.socket) === null || _c === void 0 ? void 0 : _c.on("end", () => { this.emit("socketEnd"); this.socketClosed(); }); } socketClosed(error) { // console.log("Socket Closed", this.forceDisconnect); if (this.forceDisconnect) { return; } if (error) { if (error.message.includes("EHOSTUNREACH")) { // unreachable, no need to retry this.disconnect(true); } else { console.log(`Socket Closed with error "${error.name}"`, error.message); this.disconnect(false); } } else { this.disconnect(false); } if (error) { if (this.retryTimer) { clearTimeout(this.retryTimer); delete this.retryTimer; } this.retryTimer = setTimeout(this.connect.bind(this), 5000); } } didConnect() { this.connected = true; } didReceiveResponse(data) { const combined = this.rest + data.toString("utf8"); const dataArray = combined.split("\r\n"); this.rest = dataArray.pop() || ""; for (const dataString of dataArray) { if (dataString.length === 0) { continue; } try { const response = JSON.parse(dataString); if (response.id) { this.emit("deviceUpdate", response); } else { // invalid message (disabled logging since this seems to happen regularly for some lights) } } catch (error) { console.error(error, dataString); } } } sendCommand(data) { const cmd = JSON.stringify(data); if (this.connected && this.socket) { try { this.socket.write(cmd + "\r\n"); } catch (error) { this.socketClosed(error); } } } updateDevice(device) { this.info = device; } } exports.Device = Device; //# sourceMappingURL=yeedevice.js.map