UNPKG

node-red-contrib-minelert-sensors-smartlink

Version:

Node-RED nodes for Minelert Universal IO Sensors

161 lines (127 loc) 5.78 kB
const { EventBus, logInfo } = require('@minelert-smartlink/common'); module.exports = function(RED) { function LoraLevel(config) { RED.nodes.createNode(this, config); const node = this; const gatewayNode = RED.nodes.getNode(config.gateway); node.devEui = config.devEui; if (!gatewayNode) { node.error("Gateway not configured"); return; } node.log(`Sensor node initialized for DevEUI: ${node.devEui}`); function onChirpstackEvent(mqttMsg) { // node.log(JSON.stringify(mqttMsg)) try { const topicParts = mqttMsg.topic.split('/'); const devEuiFromTopic = topicParts[3]; // "device/DEVEUI" // node.log(`${devEuiFromTopic.toLowerCase()} ${node.devEui.toLowerCase()} ${devEuiFromTopic.toLowerCase() === node.devEui.toLowerCase()}`) if (devEuiFromTopic.toLowerCase() === node.devEui.toLowerCase()) { const rawPayload = mqttMsg.payload?.data; // Base64 string if (!rawPayload) { node.error("No Base64 data found in payload"); return; } const raw = Buffer.from(rawPayload, 'base64').toString('utf-8'); // Split the decoded string const [_, id, value, battery, temperature, txInterval] = raw.split('-'); // Parse values const result = {}; result.value = value === 'FFFF' ? 'Read Error' : value === 'EEEE' ? 'Sensor Fault' : parseInt(value, 10); result.unit = 'mm'; result.error = typeof result.value === 'string'; result.batteryVoltage = parseFloat(battery); result.batteryPercent = Math.round((parseFloat(battery) / 3.3) * 100); result.temperature = temperature; result.txInterval = txInterval; result.devEui = node.devEui; result.rssi = mqttMsg.payload?.rxInfo[0].rssi; // node.log(JSON.stringify(result)) node.send({ topic: `sensor/${node.devEui}/level`, payload: result }); node.status({ fill: "green", shape: "dot", text: `Level: ${result.value}` }); } } catch (err) { node.error("Error processing message: " + err.message); } } // Subscribe to event bus EventBus.on("chirpstack-event", onChirpstackEvent); node.on("close", () => { EventBus.off("chirpstack-event", onChirpstackEvent); }); // Listen to MQTT messages from the gateway // gatewayNode.registerListener((mqttMsg) => { // try { // const topicParts = mqttMsg.topic.split('/'); // const devEuiFromTopic = topicParts[3]; // "device/DEVEUI" // if (devEuiFromTopic.toLowerCase() === node.devEui.toLowerCase()) { // const rawPayload = mqttMsg.payload?.data; // Base64 string // if (!rawPayload) { // node.error("No Base64 data found in payload"); // return; // } // const raw = Buffer.from(rawPayload, 'base64').toString('utf-8'); // // Split the decoded string // const [_, id, value, battery, temperature, txInterval] = raw.split('-'); // // Parse values // const result = {}; // result.value = value === 'FFFF' ? 'Read Error' : // value === 'EEEE' ? 'Sensor Fault' : // parseInt(value, 10); // result.unit = 'mm'; // result.error = typeof result.value === 'string'; // result.batteryVoltage = parseFloat(battery); // result.batteryPercent = Math.round((parseFloat(battery) / 3.2) * 100); // result.temperature = temperature; // result.txInterval = txInterval; // result.devEui = node.devEui; // result.rssi = mqttMsg.payload?.rxInfo[0].rssi; // node.send({ topic: `sensor/${node.devEui}/level`, payload: result }); // // node.log(JSON.stringify(mqttMsg.payload)) // // const devEui = mqttMsg.payload?.devEui; // // if (devEui && devEui === node.devEui) { // // const level = mqttMsg.payload?.object?.level; // // node.send({ // // topic: `sensor/${devEui}/level`, // // payload: { // // level: level, // // timestamp: mqttMsg.payload?.rxInfo?.[0]?.time // // }, // // devEui: devEui // // }); // node.status({ fill: "green", shape: "dot", text: `Level: ${result.value}` }); // } // } catch (err) { // node.error("Error processing message: " + err.message); // } // }); node.on('input', (msg, send, done) => { const ch = msg.channel; const value = msg.payload; if (typeof ch !== 'number' || ch < 0 || ch > 3) { node.error(`Invalid channel: ${ch}`, msg); if (done) done(); return; } node.channelValues[ch] = value; // Log or send to serial/gateway here node.status({ fill: "green", shape: "dot", text: `CH${ch}: ${value}` }); const command = { payload: value, channel: ch, moduleId: moduleId, }; node.log(`Analog Output Command ${JSON.stringify(command)}`); gatewayNode.sendCommand(command); command.topic = `${moduleId}/channel/${ch}`, send(command) if (done) done(); }); node.on('close', () => { node.status({}); }); } RED.nodes.registerType("sn-lora-level", LoraLevel); };