164 lines
5.3 KiB
JavaScript

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);
}
}