UNPKG

unifi-client

Version:

NodeJs client for Unifi products (https://www.ui.com/)

291 lines (290 loc) 13.2 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UnifiWebsockets = void 0; var events_1 = require("events"); var ws_1 = __importDefault(require("ws")); var cookie_1 = __importDefault(require("cookie")); var EControllerEvents_1 = require("./events/EControllerEvents"); var util_1 = require("../util"); var debug = (0, util_1.createDebugger)('UnifiWebsockets'); var eventDebug = debug.extend('events'); var eventSendDebug = eventDebug.extend('send'); var eventReceivedDebug = eventDebug.extend('received'); var UnifiWebsockets = /** @class */ (function (_super) { __extends(UnifiWebsockets, _super); function UnifiWebsockets(props) { var _a, _b; var _this = _super.call(this) || this; _this.isClosed = true; _this.autoReconnectInterval = 5 * 1000; debug('constructor()'); //get controller _this.controller = props.controller; _this.url = props.url; _this.strictSSL = (_a = props.strictSSL) !== null && _a !== void 0 ? _a : true; _this.isController = (_b = props.isController) !== null && _b !== void 0 ? _b : false; //start websockets connexion // this.initWebSockets(props).catch((e) => { // this._emit('ctrl.error', e); // }); //register ws on globals _this.controller.UnifiWebSockets.push(_this); UnifiWebsockets.UnifiWebSockets.push(_this); return _this; } UnifiWebsockets.prototype.initWebSockets = function () { return __awaiter(this, void 0, void 0, function () { var cookies; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: debug('initWebSockets()'); return [4 /*yield*/, this.controller.auth.getCookies(false)]; case 1: cookies = _a.sent(); this.ws = new ws_1.default(this.url, { perMessageDeflate: false, rejectUnauthorized: this.strictSSL, headers: { Cookie: cookies.map(function (c) { return cookie_1.default.serialize(c.name, c.value, c); }).join('; ') } }); // init ping pong this.pingPongInterval = setInterval(function () { _this.ws.send('ping'); }, 15000); this.ws.on('open', function () { _this.isReconnecting = false; _this._emit(EControllerEvents_1.EControllerEvents.CONNECTION); }); this.ws.on('message', function (data) { if (data.toString() === 'pong') { _this._emit(EControllerEvents_1.EControllerEvents.PONG); return; } try { _this._handleEvent(data); } catch (err) { _this._emit(EControllerEvents_1.EControllerEvents.ERROR, err); } }); this.ws.on('close', function () { _this._emit(EControllerEvents_1.EControllerEvents.CLOSE); clearInterval(_this.pingPongInterval); _this._reconnect(); }); this.ws.on('error', function (err) { _this._emit(EControllerEvents_1.EControllerEvents.ERROR, err); clearInterval(_this.pingPongInterval); _this._reconnect(); }); return [2 /*return*/]; } }); }); }; /** * reconnect to websocket */ UnifiWebsockets.prototype._reconnect = function () { var _this = this; var curDebug = debug.extend('_reconnect'); curDebug('()'); if (!this.isReconnecting && !this.isClosed) { this.isReconnecting = true; setTimeout(function () { return __awaiter(_this, void 0, void 0, function () { var e_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); this._emit(EControllerEvents_1.EControllerEvents.RECONNECTION); this.isReconnecting = false; return [4 /*yield*/, this.initWebSockets()]; case 1: _a.sent(); return [3 /*break*/, 3]; case 2: e_1 = _a.sent(); curDebug('fail to reconnect %O', e_1); this._emit(EControllerEvents_1.EControllerEvents.FATAL_ERROR, e_1); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }, this.autoReconnectInterval); } else if (this.isReconnecting) { curDebug('reconnection already in progress'); } else { curDebug('socket is closed'); } }; /** * closes all the websockets */ UnifiWebsockets.closeSockets = function () { debug('static.closeSockets()'); this.UnifiWebSockets.forEach(function (s) { return s.close(); }); }; /** * close this websocket connection */ UnifiWebsockets.prototype.close = function () { debug('close()'); this.isClosed = true; this.ws.close(); }; /** * emit an event on multiple events emitter * @param event - an event * @param args - an args */ UnifiWebsockets.prototype._emit = function (event) { var _a, _b; var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } eventSendDebug.apply(void 0, __spreadArray([event], args, false)); //store the result about listeners var resEmit1 = this.emit.apply(this, __spreadArray([event], args, false)); this.emit.apply(this, __spreadArray(['*', event], args, false)); //emit global events (_a = this.controller.globalWS).emit.apply(_a, __spreadArray([event], args, false)); (_b = this.controller.globalWS).emit.apply(_b, __spreadArray(['*', event], args, false)); return resEmit1; }; /** * Handle event for a site * @param event - event */ UnifiWebsockets.prototype._handleSiteEvent = function (event) { var _this = this; var _a, _b, _c; var curDebug = debug.extend('_handleSiteEvent'); curDebug('()'); eventReceivedDebug('receive event'); eventReceivedDebug('meta : %O', event.meta); eventReceivedDebug('data : %O', event.data); if (((_a = event.meta) === null || _a === void 0 ? void 0 : _a.message) === 'events') { var evt = event; evt.data.forEach(function (subEvent) { var match = subEvent.key.match(/EVT_([A-Z]{2})_(.*)/); if (match) { var group = match[1], eventName = match[2]; _this._emit([group.toLowerCase(), eventName.toLowerCase()].join(':'), subEvent); } else { curDebug('unable to read the event key, %O', subEvent); } }); } else { var evtName = (_b = event.meta) === null || _b === void 0 ? void 0 : _b.message; if ((_c = event.meta) === null || _c === void 0 ? void 0 : _c.product_line) { evtName = "".concat(event.meta.product_line, ":").concat(evtName); } if (!evtName) { curDebug('fail to get name from meta : %O', event); evtName = 'unknown'; } this._emit(evtName, event.data); } }; /** * globally handle event * @param data - websocket data */ UnifiWebsockets.prototype._handleEvent = function (data) { var _a; var curDebug = debug.extend('_handleEvent'); curDebug('()'); var parsed; try { parsed = JSON.parse(data.toString()); } catch (e) { curDebug('fail to parse event'); curDebug(e); } if (this.isController) { var event_1 = parsed; this._emit((_a = event_1 === null || event_1 === void 0 ? void 0 : event_1.type) !== null && _a !== void 0 ? _a : 'unknown', event_1); } else { this._handleSiteEvent(parsed); } }; // static UnifiWebSockets: Array<UnifiWebsockets> = []; UnifiWebsockets.globalWS = new events_1.EventEmitter(); UnifiWebsockets.UnifiWebSockets = []; return UnifiWebsockets; }(events_1.EventEmitter)); exports.UnifiWebsockets = UnifiWebsockets;