sokolov-sbs-flowserver/flow/particulatesensor.js
2025-08-07 21:49:01 +02:00

267 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

exports.id = 'particulatesensor';
exports.title = 'Particulate sensor';
exports.group = 'Worksys';
exports.color = '#5CB36D';
exports.version = '1.0.0';
exports.output = ["red", "white"];
exports.author = 'Rastislav Kovac';
exports.icon = 'atom';
exports.readme = `# PM sensor`;
/*
tento command zapne senzor zo stavu idle do stavu Meranie
rsPort.write([0x7E, 0x00, 0x00, 0x02, 0x01, 0x03, 0xF9, 0x7E]
tento command vypne senzor do stavu idle
rsPort.write([0x7E, 0x00, 0x01, 0x00, 0xFE, 0x7E]
tento command cita namerane data zo senzora
rsPort.write([0x7E, 0x00, 0x03, 0x00, 0xFC, 0x7E]
*/
const conversionTable = {
1: "pm1_0",
2: "pm2_5",
3: "pm4_0",
4: "pm10"
// 1: "Mass concentration PM1.0",
// 2: "Mass concentration PM2.5",
// 3: "Mass concentration PM4.0",
// 4: "Mass concentration PM10",
// 5: "Number concentration PM0.5",
// 6: "Number concentration PM1.0",
// 7: "Number concentration PM2.5",
// 8: "Number concentration PM4.0",
// 9: "Number concentration PM10",
// 10: "Typical Particle size",
}
exports.install = function(instance) {
const fs = require("fs");
const SerialPort = require('serialport');
const { exec } = require('child_process');
let rsPort = null;
let startToGetData = null;
const tbName = "mp93b2nvd7OoqgBeEyE7N18kjlAV1Y4ZNXwW0zLG";
function writeToFile(data)
{
try {
if (fs.existsSync("err.txt")) {
let stats = fs.statSync("err.txt")
let fileSizeInBytes = stats.size;
if(fileSizeInBytes > 20000000)
{
fs.unlinkSync("err.txt");
// file deleted
}
}
} catch(err) {
console.error(err)
}
fs.writeFile("err.txt", data, {flag: "a"},function (err,data) {
if (err) {
return console.log(err);
}
console.log(data);
});
}
function startRsPort()
{
rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false });
rsPort.on('open', function() {
exec("stty -F /dev/ttyUSB0 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke", (error, stdout, stderr) => {
//exec("stty -F /dev/ttyUSB0 115200 min 1 time 5 cs8 -cstopb ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke", (error, stdout, stderr) => {
instance.send(0,{"stdout":stdout,"stderr":stderr,"err":error});
instance.send(0, exports.title + " RS USB port is set");
});
setStateToMeasurement();
})
rsPort.on('error', function(err) {
instance.send(0, err.message);
let d = new Date();
writeToFile(`${d}, ${err}`);
})
rsPort.on("close", () => {
clearInterval(startToGetData);
rsPort.close();
instance.send(0, exports.title + " RS USB port is closed now ---> reopenning in 30 seconds");
writeToFile(`${d}, RS USB port is closed now ---> reopenning in 30 seconds`);
rsPort = null;
setTimeout(startRsPort, 30000);
})
/*
RECEIVED BYTES
Byte 1 0x7E start
Byte 2 0x00 adresa
Byte 3 0x03 cmd
Byte 4 0x00 state podľa obr.2
Byte 5 0x28 počet prijatých dátových bytov
Na konci 0xD4 CRC
Na konci 0x7E stop
STATE STATUS
0 - 0x00 No error
1 - 0x01 Wrong data length for this command (too much or little data)
2 - 0x02 Unknown command
3 - 0x03 No access right for command
4 - 0x04 Illegal command parameter or parameter out of allowed range
40 - 0x28 Internal function argument out of range
67 - 0x43 Command not allowed in current state
*/
let rsPortReceivedData = [];
let measuredValues;
rsPort.on("data", function(data) {
//console.log("rsPort data function called")
data = JSON.stringify(data);
try {
data = JSON.parse(data);
} catch(err) {
console.log("[Particulate Sensor] - unable to convert data to JSON");
return;
}
// array of received bytes
data = data.data;
rsPortReceivedData = [...rsPortReceivedData, ...data];
//console.log("----rsportALLDATA", rsPortReceivedData);
if (rsPortReceivedData[0] != 126) {
rsPortReceivedData = [];
return;
}
if (rsPortReceivedData[rsPortReceivedData.length - 1] != 126) return;
if (rsPortReceivedData.length === 7) {
if (rsPortReceivedData[2] === 0){
instance.send(0, "Particulate sensor is in Measurement-Mode now");
rsPortReceivedData = [];
return;
}
}
// convert special characters to single byte
rsPortReceivedData = rsPortReceivedData.toString();
rsPortReceivedData = rsPortReceivedData.replace(/125,94/g, "126");
rsPortReceivedData = rsPortReceivedData.replace(/125,93/g, "125");
rsPortReceivedData = rsPortReceivedData.replace(/125,51/g, "19");
rsPortReceivedData = rsPortReceivedData.replace(/125,49/g, "17");
rsPortReceivedData = rsPortReceivedData.split(",");
//we only take measured values from received data
measuredValues = rsPortReceivedData.slice(5, rsPortReceivedData.length-2);
//console.log(measuredValues);
let l = measuredValues.length;
//console.log("length----", l);
let i, j, temparray, counter = 0, chunk = 4;
for ( i = 0, j = l; i < j; i += chunk ) {
counter++;
temparray = measuredValues.slice(i, i + chunk);
convertDatabytesToFloat(temparray, conversionTable[counter]);
}
counter = 0;
rsPortReceivedData = [];
})
rsPort.open();
}
function convertDatabytesToFloat(array, type) {
//console.log("----", array);
if(array.length < 4 || type == undefined) return;
let result = Buffer.from(array).readFloatBE(0);
result = parseFloat(result.toFixed(4));
//console.log(result, typeof result)
let dataToTb = {
[tbName]: [
{
"ts": Date.now(),
"values": {
[type]: result
}
}
]
}
instance.send(1, dataToTb);
}
// get data from PM sensor
function getMeasurements() {
rsPort.write([0x7E, 0x00, 0x03, 0x00, 0xFC, 0x7E], function(err) {
if(err){
return console.log('[Particulate Sensor] - Error on write: ', err.message)
}
instance.send(0, "Getting data from PM sensor");
})
}
// we set the state of sensor to start to measure
function setStateToMeasurement() {
rsPort.write([0x7E, 0x00, 0x00, 0x02, 0x01, 0x03, 0xF9, 0x7E], function(err) {
if(err){
return console.log('[Particulate Sensor] - Error on write: ', err.message)
}
instance.send(0, "PM sensor state set to measure");
})
}
instance.on("close", function() {
clearInterval(startToGetData);
rsPort.close();
});
setTimeout(startRsPort, 10000);
startToGetData = setInterval(getMeasurements, 300000);
};