diff --git a/.gitignore b/.gitignore index a547bf3..251ce6d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ pnpm-debug.log* lerna-debug.log* node_modules -dist dist-ssr *.local diff --git a/README.md b/README.md index aed605a..1486feb 100644 --- a/README.md +++ b/README.md @@ -1 +1,11 @@ # Xibo Communication Framework + +Temporarily install the library by adding a line to `package.json` using the commit hash `$COMMIT_HASH` + + +`package.json` +```aiignore + ... + "@xibosignage/xibo-communications-framework": "https+git@github.com:xibosignage/xibo-communication-framework.git#$COMMIT_HASH" + ... +``` \ No newline at end of file diff --git a/dist/rollup.config.d.ts b/dist/rollup.config.d.ts new file mode 100644 index 0000000..f3c0baa --- /dev/null +++ b/dist/rollup.config.d.ts @@ -0,0 +1,3 @@ +import type { RollupOptions } from 'rollup'; +declare const config: RollupOptions[]; +export default config; diff --git a/dist/src/index.d.ts b/dist/src/index.d.ts new file mode 100644 index 0000000..28fa190 --- /dev/null +++ b/dist/src/index.d.ts @@ -0,0 +1 @@ +export * from './modules/xmr'; diff --git a/dist/src/modules/xmr/index.d.ts b/dist/src/modules/xmr/index.d.ts new file mode 100644 index 0000000..a6cdcb5 --- /dev/null +++ b/dist/src/modules/xmr/index.d.ts @@ -0,0 +1 @@ +export { default as Xmr, XmrEvents, } from './xmr'; diff --git a/dist/src/modules/xmr/xmr.d.ts b/dist/src/modules/xmr/xmr.d.ts new file mode 100644 index 0000000..1d1baf4 --- /dev/null +++ b/dist/src/modules/xmr/xmr.d.ts @@ -0,0 +1,29 @@ +import { type Emitter } from 'nanoevents'; +import { DateTime } from 'luxon'; +export interface XmrEvents { + connected: () => void; + disconnected: () => void; + error: (e: string) => void; + statusChange: (status: string) => void; + collectNow: () => void; + screenShot: () => void; + licenceCheck: () => void; + showStatusWindow: (timeout: number) => void; +} +export default class Xmr { + emitter: Emitter; + url: string | null; + cmsKey: string | null; + channel: string; + socket: WebSocket; + isConnectionWanted: boolean; + isConnected: boolean; + lastMessageAt: DateTime; + interval: NodeJS.Timeout | undefined; + constructor(channel: string); + on(event: E, callback: XmrEvents[E]): import("nanoevents").Unsubscribe; + init(): Promise; + start(url: string, cmsKey: string): Promise; + stop(): Promise; + isActive(): boolean; +} diff --git a/dist/xibo-communication-framework.amd.js b/dist/xibo-communication-framework.amd.js new file mode 100644 index 0000000..63bc75b --- /dev/null +++ b/dist/xibo-communication-framework.amd.js @@ -0,0 +1,594 @@ +define(['exports', 'luxon'], (function (exports, luxon) { 'use strict'; + + function asyncGeneratorStep(n, t, e, r, o, a, c) { + try { + var i = n[a](c), + u = i.value; + } catch (n) { + return void e(n); + } + i.done ? t(u) : Promise.resolve(u).then(r, o); + } + function _asyncToGenerator(n) { + return function () { + var t = this, + e = arguments; + return new Promise(function (r, o) { + var a = n.apply(t, e); + function _next(n) { + asyncGeneratorStep(a, r, o, _next, _throw, "next", n); + } + function _throw(n) { + asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); + } + _next(void 0); + }); + }; + } + function _classCallCheck(a, n) { + if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); + } + function _defineProperties(e, r) { + for (var t = 0; t < r.length; t++) { + var o = r[t]; + o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o); + } + } + function _createClass(e, r, t) { + return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", { + writable: false + }), e; + } + function _defineProperty(e, r, t) { + return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { + value: t, + enumerable: true, + configurable: true, + writable: true + }) : e[r] = t, e; + } + function _regeneratorRuntime() { + _regeneratorRuntime = function () { + return r; + }; + var t, + r = {}, + e = Object.prototype, + n = e.hasOwnProperty, + o = "function" == typeof Symbol ? Symbol : {}, + i = o.iterator || "@@iterator", + a = o.asyncIterator || "@@asyncIterator", + u = o.toStringTag || "@@toStringTag"; + function c(t, r, e, n) { + return Object.defineProperty(t, r, { + value: e, + enumerable: !n, + configurable: !n, + writable: !n + }); + } + try { + c({}, ""); + } catch (t) { + c = function (t, r, e) { + return t[r] = e; + }; + } + function h(r, e, n, o) { + var i = e && e.prototype instanceof Generator ? e : Generator, + a = Object.create(i.prototype); + return c(a, "_invoke", function (r, e, n) { + var o = 1; + return function (i, a) { + if (3 === o) throw Error("Generator is already running"); + if (4 === o) { + if ("throw" === i) throw a; + return { + value: t, + done: true + }; + } + for (n.method = i, n.arg = a;;) { + var u = n.delegate; + if (u) { + var c = d(u, n); + if (c) { + if (c === f) continue; + return c; + } + } + if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { + if (1 === o) throw o = 4, n.arg; + n.dispatchException(n.arg); + } else "return" === n.method && n.abrupt("return", n.arg); + o = 3; + var h = s(r, e, n); + if ("normal" === h.type) { + if (o = n.done ? 4 : 2, h.arg === f) continue; + return { + value: h.arg, + done: n.done + }; + } + "throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg); + } + }; + }(r, n, new Context(o || [])), true), a; + } + function s(t, r, e) { + try { + return { + type: "normal", + arg: t.call(r, e) + }; + } catch (t) { + return { + type: "throw", + arg: t + }; + } + } + r.wrap = h; + var f = {}; + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + var l = {}; + c(l, i, function () { + return this; + }); + var p = Object.getPrototypeOf, + y = p && p(p(x([]))); + y && y !== e && n.call(y, i) && (l = y); + var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l); + function g(t) { + ["next", "throw", "return"].forEach(function (r) { + c(t, r, function (t) { + return this._invoke(r, t); + }); + }); + } + function AsyncIterator(t, r) { + function e(o, i, a, u) { + var c = s(t[o], t, i); + if ("throw" !== c.type) { + var h = c.arg, + f = h.value; + return f && "object" == typeof f && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) { + e("next", t, a, u); + }, function (t) { + e("throw", t, a, u); + }) : r.resolve(f).then(function (t) { + h.value = t, a(h); + }, function (t) { + return e("throw", t, a, u); + }); + } + u(c.arg); + } + var o; + c(this, "_invoke", function (t, n) { + function i() { + return new r(function (r, o) { + e(t, n, r, o); + }); + } + return o = o ? o.then(i, i) : i(); + }, true); + } + function d(r, e) { + var n = e.method, + o = r.i[n]; + if (o === t) return e.delegate = null, "throw" === n && r.i.return && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a '" + n + "' method")), f; + var i = s(o, r.i, e.arg); + if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f; + var a = i.arg; + return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f); + } + function w(t) { + this.tryEntries.push(t); + } + function m(r) { + var e = r[4] || {}; + e.type = "normal", e.arg = t, r[4] = e; + } + function Context(t) { + this.tryEntries = [[-1]], t.forEach(w, this), this.reset(true); + } + function x(r) { + if (null != r) { + var e = r[i]; + if (e) return e.call(r); + if ("function" == typeof r.next) return r; + if (!isNaN(r.length)) { + var o = -1, + a = function e() { + for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = false, e; + return e.value = t, e.done = true, e; + }; + return a.next = a; + } + } + throw new TypeError(typeof r + " is not iterable"); + } + return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) { + var r = "function" == typeof t && t.constructor; + return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name)); + }, r.mark = function (t) { + return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t; + }, r.awrap = function (t) { + return { + __await: t + }; + }, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () { + return this; + }), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) { + void 0 === i && (i = Promise); + var a = new AsyncIterator(h(t, e, n, o), i); + return r.isGeneratorFunction(e) ? a : a.next().then(function (t) { + return t.done ? t.value : a.next(); + }); + }, g(v), c(v, u, "Generator"), c(v, i, function () { + return this; + }), c(v, "toString", function () { + return "[object Generator]"; + }), r.keys = function (t) { + var r = Object(t), + e = []; + for (var n in r) e.unshift(n); + return function t() { + for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = false, t; + return t.done = true, t; + }; + }, r.values = x, Context.prototype = { + constructor: Context, + reset: function (r) { + if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = false, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t); + }, + stop: function () { + this.done = true; + var t = this.tryEntries[0][4]; + if ("throw" === t.type) throw t.arg; + return this.rval; + }, + dispatchException: function (r) { + if (this.done) throw r; + var e = this; + function n(t) { + a.type = "throw", a.arg = r, e.next = t; + } + for (var o = e.tryEntries.length - 1; o >= 0; --o) { + var i = this.tryEntries[o], + a = i[4], + u = this.prev, + c = i[1], + h = i[2]; + if (-1 === i[0]) return n("end"), false; + if (!c && !h) throw Error("try statement without catch or finally"); + if (null != i[0] && i[0] <= u) { + if (u < c) return this.method = "next", this.arg = t, n(c), true; + if (u < h) return n(h), false; + } + } + }, + abrupt: function (t, r) { + for (var e = this.tryEntries.length - 1; e >= 0; --e) { + var n = this.tryEntries[e]; + if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { + var o = n; + break; + } + } + o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null); + var i = o ? o[4] : {}; + return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i); + }, + complete: function (t, r) { + if ("throw" === t.type) throw t.arg; + return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f; + }, + finish: function (t) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var e = this.tryEntries[r]; + if (e[2] === t) return this.complete(e[4], e[3]), m(e), f; + } + }, + catch: function (t) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var e = this.tryEntries[r]; + if (e[0] === t) { + var n = e[4]; + if ("throw" === n.type) { + var o = n.arg; + m(e); + } + return o; + } + } + throw Error("illegal catch attempt"); + }, + delegateYield: function (r, e, n) { + return this.delegate = { + i: x(r), + r: e, + n: n + }, "next" === this.method && (this.arg = t), f; + } + }, r; + } + function _toPrimitive(t, r) { + if ("object" != typeof t || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r); + if ("object" != typeof i) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (String )(t); + } + function _toPropertyKey(t) { + var i = _toPrimitive(t, "string"); + return "symbol" == typeof i ? i : i + ""; + } + + var createNanoEvents = function createNanoEvents() { + return { + emit: function emit(event) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + for (var callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) { + callbacks[i].apply(callbacks, args); + } + }, + events: {}, + on: function on(event, cb) { + var _this$events, + _this = this; + ((_this$events = this.events)[event] || (_this$events[event] = [])).push(cb); + return function () { + var _this$events$event; + _this.events[event] = (_this$events$event = _this.events[event]) === null || _this$events$event === void 0 ? void 0 : _this$events$event.filter(function (i) { + return cb !== i; + }); + }; + } + }; + }; + + var Xmr = /*#__PURE__*/function () { + function Xmr(channel) { + _classCallCheck(this, Xmr); + _defineProperty(this, "emitter", void 0); + _defineProperty(this, "url", void 0); + _defineProperty(this, "cmsKey", void 0); + _defineProperty(this, "channel", void 0); + _defineProperty(this, "socket", void 0); + // State + _defineProperty(this, "isConnectionWanted", void 0); + _defineProperty(this, "isConnected", void 0); + _defineProperty(this, "lastMessageAt", void 0); + _defineProperty(this, "interval", void 0); + // Emitter + this.emitter = createNanoEvents(); + this.url = null; + this.cmsKey = null; + this.channel = channel; + this.isConnected = false; + this.isConnectionWanted = false; + this.lastMessageAt = luxon.DateTime.now().minus({ + year: 1 + }); + } + return _createClass(Xmr, [{ + key: "on", + value: function on(event, callback) { + return this.emitter.on(event, callback); + } + }, { + key: "init", + value: function () { + var _init = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() { + var _this = this; + return _regeneratorRuntime().wrap(function _callee$(_context) { + while (1) switch (_context.prev = _context.next) { + case 0: + this.interval = setInterval(function () { + if (_this.isConnectionWanted && !_this.isActive()) { + console.debug('Xmr::setInterval: should be active'); + // Call start again + _this.start(_this.url || 'DISABLED', _this.cmsKey || 'n/a'); + } + }, 60000); + case 1: + case "end": + return _context.stop(); + } + }, _callee, this); + })); + function init() { + return _init.apply(this, arguments); + } + return init; + }() + }, { + key: "start", + value: function () { + var _start = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(url, cmsKey) { + var _this2 = this; + return _regeneratorRuntime().wrap(function _callee2$(_context2) { + while (1) switch (_context2.prev = _context2.next) { + case 0: + if (!(!this.channel || this.channel === 'unknown')) { + _context2.next = 3; + break; + } + console.error('Xmr::start: channel unknown, XMR will be disabled'); + return _context2.abrupt("return"); + case 3: + if (!(this.url === 'DISABLED')) { + _context2.next = 8; + break; + } + console.info('Xmr::start: XMR disabled'); + this.isConnectionWanted = false; + if (this.isActive()) { + stop(); + } + return _context2.abrupt("return"); + case 8: + this.isConnectionWanted = true; + // Are we already connected? + if (!(this.isActive() && this.url === url)) { + _context2.next = 15; + break; + } + console.debug('Xmr::start: already connected to this URL'); + this.cmsKey = cmsKey; + return _context2.abrupt("return"); + case 15: + if (!this.isConnected) { + _context2.next = 21; + break; + } + console.debug('Xmr::start: already connected but not active, or a different URL'); + _context2.next = 19; + return this.stop(); + case 19: + _context2.next = 22; + break; + case 21: + console.debug('Xmr::start: not connected yet'); + case 22: + // Set the URL and cmsKey. + this.url = url; + this.cmsKey = cmsKey; + console.debug('Xmr::start: connecting to ' + this.url); + _context2.prev = 25; + this.socket = new WebSocket(this.url); + _context2.next = 34; + break; + case 29: + _context2.prev = 29; + _context2.t0 = _context2["catch"](25); + console.debug('Xmr::start: failed connecting to ' + this.url + ', e = ' + _context2.t0); + this.emitter.emit('error', 'Failed to connect'); + return _context2.abrupt("return"); + case 34: + /** + * Listener for socket open + */ + this.socket.addEventListener('open', function (event) { + console.debug('Xmr::' + event.type); + if (_this2.socket.readyState !== WebSocket.OPEN) { + console.info('Xmr::' + event.type + ': not open yet'); + return; + } + // Create and send an initialisation message. + _this2.socket.send(JSON.stringify({ + 'type': 'init', + 'key': _this2.cmsKey, + 'channel': _this2.channel + })); + _this2.isConnected = true; + _this2.emitter.emit('connected'); + }); + /** + * Listener for socket close + */ + this.socket.addEventListener('close', function (event) { + console.debug('Xmr::' + event.type); + _this2.isConnected = false; + _this2.emitter.emit('disconnected'); + }); + /** + * Listener for socket error + */ + this.socket.addEventListener('error', function (event) { + console.debug('Xmr::' + event.type); + _this2.emitter.emit('error', 'error'); + }); + /** + * Listener for socket message + */ + this.socket.addEventListener('message', function (event) { + console.debug(event); + _this2.lastMessageAt = luxon.DateTime.now(); + _this2.emitter.emit('statusChange', _this2.lastMessageAt.toISO() || ''); + // Expect a JSON message or a H + if (event.data === 'H') { + console.debug('Xmr::message: Heartbeat...'); + } else { + // JSON message. + var message = JSON.parse(event.data); + console.debug('Xmr::message: action is ' + message.action); + // Check the createdDt and TTL against the current date time. + var expiresAt = luxon.DateTime.fromISO(message.createdDt).plus({ + seconds: parseInt(message.ttl) + }); + if (expiresAt < luxon.DateTime.now()) { + console.debug('Xmr::message: message expired at ' + expiresAt.toString()); + } else if (message.action === 'collectNow') { + _this2.emitter.emit('collectNow'); + } else if (message.action === 'screenShot') { + _this2.emitter.emit('screenShot'); + } else if (message.action === 'licenceCheck') { + _this2.emitter.emit('licenceCheck'); + } else if (message.action == 'commandAction' && message.commandCode.startsWith('showStatusWindow')) { + var split = message.commandCode.split('|'); + _this2.emitter.emit('showStatusWindow', parseInt(split[1]) || 60); + } else { + console.error('Xmr::message: unknown action: ' + message.action); + } + } + }); + case 38: + case "end": + return _context2.stop(); + } + }, _callee2, this, [[25, 29]]); + })); + function start(_x, _x2) { + return _start.apply(this, arguments); + } + return start; + }() + }, { + key: "stop", + value: function () { + var _stop = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() { + return _regeneratorRuntime().wrap(function _callee3$(_context3) { + while (1) switch (_context3.prev = _context3.next) { + case 0: + console.debug('Xmr::stop'); + if (this.socket) { + console.debug('Xmr::stop: closing active socket'); + this.socket.close(); + this.isConnected = false; + } + case 2: + case "end": + return _context3.stop(); + } + }, _callee3, this); + })); + function stop() { + return _stop.apply(this, arguments); + } + return stop; + }() + }, { + key: "isActive", + value: function isActive() { + console.debug('Xmr::isActive: lastMessageAt: ' + this.lastMessageAt.toString()); + return this.isConnected && this.lastMessageAt > luxon.DateTime.now().minus({ + minute: 15 + }); + } + }]); + }(); + + exports.Xmr = Xmr; + +})); +//# sourceMappingURL=xibo-communication-framework.amd.js.map diff --git a/dist/xibo-communication-framework.amd.js.map b/dist/xibo-communication-framework.amd.js.map new file mode 100644 index 0000000..3ba3b54 --- /dev/null +++ b/dist/xibo-communication-framework.amd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"xibo-communication-framework.amd.js","sources":["../node_modules/nanoevents/index.js","../../src/modules/xmr/xmr.ts"],"sourcesContent":["export let createNanoEvents = () => ({\n emit(event, ...args) {\n for (\n let callbacks = this.events[event] || [],\n i = 0,\n length = callbacks.length;\n i < length;\n i++\n ) {\n callbacks[i](...args)\n }\n },\n events: {},\n on(event, cb) {\n ;(this.events[event] ||= []).push(cb)\n return () => {\n this.events[event] = this.events[event]?.filter(i => cb !== i)\n }\n }\n})\n","/*\n * Copyright (C) 2025 Xibo Signage Ltd\n *\n * Xibo - Digital Signage - https://www.xibosignage.com\n *\n * This file is part of Xibo.\n *\n * Xibo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * any later version.\n *\n * Xibo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with Xibo. If not, see .\n */\nimport {createNanoEvents, type Emitter} from 'nanoevents';\nimport {DateTime} from 'luxon';\n\nexport interface XmrEvents {\n connected: () => void;\n disconnected: () => void;\n error: (e: string) => void;\n statusChange: (status: string) => void;\n\n collectNow: () => void;\n screenShot: () => void;\n licenceCheck: () => void;\n showStatusWindow: (timeout: number) => void;\n}\n\nexport default class Xmr {\n emitter: Emitter;\n\n url: string | null;\n cmsKey: string | null;\n channel: string;\n socket!: WebSocket;\n\n // State\n isConnectionWanted: boolean;\n isConnected: boolean;\n lastMessageAt: DateTime;\n\n interval: NodeJS.Timeout | undefined;\n\n constructor (channel: string) {\n // Emitter\n this.emitter = createNanoEvents();\n this.url = null;\n this.cmsKey = null;\n this.channel = channel;\n this.isConnected = false;\n this.isConnectionWanted = false;\n this.lastMessageAt = DateTime.now().minus({year: 1});\n }\n\n on(event: E, callback: XmrEvents[E]) {\n return this.emitter.on(event, callback);\n }\n\n async init() {\n this.interval = setInterval(() => {\n if (this.isConnectionWanted && !this.isActive()) {\n console.debug('Xmr::setInterval: should be active');\n\n // Call start again\n this.start(this.url || 'DISABLED', this.cmsKey || 'n/a');\n }\n }, 60000);\n }\n\n async start(url: string, cmsKey: string){\n if (!this.channel || this.channel === 'unknown') {\n console.error('Xmr::start: channel unknown, XMR will be disabled');\n return;\n }\n\n // Disable XMR if we've been told to.\n if (this.url === 'DISABLED') {\n console.info('Xmr::start: XMR disabled');\n this.isConnectionWanted = false;\n if (this.isActive()) {\n stop();\n }\n return;\n }\n\n this.isConnectionWanted = true;\n\n // Are we already connected?\n if (this.isActive() && this.url === url) {\n console.debug('Xmr::start: already connected to this URL');\n this.cmsKey = cmsKey;\n return;\n } else if (this.isConnected) {\n console.debug('Xmr::start: already connected but not active, or a different URL');\n await this.stop();\n } else {\n console.debug('Xmr::start: not connected yet');\n }\n\n // Set the URL and cmsKey.\n this.url = url;\n this.cmsKey = cmsKey;\n\n console.debug('Xmr::start: connecting to ' + this.url);\n\n try {\n this.socket = new WebSocket(this.url);\n } catch (e) {\n console.debug('Xmr::start: failed connecting to ' + this.url + ', e = ' + e);\n this.emitter.emit('error', 'Failed to connect');\n return;\n }\n\n /**\n * Listener for socket open\n */\n this.socket.addEventListener('open', (event) => {\n console.debug('Xmr::' + event.type);\n\n if (this.socket.readyState !== WebSocket.OPEN) {\n console.info('Xmr::' + event.type + ': not open yet');\n return;\n }\n\n // Create and send an initialisation message.\n this.socket.send(JSON.stringify({\n 'type': 'init',\n 'key': this.cmsKey,\n 'channel': this.channel,\n }));\n\n this.isConnected = true;\n\n this.emitter.emit('connected');\n });\n\n /**\n * Listener for socket close\n */\n this.socket.addEventListener('close', (event) => {\n console.debug('Xmr::' + event.type);\n\n this.isConnected = false;\n\n this.emitter.emit('disconnected');\n });\n\n /**\n * Listener for socket error\n */\n this.socket.addEventListener('error', (event) => {\n console.debug('Xmr::' + event.type);\n\n this.emitter.emit('error', 'error');\n });\n\n /**\n * Listener for socket message\n */\n this.socket.addEventListener('message', (event) => {\n console.debug(event);\n\n this.lastMessageAt = DateTime.now();\n this.emitter.emit('statusChange', this.lastMessageAt.toISO() || '');\n\n // Expect a JSON message or a H\n if (event.data === 'H') {\n console.debug('Xmr::message: Heartbeat...');\n } else {\n // JSON message.\n const message = JSON.parse(event.data);\n\n console.debug('Xmr::message: action is ' + message.action);\n\n // Check the createdDt and TTL against the current date time.\n const expiresAt = DateTime.fromISO(message.createdDt).plus({seconds: parseInt(message.ttl)});\n if (expiresAt < DateTime.now()) {\n console.debug('Xmr::message: message expired at ' + expiresAt.toString());\n } else if (message.action === 'collectNow') {\n this.emitter.emit('collectNow');\n } else if (message.action === 'screenShot') {\n this.emitter.emit('screenShot');\n } else if (message.action === 'licenceCheck') {\n this.emitter.emit('licenceCheck');\n } else if (message.action == 'commandAction' && message.commandCode.startsWith('showStatusWindow')) {\n const split = message.commandCode.split('|');\n this.emitter.emit('showStatusWindow', parseInt(split[1]) || 60);\n } else {\n console.error('Xmr::message: unknown action: ' + message.action);\n }\n }\n });\n }\n\n async stop() {\n console.debug('Xmr::stop');\n if (this.socket) {\n console.debug('Xmr::stop: closing active socket');\n this.socket.close();\n this.isConnected = false;\n }\n }\n\n isActive(): boolean {\n console.debug('Xmr::isActive: lastMessageAt: ' + this.lastMessageAt.toString());\n return this.isConnected && this.lastMessageAt > DateTime.now().minus({minute: 15});\n }\n}\n"],"names":["createNanoEvents","emit","event","_len","arguments","length","args","Array","_key","callbacks","events","i","apply","on","cb","_this$events","_this","push","_this$events$event","filter","Xmr","channel","_classCallCheck","_defineProperty","emitter","url","cmsKey","isConnected","isConnectionWanted","lastMessageAt","DateTime","now","minus","year","_createClass","key","value","callback","_init","_asyncToGenerator","_regeneratorRuntime","mark","_callee","wrap","_callee$","_context","prev","next","interval","setInterval","isActive","console","debug","start","stop","init","_start","_callee2","_this2","_callee2$","_context2","error","abrupt","info","socket","WebSocket","t0","addEventListener","type","readyState","OPEN","send","JSON","stringify","toISO","data","message","parse","action","expiresAt","fromISO","createdDt","plus","seconds","parseInt","ttl","toString","commandCode","startsWith","split","_x","_x2","_stop","_callee3","_callee3$","_context3","close","minute"],"mappings":"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","x_google_ignoreList":[0]} \ No newline at end of file diff --git a/dist/xibo-communication-framework.cjs.js b/dist/xibo-communication-framework.cjs.js new file mode 100644 index 0000000..4a95b11 --- /dev/null +++ b/dist/xibo-communication-framework.cjs.js @@ -0,0 +1,594 @@ +'use strict'; + +var luxon = require('luxon'); + +function asyncGeneratorStep(n, t, e, r, o, a, c) { + try { + var i = n[a](c), + u = i.value; + } catch (n) { + return void e(n); + } + i.done ? t(u) : Promise.resolve(u).then(r, o); +} +function _asyncToGenerator(n) { + return function () { + var t = this, + e = arguments; + return new Promise(function (r, o) { + var a = n.apply(t, e); + function _next(n) { + asyncGeneratorStep(a, r, o, _next, _throw, "next", n); + } + function _throw(n) { + asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); + } + _next(void 0); + }); + }; +} +function _classCallCheck(a, n) { + if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); +} +function _defineProperties(e, r) { + for (var t = 0; t < r.length; t++) { + var o = r[t]; + o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o); + } +} +function _createClass(e, r, t) { + return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", { + writable: false + }), e; +} +function _defineProperty(e, r, t) { + return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { + value: t, + enumerable: true, + configurable: true, + writable: true + }) : e[r] = t, e; +} +function _regeneratorRuntime() { + _regeneratorRuntime = function () { + return r; + }; + var t, + r = {}, + e = Object.prototype, + n = e.hasOwnProperty, + o = "function" == typeof Symbol ? Symbol : {}, + i = o.iterator || "@@iterator", + a = o.asyncIterator || "@@asyncIterator", + u = o.toStringTag || "@@toStringTag"; + function c(t, r, e, n) { + return Object.defineProperty(t, r, { + value: e, + enumerable: !n, + configurable: !n, + writable: !n + }); + } + try { + c({}, ""); + } catch (t) { + c = function (t, r, e) { + return t[r] = e; + }; + } + function h(r, e, n, o) { + var i = e && e.prototype instanceof Generator ? e : Generator, + a = Object.create(i.prototype); + return c(a, "_invoke", function (r, e, n) { + var o = 1; + return function (i, a) { + if (3 === o) throw Error("Generator is already running"); + if (4 === o) { + if ("throw" === i) throw a; + return { + value: t, + done: true + }; + } + for (n.method = i, n.arg = a;;) { + var u = n.delegate; + if (u) { + var c = d(u, n); + if (c) { + if (c === f) continue; + return c; + } + } + if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { + if (1 === o) throw o = 4, n.arg; + n.dispatchException(n.arg); + } else "return" === n.method && n.abrupt("return", n.arg); + o = 3; + var h = s(r, e, n); + if ("normal" === h.type) { + if (o = n.done ? 4 : 2, h.arg === f) continue; + return { + value: h.arg, + done: n.done + }; + } + "throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg); + } + }; + }(r, n, new Context(o || [])), true), a; + } + function s(t, r, e) { + try { + return { + type: "normal", + arg: t.call(r, e) + }; + } catch (t) { + return { + type: "throw", + arg: t + }; + } + } + r.wrap = h; + var f = {}; + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + var l = {}; + c(l, i, function () { + return this; + }); + var p = Object.getPrototypeOf, + y = p && p(p(x([]))); + y && y !== e && n.call(y, i) && (l = y); + var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l); + function g(t) { + ["next", "throw", "return"].forEach(function (r) { + c(t, r, function (t) { + return this._invoke(r, t); + }); + }); + } + function AsyncIterator(t, r) { + function e(o, i, a, u) { + var c = s(t[o], t, i); + if ("throw" !== c.type) { + var h = c.arg, + f = h.value; + return f && "object" == typeof f && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) { + e("next", t, a, u); + }, function (t) { + e("throw", t, a, u); + }) : r.resolve(f).then(function (t) { + h.value = t, a(h); + }, function (t) { + return e("throw", t, a, u); + }); + } + u(c.arg); + } + var o; + c(this, "_invoke", function (t, n) { + function i() { + return new r(function (r, o) { + e(t, n, r, o); + }); + } + return o = o ? o.then(i, i) : i(); + }, true); + } + function d(r, e) { + var n = e.method, + o = r.i[n]; + if (o === t) return e.delegate = null, "throw" === n && r.i.return && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a '" + n + "' method")), f; + var i = s(o, r.i, e.arg); + if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f; + var a = i.arg; + return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f); + } + function w(t) { + this.tryEntries.push(t); + } + function m(r) { + var e = r[4] || {}; + e.type = "normal", e.arg = t, r[4] = e; + } + function Context(t) { + this.tryEntries = [[-1]], t.forEach(w, this), this.reset(true); + } + function x(r) { + if (null != r) { + var e = r[i]; + if (e) return e.call(r); + if ("function" == typeof r.next) return r; + if (!isNaN(r.length)) { + var o = -1, + a = function e() { + for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = false, e; + return e.value = t, e.done = true, e; + }; + return a.next = a; + } + } + throw new TypeError(typeof r + " is not iterable"); + } + return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) { + var r = "function" == typeof t && t.constructor; + return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name)); + }, r.mark = function (t) { + return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t; + }, r.awrap = function (t) { + return { + __await: t + }; + }, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () { + return this; + }), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) { + void 0 === i && (i = Promise); + var a = new AsyncIterator(h(t, e, n, o), i); + return r.isGeneratorFunction(e) ? a : a.next().then(function (t) { + return t.done ? t.value : a.next(); + }); + }, g(v), c(v, u, "Generator"), c(v, i, function () { + return this; + }), c(v, "toString", function () { + return "[object Generator]"; + }), r.keys = function (t) { + var r = Object(t), + e = []; + for (var n in r) e.unshift(n); + return function t() { + for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = false, t; + return t.done = true, t; + }; + }, r.values = x, Context.prototype = { + constructor: Context, + reset: function (r) { + if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = false, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t); + }, + stop: function () { + this.done = true; + var t = this.tryEntries[0][4]; + if ("throw" === t.type) throw t.arg; + return this.rval; + }, + dispatchException: function (r) { + if (this.done) throw r; + var e = this; + function n(t) { + a.type = "throw", a.arg = r, e.next = t; + } + for (var o = e.tryEntries.length - 1; o >= 0; --o) { + var i = this.tryEntries[o], + a = i[4], + u = this.prev, + c = i[1], + h = i[2]; + if (-1 === i[0]) return n("end"), false; + if (!c && !h) throw Error("try statement without catch or finally"); + if (null != i[0] && i[0] <= u) { + if (u < c) return this.method = "next", this.arg = t, n(c), true; + if (u < h) return n(h), false; + } + } + }, + abrupt: function (t, r) { + for (var e = this.tryEntries.length - 1; e >= 0; --e) { + var n = this.tryEntries[e]; + if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { + var o = n; + break; + } + } + o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null); + var i = o ? o[4] : {}; + return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i); + }, + complete: function (t, r) { + if ("throw" === t.type) throw t.arg; + return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f; + }, + finish: function (t) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var e = this.tryEntries[r]; + if (e[2] === t) return this.complete(e[4], e[3]), m(e), f; + } + }, + catch: function (t) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var e = this.tryEntries[r]; + if (e[0] === t) { + var n = e[4]; + if ("throw" === n.type) { + var o = n.arg; + m(e); + } + return o; + } + } + throw Error("illegal catch attempt"); + }, + delegateYield: function (r, e, n) { + return this.delegate = { + i: x(r), + r: e, + n: n + }, "next" === this.method && (this.arg = t), f; + } + }, r; +} +function _toPrimitive(t, r) { + if ("object" != typeof t || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r); + if ("object" != typeof i) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (String )(t); +} +function _toPropertyKey(t) { + var i = _toPrimitive(t, "string"); + return "symbol" == typeof i ? i : i + ""; +} + +var createNanoEvents = function createNanoEvents() { + return { + emit: function emit(event) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + for (var callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) { + callbacks[i].apply(callbacks, args); + } + }, + events: {}, + on: function on(event, cb) { + var _this$events, + _this = this; + ((_this$events = this.events)[event] || (_this$events[event] = [])).push(cb); + return function () { + var _this$events$event; + _this.events[event] = (_this$events$event = _this.events[event]) === null || _this$events$event === void 0 ? void 0 : _this$events$event.filter(function (i) { + return cb !== i; + }); + }; + } + }; +}; + +var Xmr = /*#__PURE__*/function () { + function Xmr(channel) { + _classCallCheck(this, Xmr); + _defineProperty(this, "emitter", void 0); + _defineProperty(this, "url", void 0); + _defineProperty(this, "cmsKey", void 0); + _defineProperty(this, "channel", void 0); + _defineProperty(this, "socket", void 0); + // State + _defineProperty(this, "isConnectionWanted", void 0); + _defineProperty(this, "isConnected", void 0); + _defineProperty(this, "lastMessageAt", void 0); + _defineProperty(this, "interval", void 0); + // Emitter + this.emitter = createNanoEvents(); + this.url = null; + this.cmsKey = null; + this.channel = channel; + this.isConnected = false; + this.isConnectionWanted = false; + this.lastMessageAt = luxon.DateTime.now().minus({ + year: 1 + }); + } + return _createClass(Xmr, [{ + key: "on", + value: function on(event, callback) { + return this.emitter.on(event, callback); + } + }, { + key: "init", + value: function () { + var _init = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() { + var _this = this; + return _regeneratorRuntime().wrap(function _callee$(_context) { + while (1) switch (_context.prev = _context.next) { + case 0: + this.interval = setInterval(function () { + if (_this.isConnectionWanted && !_this.isActive()) { + console.debug('Xmr::setInterval: should be active'); + // Call start again + _this.start(_this.url || 'DISABLED', _this.cmsKey || 'n/a'); + } + }, 60000); + case 1: + case "end": + return _context.stop(); + } + }, _callee, this); + })); + function init() { + return _init.apply(this, arguments); + } + return init; + }() + }, { + key: "start", + value: function () { + var _start = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(url, cmsKey) { + var _this2 = this; + return _regeneratorRuntime().wrap(function _callee2$(_context2) { + while (1) switch (_context2.prev = _context2.next) { + case 0: + if (!(!this.channel || this.channel === 'unknown')) { + _context2.next = 3; + break; + } + console.error('Xmr::start: channel unknown, XMR will be disabled'); + return _context2.abrupt("return"); + case 3: + if (!(this.url === 'DISABLED')) { + _context2.next = 8; + break; + } + console.info('Xmr::start: XMR disabled'); + this.isConnectionWanted = false; + if (this.isActive()) { + stop(); + } + return _context2.abrupt("return"); + case 8: + this.isConnectionWanted = true; + // Are we already connected? + if (!(this.isActive() && this.url === url)) { + _context2.next = 15; + break; + } + console.debug('Xmr::start: already connected to this URL'); + this.cmsKey = cmsKey; + return _context2.abrupt("return"); + case 15: + if (!this.isConnected) { + _context2.next = 21; + break; + } + console.debug('Xmr::start: already connected but not active, or a different URL'); + _context2.next = 19; + return this.stop(); + case 19: + _context2.next = 22; + break; + case 21: + console.debug('Xmr::start: not connected yet'); + case 22: + // Set the URL and cmsKey. + this.url = url; + this.cmsKey = cmsKey; + console.debug('Xmr::start: connecting to ' + this.url); + _context2.prev = 25; + this.socket = new WebSocket(this.url); + _context2.next = 34; + break; + case 29: + _context2.prev = 29; + _context2.t0 = _context2["catch"](25); + console.debug('Xmr::start: failed connecting to ' + this.url + ', e = ' + _context2.t0); + this.emitter.emit('error', 'Failed to connect'); + return _context2.abrupt("return"); + case 34: + /** + * Listener for socket open + */ + this.socket.addEventListener('open', function (event) { + console.debug('Xmr::' + event.type); + if (_this2.socket.readyState !== WebSocket.OPEN) { + console.info('Xmr::' + event.type + ': not open yet'); + return; + } + // Create and send an initialisation message. + _this2.socket.send(JSON.stringify({ + 'type': 'init', + 'key': _this2.cmsKey, + 'channel': _this2.channel + })); + _this2.isConnected = true; + _this2.emitter.emit('connected'); + }); + /** + * Listener for socket close + */ + this.socket.addEventListener('close', function (event) { + console.debug('Xmr::' + event.type); + _this2.isConnected = false; + _this2.emitter.emit('disconnected'); + }); + /** + * Listener for socket error + */ + this.socket.addEventListener('error', function (event) { + console.debug('Xmr::' + event.type); + _this2.emitter.emit('error', 'error'); + }); + /** + * Listener for socket message + */ + this.socket.addEventListener('message', function (event) { + console.debug(event); + _this2.lastMessageAt = luxon.DateTime.now(); + _this2.emitter.emit('statusChange', _this2.lastMessageAt.toISO() || ''); + // Expect a JSON message or a H + if (event.data === 'H') { + console.debug('Xmr::message: Heartbeat...'); + } else { + // JSON message. + var message = JSON.parse(event.data); + console.debug('Xmr::message: action is ' + message.action); + // Check the createdDt and TTL against the current date time. + var expiresAt = luxon.DateTime.fromISO(message.createdDt).plus({ + seconds: parseInt(message.ttl) + }); + if (expiresAt < luxon.DateTime.now()) { + console.debug('Xmr::message: message expired at ' + expiresAt.toString()); + } else if (message.action === 'collectNow') { + _this2.emitter.emit('collectNow'); + } else if (message.action === 'screenShot') { + _this2.emitter.emit('screenShot'); + } else if (message.action === 'licenceCheck') { + _this2.emitter.emit('licenceCheck'); + } else if (message.action == 'commandAction' && message.commandCode.startsWith('showStatusWindow')) { + var split = message.commandCode.split('|'); + _this2.emitter.emit('showStatusWindow', parseInt(split[1]) || 60); + } else { + console.error('Xmr::message: unknown action: ' + message.action); + } + } + }); + case 38: + case "end": + return _context2.stop(); + } + }, _callee2, this, [[25, 29]]); + })); + function start(_x, _x2) { + return _start.apply(this, arguments); + } + return start; + }() + }, { + key: "stop", + value: function () { + var _stop = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() { + return _regeneratorRuntime().wrap(function _callee3$(_context3) { + while (1) switch (_context3.prev = _context3.next) { + case 0: + console.debug('Xmr::stop'); + if (this.socket) { + console.debug('Xmr::stop: closing active socket'); + this.socket.close(); + this.isConnected = false; + } + case 2: + case "end": + return _context3.stop(); + } + }, _callee3, this); + })); + function stop() { + return _stop.apply(this, arguments); + } + return stop; + }() + }, { + key: "isActive", + value: function isActive() { + console.debug('Xmr::isActive: lastMessageAt: ' + this.lastMessageAt.toString()); + return this.isConnected && this.lastMessageAt > luxon.DateTime.now().minus({ + minute: 15 + }); + } + }]); +}(); + +exports.Xmr = Xmr; +//# sourceMappingURL=xibo-communication-framework.cjs.js.map diff --git a/dist/xibo-communication-framework.cjs.js.map b/dist/xibo-communication-framework.cjs.js.map new file mode 100644 index 0000000..eddc8a2 --- /dev/null +++ b/dist/xibo-communication-framework.cjs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"xibo-communication-framework.cjs.js","sources":["../node_modules/nanoevents/index.js","../../src/modules/xmr/xmr.ts"],"sourcesContent":["export let createNanoEvents = () => ({\n emit(event, ...args) {\n for (\n let callbacks = this.events[event] || [],\n i = 0,\n length = callbacks.length;\n i < length;\n i++\n ) {\n callbacks[i](...args)\n }\n },\n events: {},\n on(event, cb) {\n ;(this.events[event] ||= []).push(cb)\n return () => {\n this.events[event] = this.events[event]?.filter(i => cb !== i)\n }\n }\n})\n","/*\n * Copyright (C) 2025 Xibo Signage Ltd\n *\n * Xibo - Digital Signage - https://www.xibosignage.com\n *\n * This file is part of Xibo.\n *\n * Xibo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * any later version.\n *\n * Xibo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with Xibo. If not, see .\n */\nimport {createNanoEvents, type Emitter} from 'nanoevents';\nimport {DateTime} from 'luxon';\n\nexport interface XmrEvents {\n connected: () => void;\n disconnected: () => void;\n error: (e: string) => void;\n statusChange: (status: string) => void;\n\n collectNow: () => void;\n screenShot: () => void;\n licenceCheck: () => void;\n showStatusWindow: (timeout: number) => void;\n}\n\nexport default class Xmr {\n emitter: Emitter;\n\n url: string | null;\n cmsKey: string | null;\n channel: string;\n socket!: WebSocket;\n\n // State\n isConnectionWanted: boolean;\n isConnected: boolean;\n lastMessageAt: DateTime;\n\n interval: NodeJS.Timeout | undefined;\n\n constructor (channel: string) {\n // Emitter\n this.emitter = createNanoEvents();\n this.url = null;\n this.cmsKey = null;\n this.channel = channel;\n this.isConnected = false;\n this.isConnectionWanted = false;\n this.lastMessageAt = DateTime.now().minus({year: 1});\n }\n\n on(event: E, callback: XmrEvents[E]) {\n return this.emitter.on(event, callback);\n }\n\n async init() {\n this.interval = setInterval(() => {\n if (this.isConnectionWanted && !this.isActive()) {\n console.debug('Xmr::setInterval: should be active');\n\n // Call start again\n this.start(this.url || 'DISABLED', this.cmsKey || 'n/a');\n }\n }, 60000);\n }\n\n async start(url: string, cmsKey: string){\n if (!this.channel || this.channel === 'unknown') {\n console.error('Xmr::start: channel unknown, XMR will be disabled');\n return;\n }\n\n // Disable XMR if we've been told to.\n if (this.url === 'DISABLED') {\n console.info('Xmr::start: XMR disabled');\n this.isConnectionWanted = false;\n if (this.isActive()) {\n stop();\n }\n return;\n }\n\n this.isConnectionWanted = true;\n\n // Are we already connected?\n if (this.isActive() && this.url === url) {\n console.debug('Xmr::start: already connected to this URL');\n this.cmsKey = cmsKey;\n return;\n } else if (this.isConnected) {\n console.debug('Xmr::start: already connected but not active, or a different URL');\n await this.stop();\n } else {\n console.debug('Xmr::start: not connected yet');\n }\n\n // Set the URL and cmsKey.\n this.url = url;\n this.cmsKey = cmsKey;\n\n console.debug('Xmr::start: connecting to ' + this.url);\n\n try {\n this.socket = new WebSocket(this.url);\n } catch (e) {\n console.debug('Xmr::start: failed connecting to ' + this.url + ', e = ' + e);\n this.emitter.emit('error', 'Failed to connect');\n return;\n }\n\n /**\n * Listener for socket open\n */\n this.socket.addEventListener('open', (event) => {\n console.debug('Xmr::' + event.type);\n\n if (this.socket.readyState !== WebSocket.OPEN) {\n console.info('Xmr::' + event.type + ': not open yet');\n return;\n }\n\n // Create and send an initialisation message.\n this.socket.send(JSON.stringify({\n 'type': 'init',\n 'key': this.cmsKey,\n 'channel': this.channel,\n }));\n\n this.isConnected = true;\n\n this.emitter.emit('connected');\n });\n\n /**\n * Listener for socket close\n */\n this.socket.addEventListener('close', (event) => {\n console.debug('Xmr::' + event.type);\n\n this.isConnected = false;\n\n this.emitter.emit('disconnected');\n });\n\n /**\n * Listener for socket error\n */\n this.socket.addEventListener('error', (event) => {\n console.debug('Xmr::' + event.type);\n\n this.emitter.emit('error', 'error');\n });\n\n /**\n * Listener for socket message\n */\n this.socket.addEventListener('message', (event) => {\n console.debug(event);\n\n this.lastMessageAt = DateTime.now();\n this.emitter.emit('statusChange', this.lastMessageAt.toISO() || '');\n\n // Expect a JSON message or a H\n if (event.data === 'H') {\n console.debug('Xmr::message: Heartbeat...');\n } else {\n // JSON message.\n const message = JSON.parse(event.data);\n\n console.debug('Xmr::message: action is ' + message.action);\n\n // Check the createdDt and TTL against the current date time.\n const expiresAt = DateTime.fromISO(message.createdDt).plus({seconds: parseInt(message.ttl)});\n if (expiresAt < DateTime.now()) {\n console.debug('Xmr::message: message expired at ' + expiresAt.toString());\n } else if (message.action === 'collectNow') {\n this.emitter.emit('collectNow');\n } else if (message.action === 'screenShot') {\n this.emitter.emit('screenShot');\n } else if (message.action === 'licenceCheck') {\n this.emitter.emit('licenceCheck');\n } else if (message.action == 'commandAction' && message.commandCode.startsWith('showStatusWindow')) {\n const split = message.commandCode.split('|');\n this.emitter.emit('showStatusWindow', parseInt(split[1]) || 60);\n } else {\n console.error('Xmr::message: unknown action: ' + message.action);\n }\n }\n });\n }\n\n async stop() {\n console.debug('Xmr::stop');\n if (this.socket) {\n console.debug('Xmr::stop: closing active socket');\n this.socket.close();\n this.isConnected = false;\n }\n }\n\n isActive(): boolean {\n console.debug('Xmr::isActive: lastMessageAt: ' + this.lastMessageAt.toString());\n return this.isConnected && this.lastMessageAt > DateTime.now().minus({minute: 15});\n }\n}\n"],"names":["createNanoEvents","emit","event","_len","arguments","length","args","Array","_key","callbacks","events","i","apply","on","cb","_this$events","_this","push","_this$events$event","filter","Xmr","channel","_classCallCheck","_defineProperty","emitter","url","cmsKey","isConnected","isConnectionWanted","lastMessageAt","DateTime","now","minus","year","_createClass","key","value","callback","_init","_asyncToGenerator","_regeneratorRuntime","mark","_callee","wrap","_callee$","_context","prev","next","interval","setInterval","isActive","console","debug","start","stop","init","_start","_callee2","_this2","_callee2$","_context2","error","abrupt","info","socket","WebSocket","t0","addEventListener","type","readyState","OPEN","send","JSON","stringify","toISO","data","message","parse","action","expiresAt","fromISO","createdDt","plus","seconds","parseInt","ttl","toString","commandCode","startsWith","split","_x","_x2","_stop","_callee3","_callee3$","_context3","close","minute"],"mappings":"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","x_google_ignoreList":[0]} \ No newline at end of file diff --git a/dist/xibo-communication-framework.d.ts b/dist/xibo-communication-framework.d.ts new file mode 100644 index 0000000..456e2da --- /dev/null +++ b/dist/xibo-communication-framework.d.ts @@ -0,0 +1,34 @@ +import * as nanoevents from 'nanoevents'; +import { Emitter } from 'nanoevents'; +import { DateTime } from 'luxon'; + +interface XmrEvents { + connected: () => void; + disconnected: () => void; + error: (e: string) => void; + statusChange: (status: string) => void; + collectNow: () => void; + screenShot: () => void; + licenceCheck: () => void; + showStatusWindow: (timeout: number) => void; +} +declare class Xmr { + emitter: Emitter; + url: string | null; + cmsKey: string | null; + channel: string; + socket: WebSocket; + isConnectionWanted: boolean; + isConnected: boolean; + lastMessageAt: DateTime; + interval: NodeJS.Timeout | undefined; + constructor(channel: string); + on(event: E, callback: XmrEvents[E]): nanoevents.Unsubscribe; + init(): Promise; + start(url: string, cmsKey: string): Promise; + stop(): Promise; + isActive(): boolean; +} + +export { Xmr }; +export type { XmrEvents }; diff --git a/dist/xibo-communication-framework.esm.js b/dist/xibo-communication-framework.esm.js new file mode 100644 index 0000000..a107fda --- /dev/null +++ b/dist/xibo-communication-framework.esm.js @@ -0,0 +1,592 @@ +import { DateTime } from 'luxon'; + +function asyncGeneratorStep(n, t, e, r, o, a, c) { + try { + var i = n[a](c), + u = i.value; + } catch (n) { + return void e(n); + } + i.done ? t(u) : Promise.resolve(u).then(r, o); +} +function _asyncToGenerator(n) { + return function () { + var t = this, + e = arguments; + return new Promise(function (r, o) { + var a = n.apply(t, e); + function _next(n) { + asyncGeneratorStep(a, r, o, _next, _throw, "next", n); + } + function _throw(n) { + asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); + } + _next(void 0); + }); + }; +} +function _classCallCheck(a, n) { + if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); +} +function _defineProperties(e, r) { + for (var t = 0; t < r.length; t++) { + var o = r[t]; + o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o); + } +} +function _createClass(e, r, t) { + return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", { + writable: false + }), e; +} +function _defineProperty(e, r, t) { + return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { + value: t, + enumerable: true, + configurable: true, + writable: true + }) : e[r] = t, e; +} +function _regeneratorRuntime() { + _regeneratorRuntime = function () { + return r; + }; + var t, + r = {}, + e = Object.prototype, + n = e.hasOwnProperty, + o = "function" == typeof Symbol ? Symbol : {}, + i = o.iterator || "@@iterator", + a = o.asyncIterator || "@@asyncIterator", + u = o.toStringTag || "@@toStringTag"; + function c(t, r, e, n) { + return Object.defineProperty(t, r, { + value: e, + enumerable: !n, + configurable: !n, + writable: !n + }); + } + try { + c({}, ""); + } catch (t) { + c = function (t, r, e) { + return t[r] = e; + }; + } + function h(r, e, n, o) { + var i = e && e.prototype instanceof Generator ? e : Generator, + a = Object.create(i.prototype); + return c(a, "_invoke", function (r, e, n) { + var o = 1; + return function (i, a) { + if (3 === o) throw Error("Generator is already running"); + if (4 === o) { + if ("throw" === i) throw a; + return { + value: t, + done: true + }; + } + for (n.method = i, n.arg = a;;) { + var u = n.delegate; + if (u) { + var c = d(u, n); + if (c) { + if (c === f) continue; + return c; + } + } + if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { + if (1 === o) throw o = 4, n.arg; + n.dispatchException(n.arg); + } else "return" === n.method && n.abrupt("return", n.arg); + o = 3; + var h = s(r, e, n); + if ("normal" === h.type) { + if (o = n.done ? 4 : 2, h.arg === f) continue; + return { + value: h.arg, + done: n.done + }; + } + "throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg); + } + }; + }(r, n, new Context(o || [])), true), a; + } + function s(t, r, e) { + try { + return { + type: "normal", + arg: t.call(r, e) + }; + } catch (t) { + return { + type: "throw", + arg: t + }; + } + } + r.wrap = h; + var f = {}; + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + var l = {}; + c(l, i, function () { + return this; + }); + var p = Object.getPrototypeOf, + y = p && p(p(x([]))); + y && y !== e && n.call(y, i) && (l = y); + var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l); + function g(t) { + ["next", "throw", "return"].forEach(function (r) { + c(t, r, function (t) { + return this._invoke(r, t); + }); + }); + } + function AsyncIterator(t, r) { + function e(o, i, a, u) { + var c = s(t[o], t, i); + if ("throw" !== c.type) { + var h = c.arg, + f = h.value; + return f && "object" == typeof f && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) { + e("next", t, a, u); + }, function (t) { + e("throw", t, a, u); + }) : r.resolve(f).then(function (t) { + h.value = t, a(h); + }, function (t) { + return e("throw", t, a, u); + }); + } + u(c.arg); + } + var o; + c(this, "_invoke", function (t, n) { + function i() { + return new r(function (r, o) { + e(t, n, r, o); + }); + } + return o = o ? o.then(i, i) : i(); + }, true); + } + function d(r, e) { + var n = e.method, + o = r.i[n]; + if (o === t) return e.delegate = null, "throw" === n && r.i.return && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a '" + n + "' method")), f; + var i = s(o, r.i, e.arg); + if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f; + var a = i.arg; + return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f); + } + function w(t) { + this.tryEntries.push(t); + } + function m(r) { + var e = r[4] || {}; + e.type = "normal", e.arg = t, r[4] = e; + } + function Context(t) { + this.tryEntries = [[-1]], t.forEach(w, this), this.reset(true); + } + function x(r) { + if (null != r) { + var e = r[i]; + if (e) return e.call(r); + if ("function" == typeof r.next) return r; + if (!isNaN(r.length)) { + var o = -1, + a = function e() { + for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = false, e; + return e.value = t, e.done = true, e; + }; + return a.next = a; + } + } + throw new TypeError(typeof r + " is not iterable"); + } + return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) { + var r = "function" == typeof t && t.constructor; + return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name)); + }, r.mark = function (t) { + return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t; + }, r.awrap = function (t) { + return { + __await: t + }; + }, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () { + return this; + }), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) { + void 0 === i && (i = Promise); + var a = new AsyncIterator(h(t, e, n, o), i); + return r.isGeneratorFunction(e) ? a : a.next().then(function (t) { + return t.done ? t.value : a.next(); + }); + }, g(v), c(v, u, "Generator"), c(v, i, function () { + return this; + }), c(v, "toString", function () { + return "[object Generator]"; + }), r.keys = function (t) { + var r = Object(t), + e = []; + for (var n in r) e.unshift(n); + return function t() { + for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = false, t; + return t.done = true, t; + }; + }, r.values = x, Context.prototype = { + constructor: Context, + reset: function (r) { + if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = false, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t); + }, + stop: function () { + this.done = true; + var t = this.tryEntries[0][4]; + if ("throw" === t.type) throw t.arg; + return this.rval; + }, + dispatchException: function (r) { + if (this.done) throw r; + var e = this; + function n(t) { + a.type = "throw", a.arg = r, e.next = t; + } + for (var o = e.tryEntries.length - 1; o >= 0; --o) { + var i = this.tryEntries[o], + a = i[4], + u = this.prev, + c = i[1], + h = i[2]; + if (-1 === i[0]) return n("end"), false; + if (!c && !h) throw Error("try statement without catch or finally"); + if (null != i[0] && i[0] <= u) { + if (u < c) return this.method = "next", this.arg = t, n(c), true; + if (u < h) return n(h), false; + } + } + }, + abrupt: function (t, r) { + for (var e = this.tryEntries.length - 1; e >= 0; --e) { + var n = this.tryEntries[e]; + if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { + var o = n; + break; + } + } + o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null); + var i = o ? o[4] : {}; + return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i); + }, + complete: function (t, r) { + if ("throw" === t.type) throw t.arg; + return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f; + }, + finish: function (t) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var e = this.tryEntries[r]; + if (e[2] === t) return this.complete(e[4], e[3]), m(e), f; + } + }, + catch: function (t) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var e = this.tryEntries[r]; + if (e[0] === t) { + var n = e[4]; + if ("throw" === n.type) { + var o = n.arg; + m(e); + } + return o; + } + } + throw Error("illegal catch attempt"); + }, + delegateYield: function (r, e, n) { + return this.delegate = { + i: x(r), + r: e, + n: n + }, "next" === this.method && (this.arg = t), f; + } + }, r; +} +function _toPrimitive(t, r) { + if ("object" != typeof t || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r); + if ("object" != typeof i) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (String )(t); +} +function _toPropertyKey(t) { + var i = _toPrimitive(t, "string"); + return "symbol" == typeof i ? i : i + ""; +} + +var createNanoEvents = function createNanoEvents() { + return { + emit: function emit(event) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + for (var callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) { + callbacks[i].apply(callbacks, args); + } + }, + events: {}, + on: function on(event, cb) { + var _this$events, + _this = this; + ((_this$events = this.events)[event] || (_this$events[event] = [])).push(cb); + return function () { + var _this$events$event; + _this.events[event] = (_this$events$event = _this.events[event]) === null || _this$events$event === void 0 ? void 0 : _this$events$event.filter(function (i) { + return cb !== i; + }); + }; + } + }; +}; + +var Xmr = /*#__PURE__*/function () { + function Xmr(channel) { + _classCallCheck(this, Xmr); + _defineProperty(this, "emitter", void 0); + _defineProperty(this, "url", void 0); + _defineProperty(this, "cmsKey", void 0); + _defineProperty(this, "channel", void 0); + _defineProperty(this, "socket", void 0); + // State + _defineProperty(this, "isConnectionWanted", void 0); + _defineProperty(this, "isConnected", void 0); + _defineProperty(this, "lastMessageAt", void 0); + _defineProperty(this, "interval", void 0); + // Emitter + this.emitter = createNanoEvents(); + this.url = null; + this.cmsKey = null; + this.channel = channel; + this.isConnected = false; + this.isConnectionWanted = false; + this.lastMessageAt = DateTime.now().minus({ + year: 1 + }); + } + return _createClass(Xmr, [{ + key: "on", + value: function on(event, callback) { + return this.emitter.on(event, callback); + } + }, { + key: "init", + value: function () { + var _init = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() { + var _this = this; + return _regeneratorRuntime().wrap(function _callee$(_context) { + while (1) switch (_context.prev = _context.next) { + case 0: + this.interval = setInterval(function () { + if (_this.isConnectionWanted && !_this.isActive()) { + console.debug('Xmr::setInterval: should be active'); + // Call start again + _this.start(_this.url || 'DISABLED', _this.cmsKey || 'n/a'); + } + }, 60000); + case 1: + case "end": + return _context.stop(); + } + }, _callee, this); + })); + function init() { + return _init.apply(this, arguments); + } + return init; + }() + }, { + key: "start", + value: function () { + var _start = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(url, cmsKey) { + var _this2 = this; + return _regeneratorRuntime().wrap(function _callee2$(_context2) { + while (1) switch (_context2.prev = _context2.next) { + case 0: + if (!(!this.channel || this.channel === 'unknown')) { + _context2.next = 3; + break; + } + console.error('Xmr::start: channel unknown, XMR will be disabled'); + return _context2.abrupt("return"); + case 3: + if (!(this.url === 'DISABLED')) { + _context2.next = 8; + break; + } + console.info('Xmr::start: XMR disabled'); + this.isConnectionWanted = false; + if (this.isActive()) { + stop(); + } + return _context2.abrupt("return"); + case 8: + this.isConnectionWanted = true; + // Are we already connected? + if (!(this.isActive() && this.url === url)) { + _context2.next = 15; + break; + } + console.debug('Xmr::start: already connected to this URL'); + this.cmsKey = cmsKey; + return _context2.abrupt("return"); + case 15: + if (!this.isConnected) { + _context2.next = 21; + break; + } + console.debug('Xmr::start: already connected but not active, or a different URL'); + _context2.next = 19; + return this.stop(); + case 19: + _context2.next = 22; + break; + case 21: + console.debug('Xmr::start: not connected yet'); + case 22: + // Set the URL and cmsKey. + this.url = url; + this.cmsKey = cmsKey; + console.debug('Xmr::start: connecting to ' + this.url); + _context2.prev = 25; + this.socket = new WebSocket(this.url); + _context2.next = 34; + break; + case 29: + _context2.prev = 29; + _context2.t0 = _context2["catch"](25); + console.debug('Xmr::start: failed connecting to ' + this.url + ', e = ' + _context2.t0); + this.emitter.emit('error', 'Failed to connect'); + return _context2.abrupt("return"); + case 34: + /** + * Listener for socket open + */ + this.socket.addEventListener('open', function (event) { + console.debug('Xmr::' + event.type); + if (_this2.socket.readyState !== WebSocket.OPEN) { + console.info('Xmr::' + event.type + ': not open yet'); + return; + } + // Create and send an initialisation message. + _this2.socket.send(JSON.stringify({ + 'type': 'init', + 'key': _this2.cmsKey, + 'channel': _this2.channel + })); + _this2.isConnected = true; + _this2.emitter.emit('connected'); + }); + /** + * Listener for socket close + */ + this.socket.addEventListener('close', function (event) { + console.debug('Xmr::' + event.type); + _this2.isConnected = false; + _this2.emitter.emit('disconnected'); + }); + /** + * Listener for socket error + */ + this.socket.addEventListener('error', function (event) { + console.debug('Xmr::' + event.type); + _this2.emitter.emit('error', 'error'); + }); + /** + * Listener for socket message + */ + this.socket.addEventListener('message', function (event) { + console.debug(event); + _this2.lastMessageAt = DateTime.now(); + _this2.emitter.emit('statusChange', _this2.lastMessageAt.toISO() || ''); + // Expect a JSON message or a H + if (event.data === 'H') { + console.debug('Xmr::message: Heartbeat...'); + } else { + // JSON message. + var message = JSON.parse(event.data); + console.debug('Xmr::message: action is ' + message.action); + // Check the createdDt and TTL against the current date time. + var expiresAt = DateTime.fromISO(message.createdDt).plus({ + seconds: parseInt(message.ttl) + }); + if (expiresAt < DateTime.now()) { + console.debug('Xmr::message: message expired at ' + expiresAt.toString()); + } else if (message.action === 'collectNow') { + _this2.emitter.emit('collectNow'); + } else if (message.action === 'screenShot') { + _this2.emitter.emit('screenShot'); + } else if (message.action === 'licenceCheck') { + _this2.emitter.emit('licenceCheck'); + } else if (message.action == 'commandAction' && message.commandCode.startsWith('showStatusWindow')) { + var split = message.commandCode.split('|'); + _this2.emitter.emit('showStatusWindow', parseInt(split[1]) || 60); + } else { + console.error('Xmr::message: unknown action: ' + message.action); + } + } + }); + case 38: + case "end": + return _context2.stop(); + } + }, _callee2, this, [[25, 29]]); + })); + function start(_x, _x2) { + return _start.apply(this, arguments); + } + return start; + }() + }, { + key: "stop", + value: function () { + var _stop = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() { + return _regeneratorRuntime().wrap(function _callee3$(_context3) { + while (1) switch (_context3.prev = _context3.next) { + case 0: + console.debug('Xmr::stop'); + if (this.socket) { + console.debug('Xmr::stop: closing active socket'); + this.socket.close(); + this.isConnected = false; + } + case 2: + case "end": + return _context3.stop(); + } + }, _callee3, this); + })); + function stop() { + return _stop.apply(this, arguments); + } + return stop; + }() + }, { + key: "isActive", + value: function isActive() { + console.debug('Xmr::isActive: lastMessageAt: ' + this.lastMessageAt.toString()); + return this.isConnected && this.lastMessageAt > DateTime.now().minus({ + minute: 15 + }); + } + }]); +}(); + +export { Xmr }; +//# sourceMappingURL=xibo-communication-framework.esm.js.map diff --git a/dist/xibo-communication-framework.esm.js.map b/dist/xibo-communication-framework.esm.js.map new file mode 100644 index 0000000..305206b --- /dev/null +++ b/dist/xibo-communication-framework.esm.js.map @@ -0,0 +1 @@ +{"version":3,"file":"xibo-communication-framework.esm.js","sources":["../node_modules/nanoevents/index.js","../../src/modules/xmr/xmr.ts"],"sourcesContent":["export let createNanoEvents = () => ({\n emit(event, ...args) {\n for (\n let callbacks = this.events[event] || [],\n i = 0,\n length = callbacks.length;\n i < length;\n i++\n ) {\n callbacks[i](...args)\n }\n },\n events: {},\n on(event, cb) {\n ;(this.events[event] ||= []).push(cb)\n return () => {\n this.events[event] = this.events[event]?.filter(i => cb !== i)\n }\n }\n})\n","/*\n * Copyright (C) 2025 Xibo Signage Ltd\n *\n * Xibo - Digital Signage - https://www.xibosignage.com\n *\n * This file is part of Xibo.\n *\n * Xibo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * any later version.\n *\n * Xibo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with Xibo. If not, see .\n */\nimport {createNanoEvents, type Emitter} from 'nanoevents';\nimport {DateTime} from 'luxon';\n\nexport interface XmrEvents {\n connected: () => void;\n disconnected: () => void;\n error: (e: string) => void;\n statusChange: (status: string) => void;\n\n collectNow: () => void;\n screenShot: () => void;\n licenceCheck: () => void;\n showStatusWindow: (timeout: number) => void;\n}\n\nexport default class Xmr {\n emitter: Emitter;\n\n url: string | null;\n cmsKey: string | null;\n channel: string;\n socket!: WebSocket;\n\n // State\n isConnectionWanted: boolean;\n isConnected: boolean;\n lastMessageAt: DateTime;\n\n interval: NodeJS.Timeout | undefined;\n\n constructor (channel: string) {\n // Emitter\n this.emitter = createNanoEvents();\n this.url = null;\n this.cmsKey = null;\n this.channel = channel;\n this.isConnected = false;\n this.isConnectionWanted = false;\n this.lastMessageAt = DateTime.now().minus({year: 1});\n }\n\n on(event: E, callback: XmrEvents[E]) {\n return this.emitter.on(event, callback);\n }\n\n async init() {\n this.interval = setInterval(() => {\n if (this.isConnectionWanted && !this.isActive()) {\n console.debug('Xmr::setInterval: should be active');\n\n // Call start again\n this.start(this.url || 'DISABLED', this.cmsKey || 'n/a');\n }\n }, 60000);\n }\n\n async start(url: string, cmsKey: string){\n if (!this.channel || this.channel === 'unknown') {\n console.error('Xmr::start: channel unknown, XMR will be disabled');\n return;\n }\n\n // Disable XMR if we've been told to.\n if (this.url === 'DISABLED') {\n console.info('Xmr::start: XMR disabled');\n this.isConnectionWanted = false;\n if (this.isActive()) {\n stop();\n }\n return;\n }\n\n this.isConnectionWanted = true;\n\n // Are we already connected?\n if (this.isActive() && this.url === url) {\n console.debug('Xmr::start: already connected to this URL');\n this.cmsKey = cmsKey;\n return;\n } else if (this.isConnected) {\n console.debug('Xmr::start: already connected but not active, or a different URL');\n await this.stop();\n } else {\n console.debug('Xmr::start: not connected yet');\n }\n\n // Set the URL and cmsKey.\n this.url = url;\n this.cmsKey = cmsKey;\n\n console.debug('Xmr::start: connecting to ' + this.url);\n\n try {\n this.socket = new WebSocket(this.url);\n } catch (e) {\n console.debug('Xmr::start: failed connecting to ' + this.url + ', e = ' + e);\n this.emitter.emit('error', 'Failed to connect');\n return;\n }\n\n /**\n * Listener for socket open\n */\n this.socket.addEventListener('open', (event) => {\n console.debug('Xmr::' + event.type);\n\n if (this.socket.readyState !== WebSocket.OPEN) {\n console.info('Xmr::' + event.type + ': not open yet');\n return;\n }\n\n // Create and send an initialisation message.\n this.socket.send(JSON.stringify({\n 'type': 'init',\n 'key': this.cmsKey,\n 'channel': this.channel,\n }));\n\n this.isConnected = true;\n\n this.emitter.emit('connected');\n });\n\n /**\n * Listener for socket close\n */\n this.socket.addEventListener('close', (event) => {\n console.debug('Xmr::' + event.type);\n\n this.isConnected = false;\n\n this.emitter.emit('disconnected');\n });\n\n /**\n * Listener for socket error\n */\n this.socket.addEventListener('error', (event) => {\n console.debug('Xmr::' + event.type);\n\n this.emitter.emit('error', 'error');\n });\n\n /**\n * Listener for socket message\n */\n this.socket.addEventListener('message', (event) => {\n console.debug(event);\n\n this.lastMessageAt = DateTime.now();\n this.emitter.emit('statusChange', this.lastMessageAt.toISO() || '');\n\n // Expect a JSON message or a H\n if (event.data === 'H') {\n console.debug('Xmr::message: Heartbeat...');\n } else {\n // JSON message.\n const message = JSON.parse(event.data);\n\n console.debug('Xmr::message: action is ' + message.action);\n\n // Check the createdDt and TTL against the current date time.\n const expiresAt = DateTime.fromISO(message.createdDt).plus({seconds: parseInt(message.ttl)});\n if (expiresAt < DateTime.now()) {\n console.debug('Xmr::message: message expired at ' + expiresAt.toString());\n } else if (message.action === 'collectNow') {\n this.emitter.emit('collectNow');\n } else if (message.action === 'screenShot') {\n this.emitter.emit('screenShot');\n } else if (message.action === 'licenceCheck') {\n this.emitter.emit('licenceCheck');\n } else if (message.action == 'commandAction' && message.commandCode.startsWith('showStatusWindow')) {\n const split = message.commandCode.split('|');\n this.emitter.emit('showStatusWindow', parseInt(split[1]) || 60);\n } else {\n console.error('Xmr::message: unknown action: ' + message.action);\n }\n }\n });\n }\n\n async stop() {\n console.debug('Xmr::stop');\n if (this.socket) {\n console.debug('Xmr::stop: closing active socket');\n this.socket.close();\n this.isConnected = false;\n }\n }\n\n isActive(): boolean {\n console.debug('Xmr::isActive: lastMessageAt: ' + this.lastMessageAt.toString());\n return this.isConnected && this.lastMessageAt > DateTime.now().minus({minute: 15});\n }\n}\n"],"names":["createNanoEvents","emit","event","_len","arguments","length","args","Array","_key","callbacks","events","i","apply","on","cb","_this$events","_this","push","_this$events$event","filter","Xmr","channel","_classCallCheck","_defineProperty","emitter","url","cmsKey","isConnected","isConnectionWanted","lastMessageAt","DateTime","now","minus","year","_createClass","key","value","callback","_init","_asyncToGenerator","_regeneratorRuntime","mark","_callee","wrap","_callee$","_context","prev","next","interval","setInterval","isActive","console","debug","start","stop","init","_start","_callee2","_this2","_callee2$","_context2","error","abrupt","info","socket","WebSocket","t0","addEventListener","type","readyState","OPEN","send","JSON","stringify","toISO","data","message","parse","action","expiresAt","fromISO","createdDt","plus","seconds","parseInt","ttl","toString","commandCode","startsWith","split","_x","_x2","_stop","_callee3","_callee3$","_context3","close","minute"],"mappings":"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","x_google_ignoreList":[0]} \ No newline at end of file diff --git a/dist/xibo-communication-framework.js b/dist/xibo-communication-framework.js new file mode 100644 index 0000000..ec65ebe --- /dev/null +++ b/dist/xibo-communication-framework.js @@ -0,0 +1,596 @@ +var XiboCommunicationFramework = (function (exports, luxon) { + 'use strict'; + + function asyncGeneratorStep(n, t, e, r, o, a, c) { + try { + var i = n[a](c), + u = i.value; + } catch (n) { + return void e(n); + } + i.done ? t(u) : Promise.resolve(u).then(r, o); + } + function _asyncToGenerator(n) { + return function () { + var t = this, + e = arguments; + return new Promise(function (r, o) { + var a = n.apply(t, e); + function _next(n) { + asyncGeneratorStep(a, r, o, _next, _throw, "next", n); + } + function _throw(n) { + asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); + } + _next(void 0); + }); + }; + } + function _classCallCheck(a, n) { + if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); + } + function _defineProperties(e, r) { + for (var t = 0; t < r.length; t++) { + var o = r[t]; + o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o); + } + } + function _createClass(e, r, t) { + return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", { + writable: false + }), e; + } + function _defineProperty(e, r, t) { + return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { + value: t, + enumerable: true, + configurable: true, + writable: true + }) : e[r] = t, e; + } + function _regeneratorRuntime() { + _regeneratorRuntime = function () { + return r; + }; + var t, + r = {}, + e = Object.prototype, + n = e.hasOwnProperty, + o = "function" == typeof Symbol ? Symbol : {}, + i = o.iterator || "@@iterator", + a = o.asyncIterator || "@@asyncIterator", + u = o.toStringTag || "@@toStringTag"; + function c(t, r, e, n) { + return Object.defineProperty(t, r, { + value: e, + enumerable: !n, + configurable: !n, + writable: !n + }); + } + try { + c({}, ""); + } catch (t) { + c = function (t, r, e) { + return t[r] = e; + }; + } + function h(r, e, n, o) { + var i = e && e.prototype instanceof Generator ? e : Generator, + a = Object.create(i.prototype); + return c(a, "_invoke", function (r, e, n) { + var o = 1; + return function (i, a) { + if (3 === o) throw Error("Generator is already running"); + if (4 === o) { + if ("throw" === i) throw a; + return { + value: t, + done: true + }; + } + for (n.method = i, n.arg = a;;) { + var u = n.delegate; + if (u) { + var c = d(u, n); + if (c) { + if (c === f) continue; + return c; + } + } + if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { + if (1 === o) throw o = 4, n.arg; + n.dispatchException(n.arg); + } else "return" === n.method && n.abrupt("return", n.arg); + o = 3; + var h = s(r, e, n); + if ("normal" === h.type) { + if (o = n.done ? 4 : 2, h.arg === f) continue; + return { + value: h.arg, + done: n.done + }; + } + "throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg); + } + }; + }(r, n, new Context(o || [])), true), a; + } + function s(t, r, e) { + try { + return { + type: "normal", + arg: t.call(r, e) + }; + } catch (t) { + return { + type: "throw", + arg: t + }; + } + } + r.wrap = h; + var f = {}; + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + var l = {}; + c(l, i, function () { + return this; + }); + var p = Object.getPrototypeOf, + y = p && p(p(x([]))); + y && y !== e && n.call(y, i) && (l = y); + var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l); + function g(t) { + ["next", "throw", "return"].forEach(function (r) { + c(t, r, function (t) { + return this._invoke(r, t); + }); + }); + } + function AsyncIterator(t, r) { + function e(o, i, a, u) { + var c = s(t[o], t, i); + if ("throw" !== c.type) { + var h = c.arg, + f = h.value; + return f && "object" == typeof f && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) { + e("next", t, a, u); + }, function (t) { + e("throw", t, a, u); + }) : r.resolve(f).then(function (t) { + h.value = t, a(h); + }, function (t) { + return e("throw", t, a, u); + }); + } + u(c.arg); + } + var o; + c(this, "_invoke", function (t, n) { + function i() { + return new r(function (r, o) { + e(t, n, r, o); + }); + } + return o = o ? o.then(i, i) : i(); + }, true); + } + function d(r, e) { + var n = e.method, + o = r.i[n]; + if (o === t) return e.delegate = null, "throw" === n && r.i.return && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a '" + n + "' method")), f; + var i = s(o, r.i, e.arg); + if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f; + var a = i.arg; + return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f); + } + function w(t) { + this.tryEntries.push(t); + } + function m(r) { + var e = r[4] || {}; + e.type = "normal", e.arg = t, r[4] = e; + } + function Context(t) { + this.tryEntries = [[-1]], t.forEach(w, this), this.reset(true); + } + function x(r) { + if (null != r) { + var e = r[i]; + if (e) return e.call(r); + if ("function" == typeof r.next) return r; + if (!isNaN(r.length)) { + var o = -1, + a = function e() { + for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = false, e; + return e.value = t, e.done = true, e; + }; + return a.next = a; + } + } + throw new TypeError(typeof r + " is not iterable"); + } + return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) { + var r = "function" == typeof t && t.constructor; + return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name)); + }, r.mark = function (t) { + return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t; + }, r.awrap = function (t) { + return { + __await: t + }; + }, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () { + return this; + }), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) { + void 0 === i && (i = Promise); + var a = new AsyncIterator(h(t, e, n, o), i); + return r.isGeneratorFunction(e) ? a : a.next().then(function (t) { + return t.done ? t.value : a.next(); + }); + }, g(v), c(v, u, "Generator"), c(v, i, function () { + return this; + }), c(v, "toString", function () { + return "[object Generator]"; + }), r.keys = function (t) { + var r = Object(t), + e = []; + for (var n in r) e.unshift(n); + return function t() { + for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = false, t; + return t.done = true, t; + }; + }, r.values = x, Context.prototype = { + constructor: Context, + reset: function (r) { + if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = false, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t); + }, + stop: function () { + this.done = true; + var t = this.tryEntries[0][4]; + if ("throw" === t.type) throw t.arg; + return this.rval; + }, + dispatchException: function (r) { + if (this.done) throw r; + var e = this; + function n(t) { + a.type = "throw", a.arg = r, e.next = t; + } + for (var o = e.tryEntries.length - 1; o >= 0; --o) { + var i = this.tryEntries[o], + a = i[4], + u = this.prev, + c = i[1], + h = i[2]; + if (-1 === i[0]) return n("end"), false; + if (!c && !h) throw Error("try statement without catch or finally"); + if (null != i[0] && i[0] <= u) { + if (u < c) return this.method = "next", this.arg = t, n(c), true; + if (u < h) return n(h), false; + } + } + }, + abrupt: function (t, r) { + for (var e = this.tryEntries.length - 1; e >= 0; --e) { + var n = this.tryEntries[e]; + if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { + var o = n; + break; + } + } + o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null); + var i = o ? o[4] : {}; + return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i); + }, + complete: function (t, r) { + if ("throw" === t.type) throw t.arg; + return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f; + }, + finish: function (t) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var e = this.tryEntries[r]; + if (e[2] === t) return this.complete(e[4], e[3]), m(e), f; + } + }, + catch: function (t) { + for (var r = this.tryEntries.length - 1; r >= 0; --r) { + var e = this.tryEntries[r]; + if (e[0] === t) { + var n = e[4]; + if ("throw" === n.type) { + var o = n.arg; + m(e); + } + return o; + } + } + throw Error("illegal catch attempt"); + }, + delegateYield: function (r, e, n) { + return this.delegate = { + i: x(r), + r: e, + n: n + }, "next" === this.method && (this.arg = t), f; + } + }, r; + } + function _toPrimitive(t, r) { + if ("object" != typeof t || !t) return t; + var e = t[Symbol.toPrimitive]; + if (void 0 !== e) { + var i = e.call(t, r); + if ("object" != typeof i) return i; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (String )(t); + } + function _toPropertyKey(t) { + var i = _toPrimitive(t, "string"); + return "symbol" == typeof i ? i : i + ""; + } + + var createNanoEvents = function createNanoEvents() { + return { + emit: function emit(event) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + for (var callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) { + callbacks[i].apply(callbacks, args); + } + }, + events: {}, + on: function on(event, cb) { + var _this$events, + _this = this; + ((_this$events = this.events)[event] || (_this$events[event] = [])).push(cb); + return function () { + var _this$events$event; + _this.events[event] = (_this$events$event = _this.events[event]) === null || _this$events$event === void 0 ? void 0 : _this$events$event.filter(function (i) { + return cb !== i; + }); + }; + } + }; + }; + + var Xmr = /*#__PURE__*/function () { + function Xmr(channel) { + _classCallCheck(this, Xmr); + _defineProperty(this, "emitter", void 0); + _defineProperty(this, "url", void 0); + _defineProperty(this, "cmsKey", void 0); + _defineProperty(this, "channel", void 0); + _defineProperty(this, "socket", void 0); + // State + _defineProperty(this, "isConnectionWanted", void 0); + _defineProperty(this, "isConnected", void 0); + _defineProperty(this, "lastMessageAt", void 0); + _defineProperty(this, "interval", void 0); + // Emitter + this.emitter = createNanoEvents(); + this.url = null; + this.cmsKey = null; + this.channel = channel; + this.isConnected = false; + this.isConnectionWanted = false; + this.lastMessageAt = luxon.DateTime.now().minus({ + year: 1 + }); + } + return _createClass(Xmr, [{ + key: "on", + value: function on(event, callback) { + return this.emitter.on(event, callback); + } + }, { + key: "init", + value: function () { + var _init = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() { + var _this = this; + return _regeneratorRuntime().wrap(function _callee$(_context) { + while (1) switch (_context.prev = _context.next) { + case 0: + this.interval = setInterval(function () { + if (_this.isConnectionWanted && !_this.isActive()) { + console.debug('Xmr::setInterval: should be active'); + // Call start again + _this.start(_this.url || 'DISABLED', _this.cmsKey || 'n/a'); + } + }, 60000); + case 1: + case "end": + return _context.stop(); + } + }, _callee, this); + })); + function init() { + return _init.apply(this, arguments); + } + return init; + }() + }, { + key: "start", + value: function () { + var _start = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(url, cmsKey) { + var _this2 = this; + return _regeneratorRuntime().wrap(function _callee2$(_context2) { + while (1) switch (_context2.prev = _context2.next) { + case 0: + if (!(!this.channel || this.channel === 'unknown')) { + _context2.next = 3; + break; + } + console.error('Xmr::start: channel unknown, XMR will be disabled'); + return _context2.abrupt("return"); + case 3: + if (!(this.url === 'DISABLED')) { + _context2.next = 8; + break; + } + console.info('Xmr::start: XMR disabled'); + this.isConnectionWanted = false; + if (this.isActive()) { + stop(); + } + return _context2.abrupt("return"); + case 8: + this.isConnectionWanted = true; + // Are we already connected? + if (!(this.isActive() && this.url === url)) { + _context2.next = 15; + break; + } + console.debug('Xmr::start: already connected to this URL'); + this.cmsKey = cmsKey; + return _context2.abrupt("return"); + case 15: + if (!this.isConnected) { + _context2.next = 21; + break; + } + console.debug('Xmr::start: already connected but not active, or a different URL'); + _context2.next = 19; + return this.stop(); + case 19: + _context2.next = 22; + break; + case 21: + console.debug('Xmr::start: not connected yet'); + case 22: + // Set the URL and cmsKey. + this.url = url; + this.cmsKey = cmsKey; + console.debug('Xmr::start: connecting to ' + this.url); + _context2.prev = 25; + this.socket = new WebSocket(this.url); + _context2.next = 34; + break; + case 29: + _context2.prev = 29; + _context2.t0 = _context2["catch"](25); + console.debug('Xmr::start: failed connecting to ' + this.url + ', e = ' + _context2.t0); + this.emitter.emit('error', 'Failed to connect'); + return _context2.abrupt("return"); + case 34: + /** + * Listener for socket open + */ + this.socket.addEventListener('open', function (event) { + console.debug('Xmr::' + event.type); + if (_this2.socket.readyState !== WebSocket.OPEN) { + console.info('Xmr::' + event.type + ': not open yet'); + return; + } + // Create and send an initialisation message. + _this2.socket.send(JSON.stringify({ + 'type': 'init', + 'key': _this2.cmsKey, + 'channel': _this2.channel + })); + _this2.isConnected = true; + _this2.emitter.emit('connected'); + }); + /** + * Listener for socket close + */ + this.socket.addEventListener('close', function (event) { + console.debug('Xmr::' + event.type); + _this2.isConnected = false; + _this2.emitter.emit('disconnected'); + }); + /** + * Listener for socket error + */ + this.socket.addEventListener('error', function (event) { + console.debug('Xmr::' + event.type); + _this2.emitter.emit('error', 'error'); + }); + /** + * Listener for socket message + */ + this.socket.addEventListener('message', function (event) { + console.debug(event); + _this2.lastMessageAt = luxon.DateTime.now(); + _this2.emitter.emit('statusChange', _this2.lastMessageAt.toISO() || ''); + // Expect a JSON message or a H + if (event.data === 'H') { + console.debug('Xmr::message: Heartbeat...'); + } else { + // JSON message. + var message = JSON.parse(event.data); + console.debug('Xmr::message: action is ' + message.action); + // Check the createdDt and TTL against the current date time. + var expiresAt = luxon.DateTime.fromISO(message.createdDt).plus({ + seconds: parseInt(message.ttl) + }); + if (expiresAt < luxon.DateTime.now()) { + console.debug('Xmr::message: message expired at ' + expiresAt.toString()); + } else if (message.action === 'collectNow') { + _this2.emitter.emit('collectNow'); + } else if (message.action === 'screenShot') { + _this2.emitter.emit('screenShot'); + } else if (message.action === 'licenceCheck') { + _this2.emitter.emit('licenceCheck'); + } else if (message.action == 'commandAction' && message.commandCode.startsWith('showStatusWindow')) { + var split = message.commandCode.split('|'); + _this2.emitter.emit('showStatusWindow', parseInt(split[1]) || 60); + } else { + console.error('Xmr::message: unknown action: ' + message.action); + } + } + }); + case 38: + case "end": + return _context2.stop(); + } + }, _callee2, this, [[25, 29]]); + })); + function start(_x, _x2) { + return _start.apply(this, arguments); + } + return start; + }() + }, { + key: "stop", + value: function () { + var _stop = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() { + return _regeneratorRuntime().wrap(function _callee3$(_context3) { + while (1) switch (_context3.prev = _context3.next) { + case 0: + console.debug('Xmr::stop'); + if (this.socket) { + console.debug('Xmr::stop: closing active socket'); + this.socket.close(); + this.isConnected = false; + } + case 2: + case "end": + return _context3.stop(); + } + }, _callee3, this); + })); + function stop() { + return _stop.apply(this, arguments); + } + return stop; + }() + }, { + key: "isActive", + value: function isActive() { + console.debug('Xmr::isActive: lastMessageAt: ' + this.lastMessageAt.toString()); + return this.isConnected && this.lastMessageAt > luxon.DateTime.now().minus({ + minute: 15 + }); + } + }]); + }(); + + exports.Xmr = Xmr; + + return exports; + +})({}, luxon); diff --git a/dist/xibo-communication-framework.min.js b/dist/xibo-communication-framework.min.js new file mode 100644 index 0000000..def8468 --- /dev/null +++ b/dist/xibo-communication-framework.min.js @@ -0,0 +1,2 @@ +var XiboCommunicationFramework=function(t,e){"use strict";function n(t,e,n,r,o,i,a){try{var s=t[i](a),c=s.value}catch(t){return void n(t)}s.done?e(c):Promise.resolve(c).then(r,o)}function r(t){return function(){var e=this,r=arguments;return new Promise((function(o,i){var a=t.apply(e,r);function s(t){n(a,o,i,s,c,"next",t)}function c(t){n(a,o,i,s,c,"throw",t)}s(void 0)}))}}function o(t,e,n){return e&&function(t,e){for(var n=0;n=0;--o){var i=this.tryEntries[o],a=i[4],s=this.prev,c=i[1],u=i[2];if(-1===i[0])return r("end"),!1;if(!c&&!u)throw Error("try statement without catch or finally");if(null!=i[0]&&i[0]<=s){if(s=0;--n){var r=this.tryEntries[n];if(r[0]>-1&&r[0]<=this.prev&&this.prev=0;--e){var n=this.tryEntries[e];if(n[2]===t)return this.complete(n[4],n[3]),X(n),f}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n[0]===t){var r=n[4];if("throw"===r.type){var o=r.arg;X(n)}return o}}throw Error("illegal catch attempt")},delegateYield:function(e,n,r){return this.delegate={i:O(e),r:n,n:r},"next"===this.method&&(this.arg=t),f}},e}function s(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var r=n.call(t,e);if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t,"string");return"symbol"==typeof e?e:e+""}var c=function(){return o((function t(n){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),i(this,"emitter",void 0),i(this,"url",void 0),i(this,"cmsKey",void 0),i(this,"channel",void 0),i(this,"socket",void 0),i(this,"isConnectionWanted",void 0),i(this,"isConnected",void 0),i(this,"lastMessageAt",void 0),i(this,"interval",void 0),this.emitter={emit:function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;re.DateTime.now().minus({minute:15})}}]);var t,n,s}();return t.Xmr=c,t}({},luxon); +//# sourceMappingURL=xibo-communication-framework.min.js.map diff --git a/dist/xibo-communication-framework.min.js.map b/dist/xibo-communication-framework.min.js.map new file mode 100644 index 0000000..17857cd --- /dev/null +++ b/dist/xibo-communication-framework.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"xibo-communication-framework.min.js","sources":["../node_modules/nanoevents/index.js","../../src/modules/xmr/xmr.ts"],"sourcesContent":["export let createNanoEvents = () => ({\n emit(event, ...args) {\n for (\n let callbacks = this.events[event] || [],\n i = 0,\n length = callbacks.length;\n i < length;\n i++\n ) {\n callbacks[i](...args)\n }\n },\n events: {},\n on(event, cb) {\n ;(this.events[event] ||= []).push(cb)\n return () => {\n this.events[event] = this.events[event]?.filter(i => cb !== i)\n }\n }\n})\n","/*\n * Copyright (C) 2025 Xibo Signage Ltd\n *\n * Xibo - Digital Signage - https://www.xibosignage.com\n *\n * This file is part of Xibo.\n *\n * Xibo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * any later version.\n *\n * Xibo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with Xibo. If not, see .\n */\nimport {createNanoEvents, type Emitter} from 'nanoevents';\nimport {DateTime} from 'luxon';\n\nexport interface XmrEvents {\n connected: () => void;\n disconnected: () => void;\n error: (e: string) => void;\n statusChange: (status: string) => void;\n\n collectNow: () => void;\n screenShot: () => void;\n licenceCheck: () => void;\n showStatusWindow: (timeout: number) => void;\n}\n\nexport default class Xmr {\n emitter: Emitter;\n\n url: string | null;\n cmsKey: string | null;\n channel: string;\n socket!: WebSocket;\n\n // State\n isConnectionWanted: boolean;\n isConnected: boolean;\n lastMessageAt: DateTime;\n\n interval: NodeJS.Timeout | undefined;\n\n constructor (channel: string) {\n // Emitter\n this.emitter = createNanoEvents();\n this.url = null;\n this.cmsKey = null;\n this.channel = channel;\n this.isConnected = false;\n this.isConnectionWanted = false;\n this.lastMessageAt = DateTime.now().minus({year: 1});\n }\n\n on(event: E, callback: XmrEvents[E]) {\n return this.emitter.on(event, callback);\n }\n\n async init() {\n this.interval = setInterval(() => {\n if (this.isConnectionWanted && !this.isActive()) {\n console.debug('Xmr::setInterval: should be active');\n\n // Call start again\n this.start(this.url || 'DISABLED', this.cmsKey || 'n/a');\n }\n }, 60000);\n }\n\n async start(url: string, cmsKey: string){\n if (!this.channel || this.channel === 'unknown') {\n console.error('Xmr::start: channel unknown, XMR will be disabled');\n return;\n }\n\n // Disable XMR if we've been told to.\n if (this.url === 'DISABLED') {\n console.info('Xmr::start: XMR disabled');\n this.isConnectionWanted = false;\n if (this.isActive()) {\n stop();\n }\n return;\n }\n\n this.isConnectionWanted = true;\n\n // Are we already connected?\n if (this.isActive() && this.url === url) {\n console.debug('Xmr::start: already connected to this URL');\n this.cmsKey = cmsKey;\n return;\n } else if (this.isConnected) {\n console.debug('Xmr::start: already connected but not active, or a different URL');\n await this.stop();\n } else {\n console.debug('Xmr::start: not connected yet');\n }\n\n // Set the URL and cmsKey.\n this.url = url;\n this.cmsKey = cmsKey;\n\n console.debug('Xmr::start: connecting to ' + this.url);\n\n try {\n this.socket = new WebSocket(this.url);\n } catch (e) {\n console.debug('Xmr::start: failed connecting to ' + this.url + ', e = ' + e);\n this.emitter.emit('error', 'Failed to connect');\n return;\n }\n\n /**\n * Listener for socket open\n */\n this.socket.addEventListener('open', (event) => {\n console.debug('Xmr::' + event.type);\n\n if (this.socket.readyState !== WebSocket.OPEN) {\n console.info('Xmr::' + event.type + ': not open yet');\n return;\n }\n\n // Create and send an initialisation message.\n this.socket.send(JSON.stringify({\n 'type': 'init',\n 'key': this.cmsKey,\n 'channel': this.channel,\n }));\n\n this.isConnected = true;\n\n this.emitter.emit('connected');\n });\n\n /**\n * Listener for socket close\n */\n this.socket.addEventListener('close', (event) => {\n console.debug('Xmr::' + event.type);\n\n this.isConnected = false;\n\n this.emitter.emit('disconnected');\n });\n\n /**\n * Listener for socket error\n */\n this.socket.addEventListener('error', (event) => {\n console.debug('Xmr::' + event.type);\n\n this.emitter.emit('error', 'error');\n });\n\n /**\n * Listener for socket message\n */\n this.socket.addEventListener('message', (event) => {\n console.debug(event);\n\n this.lastMessageAt = DateTime.now();\n this.emitter.emit('statusChange', this.lastMessageAt.toISO() || '');\n\n // Expect a JSON message or a H\n if (event.data === 'H') {\n console.debug('Xmr::message: Heartbeat...');\n } else {\n // JSON message.\n const message = JSON.parse(event.data);\n\n console.debug('Xmr::message: action is ' + message.action);\n\n // Check the createdDt and TTL against the current date time.\n const expiresAt = DateTime.fromISO(message.createdDt).plus({seconds: parseInt(message.ttl)});\n if (expiresAt < DateTime.now()) {\n console.debug('Xmr::message: message expired at ' + expiresAt.toString());\n } else if (message.action === 'collectNow') {\n this.emitter.emit('collectNow');\n } else if (message.action === 'screenShot') {\n this.emitter.emit('screenShot');\n } else if (message.action === 'licenceCheck') {\n this.emitter.emit('licenceCheck');\n } else if (message.action == 'commandAction' && message.commandCode.startsWith('showStatusWindow')) {\n const split = message.commandCode.split('|');\n this.emitter.emit('showStatusWindow', parseInt(split[1]) || 60);\n } else {\n console.error('Xmr::message: unknown action: ' + message.action);\n }\n }\n });\n }\n\n async stop() {\n console.debug('Xmr::stop');\n if (this.socket) {\n console.debug('Xmr::stop: closing active socket');\n this.socket.close();\n this.isConnected = false;\n }\n }\n\n isActive(): boolean {\n console.debug('Xmr::isActive: lastMessageAt: ' + this.lastMessageAt.toString());\n return this.isConnected && this.lastMessageAt > DateTime.now().minus({minute: 15});\n }\n}\n"],"names":["Xmr","_createClass","channel","_classCallCheck","_defineProperty","this","emitter","emit","event","_len","arguments","length","args","Array","_key","callbacks","events","i","apply","on","cb","_this$events","_this","push","_this$events$event","filter","url","cmsKey","isConnected","isConnectionWanted","lastMessageAt","DateTime","now","minus","year","key","value","callback","_init","_asyncToGenerator","_regeneratorRuntime","mark","_callee","wrap","_context","prev","next","interval","setInterval","isActive","console","debug","start","stop","_start","_callee2","_this2","_context2","error","abrupt","info","socket","WebSocket","t0","addEventListener","type","readyState","OPEN","send","JSON","stringify","toISO","data","message","parse","action","expiresAt","fromISO","createdDt","plus","seconds","parseInt","ttl","toString","commandCode","startsWith","split","_x","_x2","_stop","_callee3","_context3","close","minute"],"mappings":"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","x_google_ignoreList":[0]} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 10a9e41..5460dcb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "xibo-communication-framework", - "version": "1.0.0", + "name": "@xibosignage/xibo-communication-framework", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "xibo-communication-framework", - "version": "1.0.0", + "name": "@xibosignage/xibo-communication-framework", + "version": "0.0.1", "license": "LGPL-3.0", "devDependencies": { "@babel/core": "^7.27.1", diff --git a/package.json b/package.json index 2a7d7d1..81325a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xibosignage/xibo-communication-framework", - "version": "0.0.1", + "version": "0.0.2", "description": "Xibo Communication Framework", "main": "dist/xibo-communication-framework.cjs.js", "module": "dist/xibo-communication-framework.esm.js", diff --git a/rollup.config.ts b/rollup.config.ts index 2ccb8b2..b31d8b9 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -106,7 +106,18 @@ const config: RollupOptions[] = [ format: 'esm', } ], - } + }, + { + ...commonInputOptions, + plugins: [commonInputOptions.plugins], + output: [ + { + file: `${outputPath}${libName}.amd.js`, + format: 'amd', + sourcemap: true, + } + ], + }, ]; export default config;