6 Commits

42 changed files with 1845 additions and 87 deletions

View File

@@ -42,6 +42,8 @@ var Utils_1 = require("./Utils");
var PREFIX = "[CameraRunner]";
var CameraRunner = /** @class */ (function () {
function CameraRunner(Main) {
this.errorTriggerStartupDelay = 10000;
this.bootTime = Date.now();
this.state = 'DISCONNECTED';
this.processStatus = {
state: 'STOPPED',
@@ -92,6 +94,9 @@ var CameraRunner = /** @class */ (function () {
this.error = error;
this.state = state;
this.broadcastState();
if (error != null &&
Date.now() - this.bootTime > this.errorTriggerStartupDelay)
this._Main.Twilio.sendError('CameraRunner', error);
if (state == 'FAILED' || state == 'DISCONNECTED')
console.warn(PREFIX, message !== null && message !== void 0 ? message : error);
else
@@ -175,6 +180,7 @@ var CameraRunner = /** @class */ (function () {
reconnectionDelay: 2000,
});
this.socket.on('connect', function () {
_this._Main.Twilio.resetError('CameraRunner');
_this.setInfo('Connected', null, 'CONNECTED');
_this.startPollClock();
});

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,10 @@ exports.DefaultConfiguration = {
webServer: {
port: 6300,
},
router: {
ip: '',
waitForStartup: true,
},
unity: {
executable: {
path: '',
@@ -25,6 +29,14 @@ exports.DefaultConfiguration = {
},
pollInterval: 5000,
},
twilio: {
accountSid: '',
authToken: '',
fromNumber: '',
toNumbers: [],
aggregateTimeout: 15000,
maxMessagesPerDay: 10,
},
support: {
telephone: '+31613392837',
},

View File

@@ -1 +1 @@
{"version":3,"file":"DefaultConfiguration.js","sourceRoot":"","sources":["../../src/Configuration/DefaultConfiguration.ts"],"names":[],"mappings":";;;AAEa,QAAA,oBAAoB,GAAW;IAC3C,SAAS,EAAE;QACV,IAAI,EAAE,IAAI;KACV;IACD,KAAK,EAAE;QACN,UAAU,EAAE;YACX,IAAI,EAAE,EAAE;YACR,SAAS,EAAE,EAAE;YACb,YAAY,EAAE,IAAI;SAClB;QAED,SAAS,EAAE;YACV,EAAE,EAAE,WAAW;YACf,IAAI,EAAE,IAAI;SACV;QAED,iBAAiB,EAAE,IAAI;QACvB,wBAAwB,EAAE,IAAI;KAC9B;IACD,YAAY,EAAE;QACb,SAAS,EAAE;YACV,EAAE,EAAE,WAAW;YACf,IAAI,EAAE,IAAI;SACV;QAED,YAAY,EAAE,IAAI;KAClB;IACD,OAAO,EAAE;QACR,SAAS,EAAE,cAAc;KACzB;CACD,CAAC"}
{"version":3,"file":"DefaultConfiguration.js","sourceRoot":"","sources":["../../src/Configuration/DefaultConfiguration.ts"],"names":[],"mappings":";;;AAEa,QAAA,oBAAoB,GAAW;IAC3C,SAAS,EAAE;QACV,IAAI,EAAE,IAAI;KACV;IACD,MAAM,EAAE;QACP,EAAE,EAAE,EAAE;QACN,cAAc,EAAE,IAAI;KACpB;IACD,KAAK,EAAE;QACN,UAAU,EAAE;YACX,IAAI,EAAE,EAAE;YACR,SAAS,EAAE,EAAE;YACb,YAAY,EAAE,IAAI;SAClB;QAED,SAAS,EAAE;YACV,EAAE,EAAE,WAAW;YACf,IAAI,EAAE,IAAI;SACV;QAED,iBAAiB,EAAE,IAAI;QACvB,wBAAwB,EAAE,IAAI;KAC9B;IACD,YAAY,EAAE;QACb,SAAS,EAAE;YACV,EAAE,EAAE,WAAW;YACf,IAAI,EAAE,IAAI;SACV;QAED,YAAY,EAAE,IAAI;KAClB;IACD,MAAM,EAAE;QACP,UAAU,EAAE,EAAE;QACd,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE;QACd,SAAS,EAAE,EAAE;QACb,gBAAgB,EAAE,KAAK;QACvB,iBAAiB,EAAE,EAAE;KACrB;IACD,OAAO,EAAE;QACR,SAAS,EAAE,cAAc;KACzB;CACD,CAAC"}

80
dist/Main.js vendored
View File

@@ -44,11 +44,17 @@ var ConfigurationManager_1 = require("./Configuration/ConfigurationManager");
var CameraRunner_1 = require("./CameraRunner");
var UnityRunner_1 = require("./Unity/UnityRunner");
var UnityWebSocket_1 = require("./Unity/UnityWebSocket");
var Twilio_1 = require("./Twilio");
var Utils_1 = require("./Utils");
var ping = require("ping");
var Shutdown_1 = require("./Shutdown");
var PREFIX = '[Main]';
var Main = /** @class */ (function () {
function Main() {
this.dataPath = (0, path_1.join)((0, os_1.homedir)(), 'MorphixProductions', 'NTSHControl');
this.ConfigurationManager = new ConfigurationManager_1.ConfigurationManager(this);
this.WebServer = new WebServer_1.WebServer(this);
this.Twilio = new Twilio_1.TwilioHandler(this);
this.CameraRunner = new CameraRunner_1.CameraRunner(this);
this.UnityRunner = new UnityRunner_1.UnityRunner(this);
this.UnityWebSocket = new UnityWebSocket_1.UnityWebSocket(this);
@@ -62,11 +68,17 @@ var Main = /** @class */ (function () {
case 0: return [4 /*yield*/, this.ConfigurationManager.load()];
case 1:
_b.sent();
return [4 /*yield*/, this.WebServer.listen()];
return [4 /*yield*/, this.waitForRouter()];
case 2:
_b.sent();
return [4 /*yield*/, this.CameraRunner.connect()];
return [4 /*yield*/, this.WebServer.listen()];
case 3:
_b.sent();
return [4 /*yield*/, this.Twilio.load()];
case 4:
_b.sent();
return [4 /*yield*/, this.CameraRunner.connect()];
case 5:
_b.sent();
setTimeout(function () {
_this.UnityRunner.start();
@@ -93,10 +105,12 @@ var Main = /** @class */ (function () {
_this.CameraRunner.sendCommand(doReboot ? 'reboot' : 'restart', function (response) {
if (!response.succeed) {
console.error('Failed to reboot CameraRunner:', response.message);
_this.Twilio.sendError('CameraRunner', "Failed to reboot CameraRunner: ".concat(response.message));
resolve(false);
}
else {
console.log('CameraRunner rebooted successfully.');
_this.Twilio.sendError('CameraRunner', null);
resolve(true);
}
});
@@ -105,9 +119,12 @@ var Main = /** @class */ (function () {
succeed = _a.sent();
if (!succeed)
return [2 /*return*/];
return [4 /*yield*/, (0, Utils_1.delay)(5000)];
case 3:
_a.sent();
console.log('Starting UnityRunner...');
return [4 /*yield*/, this.UnityRunner.start()];
case 3:
case 4:
_a.sent();
console.log('Restart complete.');
return [2 /*return*/];
@@ -115,6 +132,63 @@ var Main = /** @class */ (function () {
});
});
};
Main.prototype.shutdown = function () {
return __awaiter(this, void 0, void 0, function () {
var doShutdown;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
console.log('Stopping UnityRunner...');
return [4 /*yield*/, this.UnityRunner.stop()];
case 1:
_a.sent();
doShutdown = process.argv.includes('--no-shutdown')
? false
: true;
if (doShutdown) {
console.log('Shutting down system...');
(0, Shutdown_1.shutdown)();
}
else {
console.log('Shutdown skipped due to --no-shutdown flag.');
}
process.exit(0);
return [2 /*return*/];
}
});
});
};
Main.prototype.waitForRouter = function () {
var _this = this;
var _a;
if (((_a = this.Config.router) === null || _a === void 0 ? void 0 : _a.waitForStartup) !== true)
return;
return new Promise(function (resolve) {
var check = function () {
console.log(PREFIX, 'Waiting for router...');
ping.sys.probe(_this.Config.router.ip, function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
var alive = _b.alive;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!alive) return [3 /*break*/, 2];
console.log(PREFIX, 'Router is online');
return [4 /*yield*/, (0, Utils_1.delay)(3000)];
case 1:
_c.sent();
return [2 /*return*/, resolve()];
case 2: return [4 /*yield*/, (0, Utils_1.delay)(1000)];
case 3:
_c.sent();
check();
return [2 /*return*/];
}
});
}); });
};
check();
});
};
return Main;
}());
exports.Main = Main;

2
dist/Main.js.map vendored
View File

@@ -1 +1 @@
{"version":3,"file":"Main.js","sourceRoot":"","sources":["../src/Main.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6BAA4B;AAC5B,mDAAkD;AAClD,yBAA6B;AAC7B,6EAG8C;AAC9C,+CAA8C;AAC9C,mDAAkD;AAClD,yDAAwD;AAExD;IAAA;QACC,aAAQ,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,oBAAoB,EAAE,aAAa,CAAC,CAAC;QAEhE,yBAAoB,GAAG,IAAI,2CAAoB,CAAC,IAAI,CAAC,CAAC;QACtD,cAAS,GAAG,IAAI,qBAAS,CAAC,IAAI,CAAC,CAAC;QAEhC,iBAAY,GAAG,IAAI,2BAAY,CAAC,IAAI,CAAC,CAAC;QACtC,gBAAW,GAAG,IAAI,yBAAW,CAAC,IAAI,CAAC,CAAC;QACpC,mBAAc,GAAG,IAAI,+BAAc,CAAC,IAAI,CAAC,CAAC;IA6C3C,CAAC;IAzCM,oBAAK,GAAX;;;;;;4BACC,qBAAM,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,EAAA;;wBAAtC,SAAsC,CAAC;wBACvC,qBAAM,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAA;;wBAA7B,SAA6B,CAAC;wBAE9B,qBAAM,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,EAAA;;wBAAjC,SAAiC,CAAC;wBAElC,UAAU,CAAC;4BACV,KAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;wBAC1B,CAAC,EAAE,MAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,mCAAI,CAAC,CAAC,CAAC;;;;;KACnD;IAEK,sBAAO,GAAb;;;;;;;wBACC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;wBACvC,qBAAM,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAA;;wBAA7B,SAA6B,CAAC;wBAExB,QAAQ,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;wBACvD,OAAO,CAAC,GAAG,CAAC,UAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,qBAAkB,CAAC,CAAC;wBACxD,qBAAM,IAAI,OAAO,CAAC,UAAC,OAAO;gCACzC,KAAI,CAAC,YAAY,CAAC,WAAW,CAC5B,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAC/B,UAAC,QAAgD;oCAChD,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;wCACvB,OAAO,CAAC,KAAK,CACZ,gCAAgC,EAChC,QAAQ,CAAC,OAAO,CAChB,CAAC;wCACF,OAAO,CAAC,KAAK,CAAC,CAAC;oCAChB,CAAC;yCAAM,CAAC;wCACP,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;wCACnD,OAAO,CAAC,IAAI,CAAC,CAAC;oCACf,CAAC;gCACF,CAAC,CACD,CAAC;4BACH,CAAC,CAAC,EAAA;;wBAhBI,OAAO,GAAG,SAgBd;wBACF,IAAI,CAAC,OAAO;4BAAE,sBAAO;wBAErB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;wBACvC,qBAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,EAAA;;wBAA9B,SAA8B,CAAC;wBAE/B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;;;;;KACjC;IACF,WAAC;AAAD,CAAC,AArDD,IAqDC;AArDY,oBAAI"}
{"version":3,"file":"Main.js","sourceRoot":"","sources":["../src/Main.ts"],"names":[],"mappings":"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"}

30
dist/Reboot.js vendored Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.shutdown = shutdown;
var child_process_1 = require("child_process");
function shutdown() {
if (process.platform === 'win32') {
return shutdownWindows();
}
return Promise.resolve({
succeed: false,
message: 'Platform not supported',
});
}
function shutdownWindows() {
return new Promise(function (resolve, reject) {
(0, child_process_1.exec)('shutdown /s /t 5', function (error, stdout, stderr) {
if (error) {
console.error("Error shutting down Windows: ".concat(error.message));
return resolve({ succeed: false, message: error.message });
}
if (stderr) {
console.error("Error shutting down Windows: ".concat(stderr));
return resolve({ succeed: false, message: stderr });
}
console.log("Windows shutdown command executed: ".concat(stdout));
resolve({ succeed: true });
});
});
}
//# sourceMappingURL=Reboot.js.map

1
dist/Reboot.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"Reboot.js","sourceRoot":"","sources":["../src/Reboot.ts"],"names":[],"mappings":";;AAEA,4BASC;AAXD,+CAAqC;AAErC,SAAgB,QAAQ;IACvB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,OAAO,eAAe,EAAE,CAAC;IAC1B,CAAC;IAED,OAAO,OAAO,CAAC,OAAO,CAAC;QACtB,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,wBAAwB;KACjC,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe;IACvB,OAAO,IAAI,OAAO,CACjB,UAAC,OAAO,EAAE,MAAM;QACf,IAAA,oBAAI,EAAC,kBAAkB,EAAE,UAAC,KAAK,EAAE,MAAM,EAAE,MAAM;YAC9C,IAAI,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CACZ,uCAAgC,KAAK,CAAC,OAAO,CAAE,CAC/C,CAAC;gBACF,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5D,CAAC;YACD,IAAI,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC,KAAK,CAAC,uCAAgC,MAAM,CAAE,CAAC,CAAC;gBACxD,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YACrD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,6CAAsC,MAAM,CAAE,CAAC,CAAC;YAC5D,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC,CACD,CAAC;AACH,CAAC"}

30
dist/Shutdown.js vendored Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.shutdown = shutdown;
var child_process_1 = require("child_process");
function shutdown() {
if (process.platform === 'win32') {
return shutdownWindows();
}
return Promise.resolve({
succeed: false,
message: 'Platform not supported',
});
}
function shutdownWindows() {
return new Promise(function (resolve, reject) {
(0, child_process_1.exec)('shutdown /s /t 5', function (error, stdout, stderr) {
if (error) {
console.error("Error shutting down Windows: ".concat(error.message));
return resolve({ succeed: false, message: error.message });
}
if (stderr) {
console.error("Error shutting down Windows: ".concat(stderr));
return resolve({ succeed: false, message: stderr });
}
console.log("Windows shutdown command executed: ".concat(stdout));
resolve({ succeed: true });
});
});
}
//# sourceMappingURL=Shutdown.js.map

1
dist/Shutdown.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"Shutdown.js","sourceRoot":"","sources":["../src/Shutdown.ts"],"names":[],"mappings":";;AAEA,4BASC;AAXD,+CAAqC;AAErC,SAAgB,QAAQ;IACvB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,OAAO,eAAe,EAAE,CAAC;IAC1B,CAAC;IAED,OAAO,OAAO,CAAC,OAAO,CAAC;QACtB,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,wBAAwB;KACjC,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe;IACvB,OAAO,IAAI,OAAO,CACjB,UAAC,OAAO,EAAE,MAAM;QACf,IAAA,oBAAI,EAAC,kBAAkB,EAAE,UAAC,KAAK,EAAE,MAAM,EAAE,MAAM;YAC9C,IAAI,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CACZ,uCAAgC,KAAK,CAAC,OAAO,CAAE,CAC/C,CAAC;gBACF,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5D,CAAC;YACD,IAAI,MAAM,EAAE,CAAC;gBACZ,OAAO,CAAC,KAAK,CAAC,uCAAgC,MAAM,CAAE,CAAC,CAAC;gBACxD,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YACrD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,6CAAsC,MAAM,CAAE,CAAC,CAAC;YAC5D,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACJ,CAAC,CACD,CAAC;AACH,CAAC"}

172
dist/Twilio.js vendored Normal file
View File

@@ -0,0 +1,172 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TwilioHandler = void 0;
var path_1 = require("path");
var fs_extra_1 = require("fs-extra");
var PREFIX = '[Twilio]';
var TwilioHandler = /** @class */ (function () {
function TwilioHandler(Main) {
this.counter = {
date: new Date().toLocaleDateString('nl-NL'),
count: 0,
};
this.lastErrors = new Map();
this.errorLog = [];
this._Main = Main;
}
TwilioHandler.prototype.canSendMessage = function () {
var maxMessages = this._Main.Config.twilio.maxMessagesPerDay;
return this.counter.count < maxMessages;
};
TwilioHandler.prototype.incrementCounter = function () {
return __awaiter(this, void 0, void 0, function () {
var today;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
today = new Date().toLocaleDateString('nl-NL');
if (this.counter.date !== today) {
this.counter.date = today;
this.counter.count = 0;
}
this.counter.count++;
return [4 /*yield*/, (0, fs_extra_1.writeJSON)((0, path_1.join)(this._Main.dataPath, 'twilio.json'), this.counter)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
TwilioHandler.prototype.load = function () {
return __awaiter(this, void 0, void 0, function () {
var twilioConfigPath, twilioConfigExists, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
twilioConfigPath = (0, path_1.join)(this._Main.dataPath, 'twilio.json');
return [4 /*yield*/, (0, fs_extra_1.pathExists)(twilioConfigPath)];
case 1:
twilioConfigExists = _b.sent();
if (!twilioConfigExists) return [3 /*break*/, 3];
_a = this;
return [4 /*yield*/, (0, fs_extra_1.readJSON)(twilioConfigPath)];
case 2:
_a.counter = _b.sent();
_b.label = 3;
case 3:
this.client = require('twilio')(this._Main.Config.twilio.accountSid, this._Main.Config.twilio.authToken);
return [2 /*return*/];
}
});
});
};
TwilioHandler.prototype.resetError = function (category) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (!this.lastErrors.has(category))
return [2 /*return*/];
this.lastErrors.delete(category);
return [2 /*return*/];
});
});
};
TwilioHandler.prototype.sendError = function (category, error) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
if (this.lastErrors.get(category) === error)
return [2 /*return*/];
this.lastErrors.set(category, error);
if (error == null)
return [2 /*return*/];
this.errorLog.push("".concat(category, ": ").concat(error));
clearTimeout(this.errorTimeout);
this.errorTimeout = setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
var errorMessage, promises;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
errorMessage = this.errorLog
.map(function (error) { return "- ".concat(error); })
.join('\n');
this.errorLog = [];
if (!this.canSendMessage())
return [2 /*return*/, console.log(PREFIX, 'Max messages per day reached')];
return [4 /*yield*/, this.incrementCounter()];
case 1:
_a.sent();
console.log(PREFIX, "Sending to Twilio:\n", errorMessage);
promises = this._Main.Config.twilio.toNumbers.map(function (toNumber) { return _this.sendMessage(toNumber, errorMessage); });
return [4 /*yield*/, Promise.all(promises)];
case 2:
_a.sent();
return [2 /*return*/];
}
});
}); }, this._Main.Config.twilio.aggregateTimeout);
return [2 /*return*/];
});
});
};
TwilioHandler.prototype.sendMessage = function (to, message) {
var _this = this;
return;
return new Promise(function (resolve) {
_this.client.messages
.create({
body: message,
from: "".concat(_this._Main.Config.twilio.fromNumber),
to: to,
})
.then(function (message) {
console.log("Twilio message sent with SID: ".concat(message.sid));
resolve(true);
})
.catch(function (error) {
console.error('Error sending Twilio message:', error);
resolve(false);
});
});
};
return TwilioHandler;
}());
exports.TwilioHandler = TwilioHandler;
//# sourceMappingURL=Twilio.js.map

