diff options
Diffstat (limited to 'src/NeoRuntimeManager/IPC.js')
-rw-r--r-- | src/NeoRuntimeManager/IPC.js | 199 |
1 files changed, 0 insertions, 199 deletions
diff --git a/src/NeoRuntimeManager/IPC.js b/src/NeoRuntimeManager/IPC.js deleted file mode 100644 index 56c8b5d..0000000 --- a/src/NeoRuntimeManager/IPC.js +++ /dev/null @@ -1,199 +0,0 @@ -/** - * This module is used to communicate with a python NeoRuntime instance. - * - * @author jakobst1n. - * @since 3.10.2021 - */ - -const net = require("net"); -let logger = require(__appdir + "/src/Logger"); - -/** @type {int} How long wait between each reconnection attempt */ -const RECONNECT_INTERVAL = 1000; -/** @type {Object} ENUM-ish for command that can be sent to neoruntime */ -const COMMAND = Object.freeze({SET_GLOB : 0, - SET_VAR : 1, - SET_SEND_STRIP_BUF: 2}); -/** @type {Object} ENUM-ish for globvars */ -const GLOBVAR = Object.freeze({POWER_ON : 0, - BRIGHTNESS: 1}); -/** @type {Object} ENUM-ish for what type of data neoruntime sends */ -const DATATYPE = Object.freeze({STATES : 1, - STRIP_BUF: 2, - MATRIX: 3}); - -/** - * class that will keep a active connection to a socket if possible, and - * automatically reconnect. It will emit events when data is received, - * and it will send commands to the process. */ -class IPC { - - constructor(_socketFile, _eventEmitter) { - this.socketFile = _socketFile; - this.eventEmitter = _eventEmitter; - - this.client; - this.connected = false; - this.reconnectInterval = false; - - this.globvars = {}; - this.variables = {}; - - this.reconnect(); - } - - /** - * If we are not already attempting to reconnect, this will start a - * interval that tries to reconnect. */ - reconnect() { - if (this.reconnectInterval === false) { - this.reconnectInterval = setInterval(this.tryOpenSocketConnection.bind(this), RECONNECT_INTERVAL); - } - } - - /** - * This will attempt to connect to the socket, and then setup all listeners - * if it succedes. */ - tryOpenSocketConnection() { - // logger.info("Attempting to start IPC"); - - this.client = net.createConnection(this.socketFile) - .on('connect', () => { - clearInterval(this.reconnectInterval); - this.reconnectInterval = false; - logger.info("IPC Connected."); - }) - .on("ready", () => { - this.connected = true; - }) - .on('data', (data) => { - let json_data; - switch (data[0]) { - case DATATYPE.STATES: - try { - json_data = JSON.parse(data.toString("ascii", 1)); - } catch (e) { - logger.warning("Could not parse json data from neoruntime"); - return; - } - - if (json_data.hasOwnProperty("globvars")) { - forEachDiff(json_data["globvars"], this.globvars, (key, newVal) => { - this.eventEmitter.emit("change", key, newVal); - }); - this.globvars = json_data["globvars"]; - } - if (json_data.hasOwnProperty("variables")) { - forEachDiff(json_data["variables"], this.variables, (key, newVal) => { - this.eventEmitter.emit("change", `variable/${key}`, newVal); - }); - this.variables = json_data["variables"]; - } - break; - - case DATATYPE.MATRIX: - try { - json_data = JSON.parse(data.toString("ascii", 1)); - } catch (e) { - logger.warning("Could not parse json data from neoruntime"); - console.log(e); - } - this.eventEmitter.emit("matrix", json_data); - break; - - case DATATYPE.STRIP_BUF: - this.eventEmitter.emit("strip_buffer", Array.from(data.values()).slice(1)); - break; - - default: - logger.info(data); - } - - }) - .on("timeout", () => { - logger.info("IPC Timeout"); - }) - .on("close", (hadError) => { - logger.info("IPC Close, hadError: ", hadError); - this.connected = false; - this.reconnect(); - }) - .on("end", () => { - logger.info("IPC End"); - this.connected = false; - }) - .on('error', (data) => { - logger.info('IPC Server not active.'); - this.connected = false; - this.reconnect(); - }) - ; - } - - /** - * Will send a command to the socket if we have a active connection, - * if not it will just drop the command. there is no queue implemented - * for such events. */ - sendCommand(commandType, name, value) { - if (this.connected) { - let buf; - - switch (commandType) { - case (COMMAND.SET_GLOB): - buf = Buffer.allocUnsafe(3); - buf[1] = name; - buf[2] = value; - break; - - case (COMMAND.SET_VAR): - if (name.length > 32) { return {success: false, reason: "name too long", detail: "max size of name is 32 bytes"}; } - if (value.length > 93) { return {success: false, reason: "value too long", detail: "max size of value is 93 bytes"}; } - buf = Buffer.allocUnsafe(3 + name.length + value.length); - buf[1] = name.length; - buf[2] = value.length; - buf.write(name, 3, name.length, "ascii"); - buf.write(value, 3+name.length, value.length, "ascii"); - break; - - case (COMMAND.SET_SEND_STRIP_BUF): - buf = Buffer.allocUnsafe(2); - buf[1] = (name) ? 1 : 0; - break; - - default: - logger.warning(`IPC UNKNOWN COMMANDTYPE ${commandType}`) - return {success: false, reason: "ipc command unknown", detail: commandType}; - } - - buf[0] = commandType; - this.client.write(buf); - return {success: true} - } - return {success: false, reason: "socket not connected", detail: "This usually means the python script is not running"}; - } - -} - -const isObject = v => v && typeof v === 'object'; - -/** - * Will call callback on all the differences between the dicts - */ -function forEachDiff(dict1, dict2, callback) { - for (const key of new Set([...Object.keys(dict1), ...Object.keys(dict2)])) { - if (isObject(dict1[key]) && isObject(dict2[key])) { - if (dict1[key].value !== dict2[key].value) { - callback(key, dict1[key]); - } - } else if (dict1[key] !== dict2[key]) { - if (isObject(dict2[key]) && (dict1[key] == null)) { - dict2[key].value = null; - callback(key, dict2[key]) - } else { - callback(key, dict1[key]); - } - } - } -} - -module.exports = {IPC, COMMAND, GLOBVAR}; |