const Modbus = require('jsmodbus') var fs = require("fs") const net = require('net') const mqtt = require("mqtt"); const { InfluxDB, Point } = require('@influxdata/influxdb-client') const socket = new net.Socket() const modbusClient = new Modbus.client.TCP(socket, 0); let mqttClient = null; const options = { 'host': '192.168.178.63', 'port': 502 }; let config = null; let influxOrg = 'heatctrlOrg' let influxBucket = 'measurements' const influxUrl = 'http://influxdb:8086' let influxClient = null; let influxWriteClient = null; let inputValues = {}; let configuredInputs = {}; // for reconnecting see node-net-reconnect npm module // use socket.on('open', ...) when using serialport socket.on('connect', function () { // make some calls setInterval(() => { requestTemps(); }, config.interval); }); fs.readFile('config.json', function (err, data) { if (err) { return console.error(err); } else { config = JSON.parse(data.toString()); configuredInputs = config.inputs; configuredInputs.forEach(element => { inputValues[element.label] = { value: null, synced: false, unitConversionDivider: 1 }; }); influxClient = new InfluxDB({ url: influxUrl, token: config.influxToken }); influxWriteClient = influxClient.getWriteApi(influxOrg, influxBucket, 'ms'); socket.connect(options); mqttClient = mqtt.connect(config.mqttBrokerAddress, { username: config.mqttUser, password: config.mqttPassword }); } }); async function dispatchModbus() { //console.log(CF2values); calculateLogic(); writeToInflux(); clearSynced(); } async function clearSynced() { for (const key in inputValues) { if (Object.hasOwnProperty.call(inputValues, key)) { inputValues[key].synced = false; } } } async function requestTemps() { configuredInputs.forEach(element => { modbusClient.readInputRegisters(element.register, (element.type === "u32" | element.type === "s32") ? 2 : 1).then(function (resp) { let value = null; switch (element.type) { case "u32": { value = resp.response._body._valuesAsBuffer.readUInt32BE() / element.unitConversionDivider; } break; case "s32": { value = resp.response._body._valuesAsBuffer.readInt32BE() / element.unitConversionDivider; } break; case "u16": { value = resp.response._body._valuesAsBuffer.readUInt16BE() / element.unitConversionDivider; } break; case "s16": { value = resp.response._body._valuesAsBuffer.readInt16BE() / element.unitConversionDivider; } break; case "bool": { value = resp.response._body._values[0] / element.unitConversionDivider; } break; default: { value = resp.response._body._values[0] / element.unitConversionDivider; } break; } inputValues[element.label] = { value: value, synced: true }; let allSynced = true; /* if (resp.request._body.start === 9169) { console.log(resp); console.log(resp.response._body._values[0]); } */ for (const key in inputValues) { if (Object.hasOwnProperty.call(inputValues, key)) { const element = inputValues[key]; allSynced &= element.synced; } } if (allSynced) { dispatchModbus(); } }, console.error); }); } async function writeToInflux() { for (const key in inputValues) { if (Object.hasOwnProperty.call(inputValues, key)) { let point = new Point('CF2').floatField(key, inputValues[key].value); influxWriteClient.writePoint(point); influxWriteClient.flush(); } } } async function sendMQTT(topic, msg) { let notumschichtung = config.UmschichtungSolar.Notumschichtung if (typeof mqttClient !== 'undefined' || mqttClient !== null) { if (mqttClient.connected) { mqttClient.publish(topic, msg, { retain: true }); console.log(msg); } else { console.log("client not connected to the mqtt broker"); } } else { console.log("mqttClient is undefined or null"); } //send status over mqtt let val = 0.0; if (msg == notumschichtung.mqtt.msgOn) { val = 100.0; } else if (msg == notumschichtung.mqtt.msgOff) { val = 0.0; } let point = new Point('Solarumschichtung').floatField("pumpePercent", val); influxWriteClient.writePoint(point); influxWriteClient.flush(); } async function calculateLogic() { let notumschichtung = config.UmschichtungSolar.Notumschichtung let temp = inputValues[notumschichtung.Temperaturlabel]; let topic = notumschichtung.mqtt.ctrlTopic; let msgOn = notumschichtung.mqtt.msgOn; let msgOff = notumschichtung.mqtt.msgOff; let Ton = notumschichtung.Ton; let Toff = notumschichtung.Toff; if (temp.value >= Ton) { sendMQTT(topic, msgOn); } else if (temp.value <= Toff) { sendMQTT(topic, msgOff); } }