1
dist/Twilio.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"Twilio.js","sourceRoot":"","sources":["../src/Twilio.ts"],"names":[],"mappings":"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"}

View File

@@ -54,6 +54,7 @@ var LOG_OUTPUT = !process.argv.includes('--no-output-log');
var UnityRunner = /** @class */ (function () {
function UnityRunner(Main) {
this.message = 'Awaiting startup delay...';
this.bootTime = Date.now();
this.startTime = null;
this.output = { current: [], last: [] };
this.restartTriggered = false;
@@ -64,13 +65,16 @@ var UnityRunner = /** @class */ (function () {
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var callback = args[0];
if (typeof callback !== 'function')
return;
switch (command) {
case 'restart':
var callback = args[0];
if (typeof callback !== 'function')
return;
callback(this.requestRestart());
break;
return callback(this.requestRestart());
case 'stop':
return callback(this.requestStop());
case 'start':
return callback(this.requestStart());
}
};
UnityRunner.prototype.startStatusClock = function () {
@@ -89,6 +93,24 @@ var UnityRunner = /** @class */ (function () {
this.restart(true);
return { succeed: true };
};
UnityRunner.prototype.requestStop = function () {
if (this.state !== 'RUNNING')
return {
succeed: false,
message: 'Cannot stop when process is not running. It is probably restarting already.',
};
this.stop();
return { succeed: true };
};
UnityRunner.prototype.requestStart = function () {
if (this.state !== 'STOPPED')
return {
succeed: false,
message: 'Cannot start when process is already running.',
};
this.start();
return { succeed: true };
};
UnityRunner.prototype.broadcastState = function () {
this._Main.WebServer.socket.emit('unityRunnerState', this.getStatus());
};
@@ -98,6 +120,8 @@ var UnityRunner = /** @class */ (function () {
this.error = error;
this.state = state;
this.broadcastState();
if (error != null)
this._Main.Twilio.sendError('UnityRunner', error);
this.output.current.push("[".concat(new Date().toLocaleTimeString('nl-NL'), "] [System] [").concat(state, "] ").concat(message !== null && message !== void 0 ? message : error));
if (state == 'PROBLEM' || state == 'STOPPED')
console.warn(PREFIX, message !== null && message !== void 0 ? message : error);
@@ -159,6 +183,7 @@ var UnityRunner = /** @class */ (function () {
if (this.restartTriggered)
return [2 /*return*/];
this.restartTriggered = true;
this._Main.WebServer.Calibration.hasCalibrationImage = false;
clearInterval(this.statusClock);
this.startTime = -1;
this.broadcastState();
@@ -300,6 +325,7 @@ var UnityRunner = /** @class */ (function () {
((_b = _this.process) === null || _b === void 0 ? void 0 : _b.exitCode) != null ||
_this.restartTriggered)
return;
_this._Main.Twilio.resetError('UnityRunner');
_this.setInfo('Running', '', 'RUNNING');
_this._Main.UnityWebSocket.connect();
}, 5000);

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,15 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
@@ -44,6 +55,7 @@ var UnityWebSocket = /** @class */ (function () {
function UnityWebSocket(Main) {
this.state = 'DISCONNECTED';
this.message = 'Waiting for process...';
this.errorTriggerStartupDelay = 1000;
this.parameters = {
timelineWatching: false,
timelineStanding: false,
@@ -53,6 +65,7 @@ var UnityWebSocket = /** @class */ (function () {
zedFPS: '-',
outOfService: null,
sliders: [],
advancedSliders: [],
sensors: [],
};
this.disconnected = false;
@@ -70,6 +83,11 @@ var UnityWebSocket = /** @class */ (function () {
var percentage = args[1];
this.setSliderValue(sliderIndex, percentage);
break;
case 'advancedParameterValue':
var advSliderIndex = args[0];
var advPercentage = args[1];
this.setAdvancedSliderValue(advSliderIndex, advPercentage);
break;
case 'enableOutOfService':
var enableCallback = args[0];
if (typeof enableCallback !== 'function')
@@ -106,6 +124,19 @@ var UnityWebSocket = /** @class */ (function () {
this.parameters.sliders[sliderIndex].outputValue = sliderValue;
this.broadcastState();
};
UnityWebSocket.prototype.setAdvancedSliderValue = function (sliderIndex, sliderValue) {
if (this.socket == null || this.socket.readyState !== ws_1.WebSocket.OPEN)
return;
this.socket.send(JSON.stringify({
type: 'set_advanced_slider_value',
sliderIndex: sliderIndex,
sliderValue: sliderValue,
}));
if (this.parameters.advancedSliders[sliderIndex] == undefined)
return;
this.parameters.advancedSliders[sliderIndex].outputValue = sliderValue;
this.broadcastState();
};
UnityWebSocket.prototype.setOutOfService = function (state) {
if (this.socket == null || this.socket.readyState !== ws_1.WebSocket.OPEN)
return;
@@ -125,6 +156,8 @@ var UnityWebSocket = /** @class */ (function () {
this.error = error;
this.state = state;
this.broadcastState();
if (error != null)
this._Main.Twilio.sendError('UnityWebSocket', error);
if (state == 'FAILED' || state == 'DISCONNECTED')
console.warn(PREFIX, message !== null && message !== void 0 ? message : error);
else
@@ -158,7 +191,19 @@ var UnityWebSocket = /** @class */ (function () {
this.parameters.outOfService =
(_a = message.heartbeat.showOutOfService) !== null && _a !== void 0 ? _a : false;
this.parameters.sensors = message.heartbeat.dataSensors;
this.parameters.sliders = message.heartbeat.dataSliders;
this.parameters.sliders = message.heartbeat.dataSliders.map(function (slider) {
return __assign(__assign({}, slider), { decimalPlaces: (slider.min == 0 || slider.min == -1) &&
slider.max == 1
? 2
: null });
});
this.parameters.advancedSliders =
message.heartbeat.dataAdvancedSliders.map(function (slider) {
return __assign(__assign({}, slider), { decimalPlaces: (slider.min == 0 || slider.min == -1) &&
slider.max == 1
? 2
: null });
});
this.broadcastState();
break;
case 'response_camera_frame':
@@ -238,6 +283,7 @@ var UnityWebSocket = /** @class */ (function () {
});
this.socket.on('open', function () {
_this.startFetchClocks();
_this._Main.Twilio.resetError('UnityWebSocket');
_this.setInfo('Connected', null, 'CONNECTED');
});
this.socket.on('close', function () {

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,40 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
@@ -16,6 +52,7 @@ var http_1 = require("http");
var DashboardRouter_1 = require("./DashboardRouter");
var path_1 = require("path");
var CalibrationRouter_1 = require("./CalibrationRouter");
var Utils_1 = require("../Utils");
var PREFIX = '[WebServer]';
var WebServer = /** @class */ (function () {
function WebServer(Main) {
@@ -46,6 +83,18 @@ var WebServer = /** @class */ (function () {
_this._Main.restart();
callback({ succeed: true });
});
socket.on('shutdownInstallation', function (callback) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, Utils_1.delay)(1000)];
case 1:
_a.sent();
callback({ succeed: true });
this._Main.shutdown();
return [2 /*return*/];
}
});
}); });
socket.on('cameraRunner', function (command) {
var _a;
var args = [];

View File

@@ -1 +1 @@
{"version":3,"file":"WebServer.js","sourceRoot":"","sources":["../../src/WebServer/WebServer.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"WebServer.js","sourceRoot":"","sources":["../../src/WebServer/WebServer.ts"],"names":[],"mappings":"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"}

View File

@@ -45,6 +45,8 @@ var DashboardUnity = /** @class */ (function () {
this.processStatus = document.querySelector('.ntsh_dashboard-unity-processstatus');
this.processInfo = document.querySelector('.ntsh_dashboard-unity-processinfo');
this.restartButton = document.querySelector('.ntsh_dashboard-unity-restart');
this.startButton = document.querySelector('.ntsh_dashboard-unity-start');
this.stopButton = document.querySelector('.ntsh_dashboard-unity-stop');
this.uptimeInfo = document.querySelector('.ntsh_dashboard-unity-uptime');
this.webSocketStatus = document.querySelector('.ntsh_dashboard-unity-websocketstatus');
this.webSocketInfo = document.querySelector('.ntsh_dashboard-unity-websocketinfo');
@@ -60,6 +62,7 @@ var DashboardUnity = /** @class */ (function () {
this.timelineStanding = document.querySelector('.ntsh_dashboard-unity-timeline-standing');
this.timelineProgress = document.querySelector('.ntsh_dashboard-unity-timeline-progress');
this.parametersTable = document.querySelector('.ntsh_dashboard-unity-parameters');
this.advancedParametersTable = document.querySelector('.ntsh_dashboard-unity-advancedparameters');
this.sensorsTable = document.querySelector('.ntsh_dashboard-unity-sensors');
this.errorContainer = document.querySelector('.ntsh_dashboard-unity-error');
this.errorText = document.querySelector('.ntsh_dashboard-unity-errortext');
@@ -72,10 +75,14 @@ var DashboardUnity = /** @class */ (function () {
if (state.state != 'RUNNING') {
state.startTime = -1;
this.restartButton.style.display = 'none';
this.stopButton.style.display = 'none';
}
else {
this.restartButton.style.display = 'flex';
this.stopButton.style.display = 'flex';
}
this.startButton.style.display =
state.state == 'STOPPED' ? 'flex' : 'none';
(0, utils_1.setStatusState)(this.processStatus, {
RUNNING: 'green',
STOPPED: 'gray',
@@ -143,6 +150,7 @@ var DashboardUnity = /** @class */ (function () {
(0, utils_1.setProgressState)(this.timelineProgress, Math.round(state.parameters.timelineProgress * 100), 0, 100, '%');
// ----------- Parameters -----------
this.renderParameterSliders(state.state == 'CONNECTED' ? state.parameters.sliders : []);
this.renderAdvancedParameterSliders(state.state == 'CONNECTED' ? state.parameters.advancedSliders : []);
this.renderParameterSensors(state.state == 'CONNECTED' ? state.parameters.sensors : []);
// ----------- Error -----------
if (((_b = state === null || state === void 0 ? void 0 : state.error) !== null && _b !== void 0 ? _b : '').trim().length > 0)
@@ -223,6 +231,78 @@ var DashboardUnity = /** @class */ (function () {
});
}
};
DashboardUnity.prototype.renderAdvancedParameterSliders = function (sliders) {
var _this = this;
var existingSliders = this.advancedParametersTable.querySelectorAll('.ntsh_dashboard-unity-parameter-row');
if (existingSliders.length !== sliders.length) {
this.advancedParametersTable.innerHTML = '';
if (sliders.length === 0) {
var row = (0, morphux_1.ce)('tr');
var cell = (0, morphux_1.ce)('td');
cell.appendChild((0, morphux_1.ce)('div', ['mux_text', 'ntsh_dashboard-unity-parameters-loading'], null, 'Waiting for Unity...'));
row.appendChild(cell);
this.advancedParametersTable.appendChild(row);
}
else
sliders.forEach(function (slider) {
var _a, _b;
var multiplierFactor = (_a = slider.visualMultiplier) !== null && _a !== void 0 ? _a : 1;
var decimalPlacesFactor = Math.pow(10, ((_b = slider.decimalPlaces) !== null && _b !== void 0 ? _b : 0));
var value = Math.round(slider.outputValue *
multiplierFactor *
decimalPlacesFactor) / decimalPlacesFactor;
var row = (0, morphux_1.ce)('tr', 'ntsh_dashboard-unity-parameter-row');
var nameCell = (0, morphux_1.ce)('td');
nameCell.appendChild((0, morphux_1.ce)('div', 'mux_text', null, slider.sliderName));
row.appendChild(nameCell);
var progressCell = (0, morphux_1.ce)('td', 'no-service');
progressCell.appendChild((0, utils_1.createProgress)(value, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit));
row.appendChild(progressCell);
var sliderCell = (0, morphux_1.ce)('td', 'only-service');
var sliderProgress = (0, utils_1.createProgress)(value, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit);
var sliderValue = sliderProgress.querySelector('.ntsh_progress-value');
sliderValue.classList.add('mux_resizer');
sliderCell.appendChild(sliderProgress);
var resizer = new morphux_1.MorphComponent.Resizer({
existingContainer: sliderValue,
direction: 'right',
relative: true,
min: 0,
max: function () { return sliderProgress.clientWidth; },
});
var lastValue = -1;
resizer.on('resized', function (size) {
var percentage = Math.round((size / sliderProgress.clientWidth) * 100) / 100;
var actualValue = slider.min + percentage * (slider.max - slider.min);
if (actualValue === lastValue)
return;
lastValue = actualValue;
_this._Main.socket.emit('unityWebSocket', 'advancedParameterValue', slider.sliderIndex, actualValue);
(0, utils_1.setProgressState)(sliderProgress, Math.round(actualValue *
multiplierFactor *
decimalPlacesFactor) / decimalPlacesFactor, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit);
});
row.appendChild(sliderCell);
_this.advancedParametersTable.appendChild(row);
});
}
else {
existingSliders.forEach(function (row, index) {
var _a, _b;
var slider = sliders[index];
var multiplierFactor = (_a = slider.visualMultiplier) !== null && _a !== void 0 ? _a : 1;
var decimalPlacesFactor = Math.pow(10, ((_b = slider.decimalPlaces) !== null && _b !== void 0 ? _b : 0));
var value = Math.round(slider.outputValue *
multiplierFactor *
decimalPlacesFactor) / decimalPlacesFactor;
var progressElement = row.querySelector('.no-service .ntsh_progress');
(0, utils_1.setProgressState)(progressElement, value, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit);
var sliderElement = row.querySelector('.only-service .ntsh_progress');
if (sliderElement.querySelector('.mux_resizer-moving') == null)
(0, utils_1.setProgressState)(sliderElement, value, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit);
});
}
};
DashboardUnity.prototype.renderParameterSensors = function (sensors) {
var _this = this;
var existingSensors = this.sensorsTable.querySelectorAll('.ntsh_dashboard-unity-sensor-row');
@@ -282,6 +362,18 @@ var DashboardUnity = /** @class */ (function () {
return [2 /*return*/];
});
}); });
this.startButton.addEventListener('click', function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.executeCommand('start', 'Are you sure you want to start the Unity Runner process?');
return [2 /*return*/];
});
}); });
this.stopButton.addEventListener('click', function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.executeCommand('stop', 'Are you sure you want to stop the Unity Runner process?');
return [2 /*return*/];
});
}); });
this.enableOutOfServiceButton.addEventListener('click', function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.executeCommand('enableOutOfService', 'Are you sure you want to set the installation to "Out of Service"?', 'unityWebSocket');

File diff suppressed because one or more lines are too long

View File

@@ -73,6 +73,18 @@ var MenuBar = /** @class */ (function () {
});
}); },
},
// {
// type: 'icon',
// text: 'Shutdown',
// materialIcon: 'power_settings_new',
// uniqueIdentifier: 'shutdown_installation',
// click: async () => {
// const mobileMenu: HTMLDivElement =
// document.querySelector('.mux_mobilemenu');
// mobileMenu?.click();
// this.shutdownInstallation();
// },
// },
],
right: [
{
@@ -100,6 +112,18 @@ var MenuBar = /** @class */ (function () {
});
}); },
},
// {
// type: 'normal',
// text: 'Shutdown',
// materialIcon: 'power_settings_new',
// uniqueIdentifier: 'shutdown_installation',
// click: async () => {
// const mobileMenu: HTMLDivElement =
// document.querySelector('.mux_mobilemenu');
// mobileMenu?.click();
// this.shutdownInstallation();
// },
// },
{
type: 'normal',
text: 'Dashboard',
@@ -215,6 +239,38 @@ var MenuBar = /** @class */ (function () {
});
});
};
MenuBar.prototype.shutdownInstallation = function () {
return __awaiter(this, void 0, void 0, function () {
var confirmed, shutdownContainer;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, morphux_1.MorphFeature.Confirm({
title: 'Shutdown Installation',
message: 'Are you sure you want to shutdown the installation?',
})];
case 1:
confirmed = _a.sent();
if (!confirmed)
return [2 /*return*/];
morphux_1.MorphFeature.Loader({
active: true,
message: 'Shutting down installation...',
});
shutdownContainer = document.querySelector('.ntsh_shutdown');
this._Main.socket.emit('shutdownInstallation', function (response) {
morphux_1.MorphFeature.Loader({ active: false });
if (!response.succeed)
return morphux_1.MorphFeature.Alert({
title: 'Error',
message: response.message,
});
shutdownContainer.style.display = 'flex';
});
return [2 /*return*/];
}
});
});
};
MenuBar.prototype.toggleServiceMode = function (mode, skipPin) {
return __awaiter(this, void 0, void 0, function () {
var newMode, servicePin;

File diff suppressed because one or more lines are too long

View File

@@ -105,8 +105,15 @@
<td>
<div class="ntsh_buttons">
<div class="ntsh_button mux_text ntsh_dashboard-unity-restart">
Restart Process
Restart
</div>
<div class="ntsh_button mux_text ntsh_dashboard-unity-stop">
Stop
</div>
<div class="ntsh_button mux_text ntsh_dashboard-unity-start">
Start
</div>
</div>
</td>
</tr>
@@ -241,7 +248,7 @@
<div class="ntsh_dashboard-box ntsh_dashboard-unityparameters">
<div class="ntsh_dashboard-box-header mux_header">Parameters</div>
<div class="ntsh_dashboard-box-header mux_header">Audio</div>
<table class="ntsh_vertical ntsh_dashboard-unity-parameters">
<tr>
@@ -252,6 +259,19 @@
</tr>
</table>
</div>
<div class="ntsh_dashboard-box ntsh_dashboard-unityadvancedparameters">
<div class="ntsh_dashboard-box-header mux_header">Parameters</div>
<table class="ntsh_vertical ntsh_dashboard-unity-advancedparameters">
<tr>
<td>
<div class="mux_text ntsh_dashboard-unity-advancedparameters-loading">Waiting for
Unity...
</div>
</td>
</tr>
</table>
</div>
<div class="ntsh_dashboard-box ntsh_dashboard-unitysensors">
<div class="ntsh_dashboard-box-header mux_header">Sensors</div>
@@ -296,6 +316,18 @@
</div>
</div>
</div>
<div class="ntsh_shutdown">
<span class="material-symbols-outlined">
power_settings_new
</span>
<div class="mux_header">
Installation has been shut down
</div>
<div class="mux_text">
You can now safely turn off the power to the device.
</div>
</div>
</div>
</body>

View File

@@ -5297,7 +5297,7 @@
var Index = {};
var name = "morphux";
var version = "2025.9.1";
var version = "2025.11.5";
var description = "Standardized Morphix UX framework.";
var main = "dist/Index.js";
var types = "dist/index.d.ts";
@@ -5347,7 +5347,7 @@
var CE = {};
Object.defineProperty(CE, "__esModule", { value: true });
CE.ce = ce;
CE.ce = void 0;
function ce(tagName, classList, attributes, innerText, innerHTML, style) {
var _a;
var element = document.createElement(tagName);
@@ -5371,6 +5371,7 @@
element.style[key] = style[key];
return element;
}
CE.ce = ce;
var baseComponent = {};
@@ -5471,7 +5472,7 @@
var TextHighlighter = {};
Object.defineProperty(TextHighlighter, "__esModule", { value: true });
TextHighlighter.generateTextHighlights = generateTextHighlights;
TextHighlighter.generateTextHighlights = void 0;
function generateTextHighlights(originalText, additionalClassnames) {
var _a;
if (additionalClassnames === void 0) { additionalClassnames = []; }
@@ -5505,6 +5506,7 @@
}
return div;
}
TextHighlighter.generateTextHighlights = generateTextHighlights;
var Sortable$2 = {exports: {}};
@@ -6880,7 +6882,7 @@
settings.disableInElementsWithTags.map(function (tagname) {
return tagname.toUpperCase();
});
this.binds[query] = { callback: callback, settings: settings };
this.binds[query] = { callback: callback, key: key, settings: settings };
};
return KeyBinderOverwrite;
}());
@@ -6928,7 +6930,7 @@
settings.disableInElementsWithTags.map(function (tagname) {
return tagname.toUpperCase();
});
this.binds[query] = { callback: callback, settings: settings };
this.binds[query] = { callback: callback, key: key, settings: settings };
};
KeyBinderBase.prototype.unbind = function (key, settings) {
if (settings == undefined)
@@ -6971,6 +6973,20 @@
.concat(Object.keys(this.binds))
.flat()));
};
KeyBinderBase.prototype.getBindsOverview = function () {
return Object.values(this.binds).map(function (_a) {
var key = _a.key, settings = _a.settings;
var combo = [];
if (settings === null || settings === void 0 ? void 0 : settings.controlKey)
combo.push('Ctrl');
if (settings === null || settings === void 0 ? void 0 : settings.shiftKey)
combo.push('Shift');
if (settings === null || settings === void 0 ? void 0 : settings.altKey)
combo.push('Alt');
combo.push(key.length < 3 ? key.toUpperCase() : key);
return [combo.join('+'), settings === null || settings === void 0 ? void 0 : settings.name];
});
};
KeyBinderBase.prototype.generateOverwriteId = function () {
while (true) {
var id = (Math.random() + 1).toString(36).substring(7);
@@ -7041,6 +7057,10 @@
var _this = _super.call(this) || this;
_this.open = true;
_this.container = (0, CE_1$7.ce)('div', 'mux_contextmenu');
if ((options === null || options === void 0 ? void 0 : options.width) != undefined) {
_this.container.style.minWidth = "".concat(options.width, "px");
_this.container.style.width = "".concat(options.width, "px");
}
var align = (_a = options === null || options === void 0 ? void 0 : options.align) !== null && _a !== void 0 ? _a : 'center';
if ((options === null || options === void 0 ? void 0 : options.materialIconColor) != undefined)
_this.container.style.setProperty('--mux-contextmenu-iconcolor', options.materialIconColor);
@@ -7220,6 +7240,29 @@
element.setAttribute('href', item.href);
if (item.tooltip != undefined)
element.title = item.tooltip;
if (item.uniqueIdentifier != undefined) {
element.setAttribute('uid', item.uniqueIdentifier);
}
if (item.enabled == false)
element.classList.add('mux_contextmenu-item-disabled');
var textContent = (0, CE_1$7.ce)('div', 'mux_contextmenu-item-content');
element.appendChild(textContent);
var itemContent = (0, CE_1$7.ce)('div', ['mux_text', 'mux_small'], null, (_b = item.text) !== null && _b !== void 0 ? _b : '');
if (item.customFontSize != undefined)
itemContent.style.fontSize = "".concat(item.customFontSize, "px");
textContent.appendChild(itemContent);
if (item.children == undefined && item.shortcut != undefined)
textContent.appendChild((0, CE_1$7.ce)('div', [
'mux_contextmenu-shortcut',
'mux_text',
'mux_tiny',
], null, (_c = item.shortcut) !== null && _c !== void 0 ? _c : ''));
if (item.children != undefined && item.children.length > 0) {
textContent.appendChild((0, CE_1$7.ce)('span', [
'material-symbols-outlined',
'mux_contextmenu-item-arrow',
], null, 'keyboard_arrow_right'));
}
if (item.materialIcon != undefined) {
var materialIcon = (0, CE_1$7.ce)('span', [
'mux_contextmenu-item-materialicon',
@@ -7234,27 +7277,6 @@
element.appendChild((0, CE_1$7.ce)('img', 'mux_contextmenu-item-icon', {
src: item.icon,
}));
if (item.uniqueIdentifier != undefined) {
element.setAttribute('uid', item.uniqueIdentifier);
}
if (item.enabled == false)
element.classList.add('mux_contextmenu-item-disabled');
var itemContent = (0, CE_1$7.ce)('div', ['mux_text', 'mux_small'], null, (_b = item.text) !== null && _b !== void 0 ? _b : '');
if (item.customFontSize != undefined)
itemContent.style.fontSize = "".concat(item.customFontSize, "px");
element.appendChild(itemContent);
if (item.children == undefined && item.shortcut != undefined)
element.appendChild((0, CE_1$7.ce)('div', [
'mux_contextmenu-shortcut',
'mux_text',
'mux_tiny',
], null, (_c = item.shortcut) !== null && _c !== void 0 ? _c : ''));
if (item.children != undefined && item.children.length > 0) {
element.appendChild((0, CE_1$7.ce)('span', [
'material-symbols-outlined',
'mux_contextmenu-item-arrow',
], null, 'keyboard_arrow_right'));
}
element.onmousemove = function () {
if (_this.subContextParent == itemId)
return;
@@ -10694,16 +10716,16 @@
var Utils = {};
Object.defineProperty(Utils, "__esModule", { value: true });
Utils.blackPixel = void 0;
Utils.isMobile = isMobile;
Utils.delay = delay;
Utils.delay = Utils.blackPixel = Utils.isMobile = void 0;
function isMobile() {
return /Android|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test(navigator.userAgent);
}
Utils.isMobile = isMobile;
Utils.blackPixel = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
function delay(duration) {
return new Promise(function (resolve) { return setTimeout(resolve, duration); });
}
Utils.delay = delay;
var hasRequiredComponent_ImageViewer;
@@ -10735,8 +10757,8 @@
});
};
var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
@@ -11842,7 +11864,8 @@
this.container
.querySelectorAll('.mux_menubar-item')
.forEach(function (item) {
if (item.getAttribute('uid') == uniqueIdentifier)
if (item.getAttribute('uid') == uniqueIdentifier &&
uniqueIdentifier != null)
item.classList.add('mux_menubar-item-selected');
else
item.classList.remove('mux_menubar-item-selected');
@@ -13513,8 +13536,8 @@
});
};
var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
@@ -14017,7 +14040,7 @@
if (hasRequiredFeature_Alert) return Feature_Alert;
hasRequiredFeature_Alert = 1;
Object.defineProperty(Feature_Alert, "__esModule", { value: true });
Feature_Alert.FeatureAlert = FeatureAlert;
Feature_Alert.FeatureAlert = void 0;
var Index_1 = requireIndex();
function FeatureAlert(options, callback) {
return new Promise(function (resolve) {
@@ -14038,6 +14061,7 @@
dialog.on('ok', function () { return res(); });
});
}
Feature_Alert.FeatureAlert = FeatureAlert;
return Feature_Alert;
}
@@ -14050,7 +14074,7 @@
if (hasRequiredFeature_Confirm) return Feature_Confirm;
hasRequiredFeature_Confirm = 1;
Object.defineProperty(Feature_Confirm, "__esModule", { value: true });
Feature_Confirm.FeatureConfirm = FeatureConfirm;
Feature_Confirm.FeatureConfirm = void 0;
var Index_1 = requireIndex();
function FeatureConfirm(options, callback) {
return new Promise(function (resolve) {
@@ -14071,6 +14095,7 @@
dialog.on('ok', function () { return res(true); });
});
}
Feature_Confirm.FeatureConfirm = FeatureConfirm;
return Feature_Confirm;
}
@@ -14083,7 +14108,7 @@
if (hasRequiredFeature_Loader) return Feature_Loader;
hasRequiredFeature_Loader = 1;
Object.defineProperty(Feature_Loader, "__esModule", { value: true });
Feature_Loader.FeatureLoader = FeatureLoader;
Feature_Loader.FeatureLoader = void 0;
var Index_1 = requireIndex();
function FeatureLoader(options) {
var _a, _b;
@@ -14095,6 +14120,7 @@
else
removeExisting();
}
Feature_Loader.FeatureLoader = FeatureLoader;
function showLoader(message, progress) {
var loader = document.querySelector('.mux_loader');
if (loader == null) {
@@ -14154,7 +14180,7 @@
if (hasRequiredFeature_Notification) return Feature_Notification;
hasRequiredFeature_Notification = 1;
Object.defineProperty(Feature_Notification, "__esModule", { value: true });
Feature_Notification.FeatureNotification = FeatureNotification;
Feature_Notification.FeatureNotification = void 0;
var Index_1 = requireIndex();
var NotificationHandler = new (/** @class */ (function () {
function class_1() {
@@ -14227,6 +14253,7 @@
return;
return NotificationHandler.append(notification);
}
Feature_Notification.FeatureNotification = FeatureNotification;
return Feature_Notification;
}
@@ -14239,7 +14266,7 @@
if (hasRequiredFeature_Prompt) return Feature_Prompt;
hasRequiredFeature_Prompt = 1;
Object.defineProperty(Feature_Prompt, "__esModule", { value: true });
Feature_Prompt.FeaturePrompt = FeaturePrompt;
Feature_Prompt.FeaturePrompt = void 0;
var Index_1 = requireIndex();
function FeaturePrompt(options, callback) {
return new Promise(function (resolve) {
@@ -14285,6 +14312,7 @@
input.container.focus();
});
}
Feature_Prompt.FeaturePrompt = FeaturePrompt;
return Feature_Prompt;
}
@@ -14320,12 +14348,13 @@
var clone$1 = {};
Object.defineProperty(clone$1, "__esModule", { value: true });
clone$1.clone = clone;
clone$1.clone = void 0;
function clone(object) {
if (typeof object !== 'object')
return object;
return JSON.parse(JSON.stringify(object !== null && object !== void 0 ? object : {}));
}
clone$1.clone = clone;
(function (exports) {
Object.defineProperty(exports, "__esModule", { value: true });
@@ -14450,6 +14479,18 @@
});
}); },
},
// {
// type: 'icon',
// text: 'Shutdown',
// materialIcon: 'power_settings_new',
// uniqueIdentifier: 'shutdown_installation',
// click: async () => {
// const mobileMenu: HTMLDivElement =
// document.querySelector('.mux_mobilemenu');
// mobileMenu?.click();
// this.shutdownInstallation();
// },
// },
],
right: [
{
@@ -14477,6 +14518,18 @@
});
}); },
},
// {
// type: 'normal',
// text: 'Shutdown',
// materialIcon: 'power_settings_new',
// uniqueIdentifier: 'shutdown_installation',
// click: async () => {
// const mobileMenu: HTMLDivElement =
// document.querySelector('.mux_mobilemenu');
// mobileMenu?.click();
// this.shutdownInstallation();
// },
// },
{
type: 'normal',
text: 'Dashboard',
@@ -14592,6 +14645,38 @@
});
});
};
MenuBar.prototype.shutdownInstallation = function () {
return __awaiter$4(this, void 0, void 0, function () {
var confirmed, shutdownContainer;
return __generator$4(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, morphux_1$5.MorphFeature.Confirm({
title: 'Shutdown Installation',
message: 'Are you sure you want to shutdown the installation?',
})];
case 1:
confirmed = _a.sent();
if (!confirmed)
return [2 /*return*/];
morphux_1$5.MorphFeature.Loader({
active: true,
message: 'Shutting down installation...',
});
shutdownContainer = document.querySelector('.ntsh_shutdown');
this._Main.socket.emit('shutdownInstallation', function (response) {
morphux_1$5.MorphFeature.Loader({ active: false });
if (!response.succeed)
return morphux_1$5.MorphFeature.Alert({
title: 'Error',
message: response.message,
});
shutdownContainer.style.display = 'flex';
});
return [2 /*return*/];
}
});
});
};
MenuBar.prototype.toggleServiceMode = function (mode, skipPin) {
return __awaiter$4(this, void 0, void 0, function () {
var newMode, servicePin;
@@ -15641,6 +15726,8 @@
this.processStatus = document.querySelector('.ntsh_dashboard-unity-processstatus');
this.processInfo = document.querySelector('.ntsh_dashboard-unity-processinfo');
this.restartButton = document.querySelector('.ntsh_dashboard-unity-restart');
this.startButton = document.querySelector('.ntsh_dashboard-unity-start');
this.stopButton = document.querySelector('.ntsh_dashboard-unity-stop');
this.uptimeInfo = document.querySelector('.ntsh_dashboard-unity-uptime');
this.webSocketStatus = document.querySelector('.ntsh_dashboard-unity-websocketstatus');
this.webSocketInfo = document.querySelector('.ntsh_dashboard-unity-websocketinfo');
@@ -15656,6 +15743,7 @@
this.timelineStanding = document.querySelector('.ntsh_dashboard-unity-timeline-standing');
this.timelineProgress = document.querySelector('.ntsh_dashboard-unity-timeline-progress');
this.parametersTable = document.querySelector('.ntsh_dashboard-unity-parameters');
this.advancedParametersTable = document.querySelector('.ntsh_dashboard-unity-advancedparameters');
this.sensorsTable = document.querySelector('.ntsh_dashboard-unity-sensors');
this.errorContainer = document.querySelector('.ntsh_dashboard-unity-error');
this.errorText = document.querySelector('.ntsh_dashboard-unity-errortext');
@@ -15668,10 +15756,14 @@
if (state.state != 'RUNNING') {
state.startTime = -1;
this.restartButton.style.display = 'none';
this.stopButton.style.display = 'none';
}
else {
this.restartButton.style.display = 'flex';
this.stopButton.style.display = 'flex';
}
this.startButton.style.display =
state.state == 'STOPPED' ? 'flex' : 'none';
(0, utils_1.setStatusState)(this.processStatus, {
RUNNING: 'green',
STOPPED: 'gray',
@@ -15739,6 +15831,7 @@
(0, utils_1.setProgressState)(this.timelineProgress, Math.round(state.parameters.timelineProgress * 100), 0, 100, '%');
// ----------- Parameters -----------
this.renderParameterSliders(state.state == 'CONNECTED' ? state.parameters.sliders : []);
this.renderAdvancedParameterSliders(state.state == 'CONNECTED' ? state.parameters.advancedSliders : []);
this.renderParameterSensors(state.state == 'CONNECTED' ? state.parameters.sensors : []);
// ----------- Error -----------
if (((_b = state === null || state === void 0 ? void 0 : state.error) !== null && _b !== void 0 ? _b : '').trim().length > 0)
@@ -15819,6 +15912,78 @@
});
}
};
DashboardUnity.prototype.renderAdvancedParameterSliders = function (sliders) {
var _this = this;
var existingSliders = this.advancedParametersTable.querySelectorAll('.ntsh_dashboard-unity-parameter-row');
if (existingSliders.length !== sliders.length) {
this.advancedParametersTable.innerHTML = '';
if (sliders.length === 0) {
var row = (0, morphux_1$1.ce)('tr');
var cell = (0, morphux_1$1.ce)('td');
cell.appendChild((0, morphux_1$1.ce)('div', ['mux_text', 'ntsh_dashboard-unity-parameters-loading'], null, 'Waiting for Unity...'));
row.appendChild(cell);
this.advancedParametersTable.appendChild(row);
}
else
sliders.forEach(function (slider) {
var _a, _b;
var multiplierFactor = (_a = slider.visualMultiplier) !== null && _a !== void 0 ? _a : 1;
var decimalPlacesFactor = Math.pow(10, ((_b = slider.decimalPlaces) !== null && _b !== void 0 ? _b : 0));
var value = Math.round(slider.outputValue *
multiplierFactor *
decimalPlacesFactor) / decimalPlacesFactor;
var row = (0, morphux_1$1.ce)('tr', 'ntsh_dashboard-unity-parameter-row');
var nameCell = (0, morphux_1$1.ce)('td');
nameCell.appendChild((0, morphux_1$1.ce)('div', 'mux_text', null, slider.sliderName));
row.appendChild(nameCell);
var progressCell = (0, morphux_1$1.ce)('td', 'no-service');
progressCell.appendChild((0, utils_1.createProgress)(value, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit));
row.appendChild(progressCell);
var sliderCell = (0, morphux_1$1.ce)('td', 'only-service');
var sliderProgress = (0, utils_1.createProgress)(value, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit);
var sliderValue = sliderProgress.querySelector('.ntsh_progress-value');
sliderValue.classList.add('mux_resizer');
sliderCell.appendChild(sliderProgress);
var resizer = new morphux_1$1.MorphComponent.Resizer({
existingContainer: sliderValue,
direction: 'right',
relative: true,
min: 0,
max: function () { return sliderProgress.clientWidth; },
});
var lastValue = -1;
resizer.on('resized', function (size) {
var percentage = Math.round((size / sliderProgress.clientWidth) * 100) / 100;
var actualValue = slider.min + percentage * (slider.max - slider.min);
if (actualValue === lastValue)
return;
lastValue = actualValue;
_this._Main.socket.emit('unityWebSocket', 'advancedParameterValue', slider.sliderIndex, actualValue);
(0, utils_1.setProgressState)(sliderProgress, Math.round(actualValue *
multiplierFactor *
decimalPlacesFactor) / decimalPlacesFactor, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit);
});
row.appendChild(sliderCell);
_this.advancedParametersTable.appendChild(row);
});
}
else {
existingSliders.forEach(function (row, index) {
var _a, _b;
var slider = sliders[index];
var multiplierFactor = (_a = slider.visualMultiplier) !== null && _a !== void 0 ? _a : 1;
var decimalPlacesFactor = Math.pow(10, ((_b = slider.decimalPlaces) !== null && _b !== void 0 ? _b : 0));
var value = Math.round(slider.outputValue *
multiplierFactor *
decimalPlacesFactor) / decimalPlacesFactor;
var progressElement = row.querySelector('.no-service .ntsh_progress');
(0, utils_1.setProgressState)(progressElement, value, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit);
var sliderElement = row.querySelector('.only-service .ntsh_progress');
if (sliderElement.querySelector('.mux_resizer-moving') == null)
(0, utils_1.setProgressState)(sliderElement, value, slider.min * multiplierFactor, slider.max * multiplierFactor, slider.unit);
});
}
};
DashboardUnity.prototype.renderParameterSensors = function (sensors) {
var _this = this;
var existingSensors = this.sensorsTable.querySelectorAll('.ntsh_dashboard-unity-sensor-row');
@@ -15878,6 +16043,18 @@
return [2 /*return*/];
});
}); });
this.startButton.addEventListener('click', function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.executeCommand('start', 'Are you sure you want to start the Unity Runner process?');
return [2 /*return*/];
});
}); });
this.stopButton.addEventListener('click', function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.executeCommand('stop', 'Are you sure you want to stop the Unity Runner process?');
return [2 /*return*/];
});
}); });
this.enableOutOfServiceButton.addEventListener('click', function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.executeCommand('enableOutOfService', 'Are you sure you want to set the installation to "Out of Service"?', 'unityWebSocket');

File diff suppressed because one or more lines are too long

View File

@@ -38,6 +38,13 @@
}
}
.ntsh_dashboard-unity-advancedparameters {
.ntsh_dashboard-unity-advancedparameters-loading {
text-align: center;
color: #9d9d9d;
}
}
.ntsh_dashboard-unity-sensors {
.ntsh_dashboard-unity-sensors-loading {
text-align: center;

View File

@@ -17,7 +17,7 @@ body {
}
.mux_menubar-locater.mux_left {
.mux_menubar-item:not([uid="restart_installation"]) {
.mux_menubar-item:not([uid="restart_installation"], [uid="shutdown_installation"]) {
display: none;
}
}
@@ -77,4 +77,22 @@ body {
}
}
}
}
.ntsh_shutdown {
position: absolute;
inset: 0px;
z-index: 10000;
background: var(--mux-bg-color);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
gap: var(--mux-edge-offset);
.material-symbols-outlined {
margin-bottom: var(--mux-edge-offset);
font-size: 60px;
color: #919191;
}
}

