UNPKG

smithtek-nodered

Version:

NodeRED node to post data on SmithTek using MQTT.

137 lines (118 loc) 4.83 kB
const mqtt = require("mqtt"); const fs = require("fs").promises; // Use promise-based fs methods const path = require("path"); function defineOutputObject(topic, message) { let finalValue; let variable = topic; if (topic.endsWith("/lv")) { variable = topic.slice(0, topic.length - 3); } const topicElements = variable.split("/"); variable = topicElements[topicElements.length - 1]; finalValue = parseOutputValue(topic, variable, message); return finalValue; } function parseOutputValue(topic, variable, message) { let finalValue; try { const parsedMessage = JSON.parse(message.toString()); finalValue = topic.endsWith("/lv") ? parsedMessage : parsedMessage[variable] && parsedMessage[variable].value; } catch (err) { console.error("Error parsing message:", err); } return finalValue; } function getSubscribePaths(config) { const paths = []; const labelString = "label_variable_"; const checkboxString = "checkbox_variable_"; const checkboxString2 = "_last_value"; for (let i = 1; i < 11; i++) { const completeLabelString = labelString + i.toString(); const completeCheckboxString = checkboxString + i.toString() + checkboxString2; if (config[completeLabelString]) { let devicePath = `/v1.6/devices/${config.device_label}/${config[completeLabelString]}`; if (config[completeCheckboxString]) { devicePath += "/lv"; } paths.push(devicePath); } } return paths; } module.exports = function (RED) { function SmithTekNode(config) { RED.nodes.createNode(this, config); const ENDPOINTS_URLS = { business: "industrial.api.ubidots.com", }; const useTLS = config.tls_checkbox_in; const endpointUrl = ENDPOINTS_URLS.business; const URL_PREFIX = "mqtt://"; const port = 1883; const portTLS = 8883; const topics = getSubscribePaths(config); this.status({ fill: "green", shape: "ring", text: "Disconnected" }); fs.readFile(path.join(__dirname, "../keys/certificate.pem"), "utf8") .then(certificate => { const client = mqtt.connect(URL_PREFIX + endpointUrl, { username: config.token, password: "", port: useTLS ? portTLS : port, cert: useTLS ? certificate : undefined, protocol: useTLS ? "mqtts" : "mqtt", reconnectPeriod: 10000 }); client.on("connect", () => { this.status({ fill: "green", shape: "dot", text: "Connected" }); const options = { qos: 1 }; client.subscribe(topics, options); }); client.on("message", (topic, message) => { const finalValue = defineOutputObject(topic, message); try { this.emit("input", { payload: finalValue }); } catch (e) { console.error("Error when trying to emit:", e); this.status({ fill: "red", shape: "ring", text: "Disconnected" }); } }); const handleDisconnect = () => { client.unsubscribe(topics); this.status({ fill: "red", shape: "ring", text: "Disconnected" }); }; client.on("close", handleDisconnect); client.on("error", handleDisconnect); client.on("reconnect", handleDisconnect); this.on("error", (msg) => { console.error("SmithTek Client: Inside error function", msg); if (client) { client.end(true); } this.status({ fill: "red", shape: "ring", text: "Disconnected" }); }); this.on("close", () => { if (client) { client.end(true); } }); this.on('input', (msg, send, done) => { try { send(msg); } catch (err) { console.error('Error in client when sending data to debug node,', err); this.error(err, msg); } if (done) { done(); } }); }) .catch(err => { console.error("Error reading certificate:", err); }); } RED.nodes.registerType("smithtek_in", SmithTekNode); };