@wanderxjtu/homebridge-yeelighter
Version:
Yeelight support for Homebridge with particular support of ceiling lights
150 lines • 4.55 kB
JavaScript
"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