View File

@@ -802,6 +802,7 @@
.mux_contextmenu {
position: absolute;
z-index: 1101;
min-width: 120px;
border-radius: var(--mux-rounding);
background: var(--mux-panel-color);
box-shadow: var(--mux-panel-shadow);
@@ -810,7 +811,7 @@
transform-origin: 50% 0%;
transform: scale(0);
user-select: none;
--mux-contextmenu-iconcolor: var(--mux-text-color);
--mux-contextmenu-iconcolor: #919191;
}
.mux_contextmenu .mux_contextmenu-item {
@@ -845,25 +846,33 @@
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-icon {
margin-right: var(--mux-edge-offset-tiny);
height: 20px;
margin-right: -2px;
height: 16px;
border-radius: var(--mux-rounding);
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-arrow {
font-size: 16px;
margin-right: -5px;
color: #fff;
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-materialicon {
margin-right: var(--mux-edge-offset);
margin-right: -2px;
color: var(--mux-contextmenu-iconcolor);
font-size: 20px;
font-size: 16px;
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-shortcut {
margin-left: var(--mux-edge-offset);
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-content {
flex-grow: 1;
display: flex;
justify-content: flex-start;
align-items: center;
gap: var(--mux-edge-offset-tiny);
padding-right: calc(var(--mux-edge-offset) * 2);
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-content .mux_contextmenu-item-arrow {
font-size: 16px;
margin-left: calc(var(--mux-edge-offset-tiny) * -1);
color: #c0c0c0;
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-content .mux_contextmenu-shortcut {
color: #b3b3b3;
}
@@ -2400,6 +2409,10 @@ body {
text-align: center;
color: #9d9d9d;
}
.ntsh_dashboard .ntsh_dashboard-unity-advancedparameters .ntsh_dashboard-unity-advancedparameters-loading {
text-align: center;
color: #9d9d9d;
}
.ntsh_dashboard .ntsh_dashboard-unity-sensors .ntsh_dashboard-unity-sensors-loading {
text-align: center;
color: #9d9d9d;
@@ -2573,7 +2586,7 @@ body {
body:not(.ntsh_service) .ntsh_buttons {
display: none;
}
body:not(.ntsh_service) .mux_menubar-locater.mux_left .mux_menubar-item:not([uid=restart_installation]) {
body:not(.ntsh_service) .mux_menubar-locater.mux_left .mux_menubar-item:not([uid=restart_installation], [uid=shutdown_installation]) {
display: none;
}
body:not(.ntsh_service) .only-service {
@@ -2618,4 +2631,21 @@ body.ntsh_service .no-service {
color: #c7c7c7;
}
.ntsh_shutdown {
position: absolute;
inset: 0px;
z-index: 10000;
background: var(--mux-bg-color);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
gap: var(--mux-edge-offset);
}
.ntsh_shutdown .material-symbols-outlined {
margin-bottom: var(--mux-edge-offset);
font-size: 60px;
color: #919191;
}
/*# sourceMappingURL=style.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -23,6 +23,12 @@ export class DashboardUnity {
restartButton: HTMLDivElement = document.querySelector(
'.ntsh_dashboard-unity-restart'
);
startButton: HTMLDivElement = document.querySelector(
'.ntsh_dashboard-unity-start'
);
stopButton: HTMLDivElement = document.querySelector(
'.ntsh_dashboard-unity-stop'
);
uptimeInfo: HTMLDivElement = document.querySelector(
'.ntsh_dashboard-unity-uptime'
@@ -75,6 +81,9 @@ export class DashboardUnity {
parametersTable: HTMLTableElement = document.querySelector(
'.ntsh_dashboard-unity-parameters'
);
advancedParametersTable: HTMLTableElement = document.querySelector(
'.ntsh_dashboard-unity-advancedparameters'
);
sensorsTable: HTMLTableElement = document.querySelector(
'.ntsh_dashboard-unity-sensors'
@@ -100,9 +109,13 @@ export class DashboardUnity {
state.startTime = -1;
this.restartButton.style.display = 'none';
this.stopButton.style.display = 'none';
} else {
this.restartButton.style.display = 'flex';
this.stopButton.style.display = 'flex';
}
this.startButton.style.display =
state.state == 'STOPPED' ? 'flex' : 'none';
setStatusState(
this.processStatus,
@@ -200,6 +213,9 @@ export class DashboardUnity {
this.renderParameterSliders(
state.state == 'CONNECTED' ? state.parameters.sliders : []
);
this.renderAdvancedParameterSliders(
state.state == 'CONNECTED' ? state.parameters.advancedSliders : []
);
this.renderParameterSensors(
state.state == 'CONNECTED' ? state.parameters.sensors : []
);
@@ -358,6 +374,155 @@ export class DashboardUnity {
}
}
private renderAdvancedParameterSliders(
sliders: UnityParameters['sliders']
) {
const existingSliders = this.advancedParametersTable.querySelectorAll(
'.ntsh_dashboard-unity-parameter-row'
);
if (existingSliders.length !== sliders.length) {
this.advancedParametersTable.innerHTML = '';
if (sliders.length === 0) {
const row = ce('tr');
const cell = ce('td');
cell.appendChild(
ce(
'div',
['mux_text', 'ntsh_dashboard-unity-parameters-loading'],
null,
'Waiting for Unity...'
)
);
row.appendChild(cell);
this.advancedParametersTable.appendChild(row);
} else
sliders.forEach((slider) => {
const multiplierFactor = slider.visualMultiplier ?? 1;
const decimalPlacesFactor =
10 ** (slider.decimalPlaces ?? 0);
const value =
Math.round(
slider.outputValue *
multiplierFactor *
decimalPlacesFactor
) / decimalPlacesFactor;
const row = ce('tr', 'ntsh_dashboard-unity-parameter-row');
const nameCell = ce('td');
nameCell.appendChild(
ce('div', 'mux_text', null, slider.sliderName)
);
row.appendChild(nameCell);
const progressCell = ce('td', 'no-service');
progressCell.appendChild(
createProgress(
value,
slider.min * multiplierFactor,
slider.max * multiplierFactor,
slider.unit
)
);
row.appendChild(progressCell);
const sliderCell = ce('td', 'only-service');
const sliderProgress = createProgress(
value,
slider.min * multiplierFactor,
slider.max * multiplierFactor,
slider.unit
);
const sliderValue: HTMLDivElement =
sliderProgress.querySelector('.ntsh_progress-value');
sliderValue.classList.add('mux_resizer');
sliderCell.appendChild(sliderProgress);
const resizer = new MorphComponent.Resizer({
existingContainer: sliderValue,
direction: 'right',
relative: true,
min: 0,
max: () => sliderProgress.clientWidth,
});
let lastValue: number = -1;
resizer.on('resized', (size) => {
const percentage =
Math.round(
(size / sliderProgress.clientWidth) * 100
) / 100;
var actualValue =
slider.min + percentage * (slider.max - slider.min);
if (actualValue === lastValue) return;
lastValue = actualValue;
this._Main.socket.emit(
'unityWebSocket',
'advancedParameterValue',
slider.sliderIndex,
actualValue
);
setProgressState(
sliderProgress,
Math.round(
actualValue *
multiplierFactor *
decimalPlacesFactor
) / decimalPlacesFactor,
slider.min * multiplierFactor,
slider.max * multiplierFactor,
slider.unit
);
});
row.appendChild(sliderCell);
this.advancedParametersTable.appendChild(row);
});
} else {
existingSliders.forEach((row, index) => {
const slider = sliders[index];
const multiplierFactor = slider.visualMultiplier ?? 1;
const decimalPlacesFactor = 10 ** (slider.decimalPlaces ?? 0);
const value =
Math.round(
slider.outputValue *
multiplierFactor *
decimalPlacesFactor
) / decimalPlacesFactor;
const progressElement: HTMLDivElement = row.querySelector(
'.no-service .ntsh_progress'
);
setProgressState(
progressElement,
value,
slider.min * multiplierFactor,
slider.max * multiplierFactor,
slider.unit
);
const sliderElement: HTMLDivElement = row.querySelector(
'.only-service .ntsh_progress'
);
if (sliderElement.querySelector('.mux_resizer-moving') == null)
setProgressState(
sliderElement,
value,
slider.min * multiplierFactor,
slider.max * multiplierFactor,
slider.unit
);
});
}
}
private renderParameterSensors(sensors: UnityParameters['sensors']) {
const existingSensors = this.sensorsTable.querySelectorAll(
'.ntsh_dashboard-unity-sensor-row'
@@ -448,6 +613,18 @@ export class DashboardUnity {
'Are you sure you want to restart the Unity Runner process?'
);
});
this.startButton.addEventListener('click', async () => {
this.executeCommand(
'start',
'Are you sure you want to start the Unity Runner process?'
);
});
this.stopButton.addEventListener('click', async () => {
this.executeCommand(
'stop',
'Are you sure you want to stop the Unity Runner process?'
);
});
this.enableOutOfServiceButton.addEventListener('click', async () => {
this.executeCommand(
@@ -528,6 +705,7 @@ interface UnityParameters {
zedFPS: string;
outOfService: boolean;
sliders: UnityParameterSlider[];
advancedSliders: UnityParameterSlider[];
sensors: UnitySocketMessageHeartbeat['heartbeat']['dataSensors'];
}

View File

@@ -44,6 +44,20 @@ export class MenuBar {
this.restartInstallation();
},
},
// {
// type: 'icon',
// text: 'Shutdown',
// materialIcon: 'power_settings_new',
// uniqueIdentifier: 'shutdown_installation',
// click: async () => {
// const mobileMenu: HTMLDivElement =
// document.querySelector('.mux_mobilemenu');
// mobileMenu?.click();
// this.shutdownInstallation();
// },
// },
],
right: [
{
@@ -70,6 +84,20 @@ export class MenuBar {
this.restartInstallation();
},
},
// {
// type: 'normal',
// text: 'Shutdown',
// materialIcon: 'power_settings_new',
// uniqueIdentifier: 'shutdown_installation',
// click: async () => {
// const mobileMenu: HTMLDivElement =
// document.querySelector('.mux_mobilemenu');
// mobileMenu?.click();
// this.shutdownInstallation();
// },
// },
{
type: 'normal',
text: 'Dashboard',
@@ -187,6 +215,35 @@ export class MenuBar {
);
}
async shutdownInstallation() {
const confirmed = await MorphFeature.Confirm({
title: 'Shutdown Installation',
message: 'Are you sure you want to shutdown the installation?',
});
if (!confirmed) return;
MorphFeature.Loader({
active: true,
message: 'Shutting down installation...',
});
const shutdownContainer: HTMLDivElement =
document.querySelector('.ntsh_shutdown');
this._Main.socket.emit(
'shutdownInstallation',
(response: { succeed: boolean; message?: string }) => {
MorphFeature.Loader({ active: false });
if (!response.succeed)
return MorphFeature.Alert({
title: 'Error',
message: response.message,
});
shutdownContainer.style.display = 'flex';
}
);
}
async toggleServiceMode(
mode?: boolean,
skipPin?: boolean

320
package-lock.json generated
View File

@@ -15,8 +15,10 @@
"@types/ws": "^8.18.1",
"express": "^5.1.0",
"fs-extra": "^11.3.2",
"ping": "^1.0.0",
"socket.io": "^4.8.1",
"socket.io-client": "^4.8.1",
"twilio": "^5.10.3",
"ws": "^8.18.3"
}
},
@@ -181,6 +183,35 @@
"node": ">= 0.6"
}
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"license": "MIT",
"dependencies": {
"debug": "4"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
@@ -210,6 +241,12 @@
"node": ">=18"
}
},
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
"license": "BSD-3-Clause"
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -248,6 +285,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/content-disposition": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
@@ -300,6 +349,12 @@
"node": ">= 0.10"
}
},
"node_modules/dayjs": {
"version": "1.11.18",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
"integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
"license": "MIT"
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -317,6 +372,15 @@
}
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -340,6 +404,15 @@
"node": ">= 0.4"
}
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -546,6 +619,21 @@
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -620,6 +708,63 @@
"node": ">= 0.8"
}
},
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/form-data/node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/form-data/node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -728,6 +873,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -765,6 +925,19 @@
"node": ">= 0.8"
}
},
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"license": "MIT",
"dependencies": {
"agent-base": "6",
"debug": "4"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -810,6 +983,91 @@
"graceful-fs": "^4.1.6"
}
},
"node_modules/jsonwebtoken": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
"license": "MIT",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^7.5.4"
},
"engines": {
"node": ">=12",
"npm": ">=6"
}
},
"node_modules/jwa": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
"integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"license": "MIT",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
"license": "MIT"
},
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
"license": "MIT"
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
"license": "MIT"
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
"license": "MIT"
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
"license": "MIT"
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
"license": "MIT"
},
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
"license": "MIT"
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -937,6 +1195,15 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/ping": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/ping/-/ping-1.0.0.tgz",
"integrity": "sha512-3dxdgGtV+7P/EVo42JhkGSomeO/0GGicSz3mI/yK+AI+VGNAOfakw5XfcbGI4IjyBY+ZZwvuRXdhnNF2uliKew==",
"license": "MIT",
"engines": {
"node": ">=22.0.0"
}
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -950,6 +1217,12 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
@@ -1047,6 +1320,24 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/scmp": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz",
"integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==",
"license": "BSD-3-Clause"
},
"node_modules/semver": {
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/send": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
@@ -1368,6 +1659,24 @@
"node": ">=0.6"
}
},
"node_modules/twilio": {
"version": "5.10.3",
"resolved": "https://registry.npmjs.org/twilio/-/twilio-5.10.3.tgz",
"integrity": "sha512-msve3uADprpG+LRlthOxBUJWZDczGe+mdzotG7Wluaf8nn8fSIK0n2fX3INR26Xedeea/azmAdLK0c2rJhIHpQ==",
"license": "MIT",
"dependencies": {
"axios": "^1.12.0",
"dayjs": "^1.11.9",
"https-proxy-agent": "^5.0.0",
"jsonwebtoken": "^9.0.2",
"qs": "^6.9.4",
"scmp": "^2.1.0",
"xmlbuilder": "^13.0.2"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
@@ -1442,6 +1751,15 @@
}
}
},
"node_modules/xmlbuilder": {
"version": "13.0.2",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz",
"integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==",
"license": "MIT",
"engines": {
"node": ">=6.0"
}
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
@@ -1451,4 +1769,4 @@
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "ntshcontrol",
"version": "1.0.0",
"version": "2025.11.2",
"main": "dist/Entry.js",
"scripts": {
"start": "node ."
@@ -15,8 +15,10 @@
"@types/ws": "^8.18.1",
"express": "^5.1.0",
"fs-extra": "^11.3.2",
"ping": "^1.0.0",
"socket.io": "^4.8.1",
"socket.io-client": "^4.8.1",
"twilio": "^5.10.3",
"ws": "^8.18.3"
}
}

View File

@@ -8,6 +8,9 @@ export class CameraRunner {
socket: Socket;
errorTriggerStartupDelay = 10000;
bootTime = Date.now();
state: ServiceState = 'DISCONNECTED';
message?: string;
error?: string;
@@ -76,6 +79,12 @@ export class CameraRunner {
this.state = state;
this.broadcastState();
if (
error != null &&
Date.now() - this.bootTime > this.errorTriggerStartupDelay
)
this._Main.Twilio.sendError('CameraRunner', error);
if (state == 'FAILED' || state == 'DISCONNECTED')
console.warn(PREFIX, message ?? error);
else console.log(PREFIX, message ?? error);
@@ -147,6 +156,7 @@ export class CameraRunner {
});
this.socket.on('connect', () => {
this._Main.Twilio.resetError('CameraRunner');
this.setInfo('Connected', null, 'CONNECTED');
this.startPollClock();
});

View File

@@ -99,12 +99,19 @@ export class ConfigurationManager {
}
export interface Config {
router: ConfigRouter;
webServer: ConfigWebServer;
unity: ConfigUnity;
cameraRunner: ConfigCameraRunner;
twilio: ConfigTwilio;
support: ConfigSupport;
}
export interface ConfigRouter {
ip: string;
waitForStartup: boolean;
}
export interface ConfigWebServer {
port: number;
}
@@ -134,6 +141,15 @@ export interface ConfigCameraRunner {
pollInterval: number;
}
export interface ConfigTwilio {
accountSid: string;
authToken: string;
fromNumber: string;
toNumbers: string[];
aggregateTimeout: number;
maxMessagesPerDay: number;
}
export interface ConfigSupport {
telephone: string;
}

View File

@@ -4,6 +4,10 @@ export const DefaultConfiguration: Config = {
webServer: {
port: 6300,
},
router: {
ip: '',
waitForStartup: true,
},
unity: {
executable: {
path: '',
@@ -27,6 +31,14 @@ export const DefaultConfiguration: Config = {
pollInterval: 5000,
},
twilio: {
accountSid: '',
authToken: '',
fromNumber: '',
toNumbers: [],
aggregateTimeout: 15000,
maxMessagesPerDay: 10,
},
support: {
telephone: '+31613392837',
},

View File

@@ -8,12 +8,18 @@ import {
import { CameraRunner } from './CameraRunner';
import { UnityRunner } from './Unity/UnityRunner';
import { UnityWebSocket } from './Unity/UnityWebSocket';
import { TwilioHandler } from './Twilio';
import { delay } from './Utils';
import * as ping from 'ping';
import { shutdown } from './Shutdown';
const PREFIX = '[Main]';
export class Main {
dataPath = join(homedir(), 'MorphixProductions', 'NTSHControl');
ConfigurationManager = new ConfigurationManager(this);
WebServer = new WebServer(this);
Twilio = new TwilioHandler(this);
CameraRunner = new CameraRunner(this);
UnityRunner = new UnityRunner(this);
@@ -23,7 +29,11 @@ export class Main {
async start() {
await this.ConfigurationManager.load();
await this.waitForRouter();
await this.WebServer.listen();
await this.Twilio.load();
await this.CameraRunner.connect();
@@ -47,9 +57,14 @@ export class Main {
'Failed to reboot CameraRunner:',
response.message
);
this.Twilio.sendError(
'CameraRunner',
`Failed to reboot CameraRunner: ${response.message}`
);
resolve(false);
} else {
console.log('CameraRunner rebooted successfully.');
this.Twilio.sendError('CameraRunner', null);
resolve(true);
}
}
@@ -57,9 +72,48 @@ export class Main {
});
if (!succeed) return;
await delay(5000);
console.log('Starting UnityRunner...');
await this.UnityRunner.start();
console.log('Restart complete.');
}
async shutdown() {
console.log('Stopping UnityRunner...');
await this.UnityRunner.stop();
const doShutdown = process.argv.includes('--no-shutdown')
? false
: true;
if (doShutdown) {
console.log('Shutting down system...');
shutdown();
} else {
console.log('Shutdown skipped due to --no-shutdown flag.');
}
process.exit(0);
}
waitForRouter() {
if (this.Config.router?.waitForStartup !== true) return;
return new Promise<void>((resolve) => {
const check = () => {
console.log(PREFIX, 'Waiting for router...');
ping.sys.probe(this.Config.router.ip, async ({ alive }) => {
if (alive) {
console.log(PREFIX, 'Router is online');
await delay(3000);
return resolve();
}
await delay(1000);
check();
});
};
check();
});
}
}

33
src/Shutdown.ts Normal file
View File

@@ -0,0 +1,33 @@
import { exec } from 'child_process';
export function shutdown(): Promise<{ succeed: boolean; message?: string }> {
if (process.platform === 'win32') {
return shutdownWindows();
}
return Promise.resolve({
succeed: false,
message: 'Platform not supported',
});
}
function shutdownWindows(): Promise<{ succeed: boolean; message?: string }> {
return new Promise<{ succeed: boolean; message?: string }>(
(resolve, reject) => {
exec('shutdown /s /t 5', (error, stdout, stderr) => {
if (error) {
console.error(
`Error shutting down Windows: ${error.message}`
);
return resolve({ succeed: false, message: error.message });
}
if (stderr) {
console.error(`Error shutting down Windows: ${stderr}`);
return resolve({ succeed: false, message: stderr });
}
console.log(`Windows shutdown command executed: ${stdout}`);
resolve({ succeed: true });
});
}
);
}

107
src/Twilio.ts Normal file
View File

@@ -0,0 +1,107 @@
import { join } from 'path';
import { Main } from './Main';
import { pathExists, readJSON, writeJSON } from 'fs-extra';
const PREFIX = '[Twilio]';
export class TwilioHandler {
private _Main: Main;
counter: {
date: string;
count: number;
} = {
date: new Date().toLocaleDateString('nl-NL'),
count: 0,
};
client;
constructor(Main: Main) {
this._Main = Main;
}
canSendMessage() {
const maxMessages = this._Main.Config.twilio.maxMessagesPerDay;
return this.counter.count < maxMessages;
}
async incrementCounter() {
const today = new Date().toLocaleDateString('nl-NL');
if (this.counter.date !== today) {
this.counter.date = today;
this.counter.count = 0;
}
this.counter.count++;
await writeJSON(join(this._Main.dataPath, 'twilio.json'), this.counter);
}
async load() {
const twilioConfigPath = join(this._Main.dataPath, 'twilio.json');
const twilioConfigExists = await pathExists(twilioConfigPath);
if (twilioConfigExists) {
this.counter = await readJSON(twilioConfigPath);
}
this.client = require('twilio')(
this._Main.Config.twilio.accountSid,
this._Main.Config.twilio.authToken
);
}
async resetError(category: TwilioCategories) {
if (!this.lastErrors.has(category)) return;
this.lastErrors.delete(category);
}
private lastErrors: Map<TwilioCategories, string> = new Map();
private errorLog: string[] = [];
private errorTimeout: NodeJS.Timeout;
async sendError(category: TwilioCategories, error: string) {
if (this.lastErrors.get(category) === error) return;
this.lastErrors.set(category, error);
if (error == null) return;
this.errorLog.push(`${category}: ${error}`);
clearTimeout(this.errorTimeout);
this.errorTimeout = setTimeout(async () => {
const errorMessage = this.errorLog
.map((error) => `- ${error}`)
.join('\n');
this.errorLog = [];
if (!this.canSendMessage())
return console.log(PREFIX, 'Max messages per day reached');
await this.incrementCounter();
console.log(PREFIX, `Sending to Twilio:\n`, errorMessage);
const promises = this._Main.Config.twilio.toNumbers.map(
(toNumber) => this.sendMessage(toNumber, errorMessage)
);
await Promise.all(promises);
}, this._Main.Config.twilio.aggregateTimeout);
}
sendMessage(to: string, message: string) {
return;
return new Promise<boolean>((resolve) => {
this.client.messages
.create({
body: message,
from: `${this._Main.Config.twilio.fromNumber}`,
to: to,
})
.then((message: any) => {
console.log(`Twilio message sent with SID: ${message.sid}`);
resolve(true);
})
.catch((error: any) => {
console.error('Error sending Twilio message:', error);
resolve(false);
});
});
}
}
type TwilioCategories = 'CameraRunner' | 'UnityRunner' | 'UnityWebSocket';

View File

@@ -14,6 +14,8 @@ export class UnityRunner {
message?: string = 'Awaiting startup delay...';
error?: string;
bootTime = Date.now();
startTime: number = null;
output: { current: string[]; last: string[] } = { current: [], last: [] };
@@ -24,16 +26,19 @@ export class UnityRunner {
}
handle(command: string, ...args: any[]) {
const callback: (response: {
succeed: boolean;
message?: string;
}) => void = args[0];
if (typeof callback !== 'function') return;
switch (command) {
case 'restart':
const callback: (response: {
succeed: boolean;
message?: string;
}) => void = args[0];
if (typeof callback !== 'function') return;
callback(this.requestRestart());
break;
return callback(this.requestRestart());
case 'stop':
return callback(this.requestStop());
case 'start':
return callback(this.requestStart());
}
}
@@ -57,6 +62,29 @@ export class UnityRunner {
return { succeed: true };
}
requestStop(): { succeed: boolean; message?: string } {
if (this.state !== 'RUNNING')
return {
succeed: false,
message:
'Cannot stop when process is not running. It is probably restarting already.',
};
this.stop();
return { succeed: true };
}
requestStart(): { succeed: boolean; message?: string } {
if (this.state !== 'STOPPED')
return {
succeed: false,
message: 'Cannot start when process is already running.',
};
this.start();
return { succeed: true };
}
broadcastState() {
this._Main.WebServer.socket.emit('unityRunnerState', this.getStatus());
}
@@ -71,6 +99,8 @@ export class UnityRunner {
this.state = state;
this.broadcastState();
if (error != null) this._Main.Twilio.sendError('UnityRunner', error);
this.output.current.push(
`[${new Date().toLocaleTimeString('nl-NL')}] [System] [${state}] ${
message ?? error
@@ -134,6 +164,9 @@ export class UnityRunner {
async restart(instant: boolean = false) {
if (this.restartTriggered) return;
this.restartTriggered = true;
this._Main.WebServer.Calibration.hasCalibrationImage = false;
clearInterval(this.statusClock);
this.startTime = -1;
@@ -280,6 +313,7 @@ export class UnityRunner {
)
return;
this._Main.Twilio.resetError('UnityRunner');
this.setInfo('Running', '', 'RUNNING');
this._Main.UnityWebSocket.connect();
}, 5000);

View File

@@ -10,6 +10,8 @@ export class UnityWebSocket {
message?: string = 'Waiting for process...';
error?: string;
errorTriggerStartupDelay = 1000;
parameters: UnityParameters = {
timelineWatching: false,
timelineStanding: false,
@@ -19,6 +21,7 @@ export class UnityWebSocket {
zedFPS: '-',
outOfService: null,
sliders: [],
advancedSliders: [],
sensors: [],
};
@@ -37,6 +40,13 @@ export class UnityWebSocket {
this.setSliderValue(sliderIndex, percentage);
break;
case 'advancedParameterValue':
const advSliderIndex: number = args[0];
const advPercentage: number = args[1];
this.setAdvancedSliderValue(advSliderIndex, advPercentage);
break;
case 'enableOutOfService':
const enableCallback: Function = args[0];
if (typeof enableCallback !== 'function') return;
@@ -85,6 +95,23 @@ export class UnityWebSocket {
this.broadcastState();
}
setAdvancedSliderValue(sliderIndex: number, sliderValue: number) {
if (this.socket == null || this.socket.readyState !== WebSocket.OPEN)
return;
this.socket.send(
JSON.stringify({
type: 'set_advanced_slider_value',
sliderIndex,
sliderValue,
})
);
if (this.parameters.advancedSliders[sliderIndex] == undefined) return;
this.parameters.advancedSliders[sliderIndex].outputValue = sliderValue;
this.broadcastState();
}
setOutOfService(state: boolean) {
if (this.socket == null || this.socket.readyState !== WebSocket.OPEN)
return;
@@ -113,6 +140,8 @@ export class UnityWebSocket {
this.state = state;
this.broadcastState();
if (error != null) this._Main.Twilio.sendError('UnityWebSocket', error);
if (state == 'FAILED' || state == 'DISCONNECTED')
console.warn(PREFIX, message ?? error);
else console.log(PREFIX, message ?? error);
@@ -146,7 +175,29 @@ export class UnityWebSocket {
this.parameters.outOfService =
message.heartbeat.showOutOfService ?? false;
this.parameters.sensors = message.heartbeat.dataSensors;
this.parameters.sliders = message.heartbeat.dataSliders;
this.parameters.sliders = message.heartbeat.dataSliders.map(
(slider) => {
return {
...slider,
decimalPlaces:
(slider.min == 0 || slider.min == -1) &&
slider.max == 1
? 2
: null,
};
}
);
this.parameters.advancedSliders =
message.heartbeat.dataAdvancedSliders.map((slider) => {
return {
...slider,
decimalPlaces:
(slider.min == 0 || slider.min == -1) &&
slider.max == 1
? 2
: null,
};
});
this.broadcastState();
break;
@@ -226,6 +277,8 @@ export class UnityWebSocket {
this.socket.on('open', () => {
this.startFetchClocks();
this._Main.Twilio.resetError('UnityWebSocket');
this.setInfo('Connected', null, 'CONNECTED');
});
@@ -298,6 +351,7 @@ interface UnityParameters {
zedFPS: string;
outOfService: boolean;
sliders: UnityParameterSlider[];
advancedSliders: UnityParameterSlider[];
sensors: UnitySocketMessageHeartbeat['heartbeat']['dataSensors'];
}
@@ -332,6 +386,14 @@ interface UnitySocketMessageHeartbeat extends UnitySocketMessageBase {
max: number;
unit: string;
}[];
dataAdvancedSliders: {
sliderIndex: number;
sliderName: string;
outputValue: number;
min: number;
max: number;
unit: string;
}[];
dataTimeline: {
isStanding: boolean;
isWatching: boolean;

View File

@@ -6,6 +6,7 @@ import { Main } from '../Main';
import { DashboardRouter } from './DashboardRouter';
import { join } from 'path';
import { CalibrationRouter } from './CalibrationRouter';
import { delay } from '../Utils';
const PREFIX = '[WebServer]';
export class WebServer {
@@ -74,6 +75,20 @@ export class WebServer {
callback({ succeed: true });
}
);
socket.on(
'shutdownInstallation',
async (
callback: (response: {
succeed: boolean;
message?: string;
}) => void
) => {
await delay(1000);
callback({ succeed: true });
this._Main.shutdown();
}
);
socket.on('cameraRunner', (command: string, ...args: any[]) =>
this._Main.CameraRunner.handle(command, ...args)
);