207 lines
7.1 KiB
JavaScript
207 lines
7.1 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 () {
|
|
|
|
console.log("socket connected starting interval timer");
|
|
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 };
|
|
});
|
|
console.log("config read");
|
|
console.log("now connecting to influxdb");
|
|
influxClient = new InfluxDB({ url: influxUrl, token: config.influxToken });
|
|
influxWriteClient = influxClient.getWriteApi(influxOrg, influxBucket, 'ms');
|
|
console.log("connected to influxdb, now trying to connect to modbus tcp and mqtt");
|
|
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 mqttConfig = config.UmschichtungSolar.mqtt;
|
|
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 == mqttConfig.msgOn) {
|
|
val = 100.0;
|
|
} else if (msg == mqttConfig.msgOff) {
|
|
val = 0.0;
|
|
}
|
|
let point = new Point('Solarumschichtung').floatField("pumpePercent", val);
|
|
influxWriteClient.writePoint(point);
|
|
influxWriteClient.flush();
|
|
}
|
|
let outputRegler1 = false;
|
|
let outputRegler2 = false;
|
|
async function calculateLogic() {
|
|
//Notumschichtung regler 1
|
|
let umschichtungSolar = config.UmschichtungSolar;
|
|
let notumschichtung = umschichtungSolar.Notumschichtung
|
|
let temptNotumschichtung = inputValues[notumschichtung.Temperaturlabel].value;
|
|
let TonNotumschichtung = notumschichtung.Ton;
|
|
let ToffNotumschichtung = notumschichtung.Toff;
|
|
|
|
//mqtt relais
|
|
//console.log(umschichtungSolar);
|
|
let topic = umschichtungSolar.mqtt.ctrlTopic;
|
|
|
|
let msgOn = umschichtungSolar.mqtt.msgOn;
|
|
let msgOff = umschichtungSolar.mqtt.msgOff;
|
|
|
|
//Differenzregelung
|
|
let differenzregelung = umschichtungSolar.Differenzregelung
|
|
let quellTemperatur = inputValues[differenzregelung.QuelltemperaturLabel].value;
|
|
let zielTemperatur = inputValues[differenzregelung.ZieltemperaturLabel].value;
|
|
let dTon = differenzregelung.dTon;
|
|
let dToff = differenzregelung.dToff;
|
|
|
|
//Freigabe Holzofen
|
|
let kesselstatus = inputValues["Kesselstatus"].value;
|
|
let freigabeHolzofen = kesselstatus === umschichtungSolar.FreigabeHolzofen.KesselstatusAus ? true : false;
|
|
|
|
if (temptNotumschichtung >= TonNotumschichtung) {
|
|
outputRegler1 = true;
|
|
|
|
} else if (temptNotumschichtung <= ToffNotumschichtung) {
|
|
outputRegler1 = false;
|
|
}
|
|
|
|
let diff = quellTemperatur - zielTemperatur;
|
|
if(diff >= dTon){
|
|
outputRegler2 = true;
|
|
}else if (diff <= dToff) {
|
|
outputRegler2 = false;
|
|
}
|
|
|
|
let point = new Point('Solarumschichtung').floatField("regler1", outputRegler1 ? 100.0 : 0.0);
|
|
influxWriteClient.writePoint(point);
|
|
point = new Point('Solarumschichtung').floatField("regler2", outputRegler2 ? 100.0 : 0.0);
|
|
influxWriteClient.writePoint(point);
|
|
point = new Point('Solarumschichtung').floatField("freigabeHolzofen", freigabeHolzofen ? 100.0 : 0.0);
|
|
influxWriteClient.writePoint(point);
|
|
influxWriteClient.flush();
|
|
|
|
if(freigabeHolzofen && outputRegler1 && outputRegler2){
|
|
sendMQTT(topic, msgOn);
|
|
}else{
|
|
sendMQTT(topic, msgOff);
|
|
}
|
|
}
|
|
|