Handle contactors separately in daily_report
This commit is contained in:
parent
7093d765ec
commit
c5c5b21f47
10 changed files with 427 additions and 242 deletions
4
config
4
config
|
|
@ -6,7 +6,7 @@ package#flow (Object) : { url: '/' }
|
||||||
|
|
||||||
|
|
||||||
table.relays : line:number|tbname:string|contactor:number|profile:string
|
table.relays : line:number|tbname:string|contactor:number|profile:string
|
||||||
table.nodes : node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number
|
table.nodes : node:number|pole_number:string|node_type:string|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number
|
||||||
table.settings : rvo_name:string|lang:string|temperature_address:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|project_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number|node_status_nok_time:number|phases:number|cloud_topic:string|has_main_switch:boolean
|
table.settings : rvo_name:string|lang:string|temperature_address:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|project_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number|node_status_nok_time:number|phases:number|cloud_topic:string|has_main_switch:boolean|daily_report:boolean
|
||||||
table.pins : pin:string|type:string|line:number
|
table.pins : pin:string|type:string|line:number
|
||||||
table.notifications : key:string|weight:string|sk:string|en:string
|
table.notifications : key:string|weight:string|sk:string|en:string
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file:
|
||||||
if counter != 1:
|
if counter != 1:
|
||||||
i = [m.start() for m in re.finditer(re.escape(search_str), line)]
|
i = [m.start() for m in re.finditer(re.escape(search_str), line)]
|
||||||
node = line[ i[0] + 1 : i[1] ]
|
node = line[ i[0] + 1 : i[1] ]
|
||||||
tbname = line[ i[1] + 1 : i[2] ]
|
tbname = line[ i[3] + 1 : i[4] ]
|
||||||
final.append({node:tbname})
|
final.append({node:tbname})
|
||||||
counter += 1
|
counter += 1
|
||||||
print(json.dumps(final))
|
print(json.dumps(final))
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
rvo_name:string|lang:string|temperature_address:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|project_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number|node_status_nok_time:number|phases:number|cloud_topic:string|has_main_switch:boolean
|
rvo_name:string|lang:string|temperature_address:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|project_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number|node_status_nok_time:number|phases:number|cloud_topic:string|has_main_switch:boolean|daily_report:boolean
|
||||||
+|rvo_senica_22_ip10.0.0.109|en|28.F46E9D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_22_ip10.0.0.109|9excvr7yBcF3gl3kYZGY|1883|0|48|unipi|ttyUSB0|1|20|5|6|3|u109|0|...........................................
|
+|rvo_senica_22_ip10.0.0.109|en|28.F46E9D0E0000|48.70826502|17.28455203|192.168.252.1|rvo_senica_22_ip10.0.0.109|9excvr7yBcF3gl3kYZGY|1883|0|48|unipi|ttyUSB0|1|20|5|6|3|u109|0|1|...........................................
|
||||||
|
|
|
||||||
|
|
@ -63,36 +63,39 @@ exports.install = function(instance) {
|
||||||
var opts;
|
var opts;
|
||||||
var clientReady = false;
|
var clientReady = false;
|
||||||
|
|
||||||
let o = null; //options
|
let o = {}; //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,
|
||||||
port: o.port,
|
port: o.port,
|
||||||
clientId: o.clientid,
|
clientId: o.clientid,
|
||||||
username: o.username,
|
username: o.username,
|
||||||
rejectUnauthorized: false,
|
rejectUnauthorized: false,
|
||||||
resubscribe: false
|
resubscribe: false
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("wsmqttpublich -> loadSettings from instance.options",o);
|
console.log("wsmqttpublich -> loadSettings from instance.options", o);
|
||||||
|
|
||||||
|
if (!o.topic) {
|
||||||
|
instance.status("Not configured", "white");
|
||||||
|
console.log("Cloud mqtt connect: no topic selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
@ -121,30 +124,30 @@ exports.install = function(instance) {
|
||||||
TRY(function() {
|
TRY(function() {
|
||||||
|
|
||||||
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 } });
|
||||||
}
|
}
|
||||||
|
|
||||||
}, () => 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;
|
||||||
}
|
}
|
||||||
clientReady = false;
|
clientReady = false;
|
||||||
});
|
});
|
||||||
|
|
@ -154,25 +157,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)
|
|
||||||
client.publish(`${o.topic}_forward`, stringifiedJson, {qos: 1});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//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 });
|
|
||||||
|
|
||||||
if(saveTelemetryOnError)
|
let stringifiedJson = JSON.stringify(data.data)
|
||||||
{
|
client.publish(`${o.topic}_forward`, stringifiedJson, { qos: 1 });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//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 });
|
||||||
|
|
||||||
|
if (saveTelemetryOnError && o.topic) {
|
||||||
//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,71 +187,62 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +254,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");
|
||||||
|
|
@ -279,21 +268,20 @@ exports.install = function(instance) {
|
||||||
//clear tbdata.nosql
|
//clear tbdata.nosql
|
||||||
fs.writeFileSync(source, "");
|
fs.writeFileSync(source, "");
|
||||||
fs.truncateSync(source, 0);
|
fs.truncateSync(source, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,59 +295,54 @@ 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);
|
||||||
|
|
||||||
//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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
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();
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ exports.install = function(instance) {
|
||||||
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; //accelerometer
|
||||||
|
|
||||||
minutes = 10;
|
minutes = 10;
|
||||||
priorities["74"] = minutes; // voltage
|
priorities["74"] = minutes; // voltage
|
||||||
|
|
@ -195,14 +195,17 @@ exports.install = function(instance) {
|
||||||
customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000);
|
customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000);
|
||||||
setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000);
|
setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000);
|
||||||
|
|
||||||
//dailyReport related
|
//NOTE: dailyReport related
|
||||||
emptyReportToSend();
|
emptyReportToSend();
|
||||||
|
// we handle "contactor" key separately in reportToSend
|
||||||
|
reportToSend["contactor"] = { off: [], on: [] };
|
||||||
breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0
|
breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0
|
||||||
rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME);
|
rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME);
|
||||||
setTimeout(setRvoPeriod, 3000);
|
setTimeout(setRvoPeriod, 3000);
|
||||||
setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME);
|
setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME);
|
||||||
handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME);
|
handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME);
|
||||||
|
//if dawn, we empty "contactor" key in reportToSend
|
||||||
|
setInterval(emptyContactorDataInReport, 60000);
|
||||||
|
|
||||||
setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour
|
setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour
|
||||||
setCorrectPlcTimeOnceADay();
|
setCorrectPlcTimeOnceADay();
|
||||||
|
|
@ -1342,51 +1345,69 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
if (rvo_is_on) {
|
for (const [key, value] of Object.entries(dailyReport)) {
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(dailyReport)) {
|
if (["name", "time", "dusk_and_dawn"].includes(key)) continue;
|
||||||
|
|
||||||
if (["name", "time", "dusk_and_dawn"].includes(key)) continue;
|
let poleNumber = nodesData[key]["pole_number"];
|
||||||
|
let line = dailyReport[key].line;
|
||||||
|
let nodeType = nodesData[key]["node_type"];
|
||||||
|
let fullNodeName = key // key == nodeNumber
|
||||||
|
|
||||||
|
if (poleNumber && nodeType) {
|
||||||
|
fullNodeName = SETTINGS.rvo_number + "/" + poleNumber + "_" + line + "L_" + key + "_" + nodeType;
|
||||||
|
} else {
|
||||||
|
fullNodeName = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rvo_is_on) {
|
||||||
|
|
||||||
if (value.initialTs) {
|
if (value.initialTs) {
|
||||||
if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) {
|
if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
addToArrayIfUnique(reportToSend["night_no_data"], key);
|
addToArrayIfUnique(reportToSend["night_no_data"], fullNodeName);
|
||||||
console.log('report nedostava ziadne data uz hodinu', key);
|
console.log('report nedostava ziadne data uz hodinu', fullNodeName);
|
||||||
value.initialTs = now;
|
value.initialTs = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.dimmingAndPowerAreZeroTime) {
|
if (value.dimmingIsZeroTime) {
|
||||||
if (value.dimmingAndPowerAreZeroTime + ADD_NODE_TO_REPORT_TIME < now) {
|
if (value.dimmingIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
addToArrayIfUnique(reportToSend["night_dimming=0"], key);
|
addToArrayIfUnique(reportToSend["night_dimming=0"], fullNodeName);
|
||||||
console.log("report node dimming je 0", key);
|
console.log("report node dimming je 0 ale ma svietit", fullNodeName);
|
||||||
value.dimmingAndPowerAreZeroTime = now;
|
value.dimmingIsZeroTime = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value.powerIsZeroTime) {
|
||||||
|
if (value.powerIsZeroTime + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
|
addToArrayIfUnique(reportToSend["night_power=0"], fullNodeName);
|
||||||
|
console.log("report node power je 0 ale ma svietit", fullNodeName);
|
||||||
|
value.powerIsZeroTime = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
|
|
||||||
} else {
|
let contactorStatus = relaysData[line].contactor;
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(dailyReport)) {
|
|
||||||
|
|
||||||
if (["name", "time", "dusk_and_dawn"].includes(key)) continue;
|
|
||||||
|
|
||||||
let nodeIsOnLine = dailyReport[key].line;
|
|
||||||
let contactorStatus = relaysData[nodeIsOnLine].contactor;
|
|
||||||
if (contactorStatus === 1) {
|
if (contactorStatus === 1) {
|
||||||
|
|
||||||
if (value.initialTs) {
|
if (value.initialTs) {
|
||||||
if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) {
|
if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
addToArrayIfUnique(reportToSend["day_24/7_no_data"], key);
|
addToArrayIfUnique(reportToSend["day_24/7_no_data"], fullNodeName);
|
||||||
console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', key);
|
console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', fullNodeName);
|
||||||
value.initialTs = now;
|
value.initialTs = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.nodeIsOnButShouldBeOffTime) {
|
if (value.dimmingIsOnButShouldBeOffTime) {
|
||||||
if (value.nodeIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) {
|
if (value.dimmingIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], key);
|
addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], fullNodeName);
|
||||||
console.log("report nema svietit ale svieti viac ako hodinu", key);
|
console.log("report dimming je > 0 ale nema svietit", fullNodeName);
|
||||||
value.nodeIsOnButShouldBeOffTime = now;
|
value.dimmingIsOnButShouldBeOffTime = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value.powerIsOnButShouldBeOffTime) {
|
||||||
|
if (value.powerIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
|
addToArrayIfUnique(reportToSend["day_24/7_power>0"], fullNodeName);
|
||||||
|
console.log("report power je > 0 ale nema svietit", fullNodeName);
|
||||||
|
value.powerIsOnButShouldBeOffTime = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1408,6 +1429,8 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
function dailyReportHandler() {
|
function dailyReportHandler() {
|
||||||
|
|
||||||
|
if (!SETTINGS.daily_report) return;
|
||||||
|
|
||||||
// after dawn we empty reportToSend and start to get data for a new day
|
// after dawn we empty reportToSend and start to get data for a new day
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const hour = date.getHours();
|
const hour = date.getHours();
|
||||||
|
|
@ -1432,6 +1455,10 @@ exports.install = function(instance) {
|
||||||
initialReportStatus = true;
|
initialReportStatus = true;
|
||||||
|
|
||||||
// ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac.
|
// ak sa funkcia spusti o hodinu alebo 2 neskor, ako je usvit (moze sa to stat, kedze kazde zapnutie/vypnutie linii odznova spusti casovac.
|
||||||
|
// TODO: usvit bol 7:11, posledna "reportHandler" bola 6:55. Spustila sa podmienka5. Dalsi "reportHandler mal byt 7:55, ale 7:41 sa vypli linie (teda "reportHandler" sa pusti az o hodinu 8:41),
|
||||||
|
// ale kedze uzivatel zapol linie o 8:30, posunulo sa "reportHandlovanie" na 9:30. Kedze v tento moment sa reportToSend vymazava (podmienka 3),
|
||||||
|
// tak zapnutie linii pouzivatelom o 8:30 sa do reportu nikdy nedostane
|
||||||
|
// preco nevymazavam reportToSend hned po usvite ??? (asi preto ze sa moze stat ze rvo ma stale zapnute linie a stane sa ze do reportu na dalsi den sa dostanu nody, ktore tam nemaju co robit!!!
|
||||||
} else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) {
|
} else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) {
|
||||||
if (!initialReportStatus) {
|
if (!initialReportStatus) {
|
||||||
emptyReportToSend();
|
emptyReportToSend();
|
||||||
|
|
@ -1453,17 +1480,30 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//We empty reportToSend object, but we want to keep contactor data for a current day
|
||||||
function emptyReportToSend() {
|
function emptyReportToSend() {
|
||||||
emptyJsObject(reportToSend);
|
Object.keys(reportToSend).forEach(key => { if (key !== "contactor") delete jsObject[key] });
|
||||||
reportToSend["contactor"] = { off: [], on: [] };
|
|
||||||
reportToSend["night_no_data"] = [];
|
reportToSend["night_no_data"] = [];
|
||||||
reportToSend["night_dimming=0"] = [];
|
reportToSend["night_dimming=0"] = [];
|
||||||
|
reportToSend["night_power=0"] = [];
|
||||||
reportToSend["day_24/7_no_data"] = [];
|
reportToSend["day_24/7_no_data"] = [];
|
||||||
reportToSend["day_24/7_dimming>0"] = [];
|
reportToSend["day_24/7_dimming>0"] = [];
|
||||||
//console.log(`je ${sunCalcResult.dawn_hours}:${sunCalcResult.dawn_minutes}, resetuje sa reportToSend: `, reportToSend);
|
reportToSend["day_24/7_power>0"] = [];
|
||||||
console.log(`resetuje sa reportToSend`);
|
console.log(`resetuje sa reportToSend`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// to have proper contactor data in report for a current day, we empty it when dawn is reached:
|
||||||
|
function emptyContactorDataInReport() {
|
||||||
|
const d = new Date();
|
||||||
|
if (sunCalcResult.dawn_hours === d.getHours() && sunCalcResult.dawn_minutes === d.getMinutes()) {
|
||||||
|
delete reportToSend.contactor;
|
||||||
|
reportToSend["contactor"] = { off: [], on: [] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii
|
//NOTE: ked je initialTs stale rovnaky a zistime ze linie su vypnute (relaysData.line.contactor) - zistim, ci je node na tej linii. Vieme, ze ak je linia vypnuta je to v poriadku lebo nie je na 24/7 linii
|
||||||
//ak je na 24/7 linii, reportujeme, ze neprijima data
|
//ak je na 24/7 linii, reportujeme, ze neprijima data
|
||||||
function emptyDailyReport() {
|
function emptyDailyReport() {
|
||||||
|
|
@ -1500,12 +1540,6 @@ exports.install = function(instance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rsPort.isOpen) {
|
|
||||||
instance.send(SEND_TO.debug, "!rsPort.isOpen");
|
|
||||||
//await rsPort.open();
|
|
||||||
//console.log("Cmd-mngr: !rsPort.isOpen");
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentTask = tasks[0];
|
let currentTask = tasks[0];
|
||||||
|
|
||||||
if (currentTask.debug) {
|
if (currentTask.debug) {
|
||||||
|
|
@ -1560,7 +1594,7 @@ exports.install = function(instance) {
|
||||||
date.setDate(date.getDate() + 1);//next day
|
date.setDate(date.getDate() + 1);//next day
|
||||||
|
|
||||||
let sunCalcResult;
|
let sunCalcResult;
|
||||||
if (timePointName) { sunCalcResult = calculateDuskDawn(date, params.line); console.log("typee-rellay: ", sunCalcResult.dawn_time, sunCalcResult.dusk_time); }
|
if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line);
|
||||||
|
|
||||||
|
|
||||||
if (timePointName == "dawn") {
|
if (timePointName == "dawn") {
|
||||||
|
|
@ -1615,6 +1649,7 @@ exports.install = function(instance) {
|
||||||
// state_of_braker: disconnected = true?
|
// state_of_braker: disconnected = true?
|
||||||
|
|
||||||
if (!rsPort.isOpen) {
|
if (!rsPort.isOpen) {
|
||||||
|
console.log("Cmd-mngr: rsPort is not opened in runTasks", params);
|
||||||
interval = setInterval(runTasks, LONG_INTERVAL);
|
interval = setInterval(runTasks, LONG_INTERVAL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1717,36 +1752,70 @@ exports.install = function(instance) {
|
||||||
values.status = "OK";
|
values.status = "OK";
|
||||||
nodesData[node].readout = { ...nodesData[node].readout, ...values };
|
nodesData[node].readout = { ...nodesData[node].readout, ...values };
|
||||||
|
|
||||||
//TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!!
|
|
||||||
//v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda
|
|
||||||
if (register === 1 || register === 76) {
|
|
||||||
|
|
||||||
let now = Date.now();
|
if (SETTINGS.daily_report) {
|
||||||
|
//TODO: co ak nedostavame odpovede z nodu ? Musime vyreportovat!!
|
||||||
|
//v dailyReport teda musi byt kompletny zoznam nodov a neustale kontrolovat, ci maju data, ak nie report node - neodpoveda
|
||||||
|
if (register === 1) {
|
||||||
|
|
||||||
if (rvo_is_on === true) {
|
let now = Date.now();
|
||||||
|
|
||||||
if ("nodeIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].nodeIsOnButShouldBeOffTime;
|
if (rvo_is_on === true) {
|
||||||
|
|
||||||
|
if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime;
|
||||||
|
|
||||||
|
if (values.dimming > 0) {
|
||||||
|
if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime;
|
||||||
|
dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
} else {
|
||||||
|
if (!("dimmingIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsZeroTime: now, initialTs: now };
|
||||||
|
else dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
}
|
||||||
|
|
||||||
if (values.dimming > 0 || values.power > 0) {
|
|
||||||
if ("dimmingAndPowerAreZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingAndPowerAreZeroTime;
|
|
||||||
dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
|
||||||
} else {
|
} else {
|
||||||
if (!("dimmingAndPowerAreZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingAndPowerAreZeroTime: now, initialTs: now };
|
|
||||||
else dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
if ("dimmingIsZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingIsZeroTime;
|
||||||
|
|
||||||
|
if (values.dimming > 0) {
|
||||||
|
if (!("dimmingIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingIsOnButShouldBeOffTime: now, initialTs: now };
|
||||||
|
else dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
} else {
|
||||||
|
if ("dimmingIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].dimmingIsOnButShouldBeOffTime;
|
||||||
|
dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
if (register === 76) {
|
||||||
|
|
||||||
if ("dimmingAndPowerAreZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingAndPowerAreZeroTime;
|
let now = Date.now();
|
||||||
|
|
||||||
|
if (rvo_is_on === true) {
|
||||||
|
|
||||||
|
if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime;
|
||||||
|
|
||||||
|
if (values.power > 1) {
|
||||||
|
if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime;
|
||||||
|
dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
} else {
|
||||||
|
if (!("powerIsZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsZeroTime: now, initialTs: now };
|
||||||
|
else dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
}
|
||||||
|
|
||||||
if (values.dimming > 0 || values.power > 0) {
|
|
||||||
if (!("nodeIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], nodeIsOnButShouldBeOffTime: now, initialTs: now };
|
|
||||||
else dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
|
||||||
} else {
|
} else {
|
||||||
if ("nodeIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].nodeIsOnButShouldBeOffTime;
|
|
||||||
dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ("powerIsZeroTime" in dailyReport[node]) delete dailyReport[node].powerIsZeroTime;
|
||||||
|
|
||||||
|
if (values.power > 1) {
|
||||||
|
if (!("powerIsOnButShouldBeOffTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], powerIsOnButShouldBeOffTime: now, initialTs: now };
|
||||||
|
else dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
} else {
|
||||||
|
if ("powerIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].powerIsOnButShouldBeOffTime;
|
||||||
|
dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1989,6 +2058,8 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
function setRvoPeriod() {
|
function setRvoPeriod() {
|
||||||
|
|
||||||
|
if (!SETTINGS.daily_report) return;
|
||||||
|
|
||||||
const ts = Date.now();
|
const ts = Date.now();
|
||||||
|
|
||||||
previous_rvo_is_on_value = rvo_is_on;
|
previous_rvo_is_on_value = rvo_is_on;
|
||||||
|
|
@ -2489,11 +2560,11 @@ exports.install = function(instance) {
|
||||||
// v relaysData je contactor bud 0 alebo 1, ale z platformy prichadza true, false;
|
// v relaysData je contactor bud 0 alebo 1, ale z platformy prichadza true, false;
|
||||||
if (value == false) {
|
if (value == false) {
|
||||||
turnLine("off", line, "command received from platform");
|
turnLine("off", line, "command received from platform");
|
||||||
reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode });
|
if (line != 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
turnLine("on", line, "command received from platform");
|
turnLine("on", line, "command received from platform");
|
||||||
reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode });
|
if (line != 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,10 @@ exports.install = async function(instance) {
|
||||||
if (dbs.nodesData.hasOwnProperty("0")) delete dbs.nodesData["0"];
|
if (dbs.nodesData.hasOwnProperty("0")) delete dbs.nodesData["0"];
|
||||||
Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {})
|
Object.keys(dbs.nodesData).forEach(node => dbs.nodesData[node].readout = {})
|
||||||
|
|
||||||
|
let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1];
|
||||||
|
|
||||||
dbs.settings = {
|
dbs.settings = {
|
||||||
edge_fw_version: "2025-08-08", //rok-mesiac-den
|
edge_fw_version: "2025-10-08", //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"],
|
||||||
|
|
@ -72,6 +74,8 @@ exports.install = async function(instance) {
|
||||||
phases: responseSettings[0]["phases"],
|
phases: responseSettings[0]["phases"],
|
||||||
cloud_topic: responseSettings[0]["cloud_topic"],
|
cloud_topic: responseSettings[0]["cloud_topic"],
|
||||||
has_main_switch: responseSettings[0]["has_main_switch"],
|
has_main_switch: responseSettings[0]["has_main_switch"],
|
||||||
|
daily_report: responseSettings[0]["daily_report"],
|
||||||
|
rvo_number: rvo_number,
|
||||||
|
|
||||||
//dynamic values
|
//dynamic values
|
||||||
masterNodeIsResponding: true, //cmd_manager
|
masterNodeIsResponding: true, //cmd_manager
|
||||||
|
|
@ -79,7 +83,6 @@ exports.install = async function(instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let rvo_number = responseSettings[0]["rvo_name"].match(/\D+(\d{1,2})_/)[1];
|
|
||||||
dbs.settings.energy_to_switch_lamps = total_energy[rvo_number];
|
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');
|
if (dbs.settings.energy_to_switch_lamps === undefined) console.log('=============== db_init.js: energy_to_switch_lamps is undefined');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -449,8 +449,8 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"data": "{line: 3, command: \"turnOff\", force: true}",
|
"datatype": "object",
|
||||||
"datatype": "object"
|
"data": "{line: 3, command: \"turnOff\", force: true}"
|
||||||
},
|
},
|
||||||
"color": "#F6BB42",
|
"color": "#F6BB42",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -501,8 +501,8 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"datatype": "string",
|
"data": "profile_nodes",
|
||||||
"data": "profile_nodes"
|
"datatype": "string"
|
||||||
},
|
},
|
||||||
"color": "#F6BB42",
|
"color": "#F6BB42",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -712,8 +712,8 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"datatype": "object",
|
"data": "{line: 1, command: \"turnOn\", force: true}",
|
||||||
"data": "{line: 1, command: \"turnOn\", force: true}"
|
"datatype": "object"
|
||||||
},
|
},
|
||||||
"color": "#F6BB42",
|
"color": "#F6BB42",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -852,8 +852,8 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"data": "{command: \"turnOnAlarm\"}",
|
"datatype": "object",
|
||||||
"datatype": "object"
|
"data": "{command: \"turnOnAlarm\"}"
|
||||||
},
|
},
|
||||||
"color": "#F6BB42",
|
"color": "#F6BB42",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -882,8 +882,8 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"data": "{command: \"turnOffAlarm\"}",
|
"datatype": "object",
|
||||||
"datatype": "object"
|
"data": "{command: \"turnOffAlarm\"}"
|
||||||
},
|
},
|
||||||
"color": "#F6BB42",
|
"color": "#F6BB42",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -1019,7 +1019,7 @@
|
||||||
"output": []
|
"output": []
|
||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"text": "858.06 MB / 985.68 MB",
|
"text": "858.88 MB / 985.68 MB",
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|
@ -1049,7 +1049,7 @@
|
||||||
"output": []
|
"output": []
|
||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"text": "5.69 GB / 7.26 GB",
|
"text": "5.78 GB / 7.26 GB",
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|
@ -1162,9 +1162,9 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"stringify": "json",
|
"url": "http://192.168.252.2:8004/sentmessage",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"url": "http://192.168.252.2:8004/sentmessage"
|
"stringify": "json"
|
||||||
},
|
},
|
||||||
"color": "#5D9CEC",
|
"color": "#5D9CEC",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -1505,7 +1505,7 @@
|
||||||
"output": []
|
"output": []
|
||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"text": "13% / 74.17 MB",
|
"text": "49.2% / 69.91 MB",
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|
@ -1972,8 +1972,8 @@
|
||||||
"component": "virtualwirein",
|
"component": "virtualwirein",
|
||||||
"tab": "1612772287426",
|
"tab": "1612772287426",
|
||||||
"name": "tb-push",
|
"name": "tb-push",
|
||||||
"x": 77.75,
|
"x": 88.75,
|
||||||
"y": 1630,
|
"y": 1685,
|
||||||
"connections": {
|
"connections": {
|
||||||
"0": [
|
"0": [
|
||||||
{
|
{
|
||||||
|
|
@ -2028,7 +2028,7 @@
|
||||||
"tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]",
|
"tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]",
|
||||||
"message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]",
|
"message_includes": "[\"is responding again\", \"Flow has been restarted\", \"Node db has changed\"]",
|
||||||
"types": "[\"emergency\", \"critical\", \"error\", \"alert\"]",
|
"types": "[\"emergency\", \"critical\", \"error\", \"alert\"]",
|
||||||
"name": "rvo_senica_15_ip114"
|
"name": ""
|
||||||
},
|
},
|
||||||
"color": "#30E193",
|
"color": "#30E193",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -2057,9 +2057,9 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"stringify": "json",
|
"url": "http://192.168.252.2:8004/slack",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"url": "http://192.168.252.2:8004/slack"
|
"stringify": "json"
|
||||||
},
|
},
|
||||||
"color": "#5D9CEC",
|
"color": "#5D9CEC",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -2095,8 +2095,8 @@
|
||||||
"component": "trigger",
|
"component": "trigger",
|
||||||
"tab": "1612772287426",
|
"tab": "1612772287426",
|
||||||
"name": "Trigger",
|
"name": "Trigger",
|
||||||
"x": 79,
|
"x": 87,
|
||||||
"y": 1723,
|
"y": 1591,
|
||||||
"connections": {
|
"connections": {
|
||||||
"0": [
|
"0": [
|
||||||
{
|
{
|
||||||
|
|
@ -2114,8 +2114,8 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"datatype": "object",
|
"data": "{ \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\": [ { \"ts\": 1716289039281, \"values\": { \"_event\": { \"type\": \"alert\", \"status\": \"new\", \"source\": { \"func\": \"CMD Manager: process cmd\", \"component\": \"1619515097737\", \"component_name\": \"CMD Manager\", \"edge\": \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\" }, \"message\": \"NOW CONNECTED TO SLACK !\", \"message_data\": \"\" } } } ] }",
|
||||||
"data": "{ \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\": [ { \"ts\": 1716289039281, \"values\": { \"_event\": { \"type\": \"alert\", \"status\": \"new\", \"source\": { \"func\": \"CMD Manager: process cmd\", \"component\": \"1619515097737\", \"component_name\": \"CMD Manager\", \"edge\": \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\" }, \"message\": \"NOW CONNECTED TO SLACK !\", \"message_data\": \"\" } } } ] }"
|
"datatype": "object"
|
||||||
},
|
},
|
||||||
"color": "#F6BB42",
|
"color": "#F6BB42",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -2677,8 +2677,8 @@
|
||||||
"component": "nodesdb_change_check",
|
"component": "nodesdb_change_check",
|
||||||
"tab": "1612772287426",
|
"tab": "1612772287426",
|
||||||
"name": "Nodes DB change check",
|
"name": "Nodes DB change check",
|
||||||
"x": 263.8833312988281,
|
"x": 266.8833312988281,
|
||||||
"y": 1993.2333984375,
|
"y": 1980.2333984375,
|
||||||
"connections": {
|
"connections": {
|
||||||
"0": [
|
"0": [
|
||||||
{
|
{
|
||||||
|
|
@ -2689,6 +2689,16 @@
|
||||||
"index": "0",
|
"index": "0",
|
||||||
"id": "1732700642917"
|
"id": "1732700642917"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"1": [
|
||||||
|
{
|
||||||
|
"index": "0",
|
||||||
|
"id": "1759958914348"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": "0",
|
||||||
|
"id": "1759959003114"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"disabledio": {
|
"disabledio": {
|
||||||
|
|
@ -2708,8 +2718,8 @@
|
||||||
"component": "virtualwirein",
|
"component": "virtualwirein",
|
||||||
"tab": "1612772287426",
|
"tab": "1612772287426",
|
||||||
"name": "db-init",
|
"name": "db-init",
|
||||||
"x": 84.75,
|
"x": 76.75,
|
||||||
"y": 1994,
|
"y": 1988,
|
||||||
"connections": {
|
"connections": {
|
||||||
"0": [
|
"0": [
|
||||||
{
|
{
|
||||||
|
|
@ -2737,8 +2747,8 @@
|
||||||
"component": "debug",
|
"component": "debug",
|
||||||
"tab": "1612772287426",
|
"tab": "1612772287426",
|
||||||
"name": "nodesChange",
|
"name": "nodesChange",
|
||||||
"x": 561.8833312988281,
|
"x": 571.8833312988281,
|
||||||
"y": 2055.2333984375,
|
"y": 2018.2333984375,
|
||||||
"connections": {},
|
"connections": {},
|
||||||
"disabledio": {
|
"disabledio": {
|
||||||
"input": [],
|
"input": [],
|
||||||
|
|
@ -2761,8 +2771,8 @@
|
||||||
"component": "virtualwireout",
|
"component": "virtualwireout",
|
||||||
"tab": "1612772287426",
|
"tab": "1612772287426",
|
||||||
"name": "tb-push",
|
"name": "tb-push",
|
||||||
"x": 557.8833312988281,
|
"x": 567.8833312988281,
|
||||||
"y": 1949,
|
"y": 1933,
|
||||||
"connections": {},
|
"connections": {},
|
||||||
"disabledio": {
|
"disabledio": {
|
||||||
"input": [],
|
"input": [],
|
||||||
|
|
@ -2924,9 +2934,9 @@
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"url": "http://192.168.252.2:8015/daily_report",
|
"stringify": "json",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"stringify": "json"
|
"url": "http://192.168.252.2:8015/daily_report"
|
||||||
},
|
},
|
||||||
"color": "#5D9CEC",
|
"color": "#5D9CEC",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -2978,6 +2988,114 @@
|
||||||
},
|
},
|
||||||
"color": "#967ADC",
|
"color": "#967ADC",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1759958914348",
|
||||||
|
"component": "httprequest",
|
||||||
|
"tab": "1612772287426",
|
||||||
|
"name": "http://192.168.252.2:8015/node_numbers",
|
||||||
|
"x": 571,
|
||||||
|
"y": 2111,
|
||||||
|
"connections": {
|
||||||
|
"0": [
|
||||||
|
{
|
||||||
|
"index": "0",
|
||||||
|
"id": "1759958927094"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"disabledio": {
|
||||||
|
"input": [],
|
||||||
|
"output": []
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": "",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"stringify": "json",
|
||||||
|
"method": "POST",
|
||||||
|
"url": "http://192.168.252.2:8015/node_numbers"
|
||||||
|
},
|
||||||
|
"color": "#5D9CEC",
|
||||||
|
"notes": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1759958927094",
|
||||||
|
"component": "debug",
|
||||||
|
"tab": "1612772287426",
|
||||||
|
"name": "nodesChangeCloud",
|
||||||
|
"x": 951.8833312988281,
|
||||||
|
"y": 2109.2333984375,
|
||||||
|
"connections": {},
|
||||||
|
"disabledio": {
|
||||||
|
"input": [],
|
||||||
|
"output": []
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": "Enabled",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"type": "data",
|
||||||
|
"repository": false,
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"color": "#967ADC",
|
||||||
|
"notes": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1759959003114",
|
||||||
|
"component": "debug",
|
||||||
|
"tab": "1612772287426",
|
||||||
|
"name": "nodeChangeCloud1",
|
||||||
|
"x": 574,
|
||||||
|
"y": 2218,
|
||||||
|
"connections": {},
|
||||||
|
"disabledio": {
|
||||||
|
"input": [],
|
||||||
|
"output": []
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": "Enabled",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"type": "data",
|
||||||
|
"repository": false,
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"color": "#967ADC",
|
||||||
|
"notes": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1760020290879",
|
||||||
|
"component": "virtualwirein",
|
||||||
|
"tab": "1612772287426",
|
||||||
|
"name": "db-init",
|
||||||
|
"x": 84.75,
|
||||||
|
"y": 1787,
|
||||||
|
"connections": {
|
||||||
|
"0": [
|
||||||
|
{
|
||||||
|
"index": "1",
|
||||||
|
"id": "1718016052341"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"disabledio": {
|
||||||
|
"input": [],
|
||||||
|
"output": []
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": "db-init",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"wirename": "db-init"
|
||||||
|
},
|
||||||
|
"color": "#303E4D",
|
||||||
|
"notes": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 615
|
"version": 615
|
||||||
|
|
|
||||||
|
|
@ -16,55 +16,55 @@ const nodesOriginalFile = path.join(__dirname, '../databases/nodes_original/', '
|
||||||
|
|
||||||
exports.install = function(instance) {
|
exports.install = function(instance) {
|
||||||
|
|
||||||
function compareArrays(array1, array2) {
|
function compareArrays(array1, array2) {
|
||||||
let message = "";
|
let message = "";
|
||||||
let areEqual = true;
|
let areEqual = true;
|
||||||
let zmenene = []
|
let zmenene = []
|
||||||
|
|
||||||
if (array1.length !== array2.length) {
|
if (array1.length !== array2.length) {
|
||||||
message += "Nezhoda v pocte nodov. "
|
message += "Nezhoda v pocte nodov. "
|
||||||
|
}
|
||||||
|
|
||||||
|
const set1 = new Set(array1.map(obj => JSON.stringify(obj)));
|
||||||
|
const set2 = new Set(array2.map(obj => JSON.stringify(obj)));
|
||||||
|
|
||||||
|
for (const objStr of set1) {
|
||||||
|
|
||||||
|
if (!set2.has(objStr)) {
|
||||||
|
zmenene.push(objStr)
|
||||||
|
areEqual = false;
|
||||||
|
} else {
|
||||||
|
set2.delete(objStr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const set1 = new Set(array1.map(obj => JSON.stringify(obj)));
|
if (!areEqual) {
|
||||||
const set2 = new Set(array2.map(obj => JSON.stringify(obj)));
|
message += `Aktualne nody: ${zmenene.toString()}. Zmenene proti originalu: ${Array.from(set2).join(' ')}`;
|
||||||
|
sendNotification("Nodesdb_changecheck", FLOW.GLOBALS.settings.rvoTbName, "nodes_db_changed", "", message, 0, instance);
|
||||||
|
}
|
||||||
|
else console.log("Arrays are equal.");
|
||||||
|
|
||||||
for (const objStr of set1) {
|
console.log(message)
|
||||||
|
}
|
||||||
|
|
||||||
if (!set2.has(objStr)) {
|
|
||||||
zmenene.push(objStr)
|
|
||||||
areEqual = false;
|
|
||||||
} else {
|
|
||||||
set2.delete(objStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!areEqual) {
|
instance.on("data", _ => {
|
||||||
message += `Aktualne nody: ${zmenene.toString()}. Zmenene proti originalu: ${Array.from(set2).join(' ')}`;
|
|
||||||
sendNotification("Nodesdb_changecheck", FLOW.GLOBALS.settings.rvoTbName, "nodes_db_changed", "", message, 0, instance);
|
|
||||||
}
|
|
||||||
else console.log("Arrays are equal.");
|
|
||||||
|
|
||||||
console.log(message)
|
let nodesData = FLOW.GLOBALS.nodesData;
|
||||||
|
|
||||||
|
// we check if nodes.table has changed compared to nodes_original.table (we have array of nodes e.g. [{node:255, tbname: "agruhuwhgursuhgo34hgsdiguhrr"}]
|
||||||
|
const nodes_actual = Object.keys(nodesData).map(node => ({ [node]: nodesData[node].tbname }))
|
||||||
|
let nodes_original = fs.readFileSync(nodesOriginalFile, { encoding: 'utf8', flag: 'r' });
|
||||||
|
|
||||||
|
try {
|
||||||
|
nodes_original = JSON.parse(nodes_original);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
instance.on("data", _ => {
|
setTimeout(() => compareArrays(nodes_actual, nodes_original), 10000);
|
||||||
|
})
|
||||||
let nodesData = FLOW.GLOBALS.nodesData;
|
|
||||||
|
|
||||||
// we check if nodes.table has changed compared to nodes_original.table (we have array of nodes e.g. [{node:255, tbname: "agruhuwhgursuhgo34hgsdiguhrr"}]
|
|
||||||
const nodes_actual = Object.keys(nodesData).map(node => ({[node]: nodesData[node].tbname}))
|
|
||||||
let nodes_original = fs.readFileSync(nodesOriginalFile, { encoding: 'utf8', flag: 'r' });
|
|
||||||
|
|
||||||
try {
|
|
||||||
nodes_original = JSON.parse(nodes_original);
|
|
||||||
} catch(e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setTimeout(() => compareArrays(nodes_actual, nodes_original),10000);
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ exports.id = 'slack_filter';
|
||||||
exports.title = 'Slack Filter';
|
exports.title = 'Slack Filter';
|
||||||
exports.group = 'Citysys';
|
exports.group = 'Citysys';
|
||||||
exports.color = '#30E193';
|
exports.color = '#30E193';
|
||||||
exports.input = 1;
|
exports.input = 2;
|
||||||
exports.output = 1;
|
exports.output = 1;
|
||||||
exports.author = 'Jakub Klena';
|
exports.author = 'Jakub Klena';
|
||||||
exports.icon = 'plug';
|
exports.icon = 'plug';
|
||||||
|
|
@ -33,7 +33,7 @@ exports.install = function(instance) {
|
||||||
instance["savedSlackMessages"] = [];
|
instance["savedSlackMessages"] = [];
|
||||||
var timer = null;
|
var timer = null;
|
||||||
|
|
||||||
instance.on('data', function(response) {
|
instance.on('0', function(response) {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
let value = response.data;
|
let value = response.data;
|
||||||
if (typeof value !== 'object') return;
|
if (typeof value !== 'object') return;
|
||||||
|
|
@ -181,6 +181,8 @@ exports.install = function(instance) {
|
||||||
};
|
};
|
||||||
|
|
||||||
instance.on('options', instance.reconfigure);
|
instance.on('options', instance.reconfigure);
|
||||||
setTimeout(instance.reconfigure, 10000);
|
|
||||||
|
|
||||||
|
instance.on("1", _ => {
|
||||||
|
instance.reconfigure();
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
|
||||||
16
readme.md
16
readme.md
|
|
@ -1,10 +1,18 @@
|
||||||
# Total.js version 4 - Flow
|
# Total.js version 3 - Flow
|
||||||
|
|
||||||
This is a version of citysys-flowserver, running on Debian12 OS.
|
|
||||||
It has the latest LTS version of nodejs and latest npm modules installed.
|
|
||||||
|
|
||||||
- open terminal / command-line
|
- open terminal / command-line
|
||||||
- open app directory
|
- open app directory
|
||||||
- run `$ npm install`
|
- run `$ npm install`
|
||||||
- run `$ node index.js`
|
- run `$ node index.js`
|
||||||
- open browser `http://0.0.0.0:12345`
|
- open browser `http://0.0.0.0:12345`
|
||||||
|
|
||||||
|
# Settings configuration:
|
||||||
|
- set in databases directory
|
||||||
|
- chosen options:
|
||||||
|
- restore_from_backup => number of records, that are restored from db after thingsboard reconnected
|
||||||
|
- restore_backup_wait => number of seconds between bulk of records are sent
|
||||||
|
- node_status_nok_time => number of hours after which the node sends a message to thingsboard that its status is NOK
|
||||||
|
- phases => number of phases in RVO
|
||||||
|
- cloud_topic => we need to set cloud_topic, if we want to send telemetry to RADO's thingsboard
|
||||||
|
- daily_report => if we want to create and send daily reports by email, set this to 1
|
||||||
|
- send_changed_node_numbers => if we are sending daily reports, we need to keep a track of changed node numbers. They are processed on the cloud. Set this to 1 if yes.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue