Daily reports - dimming and power combined results
This commit is contained in:
parent
cf16481324
commit
7093d765ec
5 changed files with 433 additions and 86 deletions
|
|
@ -30,6 +30,7 @@ const total_energy = {
|
||||||
47: 1100,
|
47: 1100,
|
||||||
48: 1500,
|
48: 1500,
|
||||||
50: 3200,
|
50: 3200,
|
||||||
|
53: 1250,
|
||||||
55: 1000,
|
55: 1000,
|
||||||
56: 5500
|
56: 5500
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ exports.title = 'CMD Manager';
|
||||||
exports.group = 'Worksys';
|
exports.group = 'Worksys';
|
||||||
exports.color = '#5D9CEC';
|
exports.color = '#5D9CEC';
|
||||||
exports.version = '0.0.3';
|
exports.version = '0.0.3';
|
||||||
exports.output = ['red', 'blue', 'yellow', 'blue', 'white'];
|
exports.output = ['red', 'blue', 'yellow', 'blue', 'white', 'green'];
|
||||||
exports.input = 3;
|
exports.input = 3;
|
||||||
exports.icon = 'cloud-upload';
|
exports.icon = 'cloud-upload';
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ exports.install = function(instance) {
|
||||||
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');
|
||||||
const { bytesToInt, longToByteArray, addZeroBefore } = require('./helper/utils');
|
const { bytesToInt, longToByteArray, addZeroBefore, isEmptyObject, emptyJsObject, writeToFile, addToArrayIfUnique } = require('./helper/utils');
|
||||||
const bitwise = require('bitwise');
|
const bitwise = require('bitwise');
|
||||||
|
|
||||||
var SunCalc = require('./helper/suncalc');
|
var SunCalc = require('./helper/suncalc');
|
||||||
|
|
@ -65,7 +65,8 @@ exports.install = function(instance) {
|
||||||
tb: 1,
|
tb: 1,
|
||||||
http_response: 2,
|
http_response: 2,
|
||||||
dido_controller: 3,
|
dido_controller: 3,
|
||||||
infoSender: 4
|
infoSender: 4,
|
||||||
|
dailyReport: 5
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRIORITY_TYPES = {
|
const PRIORITY_TYPES = {
|
||||||
|
|
@ -139,12 +140,13 @@ exports.install = function(instance) {
|
||||||
let relaysData;
|
let relaysData;
|
||||||
let nodesData;
|
let nodesData;
|
||||||
|
|
||||||
|
// holds dusk, dawn (and more) values
|
||||||
let sunCalcResult;
|
let sunCalcResult;
|
||||||
let reportDuskDawn;
|
|
||||||
|
|
||||||
//helper container for counting resolved group of commands (commands related to set profile)
|
//helper container for counting resolved group of commands (commands related to set profile)
|
||||||
let cmdCounter = {};//key is node, value is counter
|
let cmdCounter = {};//key is node, value is counter
|
||||||
|
|
||||||
|
//TODO: is this set working?? According to previous checks, sets do not work
|
||||||
//if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice
|
//if sending of profile to node fails, we send notification and push node into set, so we do not send notification twice
|
||||||
const nodeProfileSendFail = new Set();
|
const nodeProfileSendFail = new Set();
|
||||||
|
|
||||||
|
|
@ -152,6 +154,22 @@ exports.install = function(instance) {
|
||||||
let temperatureInSenica = null;
|
let temperatureInSenica = null;
|
||||||
let accelerometerInterval = null;
|
let accelerometerInterval = null;
|
||||||
|
|
||||||
|
//NOTE: daily reports senica:
|
||||||
|
//rvo_is_on status, we monitor all nodes - if true, power and dimming should be not 0, if false, 24/7 nodes should be 0, other rvo should not respond
|
||||||
|
let rvo_is_on;
|
||||||
|
let previous_rvo_is_on_value;
|
||||||
|
let handleDailyReport; //setInterval for dailyReportHandler function
|
||||||
|
let dailyReport = {}; //data needed for daily report
|
||||||
|
let reportToSend = {}; //final report which we send to cloud
|
||||||
|
let breakerCounter = null; // status of breakers after flow starts is not in report
|
||||||
|
let rvoPeriod; // interval of checking dusk dawn and if rvo_is_on
|
||||||
|
let initialReportStatus = false;
|
||||||
|
|
||||||
|
const DAILY_REPORT_HANDLER_TIME = 3_600_000;
|
||||||
|
const SET_SUNCALC_RESULT_TIME = 3_600_000;
|
||||||
|
const SET_RVO_PERIOD_TIME = 300_000;
|
||||||
|
const ADD_NODE_TO_REPORT_TIME = 3_600_000;
|
||||||
|
|
||||||
//END OF VARIABLE SETTINGS
|
//END OF VARIABLE SETTINGS
|
||||||
//--------------------------------
|
//--------------------------------
|
||||||
|
|
||||||
|
|
@ -172,24 +190,24 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
sunCalcResult = calculateDuskDawn();
|
sunCalcResult = calculateDuskDawn();
|
||||||
|
|
||||||
reportDuskDawn = {
|
|
||||||
dusk_time: sunCalcResult.dusk_time,
|
|
||||||
dawn_time: sunCalcResult.dawn_time,
|
|
||||||
dusk_time_reported: undefined,
|
|
||||||
dawn_time_reported: undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
handleRsPort();
|
handleRsPort();
|
||||||
|
|
||||||
customTasksInterval = setInterval(function() {
|
customTasksInterval = setInterval(reportEdgeDateTimeAndNumberOfLuminaires, 120_000);
|
||||||
reportEdgeDateTimeAndNumberOfLuminaires();
|
setTimeout(reportEdgeDateTimeAndNumberOfLuminaires, 4000);
|
||||||
}, 120000);
|
|
||||||
reportEdgeDateTimeAndNumberOfLuminaires();
|
//dailyReport related
|
||||||
|
emptyReportToSend();
|
||||||
|
breakerCounter = Object.keys(relaysData).length - 1; // we get number of lines (breakers) except of line 0
|
||||||
|
rvoPeriod = setInterval(setRvoPeriod, SET_RVO_PERIOD_TIME);
|
||||||
|
setTimeout(setRvoPeriod, 3000);
|
||||||
|
setInterval(setSunCalcResult, SET_SUNCALC_RESULT_TIME);
|
||||||
|
handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME);
|
||||||
|
|
||||||
|
|
||||||
setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour
|
setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour
|
||||||
setCorrectPlcTimeOnceADay();
|
setCorrectPlcTimeOnceADay();
|
||||||
|
|
||||||
sendNodeReadout = setInterval(sendNodesData, 150000);
|
sendNodeReadout = setInterval(sendNodesData, 150_000);
|
||||||
accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min
|
accelerometerInterval = setInterval(accelerometerData, 60000 * 30); //30 min
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -792,6 +810,10 @@ exports.install = function(instance) {
|
||||||
info: info
|
info: info
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//to assure, handleDailyReportFunction do not run before rvo_is_on variable changes. So after every line switch we reset the timer
|
||||||
|
clearInterval(handleDailyReport);
|
||||||
|
handleDailyReport = setInterval(dailyReportHandler, DAILY_REPORT_HANDLER_TIME);
|
||||||
|
|
||||||
//logger.debug("linia", line, obj);
|
//logger.debug("linia", line, obj);
|
||||||
instance.send(SEND_TO.dido_controller, obj);
|
instance.send(SEND_TO.dido_controller, obj);
|
||||||
}
|
}
|
||||||
|
|
@ -863,11 +885,10 @@ exports.install = function(instance) {
|
||||||
logger.debug("-->buildTasks clear tasks");
|
logger.debug("-->buildTasks clear tasks");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
processLineProfiles = false;
|
processLineProfiles = params.processLineProfiles;
|
||||||
processBroadcast = false;
|
processBroadcast = false;
|
||||||
processNodes = false;
|
processNodes = false;
|
||||||
|
|
||||||
processLineProfiles = params.processLineProfiles;
|
|
||||||
processLine = params.line;
|
processLine = params.line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -920,6 +941,13 @@ exports.install = function(instance) {
|
||||||
// if astro clock true, we remove all regular profile points
|
// if astro clock true, we remove all regular profile points
|
||||||
time_points = [];
|
time_points = [];
|
||||||
|
|
||||||
|
//TODO: when astro clock == true, is offset calculated ???
|
||||||
|
//let duskAstroClockOffset = profile.dusk_astro_clock_offset;
|
||||||
|
//let dawnAstroClockOffset = profile.dawn_astro_clock_offset;
|
||||||
|
//console.log("line astro clock offsets dusk a dawn: ", duskAstroClockOffset, dawnAstroClockOffset);
|
||||||
|
// maybe add dusk dawn offset to calculateDuskDawn ?? what dusk dawn will be if dawn_lux_sensor == true??
|
||||||
|
//let sunCalcResult = calculateDuskDawn(new Date(), line, duskAstroClockOffset, dawnAstroClockOffset);
|
||||||
|
|
||||||
let sunCalcResult = calculateDuskDawn(new Date(), line);
|
let sunCalcResult = calculateDuskDawn(new Date(), line);
|
||||||
|
|
||||||
// adding dusk dawn to timpoints
|
// adding dusk dawn to timpoints
|
||||||
|
|
@ -1053,7 +1081,7 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
let d = new Date();
|
let d = new Date();
|
||||||
let time = d.getTime();
|
let time = d.getTime();
|
||||||
let sunCalcResult = calculateDuskDawn();
|
//let sunCalcResult = calculateDuskDawn();
|
||||||
|
|
||||||
{
|
{
|
||||||
let params = getParams();
|
let params = getParams();
|
||||||
|
|
@ -1310,49 +1338,154 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function processDailyReport() {
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
if (rvo_is_on) {
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(dailyReport)) {
|
||||||
|
|
||||||
|
if (["name", "time", "dusk_and_dawn"].includes(key)) continue;
|
||||||
|
|
||||||
|
if (value.initialTs) {
|
||||||
|
if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
|
addToArrayIfUnique(reportToSend["night_no_data"], key);
|
||||||
|
console.log('report nedostava ziadne data uz hodinu', key);
|
||||||
|
value.initialTs = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value.dimmingAndPowerAreZeroTime) {
|
||||||
|
if (value.dimmingAndPowerAreZeroTime + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
|
addToArrayIfUnique(reportToSend["night_dimming=0"], key);
|
||||||
|
console.log("report node dimming je 0", key);
|
||||||
|
value.dimmingAndPowerAreZeroTime = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
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 (value.initialTs) {
|
||||||
|
if (value.initialTs + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
|
addToArrayIfUnique(reportToSend["day_24/7_no_data"], key);
|
||||||
|
console.log('node je na 24/7 ale nedostava ziadne data uz hodinu', key);
|
||||||
|
value.initialTs = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value.nodeIsOnButShouldBeOffTime) {
|
||||||
|
if (value.nodeIsOnButShouldBeOffTime + ADD_NODE_TO_REPORT_TIME < now) {
|
||||||
|
addToArrayIfUnique(reportToSend["day_24/7_dimming>0"], key);
|
||||||
|
console.log("report nema svietit ale svieti viac ako hodinu", key);
|
||||||
|
value.nodeIsOnButShouldBeOffTime = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let report = {};
|
||||||
|
report["name"] = SETTINGS.rvo_name;
|
||||||
|
report["time"] = new Date();
|
||||||
|
report["report"] = reportToSend;
|
||||||
|
|
||||||
|
writeToFile(F.path.root("report_data.log"), report, true);
|
||||||
|
instance.send(SEND_TO.dailyReport, report);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function dailyReportHandler() {
|
||||||
|
|
||||||
|
// after dawn we empty reportToSend and start to get data for a new day
|
||||||
|
const date = new Date();
|
||||||
|
const hour = date.getHours();
|
||||||
|
const minute = date.getMinutes();
|
||||||
|
|
||||||
|
console.log("now: ", hour, minute, "suncalc: ", sunCalcResult.dawn_hours, sunCalcResult.dawn_minutes);
|
||||||
|
|
||||||
|
if (hour === sunCalcResult.dawn_hours) {
|
||||||
|
|
||||||
|
//NOTE: ak je este pred usvitom, spracujeme report a posleme na cloud, ak uz je po usvite, resetujeme report plnime data noveho dna
|
||||||
|
if (minute >= sunCalcResult.dawn_minutes - 2) {
|
||||||
|
emptyReportToSend();
|
||||||
|
emptyDailyReport();
|
||||||
|
console.log("Podmienka 1 v dailyReport handler");
|
||||||
|
} else {
|
||||||
|
processDailyReport();
|
||||||
|
emptyReportToSend();
|
||||||
|
emptyDailyReport();
|
||||||
|
console.log("Podmienka 2 v dailyReport handler");
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
} else if (hour === sunCalcResult.dawn_hours + 1 || hour === sunCalcResult.dawn_hours + 2) {
|
||||||
|
if (!initialReportStatus) {
|
||||||
|
emptyReportToSend();
|
||||||
|
emptyDailyReport();
|
||||||
|
initialReportStatus = true;
|
||||||
|
console.log("Podmienka 3 v dailyReport handler");
|
||||||
|
} else {
|
||||||
|
processDailyReport();
|
||||||
|
initialReportStatus = true;
|
||||||
|
console.log("Podmienka 4 v dailyReport handler");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processDailyReport();
|
||||||
|
initialReportStatus = false;
|
||||||
|
console.log("Podmienka 5 v dailyReport handler");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("initialReportStatus: ", initialReportStatus);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function emptyReportToSend() {
|
||||||
|
emptyJsObject(reportToSend);
|
||||||
|
reportToSend["contactor"] = { off: [], on: [] };
|
||||||
|
reportToSend["night_no_data"] = [];
|
||||||
|
reportToSend["night_dimming=0"] = [];
|
||||||
|
reportToSend["day_24/7_no_data"] = [];
|
||||||
|
reportToSend["day_24/7_dimming>0"] = [];
|
||||||
|
//console.log(`je ${sunCalcResult.dawn_hours}:${sunCalcResult.dawn_minutes}, resetuje sa reportToSend: `, reportToSend);
|
||||||
|
console.log(`resetuje sa reportToSend`);
|
||||||
|
}
|
||||||
|
|
||||||
|
//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
|
||||||
|
function emptyDailyReport() {
|
||||||
|
const ts = Date.now();
|
||||||
|
emptyJsObject(dailyReport);
|
||||||
|
|
||||||
|
//NOTE: do dailyReport dame vsetky nody a pravidelne kontrolujeme ci maju data
|
||||||
|
//ked nastane sumrak/usvit a svetla maju zacat/prestat svietit, dailyReport spravime nanovo:
|
||||||
|
for (const [key, value] of Object.entries(nodesData)) {
|
||||||
|
dailyReport[value.node] = { line: value.line, initialTs: ts };
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("dailyReport: ", dailyReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function runTasks() {
|
async function runTasks() {
|
||||||
|
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
|
|
||||||
let currentTimestamp = Date.now();
|
let currentTimestamp = Date.now();
|
||||||
|
|
||||||
//report dusk, dawn---------------------------------
|
|
||||||
if (reportDuskDawn.dusk_time < currentTimestamp) {
|
|
||||||
//vyreportuj iba ak nie je velky rozdiel napr. 60 sekund
|
|
||||||
if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) {
|
|
||||||
//reportovali sme?
|
|
||||||
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);
|
|
||||||
reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var nextDay = new Date();
|
|
||||||
nextDay.setDate(nextDay.getDate() + 1);
|
|
||||||
|
|
||||||
sunCalcResult = calculateDuskDawn(nextDay);
|
|
||||||
reportDuskDawn.dusk_time = sunCalcResult.dusk_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reportDuskDawn.dawn_time < currentTimestamp) {
|
|
||||||
//vyreportuj iba ak nie je velky rozdiel napr. 60 sekund
|
|
||||||
if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) {
|
|
||||||
//reportovali sme?
|
|
||||||
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);
|
|
||||||
reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var nextDay = new Date();
|
|
||||||
nextDay.setDate(nextDay.getDate() + 1);
|
|
||||||
|
|
||||||
sunCalcResult = calculateDuskDawn(nextDay);
|
|
||||||
reportDuskDawn.dawn_time = sunCalcResult.dawn_time;
|
|
||||||
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------
|
|
||||||
|
|
||||||
//sort tasks based on timestamp
|
//sort tasks based on timestamp
|
||||||
tasks.sort(function(a, b) {
|
tasks.sort(function(a, b) {
|
||||||
if (a.timestamp <= currentTimestamp && b.timestamp <= currentTimestamp) {
|
if (a.timestamp <= currentTimestamp && b.timestamp <= currentTimestamp) {
|
||||||
|
|
@ -1409,6 +1542,7 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//kontrola nespracovanych profilov nodov
|
//kontrola nespracovanych profilov nodov
|
||||||
|
//TODO: co ked niektore nody neprijimaju profily? kazdu hodinu zahltuju "tasks" array
|
||||||
if (type == "process_profiles") {
|
if (type == "process_profiles") {
|
||||||
//na vsetky zapnutych liniach sa spracuju nespracovane profily nodov
|
//na vsetky zapnutych liniach sa spracuju nespracovane profily nodov
|
||||||
loadRelaysData();
|
loadRelaysData();
|
||||||
|
|
@ -1426,7 +1560,8 @@ 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);
|
if (timePointName) { sunCalcResult = calculateDuskDawn(date, params.line); console.log("typee-rellay: ", sunCalcResult.dawn_time, sunCalcResult.dusk_time); }
|
||||||
|
|
||||||
|
|
||||||
if (timePointName == "dawn") {
|
if (timePointName == "dawn") {
|
||||||
tasks[0].timestamp = sunCalcResult.dawn_time;
|
tasks[0].timestamp = sunCalcResult.dawn_time;
|
||||||
|
|
@ -1497,7 +1632,6 @@ exports.install = function(instance) {
|
||||||
if (register == 6 && params.recipient === 2) {
|
if (register == 6 && params.recipient === 2) {
|
||||||
|
|
||||||
if (type != "cmd-terminal") {
|
if (type != "cmd-terminal") {
|
||||||
let sunCalcResult = calculateDuskDawn();
|
|
||||||
params.byte1 = sunCalcResult["dusk_hours"];//h
|
params.byte1 = sunCalcResult["dusk_hours"];//h
|
||||||
params.byte2 = sunCalcResult["dusk_minutes"];//m
|
params.byte2 = sunCalcResult["dusk_minutes"];//m
|
||||||
}
|
}
|
||||||
|
|
@ -1506,7 +1640,6 @@ exports.install = function(instance) {
|
||||||
//Time of dawn
|
//Time of dawn
|
||||||
if (register == 7 && params.recipient === 2) {
|
if (register == 7 && params.recipient === 2) {
|
||||||
if (type != "cmd-terminal") {
|
if (type != "cmd-terminal") {
|
||||||
let sunCalcResult = calculateDuskDawn();
|
|
||||||
params.byte1 = sunCalcResult["dawn_hours"];//h
|
params.byte1 = sunCalcResult["dawn_hours"];//h
|
||||||
params.byte2 = sunCalcResult["dawn_minutes"];//m
|
params.byte2 = sunCalcResult["dawn_minutes"];//m
|
||||||
}
|
}
|
||||||
|
|
@ -1583,6 +1716,40 @@ exports.install = function(instance) {
|
||||||
values.comm_status = "OK";
|
values.comm_status = "OK";
|
||||||
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 (rvo_is_on === true) {
|
||||||
|
|
||||||
|
if ("nodeIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].nodeIsOnButShouldBeOffTime;
|
||||||
|
|
||||||
|
if (values.dimming > 0 || values.power > 0) {
|
||||||
|
if ("dimmingAndPowerAreZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingAndPowerAreZeroTime;
|
||||||
|
dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
} else {
|
||||||
|
if (!("dimmingAndPowerAreZeroTime" in dailyReport[node])) dailyReport[node] = { ...dailyReport[node], dimmingAndPowerAreZeroTime: now, initialTs: now };
|
||||||
|
else dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if ("dimmingAndPowerAreZeroTime" in dailyReport[node]) delete dailyReport[node].dimmingAndPowerAreZeroTime;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
if ("nodeIsOnButShouldBeOffTime" in dailyReport[node]) delete dailyReport[node].nodeIsOnButShouldBeOffTime;
|
||||||
|
dailyReport[node] = { ...dailyReport[node], initialTs: now };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//master node
|
//master node
|
||||||
|
|
@ -1811,6 +1978,36 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setSunCalcResult() {
|
||||||
|
//if next day, we get new dusk and dawn. To make sure, in local timezone 2:00 means 00:00 in utc (it means next day)
|
||||||
|
if (new Date().getHours() === 2) {
|
||||||
|
sunCalcResult = calculateDuskDawn();
|
||||||
|
console.log("Novy suncalc: ", sunCalcResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setRvoPeriod() {
|
||||||
|
|
||||||
|
const ts = Date.now();
|
||||||
|
|
||||||
|
previous_rvo_is_on_value = rvo_is_on;
|
||||||
|
|
||||||
|
if (ts < sunCalcResult.dawn_time - 1_800_000) { // nodes should be on (00:00 -> 06:00 ( - pol hodina, lebo rvo vypina skor)
|
||||||
|
rvo_is_on = true;
|
||||||
|
} else if (sunCalcResult.dawn_time - 1_800_000 < ts && ts < sunCalcResult.dusk_time + 1_800_000) { // nodes should be off 06:00 -> 21:00
|
||||||
|
rvo_is_on = false;
|
||||||
|
} else if (sunCalcResult.dusk_time + 1_800_000 < ts) { // nodes should be on 21:00 -> 00:00
|
||||||
|
rvo_is_on = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous_rvo_is_on_value !== rvo_is_on) {
|
||||||
|
emptyDailyReport();
|
||||||
|
console.log("rvo_is: ", rvo_is_on, previous_rvo_is_on_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleRsPort() {
|
function handleRsPort() {
|
||||||
|
|
||||||
if (rsPort) {
|
if (rsPort) {
|
||||||
|
|
@ -1868,6 +2065,11 @@ exports.install = function(instance) {
|
||||||
main();
|
main();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
instance.on("2", _ => {
|
||||||
|
console.log("dailyReport, reportToSend, rvo_is_on", dailyReport, reportToSend, rvo_is_on, previous_rvo_is_on_value);
|
||||||
|
})
|
||||||
|
|
||||||
instance.on("1", async function(flowdata) {
|
instance.on("1", async function(flowdata) {
|
||||||
|
|
||||||
//instance.send(SEND_TO.debug, "on Data");
|
//instance.send(SEND_TO.debug, "on Data");
|
||||||
|
|
@ -1987,6 +2189,9 @@ exports.install = function(instance) {
|
||||||
}
|
}
|
||||||
else if (cmd == "state_of_breaker") {
|
else if (cmd == "state_of_breaker") {
|
||||||
//istic linie
|
//istic linie
|
||||||
|
|
||||||
|
breakerCounter--;
|
||||||
|
|
||||||
let value = flowdata.data.value;
|
let value = flowdata.data.value;
|
||||||
let line = parseInt(flowdata.data.line);
|
let line = parseInt(flowdata.data.line);
|
||||||
|
|
||||||
|
|
@ -2003,8 +2208,14 @@ 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") {
|
||||||
else sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker");
|
sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker");
|
||||||
|
if (breakerCounter < 0) reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendNotification("Cmd-mngr: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker");
|
||||||
|
if (breakerCounter < 0) reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode });
|
||||||
|
}
|
||||||
|
|
||||||
//report status liniu
|
//report status liniu
|
||||||
sendTelemetry({ status: status }, tbname)
|
sendTelemetry({ status: status }, tbname)
|
||||||
|
|
@ -2276,8 +2487,14 @@ exports.install = function(instance) {
|
||||||
if (isObject(relayObject)) line = relayObject.line;
|
if (isObject(relayObject)) line = relayObject.line;
|
||||||
|
|
||||||
// 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) turnLine("off", line, "command received from platform");
|
if (value == false) {
|
||||||
else turnLine("on", line, "command received from platform");
|
turnLine("off", line, "command received from platform");
|
||||||
|
reportToSend["contactor"]["off"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
turnLine("on", line, "command received from platform");
|
||||||
|
reportToSend["contactor"]["on"].push({ [line]: Date.now(), maintenance_mode: SETTINGS.maintenance_mode });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -2472,13 +2689,11 @@ exports.install = function(instance) {
|
||||||
tbHandler.sendToTb(dataToTb, instance);
|
tbHandler.sendToTb(dataToTb, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) {
|
function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) {
|
||||||
|
|
||||||
if (date === undefined) date = new Date();
|
if (date === undefined) date = new Date();
|
||||||
//if(duskOffset === undefined) duskOffset = 0;
|
|
||||||
//if(dawnOffset === undefined) dawnOffset = 0;
|
|
||||||
|
|
||||||
//let line = keys[i];
|
|
||||||
let profilestr = "";
|
let profilestr = "";
|
||||||
if (relaysData[line] != undefined) profilestr = relaysData[line].profile;
|
if (relaysData[line] != undefined) profilestr = relaysData[line].profile;
|
||||||
|
|
||||||
|
|
@ -2492,7 +2707,6 @@ exports.install = function(instance) {
|
||||||
//http://suncalc.net/#/48.5598,18.169,11/2021.04.07/11:06
|
//http://suncalc.net/#/48.5598,18.169,11/2021.04.07/11:06
|
||||||
//https://mapa.zoznam.sk/zisti-gps-suradnice-m6
|
//https://mapa.zoznam.sk/zisti-gps-suradnice-m6
|
||||||
|
|
||||||
|
|
||||||
let dusk_astro_clock_offset = duskOffset;//minutes
|
let dusk_astro_clock_offset = duskOffset;//minutes
|
||||||
let dawn_astro_clock_offset = dawnOffset;//minutes
|
let dawn_astro_clock_offset = dawnOffset;//minutes
|
||||||
|
|
||||||
|
|
@ -2520,9 +2734,6 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//dusk - súmrak
|
|
||||||
//down, sunrise - svitanie
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (profilestr != "") {
|
if (profilestr != "") {
|
||||||
logger.debug(profilestr);
|
logger.debug(profilestr);
|
||||||
|
|
@ -2741,10 +2952,12 @@ exports.install = function(instance) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getObjectByTbValue(object, tbname) {
|
function getObjectByTbValue(object, tbname) {
|
||||||
return object[Object.keys(object).find(key => object[key].tbname === tbname)];
|
return object[Object.keys(object).find(key => object[key].tbname === tbname)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function isObject(item) {
|
function isObject(item) {
|
||||||
return (typeof item === "object" && !Array.isArray(item) && item !== null);
|
return (typeof item === "object" && !Array.isArray(item) && item !== null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -759,6 +759,16 @@
|
||||||
"index": "0",
|
"index": "0",
|
||||||
"id": "1635936391935"
|
"id": "1635936391935"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"5": [
|
||||||
|
{
|
||||||
|
"index": "0",
|
||||||
|
"id": "1757006030239"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": "0",
|
||||||
|
"id": "1757006060377"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"disabledio": {
|
"disabledio": {
|
||||||
|
|
@ -1009,7 +1019,7 @@
|
||||||
"output": []
|
"output": []
|
||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"text": "840.05 MB / 985.68 MB",
|
"text": "858.06 MB / 985.68 MB",
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|
@ -1039,7 +1049,7 @@
|
||||||
"output": []
|
"output": []
|
||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"text": "5.78 GB / 7.26 GB",
|
"text": "5.69 GB / 7.26 GB",
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|
@ -1495,7 +1505,7 @@
|
||||||
"output": []
|
"output": []
|
||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"text": "2.4% / 74.33 MB",
|
"text": "13% / 74.17 MB",
|
||||||
"color": "gray"
|
"color": "gray"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|
@ -2018,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_33_10.0.0.127"
|
"name": "rvo_senica_15_ip114"
|
||||||
},
|
},
|
||||||
"color": "#30E193",
|
"color": "#30E193",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
|
@ -2889,6 +2899,85 @@
|
||||||
"options": {},
|
"options": {},
|
||||||
"color": "#F6BB42",
|
"color": "#F6BB42",
|
||||||
"notes": ""
|
"notes": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1757006030239",
|
||||||
|
"component": "httprequest",
|
||||||
|
"tab": "1615551125555",
|
||||||
|
"name": "192.168.252.2:8015/daily_report",
|
||||||
|
"x": 756.5666656494141,
|
||||||
|
"y": 715.4499969482422,
|
||||||
|
"connections": {
|
||||||
|
"0": [
|
||||||
|
{
|
||||||
|
"index": "0",
|
||||||
|
"id": "1757006045804"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"disabledio": {
|
||||||
|
"input": [],
|
||||||
|
"output": []
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": "",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"url": "http://192.168.252.2:8015/daily_report",
|
||||||
|
"method": "POST",
|
||||||
|
"stringify": "json"
|
||||||
|
},
|
||||||
|
"color": "#5D9CEC",
|
||||||
|
"notes": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1757006045804",
|
||||||
|
"component": "debug",
|
||||||
|
"tab": "1615551125555",
|
||||||
|
"name": "ddd",
|
||||||
|
"x": 1091.566665649414,
|
||||||
|
"y": 711.4499969482422,
|
||||||
|
"connections": {},
|
||||||
|
"disabledio": {
|
||||||
|
"input": [],
|
||||||
|
"output": []
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": "Enabled",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"type": "data",
|
||||||
|
"repository": false,
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"color": "#967ADC",
|
||||||
|
"notes": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1757006060377",
|
||||||
|
"component": "debug",
|
||||||
|
"tab": "1615551125555",
|
||||||
|
"name": "reportDebug",
|
||||||
|
"x": 749.5666656494141,
|
||||||
|
"y": 799.4499969482422,
|
||||||
|
"connections": {},
|
||||||
|
"disabledio": {
|
||||||
|
"input": [],
|
||||||
|
"output": []
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"text": "Enabled",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"type": "data",
|
||||||
|
"repository": false,
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"color": "#967ADC",
|
||||||
|
"notes": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 615
|
"version": 615
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
const fs = require('fs').promises;
|
||||||
|
|
||||||
function bytesToInt(bytes, numberOfBytes) {
|
function bytesToInt(bytes, numberOfBytes) {
|
||||||
let buffer = [];
|
let buffer = [];
|
||||||
if (Array.isArray(bytes)) {
|
if (Array.isArray(bytes)) {
|
||||||
|
|
@ -60,6 +62,10 @@ function isEmptyObject(obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function emptyJsObject(jsObject) {
|
||||||
|
Object.keys(jsObject).forEach(key => delete jsObject[key]);
|
||||||
|
}
|
||||||
|
|
||||||
function convertUTCDateToLocalDate(date) {
|
function convertUTCDateToLocalDate(date) {
|
||||||
var newDate = new Date(date);
|
var newDate = new Date(date);
|
||||||
newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset());
|
newDate.setMinutes(date.getMinutes() + date.getTimezoneOffset());
|
||||||
|
|
@ -70,6 +76,46 @@ function addZeroBefore(n) {
|
||||||
return (n < 10 ? '0' : '') + n;
|
return (n < 10 ? '0' : '') + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously writes data to a file.
|
||||||
|
*
|
||||||
|
* @param {string} filePath The path to the file.
|
||||||
|
* @param {string} data The data to write to the file.
|
||||||
|
* @param {boolean} [append=false] If true, appends the data to the file. If false, it overwrites the file.
|
||||||
|
*/
|
||||||
|
async function writeToFile(filePath, data, append = false) {
|
||||||
|
if (typeof data !== 'string') data = JSON.stringify(data, null, 2);
|
||||||
|
try {
|
||||||
|
if (append) {
|
||||||
|
// Append the data to the end of the file. This is the simplest way to append.
|
||||||
|
await fs.appendFile(filePath, data, 'utf8');
|
||||||
|
console.log(`Successfully appended data to ${filePath} using fs.appendFile.`);
|
||||||
|
} else {
|
||||||
|
// Overwrite the file with the new data.
|
||||||
|
await fs.writeFile(filePath, data, 'utf8');
|
||||||
|
console.log(`Successfully wrote (overwrote) data to ${filePath} using fs.writeFile.`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error writing to file ${filePath}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an item is present in an array and adds it if it's not.
|
||||||
|
* * @param {Array} arr The array to check.
|
||||||
|
* @param {*} item The item to add.
|
||||||
|
* @returns {Array} The modified array.
|
||||||
|
*/
|
||||||
|
const addToArrayIfUnique = (arr, item) => {
|
||||||
|
if (!arr.includes(item)) {
|
||||||
|
arr.push(item);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var convertBase = function() {
|
var convertBase = function() {
|
||||||
|
|
||||||
function convertBase(baseFrom, baseTo) {
|
function convertBase(baseFrom, baseTo) {
|
||||||
|
|
@ -107,6 +153,9 @@ module.exports = {
|
||||||
addZeroBefore,
|
addZeroBefore,
|
||||||
resizeArray,
|
resizeArray,
|
||||||
isEmptyObject,
|
isEmptyObject,
|
||||||
|
emptyJsObject,
|
||||||
sleep,
|
sleep,
|
||||||
convertUTCDateToLocalDate
|
convertUTCDateToLocalDate,
|
||||||
|
writeToFile,
|
||||||
|
addToArrayIfUnique
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
readme.md
17
readme.md
|
|
@ -1,15 +1,10 @@
|
||||||
[](https://www.totaljs.com/support/)
|
# Total.js version 4 - Flow
|
||||||
|
|
||||||
- [__Live chat with professional support__](https://messenger.totaljs.com)
|
This is a version of citysys-flowserver, running on Debian12 OS.
|
||||||
- [__HelpDesk with professional support__](https://helpdesk.totaljs.com)
|
It has the latest LTS version of nodejs and latest npm modules installed.
|
||||||
- [Documentation](https://docs.totaljs.com)
|
|
||||||
- [Wiki](https://wiki.totaljs.com)
|
|
||||||
|
|
||||||
# Total.js: Empty Project - Flow
|
|
||||||
|
|
||||||
- download example
|
|
||||||
- open terminal / command-line
|
- open terminal / command-line
|
||||||
- open app directory
|
- open app directory
|
||||||
- install latest version of Total.js from NPM `$ npm install total.js`
|
- run `$ npm install`
|
||||||
- run `$ node debug.js`
|
- run `$ node index.js`
|
||||||
- open browser `http://127.0.0.1:8000`
|
- open browser `http://0.0.0.0:12345`
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue