-
-
Save skylord123/6de070b22e2231f419215774eeb504fb to your computer and use it in GitHub Desktop.
Node-RED telnet client for Torque Game Engine console
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [ | |
| { | |
| "id": "5eb5381789943947", | |
| "type": "group", | |
| "z": "f740c835e145407e", | |
| "name": "AOT Telnet Console", | |
| "style": { | |
| "label": true | |
| }, | |
| "nodes": [ | |
| "8fee83604ae9f94b", | |
| "2725b21880fa7406", | |
| "2423ee2b4b84e6f2", | |
| "5c798a02c96d56d3", | |
| "a4d6217fb50a0507", | |
| "fde6528ee25bdb01", | |
| "0b3cdb6bb0f6f102", | |
| "aea19681196029c0", | |
| "39756dd0b5365a1d" | |
| ], | |
| "x": 254, | |
| "y": 5119, | |
| "w": 1292, | |
| "h": 242 | |
| }, | |
| { | |
| "id": "8fee83604ae9f94b", | |
| "type": "function", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "Torque TelnetConsole", | |
| "func": "if(msg.payload && this.client) {\n node.warn(\"sending: \" + msg.payload);\n context.set('aot_telnet_client_last_cmd', msg.payload);\n node.status({ fill: \"orange\", shape: \"dot\", text: \"Sending command\" });\n this.last_cmd = msg.payload;\n this.client.write(msg.payload + \"\\n\");\n}", | |
| "outputs": 1, | |
| "timeout": 0, | |
| "noerr": 0, | |
| "initialize": "// telnet server details\nconst host = '192.168.18.2';\nconst port = 3333;\nconst password = 'Twig-Sappiness-Numbing1';\n\n// Reconnection configuration\nconst auto_reconnect = true; // Enable or disable auto-reconnect\nlet reconnect_attempts = 0;\nconst reconnect_delay = 5000; // Initial delay in milliseconds\nconst max_reconnect_delay = 30000; // Maximum delay in milliseconds\nconst attempts_before_increase = 3; // Attempts before increasing delay\nlet current_delay = reconnect_delay;\nlet self = this;\n\n// Initialize the connection status\nnode.status({ fill: \"orange\", shape: \"ring\", text: \"Connecting\" });\n\n// Function to create a TCP client and handle its events\nfunction connectToServer() {\n if(self.client) {\n self.client.end();\n if (typeof self.client[\"destroy\"] === \"function\") {\n self.client[\"destroy\"]();\n } else {\n node.warn(\"unknown destroy function\");\n }\n self.client = null;\n }\n if (context.get('aot_telnet_client')) {\n context.set('aot_telnet_client', undefined);\n }\n \n self.client = net.createConnection({ host: host, port: port }, () => {\n node.debug('Connected to Torque Game Engine TelnetConsole');\n node.status({ fill: \"green\", shape: \"dot\", text: \"Connected\" });\n reconnect_attempts = 0; // Reset reconnect attempts on successful connection\n current_delay = reconnect_delay; // Reset the delay to initial value\n });\n context.set('aot_telnet_client_last_cmd', null);\n self.last_cmd = null;\n context.set('aot_telnet_client', self.client);\n node.client = self.client;\n\n let isPasswordSent = false,\n authSuccess = false;\n\n self.client.on('data', (data) => {\n try {\n\n const response = data.toString();\n if (!isPasswordSent && response.includes('Password:')) {\n self.client.write(password + '\\n');\n isPasswordSent = true;\n node.status({ fill: \"green\", shape: \"dot\", text: \"Password sent\" });\n } else if (\n self.last_cmd\n && self.last_cmd.trim().length\n && (self.last_cmd.trim() === response.trim() || response.indexOf(self.last_cmd.trim() + \"\\r\\n\") >= 0)\n ) {\n // successfully sent our command\n node.status({ fill: \"green\", shape: \"dot\", text: \"Sent command\" });\n if (response.indexOf(self.last_cmd.trim() + \"\\r\") >= 0) {\n // our command only makes up part of this message\n // remove our command and send the rest\n let newResponse = response.replaceAll(self.last_cmd.trim() + \"\\r\\n\", \"\");\n if (newResponse.trim().length) {\n node.send({\n payload: response.replaceAll(self.last_cmd.trim() + \"\\r\\n\", \"\")\n });\n }\n }\n self.last_cmd = null;\n } else if (isPasswordSent && response.trim().length) {\n if (!authSuccess) {\n authSuccess = true;\n node.status({ fill: \"green\", shape: \"dot\", text: \"Authenticated\" });\n // send $Con::Prompt = \"<input> \";\n }\n\n let lastChar = response.charAt(response.length - 1).charCodeAt(0).toString(16);\n let firstChar = response.charAt(0).charCodeAt(0).toString(16);\n\n node.send({\n payload: response,\n first_char_hex: firstChar,\n last_char_hex: lastChar\n });\n }\n } catch(e) {\n node.warn(\"Error: \" + e);\n }\n });\n\n self.client.on('end', () => {\n node.status({ fill: \"red\", shape: \"ring\", text: \"Disconnected\" });\n isPasswordSent = false;\n authSuccess = false;\n if (typeof self.client[\"destroy\"] === \"function\") {\n self.client[\"destroy\"]();\n } else {\n node.warn(\"unknown destroy function\");\n }\n if (auto_reconnect) {\n node.warn(\"Disconnected for some reason, attempting reconnect..\");\n attemptReconnect();\n }\n });\n\n self.client.on('error', (err) => {\n node.status({ fill: \"red\", shape: \"ring\", text: \"Error: \" + err });\n node.error('Connection error: ' + err.message);\n self.client.end(); // Ensure the socket is closed on error\n if (auto_reconnect) {\n attemptReconnect();\n }\n });\n}\n\n// Function to handle reconnection attempts\nfunction attemptReconnect() {\n if (reconnect_attempts >= attempts_before_increase) {\n current_delay = Math.min(current_delay * 2, max_reconnect_delay);\n reconnect_attempts = 0;\n } else {\n reconnect_attempts++;\n }\n\n setTimeout(connectToServer, current_delay);\n node.status({ fill: \"yellow\", shape: \"ring\", text: \"Reconnecting in \" + (current_delay / 1000) + \"s\" });\n}\n\nconnectToServer(); // Initial connection attempt", | |
| "finalize": "// Code added here will be run when the\n// node is being stopped or re-deployed.\n\nif(this.client) {\n this.client.end();\n this.client[\"destroy\"]();\n}", | |
| "libs": [ | |
| { | |
| "var": "net", | |
| "module": "net" | |
| } | |
| ], | |
| "x": 900, | |
| "y": 5220, | |
| "wires": [ | |
| [ | |
| "2725b21880fa7406", | |
| "aea19681196029c0" | |
| ] | |
| ] | |
| }, | |
| { | |
| "id": "2725b21880fa7406", | |
| "type": "debug", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "debug 186", | |
| "active": false, | |
| "tosidebar": true, | |
| "console": false, | |
| "tostatus": false, | |
| "complete": "true", | |
| "targetType": "full", | |
| "statusVal": "", | |
| "statusType": "auto", | |
| "x": 1090, | |
| "y": 5280, | |
| "wires": [] | |
| }, | |
| { | |
| "id": "2423ee2b4b84e6f2", | |
| "type": "inject", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "echo(\"test\\nstring\\ntest\\nstringzzzz\");", | |
| "props": [ | |
| { | |
| "p": "payload" | |
| } | |
| ], | |
| "repeat": "", | |
| "crontab": "", | |
| "once": false, | |
| "onceDelay": 0.1, | |
| "topic": "", | |
| "payload": "echo(\"test\\nstring\\ntest\\nstringzzzz\");", | |
| "payloadType": "str", | |
| "x": 540, | |
| "y": 5160, | |
| "wires": [ | |
| [ | |
| "8fee83604ae9f94b" | |
| ] | |
| ] | |
| }, | |
| { | |
| "id": "5c798a02c96d56d3", | |
| "type": "inject", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "isFullScreen();", | |
| "props": [ | |
| { | |
| "p": "payload" | |
| } | |
| ], | |
| "repeat": "", | |
| "crontab": "", | |
| "once": false, | |
| "onceDelay": 0.1, | |
| "topic": "", | |
| "payload": "echo(\"[START]\"); isFullScreen(); echo(\"[END]\");", | |
| "payloadType": "str", | |
| "x": 610, | |
| "y": 5200, | |
| "wires": [ | |
| [ | |
| "8fee83604ae9f94b" | |
| ] | |
| ] | |
| }, | |
| { | |
| "id": "a4d6217fb50a0507", | |
| "type": "inject", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "echo(\"[start eval]\"); echo(\"test\"); echo(\"[end eval]\");", | |
| "props": [ | |
| { | |
| "p": "payload" | |
| } | |
| ], | |
| "repeat": "", | |
| "crontab": "", | |
| "once": false, | |
| "onceDelay": 0.1, | |
| "topic": "", | |
| "payload": "echo(\"[start eval]\"); echo(\"test\\n\\rtest2\\ntest3\\r\\r\\r\\r\\rtest4\"); echo(\"[end eval]\");", | |
| "payloadType": "str", | |
| "x": 490, | |
| "y": 5240, | |
| "wires": [ | |
| [ | |
| "8fee83604ae9f94b" | |
| ] | |
| ] | |
| }, | |
| { | |
| "id": "fde6528ee25bdb01", | |
| "type": "inject", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "$Con::Prompt = \"\";", | |
| "props": [ | |
| { | |
| "p": "payload" | |
| } | |
| ], | |
| "repeat": "", | |
| "crontab": "", | |
| "once": false, | |
| "onceDelay": 0.1, | |
| "topic": "", | |
| "payload": "$Con::Prompt = \"\";", | |
| "payloadType": "str", | |
| "x": 550, | |
| "y": 5280, | |
| "wires": [ | |
| [ | |
| "8fee83604ae9f94b" | |
| ] | |
| ] | |
| }, | |
| { | |
| "id": "0b3cdb6bb0f6f102", | |
| "type": "inject", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "$Con::Prompt = \"\";", | |
| "props": [ | |
| { | |
| "p": "payload" | |
| } | |
| ], | |
| "repeat": "", | |
| "crontab": "", | |
| "once": false, | |
| "onceDelay": 0.1, | |
| "topic": "", | |
| "payload": "$Con::Prompt = \"<input> \";", | |
| "payloadType": "str", | |
| "x": 550, | |
| "y": 5320, | |
| "wires": [ | |
| [ | |
| "8fee83604ae9f94b" | |
| ] | |
| ] | |
| }, | |
| { | |
| "id": "aea19681196029c0", | |
| "type": "switch", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "", | |
| "property": "monitor_aot_logs", | |
| "propertyType": "flow", | |
| "rules": [ | |
| { | |
| "t": "true" | |
| } | |
| ], | |
| "checkall": "true", | |
| "repair": false, | |
| "outputs": 1, | |
| "x": 1110, | |
| "y": 5220, | |
| "wires": [ | |
| [ | |
| "39756dd0b5365a1d" | |
| ] | |
| ] | |
| }, | |
| { | |
| "id": "39756dd0b5365a1d", | |
| "type": "function", | |
| "z": "f740c835e145407e", | |
| "g": "5eb5381789943947", | |
| "name": "Push log line into local memory variable", | |
| "func": "\nlet aot_logs = flow.get(\"aot_logs\");\naot_logs.push(msg.payload.trimEnd());\nflow.set(\"aot_logs\", aot_logs);\nreturn msg;", | |
| "outputs": 1, | |
| "timeout": 0, | |
| "noerr": 0, | |
| "initialize": "", | |
| "finalize": "", | |
| "libs": [], | |
| "x": 1360, | |
| "y": 5220, | |
| "wires": [ | |
| [] | |
| ] | |
| } | |
| ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment