UNPKG

teoclits

Version:

Typescript angular Teonet Client module

599 lines 21.2 kB
/* * The MIT License * * Copyright 2017 Kirill Scherba <kirill@scherba.ru>. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); import { Injectable } from '@angular/core'; import { TeonetAuth } from './teocli.auth'; import { TeocliRTC } from './teocli.webrtc'; ; export var Teonet = { peer: { l0: 'ps-server', auth: 'teo-auth' }, status: { offline: 0, connecting: 1, logining: 2, online: 3 } }; var TeonetCli = /** @class */ (function (_super) { __extends(TeonetCli, _super); function TeonetCli() { var _this = this; console.debug("TeonetCli::constructor"); var connect_url = 'ws://' + 'teomac.ksproject.org:80' + '/ws'; var ws = new WebSocket(connect_url); _this = _super.call(this, ws) || this; _this.status = Teonet.status.connecting; _this.isTeonetClientsActiveFunc = function () { return true; }; _this.connect_url = connect_url; _this.RECONNECT_TIMEOUT = 1000; _this.INIT_TIMEOUT = 7000; _this.inited = false; _this.eventSubscribers = []; _this.ws = ws; _this.init(); return _this; } TeonetCli.prototype.init = function () { var _this = this; var authserver = new TeonetAuth(this); // When connected to websocket this.onopen = function (ev) { console.debug("TeonetCli::teocli.onopen"); // Prepare client name _this.status = Teonet.status.logining; if (!_this.client_name) { // Get name from local storage var user = authserver.storage.get(); console.debug("TeonetCli::init user", user); if (user.remember_me && user.accessToken) { _this.setClientName(user.accessToken); } else { _this.setClientName('teoclits-' + Math.floor((Math.random() * 100) + 1)); } } // Send login command to teonet L0 server _this.login(_this.client_name); // Set reconnect timeout (reconnect if does not login during timeout setTimeout(function () { if (!_this.isInit()) { console.debug("TeonetCli::teocli.onopen can't login - disconnect"); _this.disconnect(); } }, _this.INIT_TIMEOUT); }; // When disconnect from web socket (reconnect) // Send 'teonet-close' to subscribers this.onclose = function (ev) { console.debug("TeonetCli::teocli.onclose"); // Reconnect after timeout setTimeout(function () { delete _this.ws; _this.status = Teonet.status.connecting; _this.ws = new WebSocket(_this.connect_url); _this.ws.onopen = _this.onopen; _this.ws.onclose = _this.onclose; _this.ws.onerror = _this.onerror; _this.ws.onmessage = function (ev) { if (!_this.process(ev.data)) { //if (typeof this.onmessage === 'function') { // this.onmessage(ev); //} } }; }, _this.RECONNECT_TIMEOUT); _this.sendEvent(TeonetCli.EVENT.TEONET_CLOSE); _this.status = Teonet.status.offline; _this.inited = false; }; // When get websocket error this.onerror = function (ev) { }; // When get 'onother' message fom webspcket. Check cmd 96 - teo-auth answer // Send 'teonet-init' to subscribers // Send 'onother' to subscribers this.onother = function (err, data) { console.debug("TeonetCli::onother", err, data); var processed = 0; var d = data; // Check login answer if (d && d.cmd === 96) { console.debug("TeonetCli:: Got check login answer", d); // Set name _this.setClientName(d.data.name); // Get user from storage var user = authserver.storage.get(); // Send teocli-init event var sendEventInit_1 = function (loggedin) { if (loggedin === void 0) { loggedin = false; } _this.sendEvent(TeonetCli.EVENT.TEONET_INIT); _this.status = Teonet.status.online; _this.inited = true; if (loggedin) _this.sendEvent(TeonetCli.EVENT.TEONET_LOGGEDIN); //$rootScope.networksItems = data.data.networks; }; // Login success if (_this.getClientName() == user.userId + ':' + user.clientId) { sendEventInit_1(true); } else { // Login with saved email and password if remember_me is set if (user.remember_me) { //authserver.refresh(); // refresh auth token authserver.login(user.email, authserver.base64.decode(user.password), function (err, response) { if (err) { // Goto Login screen sendEventInit_1(); _this.loginPage(); } else { // Reconect with new client name _this.setClientName(authserver.getUser().accessToken); _this.disconnect(); } }); } else { sendEventInit_1(); _this.loginPage(); } } processed = 1; } if (!processed) _this.sendEvent('onother', data); return processed; }; // Send 'onecho' to subscribers this.onecho = function (err, data) { console.debug("TeonetCli::onecho", err, data); _this.sendEvent('onecho', data); return 1; }; // Send 'onclients' to subscribers this.onclients = function (err, data) { console.debug("TeonetCli::onclients", err, data); _this.sendEvent('onclients', data); return 1; }; // Send 'onpeers' to subscribers this.onpeers = function (err, data) { console.debug("TeonetCli::onpeers", err, data); _this.sendEvent('onpeers', data); return 1; }; }; /** * Disconnect TeonetCli * */ TeonetCli.prototype.disconnect = function () { this.ws.close(); }; TeonetCli.prototype.getConnectUrl = function () { return this.connect_url.replace('ws://', '').replace('/ws', ''); }; TeonetCli.prototype.setConnectUrl = function (url) { this.connect_url = 'ws://' + url + '/ws'; }; /** * Sel login page */ TeonetCli.prototype.setLoginPage = function (func) { this.login_page = func; }; /** * Load Login page */ TeonetCli.prototype.loginPage = function (push) { if (push === void 0) { push = undefined; } if (this.login_page) this.login_page(push); else { alert('TODO: Login page is udefined!'); } }; /** * Sel SignUp page */ TeonetCli.prototype.setSignupPage = function (func) { this.signup_page = func; }; /** * Load SignUp page */ TeonetCli.prototype.signupPage = function (push) { if (push === void 0) { push = undefined; } if (this.signup_page) this.signup_page(push); else { alert('TODO: SignUp page is udefined!'); } }; /** * Sel Restore page */ TeonetCli.prototype.setRestorePage = function (func) { this.restore_page = func; }; /** * Load Restore page */ TeonetCli.prototype.restorePage = function (push) { if (push === void 0) { push = undefined; } if (this.restore_page) this.restore_page(push); else { alert('TODO: Restore page is udefined!'); } }; /** * Is TeonetCli connected and initialized * * @returns {boolean} True if connected and initialized */ TeonetCli.prototype.isInit = function () { return this.inited; }; /** * Get teonet status * * @return {number} Teonet status */ TeonetCli.prototype.getStatus = function () { return this.status; }; /** * Get client name * * @return {string} Teonet client name */ TeonetCli.prototype.getClientName = function () { return this.client_name; }; /** * Set client name * * @return {string} Teonet client name */ TeonetCli.prototype.setClientName = function (name) { if (name === void 0) { name = ''; } this.client_name = name; }; /** * Subscribe to even * * @param {eventSubscribersFunc} func */ TeonetCli.prototype.subscribe = function (func) { this.eventSubscribers.push(func); return func; }; /** * Unsubscribe from event * * @param {eventSubscribersFunc} func */ TeonetCli.prototype.unsubscribe = function (func) { this.eventSubscribers = this.eventSubscribers.filter(function (f) { return f !== func; }); }; /** * Send event to Event Subscribers * * @param {string} ev Event name * @param {object[]) ...obj Objects send to subscribers */ TeonetCli.prototype.sendEvent = function (ev) { var obj = []; for (var _i = 1; _i < arguments.length; _i++) { obj[_i - 1] = arguments[_i]; } for (var _a = 0, _b = this.eventSubscribers; _a < _b.length; _a++) { var func = _b[_a]; func(ev, obj); } _super.prototype.sendEvent.call(this, ev, obj); // Send event to parrent class }; TeonetCli.prototype.whenEvent = function (event, func) { return this.subscribe(function (ev) { var obj = []; for (var _i = 1; _i < arguments.length; _i++) { obj[_i - 1] = arguments[_i]; } if (ev == event) { func(obj); } return 0; }); }; TeonetCli.prototype.whenInit = function (func) { if (this.isInit()) func(); return this.whenEvent(TeonetCli.EVENT.TEONET_INIT, function () { func(); return 0; }); }; TeonetCli.prototype.whenClose = function (func) { return this.whenEvent(TeonetCli.EVENT.TEONET_CLOSE, function () { func(); return 0; }); }; TeonetCli.prototype.isTeonetClientsActive = function () { return this.isTeonetClientsActiveFunc(); }; TeonetCli.prototype.setTeonetClientsActive = function (func) { this.isTeonetClientsActiveFunc = func; }; TeonetCli.EVENT = { TEONET_INIT: 'teonet-init', TEONET_CLOSE: 'teonet-close', TEONET_LOGGEDIN: 'teonet-loggedin' }; TeonetCli.decorators = [ { type: Injectable }, ]; /** @nocollapse */ TeonetCli.ctorParameters = function () { return []; }; return TeonetCli; }(TeocliRTC)); export { TeonetCli }; ; import { Component } from '@angular/core'; import { IntervalObservable } from 'rxjs/observable/IntervalObservable'; import { TeonetClientsNum } from './teocli.clients'; var TeonetStatus = /** @class */ (function () { /** * Constructor connect to Teonet and load TeonetClientsNum class */ function TeonetStatus(t) { this.t = t; this.peer = ''; //! Peer name Component input this.label = 'Teo is'; //! Label of state Component input this.reconnect = 'true'; //! Reconnect when peer don't answer this.show_peer = 'false'; //! Show peer name Component input this.time = (this.t.status == Teonet.status.online) ? 0 : -1; //! Peer answer time in ms this.last_answere = 0.00; //! Last peer answer time this.SEND_ECHO_AFTER = 1.00; //! Send echo after timeout this.SET_LOGOFF_AFTER = 3.00; //! Set status logoff after timeout this.RECONNECT_AFTER = 8.00; //! Reconnect after timeout console.debug('TeonetStatus::constructor, peer = ' + this.peer); this.tcli = new TeonetClientsNum(t); } /** * This function calls by angular after html content init */ TeonetStatus.prototype.ngAfterContentInit = function () { var _this = this; console.debug('TeonetStatus::ngAfterContentInit, peer = ' + this.peer + ', reconnect: ' + this.reconnect); if (this.peer) { //Send ping to peer this.sendEcho(); IntervalObservable.create(1000).subscribe(function () { if (_this.t.isInit()) { var date = new Date(); var current = date.valueOf() / 1000.0; if ((current - _this.last_answere) > _this.SEND_ECHO_AFTER) { _this.sendEcho(); } if (!_this.last_answere) _this.last_answere = current; if (_this.time >= 0 && _this.last_answere && (current - _this.last_answere) > _this.SET_LOGOFF_AFTER) { console.debug('TeonetStatus::IntervalObservable - set "peer logoff"'); _this.time = -1; } if (_this.last_answere && (current - _this.last_answere) > _this.RECONNECT_AFTER && _this.reconnect == 'true') { console.debug('TeonetStatus::IntervalObservable' + '- disconnect from teonet, ' + '(current - this.last_answere) = ', (current - _this.last_answere)); _this.last_answere = 0; _this.t.disconnect(); } } else _this.time = -1; }); // Process echo answer this.t.whenEvent('onecho', function (data) { var d = data[0][0]; console.debug('TeonetStatus::onecho', data, d, 'this.peer:', _this.peer); if (d.from == _this.peer) { var date = new Date(); _this.time = d.data.time; _this.last_answere = date.valueOf() / 1000.0; console.debug('TeonetStatus::onecho this.last_answere:', _this.last_answere); } return 0; }); } }; /** * Send ping to peer */ TeonetStatus.prototype.sendEcho = function () { console.debug('TeonetStatus::sendEcho to peer: ' + this.peer); this.t.echo(this.peer, 'TeonetStatus'); }; /** * Return true if Teonet is online * @return {boolean} */ TeonetStatus.prototype.ifOnline = function () { return this.t.status == Teonet.status.online; }; /** * Return true if peer input is set * * @param {string} peer Peer name */ TeonetStatus.prototype.ifPeer = function (peer) { if (peer) return true; else return false; }; /** * Get Teonet status color * * @param {number} Teonet status * @return Teonet status color string */ TeonetStatus.prototype.getStatusColor = function (status) { var color; switch (status) { case Teonet.status.offline: color = 'danger'; break; case Teonet.status.connecting: color = 'dark'; break; case Teonet.status.logining: color = 'primary'; break; case Teonet.status.online: color = 'secondary'; break; default: color = 'light'; } return color; }; /** * Get name of Teonet status * * @param {number} Teonet status * @return Teonet status string */ TeonetStatus.prototype.getStatusText = function (status) { var text; switch (status) { case Teonet.status.offline: text = 'Offline'; break; case Teonet.status.connecting: text = 'Connecting...'; break; case Teonet.status.logining: text = 'Logining'; break; case Teonet.status.online: text = 'online'; break; default: text = ''; } return text; }; TeonetStatus.decorators = [ { type: Component, args: [{ selector: 'teonet-status', inputs: ['peer', 'label', 'show_peer', 'reconnect'], styles: ['\n\ .teonet-status { \n\ opacity: 0.85;\n\ position: relative;\n\ float: right;\n\ right: 20px;\n\ top: 10px;\n\ /*font-size: 60%;*/\n\ }\n\ /deep/ ion-nav.menu-content-open + teonet-status {\n\ display: none;\n\ }\n\ /deep/ ion-app.platform-ios .teonet-status {\n\ top: 22px;\n\ }\n\ .teonet-status-no-badge {\n\ top: 3px;\n\ }\n\ /deep/ ion-app.platform-ios .teonet-status-no-badge {\n\ top: 35px;\n\ }\n\ /deep/ ion-app.platform-android .teonet-status-no-badge {\n\ top: 20px;\n\ }\n\ .teonet-status-badge {\n\ position: absolute;\n\ bottom: -15px;\n\ right: 0;\n\ font-size: 70%;\n\ }\n\ .teonet-badge {\n\ padding: 3px 8px;\n\ text-align: center;\n\ display: inline-block;\n\ min-width: 10px;\n\ /* font-size: 1.3rem; */\n\ font-weight: bold;\n\ line-height: 1;\n\ white-space: nowrap;\n\ vertical-align: baseline;\n\ }\n\ '], template: '\n\ <span class="teonet-status \n\ text-md-{{ getStatusColor(t.status) }}\n\ {{ (!ifPeer(peer) ? \' teonet-status-no-badge\' : \'\') }}">\n\ {{\n\ (ifOnline() ? label + " " : "") + \n\ getStatusText(t.status) + \n\ (ifOnline() && tcli.num_clients ? ": " + tcli.num_clients : "")\n\ }}\n\ <div *ngIf="ifPeer(peer)"\n\ class="teonet-badge teonet-status-badge badge-md\n\ badge-md-{{ time >= 0 ? \'secondary\' : \'danger\'}}"\n\ >\n\ {{\n\ (peer && show_peer == "true" ? (peer | titlecase) + ": " : "") + \n\ (time >= 0 ? time + " ms" : "offline")\n\ }}\n\ </div>\n\ </span>' },] }, ]; /** @nocollapse */ TeonetStatus.ctorParameters = function () { return [ { type: TeonetCli } ]; }; return TeonetStatus; }()); export { TeonetStatus }; //# sourceMappingURL=teocli.module.js.map