@cutos/core
Version:
The CUTOS (CUT Operating System) Core API is a JavaScript library that provides essential functionalities for LWA (Local Web Application) edge computing and communication in the CUTOS ecosystem.
1,681 lines (1,438 loc) • 52.7 kB
JavaScript
import require$$1 from 'mqtt';
function getAugmentedNamespace(n) {
if (n.__esModule) return n;
var f = n.default;
if (typeof f == "function") {
var a = function a () {
if (this instanceof a) {
return Reflect.construct(f, arguments, this.constructor);
}
return f.apply(this, arguments);
};
a.prototype = f.prototype;
} else a = {};
Object.defineProperty(a, '__esModule', {value: true});
Object.keys(n).forEach(function (k) {
var d = Object.getOwnPropertyDescriptor(n, k);
Object.defineProperty(a, k, d.get ? d : {
enumerable: true,
get: function () {
return n[k];
}
});
});
return a;
}
var src = {};
var cutos = {};
// Unique ID creation requires a high quality random # generator. In the browser we therefore
// require the crypto API and do not support built-in fallback to lower quality random number
// generators (like Math.random()).
let getRandomValues;
const rnds8 = new Uint8Array(16);
function rng() {
// lazy load so that environments that need to polyfill have a chance to do so
if (!getRandomValues) {
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
if (!getRandomValues) {
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
}
}
return getRandomValues(rnds8);
}
var REGEX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
function validate(uuid) {
return typeof uuid === 'string' && REGEX.test(uuid);
}
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
const byteToHex = [];
for (let i = 0; i < 256; ++i) {
byteToHex.push((i + 0x100).toString(16).slice(1));
}
function unsafeStringify(arr, offset = 0) {
// Note: Be careful editing this code! It's been tuned for performance
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
}
function stringify(arr, offset = 0) {
const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one
// of the following:
// - One or more input array values don't map to a hex octet (leading to
// "undefined" in the uuid)
// - Invalid input values for the RFC `version` or `variant` fields
if (!validate(uuid)) {
throw TypeError('Stringified UUID is invalid');
}
return uuid;
}
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html
let _nodeId;
let _clockseq; // Previous uuid creation time
let _lastMSecs = 0;
let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details
function v1(options, buf, offset) {
let i = buf && offset || 0;
const b = buf || new Array(16);
options = options || {};
let node = options.node || _nodeId;
let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not
// specified. We do this lazily to minimize issues related to insufficient
// system entropy. See #189
if (node == null || clockseq == null) {
const seedBytes = options.random || (options.rng || rng)();
if (node == null) {
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];
}
if (clockseq == null) {
// Per 4.2.2, randomize (14 bit) clockseq
clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
}
} // UUID timestamps are 100 nano-second units since the Gregorian epoch,
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock
// cycle to simulate higher resolution clock
let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs)
const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression
if (dt < 0 && options.clockseq === undefined) {
clockseq = clockseq + 1 & 0x3fff;
} // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
// time interval
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
nsecs = 0;
} // Per 4.2.1.2 Throw error if too many uuids are requested
if (nsecs >= 10000) {
throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");
}
_lastMSecs = msecs;
_lastNSecs = nsecs;
_clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
msecs += 12219292800000; // `time_low`
const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
b[i++] = tl >>> 24 & 0xff;
b[i++] = tl >>> 16 & 0xff;
b[i++] = tl >>> 8 & 0xff;
b[i++] = tl & 0xff; // `time_mid`
const tmh = msecs / 0x100000000 * 10000 & 0xfffffff;
b[i++] = tmh >>> 8 & 0xff;
b[i++] = tmh & 0xff; // `time_high_and_version`
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low`
b[i++] = clockseq & 0xff; // `node`
for (let n = 0; n < 6; ++n) {
b[i + n] = node[n];
}
return buf || unsafeStringify(b);
}
function parse(uuid) {
if (!validate(uuid)) {
throw TypeError('Invalid UUID');
}
let v;
const arr = new Uint8Array(16); // Parse ########-....-....-....-............
arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24;
arr[1] = v >>> 16 & 0xff;
arr[2] = v >>> 8 & 0xff;
arr[3] = v & 0xff; // Parse ........-####-....-....-............
arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8;
arr[5] = v & 0xff; // Parse ........-....-####-....-............
arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8;
arr[7] = v & 0xff; // Parse ........-....-....-####-............
arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8;
arr[9] = v & 0xff; // Parse ........-....-....-....-############
// (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes)
arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff;
arr[11] = v / 0x100000000 & 0xff;
arr[12] = v >>> 24 & 0xff;
arr[13] = v >>> 16 & 0xff;
arr[14] = v >>> 8 & 0xff;
arr[15] = v & 0xff;
return arr;
}
function stringToBytes(str) {
str = unescape(encodeURIComponent(str)); // UTF8 escape
const bytes = [];
for (let i = 0; i < str.length; ++i) {
bytes.push(str.charCodeAt(i));
}
return bytes;
}
const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
function v35(name, version, hashfunc) {
function generateUUID(value, namespace, buf, offset) {
var _namespace;
if (typeof value === 'string') {
value = stringToBytes(value);
}
if (typeof namespace === 'string') {
namespace = parse(namespace);
}
if (((_namespace = namespace) === null || _namespace === void 0 ? void 0 : _namespace.length) !== 16) {
throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)');
} // Compute hash of namespace and value, Per 4.3
// Future: Use spread syntax when supported on all platforms, e.g. `bytes =
// hashfunc([...namespace, ... value])`
let bytes = new Uint8Array(16 + value.length);
bytes.set(namespace);
bytes.set(value, namespace.length);
bytes = hashfunc(bytes);
bytes[6] = bytes[6] & 0x0f | version;
bytes[8] = bytes[8] & 0x3f | 0x80;
if (buf) {
offset = offset || 0;
for (let i = 0; i < 16; ++i) {
buf[offset + i] = bytes[i];
}
return buf;
}
return unsafeStringify(bytes);
} // Function#name is not settable on some platforms (#270)
try {
generateUUID.name = name; // eslint-disable-next-line no-empty
} catch (err) {} // For CommonJS default export support
generateUUID.DNS = DNS;
generateUUID.URL = URL;
return generateUUID;
}
/*
* Browser-compatible JavaScript MD5
*
* Modification of JavaScript MD5
* https://github.com/blueimp/JavaScript-MD5
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* https://opensource.org/licenses/MIT
*
* Based on
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
function md5(bytes) {
if (typeof bytes === 'string') {
const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
bytes = new Uint8Array(msg.length);
for (let i = 0; i < msg.length; ++i) {
bytes[i] = msg.charCodeAt(i);
}
}
return md5ToHexEncodedArray(wordsToMd5(bytesToWords(bytes), bytes.length * 8));
}
/*
* Convert an array of little-endian words to an array of bytes
*/
function md5ToHexEncodedArray(input) {
const output = [];
const length32 = input.length * 32;
const hexTab = '0123456789abcdef';
for (let i = 0; i < length32; i += 8) {
const x = input[i >> 5] >>> i % 32 & 0xff;
const hex = parseInt(hexTab.charAt(x >>> 4 & 0x0f) + hexTab.charAt(x & 0x0f), 16);
output.push(hex);
}
return output;
}
/**
* Calculate output length with padding and bit length
*/
function getOutputLength(inputLength8) {
return (inputLength8 + 64 >>> 9 << 4) + 14 + 1;
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function wordsToMd5(x, len) {
/* append padding */
x[len >> 5] |= 0x80 << len % 32;
x[getOutputLength(len) - 1] = len;
let a = 1732584193;
let b = -271733879;
let c = -1732584194;
let d = 271733878;
for (let i = 0; i < x.length; i += 16) {
const olda = a;
const oldb = b;
const oldc = c;
const oldd = d;
a = md5ff(a, b, c, d, x[i], 7, -680876936);
d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
b = md5gg(b, c, d, a, x[i], 20, -373897302);
a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
d = md5hh(d, a, b, c, x[i], 11, -358537222);
c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
a = md5ii(a, b, c, d, x[i], 6, -198630844);
d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
a = safeAdd(a, olda);
b = safeAdd(b, oldb);
c = safeAdd(c, oldc);
d = safeAdd(d, oldd);
}
return [a, b, c, d];
}
/*
* Convert an array bytes to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function bytesToWords(input) {
if (input.length === 0) {
return [];
}
const length8 = input.length * 8;
const output = new Uint32Array(getOutputLength(length8));
for (let i = 0; i < length8; i += 8) {
output[i >> 5] |= (input[i / 8] & 0xff) << i % 32;
}
return output;
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safeAdd(x, y) {
const lsw = (x & 0xffff) + (y & 0xffff);
const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return msw << 16 | lsw & 0xffff;
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bitRotateLeft(num, cnt) {
return num << cnt | num >>> 32 - cnt;
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5cmn(q, a, b, x, s, t) {
return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
}
function md5ff(a, b, c, d, x, s, t) {
return md5cmn(b & c | ~b & d, a, b, x, s, t);
}
function md5gg(a, b, c, d, x, s, t) {
return md5cmn(b & d | c & ~d, a, b, x, s, t);
}
function md5hh(a, b, c, d, x, s, t) {
return md5cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5ii(a, b, c, d, x, s, t) {
return md5cmn(c ^ (b | ~d), a, b, x, s, t);
}
const v3 = v35('v3', 0x30, md5);
var v3$1 = v3;
const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
var native = {
randomUUID
};
function v4(options, buf, offset) {
if (native.randomUUID && !buf && !options) {
return native.randomUUID();
}
options = options || {};
const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = rnds[6] & 0x0f | 0x40;
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
if (buf) {
offset = offset || 0;
for (let i = 0; i < 16; ++i) {
buf[offset + i] = rnds[i];
}
return buf;
}
return unsafeStringify(rnds);
}
// Adapted from Chris Veness' SHA1 code at
// http://www.movable-type.co.uk/scripts/sha1.html
function f(s, x, y, z) {
switch (s) {
case 0:
return x & y ^ ~x & z;
case 1:
return x ^ y ^ z;
case 2:
return x & y ^ x & z ^ y & z;
case 3:
return x ^ y ^ z;
}
}
function ROTL(x, n) {
return x << n | x >>> 32 - n;
}
function sha1(bytes) {
const K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
const H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
if (typeof bytes === 'string') {
const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
bytes = [];
for (let i = 0; i < msg.length; ++i) {
bytes.push(msg.charCodeAt(i));
}
} else if (!Array.isArray(bytes)) {
// Convert Array-like to Array
bytes = Array.prototype.slice.call(bytes);
}
bytes.push(0x80);
const l = bytes.length / 4 + 2;
const N = Math.ceil(l / 16);
const M = new Array(N);
for (let i = 0; i < N; ++i) {
const arr = new Uint32Array(16);
for (let j = 0; j < 16; ++j) {
arr[j] = bytes[i * 64 + j * 4] << 24 | bytes[i * 64 + j * 4 + 1] << 16 | bytes[i * 64 + j * 4 + 2] << 8 | bytes[i * 64 + j * 4 + 3];
}
M[i] = arr;
}
M[N - 1][14] = (bytes.length - 1) * 8 / Math.pow(2, 32);
M[N - 1][14] = Math.floor(M[N - 1][14]);
M[N - 1][15] = (bytes.length - 1) * 8 & 0xffffffff;
for (let i = 0; i < N; ++i) {
const W = new Uint32Array(80);
for (let t = 0; t < 16; ++t) {
W[t] = M[i][t];
}
for (let t = 16; t < 80; ++t) {
W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
}
let a = H[0];
let b = H[1];
let c = H[2];
let d = H[3];
let e = H[4];
for (let t = 0; t < 80; ++t) {
const s = Math.floor(t / 20);
const T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t] >>> 0;
e = d;
d = c;
c = ROTL(b, 30) >>> 0;
b = a;
a = T;
}
H[0] = H[0] + a >>> 0;
H[1] = H[1] + b >>> 0;
H[2] = H[2] + c >>> 0;
H[3] = H[3] + d >>> 0;
H[4] = H[4] + e >>> 0;
}
return [H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff, H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff, H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff, H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff, H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff];
}
const v5 = v35('v5', 0x50, sha1);
var v5$1 = v5;
var nil = '00000000-0000-0000-0000-000000000000';
function version$1(uuid) {
if (!validate(uuid)) {
throw TypeError('Invalid UUID');
}
return parseInt(uuid.slice(14, 15), 16);
}
var esmBrowser = /*#__PURE__*/Object.freeze({
__proto__: null,
NIL: nil,
parse: parse,
stringify: stringify,
v1: v1,
v3: v3$1,
v4: v4,
v5: v5$1,
validate: validate,
version: version$1
});
var require$$0 = /*@__PURE__*/getAugmentedNamespace(esmBrowser);
/**
* Copyright (C) 2010-2023 - SipTimes Technologies Corporation - All rights reserved.
*/
const CORE = Object.freeze({ // core level api
PLATFORM: 'core-platform',
CONFIG: 'core-config',
BOX_INFO: 'core-box-info',
SIGN_INFO: 'core-sign-info',
DEVICE_INFO: 'core-device-info',
SIGN_GROUP_INFO: 'core-sign-group-info',
SHELL: 'core-shell',
DATABASE: 'core-database',
GET_VOLUME: 'core-get-volume',
SET_VOLUME: 'core-set-volume',
SET_HTTP_PROXY: 'core-set-http-proxy'
});
const CORE_NORESP = Object.freeze({ // core level api with no response
IPC: 'core-ipc',
HEARTBEAT_PING: 'core-heartbeat-ping',
HEARTBEAT_REGISTER: 'core-heartbeat-register',
HEARTBEAT_UNREGISTER: 'core-heartbeat-unregister',
LOGGER: 'core-logger'
});
const CORE_APP = Object.freeze({ // application level api, notification from core
NOTIFICATION: 'core-notification', HEARTBEAT_LISTENER: 'core-heartbeat-listener'
});
const DEVICE = Object.freeze({ // core level api
CHANNEL: 'device-channel',
DEFAULT: 'device-default',
ID_CARD_READER: 'device-id-card-reader',
NFC: 'device-nfc',
FINGERPRINT: 'device-fingerprint',
QR_CODE_SCANNER: 'device-qr-code-scanner',
PRINTER: 'device-printer',
});
const HEARTBEAT_STATUS = Object.freeze({
REGISTER: "register", ALIVE: "alive", ERROR: 'error', NOT_FOUND: 'not-found', SUCCESS: 'success'
});
const cutosAPI$2 = {
version: '3.0.0', CORE, CORE_NORESP, CORE_APP, DEVICE, HEARTBEAT_STATUS
};
var cutosApi = cutosAPI$2;
var name = "@cutos/core";
var version = "3.4.0";
var description = "The CUTOS (CUT Operating System) Core API is a JavaScript library that provides essential functionalities for LWA (Local Web Application) edge computing and communication in the CUTOS ecosystem. ";
var main = "dist/cutos.cjs.js";
var module = "dist/cutos.esm.js";
var scripts = {
"build:rollup": "rollup -c rollup.config.cjs"
};
var keywords = [
"CUTOS",
"core",
"database",
"IPC",
"notification",
"logging",
"device&driver"
];
var author = "SipTimes";
var dependencies = {
mqtt: "^5.3.6"
};
var devDependencies = {
"@rollup/plugin-commonjs": "25.0.7",
"@rollup/plugin-json": "6.1.0",
"@rollup/plugin-node-resolve": "15.2.3",
rollup: "4.9.4",
uuid: "9.0.1"
};
var files = [
"dist/cutos.cjs.js",
"dist/cutos.esm.js",
"package.json"
];
var require$$3 = {
name: name,
version: version,
description: description,
main: main,
module: module,
scripts: scripts,
keywords: keywords,
author: author,
dependencies: dependencies,
devDependencies: devDependencies,
files: files
};
/**
* Copyright (C) 2010-2024 - SipTimes Technologies Corporation - All rights reserved.
*/
const {v4: uuidv4} = require$$0;
const mqtt = require$$1;
const cutosAPI$1 = cutosApi;
const callbackMap = new Map();
const callbackInterval = 500; // 500ms
const callbackTimeout = 5000; // 5s
const listenerMap = new Map();
const ipcListenerMap = new Map();
const packageJson = require$$3;
const ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
let client = null;
let callbackTimer = null;
let coreApiInitialized = false;
let _logger = null;
let _notification = null;
function publishRequest(topic, callback, body, destAddress) {
let request = {};
request.context = {};
request.context.id = uuidv4();
request.context.destAddress = destAddress;
request.body = body;
if (typeof callback === "function") {
let callbackItem = {};
callbackItem.callback = callback;
callbackItem.timestamp = Date.now();
saveCallback(request.context.id, callbackItem);
}
client.publish(topic, JSON.stringify(request));
return true;
}
function publishResponse(topic, request, result) {
if (!request.context || !request.context.id) {
return false;
}
let response = {};
response.id = request.context.id;
response.result = result;
client.publish(topic + '-callback', JSON.stringify(response));
return true;
}
function saveCallback(id, item) {
callbackMap.set(id, item);
if (callbackTimer) {
return;
}
// process timeout callback
callbackTimer = setInterval(() => {
let currentTimestamp = new Date().getTime();
callbackMap.forEach((callbackItem, id) => {
if (currentTimestamp - callbackItem.timestamp > callbackTimeout) {
console.warn("callback is timeout");
callbackMap.delete(id);
}
});
}, callbackInterval);
}
function doCallback(id, body, err) {
if (!callbackMap.has(id)) {
return false;
}
try {
if (err) {
callbackMap.get(id).callback(null, new CutosError('CUTOS CORE error', err));
} else {
callbackMap.get(id).callback(body);
}
} catch (e) {
console.warn(e.message);
}
callbackMap.delete(id);
return true;
}
/**
* @Database
* The basic table structure of CUTOS database is in Key-Value format, and Value can be any json object.
*/
class Database {
KEY_TYPE_TEXT = "TEXT";
KEY_TYPE_INTEGER = "INTEGER";
/**
* The constructor of Database
* @param {String} [db] - name of database, can be null
*/
constructor(db) {
this.db = db;
}
/**
* Connect to database
* @param {Function} callback
*/
connect(callback) {
let body = {
cmd: "db.connect", db: this.db
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* Run sql
* @param {String} sql - execute sql statement
* @param {Function} callback
*/
run(sql, callback) {
let body = {
db: this.db, cmd: "db.run", sql: sql
};
return publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
setupMirror(gwIPC, lwaName, confirm = false) {
this.mirror = {gwIPC, lwaName, confirm};
}
}
Database.Table = class {
/**
* @constructor The constructor of Table
* @param {String} name - name of table, can not be null
* @param {Object} database - database object, can not be null
*/
constructor(name, database) {
this.name = name;
this.database = database;
this.db = database.db;
if (!this.name || !this.database) {
throw new Error("name or database cannot be empty.");
}
}
/**
* Create a Table
* @param {Object} [opts]
* @param {Function} callback
*/
create(opts, callback) {
if (typeof opts === "function") {
callback = opts;
opts = {};
}
if (!opts) {
opts = {};
}
opts.keyName = opts.keyName ? opts.keyName : 'id';
opts.keyType = opts.keyType ? opts.keyType : 'INTEGER';
if (opts.keyType !== 'INTEGER' && opts.keyType !== 'TEXT') {
throw new Error("keyType MUST be INTEGER or TEXT");
}
this.opts = opts;
let body = {
db: this.db, cmd: "db.table.create", name: this.name,
retentionTime: opts.retentionTime,
keyType: opts.keyType,
keyName: opts.keyName
};
this.publishRequestMirror(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* Insert data
* @param {Object} value
* @param {Object} [opts]
* @param {Function} callback
*/
insert(value, opts, callback) {
if (typeof opts === "function") {
callback = opts;
opts = {};
}
let body = {
db: this.db, cmd: "db.table.insert", name: this.name, value: value, tid: opts?.tid
};
this.publishRequestMirror(cutosAPI$1.CORE.DATABASE, callback, body);
}
insertById(id, value, opts, callback) {
if (typeof opts === "function") {
callback = opts;
opts = {};
}
let body = {
db: this.db, cmd: "db.table.insertById", name: this.name, id: id, value: value, tid: opts?.tid
};
this.publishRequestMirror(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* Insert data by key
* @param {String} key
* @param {Object} value
* @param {Object} [opts] - opts.tid - if exist it contains tid
* @param {Function} callback
*/
insertByKey(key, value, opts, callback) {
if (typeof opts === "function") {
callback = opts;
opts = {};
}
let body = {
db: this.db, cmd: "db.table.insertByKey", name: this.name, key: key, value: value, tid: opts?.tid
};
this.publishRequestMirror(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* Update data
* @param {Number} id
* @param {Object} value
* @param {Function} callback
*/
update(id, value, callback) {
let body = {
db: this.db, cmd: "db.table.update", name: this.name, id: id, value: value
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
updateByKey(key, value, callback) {
let body = {
db: this.db, cmd: "db.table.updateByKey", name: this.name, key: key, value: value
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* delete data
* @param {Number} id
* @param {Function} callback
*/
delete(id, callback) {
let body = {
db: this.db, cmd: "db.table.delete", name: this.name, id: id
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* query data
* @param {Number} id
* @param {Function} callback
*/
query(id, callback) {
let body = {
db: this.db, cmd: "db.table.query", name: this.name, id: id
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* query data by key
* @param {String} key
* @param {Function} callback
*/
queryByKey(key, callback) {
let body = {
db: this.db, cmd: "db.table.queryByKey", name: this.name, key: key
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* query data by tid
* @param {Number} tid
* @param {Function} callback
*/
queryByTid(tid, callback) {
let body = {
db: this.db, cmd: "db.table.queryByTid", name: this.name, tid: tid
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* query unsynced data by tid
* @param {Number} tid
* @param {Function} callback
*/
queryUnsynced(opts, callback) {
if (typeof opts === "function") {
callback = opts;
opts = {limit: 100};
}
if (!opts) opts = {};
if (opts.limit <= 0) opts.limit = 100;
let body = {
db: this.db, cmd: "db.table.queryUnsynced", name: this.name, limit: opts.limit
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* query all data
* @param {Function} callback
*/
queryAll(callback) {
let body = {
db: this.db, cmd: "db.table.queryAll", name: this.name
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
/**
* sync data
* @param {Number} id
* @param {Function} callback
*/
sync(id, callback) {
let body = {
db: this.db, cmd: "db.table.sync", name: this.name, id: id
};
publishRequest(cutosAPI$1.CORE.DATABASE, callback, body);
}
publishRequestMirror(topic, callback, body) {
let mirror = this.database.mirror;
let cb = callback;
if (mirror && mirror.gwIPC) { // mirror enabled
cb = (dbResult) => {
let confirmCallback = !mirror.confirm ? null : (gwResult) => {
if (gwResult.status === "success") {
this.sync(dbResult.row);
}
};
if (dbResult.status === true) {
switch (body.cmd) {
case "db.table.create":
break;
case "db.table.insert":
body.id = dbResult.msg.row;
body.timestamp = dbResult.msg.timestamp;
break;
case "db.table.insertById":
case "db.table.insertByKey":
body.timestamp = dbResult.msg.timestamp;
break;
}
mirror.gwIPC.mirror(body, confirmCallback, {lwaName: mirror.lwaName});
}
callback && callback(dbResult);
};
}
return publishRequest(topic, cb, body);
}
};
class Logger {
/**
* The constructor of logger
*/
constructor() {
}
/**
* Information
* @param {String} remark
* @param {String} content
* @param {String} type
*/
info(remark, content, type = "LWA") {
let body = {
type: type, level: "info", remark: remark, content: content
};
return publishRequest(cutosAPI$1.CORE_NORESP.LOGGER, null, body);
}
/**
* Warning
* @param {String} remark
* @param {String} content
* @param {String} type
*/
warning(remark, content, type = "LWA") {
let body = {
type: type, level: "warning", remark: remark, content: content
};
return publishRequest(cutosAPI$1.CORE_NORESP.LOGGER, null, body);
}
/**
* Error
* @param {String} remark
* @param {String} content
* @param {String} type
*/
error(remark, content, type = "LWA") {
let body = {
type: type, level: "error", remark: remark, content: content
};
return publishRequest(cutosAPI$1.CORE_NORESP.LOGGER, null, body);
}
/**
* Debug
* @param {String} remark
* @param {String} content
* @param {String} type
*/
debug(remark, content, type = "LWA") {
let body = {
type: type, level: "debug", remark: remark, content: content
};
return publishRequest(cutosAPI$1.CORE_NORESP.LOGGER, null, body);
}
}
class IPC {
constructor(destAddress) {
if (destAddress === undefined || destAddress === null || destAddress.length === 0 || destAddress === 'localhost' || destAddress === '127.0.0.1') {
this.destAddress = undefined;
} else if (destAddress.match(ipformat)) {
this.destAddress = destAddress;
} else {
throw new TypeError(destAddress + " is NOT an ip address.");
}
}
/**
* send message to channel
* @param channel
* @param args
* @param callback (result) response from receiver
* @returns {boolean}
*/
sendTo(channel, args, callback = null) {
let body = {};
body.channel = channel;
body.args = args;
let topic = cutosAPI$1.CORE_NORESP.IPC + (this.destAddress ? "" : "-endpoint");
return publishRequest(topic, callback, body, this.destAddress);
}
/**
* internal function, used to response sender with the result
* @param context contain sender information
* @param result
*/
_sendResponse(context, result) {
let response = {};
response.context = {};
response.context.destAddress = context.sourceAddress;
response.id = context.id;
response.result = result;
let topic = cutosAPI$1.CORE_NORESP.IPC + (this.destAddress ? "" : "-endpoint");
client.publish(topic, JSON.stringify(response));
}
/**
* listening channel
* @param channel
* @param listener (args, respond(result)) args is the data from sender, respond is used to send data back to sender's callback
*/
on(channel, listener) {
if (listener) {
if (!ipcListenerMap.has(channel)) {
ipcListenerMap.set(channel, new Map());
}
if (!ipcListenerMap.get(channel).has(listener)) {
let innerListener = (args, context) => {
listener(args, (result) => {
this._sendResponse(context, result);
});
};
ipcListenerMap.get(channel).set(listener, innerListener);
}
}
}
/**
* unsubscribe from channel, if listener is null, all listeners will remove
* @param channel
* @param listener
*/
removeListener(channel, listener = null) {
if (!ipcListenerMap.has(channel)) {
return;
}
if (!listener) {
ipcListenerMap.delete(channel);
} else {
ipcListenerMap.get(channel).delete(listener);
}
}
}
class Notification {
/**
* The constructor of Notification
*/
constructor() {
}
/**
* Register notification listener function
* @param {Function} listener - listener function (data)
*/
register(listener) {
listenerMap.set(cutosAPI$1.CORE_APP.NOTIFICATION, listener);
}
/**
* Unregister, used to cancel the registration of notification
*/
unregister() {
listenerMap.delete(cutosAPI$1.CORE_APP.NOTIFICATION);
}
/**
* Cancel registration, used to cancel the registration of notification
* @param {String} event - event name
* @param {String} msg - event content
*/
emit(event, msg) {
client.publish(cutosAPI$1.CORE_APP.NOTIFICATION, JSON.stringify({event: event, msg: msg}));
return true;
}
}
class Heartbeat {
STATUS = cutosAPI$1.HEARTBEAT_STATUS;
constructor(pinger, counter) {
this.registered = false;
this.request = {};
this.request.counter = counter;
this.request.pinger = pinger;
this.request.subscriber = cutosAPI$1.CORE_NORESP.HEARTBEAT_PING + '-' + pinger;
}
register() {
this.request.msg = {};
this.request.msg.status = this.STATUS.REGISTER;
this.request.msg.info = `Start to monitor ${this.request.pinger}.`;
client.publish(cutosAPI$1.CORE_NORESP.HEARTBEAT_REGISTER, JSON.stringify(this.request));
this.registered = true;
}
ping(status, info = {}) {
if (!this.registered) {
throw ("The heartbeat is NOT registered!")
}
this.request.msg = {};
this.request.msg.status = status;
this.request.msg.info = info;
client.publish(cutosAPI$1.CORE_NORESP.HEARTBEAT_PING, JSON.stringify(this.request));
}
}
class Device {
/**
* The constructor of Device
* @param name
* @param type
*/
constructor(name = 'default-device-name', type = cutosAPI$1.DEVICE.DEFAULT) {
this.name = name;
this.type = type;
this.topicData = cutosAPI$1.DEVICE.CHANNEL + '-' + type + '-data';
this.topicResponse = cutosAPI$1.DEVICE.CHANNEL + '-' + type + '-response';
this.topicCommand = cutosAPI$1.DEVICE.CHANNEL + '-' + type + '-command';
this.data = {};
if (Device.objectMap === undefined) {
Device.objectMap = new Map();
}
Device.objectMap.set(this.type, this);
if (Device.heartbeatListener === undefined) {
Device.heartbeatListener = function (msg) {
for (const [key, obj] of Device.objectMap) {
if (obj.statusListener !== undefined) {
if (obj.type === "default-device" || obj.type === msg.pinger) {
obj.statusListener(msg);
obj.msg = msg;
}
}
}
//console.debug(JSON.stringify(msg));
};
listenerMap.set(cutosAPI$1.CORE_APP.HEARTBEAT_LISTENER, Device.heartbeatListener);
}
// subscribe command callback
client.subscribe(this.topicCommand + '-callback');
}
/**
* Device initialize
* @param callback(result, error)
* @param opts
*/
init(opts, callback) {
if (typeof opts === "function") {
callback = opts;
opts = null;
}
let command = {};
command.cmd = "init";
command.args = {name: this.name, type: this.type, opts};
command.topicResponse = this.topicResponse;
let defaultTopic = cutosAPI$1.DEVICE.CHANNEL + '-' + cutosAPI$1.DEVICE.DEFAULT + '-command';
publishRequest(defaultTopic, null, command);
// subscribe response callback, currently only used for init
client.subscribe(this.topicResponse); // receive response from device
listenerMap.set(this.topicResponse, (result) => {
if (result.status) {
callback && callback(`Driver ${this.type} loaded`);
} else {
callback && callback(null, result.msg);
}
});
}
/**
* Get device status
* @param {Function} listener
*/
onStatus(listener) {
this.statusListener = listener;
}
/**
* Get device status
* @param {Function} listener
*/
getCurrentStatus() {
return this.msg;
}
/**
*
* @param command - command description object {cmd: 'command', args: (''|{}) }
* @param callback - (result) => {}, the result is normal make up of {status: true|false, msg: (''| {})}
*/
sendCommand(command, callback) {
// exam: command = {cmd: "connect", args: ""}
publishRequest(this.topicCommand, callback, command);
}
/**
* Receive data sent by the driver
* @param listener - listener(data)
*/
onData(listener) {
if (!listenerMap.has(this.topicData)) {
client.subscribe(this.topicData); // receive data from device
}
listenerMap.set(this.topicData, (data) => {
this.data = data;
listener(data);
});
}
getCurrentData() {
return this.data;
}
/**
*
* @param callback (result) => {}, the result is normal make up of {status: true|false, msg: (''| {})}
*/
readDeviceInfo(callback) {
let msg = {};
msg.cmd = "read-device-info";
this.sendCommand(msg, callback);
}
}
class Driver {
/**
* The constructor of Driver
* @param name
* @param type
* @param counter
*/
constructor(name = 'default-driver-name', type = cutosAPI$1.DEVICE.DEFAULT, counter = 10) {
this.name = name;
this.type = type;
this.heartbeat = new Heartbeat(type, counter);
this.statusInfo = {};
this.beatInterval = 3000;
this.topicData = cutosAPI$1.DEVICE.CHANNEL + '-' + type + '-data';
this.topicResponse = cutosAPI$1.DEVICE.CHANNEL + '-' + type + '-response';
this.topicCommand = cutosAPI$1.DEVICE.CHANNEL + '-' + type + '-command';
}
startBeat() {
this.heartbeat.register();
let _this = this;
setInterval(function () {
if (_this.statusInfo.status !== undefined && _this.statusInfo.status !== _this.heartbeat.STATUS.REGISTER) {
_this.heartbeat.ping(_this.statusInfo.status, _this.statusInfo.info);
}
}, _this.beatInterval);
}
updateStatusInfo(status = 'default-status', info = 'default-info') {
this.statusInfo.status = status;
this.statusInfo.info = info;
}
/**
* Send data to the device
* @param data
*/
sendData(data) {
client.publish(this.topicData, JSON.stringify(data));
}
sendResponse(data, topic = this.topicResponse) {
client.publish(topic, JSON.stringify(data));
}
/**
* Receive device commands
* @param listener(command, respond(result))
*/
onCommand(listener) {
if (listener) {
let cmdListener = (message) => {
// process command callback
// message.context
// message.context.id
// message.body
listener(message.body, result => {
publishResponse(this.topicCommand, message, result);
});
};
client.subscribe(this.topicCommand); // receive command from app
listenerMap.set(this.topicCommand, cmdListener);
}
}
}
class CutosError {
constructor(name, message) {
this.name = name;
this.message = message;
}
}
const CoreAPI$2 = {
/**
* Initialization of CUTOS core
* @param {string} host CUTOS address.When host is equal to null, it takes the value 'localhost'. During development, it can be changed to the target address (the device address where CUTOS is installed), such as: '192.168.1.11'
* @param {Function} callback callback(result, error)
*/
init(host = 'localhost', callback) {
let brokerUrl;
if (host && host.startsWith('ws://') && host.endsWith(':1883')) {
brokerUrl = host;
} else {
if (!host) {
host = 'localhost';
}
if (host !== 'localhost' && !host.match(ipformat)) {
throw new Error("invalid host address");
}
brokerUrl = `ws://${host}:1883`;
}
if (callback && typeof (callback) !== 'function') {
throw new Error("callback must be a function");
}
client = mqtt.connect(brokerUrl);
client.on('connect', function () {
console.log("CUTOS CORE connected.");
for (let api in cutosAPI$1.CORE) {
client.subscribe(cutosAPI$1.CORE[api] + '-callback');
}
for (let api in cutosAPI$1.CORE_NORESP) {
client.subscribe(cutosAPI$1.CORE_NORESP[api] + '-endpoint');
}
for (let api in cutosAPI$1.CORE_APP) {
client.subscribe(cutosAPI$1.CORE_APP[api]);
}
!coreApiInitialized && callback && callback('CoreAPI init success');
coreApiInitialized = true;
});
client.on('message', function (topic, message, context) {
// message is Buffer
// console.debug(topic.toString() + message.toString());
let _message = JSON.parse(message);
if (topic === cutosAPI$1.CORE_NORESP.IPC + '-endpoint') { // ipc
// process response message
if (_message.id) {
doCallback(_message.id, _message.result);
return
}
let listenerMap = ipcListenerMap.get(_message.body.channel);
if (listenerMap) {
listenerMap.forEach(listener => listener(_message.body.args, _message.context));
}
} else if (topic === cutosAPI$1.CORE_APP.NOTIFICATION || topic === cutosAPI$1.CORE_APP.HEARTBEAT_LISTENER
|| topic.startsWith(cutosAPI$1.DEVICE.CHANNEL) && !topic.endsWith('-callback')) {
let listener = listenerMap.get(topic);
if (listener !== undefined) {
listener(_message);
}
} else { // cutos core api callback
doCallback(_message.id, _message.result, _message.err);
}
});
client.on("close", () => {
console.log("CUTOS CORE closed.");
});
client.on("error", (err) => {
callback && callback(null, new CutosError('CUTOS CORE error', err.message));
console.error("CUTOS CORE error:", err.message);
});
client.stream.on("error", (err) => {
callback && callback(null, new CutosError('CUTOS CORE error', err.message));
console.error("CUTOS CORE error:", err.message);
});
},
connected() {
return !!client && client.connected;
},
/**
* Get platform version information
*/
getVersion() {
return packageJson.version ;
},
/**
* Get platform information
* @param {Function} callback - callback(result)
*/
getPlatform(callback) {
return publishRequest(cutosAPI$1.CORE.PLATFORM, callback);
},
/**
* Get configuration information
* @param {Function} callback - callback(result)
*/
getConfig(callback) {
return publishRequest(cutosAPI$1.CORE.CONFIG, callback);
},
/**
* Get host information
* @param {Function} callback - callback(result)
*/
getBoxInfo(callback) {
return publishRequest(cutosAPI$1.CORE.BOX_INFO, callback);
},
/**
* Get sign information
* @param {Function} callback - callback(result)
*/
getSignInfo(callback) {
return publishRequest(cutosAPI$1.CORE.SIGN_INFO, callback);
},
/**
* Get device information
* @param {Function} callback - callback(result)
*/
getDeviceInfo(callback) {
return publishRequest(cutosAPI$1.CORE.DEVICE_INFO, callback);
},
getSignGroupInfo(callback) {
return publishRequest(cutosAPI$1.CORE.SIGN_GROUP_INFO, callback);
},
/**
* Get IPC instance object
* @param {String} destAddress - optional parameter, target IP address, used for inter-device process communication
*/
getIPC(destAddress) {
return new IPC(destAddress);
},
/**
* Get notification information instance object
*/
getNotification() {
if (!_notification) {
_notification = new Notification();
}
return _notification;
},
/**
* Get the log instance object
*/
getLogger() {
if (!_logger) {
_logger = new Logger();
}
return _logger;
},
/**
* Shell command execution
* @param {String} command - command
* @param {Function} callback - callback(result, error)
*/
shell(command, callback) {
return publishRequest(cutosAPI$1.CO