Initial commit - testing version

This commit is contained in:
rasta5man 2025-08-08 16:53:33 +02:00
parent cf16481324
commit 06b289d7a3
11 changed files with 6636 additions and 3819 deletions

View file

@ -27,8 +27,6 @@ exports.html = `<div class="padding">
</div> </div>
</div>`; </div>`;
const { promisifyBuilder } = require('./helper/db_helper'); const { promisifyBuilder } = require('./helper/db_helper');
const fs = require('fs'); const fs = require('fs');
const mqtt = require('mqtt'); const mqtt = require('mqtt');
@ -56,7 +54,6 @@ let lastRestoreTime = 0;
// if there is an error in client connection, flow logs to monitor.txt. Not to log messages every second, we use sendClientError variable // if there is an error in client connection, flow logs to monitor.txt. Not to log messages every second, we use sendClientError variable
let sendClientError = true; let sendClientError = true;
exports.install = function(instance) { exports.install = function(instance) {
var client; var client;
@ -65,17 +62,15 @@ exports.install = function(instance) {
let o = null; //options let o = null; //options
function main() function main() {
{
loadSettings(); loadSettings();
} }
//set opts according to db settings //set opts according to db settings
function loadSettings() function loadSettings() {
{
o = instance.options; o = instance.options;
if(!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic; if (!o.topic) o.topic = FLOW.GLOBALS.settings.cloud_topic;
opts = { opts = {
host: o.host, host: o.host,
@ -86,13 +81,12 @@ exports.install = function(instance) {
resubscribe: false resubscribe: false
}; };
console.log("wsmqttpublich -> loadSettings from instance.options",o); console.log("wsmqttpublich -> loadSettings from instance.options", o);
connectToTbServer(); connectToTbServer();
} }
function connectToTbServer() function connectToTbServer() {
{
var url = "mqtt://" + opts.host + ":" + opts.port; var url = "mqtt://" + opts.host + ":" + opts.port;
console.log("MQTT URL: ", url); console.log("MQTT URL: ", url);
@ -118,31 +112,31 @@ exports.install = function(instance) {
// message is type of buffer // message is type of buffer
message = message.toString(); message = message.toString();
if (message[0] === '{') { if (message[0] === '{') {
TRY(function() {
try {
message = JSON.parse(message); message = JSON.parse(message);
if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) {
client.publish(`${o.topic}_forward`, `{"device": "${message.device}", "id": ${message.data.id}, "data": {"success": true}}`, {qos:1}); client.publish(`${o.topic}_forward`, `{"device": "${message.device}", "id": ${message.data.id}, "data": {"success": true}}`, { qos: 1 });
instance.send(SEND_TO.rpcCall, {"device": message.device, "id": message.data.id, "RPC response": {"success": true}}); instance.send(SEND_TO.rpcCall, { "device": message.device, "id": message.data.id, "RPC response": { "success": true } });
} }
} catch (e) { instance.debug('MQTT: Error parsing data', message) }
}, () => instance.debug('MQTT: Error parsing data', message)); instance.send(SEND_TO.rpcCall, { "topic": o.topic, "content": message });
} }
instance.send(SEND_TO.rpcCall, {"topic":o.topic, "content":message });
}); });
client.on('close', function() { client.on('close', function() {
clientReady = false; clientReady = false;
instance.status("Disconnected", "red"); instance.status("Disconnected", "red");
instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !"}); instance.send(SEND_TO.debug, { "message": "Client CLOSE signal received !" });
}); });
client.on('error', function(err) { client.on('error', function(err) {
instance.status("Err: "+ err.code, "red"); instance.status("Err: " + err.code, "red");
instance.send(SEND_TO.debug, {"message":"Client ERROR signal received !", "error":err, "opt":opts }); instance.send(SEND_TO.debug, { "message": "Client ERROR signal received !", "error": err, "opt": opts });
if(sendClientError) { if (sendClientError) {
console.log('MQTT client error', err); console.log('MQTT client error', err);
sendClientError = false; sendClientError = false;
} }
@ -154,25 +148,21 @@ exports.install = function(instance) {
instance.on('0', function(data) { instance.on('0', function(data) {
if(clientReady) if (clientReady) {
{
//do we have some data in backup file? if any, process data from database //do we have some data in backup file? if any, process data from database
if(saveTelemetryOnError) if (saveTelemetryOnError) {
{
//read telemetry data and send back to server //read telemetry data and send back to server
if(!processingData) processDataFromDatabase(); if (!processingData) processDataFromDatabase();
} }
let stringifiedJson = JSON.stringify(data.data) let stringifiedJson = JSON.stringify(data.data)
client.publish(`${o.topic}_forward`, stringifiedJson, {qos: 1}); client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 });
} }
else else {
{
//logger.debug("Client unavailable. Data not sent !", JSON.stringify(data.data)); //logger.debug("Client unavailable. Data not sent !", JSON.stringify(data.data));
instance.send(SEND_TO.debug, {"message":"Client unavailable. Data not sent !", "data": data.data }); instance.send(SEND_TO.debug, { "message": "Client unavailable. Data not sent !", "data": data.data });
if(saveTelemetryOnError) if (saveTelemetryOnError) {
{
//create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql //create new file from tbdata.nosql, if file size exceeds given limit, and clear tbdata.nosql
makeBackupFromDbFile(); makeBackupFromDbFile();
@ -188,49 +178,41 @@ exports.install = function(instance) {
}) })
instance.close = function(done) { instance.close = function(done) {
if(clientReady){ if (clientReady) {
client.end(); client.end();
} }
}; };
function getDbBackupFileCounter(type) function getDbBackupFileCounter(type) {
{
var files = fs.readdirSync(__dirname + "/../databases"); var files = fs.readdirSync(__dirname + "/../databases");
let counter = 0; let counter = 0;
for(var i = 0; i < files.length; i++) for (var i = 0; i < files.length; i++) {
{
if(files[i] == "tbdatacloud.nosql") continue; if (files[i] == "tbdatacloud.nosql") continue;
if(files[i].endsWith(".nosql")) if (files[i].endsWith(".nosql")) {
{
let pos = files[i].indexOf("."); let pos = files[i].indexOf(".");
if(pos > -1) if (pos > -1) {
{
let fileCounter = counter; let fileCounter = counter;
let firstDigit = files[i].slice(0, pos); let firstDigit = files[i].slice(0, pos);
fileCounter = parseInt(firstDigit); fileCounter = parseInt(firstDigit);
if(isNaN(fileCounter)) fileCounter = 0; if (isNaN(fileCounter)) fileCounter = 0;
//console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type);
if(type == "max") if (type == "max") {
{ if (fileCounter > counter) {
if(fileCounter > counter)
{
counter = fileCounter; counter = fileCounter;
} }
} }
else if(type == "min") else if (type == "min") {
{ if (counter == 0) counter = fileCounter;
if(counter == 0) counter = fileCounter;
if(fileCounter < counter) if (fileCounter < counter) {
{
counter = fileCounter; counter = fileCounter;
} }
} }
@ -239,20 +221,19 @@ exports.install = function(instance) {
} }
if(type == "max") counter++; if (type == "max") counter++;
return counter; return counter;
} }
const makeBackupFromDbFile = async () => { const makeBackupFromDbFile = async () => {
if(!saveTelemetryOnError) return; if (!saveTelemetryOnError) return;
//to avoid large file: tbdata.nosql //to avoid large file: tbdata.nosql
//init value is 0! //init value is 0!
if(insertNoSqlCounter > 0) if (insertNoSqlCounter > 0) {
{
--insertNoSqlCounter; --insertNoSqlCounter;
return; return;
} }
@ -264,8 +245,7 @@ exports.install = function(instance) {
var stats = fs.statSync(source); var stats = fs.statSync(source);
var fileSizeInBytes = stats.size; var fileSizeInBytes = stats.size;
if(fileSizeInBytes > noSqlFileSizeLimit) if (fileSizeInBytes > noSqlFileSizeLimit) {
{
let counter = 1; let counter = 1;
counter = getDbBackupFileCounter("max"); counter = getDbBackupFileCounter("max");
@ -285,15 +265,14 @@ exports.install = function(instance) {
const processDataFromDatabase = async () => { const processDataFromDatabase = async () => {
if(restore_from_backup <= 0) return; if (restore_from_backup <= 0) return;
//calculate diff //calculate diff
const now = new Date(); const now = new Date();
let currentTime = now.getTime(); let currentTime = now.getTime();
let diff = currentTime - lastRestoreTime; let diff = currentTime - lastRestoreTime;
if( (diff / 1000) < restore_backup_wait) if ((diff / 1000) < restore_backup_wait) {
{
//console.log("*********restore_backup_wait", diff, restore_backup_wait); //console.log("*********restore_backup_wait", diff, restore_backup_wait);
return; return;
} }
@ -307,7 +286,7 @@ exports.install = function(instance) {
let dataBase = 'tbdata'; let dataBase = 'tbdata';
var nosql; var nosql;
if(counter == 0) dataBase = 'tbdatacloud'; if (counter == 0) dataBase = 'tbdatacloud';
else dataBase = counter + "." + 'tbdatacloud'; else dataBase = counter + "." + 'tbdatacloud';
nosql = NOSQL(dataBase); nosql = NOSQL(dataBase);
@ -315,27 +294,25 @@ exports.install = function(instance) {
//select all data - use limit restore_from_backup //select all data - use limit restore_from_backup
let records = await promisifyBuilder(nosql.find().take(restore_from_backup)); let records = await promisifyBuilder(nosql.find().take(restore_from_backup));
for(let i = 0; i < records.length; i++) for (let i = 0; i < records.length; i++) {
{ if (clientReady) {
if(clientReady) {
let item = records[i]; let item = records[i];
let id = item.id; let id = item.id;
if(id !== undefined) if (id !== undefined) {
{
//console.log("------------processDataFromDatabase - remove", id, dataBase, i); //console.log("------------processDataFromDatabase - remove", id, dataBase, i);
try { try {
let message = JSON.parse(JSON.stringify(item)); let message = JSON.parse(JSON.stringify(item));
delete message.id; delete message.id;
client.publish(`${o.topic}_forward`, JSON.stringify(message), {qos:1}); client.publish(`${o.topic}_forward`, JSON.stringify(message), { qos: 1 });
//remove from database //remove from database
await promisifyBuilder(nosql.remove().where("id", id)); await promisifyBuilder(nosql.remove().where("id", id));
} catch(error) { } catch (error) {
//process error //process error
console.log("processDataFromDatabase", error); console.log("processDataFromDatabase", error);
} }
@ -343,23 +320,20 @@ exports.install = function(instance) {
} }
} }
else else {
{
processingData = false; processingData = false;
return; return;
} }
} }
if(records.length > 0) if (records.length > 0) {
{
//clean backup file //clean backup file
if(counter > 0) nosql.clean(); if (counter > 0) nosql.clean();
} }
//no data in db, remove //no data in db, remove
if(records.length == 0) if (records.length == 0) {
{ if (counter > 0) nosql.drop();
if(counter > 0) nosql.drop();
} }
const d = new Date(); const d = new Date();

View file

@ -30,7 +30,7 @@ exports.readme = `Manager for CMD calls`;
exports.install = function(instance) { exports.install = function(instance) {
const SerialPort = require('serialport'); const { SerialPort } = require('serialport');
const { exec } = require('child_process'); const { exec } = require('child_process');
const { crc16 } = require('easy-crc'); const { crc16 } = require('easy-crc');
const { runSyncExec, writeData } = require('./helper/serialport_helper'); const { runSyncExec, writeData } = require('./helper/serialport_helper');
@ -104,29 +104,29 @@ exports.install = function(instance) {
let priorities = []; let priorities = [];
let minutes = 1; let minutes = 1;
priorities["1"] = minutes; // dimming priorities["1"] = minutes;
priorities["76"] = minutes; // power priorities["76"] = minutes;
minutes = 5; // minutes = 5;
priorities["75"] = minutes; // current priorities["75"] = minutes;//current
priorities["79"] = minutes; // energy priorities["79"] = minutes;//energy
priorities["87"] = minutes; // aktualny cas priorities["87"] = minutes;//aktualny cas
//priorities["84"] = minutes; //priorities["84"] = minutes;
minutes = 10; // minutes = 10;
priorities["74"] = minutes; // voltage priorities["74"] = minutes;
priorities["77"] = minutes; // power factor priorities["77"] = minutes;
priorities["78"] = minutes; // frequency priorities["78"] = minutes;
minutes = 60; // minutes = 60;
priorities["0"] = minutes; // statecode priorities["0"] = minutes;
priorities["6"] = minutes; // dusk priorities["6"] = minutes;
priorities["7"] = minutes; // dawn priorities["7"] = minutes;
priorities["8"] = minutes; // profile priorities["8"] = minutes;
minutes = 60 * 24; // minutes = 60 * 24;
priorities["89"] = minutes; // verzia fw priorities["89"] = minutes;
priorities["80"] = minutes; // lifetime priorities["80"] = minutes;
//prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming)
let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89]; let listOfCommands = [0, 1, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 87, 89];
@ -168,7 +168,7 @@ exports.install = function(instance) {
tbHandler.setSender(exports.title); tbHandler.setSender(exports.title);
let now = new Date(); let now = new Date();
console.log("Cmd-mngr installed", now.toLocaleString("sk-SK")); console.log("CMD Manager installed", now.toLocaleString("sk-SK"));
sunCalcResult = calculateDuskDawn(); sunCalcResult = calculateDuskDawn();
@ -230,7 +230,7 @@ exports.install = function(instance) {
} }
params.addMinutesToTimestamp = 0;//repeat task if value is > 0 params.addMinutesToTimestamp = 0;//repeat task if value is > 0
// if node regular readout does not respond, we repeat request //if node regular readout does not respond, we repeat request
params.repeatCounter = 0; params.repeatCounter = 0;
//params.timePointName = "luxOff" // "luxOn", "dusk", "dawn", "profileTimepoint" //params.timePointName = "luxOff" // "luxOn", "dusk", "dawn", "profileTimepoint"
//params.info = ""; //params.info = "";
@ -267,7 +267,7 @@ exports.install = function(instance) {
try { try {
nodeProfile = JSON.parse(nodeProfile); nodeProfile = JSON.parse(nodeProfile);
} catch (error) { } catch (error) {
logger.debug("Cmd-mngr: Error parsing node profile", error); logger.debug("Cmd_manager - Error parsing node profile", error);
} }
} }
@ -753,7 +753,7 @@ exports.install = function(instance) {
function reportOfflineNodeStatus(line) { function reportOfflineNodeStatus(line) {
logger.info("Cmd-mngr: ------>reportOffLineNodeStatus for line ", line); logger.debug("Cmd-mngr: ------>reportOfflineNodeStatus for line", line);
values = {}; values = {};
values["dimming"] = 0;//brightness values["dimming"] = 0;//brightness
@ -780,7 +780,7 @@ exports.install = function(instance) {
sendTelemetry({ ...values }, tbname, date); sendTelemetry({ ...values }, tbname, date);
} }
}); })
} }
@ -797,6 +797,7 @@ exports.install = function(instance) {
} }
function detectIfResponseIsValid(bytes) { function detectIfResponseIsValid(bytes) {
//ak sa odpoved zacina 0 - je to v poriadku, inak je NOK //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK
let type = "RESPONSE"; let type = "RESPONSE";
@ -1035,7 +1036,7 @@ exports.install = function(instance) {
} catch (error) { } catch (error) {
if (profilestr !== "") { if (profilestr !== "") {
//errLogger.error(profilestr, error); //errLogger.error(profilestr, error);
console.log(`Cmd_mngr: Unable to process line profile ${line}. Error: `, error); console.log(`Cmd_manager: Unable to process line profile ${line}. Error: `, error);
errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error");
} else { } else {
turnLine("off", line, "No line profile. Switching it off on startup"); turnLine("off", line, "No line profile. Switching it off on startup");
@ -1300,13 +1301,11 @@ exports.install = function(instance) {
function nodeDbStatusModify(node, data) { function nodeDbStatusModify(node, data) {
dbNodes.modify(data).where("node", node).make(function(builder) { dbNodes.modify(data).where("node", node).callback(function(err, response) {
builder.callback(function(err, response) {
if (!err) { if (!err) {
nodesData[node] = { ...nodesData[node], ...data }; nodesData[node] = { ...nodesData[node], ...data };
} }
}); });
});
} }
@ -1322,7 +1321,7 @@ exports.install = function(instance) {
if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) { if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) {
//reportovali sme? //reportovali sme?
if (reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) { if (reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) {
//sendNotification("Cmd-mngr: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance); //sendNotification("CMD Manager: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance);
reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time;
} }
} }
@ -1339,7 +1338,7 @@ exports.install = function(instance) {
if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) { if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) {
//reportovali sme? //reportovali sme?
if (reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) { if (reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) {
//sendNotification(": calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance); //sendNotification("CMD Manager: calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance);
reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time;
} }
} }
@ -1370,7 +1369,7 @@ exports.install = function(instance) {
if (!rsPort.isOpen) { if (!rsPort.isOpen) {
instance.send(SEND_TO.debug, "!rsPort.isOpen"); instance.send(SEND_TO.debug, "!rsPort.isOpen");
//await rsPort.open(); //await rsPort.open();
//console.log("Cmd-mngr: !rsPort.isOpen"); //console.log("Cmd_manager - !rsPort.isOpen");
} }
let currentTask = tasks[0]; let currentTask = tasks[0];
@ -1391,6 +1390,7 @@ exports.install = function(instance) {
let type = params.type; let type = params.type;
let tbname = params.tbname; let tbname = params.tbname;
let node = params.address; let node = params.address;
let register = params.register; let register = params.register;
let line = null; let line = null;
let itIsNodeCommand; let itIsNodeCommand;
@ -1476,7 +1476,7 @@ exports.install = function(instance) {
} }
// TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors // TODO: -> status offline for rvo if rotary_switch_state is OFF, this is source of errors
// check if rotary_switch_state == "Off" //check if rotary_switch_state == "Off"
// state_of_braker: disconnected = true? // state_of_braker: disconnected = true?
if (!rsPort.isOpen) { if (!rsPort.isOpen) {
@ -1529,7 +1529,7 @@ exports.install = function(instance) {
// await keyword is important, otherwise incorrect data is returned! // await keyword is important, otherwise incorrect data is returned!
await writeData(rsPort, resp, readBytes, timeout).then(function(data) { await writeData(rsPort, resp, readBytes, timeout).then(function(data) {
//sometimes happens, that status of node changes to OK, NOK even if line was turned off and should be status OFFLINE. To prevent this, we return if line contactor is 0: //sometimes happens, that status of node changes even if line was turned off and should be offline. To prevent this, we return if line contactor is 0:
if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return; if (itIsNodeCommand && line && relaysData[line].contactor !== 1) return;
endTime = new Date(); endTime = new Date();
@ -1539,6 +1539,7 @@ exports.install = function(instance) {
let dataBytes = data.slice(5, 9); let dataBytes = data.slice(5, 9);
let result = detectIfResponseIsValid(data); let result = detectIfResponseIsValid(data);
if(register === 79) console.log("node responsee: ", dataBytes);
//ak sa odpoved zacina 0 - je to v poriadku, inak je NOK //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK
let message = result.message; // OK, NOK let message = result.message; // OK, NOK
let message_type = result.type; let message_type = result.type;
@ -1561,22 +1562,21 @@ exports.install = function(instance) {
if (type == "set_node_profile") { if (type == "set_node_profile") {
let result = cmdCounterResolve(node); let result = cmdCounterResolve(node);
if (result == 0) { if (result == 0) {
dbNodes.modify({ processed: true }).where("node", node).make(function(builder) { dbNodes.modify({ processed: true }).where("node", node).callback(function(err, response) {
builder.callback(function(err, response) {
sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance); sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: node }, "", SEND_TO.tb, instance);
logger.debug("--> profil úspešne odoslaný na node č. " + node); logger.debug("--> profil úspešne odoslaný na node č. " + node);
nodesData[node].processed = true; nodesData[node].processed = true;
nodeProfileSendFail.delete(node); nodeProfileSendFail.delete(node);
}); });
});
} }
} }
//parse read response //parse read response
if (params.rw == 0) { if (params.rw == 0) {
values = processResponse(register, dataBytes); //read values = processResponse(register, dataBytes); //read
console.log("command params: ", params.address, register);
} }
if (itIsNodeCommand) { if (itIsNodeCommand) {
@ -1587,7 +1587,7 @@ exports.install = function(instance) {
//master node //master node
if (node == 0) { if (node == 0) {
sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status"); sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status");
SETTINGS.masterNodeIsResponding = true; SETTINGS.masterNodeIsResponding = true;
if (register == 4) values["edge_fw_version"] = SETTINGS.edge_fw_version; if (register == 4) values["edge_fw_version"] = SETTINGS.edge_fw_version;
} }
@ -1607,6 +1607,7 @@ exports.install = function(instance) {
} }
else { else {
terminalCommandResponse(params, "ERROR", data); terminalCommandResponse(params, "ERROR", data);
handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb);
@ -1650,16 +1651,6 @@ exports.install = function(instance) {
} }
// if node does not respond to request, we repeat request 3 times:
function repeatCommand(params) {
params.repeatCounter++;
if (params.repeatCounter < 4) {
params.timestamp = 0;
params.addMinutesToTimestamp = 0;
tasks.push(params);
}
}
function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) {
let node = params.address; let node = params.address;
@ -1675,7 +1666,6 @@ exports.install = function(instance) {
if (itIsNodeCommand) { if (itIsNodeCommand) {
values.comm_status = "NOK"; values.comm_status = "NOK";
nodesData[node].readout.comm_status = "NOK"; nodesData[node].readout.comm_status = "NOK";
repeatCommand(params);
} }
if (updateStatus) { if (updateStatus) {
@ -1687,7 +1677,7 @@ exports.install = function(instance) {
//master node //master node
if (node == 0) { if (node == 0) {
sendNotification("Cmd-mngr: process cmd", SETTINGS.rvoTbName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status");
logger.debug("master_node_is_not_responding", params); logger.debug("master_node_is_not_responding", params);
SETTINGS.masterNodeIsResponding = false; SETTINGS.masterNodeIsResponding = false;
@ -1699,7 +1689,7 @@ exports.install = function(instance) {
logger.debug("profil nebol úspešne odoslaný na node č. ", params); logger.debug("profil nebol úspešne odoslaný na node č. ", params);
if (!nodeProfileSendFail.has(node)) { if (!nodeProfileSendFail.has(node)) {
sendNotification("Cmd-mngr: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance);
nodeProfileSendFail.add(node); nodeProfileSendFail.add(node);
} }
} }
@ -1711,7 +1701,6 @@ exports.install = function(instance) {
} }
function sendNodesData() { function sendNodesData() {
Object.keys(nodesData).forEach(node => { Object.keys(nodesData).forEach(node => {
if (nodesData[node]["status"] !== "OFFLINE") { if (nodesData[node]["status"] !== "OFFLINE") {
@ -1733,6 +1722,9 @@ exports.install = function(instance) {
//console.log("params.refFlowdataKey is undefined", params); //console.log("params.refFlowdataKey is undefined", params);
return; return;
} }
else {
console.log("params.refFlowdataKey: ", params);
}
let message = null; let message = null;
let type = null; let type = null;
@ -1755,6 +1747,7 @@ exports.install = function(instance) {
} }
logger.debug(message); logger.debug(message);
logger.debug(params);
//make http response //make http response
let responseObj = {} let responseObj = {}
@ -1813,23 +1806,22 @@ exports.install = function(instance) {
function handleRsPort() { function handleRsPort() {
if (rsPort) { console.log("cmd_man: handleRsPort called");
rsPort.removeAllListeners();
rsPort = null;
}
//! rsPort LM = "/dev/ttymxc4", rsPort UNIPI = "/dev/ttyUSB0" //! rsPort LM = "/dev/ttymxc4", rsPort UNIPI = "/dev/ttyUSB0"
// const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM // const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM
// const rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false }); // UNIPI // const rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false }); // UNIPI
if (SETTINGS.serial_port == "" || SETTINGS.serial_port == undefined || SETTINGS.serial_port.length === 1) SETTINGS.serial_port = "ttymxc4"; if (SETTINGS.serial_port == "" || SETTINGS.serial_port == undefined || SETTINGS.serial_port.length === 1) SETTINGS.serial_port = "ttymxc4";
rsPort = new SerialPort(`/dev/${SETTINGS.serial_port}`, { autoOpen: false }); console.log('SETTINGS.serial_port', SETTINGS.serial_port);
//rsPort = new SerialPort({path: `/dev/${SETTINGS.serial_port}`, baudRate: 57600, autoOpen: false });
rsPort = new SerialPort({ path: "/dev/ttyUSB0", baudRate: 9600, autoOpen: false });
//(node:16372) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 13 data listeners added to [SerialPort]. Use emitter.setMaxListeners() to increase limit //(node:16372) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 13 data listeners added to [SerialPort]. Use emitter.setMaxListeners() to increase limit
//rsPort.setMaxListeners(0); //rsPort.setMaxListeners(0);
rsPort.on('open', async function() { rsPort.on('open', async function() {
logger.debug("Cmd-mngr: rsPort opened success"); logger.debug("CMD manager - rsPort opened success");
console.log("CMD manager - rsPort opened success");
await runSyncExec(`stty -F /dev/${SETTINGS.serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function(status) { await runSyncExec(`stty -F /dev/${SETTINGS.serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function(status) {
instance.send(SEND_TO.debug, "RPC runSyncExec - Promise Resolved:" + status); instance.send(SEND_TO.debug, "RPC runSyncExec - Promise Resolved:" + status);
@ -1837,21 +1829,28 @@ exports.install = function(instance) {
logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status); logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status);
}).catch(function(reason) { }).catch(function(reason) {
instance.send(SEND_TO.debug, "Cmd-mngr: RPC runSyncExec - promise rejected:" + reason); instance.send(SEND_TO.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason);
console.log("cmd_man: rsport error", reason);
}); });
}); });
rsPort.on('error', function(err) { rsPort.on('error', function(err) {
//TODO report to service!!!
//errLogger.error(exports.title, "unable to open port", SETTINGS.serial_port, err.message);
errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0);
monitor.info("Cmd-mngr: Error on rsPort", err.message); console.log("cmd_manager: unable to open rsport", SETTINGS.serial_port, err.message);
instance.send(SEND_TO.debug, err.message);
}); });
rsPort.on("close", () => { rsPort.on("close", () => {
monitor.info("Cmd-mngr: rsPort closed, reconnecting..."); setTimeout(() => rsPort.open(), 1000);
setTimeout(handleRsPort, 1000);
}); });
rsPort.open();
rsPort.open(function(err) {
if (err) console.log('rsport open error', err);
})
} }
@ -1923,13 +1922,13 @@ exports.install = function(instance) {
if (cmd == "buildTasks") { if (cmd == "buildTasks") {
clearInterval(interval); clearInterval(interval);
logger.debug("-->Cmd-mngr: BUILD TASKS"); logger.debug("-->CMD MANAGER - BUILD TASKS");
buildTasks(); buildTasks();
//logger.debug("tasks:"); //logger.debug("tasks:");
//logger.debug(tasks); //logger.debug(tasks);
logger.debug("-->Cmd-mngr: RUN TASKS"); logger.debug("-->CMD MANAGER - RUN TASKS");
interval = setInterval(runTasks, 5000); interval = setInterval(runTasks, 5000);
} }
else if (cmd == "reload_relays") { else if (cmd == "reload_relays") {
@ -2003,8 +2002,8 @@ exports.install = function(instance) {
if (relaysData.hasOwnProperty(line)) { if (relaysData.hasOwnProperty(line)) {
let tbname = relaysData[line].tbname; let tbname = relaysData[line].tbname;
if (value == "Off") sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); if (value == "Off") sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker");
else sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); else sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker");
//report status liniu //report status liniu
sendTelemetry({ status: status }, tbname) sendTelemetry({ status: status }, tbname)
@ -2194,22 +2193,19 @@ exports.install = function(instance) {
if (tbname == nodesData[node].tbname) { if (tbname == nodesData[node].tbname) {
if (profile != "") profile = JSON.stringify(profile); if (profile != "") profile = JSON.stringify(profile);
dbNodes.modify({ processed: false, profile: profile }).where("node", node).make(function(builder) { dbNodes.modify({ processed: false, profile: profile }).where("node", node).callback(function(err, response) {
builder.callback(function(err, response) {
logger.debug("worksys - update node profile done", profile); logger.debug("worksys - update node profile done", profile);
if (profile === "") logger.debug("worksys - update node profile done - profile is empty"); if (profile === "") logger.debug("worksys - update node profile done - profile is empty");
//profil úspešne prijatý pre node č. xx //profil úspešne prijatý pre node č. xx
sendNotification("Cmd-mngr", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance);
nodesData[node].processed = false; nodesData[node].processed = false;
nodesData[node].profile = profile; nodesData[node].profile = profile;
processNodeProfile(node); processNodeProfile(node);
}); });
});
} }
} }
} }
@ -2241,9 +2237,7 @@ exports.install = function(instance) {
removeTask({ type: "relay", line: line }); removeTask({ type: "relay", line: line });
if (profile != "") profile = JSON.stringify(profile); if (profile != "") profile = JSON.stringify(profile);
dbRelays.modify({ profile: profile }).where("line", line).make(function(builder) { dbRelays.modify({ profile: profile }).where("line", line).callback(function(err, response) {
builder.callback(function(err, response) {
//update profile //update profile
logger.debug("worksys - update relay profile done:", profile); logger.debug("worksys - update relay profile done:", profile);
@ -2256,8 +2250,7 @@ exports.install = function(instance) {
buildTasks({ processLineProfiles: true, line: line }); buildTasks({ processLineProfiles: true, line: line });
sendNotification("Cmd-mngr: set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); sendNotification("CMD manager - set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance);
});
}); });
break; break;
} }
@ -2299,7 +2292,7 @@ exports.install = function(instance) {
let params = flowdata.data.body; let params = flowdata.data.body;
if (params == undefined) { if (params == undefined) {
//logger.debug("Cmd-mngr: flowdata.data.body is undefined"); //logger.debug("CMD manager flowdata.data.body is undefined");
return; return;
} }
@ -2630,7 +2623,9 @@ exports.install = function(instance) {
//energia //energia
else if (register == 79) { else if (register == 79) {
let energy = bytesToInt(bytes); let energy = bytesToInt(bytes);
values["energy"] = energy / 1000; //energia v kWh -> delit 1000 console.log("bytesToIng ",bytesToInt(bytes))
//Energiu treba reportovať v kWh -> delit 1000
values["energy"] = energy / 1000;
} }
//doba života //doba života

View file

@ -6,14 +6,33 @@ exports.version = '1.0.2';
exports.icon = 'sign-out'; exports.icon = 'sign-out';
exports.output = 2; exports.output = 2;
exports.html = `<div class="padding">
<div class="row">
<div class="col-md-6">
<div data-jc="textbox" data-jc-path="host" data-jc-config="placeholder:test.mosquitto.org;required:false" class="m">Hostname or IP address (if not empty - setting will override db setting)</div>
</div>
<div class="col-md-6">
<div data-jc="textbox" data-jc-path="port" data-jc-config="placeholder:1883;required:true" class="m">Port</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div data-jc="textbox" data-jc-path="clientid">@(Client id)</div>
</div>
<div class="col-md-6">
<div data-jc="textbox" data-jc-path="username" class="m">@(Username)</div>
</div>
</div>
</div>`;
exports.readme = ` exports.readme = `
# DB initialization # DB initialization
`; `;
const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js');
const { initNotification } = require('./helper/notification_reporter'); const { initNotification } = require('./helper/notification_reporter');
const errorHandler = require('./helper/ErrorToServiceHandler'); const errorHandler = require('./helper/ErrorToServiceHandler');
const total_energy = require('../databases/total_energy');
const SEND_TO = { const SEND_TO = {
db_init: 0, db_init: 0,
@ -22,6 +41,7 @@ const SEND_TO = {
exports.install = async function(instance) { exports.install = async function(instance) {
const dbNodes = TABLE("nodes"); const dbNodes = TABLE("nodes");
const dbRelays = TABLE("relays"); const dbRelays = TABLE("relays");
const dbSettings = TABLE("settings"); const dbSettings = TABLE("settings");
@ -50,7 +70,7 @@ exports.install = async function(instance) {
Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {}) Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {})
dbs.settings = { dbs.settings = {
edge_fw_version: "2025-08-08", //rok-mesiac-den edge_fw_version: "2025-04-24", //rok-mesiac-den
language: responseSettings[0]["lang"], language: responseSettings[0]["lang"],
rvo_name: responseSettings[0]["rvo_name"], rvo_name: responseSettings[0]["rvo_name"],
project_id: responseSettings[0]["project_id"], project_id: responseSettings[0]["project_id"],
@ -78,11 +98,6 @@ exports.install = async function(instance) {
maintenance_mode: false, maintenance_mode: false,
} }
let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1];
dbs.settings.energy_to_switch_lamps = total_energy[rvo_number];
if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined');
FLOW.dbLoaded = true; FLOW.dbLoaded = true;
errorHandler.setProjectId(dbs.settings.project_id); errorHandler.setProjectId(dbs.settings.project_id);
initNotification(); initNotification();

File diff suppressed because it is too large Load diff

2775
flow/designer.json_orig Normal file

File diff suppressed because it is too large Load diff

View file

@ -364,7 +364,7 @@ exports.install = function(instance) {
data.map(item => { data.map(item => {
let value = item['value']; let value = item['value'];
let pin = item["dev"] + item["circuit"]; // for example "relay1_03" or "input1_01" let pin = item["dev"] + item["circuit"]; // for example "ro1_03" or "di1_01"
if (pin == undefined) return; if (pin == undefined) return;
switchLogic(pin, value); switchLogic(pin, value);
@ -516,9 +516,9 @@ exports.install = function(instance) {
} }
else if (ws) { else if (ws) {
//pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method //pin = "ro1_03" or "di1_01" ... we must make just "1_01" with slice method
monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); monitor.info(`Dido: turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info);
let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value }; let cmd = { "cmd": "set", "dev": "relay", "circuit": pin.slice(2), "value": value };
ws.send(JSON.stringify(cmd)); ws.send(JSON.stringify(cmd));
} }
@ -754,9 +754,9 @@ exports.install = function(instance) {
pins = [4, 6]; pins = [4, 6];
} }
} else if (controllerType === "unipi") { } else if (controllerType === "unipi") {
pins = ["input1_01", "input1_04", "input1_05"]; pins = ["di1_01", "di1_04", "di1_05"];
if (hasMainSwitch === 1) { if (hasMainSwitch === 1) {
pins = ["input1_01", "input1_04"]; pins = ["di1_01", "di1_04"];
} }
} }
@ -781,7 +781,7 @@ exports.install = function(instance) {
for (const pinIndex of pinIndexes) { for (const pinIndex of pinIndexes) {
if (previousValues[pinIndex] === 0) { if (previousValues[pinIndex] === 0) {
if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; if ((pinIndex === 6 || pinIndex === 'di1_01' || pinIndex === 'di1_05') && SETTINGS.maintenance_mode) continue;
status = "NOK"; status = "NOK";
break; break;
} }
@ -798,7 +798,7 @@ exports.install = function(instance) {
// we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]] // we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]]
// we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] // we pass two values in case of websocket ==> switchLogic("ro1_03",1) ==> ["ro1_03",1]
const switchLogic = (...args) => { const switchLogic = (...args) => {
let values = {}; let values = {};
@ -849,18 +849,18 @@ exports.install = function(instance) {
else if (type == "rotary_switch_state") { else if (type == "rotary_switch_state") {
// combination of these two pins required to get result // combination of these two pins required to get result
let pin2, pin3; let pin2, pin3;
if (pinIndex == 2 || pinIndex == "input1_02") { if (pinIndex == 2 || pinIndex == "di1_02") {
pin2 = newPinValue; pin2 = newPinValue;
pin3 = previousValues[3] || previousValues["input1_03"]; pin3 = previousValues[3] || previousValues["di1_03"];
if (pin3 == undefined) { if (pin3 == undefined) {
previousValues[pinIndex] = newPinValue; previousValues[pinIndex] = newPinValue;
return; return;
} }
} }
else if (pinIndex == 3 || pinIndex == "input1_03") { else if (pinIndex == 3 || pinIndex == "di1_03") {
pin3 = newPinValue; pin3 = newPinValue;
pin2 = previousValues[2] || previousValues["input1_02"]; pin2 = previousValues[2] || previousValues["di1_02"];
if (pin2 == undefined) { if (pin2 == undefined) {
previousValues[pinIndex] = newPinValue; previousValues[pinIndex] = newPinValue;
@ -913,7 +913,7 @@ exports.install = function(instance) {
} }
//Dverovy kontakt - pin 6 //Dverovy kontakt - pin 6
//! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z input1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition' //! Ak je rvo s dvoma dverovymi kontaktami, ked pride z evoku signal z di1_05, co bol predytm "state_of_main switch" handlujeme ho teraz ako 'door_condition'
else if (type == "door_condition" || type === "state_of_main_switch") { else if (type == "door_condition" || type === "state_of_main_switch") {
newPinValue === 0 ? value = "open" : value = "closed"; newPinValue === 0 ? value = "open" : value = "closed";
@ -1369,60 +1369,60 @@ exports.install = function(instance) {
//! pins.table --> from UNIPI //! pins.table --> from UNIPI
// pin:string|type:string|line:number // pin:string|type:string|line:number
// *|input1_01|state_of_main_switch|0|........... // *|di1_01|state_of_main_switch|0|...........
// *|input1_02|rotary_switch_state|0|........... // *|di1_02|rotary_switch_state|0|...........
// *|input1_03|rotary_switch_state|0|........... // *|di1_03|rotary_switch_state|0|...........
// *|intut1_04|power_supply|0|........... // *|intut1_04|power_supply|0|...........
// *|input1_05|door_condition|0|........... // *|di1_05|door_condition|0|...........
// *|input1_06|state_of_breaker|1|........... // *|di1_06|state_of_breaker|1|...........
// *|input1_07|state_of_breaker|2|........... // *|di1_07|state_of_breaker|2|...........
// *|input1_08|state_of_breaker|3|........... // *|di1_08|state_of_breaker|3|...........
// *|relay1_02|state_of_contactor|1|........... // *|ro1_02|state_of_contactor|1|...........
// *|relay1_03|state_of_contactor|2|........... // *|ro1_03|state_of_contactor|2|...........
// *|relay1_04|state_of_contactor|3|........... // *|ro1_04|state_of_contactor|3|...........
// *|287D8776E0013CE9|temperature|0|........... // *|287D8776E0013CE9|temperature|0|...........
//! pins_data --> from UNIPI //! pins_data --> from UNIPI
// { // {
// input1_01: { // di1_01: {
// pin: 'input1_01', // pin: 'di1_01',
// type: 'door_condition', // type: 'door_condition',
// line: 0, // line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8' // tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// }, // },
// input1_02: { // di1_02: {
// pin: 'input1_02', // pin: 'di1_02',
// type: 'rotary_switch_state', // type: 'rotary_switch_state',
// line: 0, // line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8' // tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// }, // },
// input1_03: { // di1_03: {
// pin: 'input1_03', // pin: 'di1_03',
// type: 'rotary_switch_state', // type: 'rotary_switch_state',
// line: 0, // line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8' // tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// }, // },
// input1_04: { // di1_04: {
// pin: 'input1_04', // pin: 'di1_04',
// type: 'power_supply', // type: 'power_supply',
// line: 0, // line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8' // tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// }, // },
// input1_05: { // di1_05: {
// pin: 'input1_05', // pin: 'di1_05',
// type: 'state_of_main_switch', // type: 'state_of_main_switch',
// line: 0, // line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8' // tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// }, // },
// input1_06: { // di1_06: {
// pin: 'input1_06', // pin: 'di1_06',
// type: 'state_of_breaker', // type: 'state_of_breaker',
// line: 1, // line: 1,
// tbname: '52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo' // tbname: '52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo'
// }, // },
// relay1_02: { // ro1_02: {
// pin: 'relay1_02', // pin: 'ro1_02',
// type: 'state_of_contactor', // type: 'state_of_contactor',
// line: 1, // line: 1,
// tbname: '52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo' // tbname: '52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo'

View file

@ -1,4 +1,36 @@
function bytesToInt_orig(bytes, numberOfBytes) {
let buffer = [];
if (Array.isArray(bytes)) {
buffer = bytes.slice(0);
if (numberOfBytes != undefined) {
buffer = bytes.slice(bytes.length - numberOfBytes);
}
}
else buffer.push(bytes);
//var decimal = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
let l = (buffer.length - 1) * 8;
let decimal = 0;
for (let i = 0; i < buffer.length; i++) {
var s = buffer[i] << l;
if (l < 8) s = buffer[i]
decimal = decimal + s;
l = l - 8;
}
// console.log("decimal utils.js: ", decimal);
let decimal1 = 0n;
for (let i = 0; i < buffer.length; i++) {
decimal1 += BigInt(buffer[i]) * (2n ** BigInt((buffer.length - 1 - i) * 8));
}
// console.log("decimal biging utils.js: ", decimal1);
return decimal;
}
//bytestouintBE
function bytesToInt(bytes, numberOfBytes) { function bytesToInt(bytes, numberOfBytes) {
let buffer = []; let buffer = [];
if (Array.isArray(bytes)) { if (Array.isArray(bytes)) {
buffer = bytes.slice(0); buffer = bytes.slice(0);
@ -8,14 +40,40 @@ function bytesToInt(bytes, numberOfBytes) {
} }
else buffer.push(bytes); else buffer.push(bytes);
console.log(bytes, buffer);
let result = 0; let result = 0;
for (let i = 0; i < buffer.length; i++) { for (let i = 0; i < buffer.length; i++) {
result = (result << 8) | buffer[i]; result = (result << 8) | bytes[i];
} }
// console.log("decimal biging utils.js: ", decimal1);
return result >>> 0; //ensure it's an unsigned 32-bit number console.log("originall: ", bytesToInt_orig(buffer));
console.log("uint little endian: ", bytesToUintLE(buffer));
console.log('neww: ', result >>> 0);
return result >>> 0;
} }
function bytesToUintLE(bytes, numberOfBytes) {
let buffer = [];
if (Array.isArray(bytes)) {
buffer = bytes.slice(0);
if (numberOfBytes != undefined) {
buffer = bytes.slice(bytes.length - numberOfBytes);
}
}
else buffer.push(bytes);
//var decimal = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
let result = 0;
for (let i = buffer.length - 1; i <= 0; i--) {
result = (result << 8) | bytes[i];
}
return result >>> 0;
}
function resizeArray(arr, newSize, defaultValue) { function resizeArray(arr, newSize, defaultValue) {
while (newSize > arr.length) while (newSize > arr.length)
arr.push(defaultValue); arr.push(defaultValue);

View file

@ -16,7 +16,7 @@ exports.readme = `
`; `;
const modbus = require('jsmodbus'); const modbus = require('jsmodbus');
const SerialPort = require('serialport'); const {SerialPort} = require('serialport');
const { timeoutInterval, deviceConfig } = require("../databases/modbus_config"); const { timeoutInterval, deviceConfig } = require("../databases/modbus_config");
const { sendNotification } = require('./helper/notification_reporter'); const { sendNotification } = require('./helper/notification_reporter');
@ -36,7 +36,6 @@ let mainSocket;
let phases; let phases;
//phases where voltage is 0 (set) //phases where voltage is 0 (set)
let noVoltage; let noVoltage;
let energyToSwitchLamps;
exports.install = function(instance) { exports.install = function(instance) {
@ -77,13 +76,8 @@ exports.install = function(instance) {
let obj = this; let obj = this;
if (this.socket) { this.socket = new SerialPort({path: "/dev/ttymxc0",
this.socket.removeAllListeners(); baudRate: 9600
this.socket = null;
}
this.socket = new SerialPort("/dev/ttymxc0", {
baudRate: 9600,
}) })
// we create a client for every deviceAddress ( = address) in list and push them into dictionary // we create a client for every deviceAddress ( = address) in list and push them into dictionary
@ -92,11 +86,15 @@ exports.install = function(instance) {
} }
this.socket.on('error', function(e) { this.socket.on('error', function(e) {
console.log('Modbus_reader: Socket connection error', e); //'ECONNREFUSED' or 'ECONNRESET' ?? console.log('socket connection error', e);
if (e.code == 'ECONNREFUSED' || e.code == 'ECONNRESET') {
console.log(exports.title + ' Waiting 10 seconds before trying to connect again');
setTimeout(obj.startSocket, 10000);
}
}); });
this.socket.on('close', function() { this.socket.on('close', function() {
console.log('Modbus_reader: Socket connection closed - Waiting 10 seconds before connecting again'); console.log('Socket connection closed ' + exports.title + ' Waiting 10 seconds before trying to connect again');
setTimeout(obj.startSocket, 10000); setTimeout(obj.startSocket, 10000);
}); });
@ -117,8 +115,7 @@ exports.install = function(instance) {
this.deviceAddress = dev.deviceAddress; // 1 or 2 or any number this.deviceAddress = dev.deviceAddress; // 1 or 2 or any number
this.device = dev.device; //em340, twilight_sensor this.device = dev.device; //em340, twilight_sensor
//if we just start to loop devices from the beginning, or there is just 1 device in config, we wait whole timeoutInterval if (this.indexInDeviceConfig == 0) setTimeout(this.readRegisters, this.timeoutInterval);
if (this.indexInDeviceConfig == 0 || deviceConfig.length === 1) setTimeout(this.readRegisters, this.timeoutInterval);
else setTimeout(this.readRegisters, DELAY_BETWEEN_DEVICES); else setTimeout(this.readRegisters, DELAY_BETWEEN_DEVICES);
} }
@ -307,12 +304,15 @@ exports.install = function(instance) {
const actualTotalPower = values.total_power; const actualTotalPower = values.total_power;
if (actualTotalPower > energyToSwitchLamps && this.onNotificationSent == false) { const numberOfNodes = Object.keys(FLOW.GLOBALS.nodesData).length;
if (numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300
if (actualTotalPower > numberOfNodes * 15 && this.onNotificationSent == false) {
sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance); sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance);
this.onNotificationSent = true; this.onNotificationSent = true;
this.offNotificationSent = false; this.offNotificationSent = false;
} }
else if (actualTotalPower <= energyToSwitchLamps && this.offNotificationSent == false) { else if (actualTotalPower <= numberOfNodes * 15 && this.offNotificationSent == false) {
sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_off", {}, "", SEND_TO.tb, instance); sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_off", {}, "", SEND_TO.tb, instance);
this.onNotificationSent = false; this.onNotificationSent = false;
this.offNotificationSent = true; this.offNotificationSent = true;
@ -330,9 +330,9 @@ exports.install = function(instance) {
phases = FLOW.GLOBALS.settings.phases; phases = FLOW.GLOBALS.settings.phases;
tbName = FLOW.GLOBALS.settings.rvoTbName; tbName = FLOW.GLOBALS.settings.rvoTbName;
noVoltage = FLOW.GLOBALS.settings.no_voltage; noVoltage = FLOW.GLOBALS.settings.no_voltage;
energyToSwitchLamps = FLOW.GLOBALS.settings.energy_to_switch_lamps / 2.5; //half value is enought to show if lamps are turned on or off mainSocket = new SocketWithClients();
if (deviceConfig.length) mainSocket = new SocketWithClients();
else console.log("Modbus_reader: no modbus device in configuration"); console.log("novoltage: ", noVoltage, typeof noVoltage);
// this notification is to show, that flow (unipi) has been restarted // this notification is to show, that flow (unipi) has been restarted
sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance);

0
flow/variables.txt Normal file
View file

View file

@ -155,7 +155,7 @@ exports.install = function(instance) {
clientId: mqtt_clientid, clientId: mqtt_clientid,
username: mqtt_username, username: mqtt_username,
rejectUnauthorized: false, rejectUnauthorized: false,
resubscribe: false resubscribe: false,
}; };
wsmqttName = getWsmqttName(mqtt_host); wsmqttName = getWsmqttName(mqtt_host);
@ -188,15 +188,17 @@ exports.install = function(instance) {
// message is type of buffer // message is type of buffer
message = message.toString(); message = message.toString();
if (message[0] === '{') { if (message[0] === '{') {
TRY(function() {
try {
message = JSON.parse(message); message = JSON.parse(message);
if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) {
client.publish(topic, `{"device": ${message.device}, "id": ${message.data.id}, "data": {"success": true}}`, { qos: 1 }); client.publish(topic, `{"device": ${message.device}, "id": ${message.data.id}, "data": {"success": true}}`, { qos: 1 });
instance.send(SEND_TO.rpcCall, { "device": message.device, "id": message.data.id, "RPC response": { "success": true } }); instance.send(SEND_TO.rpcCall, { "device": message.device, "id": message.data.id, "RPC response": { "success": true } });
} }
}, () => instance.debug('MQTT: Error parsing data', message)); } catch (e) {
console.log('MQTT: Error parsing data', e);
}
} }
instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message }); instance.send(SEND_TO.rpcCall, { "topic": topic, "content": message });