diff --git a/config b/config
index 287769b..25ee651 100644
--- a/config
+++ b/config
@@ -7,7 +7,6 @@ package#flow (Object) : { url: '/' }
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.settings : rvo_name:string|lang:string|temperature_adress:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_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
+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
table.pins : pin:string|type:string|line:number
table.notifications : key:string|weight:string|sk:string|en:string
-table.status : thermometer:string|em:string|twilight_sensor:string
diff --git a/createNode.py b/createNode.py
new file mode 100644
index 0000000..21406cc
--- /dev/null
+++ b/createNode.py
@@ -0,0 +1,43 @@
+print("zaciname")
+import re, json
+
+search_str = '|'
+final = []
+counter = 1
+with open("/home/unipi/flowserver/databases/nodes.table", 'r') as file:
+# with open("/home/rasta5man/dev/oms/flowserver/databases/nodes.table", 'r') as file:
+ # Read each line in the file
+ for line in file:
+ # Print each line
+ line = line.strip()
+ print(line)
+ if counter != 1:
+ i = [m.start() for m in re.finditer(re.escape(search_str), line)]
+ node = line[ i[0] + 1 : i[1] ]
+ tbname = line[ i[1] + 1 : i[2] ]
+ final.append({node:tbname})
+ counter += 1
+print(json.dumps(final))
+f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w")
+f.write(json.dumps(final))
+f.close()
+
+
+#
+# # ``d`` has to be replaced with a different character
+# old_character = "'"
+#
+# # ``t`` will replace ``d`
+# new_character = '"'
+# resultant_string = 0;
+# with open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", 'r') as file:
+# for line in file:
+# resultant_string = re.sub("'", '"', line)
+#
+# resultant_string = re.sub(" ", "", resultant_string)
+# print(resultant_string)
+#
+# f = open("/home/unipi/flowserver/databases/nodes_original/nodes_original.table", "w")
+# f.write(str(resultant_string))
+# f.close()
+#
diff --git a/databases/nodes_original/nodes_original.table b/databases/nodes_original/nodes_original.table
new file mode 100644
index 0000000..d8670f9
--- /dev/null
+++ b/databases/nodes_original/nodes_original.table
@@ -0,0 +1 @@
+[{"3815": "B5EoxeMVp4zwr8nqW0GjjoARjvD1PNamOGbLg63Z"}, {"3799": "roKgWqY95V3mXMRzyAjmmj7bLjexpJPvaGDBw826"}]
diff --git a/databases/notifications.table b/databases/notifications.table
index 77f9e7a..8e3788f 100644
--- a/databases/notifications.table
+++ b/databases/notifications.table
@@ -34,4 +34,5 @@ key:string|weight:string|sk:string|en:string
+|twilight_sensor_ok|NOTICE|Sensor súmraku znovu odpovedá|Twilight sensor is responding again|...............
+|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|...............
+|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|...............
-+|flow_restart|NOTICE|Restart flowu|Flow has been restarted|...............
\ No newline at end of file
++|flow_restart|NOTICE|Restart flowu|Flow has been restarted|...............
++|nodes_db_changed|NOTICE|Zmena v node databaze|Node db has changed|...............
diff --git a/databases/relays.table b/databases/relays.table
index 68e4f06..40843b1 100644
--- a/databases/relays.table
+++ b/databases/relays.table
@@ -1,5 +1,5 @@
line:number|tbname:string|contactor:number|profile:string
+|0|6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq|1||...........
-+|1|JzwxZXOvDj1bVrN4nkWw9Qk8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
-+|2|g9OxBZ5KRwNznlY6pAp6mxkWXvjdEL4eGQobMDy2|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
-+|3|OzNMgZ9n43qPbjXmy7zWMJA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
++|1|JzwxZXOvDj1bVrN4nkWw9Qk8qdyBl3MRKLpGPgaQ|9|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
++|2|g9OxBZ5KRwNznlY6pAp6mxkWXvjdEL4eGQobMDy2|9|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
++|3|OzNMgZ9n43qPbjXmy7zWMJA2DKdYvW5e6pxGRrVa|9|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|...........
diff --git a/databases/status.table b/databases/status.table
deleted file mode 100644
index 6d4f686..0000000
--- a/databases/status.table
+++ /dev/null
@@ -1,2 +0,0 @@
-thermometer:string|em:string|twilight_sensor:string
-+|OK|OK|OK|.............
diff --git a/flow/cmd_manager.js b/flow/cmd_manager.js
index d84daf3..ed4a928 100644
--- a/flow/cmd_manager.js
+++ b/flow/cmd_manager.js
@@ -113,7 +113,7 @@ exports.install = function(instance) {
priorities["79"] = minutes;
priorities["84"] = minutes;
- minutes = 10;
+ minutes = 10;
priorities["87"] = minutes;
priorities["6"] = minutes;
priorities["7"] = minutes;
@@ -123,7 +123,7 @@ exports.install = function(instance) {
priorities["89"] = minutes;
//prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming)
- let listOfCommands = [0,1,3,6,7,8,74,75,76,77,78,79,80,84,87,89];
+ let listOfCommands = [0, 1, 3, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 84, 87, 89];
const errorHandler = new ErrorToServiceHandler();
@@ -146,8 +146,7 @@ exports.install = function(instance) {
//--------------------------------
- function main()
- {
+ function main() {
GLOBALS = FLOW.GLOBALS;
SETTINGS = FLOW.GLOBALS.settings;
relaysData = GLOBALS.relaysData;
@@ -166,7 +165,7 @@ exports.install = function(instance) {
let now = new Date();
console.log("CMD Manager installed", now.toLocaleString("sk-SK"));
-
+
sunCalcResult = calculateDuskDawn();
reportDuskDawn = {
@@ -180,7 +179,7 @@ exports.install = function(instance) {
//to ensure, edgeDateTime will be send to tb at full minute
customTasksInterval = setInterval(function() {
- if(new Date().getSeconds() === 0) reportEdgeDateTimeAndNumberOfLuminaires();
+ if (new Date().getSeconds() === 0) reportEdgeDateTimeAndNumberOfLuminaires();
}, 1000);
setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour
@@ -188,22 +187,19 @@ exports.install = function(instance) {
}
- function cmdCounterResolve(address)
- {
- if(cmdCounter.hasOwnProperty(address))
- {
+ function cmdCounterResolve(address) {
+ if (cmdCounter.hasOwnProperty(address)) {
cmdCounter[address] = cmdCounter[address] - 1;
-
+
let result = cmdCounter[address];
- if(result == 0) delete cmdCounter[address];
+ if (result == 0) delete cmdCounter[address];
return result;
}
return -1;
}
- function getParams(priority)
- {
+ function getParams(priority) {
let params = {};
//core rpc values
@@ -221,12 +217,11 @@ exports.install = function(instance) {
//params.tbname = tbname;
params.priority = PRIORITY_TYPES.node_cmd; //default priority - if more tasks with the same timestamp, we sort them based on priority
params.timestamp = 0; //execution time - if timestamp < Date.now(), the task is processed
- if(priority != undefined )
- {
+ if (priority != undefined) {
params.timestamp = priority;
params.priority = priority;
}
-
+
params.addMinutesToTimestamp = 0;//repeat task if value is > 0,
//params.timePointName = "luxOff" // "luxOn", "dusk", "dawn", "profileTimepoint"
@@ -238,10 +233,8 @@ exports.install = function(instance) {
//nastav profil nodu
- function processNodeProfile(node)
- {
- if(rotary_switch_state != "Automatic")
- {
+ function processNodeProfile(node) {
+ if (rotary_switch_state != "Automatic") {
logger.debug("unable to process profile for node", node, "rotary_switch_state != Automatic");
return;
}
@@ -249,21 +242,19 @@ exports.install = function(instance) {
let nodeObj = nodesData[node];
let line = nodeObj.line;
- if(relaysData[line].contactor == 0)
- {
+ if (relaysData[line].contactor == 0) {
logger.debug("line line is off", line, node);
return;
}
- if(nodeObj.processed == 1)
- {
+ if (nodeObj.processed == 1) {
//logger.debug("node was already processed", node);
return;
}
let nodeProfile = nodeObj.profile;
logger.debug("processNodeProfile: start - set profile for ", node, nodeProfile);
- if(nodeProfile) {
+ if (nodeProfile) {
try {
nodeProfile = JSON.parse(nodeProfile);
@@ -277,10 +268,9 @@ exports.install = function(instance) {
let timestamp = PRIORITY_TYPES.node_cmd;
- removeTask({type: "set_node_profile", address: node});
+ removeTask({ type: "set_node_profile", address: node });
- if(nodeProfile === "")
- {
+ if (nodeProfile === "") {
//vypneme profil nodu, posleme cmd
//Pokiaľ je hodnota rovná 1 – Profil sa zapne, ostatné bity sa nezmenia.
//Pokiaľ sa hodnota rovná 2 – profil sa vypne, ostatné bity sa nezmenia
@@ -305,8 +295,7 @@ exports.install = function(instance) {
tasks.push(params);
}
- else
- {
+ else {
let tasksProfile = [];
//vypneme profil - Zapísať hodnotu 32 do registra Time Schedule Settings – reset profilu
@@ -332,11 +321,10 @@ exports.install = function(instance) {
//TS1 Time point a TS1 Time Point Levels
let register = 9;
- for(let i = 0; i < nodeProfile.intervals.length; i++)
- {
+ for (let i = 0; i < nodeProfile.intervals.length; i++) {
let obj = nodeProfile.intervals[i];
//let timePoint = obj.time_point;
- let dim_value = obj.value;
+ let dim_value = obj.value;
//Reg 9 až Reg 40
@@ -350,12 +338,12 @@ exports.install = function(instance) {
Register úrovne má rovnaký formát ako dimming register (Reg 1).
*/
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- //params.byte1 = 0;//msb, podla dokumentacie data3
- //params.byte2 = 0;//podla dokumentacie data2
- //params.byte3 = 0;//podla dokumentacie data1
- //params.byte4 = 0;//lsb, podla dokumentacie data0
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ //params.byte1 = 0;//msb, podla dokumentacie data3
+ //params.byte2 = 0;//podla dokumentacie data2
+ //params.byte3 = 0;//podla dokumentacie data1
+ //params.byte4 = 0;//lsb, podla dokumentacie data0
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
let start_time = obj.start_time;
let t = start_time.split(":");
@@ -428,8 +416,7 @@ exports.install = function(instance) {
params.addMinutesToTimestamp = 0;
params.info = "Threshold lux level for DUSK/DAWN";
- if(nodeProfile.dusk_lux_sensor)
- {
+ if (nodeProfile.dusk_lux_sensor) {
let v = nodeProfile.dusk_lux_sensor_value;
let ba = longToByteArray(v);
@@ -437,8 +424,7 @@ exports.install = function(instance) {
params.byte2 = ba[0];
}
- if(nodeProfile.dawn_lux_sensor)
- {
+ if (nodeProfile.dawn_lux_sensor) {
let v = nodeProfile.dawn_lux_sensor_value;
let ba = longToByteArray(v);
@@ -466,8 +452,7 @@ exports.install = function(instance) {
params.addMinutesToTimestamp = 0;
params.info = "DUSK/DAWN max. adjust period";
- if(nodeProfile.astro_clock)
- {
+ if (nodeProfile.astro_clock) {
let v = nodeProfile.dusk_lux_sensor_time_window;
let ba = longToByteArray(v);
@@ -475,8 +460,7 @@ exports.install = function(instance) {
params.byte2 = ba[0];
}
- if(nodeProfile.astro_clock)
- {
+ if (nodeProfile.astro_clock) {
let v = nodeProfile.dawn_lux_sensor_time_window;
let ba = longToByteArray(v);
@@ -495,7 +479,7 @@ exports.install = function(instance) {
//Statický offset pre časy úsvitu a súmraku. Byte 1 je pre DUSK, Byte 0 je pre DAWN. Formát:
//Bity 0 – 6: hodnota v minútach
//Bit 7: znamienko (1 – mínus)
-
+
logger.debug("processNodeProfile: Static offset", node);
let params = getParams(PRIORITY_TYPES.node_cmd);
@@ -508,26 +492,21 @@ exports.install = function(instance) {
params.addMinutesToTimestamp = 0;
params.info = "Static offset";
- if(nodeProfile.astro_clock)
- {
+ if (nodeProfile.astro_clock) {
let dusk_astro_clock_offset = parseInt(nodeProfile.dusk_astro_clock_offset);
let dawn_astro_clock_offset = parseInt(nodeProfile.dawn_astro_clock_offset);
- if(dusk_astro_clock_offset < 0)
- {
+ if (dusk_astro_clock_offset < 0) {
params.byte3 = (dusk_astro_clock_offset * -1) + 128;
}
- else
- {
+ else {
params.byte3 = dusk_astro_clock_offset;
}
- if(dawn_astro_clock_offset < 0)
- {
+ if (dawn_astro_clock_offset < 0) {
params.byte4 = (dawn_astro_clock_offset * -1) + 128;
}
- else
- {
+ else {
params.byte4 = dawn_astro_clock_offset;
}
}
@@ -555,8 +534,7 @@ exports.install = function(instance) {
bits.push(0);
bits.push(0);
bits.push(0);
- if(nodeProfile.astro_clock == true)
- {
+ if (nodeProfile.astro_clock == true) {
//Bit 4 – ak je nastavený profil sa riadi podľa astrohodín, a je 0 tak profil je jednoduchý
bits.push(1);
}
@@ -575,14 +553,14 @@ exports.install = function(instance) {
bits = [];
//Bit 0 (LSB) – riadenie súmraku podľa lux senzoru (1 – zapnuté). Súmrak sa môže posúvať v rámci času v registri 97 podľa intenzity osvetlenia
- if(nodeProfile.dusk_lux_sensor == true)//sumrak
+ if (nodeProfile.dusk_lux_sensor == true)//sumrak
{
bits.push(1);
}
else bits.push(0);
//Bit 1 - riadenie úsvitu podľa lux senzoru (1 – zapnuté). Úsvit sa môže posúvať v rámci času v registri 97 podľa intenzity osvetlenia
- if(nodeProfile.dawn_lux_sensor == true)//usvit
+ if (nodeProfile.dawn_lux_sensor == true)//usvit
{
bits.push(1);
}
@@ -608,7 +586,7 @@ exports.install = function(instance) {
cmdCounter[node] = tasksProfile.length;
//tasks.push(tasksProfile);
- tasks = tasks.concat(tasksProfile);
+ tasks = tasks.concat(tasksProfile);
}
@@ -618,100 +596,88 @@ exports.install = function(instance) {
}
- function cleanUpRefFlowdataObj()
- {
+ function cleanUpRefFlowdataObj() {
let now = new Date();
let timestamp = now.getTime();
//clear old refFlowdata references
let keys = Object.keys(refFlowdataObj);
- for(let i = 0; i < keys.length; i++)
- {
+ for (let i = 0; i < keys.length; i++) {
let timestampKey = keys[i];
- if((timestamp - timestampKey) > 60*1000 )
- {
+ if ((timestamp - timestampKey) > 60 * 1000) {
console.log("cleanUpRefFlowdataObj delete", timestampKey);
- delete refFlowdataObj[ timestampKey ];
+ delete refFlowdataObj[timestampKey];
}
}
}
- function removeTask(obj)
- {
+ function removeTask(obj) {
let keys = Object.keys(obj);
tasks = tasks.filter((task) => {
let counter = 0;
- for(let i = 0; i < keys.length; i++)
- {
+ for (let i = 0; i < keys.length; i++) {
let key = keys[i];
- if(task.hasOwnProperty(key) && obj.hasOwnProperty(key))
- {
- if(task[key] == obj[key]) counter++;
+ if (task.hasOwnProperty(key) && obj.hasOwnProperty(key)) {
+ if (task[key] == obj[key]) counter++;
}
}
-
- if(counter == keys.length) return false;
+
+ if (counter == keys.length) return false;
return true;
});
}
- process.on('uncaughtException', function (err) {
+ process.on('uncaughtException', function(err) {
//TODO send to service
-
+
errLogger.error('uncaughtException:', err.message)
errLogger.error(err.stack);
errorHandler.sendMessageToService(err.message + "\n" + err.stack, 0, "js_error");
//process.exit(1);
})
-
+
//te();//force error
- function processAllNodeProfilesOnLine(line)
- {
+ function processAllNodeProfilesOnLine(line) {
for (let k in nodesData) {
- if(line == nodesData[k].line)
- {
+ if (line == nodesData[k].line) {
let node = nodesData[k].node;
let processed = nodesData[k].processed;
- if(!processed) processNodeProfile(node);
+ if (!processed) processNodeProfile(node);
//else logger.debug( `Node ${node} profile for line ${nodesData[k].line} was already processed`);
}
- }
- }
-
-
- function loadRelaysData(line)
- {
- for (const [key, value] of Object.entries(relaysData))
- {
- if(key == "0") continue;
- if(line != undefined)
- {
- //ak sa jedna o update profilu linie - pozor dido_controller posiela command pre loadRelaysData
- if(line != value.line) continue;
- }
-
- if(value.contactor == 1) processAllNodeProfilesOnLine(value.line);
}
}
- function reportOnlineNodeStatus(line)
- {
+ function loadRelaysData(line) {
+ for (const [key, value] of Object.entries(relaysData)) {
+ if (key == "0") continue;
+ if (line != undefined) {
+ //ak sa jedna o update profilu linie - pozor dido_controller posiela command pre loadRelaysData
+ if (line != value.line) continue;
+ }
+
+ if (value.contactor == 1) processAllNodeProfilesOnLine(value.line);
+ }
+ }
+
+
+ function reportOnlineNodeStatus(line) {
//broadcast cas, o 3 sek neskor - status, brightness
//Po zapnutí línie broadcastovo aktualizovať predtým čas.
logger.debug("--->reportOnlineNodeStatus for line", line);
//return;
-
+
//run broadcast //Actual time
addMinutesToTimestamp = 0;
@@ -729,41 +695,40 @@ exports.install = function(instance) {
params.byte2 = minutes;//m
params.byte3 = seconds;//s
params.byte4 = 0;
- params.recipient = 2;//2 broadcast, address = 0
+ params.recipient = 2;//2 broadcast, address = 0
params.register = 87;//Actual time
params.rw = 1;//write
//other values
params.type = "cmd";
- params.timestamp = Date.now() + 60000;
+ params.timestamp = Date.now() + 60000;
params.addMinutesToTimestamp = addMinutesToTimestamp;
params.info = "run broadcast: Actual time";
tasks.push(params);
let sec = 3;
- setTimeout(function(){
+ setTimeout(function() {
//Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel
for (let k in nodesData) {
-
+
//potrebujem nody k danej linii
- if(line == nodesData[k].line || line == undefined)
- {
+ if (line == nodesData[k].line || line == undefined) {
let tbname = nodesData[k].tbname;
let node = nodesData[k].node;
let status = "NOK";
// if status of node was "OK" before switching it off, we set the node's time_of_last_communication on time, it was switched on again and send OK status to tb.
- if(nodesData[k].status) {
+ if (nodesData[k].status) {
status = "OK";
nodesData[k].time_of_last_communication = time;
}
-
- sendTelemetry({status: status}, tbname, time);
+
+ sendTelemetry({ status: status }, tbname, time);
//prud, vykon - current, input power pre liniu pre vsetky nody
-
+
//a pridame aj vyreportovanie dimmingu
{
let params = getParams(PRIORITY_TYPES.high_priority);
@@ -816,12 +781,11 @@ exports.install = function(instance) {
}
}
}
- },sec*1000);
+ }, sec * 1000);
}
- function reportOfflineNodeStatus(line)
- {
+ function reportOfflineNodeStatus(line) {
logger.debug("--->reportOfflineNodeStatus for line", line);
values = {};
@@ -829,45 +793,31 @@ exports.install = function(instance) {
values["power"] = 0;//výkon
values["current"] = 0;//prúd
values["status"] = "OFFLINE";
-
+
const date = Date.now();
// it happens, that some data did not get to tb after sending
// we setTimeout to make more time for db to process telemetry (eg 150 messages at once)
Object.keys(nodesData).forEach((node, index) => {
-
+
setTimeout(function() {
-
- //potrebujem nody k danej linii
- if(line == nodesData[node].line || line == undefined)
- {
- let tbname = nodesData[node].tbname;
- sendTelemetry(values, tbname, date)
- }
- },(index+1) * 300);
+ //potrebujem nody k danej linii
+ if (line == nodesData[node].line || line == undefined) {
+ let tbname = nodesData[node].tbname;
+ sendTelemetry(values, tbname, date)
+ }
+
+ }, (index + 1) * 1000);
})
-
+
}
- function turnOnLine(line, info)
- {
+ function turnLine(onOrOff, line, info) {
let obj = {
line: line,
- command: "turnOn",
- info: info
- };
-
- logger.debug("linia", line, obj);
- instance.send(SEND_TO.dido_controller, obj);
- }
-
- function turnOffLine(line, info)
- {
- let obj = {
- line: line,
- command: "turnOff",
+ command: onOrOff,
info: info
};
@@ -876,43 +826,40 @@ exports.install = function(instance) {
}
- function detectIfResponseIsValid(bytes)
- {
+
+ function detectIfResponseIsValid(bytes) {
//ak sa odpoved zacina 0 - je to v poriadku, inak je NOK
let type = "RESPONSE";
- if(bytes.length == 1) type = "BROADCAST"; // odpoved z rsPortu na broadcast command: ["broadcast"]
- else if(bytes[4] == 0) type = "RESPONSE";
- else if(bytes[4] == 1) type = "ERROR";
- else if(bytes[4] == 2) type = "EVENT";
+ if (bytes.length == 1) type = "BROADCAST"; // odpoved z rsPortu na broadcast command: ["broadcast"]
+ else if (bytes[4] == 0) type = "RESPONSE";
+ else if (bytes[4] == 1) type = "ERROR";
+ else if (bytes[4] == 2) type = "EVENT";
else type = "UNKNOWN";
-
+
let message = "OK";
let error = "";
- if(type == "BROADCAST") return {message, type, error};
+ if (type == "BROADCAST") return { message, type, error };
let crc = crc16('ARC', bytes.slice(0, 9));
let c1 = (crc >> 8) & 0xFF;
let c2 = crc & 0xFF;
-
- if(c1 != bytes[9])
- {
+
+ if (c1 != bytes[9]) {
//CRC_ERROR
message = "NOK";
error = "CRC_ERROR c1";
instance.send(SEND_TO.debug, "CRC_ERROR c1");
}
-
- if(c2 != bytes[10])
- {
+
+ if (c2 != bytes[10]) {
//CRC_ERROR
message = "NOK";
error = "CRC_ERROR c2";
instance.send(SEND_TO.debug, "CRC_ERROR c2");
}
-
+
//crc error
- if(type != "RESPONSE")
- {
+ if (type != "RESPONSE") {
instance.send(SEND_TO.debug, bytes);
instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]);
@@ -922,14 +869,13 @@ exports.install = function(instance) {
message = "NOK";
}
-
- return {message, type, error};
+
+ return { message, type, error };
}
//BUILD TASKS//
- function buildTasks(params)
- {
+ function buildTasks(params) {
//report SETTINGS.edge_fw_version as fw_version
//report date as startdate
@@ -944,14 +890,12 @@ exports.install = function(instance) {
let processBroadcast = true;
let processNodes = true;
- if(params == undefined)
- {
+ if (params == undefined) {
init = true;
tasks = [];
logger.debug("-->buildTasks clear tasks");
}
- else
- {
+ else {
processLineProfiles = false;
processBroadcast = false;
processNodes = false;
@@ -960,23 +904,18 @@ exports.install = function(instance) {
processLine = params.line;
}
- //load profiles pre linie
- //relaysData[ record["line"] ]
-
+ //load profiles pre vsetky linie:
let now = new Date();
- if(processLineProfiles)
- {
+ if (processLineProfiles) {
//process line profiles
let keys = Object.keys(relaysData);
- for(let i = 0; i < keys.length; i++)
- {
+ for (let i = 0; i < keys.length; i++) {
let line = parseInt(keys[i]); //line is turned off by default
let profilestr = relaysData[line].profile;
- if(processLine != undefined)
- {
- if(processLine != line) continue;
+ if (processLine != undefined) {
+ if (processLine != line) continue;
}
try {
@@ -984,14 +923,14 @@ exports.install = function(instance) {
/**
* we process line profiles: timepoints, astro clock, lux_sensor, offsets ...
*/
- if(profilestr === "") throw ("Profile is not defined");
+ if (profilestr === "") throw ("Profile is not defined");
let profile = JSON.parse(profilestr);
- if(Object.keys(profile).length === 0) throw ("Profile is empty");
+ if (Object.keys(profile).length === 0) throw ("Profile is empty");
monitor.info("buildTasks: profile for line", line);
monitor.info("profile:", profile);
- let time_points= profile.intervals;
+ let time_points = profile.intervals;
// add name to regular profile timepoint and delete unused end_time key:
time_points.forEach(point => {
@@ -1001,17 +940,13 @@ exports.install = function(instance) {
//monitor.info("buildTasks: time_points", time_points);
- let currentValue = 0;
- if(time_points.length > 0) currentValue = time_points[time_points.length - 1].value;
-
/**
* if astro_clock is true, we create timepoints, that switch on/off relays accordingly.
* we need to manage, astro clock timepoints has the greatest priority - normal timepoints will not switch off/on lines before dusk or dawn
* if dawn/dusk_lux_sensor is true, it has higher priority than astro_clock switching
*/
- if(profile.astro_clock == true)
- {
+ if (profile.astro_clock == true) {
// if astro clock true, we remove all regular profile points
time_points = [];
@@ -1019,74 +954,60 @@ exports.install = function(instance) {
let sunCalcResult = calculateDuskDawn(new Date(), line);
// adding dusk dawn to timpoints
- if(profile.dawn_lux_sensor == false) time_points.push({"start_time": sunCalcResult["dawn"], "value": 0, "name":"dawn"});
- if(profile.dusk_lux_sensor == false) time_points.push({"start_time": sunCalcResult["dusk"], "value": 1, "name":"dusk"});
+ if (profile.dawn_lux_sensor == false) time_points.push({ "start_time": sunCalcResult["dawn"], "value": 0, "name": "dawn" });
+ if (profile.dusk_lux_sensor == false) time_points.push({ "start_time": sunCalcResult["dusk"], "value": 1, "name": "dusk" });
//if dusk/dawn is true, lines will switch on/off according to lux_sensor value. In case it fails, we create lux_timepoints, to make sure lines will switch on/off (aby nam to nezostalo svietit)
//force to turn off after timestamp: dawn + dawn_lux_sensor_time_window
- if(profile.dawn_lux_sensor == true)
- {
- let [ahours, aminutes, aseconds] = sunCalcResult["dawn"].split(':');
- let ad = new Date();
- ad.setHours(parseInt(ahours));
- ad.setMinutes(parseInt(aminutes) + profile.dawn_lux_sensor_time_window);
- ad.setSeconds(0);
+ if (profile.dawn_lux_sensor == true) {
+ let [ahours, aminutes] = sunCalcResult["dawn"].split(':');
+ let ad = new Date();
+ ad.setHours(parseInt(ahours), parseInt(aminutes) + profile.dawn_lux_sensor_time_window, 0);
- let strDate = ad.getHours() + ":" + ad.getMinutes();
-
- time_points.push({"value": 0, "start_time": strDate, "name": "luxOff"});
+ let strDate = ad.getHours() + ":" + ad.getMinutes();
+ time_points.push({ "value": 0, "start_time": strDate, "name": "luxOff" });
}
- if(profile.dusk_lux_sensor == true)
- {
- let [ahours, aminutes, aseconds] = sunCalcResult["dusk"].split(':');
- let ad = new Date();
- ad.setHours(parseInt(ahours));
- ad.setMinutes(parseInt(aminutes) + profile.dusk_lux_sensor_time_window);
- ad.setSeconds(0);
+ if (profile.dusk_lux_sensor == true) {
+ let [ahours, aminutes] = sunCalcResult["dusk"].split(':');
+ let ad = new Date();
+ ad.setHours(parseInt(ahours), parseInt(aminutes) + profile.dusk_lux_sensor_time_window, 0);
- let strDate = ad.getHours() + ":" + ad.getMinutes();
-
- time_points.push({"value": 1, "start_time": strDate, "name": "luxOn"});
- //time_points.push({"value": 1, "start_time": "15:19", "name": "luxOn"}); //testing
+ let strDate = ad.getHours() + ":" + ad.getMinutes();
+ time_points.push({ "value": 1, "start_time": strDate, "name": "luxOn" });
+ //time_points.push({"value": 1, "start_time": "15:19", "name": "luxOn"}); //testing
}
}
//sort time_points
- time_points.sort(function (a, b) {
+ time_points.sort(function(a, b) {
+
+ let [ahours, aminutes] = a.start_time.split(':');
+ let [bhours, bminutes] = b.start_time.split(':');
- let [ahours, aminutes, aseconds] = a.start_time.split(':');
- let [bhours, bminutes, bseconds] = b.start_time.split(':');
-
let ad = new Date();
- ad.setHours( parseInt(ahours) );
- ad.setMinutes( parseInt(aminutes) );
- ad.setSeconds(0);
-
+ ad.setHours(parseInt(ahours), parseInt(aminutes), 0);
+
let bd = new Date();
- bd.setHours( parseInt(bhours) );
- bd.setMinutes( parseInt(bminutes) );
- ad.setSeconds(0);
-
+ bd.setHours(parseInt(bhours), parseInt(bminutes), 0);
+
return ad.getTime() - bd.getTime();
});
console.log("line timepoints ........", time_points);
- monitor.info("-->comming events turn on/off lines:");
- for(let t = 0; t < time_points.length; t++)
- {
-
- let start_time = new Date();
- let [hours, minutes, seconds] = time_points[t].start_time.split(':');
+ let currentValue = 0;
+ if (time_points.length > 0) currentValue = time_points[time_points.length - 1].value;
- start_time.setHours( parseInt(hours) );
- start_time.setMinutes( parseInt(minutes) );
- start_time.setSeconds(0);
-
- //task is the past
- if(now.getTime() > start_time.getTime())
- {
+ monitor.info("-->comming events turn on/off lines:");
+ for (let t = 0; t < time_points.length; t++) {
+
+ let start_time = new Date();
+ let [hours, minutes] = time_points[t].start_time.split(':');
+ start_time.setHours(parseInt(hours), parseInt(minutes), 0);
+
+ //task is in the past
+ if (now.getTime() > start_time.getTime()) {
currentValue = time_points[t].value;
//timepoint is in past, we add 24 hours
@@ -1103,32 +1024,30 @@ exports.install = function(instance) {
params.addMinutesToTimestamp = 0;
// it timepoints are not calculated (dawn, dusk, lux_timepoint), but static points in line profile, we just repeat the task every day
- if(time_points[t].name == "profileTimepoint") params.addMinutesToTimestamp = 24*60;
+ if (time_points[t].name == "profileTimepoint") params.addMinutesToTimestamp = 24 * 60;
//astro timepoints will be recalculated dynamically:
params.timePointName = time_points[t].name;
// if astro timepoint, we save time window:
- if(['luxOn', 'luxOff', 'dusk','dawn'].includes(params.timePointName))
- {
+ if (['luxOn', 'luxOff', 'dusk', 'dawn'].includes(params.timePointName)) {
params.dawn_lux_sensor_time_window = profile.dawn_lux_sensor_time_window;
params.dusk_lux_sensor_time_window = profile.dusk_lux_sensor_time_window;
}
- if(params.value == 0) params.info = `${params.timePointName}: turn off line: ` + line;
- else if(params.value == 1) params.info = `${params.timePointName}: turn on line: ` + line;
+ if (params.value == 0) params.info = `${params.timePointName}: turn off line: ` + line;
+ else if (params.value == 1) params.info = `${params.timePointName}: turn on line: ` + line;
params.debug = true;
//turn on/off line
tasks.push(params);
- monitor.info(params.info, start_time);
-
+ monitor.info("TimePoint params: ", params.info, start_time);
}
monitor.info("-->time_points final", line, time_points);
- //ensure to turn on/off according to calculated value
+ //ensure to turn on/off according to calculated currentValue
let params = getParams(PRIORITY_TYPES.terminal);
params.type = "relay";
params.line = parseInt(line);
@@ -1143,14 +1062,13 @@ exports.install = function(instance) {
monitor.info("-->currentValue for relay", line, currentValue);
//turn on/off line
- if(params.value == 0) params.info = "turn off line on startup: " + line;
- else if(params.value == 1) params.info = "turn on line on startup: " + line;
+ if (params.value == 0) params.info = "turn off line on startup: " + line;
+ else if (params.value == 1) params.info = "turn on line on startup: " + line;
tasks.push(params);
} catch (error) {
- if(profilestr !=="" )
- {
+ if (profilestr !== "") {
//errLogger.error(profilestr, error);
errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error");
}
@@ -1166,29 +1084,28 @@ exports.install = function(instance) {
//PROCESS DEFAULT BROADCASTS
//Time of dusk, Time of dawn, Actual Time
- if(processBroadcast)
- {
+ if (processBroadcast) {
let addMinutesToTimestamp = 5;
{
//run broadcast Time of dusk
addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk
-
+
let params = getParams(PRIORITY_TYPES.node_broadcast);
-
+
let sunCalcResult = calculateDuskDawn();
let dusk_hours = sunCalcResult["dusk_hours"];
let dusk_minutes = sunCalcResult["dusk_minutes"];
-
+
params.address = 0xffffffff;//broadcast
params.byte1 = dusk_hours;//h
params.byte2 = dusk_minutes;//m
params.byte3 = 0;//s
params.byte4 = 0;
- params.recipient = 2;//2 broadcast,
+ params.recipient = 2;//2 broadcast,
params.register = 6;//Time of dusk - Reg 6
params.rw = 1;//write
-
+
//other values
params.type = "cmd";
params.timestamp = Date.now() + 60000;
@@ -1197,18 +1114,18 @@ exports.install = function(instance) {
tasks.push(params);
}
-
+
{
-
+
//run broadcast Time of dawn
addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn
-
+
let params = getParams(PRIORITY_TYPES.node_broadcast);
-
+
let sunCalcResult = calculateDuskDawn();
let dawn_hours = sunCalcResult["dawn_hours"];
let dawn_minutes = sunCalcResult["dawn_minutes"];
-
+
params.address = 0xffffffff;//broadcast
params.byte1 = dawn_hours;//h
params.byte2 = dawn_minutes;//m
@@ -1217,27 +1134,27 @@ exports.install = function(instance) {
params.recipient = 2; //2 broadcast
params.register = 7;//Time of dawn - Reg 6
params.rw = 1;//write
-
+
//other values
params.type = "cmd";
params.timestamp = Date.now() + 60000;
params.addMinutesToTimestamp = addMinutesToTimestamp;
params.info = "Broadcast-dawnTime";
-
+
tasks.push(params);
}
-
+
{
//run broadcast Actual time
addMinutesToTimestamp = 5;
-
+
let params = getParams(PRIORITY_TYPES.node_broadcast);
-
+
var d = new Date();
let hours = d.getHours();
let minutes = d.getMinutes();
let seconds = d.getSeconds();
-
+
params.address = 0xffffffff;//broadcast
params.byte1 = hours;//h
params.byte2 = minutes;//m
@@ -1246,13 +1163,13 @@ exports.install = function(instance) {
params.recipient = 2; //2 broadcast
params.register = 87;//Actual time
params.rw = 1;//write
-
+
//other values
params.type = "cmd";
params.timestamp = Date.now() + 60000;
params.addMinutesToTimestamp = addMinutesToTimestamp;
params.info = "run broadcast: Actual time";
-
+
tasks.push(params);
}
@@ -1260,22 +1177,20 @@ exports.install = function(instance) {
//process nodes & tasks
//reportovanie pre platformu
- if(processNodes)
- {
+ if (processNodes) {
for (let k in nodesData) {
let address = parseInt(k);
let tbname = nodesData[k].tbname;
let register = 0;
-
+
//logger.debug("generated cmd - buildTasks for node:", address);
-
+
//listOfCommands - READ
- for(let i = 0; i < listOfCommands.length; i++)
- {
+ for (let i = 0; i < listOfCommands.length; i++) {
register = listOfCommands[i];
-
+
let params = getParams(PRIORITY_TYPES.node_cmd);
-
+
//core rpc values
params.address = address;
params.byte1 = 0;
@@ -1285,31 +1200,30 @@ exports.install = function(instance) {
params.recipient = 1;
params.register = register;
params.rw = 0;
-
+
let addMinutesToTimestamp = priorities[register];
-
+
let timestampStart = PRIORITY_TYPES.node_cmd; //run imediatelly in function runTasks
- if(addMinutesToTimestamp > 1)
- {
+ if (addMinutesToTimestamp > 1) {
timestampStart = timestampStart + addMinutesToTimestamp * 60000;
}
-
+
//other values
params.type = "cmd";
params.tbname = tbname;
params.timestamp = timestampStart;
params.addMinutesToTimestamp = addMinutesToTimestamp;
params.info = "generated cmd - buildTasks (node)";
-
+
tasks.push(params);
-
+
}
}
}
//niektore ulohy sa vygeneruju iba 1x pri starte!!!
- if(!init) return;
+ if (!init) return;
//Priebežne (raz za cca 5 minút) je potrebné vyčítať z Master nodu verziu jeho FW.
@@ -1328,7 +1242,7 @@ exports.install = function(instance) {
//params.debug = true;
//this will set SETTINGS.masterNodeIsResponding
-
+
tasks.push(params);
}
@@ -1340,7 +1254,7 @@ exports.install = function(instance) {
params.addMinutesToTimestamp = 60;//60 = every hour
params.info = "detekcia nespracovaných profilov linie a nodov";
//params.debug = true;
-
+
tasks.push(params);
}
@@ -1369,15 +1283,13 @@ exports.install = function(instance) {
* dawn: usvit - lux je nad hranicou - vypnem
* dusk: sumrak - lux je pod hranicou - zapnem
*/
- function turnOnOffLinesAccordingToLuxSensor(lux_sensor_value)
- {
+ function turnOnOffLinesAccordingToLuxSensor(lux_sensor_value) {
let now = new Date();
let currentTimestamp = now.getTime();
let keys = Object.keys(relaysData);
- for(let i = 0; i < keys.length; i++)
- {
+ for (let i = 0; i < keys.length; i++) {
let line = keys[i]; //line is turned off by default
let profilestr = relaysData[line].profile;
@@ -1386,38 +1298,31 @@ exports.install = function(instance) {
try {
let profile = JSON.parse(profilestr);
- if(Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined");
+ if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined");
- if(profile.astro_clock == true)
- {
+ if (profile.astro_clock == true) {
let sunCalcResult = calculateDuskDawn(now, line);
//usvit
- if(profile.dawn_lux_sensor == true)
- {
- let lux_sensor_time_window1 = sunCalcResult.dawn_time - (parseInt( profile.dawn_lux_sensor_time_window ) * 1000 * 60); // LUX_SENSOR_TIME_WINDOW x 1000 x 60 --> dostaneme odpocet/pripocitanie minut
- let lux_sensor_time_window2 = sunCalcResult.dawn_time + (parseInt( profile.dawn_lux_sensor_time_window ) * 1000 * 60);
+ if (profile.dawn_lux_sensor == true) {
+ let lux_sensor_time_window1 = sunCalcResult.dawn_time - (parseInt(profile.dawn_lux_sensor_time_window) * 1000 * 60); // LUX_SENSOR_TIME_WINDOW x 1000 x 60 --> dostaneme odpocet/pripocitanie minut
+ let lux_sensor_time_window2 = sunCalcResult.dawn_time + (parseInt(profile.dawn_lux_sensor_time_window) * 1000 * 60);
- if(currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2)
- {
- if(lux_sensor_value > profile.dawn_lux_sensor_value)
- {
- if(contactor) turnOffLine(line, "Profile: dawn - turnOff line according to lux sensor");
+ if (currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2) {
+ if (lux_sensor_value > profile.dawn_lux_sensor_value) {
+ if (contactor) turnLine("off", line, "Profile: dawn - turnOff line according to lux sensor");
}
}
}
//sumrak
- if(profile.dusk_lux_sensor == true)
- {
- let lux_sensor_time_window1 = sunCalcResult.dusk_time - (parseInt( profile.dusk_lux_sensor_time_window ) * 1000 * 60);
- let lux_sensor_time_window2 = sunCalcResult.dusk_time + (parseInt( profile.dusk_lux_sensor_time_window ) * 1000 * 60);
+ if (profile.dusk_lux_sensor == true) {
+ let lux_sensor_time_window1 = sunCalcResult.dusk_time - (parseInt(profile.dusk_lux_sensor_time_window) * 1000 * 60);
+ let lux_sensor_time_window2 = sunCalcResult.dusk_time + (parseInt(profile.dusk_lux_sensor_time_window) * 1000 * 60);
- if(currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2)
- {
- if(lux_sensor_value < profile.dusk_lux_sensor_value)
- {
- if(!contactor) turnOnLine(line, "Profile: dusk - turnOn line according to lux sensor");
+ if (currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2) {
+ if (lux_sensor_value < profile.dusk_lux_sensor_value) {
+ if (!contactor) turnLine("on", line, "Profile: dusk - turnOn line according to lux sensor");
}
}
}
@@ -1425,7 +1330,7 @@ exports.install = function(instance) {
}
} catch (error) {
- if(profilestr !== "" ) monitor.info('Error parsing profile in turnOnOffLinesAccordingToLuxSensor', error);
+ if (profilestr !== "") monitor.info('Error parsing profile in turnOnOffLinesAccordingToLuxSensor', error);
}
}
@@ -1439,39 +1344,35 @@ exports.install = function(instance) {
* if newStatus of node is always receiving false, and it is already for more than SETTINGS.node_status_nok_time value, we update status to "NOK" in tb
* function returns true, if status of node needs to be updated in TB (newStatus attribute is false in this case).
*/
- function updateNodeStatus(node, newStatus)
- {
+ function updateNodeStatus(node, newStatus) {
//MASTER
- if(node == 0) return;
+ if (node == 0) return;
let nodeObj = nodesData[node];
- if(nodeObj == undefined) return;
+ if (nodeObj == undefined) return;
let nodeCurrentStatus = nodeObj.status;
const now = Date.now();
let data = null;
- if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication > now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION) return;
- else if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication < now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION)
- {
- data = {time_of_last_communication: now};
+ if (newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication > now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION) return;
+ else if (newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication < now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION) {
+ data = { time_of_last_communication: now };
nodeDbStatusModify(node, data);
return;
}
- else if(newStatus == false && nodeCurrentStatus == false) return true;
- else if(newStatus == false && nodeCurrentStatus == true)
- {
- if(nodeObj.time_of_last_communication + SETTINGS.node_status_nok_time > now) return;
+ else if (newStatus == false && nodeCurrentStatus == false) return true;
+ else if (newStatus == false && nodeCurrentStatus == true) {
+ if (nodeObj.time_of_last_communication + SETTINGS.node_status_nok_time > now) return;
else {
- data = {status: newStatus};
+ data = { status: newStatus };
nodeDbStatusModify(node, data);
return true;
}
}
- else if(newStatus == true && nodeCurrentStatus == false)
- {
- data = {status: newStatus, time_of_last_communication: now};
+ else if (newStatus == true && nodeCurrentStatus == false) {
+ data = { status: newStatus, time_of_last_communication: now };
nodeDbStatusModify(node, data);
return;
}
@@ -1479,33 +1380,30 @@ exports.install = function(instance) {
}
- function nodeDbStatusModify(node, data){
+ function nodeDbStatusModify(node, data) {
dbNodes.modify(data).where("node", node).make(function(builder) {
builder.callback(function(err, response) {
- if(!err) {
- nodesData[node] = {...nodesData[node], ...data};
+ if (!err) {
+ nodesData[node] = { ...nodesData[node], ...data };
}
});
});
}
- async function runTasks(){
+ async function runTasks() {
clearInterval(interval);
let currentTimestamp = Date.now();
//report dusk, dawn---------------------------------
- if(reportDuskDawn.dusk_time < currentTimestamp)
- {
+ if (reportDuskDawn.dusk_time < currentTimestamp) {
//vyreportuj iba ak nie je velky rozdiel napr. 60 sekund
- if( (currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000)
- {
+ if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) {
//reportovali sme?
- if(reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time)
- {
- sendNotification("CMD Manager: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", {value: sunCalcResult["dusk"]}, "", SEND_TO.tb, instance);
+ if (reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) {
+ sendNotification("CMD Manager: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance);
reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time;
}
}
@@ -1517,15 +1415,12 @@ exports.install = function(instance) {
reportDuskDawn.dusk_time = sunCalcResult.dusk_time;
}
- if(reportDuskDawn.dawn_time < currentTimestamp)
- {
+ if (reportDuskDawn.dawn_time < currentTimestamp) {
//vyreportuj iba ak nie je velky rozdiel napr. 60 sekund
- if( (currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000)
- {
+ if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) {
//reportovali sme?
- if(reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time)
- {
- sendNotification("CMD Manager: calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", {value: sunCalcResult["dawn"]}, "", SEND_TO.tb, instance);
+ if (reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) {
+ sendNotification("CMD Manager: calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance);
reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time;
}
}
@@ -1540,23 +1435,20 @@ exports.install = function(instance) {
//--------------------------------------------------------
//sort tasks based on timestamp
- tasks.sort(function (a, b) {
- if(a.timestamp <= currentTimestamp && b.timestamp <= currentTimestamp)
- {
+ tasks.sort(function(a, b) {
+ if (a.timestamp <= currentTimestamp && b.timestamp <= currentTimestamp) {
return a.priority - b.priority;
}
return a.timestamp - b.timestamp;
});
- if(tasks.length == 0 )
- {
+ if (tasks.length == 0) {
instance.send(SEND_TO.debug, "no tasks created");
interval = setInterval(runTasks, LONG_INTERVAL);
return;
}
- if(!rsPort.isOpen)
- {
+ if (!rsPort.isOpen) {
instance.send(SEND_TO.debug, "!rsPort.isOpen");
//await rsPort.open();
console.log("Cmd_manager - !rsPort.isOpen");
@@ -1564,18 +1456,15 @@ exports.install = function(instance) {
let currentTask = tasks[0];
- if(currentTask.debug)
- {
+ if (currentTask.debug) {
//logger.debug("--->task to process", currentTask);
}
- if(currentTask.timestamp <= currentTimestamp)
- {
- let params = {...tasks[0]};
+ if (currentTask.timestamp <= currentTimestamp) {
+ let params = { ...tasks[0] };
//allow terminal commands
- if(SETTINGS.maintenance_mode && params.type !== "cmd-terminal")
- {
+ if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") {
interval = setInterval(runTasks, LONG_INTERVAL);
return;
}
@@ -1587,28 +1476,24 @@ exports.install = function(instance) {
let line = null;
//rpc related
- if(nodesData[nodeAddress] !== undefined) line = nodesData[nodeAddress].line;
- if(params.line !== undefined) line = params.line;
+ if (nodesData[nodeAddress] !== undefined) line = nodesData[nodeAddress].line;
+ if (params.line !== undefined) line = params.line;
let repeatTask = false;
- if(params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true;
+ if (params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true;
- if(repeatTask)
- {
- if(type === "cmd" || type === "cmd-master")
- {
+ if (repeatTask) {
+ if (type === "cmd" || type === "cmd-master") {
//set next start time automatically
tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000;
}
}
- else
- {
+ else {
tasks.shift();
}
//kontrola nespracovanych profilov nodov
- if(type == "process_profiles")
- {
+ if (type == "process_profiles") {
tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000;
//vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov
@@ -1619,8 +1504,7 @@ exports.install = function(instance) {
}
//relay
- if(type == "relay")
- {
+ if (type == "relay") {
const timePointName = params.timePointName;
const value = params.value;
@@ -1629,43 +1513,31 @@ exports.install = function(instance) {
date.setDate(date.getDate() + 1);//next day
let sunCalcResult;
- sunCalcResult = calculateDuskDawn(date, params.line);
+ if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line);
- if(timePointName == "dawn")
- {
+ if (timePointName == "dawn") {
tasks[0].timestamp = sunCalcResult.dawn_time;
}
- else if(timePointName == "dusk")
- {
+ else if (timePointName == "dusk") {
tasks[0].timestamp = sunCalcResult.dusk_time;
}
- else if(timePointName == "luxOn")
- {
+ else if (timePointName == "luxOn") {
tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000;
}
- else if(timePointName == "luxOff")
- {
+ else if (timePointName == "luxOff") {
tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000;
}
- else if(timePointName == "profileTimepoint")
- {
+ else if (timePointName == "profileTimepoint") {
tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000;
}
let info = "aplikovany bod profilu";
let message = "";
- if(value == 1)
- {
- turnOnLine(params.line, info);
- message = "on";
- }
- else if(value == 0)
- {
- turnOffLine(params.line, info);
- message = "off";
- }
+ value == 1 ? message = "on" : message = "off";
- sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", {line: params.line, value: message}, "", SEND_TO.tb, instance );
+ turnLine(message, params.line, info);
+
+ sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: params.line, value: message }, "", SEND_TO.tb, instance);
interval = setInterval(runTasks, SHORT_INTERVAL);
return;
}
@@ -1675,25 +1547,22 @@ exports.install = function(instance) {
//if(rotary_switch_state == "Off") disconnected = true;
//state_of_breaker[line] - alebo istic linie
- if(state_of_breaker.hasOwnProperty(line))
- {
+ if (state_of_breaker.hasOwnProperty(line)) {
//if(state_of_breaker[line] == "Off") disconnected = true;
}
//toto sa reportuje po prijati dat z dido_controlera
- if(disconnected)
- {
- let values = {"status": "OFFLINE"};
+ if (disconnected) {
+ let values = { "status": "OFFLINE" };
logger.debug("disconnected", values);
logger.debug("rotary_switch_state", rotary_switch_state);
logger.debug("state_of_breaker", state_of_breaker[line]);
//report only once!
- if(!disconnectedReport.hasOwnProperty(tbname)) disconnectedReport[tbname] = false;
+ if (!disconnectedReport.hasOwnProperty(tbname)) disconnectedReport[tbname] = false;
- if(!disconnectedReport[tbname])
- {
+ if (!disconnectedReport[tbname]) {
sendTelemetry(values, tbname)
}
@@ -1707,54 +1576,48 @@ exports.install = function(instance) {
const register = params.register;
//high_priority
- if(!SETTINGS.masterNodeIsResponding)
- {
+ if (!SETTINGS.masterNodeIsResponding) {
//ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version
errorHandler.sendMessageToService("Master node is not responding");
let stop = true;
//fw version - register == 4
- if(type == "cmd-terminal" || register == 4) stop = false;
- if(stop)
- {
+ if (type == "cmd-terminal" || register == 4) stop = false;
+ if (stop) {
interval = setInterval(runTasks, LONG_INTERVAL);
return;
}
}
let relayStatus = 1;
- if(relaysData[line] != undefined)
- {
+ if (relaysData[line] != undefined) {
relayStatus = relaysData[line].contactor;
}
- if(line == 0) relayStatus = 0;
- if(type == "cmd-terminal") relayStatus = 1;
+ if (line == 0) relayStatus = 0;
+ if (type == "cmd-terminal") relayStatus = 1;
//check if rotary_switch_state == "Off"
- if(relayStatus == 0)
- {
+ if (relayStatus == 0) {
//console.log("------------------------------------relayStatus", relayStatus, line);
- let values = {"status": "OFFLINE"};
+ let values = { "status": "OFFLINE" };
sendTelemetry(values, tbname)
-
+
interval = setInterval(runTasks, SHORT_INTERVAL);
return;
}
- if(!rsPort.isOpen)
- {
+ if (!rsPort.isOpen) {
interval = setInterval(runTasks, LONG_INTERVAL);
return;
}
-
+
//RE-CALCULATE VALUES
//set actual time for broadcast
- if(register == 87 && params.recipient === 2)
- {
+ if (register == 87 && params.recipient === 2) {
var d = new Date();
let hours = d.getHours();
let minutes = d.getMinutes();
@@ -1768,15 +1631,13 @@ exports.install = function(instance) {
//SET DUSK/DAWN FOR BROADCAST
//Time of dusk
- if(register == 6 && params.recipient === 2)
- {
+ if (register == 6 && params.recipient === 2) {
- if(type != "cmd-terminal")
- {
+ if (type != "cmd-terminal") {
let sunCalcResult = calculateDuskDawn();
let dusk_hours = sunCalcResult["dusk_hours"];
let dusk_minutes = sunCalcResult["dusk_minutes"];
-
+
params.byte1 = dusk_hours;//h
params.byte2 = dusk_minutes;//m
params.byte3 = 0;//s
@@ -1788,14 +1649,12 @@ exports.install = function(instance) {
}
//Time of dawn
- if(register == 7 && params.recipient === 2)
- {
- if(type != "cmd-terminal")
- {
+ if (register == 7 && params.recipient === 2) {
+ if (type != "cmd-terminal") {
let sunCalcResult = calculateDuskDawn();
let dawn_hours = sunCalcResult["dawn_hours"];
let dawn_minutes = sunCalcResult["dawn_minutes"];
-
+
params.byte1 = dawn_hours;//h
params.byte2 = dawn_minutes;//m
params.byte3 = 0;//s
@@ -1804,7 +1663,7 @@ exports.install = function(instance) {
//TODO astrohodiny
let dawn = "Time of dawn: " + sunCalcResult["dawn"];
}
-
+
}
//-----------------------
@@ -1814,7 +1673,7 @@ exports.install = function(instance) {
startTime = new Date();
let saveToTb = true;
- if(!tbname) saveToTb = false;
+ if (!tbname) saveToTb = false;
let itIsNodeCommand = listOfCommands.includes(register); //reading data from node (voltage, current, dimming, status)
let resp = com_generic(nodeAddress, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4);
@@ -1822,22 +1681,21 @@ exports.install = function(instance) {
let timeout = 4000;
// await keyword is important, otherwise incorrect data is returned!
- await writeData(rsPort, resp, readBytes, timeout).then(function (data) {
+ await writeData(rsPort, resp, readBytes, timeout).then(function(data) {
endTime = new Date();
var timeDiff = endTime - startTime;
//data je array z 11 bytov: 1-4 adresa, 5 status ak je status 0 - ok, nasleduju 4 byty data a 2 byty CRC
- let dataBytes = data.slice(5,9);
+ let dataBytes = data.slice(5, 9);
let result = detectIfResponseIsValid(data);
-
+
//ak sa odpoved zacina 0 - je to v poriadku, inak je NOK
let message = result.message; // OK, NOK
let message_type = result.type;
let error = result.error;
- if(params.debug != "generated cmd")
- {
+ if (params.debug != "generated cmd") {
//debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params);
}
@@ -1857,23 +1715,20 @@ exports.install = function(instance) {
let values = {};
//CMD FINISHED
- if(message == "OK")
- {
+ if (message == "OK") {
updateNodeStatus(nodeAddress, true);
//write
- if(type == "set_node_profile")
- {
+ if (type == "set_node_profile") {
let result = cmdCounterResolve(nodeAddress);
- if(result == 0)
- {
+ if (result == 0) {
dbNodes.modify({ processed: true }).where("node", nodeAddress).make(function(builder) {
builder.callback(function(err, response) {
- sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", {node: nodeAddress}, "", SEND_TO.tb, instance );
-
- logger.debug( "--> profil úspešne odoslaný na node č. " + nodeAddress);
+ sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: nodeAddress }, "", SEND_TO.tb, instance);
+
+ logger.debug("--> profil úspešne odoslaný na node č. " + nodeAddress);
nodesData[nodeAddress].processed = true;
});
});
@@ -1881,59 +1736,48 @@ exports.install = function(instance) {
}
//parse read response
- if(params.rw == 0)
- {
+ if (params.rw == 0) {
values = processResponse(register, dataBytes); //read
}
- if(itIsNodeCommand)
- {
+ if (itIsNodeCommand) {
values.comm_status = "OK";
values.status = "OK";
}
//master node
- if(nodeAddress == 0)
- {
- sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status" );
+ if (nodeAddress == 0) {
+ sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status");
SETTINGS.masterNodeIsResponding = true;
- if(register == 4) values["edge_fw_version"] = SETTINGS.edge_fw_version;
+ if (register == 4) values["edge_fw_version"] = SETTINGS.edge_fw_version;
}
//odoslanie príkazu z terminálu - dáta
- if(type == "cmd-terminal")
- {
- sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "command_was_sent_from_terminal_interface", {}, params, SEND_TO.tb, instance );
+ if (type == "cmd-terminal") {
+ sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "command_was_sent_from_terminal_interface", {}, params, SEND_TO.tb, instance);
}
- if(params.debug)
- {
+ if (params.debug) {
//logger.debug("saveToTb", saveToTb, tbname, values);
}
- if(saveToTb)
- {
+ if (saveToTb) {
sendTelemetry(values, tbname)
}
- else
- {
- if(type == "cmd-terminal")
- {
+ else {
+ if (type == "cmd-terminal") {
terminalCommandResponse(params, "SUCCESS", data);
}
}
}
- else
- {
+ else {
terminalCommandResponse(params, "ERROR", data)
handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb);
-
- if(params.hasOwnProperty("debug"))
- {
- if(params.debug)
- {
+
+ if (params.hasOwnProperty("debug")) {
+ if (params.debug) {
//logger.debug("writeData err: ", error, result, params);
logger.debug("writeData err: ", tbname, nodeAddress, register, values);
}
@@ -1949,19 +1793,16 @@ exports.install = function(instance) {
terminalCommandResponse(params, "FAILURE", null, reason);
handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb);
- if(params.hasOwnProperty("debug"))
- {
- if(params.debug)
- {
+ if (params.hasOwnProperty("debug")) {
+ if (params.debug) {
logger.debug("-->WRITE FAILED: " + reason, params.debug, params);
}
}
});
-
+
}
- else
- {
+ else {
// if(currentTask.debug)
// {
// //currentTask.timestamp <= currentTimestamp
@@ -1970,20 +1811,20 @@ exports.install = function(instance) {
interval = setInterval(runTasks, LONG_INTERVAL);
return;
- }
+ }
//console.log("----->runTasks - setInterval", new Date());
interval = setInterval(runTasks, SHORT_INTERVAL);
- }
+ }
- function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb){
+ function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) {
let node = params.address;
let register = params.register;
let type = params.type;
let tbName = params.tbname;
- if(!tbName) return;
+ if (!tbName) return;
let values = {};
@@ -1991,55 +1832,48 @@ exports.install = function(instance) {
let updateStatus = updateNodeStatus(node, false);
//master node
- if(node == 0)
- {
+ if (node == 0) {
sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status");
logger.debug("master_node_is_not_responding", params);
SETTINGS.masterNodeIsResponding = false;
- if(register == 4) values["master_node_version"] = "NOK";
+ if (register == 4) values["master_node_version"] = "NOK";
}
- if(type == "set_node_profile")
- {
+ if (type == "set_node_profile") {
delete cmdCounter[node];
- logger.debug( "profil nebol úspešne odoslaný na node č. ", params);
- sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", {node: node}, "", SEND_TO.tb, instance );
+ logger.debug("profil nebol úspešne odoslaný na node č. ", params);
+ sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance);
}
- if(itIsNodeCommand)
- {
+ if (itIsNodeCommand) {
values.comm_status = "NOK";
}
- if(updateStatus)
- {
+ if (updateStatus) {
values.status = "NOK";
}
// console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values);
- if(saveToTb && Object.keys(values).length > 0)
- {
+ if (saveToTb && Object.keys(values).length > 0) {
sendTelemetry(values, tbName)
}
}
-
-
+
+
/**
* function handles requests from terminal
* responseType can be "SUCCESS", "ERROR" or "FAILURE", depending on rsPort data.
* FAILURE means, that we got into catch block of writeData function.
*/
- function terminalCommandResponse(params, responseType, data=null, reason="") { //success, error, failure
-
- if(params.refFlowdataKey == undefined)
- {
+ function terminalCommandResponse(params, responseType, data = null, reason = "") { //success, error, failure
+
+ if (params.refFlowdataKey == undefined) {
//console.log("params.refFlowdataKey is undefined", params);
return;
}
- else
- {
+ else {
console.log("params.refFlowdataKey: ", params);
}
@@ -2070,12 +1904,11 @@ exports.install = function(instance) {
let responseObj = {}
responseObj["type"] = type;
- if(responseType == "FAILURE") responseObj["message"] = "ERROR WRITE FAILED: " + reason;
+ if (responseType == "FAILURE") responseObj["message"] = "ERROR WRITE FAILED: " + reason;
else responseObj["bytes"] = data;
let refFlowdata = refFlowdataObj[params.refFlowdataKey]; //holds reference to httprequest flowdata
- if(refFlowdata)
- {
+ if (refFlowdata) {
refFlowdata.data = responseObj;
instance.send(SEND_TO.http_response, refFlowdata);
}
@@ -2085,7 +1918,7 @@ exports.install = function(instance) {
/**
* function handles tasks, that are not needed to run through masterNode. To make them run smooth without waiting for other tasks to be completed, we moved them in separate function
*/
- function reportEdgeDateTimeAndNumberOfLuminaires(){
+ function reportEdgeDateTimeAndNumberOfLuminaires() {
//Number of ok and nok nodes on platform does not equals to total number of nodes.
//possible error is, that nodesData object is changing all the time. To make a proper calculation of ok,nok luminaires, we make a copy of it:
@@ -2098,16 +1931,15 @@ exports.install = function(instance) {
let number_of_ok_luminaires = 0;
let number_of_nok_luminaires = 0;
- for(let i = 0; i < keys.length; i++)
- {
+ for (let i = 0; i < keys.length; i++) {
let key = keys[i];
let nodeObj = nodesData_clone[key];
- if(nodeObj.tbname == undefined) continue;
+ if (nodeObj.tbname == undefined) continue;
- if(nodeObj.status) number_of_ok_luminaires++;
+ if (nodeObj.status) number_of_ok_luminaires++;
else number_of_nok_luminaires++;
}
-
+
const values = {
"number_of_luminaires": number_of_luminaires,
"number_of_ok_luminaires": number_of_ok_luminaires,
@@ -2125,7 +1957,7 @@ exports.install = function(instance) {
// const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM
// const rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false }); // UNIPI
- if(SETTINGS.serial_port == "" || SETTINGS.serial_port == undefined || SETTINGS.serial_port.length === 1) SETTINGS.serial_port = "ttymxc4";
+ if (SETTINGS.serial_port == "" || SETTINGS.serial_port == undefined || SETTINGS.serial_port.length === 1) SETTINGS.serial_port = "ttymxc4";
rsPort = new SerialPort(`/dev/${SETTINGS.serial_port}`, { autoOpen: false });
//(node:16372) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 13 data listeners added to [SerialPort]. Use emitter.setMaxListeners() to increase limit
//rsPort.setMaxListeners(0);
@@ -2136,33 +1968,33 @@ exports.install = function(instance) {
//loadRelaysData();
- await runSyncExec(`stty -F /dev/${SETTINGS.serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function (status) {
+ await runSyncExec(`stty -F /dev/${SETTINGS.serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function(status) {
instance.send(SEND_TO.debug, "RPC runSyncExec - Promise Resolved:" + status);
logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status);
//APP START
- let dataToInfoSender = {id: SETTINGS.project_id, name: SETTINGS.rvo_name};
+ let dataToInfoSender = { id: SETTINGS.project_id, name: SETTINGS.rvo_name };
dataToInfoSender.fw_version = SETTINGS.edge_fw_version;
dataToInfoSender.startdate = new Date().toISOString().slice(0, 19).replace('T', ' ');
dataToInfoSender.__force__ = true;
-
+
instance.send(SEND_TO.infoSender, dataToInfoSender);
logger.debug(0, "---------------------------->START message send to service", dataToInfoSender);
- }).catch(function (reason) {
+ }).catch(function(reason) {
instance.send(SEND_TO.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason);
});
});
rsPort.on('error', function(err) {
-
- //TODO report to service!!!
- //errLogger.error(exports.title, "unable to open port", SETTINGS.serial_port, err.message);
- errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0);
- instance.send(SEND_TO.debug, err.message);
+ //TODO report to service!!!
+ //errLogger.error(exports.title, "unable to open port", SETTINGS.serial_port, err.message);
+ errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0);
+
+ instance.send(SEND_TO.debug, err.message);
});
rsPort.on("close", () => {
@@ -2171,7 +2003,7 @@ exports.install = function(instance) {
rsPort.open();
}
-
+
instance.on("close", () => {
clearInterval(interval);
@@ -2189,69 +2021,55 @@ exports.install = function(instance) {
//instance.send(SEND_TO.debug, "on Data");
//instance.send(SEND_TO.debug, flowdata);
-
+
//logger.debug(flowdata.data);
//just testing functions
- if(flowdata.data == "open")
- {
- if(!rsPort.isOpen) rsPort.open();
+ if (flowdata.data == "open") {
+ if (!rsPort.isOpen) rsPort.open();
return;
}
- else if(flowdata.data == "close")
- {
+ else if (flowdata.data == "close") {
rsPort.close();
return;
}
- else if(flowdata.data == "clean")
- {
+ else if (flowdata.data == "clean") {
tasks = [];
return;
}
- else if(flowdata.data == "buildtasks")
- {
+ else if (flowdata.data == "buildtasks") {
//build & run
return;
}
- else if(flowdata.data == "run")
- {
+ else if (flowdata.data == "run") {
//durations = [];
- if(tasks.length == 0)
- {
+ if (tasks.length == 0) {
buildTasks();
- if(rsPort.isOpen)
- {
- interval = setInterval(runTasks, 100);
+ if (rsPort.isOpen) {
+ interval = setInterval(runTasks, 100);
}
- else
- {
- instance.send(SEND_TO.debug, "port is not opened!!!");
+ else {
+ instance.send(SEND_TO.debug, "port is not opened!!!");
}
}
}
- else
- {
+ else {
//terminal data - object
//logger.debug("flowdata", flowdata.data);
- if(typeof flowdata.data === 'object')
- {
+ if (typeof flowdata.data === 'object') {
//logger.debug("dido", flowdata.data);
- if(flowdata.data.hasOwnProperty("sender"))
- {
+ if (flowdata.data.hasOwnProperty("sender")) {
//data from dido_controller
- if(flowdata.data.sender == "dido_controller")
- {
+ if (flowdata.data.sender == "dido_controller") {
- if(flowdata.data.hasOwnProperty("cmd"))
- {
+ if (flowdata.data.hasOwnProperty("cmd")) {
let cmd = flowdata.data.cmd;
-
- if(cmd == "buildTasks")
- {
+
+ if (cmd == "buildTasks") {
clearInterval(interval);
logger.debug("-->CMD MANAGER - BUILD TASKS");
@@ -2263,32 +2081,25 @@ exports.install = function(instance) {
logger.debug("-->CMD MANAGER - RUN TASKS");
interval = setInterval(runTasks, LONG_INTERVAL);
}
- else if(cmd == "reload_relays")
- {
+ else if (cmd == "reload_relays") {
loadRelaysData(flowdata.data.line);
- if(flowdata.data.dataChanged)
- {
- if(!flowdata.data.value)
- {
+ if (flowdata.data.dataChanged) {
+ if (!flowdata.data.value) {
reportOfflineNodeStatus(flowdata.data.line);
}
- else
- {
+ else {
reportOnlineNodeStatus(flowdata.data.line);
}
}
-
+
}
- else if(cmd == "rotary_switch_state")
- {
+ else if (cmd == "rotary_switch_state") {
let value = flowdata.data.value;
//state was changed
- if(rotary_switch_state != value)
- {
- if(value == "Off")
- {
+ if (rotary_switch_state != value) {
+ if (value == "Off") {
//vyreportovat vsetky svietdla
reportOfflineNodeStatus();
}
@@ -2296,13 +2107,11 @@ exports.install = function(instance) {
rotary_switch_state = value;
}
}
- else if(cmd == "lux_sensor")
- {
+ else if (cmd == "lux_sensor") {
lux_sensor = parseInt(flowdata.data.value);
// POSSIBLE SOURCE OF PROBLEMS, IF USER SETS LUX TRESHOLD LEVEL GREATER THAN 100 - WE SHOULD BE CHECKING "DUSK/DAWN_LUX_SENSOR_VALUE" IN PROFILE MAYBE ??
- if(lux_sensor < 100)
- {
+ if (lux_sensor < 100) {
// we send lux_sensor value to all nodes:
let params = getParams(PRIORITY_TYPES.node_broadcast);
@@ -2325,39 +2134,37 @@ exports.install = function(instance) {
turnOnOffLinesAccordingToLuxSensor(lux_sensor);
}
}
- else if(cmd == "state_of_breaker")
- {
+ else if (cmd == "state_of_breaker") {
//istic linie
let value = flowdata.data.value;
let line = parseInt(flowdata.data.line);
let dataChanged = false;
- if(state_of_breaker[line] != value) dataChanged = true;
+ if (state_of_breaker[line] != value) dataChanged = true;
state_of_breaker[line] = value;
let status = "OK";
- if(value == "Off") status = "NOK";
+ if (value == "Off") status = "NOK";
- if(dataChanged) {
+ if (dataChanged) {
- if(relaysData.hasOwnProperty(line))
- {
+ if (relaysData.hasOwnProperty(line)) {
let tbname = relaysData[line].tbname;
- if(value == "Off") sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_off_line", {line: line}, "", SEND_TO.tb, instance, "circuit_breaker");
- else sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_on_line", {line: line}, "", SEND_TO.tb, instance, "circuit_breaker");
+ if (value == "Off") sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker");
+ else sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker");
//report status liniu
- sendTelemetry({status: status}, tbname)
+ sendTelemetry({ status: status }, tbname)
//current value
- if(value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii
+ if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii
}
}
}
- else{
+ else {
logger.debug("undefined cmd", cmd);
}
}
@@ -2367,19 +2174,18 @@ exports.install = function(instance) {
}
//data from worksys
- if(flowdata.data.hasOwnProperty("topic"))
- {
+ if (flowdata.data.hasOwnProperty("topic")) {
let data = getNested(flowdata.data, "content", "data");
- if(data == undefined) {
- console.log("Invalid rpc command came from platform");
- return;
+ if (data == undefined) {
+ console.log("Invalid rpc command came from platform");
+ return;
}
let command = data.params.command;
let method = data.method;
let profile = data.params.payload;
- if(profile == undefined) profile = "";
+ if (profile == undefined) profile = "";
let entity = data.params.entities[0];
let entity_type = entity.entity_type;
let tbname = entity.tb_name;
@@ -2388,33 +2194,28 @@ exports.install = function(instance) {
logger.debug("--->worksys", flowdata.data, data.params, entity, entity_type, command, method);
logger.debug("----------------------------");
- if(entity_type == "street_luminaire"|| entity_type === "street_luminaire_v4_1" || entity_type === "street_luminaire_v4_1cez" || entity_type === "street_luminaire_v4")
- {
- if(method == "set_command")
- {
+ if (entity_type == "street_luminaire" || entity_type === "street_luminaire_v4_1" || entity_type === "street_luminaire_v4_1cez" || entity_type === "street_luminaire_v4") {
+ if (method == "set_command") {
//let command = data.params.command;
let value = data.params.payload.value;
-
- if(command == "dimming")
- {
+
+ if (command == "dimming") {
let nodeWasFound = false;
let keys = Object.keys(nodesData);
//logger.debug("-----", keys);
- for(let i = 0; i < keys.length; i++)
- {
+ for (let i = 0; i < keys.length; i++) {
let node = keys[i];
//logger.debug( node, nodesData[node], tbname);
- if(tbname == nodesData[node].tbname)
- {
+ if (tbname == nodesData[node].tbname) {
let params = getParams(PRIORITY_TYPES.high_priority);
value = parseInt(value);
- if(value > 0) value = value + 128;
+ if (value > 0) value = value + 128;
//set dimming - LUM1_13 - 647 je node linie 1 kt. dobre vidime
params.type = "cmd";
@@ -2435,7 +2236,7 @@ exports.install = function(instance) {
tasks.push(params);
- setTimeout(function(){
+ setTimeout(function() {
//spustime o 4 sekundy neskor, s prioritou PRIORITY_TYPES.high_priority
//a pridame aj vyreportovanie dimmingu
@@ -2506,8 +2307,8 @@ exports.install = function(instance) {
tasks.push(params);
}
- },4000);
-
+ }, 4000);
+
nodeWasFound = true;
@@ -2515,55 +2316,49 @@ exports.install = function(instance) {
}
}
- if(!nodeWasFound)
- {
+ if (!nodeWasFound) {
logger.debug("set dimming from platform", "unable to find tbname", tbname);
}
}
- else
- {
+ else {
instance.send(SEND_TO.debug, "undefined command " + command);
logger.debug("undefined command", command);
}
return;
}
- else if(method == "set_profile")
- {
+ else if (method == "set_profile") {
//nastav profil nodu
logger.debug("-->set_profile for node", data.params);
logger.debug("------profile data", profile);
//instance.send(SEND_TO.debug, "set_profile" + command);
let keys = Object.keys(nodesData);
- for(let i = 0; i < keys.length; i++)
- {
+ for (let i = 0; i < keys.length; i++) {
let node = keys[i];
- if(tbname == nodesData[node].tbname)
- {
+ if (tbname == nodesData[node].tbname) {
- if(profile != "") profile = JSON.stringify(profile);
+ if (profile != "") profile = JSON.stringify(profile);
dbNodes.modify({ processed: false, profile: profile }).where("node", node).make(function(builder) {
builder.callback(function(err, response) {
- logger.debug("worksys - update node profile done", profile);
- if(profile === "") logger.debug("worksys - update node profile done - profile is empty");
+ logger.debug("worksys - update node profile done", profile);
+ if (profile === "") logger.debug("worksys - update node profile done - profile is empty");
- //profil úspešne prijatý pre node č. xx
- sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", {node: node}, profile, SEND_TO.tb, instance );
+ //profil úspešne prijatý pre node č. xx
+ sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance);
- nodesData[node].processed = false;
- nodesData[node].profile = profile;
+ nodesData[node].processed = false;
+ nodesData[node].profile = profile;
- processNodeProfile(node);
+ processNodeProfile(node);
});
});
}
}
}
- else
- {
+ else {
instance.send(SEND_TO.debug, "unknown method " + method);
logger.debug("unknown method", method);
@@ -2573,28 +2368,24 @@ exports.install = function(instance) {
}
//nastav profil linie z platformy
- else if(entity_type == "edb_line" || entity_type == "edb" || entity_type == "edb_line_ver4" || entity_type == "edb_ver4_se")
- {
+ else if (entity_type == "edb_line" || entity_type == "edb" || entity_type == "edb_line_ver4" || entity_type == "edb_ver4_se") {
//profil linie
//relays.table line:number|tbname:string|contactor:number|profile:string
//najdeme line relaysData
- if(method == "set_profile")
- {
+ if (method == "set_profile") {
logger.debug("-->set_profile for line", data.params);
logger.debug("profile data:", profile);
let keys = Object.keys(relaysData);
- for(let i = 0; i < keys.length; i++)
- {
+ for (let i = 0; i < keys.length; i++) {
let line = keys[i];
- if(tbname == relaysData[line].tbname)
- {
+ if (tbname == relaysData[line].tbname) {
//zmazeme tasky
- removeTask({type: "relay", line: line});
-
- if(profile != "") profile = JSON.stringify(profile);
+ removeTask({ type: "relay", line: line });
+
+ if (profile != "") profile = JSON.stringify(profile);
dbRelays.modify({ profile: profile }).where("line", line).make(function(builder) {
builder.callback(function(err, response) {
@@ -2606,15 +2397,15 @@ exports.install = function(instance) {
relaysData[line].profile = profile;
loadRelaysData(line)
-
+
//TODO build tasks by mala bezat az ked je vsetko loadRelaysData
//spracovane, pravdepodobne treba spravit promisy
logger.debug("loadRelaysData DONE for line", line);
- console.log("zacina buildTasks po loadRelaysData.........")
+ console.log("zacina buildTasks po loadRelaysData.........")
- buildTasks({processLineProfiles: true, line: line});
-
- sendNotification("CMD manager - set profile from worksys", tbname, "switching_profile_was_processed_for_line", {line: line}, profile, SEND_TO.tb, instance );
+ buildTasks({ processLineProfiles: true, line: line });
+
+ sendNotification("CMD manager - set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance);
});
});
@@ -2622,35 +2413,31 @@ exports.install = function(instance) {
}
}
}
- else if(method == "set_command")
- {
+ else if (method == "set_command") {
let value = data.params.payload.value;
- if(command === "switch")
- {
+ if (command === "switch") {
// if we receive rpc from platform, to switch maintenance mode, we set SETTINGS.maintenance_mode flow variable to value;
- if(entity_type === "edb" || entity_type === "edb_ver4_se") SETTINGS.maintenance_mode = value;
+ if (entity_type === "edb" || entity_type === "edb_ver4_se") SETTINGS.maintenance_mode = value;
const relayObject = getObjectByTbValue(relaysData, tbname);
let line = 0;
- 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;
- if(value == false) turnOffLine(line, "command received from platform");
- else turnOnLine(line, "command received from platform");
+ if (value == false) turnLine("off", line, "command received from platform");
+ else turnLine("on", line, "command received from platform");
}
}
- else
- {
+ else {
instance.send(SEND_TO.debug, "undefined method " + method);
logger.debug("undefined method", method);
}
return;
}
- else
- {
+ else {
instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type);
logger.debug("UNKNOW entity_type", entity_type);
}
@@ -2658,11 +2445,10 @@ exports.install = function(instance) {
}
//terminal
- if(!rsPort.isOpen) await rsPort.open();
+ if (!rsPort.isOpen) await rsPort.open();
let params = flowdata.data.body;
- if(params == undefined)
- {
+ if (params == undefined) {
//logger.debug("CMD manager flowdata.data.body is undefined");
return;
}
@@ -2683,7 +2469,7 @@ exports.install = function(instance) {
cleanUpRefFlowdataObj();
- refFlowdataObj[ timestamp ] = flowdata;
+ refFlowdataObj[timestamp] = flowdata;
//fix
//params.address = params.adress;
@@ -2701,546 +2487,497 @@ exports.install = function(instance) {
})
-//function gets value of a nested property in an object and returns undefined if it does not exists:
-function getNested(obj, ...args) {
- return args.reduce((obj, level) => obj && obj[level], obj)
-}
+ //function gets value of a nested property in an object and returns undefined if it does not exists:
+ function getNested(obj, ...args) {
+ return args.reduce((obj, level) => obj && obj[level], obj)
+ }
-/**
- * setCorrectTime function runs once per hour
- * If it is 3 o'clock, it sets actual time, which is got from services
- * https://service-prod01.worksys.io/gettime
- * If also detects Read Only Filesystem once a day
- */
-function setCorrectPlcTimeOnceADay()
-{
+ /**
+ * setCorrectTime function runs once per hour
+ * If it is 3 o'clock, it sets actual time, which is got from services
+ * https://service-prod01.worksys.io/gettime
+ * If also detects Read Only Filesystem once a day
+ */
+ function setCorrectPlcTimeOnceADay() {
- const currentTime = new Date();
- if(currentTime.getHours() != 3) return;
+ const currentTime = new Date();
+ if (currentTime.getHours() != 3) return;
- RESTBuilder.make(function(builder) {
+ RESTBuilder.make(function(builder) {
- if(!builder) return;
+ if (!builder) return;
- builder.method('GET');
- builder.url('http://192.168.252.2:8004/gettime?projects_id=1');
+ builder.method('GET');
+ builder.url('http://192.168.252.2:8004/gettime?projects_id=1');
- builder.callback(function(err, response, output) {
+ builder.callback(function(err, response, output) {
- if (err) {
- console.log(err);
- return;
- }
-
- const res = output.response;
-
- try {
-
- const obj = JSON.parse(res);
- let d = new Date(obj.date);
-
- const now = new Date();
-
- let diffInMinutes = now.getTimezoneOffset();
- console.log("---->TimezoneOffset", diffInMinutes);
-
- if(d instanceof Date)
- {
-
- // monitor.info("----------->setCorrectPlcTimeOnceADay() current js date:", d, d.getHours());
-
- let year = d.getFullYear();
- let month = addZeroBefore(d.getMonth() + 1);
- let day = addZeroBefore(d.getDate());
-
- let hours = addZeroBefore(d.getHours());
- let minutes = addZeroBefore(d.getMinutes() );
- let seconds = addZeroBefore(d.getSeconds());
-
- let dateStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
-
- exec(`sudo timedatectl set-time "${dateStr}"`, (err, stdout, stderr) => {
- if (err || stderr) {
- console.error(err);
- console.log(stderr);
- console.log(dateStr);
-
- monitor.info("failed timedatectl set-time", err, stderr);
- }
- else
- {
- monitor.info("setCorrectPlcTimeOnceADay() --> Nastaveny cas na: ", dateStr);
- }
-
- });
+ if (err) {
+ console.log(err);
+ return;
}
- } catch (error) {
- logger.debug("setCorrectPlcTimeOnceADay - function error", error, res);
- monitor.info("setCorrectPlcTimeOnceADay - function error", error, res);
- }
+ const res = output.response;
- // we detect readOnlyFileSystem once an hour as well
- detectReadOnlyFilesystem();
+ try {
+ const obj = JSON.parse(res);
+ let d = new Date(obj.date);
+
+ const now = new Date();
+
+ let diffInMinutes = now.getTimezoneOffset();
+ console.log("---->TimezoneOffset", diffInMinutes);
+
+ if (d instanceof Date) {
+
+ // monitor.info("----------->setCorrectPlcTimeOnceADay() current js date:", d, d.getHours());
+
+ let year = d.getFullYear();
+ let month = addZeroBefore(d.getMonth() + 1);
+ let day = addZeroBefore(d.getDate());
+
+ let hours = addZeroBefore(d.getHours());
+ let minutes = addZeroBefore(d.getMinutes());
+ let seconds = addZeroBefore(d.getSeconds());
+
+ let dateStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+
+ exec(`sudo timedatectl set-time "${dateStr}"`, (err, stdout, stderr) => {
+ if (err || stderr) {
+ console.error(err);
+ console.log(stderr);
+ console.log(dateStr);
+
+ monitor.info("failed timedatectl set-time", err, stderr);
+ }
+ else {
+ monitor.info("setCorrectPlcTimeOnceADay() --> Nastaveny cas na: ", dateStr);
+ }
+
+ });
+ }
+
+ } catch (error) {
+ logger.debug("setCorrectPlcTimeOnceADay - function error", error, res);
+ monitor.info("setCorrectPlcTimeOnceADay - function error", error, res);
+ }
+
+ // we detect readOnlyFileSystem once an hour as well
+ detectReadOnlyFilesystem();
+
+ });
});
- });
-}
+ }
-function detectReadOnlyFilesystem()
-{
- exec(`sudo egrep " ro,|,ro " /proc/mounts`, (err, stdout, stderr) => {
- if (err || stderr) {
- console.error(err);
- console.log(stderr);
+ function detectReadOnlyFilesystem() {
+ exec(`sudo egrep " ro,|,ro " /proc/mounts`, (err, stdout, stderr) => {
+ if (err || stderr) {
+ console.error(err);
+ console.log(stderr);
- } else {
- //console.log("Read-only", stdout);
-
- let lines = stdout + "";
- lines = lines.split("\n");
+ } else {
+ //console.log("Read-only", stdout);
- let readOnlyDetected = "";
- for(let i = 0; i < lines.length; i++)
- {
- if(lines[i].startsWith("/dev/mmcblk0p2"))
- {
- readOnlyDetected = lines[i];
+ let lines = stdout + "";
+ lines = lines.split("\n");
+
+ let readOnlyDetected = "";
+ for (let i = 0; i < lines.length; i++) {
+ if (lines[i].startsWith("/dev/mmcblk0p2")) {
+ readOnlyDetected = lines[i];
+ }
}
+
+ if (readOnlyDetected !== "") {
+ errorHandler.sendMessageToService("Detected: Read-only file system: " + readOnlyDetected);
+ monitor.info("Read only filesystem detected");
+ }
+
}
-
- if(readOnlyDetected !== "")
- {
- errorHandler.sendMessageToService("Detected: Read-only file system: " + readOnlyDetected);
- monitor.info("Read only filesystem detected");
- }
-
- }
- });
-}
-
-
-
-
-
-
-
-
-///helper functions
-function sendTelemetry(values, tbname, date=Date.now())
-{
- const dataToTb = {
- [tbname]: [
- {
- "ts": date,
- "values": values
- }
- ]
+ });
}
- tbHandler.sendToTb(dataToTb, instance);
-}
-
-function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0)
-{
-
- if(date === undefined) date = new Date();
- //if(duskOffset === undefined) duskOffset = 0;
- //if(dawnOffset === undefined) dawnOffset = 0;
-
- //let line = keys[i];
- let profilestr = "";
- if(relaysData[line] != undefined) profilestr = relaysData[line].profile;
-
- let result = {};
-
- var times = SunCalc.getTimes(date, latitude, longitude);
- let dawn = new Date(times.sunrise);//usvit
- let dusk = new Date(times.sunset);//sumrak
-
-
- //http://suncalc.net/#/48.5598,18.169,11/2021.04.07/11:06
- //https://mapa.zoznam.sk/zisti-gps-suradnice-m6
- let dusk_astro_clock_offset = duskOffset;//minutes
- let dawn_astro_clock_offset = dawnOffset;//minutes
- try {
- let profile = JSON.parse(profilestr);
- if(Object.keys(profile).length === 0) throw ("profile is not defined");
- //Jednoduchý režim
- if(profile.astro_clock == false && profile.dusk_lux_sensor == false && profile.dawn_lux_sensor == false)
- {
+
+ ///helper functions
+ function sendTelemetry(values, tbname, date = Date.now()) {
+ const dataToTb = {
+ [tbname]: [
+ {
+ "ts": date,
+ "values": values
+ }
+ ]
}
- //Režim astrohodín
- if(profile.astro_clock == true)
- {
- //if(profile.dusk_lux_sensor == false)
- {
- if(profile.hasOwnProperty("dusk_astro_clock_offset")) dusk_astro_clock_offset = parseInt( profile.dusk_astro_clock_offset );
+ tbHandler.sendToTb(dataToTb, instance);
+ }
+
+ function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) {
+
+ if (date === undefined) date = new Date();
+ //if(duskOffset === undefined) duskOffset = 0;
+ //if(dawnOffset === undefined) dawnOffset = 0;
+
+ //let line = keys[i];
+ let profilestr = "";
+ if (relaysData[line] != undefined) profilestr = relaysData[line].profile;
+
+ let result = {};
+
+ var times = SunCalc.getTimes(date, latitude, longitude);
+ let dawn = new Date(times.sunrise);//usvit
+ let dusk = new Date(times.sunset);//sumrak
+
+
+ //http://suncalc.net/#/48.5598,18.169,11/2021.04.07/11:06
+ //https://mapa.zoznam.sk/zisti-gps-suradnice-m6
+
+
+ let dusk_astro_clock_offset = duskOffset;//minutes
+ let dawn_astro_clock_offset = dawnOffset;//minutes
+
+ try {
+
+ let profile = JSON.parse(profilestr);
+ if (Object.keys(profile).length === 0) throw ("profile is not defined");
+
+ //Jednoduchý režim
+ if (profile.astro_clock == false && profile.dusk_lux_sensor == false && profile.dawn_lux_sensor == false) {
+
}
- //if(profile.dawn_lux_sensor == false)
- {
- if(profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt( profile.dawn_astro_clock_offset );
+ //Režim astrohodín
+ if (profile.astro_clock == true) {
+ //if(profile.dusk_lux_sensor == false)
+ {
+ if (profile.hasOwnProperty("dusk_astro_clock_offset")) dusk_astro_clock_offset = parseInt(profile.dusk_astro_clock_offset);
+ }
+
+ //if(profile.dawn_lux_sensor == false)
+ {
+ if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset);
+ }
+
+ }
+
+ //dusk - súmrak
+ //down, sunrise - svitanie
+
+ } catch (error) {
+ if (profilestr != "") {
+ logger.debug(profilestr);
+ logger.debug(error);
}
-
}
- //dusk - súmrak
- //down, sunrise - svitanie
-
- } catch (error) {
- if(profilestr != "")
- {
- logger.debug(profilestr);
- logger.debug(error);
+ result.dusk_no_offset = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes());
+ result.dawn_no_offset = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes());
+
+ dusk = new Date(dusk.getTime() + gmtOffset + dusk_astro_clock_offset * 60000);
+ dawn = new Date(dawn.getTime() + gmtOffset + dawn_astro_clock_offset * 60000);
+
+ result.dusk = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes());
+ result.dusk_hours = dusk.getHours();
+ result.dusk_minutes = dusk.getMinutes();
+
+ result.dawn = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes());
+ result.dawn_hours = dawn.getHours();
+ result.dawn_minutes = dawn.getMinutes();
+
+ result.dusk_time = dusk.getTime();
+ result.dawn_time = dawn.getTime();
+
+ result.dusk_astro_clock_offset = dusk_astro_clock_offset;
+ result.dawn_astro_clock_offset = dawn_astro_clock_offset;
+
+ return result;
+ }
+
+
+ function processResponse(register, bytes) {
+
+ let values = {};
+
+ let byte3 = bytes[0];
+ let byte2 = bytes[1];
+ let byte1 = bytes[2];
+ let byte0 = bytes[3];
+
+ //status
+ if (register == 0) {
+ let statecode = bytesToInt(bytes);
+ values = { "statecode": statecode };
+ return values;
}
- }
- result.dusk_no_offset = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes());
- result.dawn_no_offset = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes());
+ //Dimming, CCT
+ if (register == 1) {
+ let brightness = 0;
+ let dimming = byte0;
+ if (dimming > 128) {
+ //dimming = -128;
+ brightness = dimming - 128;
+ }
- dusk = new Date(dusk.getTime() + gmtOffset + dusk_astro_clock_offset*60000);
- dawn = new Date(dawn.getTime() + gmtOffset + dawn_astro_clock_offset*60000);
+ //cct
+ //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1
+ let cct;
+ if (byte3 == 1) cct = byte2 * 256 + byte1;
+ else cct = bytesToInt(bytes.slice(0, 3));
- result.dusk = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes());
- result.dusk_hours = dusk.getHours();
- result.dusk_minutes = dusk.getMinutes();
+ //cct podla auditu
- result.dawn = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes());
- result.dawn_hours = dawn.getHours();
- result.dawn_minutes = dawn.getMinutes();
+ values["dimming"] = brightness;
+ return values;
+ }
- result.dusk_time = dusk.getTime();
- result.dawn_time = dawn.getTime();
+ //
+ if (register == 4) {
+ values["master_node_version"] = bytes[1] + "." + bytes[2];
+ //logger.debug("FW Version", register, bytes);
+ }
- result.dusk_astro_clock_offset = dusk_astro_clock_offset;
- result.dawn_astro_clock_offset = dawn_astro_clock_offset;
+ //Napätie
+ if (register == 74) {
+ let voltage = (bytesToInt(bytes) * 0.1).toFixed(1);
+ values["voltage"] = Number(voltage);
+ }
- return result;
-}
+ //Prúd
+ if (register == 75) {
+ let current = bytesToInt(bytes);
+ values["current"] = current;
+ }
+ //výkon
+ if (register == 76) {
+ let power = (bytesToInt(bytes) * 0.1).toFixed(2);
+ values["power"] = Number(power);
+ }
-function processResponse(register, bytes)
-{
+ //účinník
+ if (register == 77) {
+ let power_factor = Math.cos(bytesToInt(bytes) * 0.1).toFixed(2);
+ values["power_factor"] = Number(power_factor);
+ }
- let values = {};
+ //frekvencia
+ if (register == 78) {
+ let frequency = (bytesToInt(bytes) * 0.1).toFixed(2);
+ values["frequency"] = Number(frequency);
+ }
- let byte3 = bytes[0];
- let byte2 = bytes[1];
- let byte1 = bytes[2];
- let byte0 = bytes[3];
+ //energia
+ if (register == 79) {
+ let energy = bytesToInt(bytes);
+
+ //Energiu treba reportovať v kWh. Teda číslo, ktoré príde treba podeliť 1000. Toto som ti možno zle napísal.
+
+ values["energy"] = energy / 1000;
+ }
+
+ //doba života
+ if (register == 80) {
+ let lifetime = (bytesToInt(bytes) / 60).toFixed(2);
+ values["lifetime"] = Number(lifetime);
+ }
+
+ //nastavenie profilu
+ if (register == 8) {
+ let time_schedule_settings = bytesToInt(bytes);
+ values["time_schedule_settings"] = time_schedule_settings;
+ }
+
+ //skupinová adresa 1
+ if (register == 3) {
+ let gr_add_1 = bytesToInt(byte0);
+ values["gr_add_1"] = gr_add_1;
+
+ let gr_add_2 = bytesToInt(byte1);
+ values["gr_add_2"] = gr_add_2;
+
+ let gr_add_3 = bytesToInt(byte2);
+ values["gr_add_3"] = gr_add_3;
+
+ let gr_add_4 = bytesToInt(byte3);
+ values["gr_add_4"] = gr_add_4;
+ }
+
+ //naklon
+ if (register == 84) {
+ let temp;
+ if (byte3 >= 128) {
+ temp = (byte3 - 128) * (-1);
+ }
+ else {
+ temp = byte3;
+ }
+
+ let inclination_x;
+ if (byte2 >= 128) {
+ inclination_x = (byte2 - 128) * (-1);
+ }
+ else {
+ inclination_x = byte2;
+ }
+
+ let inclination_y;
+ if (byte1 >= 128) {
+ inclination_y = (byte1 - 128) * (-1);
+ }
+ else {
+ inclination_y = byte1;
+ }
+
+ let inclination_z;
+ if (byte0 >= 128) {
+ inclination_z = (byte0 - 128) * (-1);
+ }
+ else {
+ inclination_z = byte0;
+ }
+
+ values["temperature"] = temp;
+
+ //náklon x
+ values["inclination_x"] = inclination_x;
+
+ //náklon y
+ values["inclination_y"] = inclination_y;
+
+ //náklon z
+ values["inclination_z"] = inclination_z;
+ }
+
+ let h = byte3;
+ let m = byte2;
+
+ let timestamp;
+
+ if (register == 87 || register == 6 || register == 7) {
+ //if(byte3 < 10) h = "0" + byte3;
+ //if(byte2 < 10) m = "0" + byte2;
+ //if(byte1 < 10) s = "0" + byte1;
+
+ var d = new Date();
+ d.setHours(h, m, 0);
+ timestamp = d.getTime();
+ }
+
+ //aktuálny čas
+ if (register == 87) {
+ //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
+ //values["actual_time"] = h + ":" + m + ":" + s;
+
+ values["actual_time"] = timestamp;
+ }
+
+ //čas súmraku
+ if (register == 6) {
+ //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
+ //values["dusk_time"] = h + ":" + m + ":" + s;
+
+ values["dusk_time"] = timestamp;
+ }
+
+ //čas úsvitu
+ if (register == 7) {
+ //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
+ //values["dawn_time"] = h + ":" + m + ":" + s;
+
+ values["dawn_time"] = timestamp;
+ }
+
+ //FW verzia
+ if (register == 89) {
+ //formát: "Byte3: Byte2.Byte1 (Byte0)"
+ values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")";
+ }
- //status
- if(register == 0)
- {
- let statecode = bytesToInt(bytes);
- values = {"statecode": statecode};
return values;
}
- //Dimming, CCT
- if(register == 1)
- {
- let brightness = 0;
- let dimming = byte0;
- if(dimming > 128) {
- //dimming = -128;
- brightness = dimming - 128;
+
+ //byte1 MSB = data3, byte2 = data2, byte3 = data1, byte4 = data0 LSB
+ function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4) {
+ let resp = [];
+
+ let cmd = register;
+
+ if (typeof adresa === 'string') adresa = parseInt(adresa);
+ if (typeof byte1 === 'string') byte1 = parseInt(byte1);
+ if (typeof byte2 === 'string') byte2 = parseInt(byte2);
+ if (typeof byte3 === 'string') byte3 = parseInt(byte3);
+ if (typeof byte4 === 'string') byte4 = parseInt(byte4);
+
+ if (rw === 0) {
+ cmd = cmd + 0x8000;
}
- //cct
- //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1
- let cct;
- if(byte3 == 1) cct = byte2*256 + byte1;
- else cct = bytesToInt(bytes.slice(0, 3));
+ //master
+ if (rec === 0) adresa = 0;
- //cct podla auditu
-
- values["dimming"] = brightness;
- return values;
- }
-
- //
- if(register == 4)
- {
- values["master_node_version"] = bytes[1] + "." + bytes[2];
- //logger.debug("FW Version", register, bytes);
- }
-
- //Napätie
- if(register == 74)
- {
- let voltage = (bytesToInt(bytes) * 0.1).toFixed(1);
- values["voltage"] = Number(voltage);
- }
-
- //Prúd
- if(register == 75)
- {
- let current = bytesToInt(bytes);
- values["current"] = current;
- }
-
- //výkon
- if(register == 76)
- {
- let power = (bytesToInt(bytes) * 0.1).toFixed(2);
- values["power"] = Number(power);
- }
-
- //účinník
- if(register == 77)
- {
- let power_factor = Math.cos(bytesToInt(bytes) * 0.1).toFixed(2);
- values["power_factor"] = Number(power_factor);
- }
-
- //frekvencia
- if(register == 78)
- {
- let frequency = (bytesToInt(bytes) * 0.1).toFixed(2);
- values["frequency"] = Number(frequency);
- }
-
- //energia
- if(register == 79)
- {
- let energy = bytesToInt(bytes);
-
- //Energiu treba reportovať v kWh. Teda číslo, ktoré príde treba podeliť 1000. Toto som ti možno zle napísal.
-
- values["energy"] = energy / 1000;
- }
-
- //doba života
- if(register == 80)
- {
- let lifetime = ( bytesToInt(bytes) / 60).toFixed(2);
- values["lifetime"] = Number(lifetime);
- }
-
- //nastavenie profilu
- if(register == 8)
- {
- let time_schedule_settings = bytesToInt(bytes);
- values["time_schedule_settings"] = time_schedule_settings;
- }
-
- //skupinová adresa 1
- if(register == 3)
- {
- let gr_add_1 = bytesToInt(byte0);
- values["gr_add_1"] = gr_add_1;
-
- let gr_add_2 = bytesToInt(byte1);
- values["gr_add_2"] = gr_add_2;
-
- let gr_add_3 = bytesToInt(byte2);
- values["gr_add_3"] = gr_add_3;
-
- let gr_add_4 = bytesToInt(byte3);
- values["gr_add_4"] = gr_add_4;
- }
-
- //naklon
- if(register == 84)
- {
- let temp;
- if(byte3 >= 128)
- {
- temp = (byte3 - 128) * (-1);
- }
- else
- {
- temp = byte3;
+ if (rec === 2) {
+ adresa = 0xffffffff;//Broadcast
}
- let inclination_x;
- if(byte2 >= 128)
- {
- inclination_x = (byte2 - 128) * (-1);
- }
- else
- {
- inclination_x = byte2;
+ //recipient
+ if (rec === 3) {
+ resp.push(0xFF);
+ resp.push(0xFF);
+ resp.push(0xFF);
+ resp.push(0xFF);
+ resp.push(adresa & 0xFF);//band
}
+ else {
+ resp.push((adresa >> 24) & 0xFF);//rshift
+ resp.push((adresa >> 16) & 0xFF);
+ resp.push((adresa >> 8) & 0xFF);
+ resp.push(adresa & 0xFF);
- let inclination_y;
- if(byte1 >= 128)
- {
- inclination_y = (byte1 - 128) * (-1);
- }
- else
- {
- inclination_y = byte1;
- }
-
- let inclination_z;
- if(byte0 >= 128)
- {
- inclination_z = (byte0 - 128) * (-1);
- }
- else
- {
- inclination_z = byte0;
- }
-
- values["temperature"] = temp;
-
- //náklon x
- values["inclination_x"] = inclination_x;
-
- //náklon y
- values["inclination_y"] = inclination_y;
-
- //náklon z
- values["inclination_z"] = inclination_z;
- }
-
- let h = byte3;
- let m = byte2;
- let s = byte1;
-
- let timestamp;
-
- if(register == 87 || register == 6 || register == 7 )
- {
- //if(byte3 < 10) h = "0" + byte3;
- //if(byte2 < 10) m = "0" + byte2;
- //if(byte1 < 10) s = "0" + byte1;
-
- var d = new Date();
- d.setHours(h);
- d.setMinutes(m);
- d.setSeconds(0);
- d.setMilliseconds(0);
-
- timestamp = d.getTime();
- }
-
- //aktuálny čas
- if(register == 87)
- {
- //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
- //values["actual_time"] = h + ":" + m + ":" + s;
-
- values["actual_time"] = timestamp;
- }
-
- //čas súmraku
- if(register == 6)
- {
- //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
- //values["dusk_time"] = h + ":" + m + ":" + s;
-
- values["dusk_time"] = timestamp;
- }
-
- //čas úsvitu
- if(register == 7)
- {
- //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
- //values["dawn_time"] = h + ":" + m + ":" + s;
-
- values["dawn_time"] = timestamp;
- }
-
- //FW verzia
- if(register == 89)
- {
- //formát: "Byte3: Byte2.Byte1 (Byte0)"
- values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")";
- }
-
- return values;
-}
-
-
-//byte1 MSB = data3, byte2 = data2, byte3 = data1, byte4 = data0 LSB
-function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4) {
- let resp = [];
-
- let cmd = register;
-
- if (typeof adresa === 'string') adresa = parseInt(adresa);
- if (typeof byte1 === 'string') byte1 = parseInt(byte1);
- if (typeof byte2 === 'string') byte2 = parseInt(byte2);
- if (typeof byte3 === 'string') byte3 = parseInt(byte3);
- if (typeof byte4 === 'string') byte4 = parseInt(byte4);
-
- if (rw === 0)
- {
- cmd = cmd + 0x8000;
- }
-
- //master
- if(rec === 0) adresa = 0;
-
- if(rec === 2)
- {
- adresa = 0xffffffff;//Broadcast
- }
-
- //recipient
- if (rec === 3)
- {
- resp.push(0xFF);
- resp.push(0xFF);
- resp.push(0xFF);
- resp.push(0xFF);
- resp.push( adresa & 0xFF );//band
- }
- else
- {
- resp.push( (adresa >> 24) & 0xFF);//rshift
- resp.push( (adresa >> 16) & 0xFF);
- resp.push( (adresa >> 8) & 0xFF);
- resp.push( adresa & 0xFF );
-
- if (rec === 2)
- {
+ if (rec === 2) {
resp.push(0xFF);
+ }
+ else resp.push(0);
}
- else resp.push(0);
+
+ resp.push((cmd >> 8) & 0xFF);//rshift
+ resp.push(cmd & 0xFF);//band
+ resp.push(byte1 & 0xFF);//band
+ resp.push(byte2 & 0xFF);//band
+ resp.push(byte3 & 0xFF);//band
+ resp.push(byte4 & 0xFF);//band
+
+ //let data = '12345';
+ let crc = crc16('ARC', resp);
+ let c1 = (crc >> 8) & 0xFF;
+ let c2 = crc & 0xFF;
+
+ resp.push(c1);
+ resp.push(c2);
+
+ //logger.debug("checksum", crc);
+ //logger.debug("resp", resp);
+
+ return resp;
+
}
- resp.push( (cmd >> 8) & 0xFF);//rshift
- resp.push( cmd & 0xFF );//band
- resp.push( byte1 & 0xFF );//band
- resp.push( byte2 & 0xFF );//band
- resp.push( byte3 & 0xFF );//band
- resp.push( byte4 & 0xFF );//band
-
- //let data = '12345';
- let crc = crc16('ARC', resp);
- let c1 = (crc >> 8) & 0xFF;
- let c2 = crc & 0xFF;
-
- resp.push(c1);
- resp.push(c2);
-
- //logger.debug("checksum", crc);
- //logger.debug("resp", resp);
-
- return resp;
-
-}
-
function getObjectByTbValue(object, 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);
}
diff --git a/flow/cmd_manager131.js b/flow/cmd_manager131.js
deleted file mode 100644
index 63c1a1f..0000000
--- a/flow/cmd_manager131.js
+++ /dev/null
@@ -1,3603 +0,0 @@
-exports.id = 'cmd_manager';
-exports.title = 'CMD Manager';
-exports.group = 'Worksys';
-exports.color = '#5D9CEC';
-exports.version = '0.0.3';
-exports.output = ['red', 'blue', 'yellow', 'blue', 'white'];
-
-//blue - send message to relays
-
-exports.input = 2;
-exports.icon = 'cloud-upload';
-//exports.npm = ['serialport' , 'child_process'];
-
-exports.html = `
-
-`;
-
-exports.readme = `Manager for CMD calls`;
-
-const SerialPort = require('serialport');
-const { exec } = require('child_process');
-const { crc8, crc16, crc32 } = require('easy-crc');
-const { openPort, runSyncExec, writeData } = require('./helper/serialport_helper.js');
-const { bytesToInt, longToByteArray, addZeroBefore, isEmptyObject, convertUTCDateToLocalDate } = require('./helper/utils');
-const bitwise = require('bitwise');
-
-var SunCalc = require('./helper/suncalc.js');
-const DataToTbHandler = require('./helper/DataToTbHandler.js');
-const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler.js');
-const { promisifyBuilder, makeMapFromDbResult} = require('./helper/db_helper.js');
-const { sendNotification, initNotifications, ERRWEIGHT } = require('./helper/notification_reporter.js');
-
-const dbNodes = TABLE("nodes");
-const dbRelays = TABLE("relays");
-const dbSettings = TABLE("settings");
-
-//https://github.com/log4js-node/log4js-node/blob/master/examples/example.js
-//file: { type: 'file', filename: path.join(__dirname, 'log/file.log') }
-var path = require('path');
-var log4js = require("log4js");
-const process = require('process');
-
-//TODO - to remove?
-// runTasks intervals
-const SHORT_INTERVAL = 30;
-const LONG_INTERVAL = 300;
-
-//send data to following instances:
-const SEND_TO = {
- debug: 0,
- tb: 1,
- http_response: 2,
- dido_controller: 3,
- infoSender: 4
-}
-
-const PRIORITY_TYPES = {
- terminal: 0,
- fw_detection: 1,//reserved only for FW detection - FLOW.OMS_masterNodeIsResponding
- high_priority: 2,//reserverd only for: read dimming / brightness (after set dimming from platform)
- relay_profile: 3,
- node_broadcast: 4,
- node_profile: 5,
- node_cmd: 6
-}
-
-const TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION = 600000; // 10 minutes
-
-//list of command calls to process. Processing in runTasks function
-let tasks = [];
-
-let interval = null;//timeout for procesing tasks
-let customTasksInterval = null;
-let refFlowdata = null;//holds reference to httprequest flowdata
-let refFlowdataObj = {};
-
-//load from settings
-let latitude = 48.70826502;//48.682255758;
-let longitude = 17.28455203;//17.278910807;
-
-const gmtOffset = 0;
-
-//ak nie je nastaveny
-//https://www.tecmint.com/set-time-timezone-and-synchronize-time-using-timedatectl-command/
-//https://stackoverflow.com/questions/16086962/how-to-get-a-time-zone-from-a-location-using-latitude-and-longitude-coordinates
-
-//priorities for registers
-let priorities = [];
-
-let minutes = 1;
-priorities["0"] = minutes;
-priorities["1"] = minutes;
-
-minutes = 5;
-priorities["74"] = minutes;
-priorities["75"] = minutes;
-priorities["76"] = minutes;
-priorities["77"] = minutes;
-priorities["78"] = minutes;
-priorities["79"] = minutes;
-priorities["84"] = minutes;
-
-minutes = 10;
-priorities["87"] = minutes;
-priorities["6"] = minutes;
-priorities["7"] = minutes;
-priorities["80"] = minutes;
-priorities["8"] = minutes;
-priorities["3"] = minutes;
-priorities["89"] = minutes;
-
-//prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming)
-let listOfCommands = [0,1,3,6,7,8,74,75,76,77,78,79,80,84,87,89];
-
-const errorHandler = new ErrorToServiceHandler();
-
-let rotary_switch_state = "Off";
-let lux_sensor;
-let state_of_breaker = {};//key is line, value is On/Off
-let disconnectedReport = {};//key is tbname, value true/false
-
-let relaysData = {};//key is line, value is data from db
-let nodesData = {};//key is node, value data from db
-
-//helper container for counting resolved group of commands (commands related to set profile)
-let cmdCounter = {};//key is node, value is counter
-
-//END OF VARIABLE SETTINGS
-//--------------------------------
-
-
-log4js.configure({
- appenders: {
- errLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'err.txt') },
- monitorLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'monitor.txt') },
- console: { type: 'console' }
- },
- categories: {
- errLogs: { appenders: ['console', 'errLogs'], level: 'error' },
- monitorLogs: { appenders: ['console', 'monitorLogs'], level: 'trace' },
- //another: { appenders: ['console'], level: 'trace' },
- default: { appenders: ['console'], level: 'trace' }
- }
-});
-
-const errLogger = log4js.getLogger("errLogs");
-const logger = log4js.getLogger();
-const monitor = log4js.getLogger("monitorLogs");
-
-//USAGE
-//logger.debug("text")
-//monitor.info('info');
-//errLogger.error("some error");
-
-
-function cmdCounterResolve(address)
-{
- if(cmdCounter.hasOwnProperty(address))
- {
- cmdCounter[address] = cmdCounter[address] - 1;
-
- let result = cmdCounter[address];
- if(result == 0) delete cmdCounter[address];
- return result;
- }
- return -1;
-}
-
-
-function getParams(priority)
-{
- let params = {};
-
- //core rpc values
- params.address = 0;//if(recipient === 0) address = 0;
- params.byte1 = 0;//msb, podla dokumentacie data3
- params.byte2 = 0;//podla dokumentacie data2
- params.byte3 = 0;//podla dokumentacie data1
- params.byte4 = 0;//lsb, podla dokumentacie data0
- params.recipient = 0;//0: Master, 1: Slave, 2: Broadcast
- params.register = -1;//register number
- params.rw = 0;//0: read, 1: write
-
- //other values
- //params.type = "cmd"; "relay" "cmd-terminal" "set_node_profile" "process_profiles"
- //params.tbname = tbname;
- params.priority = PRIORITY_TYPES.node_cmd; //default priority - if more tasks with the same timestamp, we sort them based on priority
- params.timestamp = 0; //execution time - if timestamp < Date.now(), the task is processed
- if(priority != undefined )
- {
- params.timestamp = priority;
- params.priority = priority;
- }
-
- params.addMinutesToTimestamp = 0;//repeat task if value is > 0,
-
- //params.timePointName = "luxOff" // "luxOn", "dusk", "dawn", "profileTimepoint"
- //params.info = "";
-
- return params;
-}
-
-
-async function loadSettings()
-{
- let responseSettings = await promisifyBuilder(dbSettings.find());
-
- latitude = responseSettings[0]["latitude"];
- longitude = responseSettings[0]["longitude"];
-
- //globals
- FLOW.OMS_language = responseSettings[0]["lang"];
- FLOW.OMS_rvo_name = responseSettings[0]["rvo_name"];
- FLOW.OMS_projects_id = responseSettings[0]["projects_id"];
- //FLOW.OMS_rvo_tbname = responseSettings[0]["tbname"];
- FLOW.OMS_temperature_adress = responseSettings[0]["temperature_adress"];
- FLOW.OMS_controller_type = responseSettings[0]["controller_type"];
- FLOW.OMS_serial_port = responseSettings[0]["serial_port"];
- FLOW.OMS_node_status_nok_time = responseSettings[0]["node_status_nok_time"] * 60 * 60 * 1000; // hour * minutes * seconds
- //logger.debug('settings', responseSettings[0]);
-
- initNotifications();
-}
-
-loadSettings();
-
-
-async function loadNodes()
-{
- const responseNodes = await promisifyBuilder(dbNodes.find());
- nodesData = makeMapFromDbResult(responseNodes, "node");
-}
-
-loadNodes();
-
-
-//nastav profil nodu
-function processNodeProfile(node)
-{
- if(rotary_switch_state != "Automatic")
- {
- logger.debug("unable to process profile for node", node, "rotary_switch_state != Automatic");
- return;
- }
-
- let nodeObj = nodesData[node];
- let line = nodeObj.line;
-
- if(relaysData[line].contactor == 0)
- {
- logger.debug("line line is off", line, node);
- return;
- }
-
- if(nodeObj.processed == 1)
- {
- logger.debug("node was already processed", node);
- return;
- }
-
- let nodeProfile = nodeObj.profile;
- logger.debug("processNodeProfile: start - set profile for ", node, nodeProfile);
- if(nodeProfile) {
-
- try {
- nodeProfile = JSON.parse(nodeProfile);
- } catch (error) {
- logger.debug("Cmd_manager - Error parsing node profile", error);
- }
-
- }
-
- logger.debug("processNodeProfile", node, line, nodeObj, nodeProfile);
-
- let timestamp = PRIORITY_TYPES.node_cmd;
-
- removeTask({type: "set_node_profile", address: node});
-
- if(nodeProfile === "")
- {
- //vypneme profil nodu, posleme cmd
- //Pokiaľ je hodnota rovná 1 – Profil sa zapne, ostatné bity sa nezmenia.
- //Pokiaľ sa hodnota rovná 2 – profil sa vypne, ostatné bity sa nezmenia
-
- logger.debug("turn off profile");
-
- let params = getParams(PRIORITY_TYPES.node_cmd);
- params.type = "set_node_profile";
- params.address = node;
- params.byte1 = 0;
- params.byte2 = 0;
- params.byte3 = 0;
- params.byte4 = 96;
- params.recipient = 1;
- params.register = 8;
- params.rw = 1;//write
- params.timestamp = timestamp;
- params.addMinutesToTimestamp = 0;
- params.info = 'turn off/reset node profile';
-
- cmdCounter[node] = 1;
-
- tasks.push(params);
- }
- else
- {
- let tasksProfile = [];
-
- //vypneme profil - Zapísať hodnotu 32 do registra Time Schedule Settings – reset profilu
- let params = getParams(PRIORITY_TYPES.node_cmd);
- params.type = "set_node_profile";
- params.address = node;
- params.byte1 = 0;
- params.byte2 = 0;
- params.byte3 = 0;
- params.byte4 = 96;
- params.recipient = 1;
- params.register = 8;
- params.rw = 1;//write
- params.timestamp = timestamp;
- params.addMinutesToTimestamp = 0;
- params.info = 'turn off node profile';
-
- tasksProfile.push(params);
-
- timestamp++;
-
- logger.debug("processNodeProfile: TS1 Time point a TS1 Time Point Levels ", node);
-
- //TS1 Time point a TS1 Time Point Levels
- let register = 9;
- for(let i = 0; i < nodeProfile.intervals.length; i++)
- {
- let obj = nodeProfile.intervals[i];
- //let timePoint = obj.time_point;
- let dim_value = obj.value;
-
-
- //Reg 9 až Reg 40
-
- /*
- Samotný profil sa zapisuje do max. 16 párov – časový bod a úroveň.
- Prázdny profil je vtedy keď časový bod obsahuje hodnotu 0xFFFFFFFF (táto hodnota sa zapíše do registrov keď sa aktivuje reset profilu do registru 8).
- Páry sa prechádzajú časovo zoradené takže teoreticky je jedno v akom poradí sa zapisujú ale je lepšie ich zapisovať v chronologickom poradí od 13:00.
- Časový bod má formát:
- Byte 3: hodiny Byte 2: minúty Byte 1: sekundy Byte 0 – rezervované
- Register úrovne má rovnaký formát ako dimming register (Reg 1).
- */
-
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- //params.byte1 = 0;//msb, podla dokumentacie data3
- //params.byte2 = 0;//podla dokumentacie data2
- //params.byte3 = 0;//podla dokumentacie data1
- //params.byte4 = 0;//lsb, podla dokumentacie data0
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
- let start_time = obj.start_time;
- let t = start_time.split(":");
- //if(timePoint != undefined) t = timePoint.split(":");
- //else t = [0,0];
-
- logger.debug("processNodeProfile: TS1 Time point ", (i + 1), node);
-
- params = getParams(PRIORITY_TYPES.node_cmd);
- params.type = "set_node_profile";
- params.address = node;
- params.byte1 = parseInt(t[0]);//hh
- params.byte2 = parseInt(t[1]);//mm
- params.byte3 = 0;//ss
- params.byte4 = 0;//
- params.recipient = 1;
- params.register = register;
- params.rw = 1;//write
- params.timestamp = timestamp;
- params.addMinutesToTimestamp = 0;
- params.info = 'TS1 Time point ' + (i + 1);
-
- tasksProfile.push(params);
-
- register++;
- timestamp++;
-
- params = getParams(PRIORITY_TYPES.node_cmd);
- params.type = "set_node_profile";
- params.address = node;
- params.byte1 = 0;
- params.byte2 = 0;
- params.byte3 = 0;//ss
- params.byte4 = parseInt(dim_value) + 128;//
- params.recipient = 1;
- params.register = register;
- params.rw = 1;//write
- params.timestamp = timestamp;
- params.addMinutesToTimestamp = 0;
- params.info = 'TS1 Time point Levels ' + (i + 1);
-
- tasksProfile.push(params);
-
- register++;
- timestamp++;
- }
-
- //Threshold lux level for DUSK/DAWN
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- //params.byte1 = 0;//msb, podla dokumentacie data3
- //params.byte2 = 0;//podla dokumentacie data2
- //params.byte3 = 0;//podla dokumentacie data1
- //params.byte4 = 0;//lsb, podla dokumentacie data0
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-
- //Time schedule settings na koniec
- //if(nodeProfile.dusk_lux_sensor || nodeProfile.dawn_lux_sensor)
- {
-
- logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node);
-
- let params = getParams(PRIORITY_TYPES.node_cmd);
- params.type = "set_node_profile";
- params.address = node;
- params.register = 96;
- params.recipient = 1;
- params.rw = 1;//write
- params.timestamp = timestamp;
- params.addMinutesToTimestamp = 0;
- params.info = "Threshold lux level for DUSK/DAWN";
-
- if(nodeProfile.dusk_lux_sensor)
- {
- let v = nodeProfile.dusk_lux_sensor_value;
- let ba = longToByteArray(v);
-
- params.byte1 = ba[1];//msb
- params.byte2 = ba[0];
- }
-
- if(nodeProfile.dawn_lux_sensor)
- {
- let v = nodeProfile.dawn_lux_sensor_value;
- let ba = longToByteArray(v);
-
- params.byte3 = ba[1];//msb
- params.byte4 = ba[0];
- }
-
- tasksProfile.push(params);
- timestamp++;
-
- }
-
- //DUSK/DAWN max. adjust period
- {
-
- logger.debug("processNodeProfile: DUSK/DAWN max. adjust period", node);
-
- let params = getParams(PRIORITY_TYPES.node_cmd);
- params.type = "set_node_profile";
- params.address = node;
- params.register = 97;
- params.recipient = 1;
- params.rw = 1;//write
- params.timestamp = timestamp;
- params.addMinutesToTimestamp = 0;
- params.info = "DUSK/DAWN max. adjust period";
-
- if(nodeProfile.astro_clock)
- {
- let v = nodeProfile.dusk_lux_sensor_time_window;
- let ba = longToByteArray(v);
-
- params.byte1 = ba[1];//msb
- params.byte2 = ba[0];
- }
-
- if(nodeProfile.astro_clock)
- {
- let v = nodeProfile.dawn_lux_sensor_time_window;
- let ba = longToByteArray(v);
-
- params.byte3 = ba[1];//msb
- params.byte4 = ba[0];
- }
-
- tasksProfile.push(params);
- timestamp++;
-
- }
-
- //Static offset
- {
-
- //Statický offset pre časy úsvitu a súmraku. Byte 1 je pre DUSK, Byte 0 je pre DAWN. Formát:
- //Bity 0 – 6: hodnota v minútach
- //Bit 7: znamienko (1 – mínus)
-
- logger.debug("processNodeProfile: Static offset", node);
-
- let params = getParams(PRIORITY_TYPES.node_cmd);
- params.type = "set_node_profile";
- params.address = node;
- params.register = 98;
- params.recipient = 1;
- params.rw = 1;//write
- params.timestamp = timestamp;
- params.addMinutesToTimestamp = 0;
- params.info = "Static offset";
-
- if(nodeProfile.astro_clock)
- {
- let dusk_astro_clock_offset = parseInt(nodeProfile.dusk_astro_clock_offset);
- let dawn_astro_clock_offset = parseInt(nodeProfile.dawn_astro_clock_offset);
-
- if(dusk_astro_clock_offset < 0)
- {
- params.byte3 = (dusk_astro_clock_offset * -1) + 128;
- }
- else
- {
- params.byte3 = dusk_astro_clock_offset;
- }
-
- if(dawn_astro_clock_offset < 0)
- {
- params.byte4 = (dawn_astro_clock_offset * -1) + 128;
- }
- else
- {
- params.byte4 = dawn_astro_clock_offset;
- }
- }
-
- tasksProfile.push(params);
- timestamp++;
- }
-
- logger.debug("Time schedule settings - turn on", node);
-
- params = getParams(PRIORITY_TYPES.node_cmd);
- params.type = "set_node_profile";
- params.address = node;
- params.register = 8;
- params.recipient = 1;
- params.rw = 1;//write
-
- //Time schedule settings
- let bits = [];
-
- //Byte 0 (LSB):
- //Bit 0 (LSB) – zapnutie/vypnutie profilov ako takých (1 – zapnuté).
- bits.push(1);
- //Bit 1 – 3 - zatiaľ nepoužité (zapisovať 0)
- bits.push(0);
- bits.push(0);
- bits.push(0);
- if(nodeProfile.astro_clock == true)
- {
- //Bit 4 – ak je nastavený profil sa riadi podľa astrohodín, a je 0 tak profil je jednoduchý
- bits.push(1);
- }
- else bits.push(0);
-
- //Bit 5 – zápis 1 spôsobí reset nastavení profilu (nastavenie prázdneho profilu)
- bits.push(0);
-
- //Bity 6-7 - zatiaľ nepoužité
- bits.push(0);
- bits.push(0);
-
- params.byte4 = bitwise.byte.write(bits.reverse());
-
- //Byte 2 – nastavenie pre lux senzor:
- bits = [];
-
- //Bit 0 (LSB) – riadenie súmraku podľa lux senzoru (1 – zapnuté). Súmrak sa môže posúvať v rámci času v registri 97 podľa intenzity osvetlenia
- if(nodeProfile.dusk_lux_sensor == true)//sumrak
- {
- bits.push(1);
- }
- else bits.push(0);
-
- //Bit 1 - riadenie úsvitu podľa lux senzoru (1 – zapnuté). Úsvit sa môže posúvať v rámci času v registri 97 podľa intenzity osvetlenia
- if(nodeProfile.dawn_lux_sensor == true)//usvit
- {
- bits.push(1);
- }
- else bits.push(0);
-
- //Bit 2 – zdroj pre hodnotu luxov – 0 – RVO posiela hodnoty zo svojho luxmetra, 1 – node má pripojený svoj vlastný lux meter.
- bits.push(0);//zatial neimplementovane
-
- //Bit 3 – 7 - nepoužité
- bits.push(0);
- bits.push(0);
- bits.push(0);
- bits.push(0);
- bits.push(0);
-
- params.byte2 = bitwise.byte.write(bits.reverse());
- params.timestamp = timestamp;
- params.info = "Time schedule settings - turn on";
-
- tasksProfile.push(params);
-
- //zaver
- cmdCounter[node] = tasksProfile.length;
-
- //tasks.push(tasksProfile);
- tasks = tasks.concat(tasksProfile);
-
- }
-
- logger.debug("finished set profile for ", node);
-
-}
-
-
-function cleanUpRefFlowdataObj()
-{
- let now = new Date();
- let timestamp = now.getTime();
-
- //clear old refFlowdata references
- let keys = Object.keys(refFlowdataObj);
- for(let i = 0; i < keys.length; i++)
- {
- let timestampKey = keys[i];
-
- if((timestamp - timestampKey) > 60*1000 )
- {
- console.log("cleanUpRefFlowdataObj delete", timestampKey);
- delete refFlowdataObj[ timestampKey ];
- }
- }
-}
-
-
-function removeTask(obj)
-{
- let keys = Object.keys(obj);
- tasks = tasks.filter((task) => {
-
- let counter = 0;
- for(let i = 0; i < keys.length; i++)
- {
- let key = keys[i];
- if(task.hasOwnProperty(key) && obj.hasOwnProperty(key))
- {
- if(task[key] == obj[key]) counter++;
- }
- }
-
- if(counter == keys.length) return false;
- return true;
- });
-}
-
-
-exports.install = function(instance) {
-
- let now = new Date();
- console.log("CMD Manager installed", now.toLocaleString("sk-SK"));
-
- const tbHandler = new DataToTbHandler(SEND_TO.tb);
- tbHandler.setSender(exports.title);
-
- //FLOW.OMS_projects_id, name: FLOW.OMS_rvo_name
- //const errorHandler = new ErrorToServiceHandler(instance, SEND_TO.infoSender);
- errorHandler.setProjectsId(FLOW.OMS_projects_id);
- //const errorHandler = new ErrorToServiceHandler(instance);
- //errorHandler.sendMessageToService("ahoj", 0);
-
- let sunCalcResult = calculateDuskDawn();
-
- let reportDuskDawn = {
- dusk_time: sunCalcResult.dusk_time,
- dawn_time: sunCalcResult.dawn_time,
- dusk_time_reported: undefined,
- dawn_time_reported: undefined
- };
-
-
- process.on('uncaughtException', function (err) {
- //TODO send to service
-
- errLogger.error('uncaughtException:', err.message)
- errLogger.error(err.stack);
-
- errorHandler.sendMessageToService(err.message + "\n" + err.stack, 0, "js_error");
- //process.exit(1);
- })
-
- //te();//force error
-
-
- function processAllNodeProfilesOnLine(line)
- {
-
- for (let k in nodesData) {
- //node:number|tbname:string|line:number|profile:string|processed:boolean
-
- if(line == nodesData[k].line)
- {
- let node = nodesData[k].node;
- let processed = nodesData[k].processed;
-
- if(!processed)
- {
- processNodeProfile(node);
- }
- else
- {
- logger.debug( `Node ${node} profile for line ${nodesData[k].line} was already processed`);
- }
- }
- }
- }
-
-
- async function loadRelaysData(line) {
-
- relaysData = await promisifyBuilder(dbRelays.find());
- relaysData = makeMapFromDbResult(relaysData, "line");
-
- for (const [key, value] of Object.entries(relaysData))
- {
- if(key == "0") continue;
- if(line != undefined)
- {
- //ak sa jedna o update profilu linie - pozor dido_controller posiela command pre loadRelaysData
- if(line != value.line ) continue;
- }
-
- if(value.contactor == 1) processAllNodeProfilesOnLine(value.line);
- }
-
-// console.log('.........', relaysData);
- }
-
-
- function reportOnlineNodeStatus(line)
- {
- //broadcast cas, o 3 sek neskor - status, brightness
- //Po zapnutí línie broadcastovo aktualizovať predtým čas.
-
- logger.debug("--->reportOnlineNodeStatus for line", line);
-
- //return;
-
- //run broadcast //Actual time
- addMinutesToTimestamp = 0;
-
- let params = {};
-
- var d = new Date();
- let hours = d.getHours();
- let minutes = d.getMinutes();
- let seconds = d.getSeconds();
-
- let time = d.getTime(); // time in ms
-
- params.address = 0xffffffff;//Broadcast
- params.byte1 = hours;//h
- params.byte2 = minutes;//m
- params.byte3 = seconds;//s
- params.byte4 = 0;
- params.recipient = 2;//2 broadcast, address = 0
- params.register = 87;//Actual time
- params.rw = 1;//write
-
- //other values
- params.type = "cmd";
- params.timestamp = Date.now() + 60000;
- params.addMinutesToTimestamp = addMinutesToTimestamp;
- params.info = "run broadcast: Actual time";
-
- tasks.push(params);
-
- let sec = 3;
- setTimeout(function(){
- //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel
-
- for (let k in nodesData) {
-
- //potrebujem nody k danej linii
- if(line == nodesData[k].line || line == undefined)
- {
- let tbname = nodesData[k].tbname;
- let node = nodesData[k].node;
- let status = "NOK";
-
- // if status of node was "OK" before switching it off, we set the node's time_of_last_communication on time, it was switched on again and send OK status to tb.
- if(nodesData[k].status) {
- status = "OK";
- nodesData[k].time_of_last_communication = time;
- }
-
- let dataToTb = {
- [tbname]: [
- {
- ts: time,
- values: {
- status: status
- }
- }
- ]
- }
-
- tbHandler.sendToTb(dataToTb, instance);
-
- //prud, vykon - current, input power pre liniu pre vsetky nody
-
- //a pridame aj vyreportovanie dimmingu
- {
- let params = getParams(PRIORITY_TYPES.high_priority);
-
- params.type = "cmd";
- params.tbname = tbname;
- params.address = node;
- params.register = 1;//dimming
- params.recipient = 1;//slave
- params.rw = 0;//read
- params.timestamp = PRIORITY_TYPES.high_priority;
- params.info = 'read dimming';
- //params.debug = true;
-
- tasks.push(params);
- }
-
- //Prúd
- {
- let params = getParams(PRIORITY_TYPES.high_priority);
-
- params.type = "cmd";
- params.tbname = tbname;
- params.address = node;
- params.register = 75;//prud
- params.recipient = 1;//slave
- params.rw = 0;//read
- params.timestamp = PRIORITY_TYPES.high_priority;
- params.info = 'read current';
- //params.debug = true;
-
- tasks.push(params);
- }
-
- //výkon
- {
- let params = getParams(PRIORITY_TYPES.high_priority);
-
- params.type = "cmd";
- params.tbname = tbname;
- params.address = node;
- params.register = 76;//výkon
- params.recipient = 1;//slave
- params.rw = 0;//read
- params.timestamp = PRIORITY_TYPES.high_priority;
- params.info = 'read power';
- //params.debug = true;
-
- tasks.push(params);
- }
- }
- }
- },sec*1000);
- }
-
-
- function reportOfflineNodeStatus(line)
- {
- logger.debug("--->reportOfflineNodeStatus for line", line);
-
- values = {};
- values["dimming"] = 0;//brightness
- values["power"] = 0;//výkon
- values["current"] = 0;//prúd
- values["status"] = "OFFLINE";
-
- // it happens, that some data did not get to tb after sending
- // we setTimeout to make more time for db to process telemetry (eg 150 messages at once)
- Object.keys(nodesData).forEach((node, index) => {
-
- setTimeout(function() {
-
- //potrebujem nody k danej linii
- if(line == nodesData[node].line || line == undefined)
- {
- let tbname = nodesData[node].tbname;
-
- let dataToTb = {
- [tbname]: [
- {
- "ts": Date.now(),
- "values": values
- }
- ]
- }
-
- //instance.send(SEND_TO.tb, dataToTb);
- tbHandler.sendToTb(dataToTb, instance);
- }
-
- },(index+1) * 300);
- })
-
- }
-
-
- function turnOnLine(line, info)
- {
- let obj = {
- line: line,
- command: "turnOn",
- info: info
- };
-
- logger.debug("linia", line, obj);
- instance.send(SEND_TO.dido_controller, obj);
- }
-
- function turnOffLine(line, info)
- {
- let obj = {
- line: line,
- command: "turnOff",
- info: info
- };
-
- logger.debug("linia", line, obj);
- instance.send(SEND_TO.dido_controller, obj);
- }
-
-
- function detectIfResponseIsValid(bytes)
- {
- //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK
- let type = "RESPONSE";
- if(bytes[4] == 0) type = "RESPONSE";
- else if(bytes[4] == 1) type = "ERROR";
- else if(bytes[4] == 2) type = "EVENT";
- else type = "UNKNOWN";
-
- let crc = crc16('ARC', bytes.slice(0, 9));
- let c1 = (crc >> 8) & 0xFF;
- let c2 = crc & 0xFF;
-
- let message = "OK";
- let error = "";
- if(c1 != bytes[9])
- {
- //CRC_ERROR
- message = "NOK";
- error = "CRC_ERROR c1";
- instance.send(SEND_TO.debug, "CRC_ERROR c1");
- }
-
- if(c2 != bytes[10])
- {
- //CRC_ERROR
- message = "NOK";
- error = "CRC_ERROR c2";
- instance.send(SEND_TO.debug, "CRC_ERROR c2");
- }
-
- //crc error
- if(type != "RESPONSE")
- {
- instance.send(SEND_TO.debug, bytes);
- instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]);
-
- //logger.debug(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4], bytes);
-
- error = "type is: " + type;
-
- message = "NOK";
- }
-
- return {message, type, error};
- }
-
-
- //BUILD TASKS//
- function buildTasks(params)
- {
- //report FLOW.OMS_edge_fw_version as fw_version
- //report date as startdate
-
- //return;
-
- monitor.info("buildTasks - params", params);
-
- let processLine; //defined line
- let init = false;
- let processLineProfiles = true;
- let processBroadcast = true;
- let processNodes = true;
-
- if(params == undefined)
- {
- init = true;
- tasks = [];
- logger.debug("-->buildTasks clear tasks");
- }
- else
- {
- processLineProfiles = false;
- processBroadcast = false;
- processNodes = false;
-
- processLineProfiles = params.processLineProfiles;
- processLine = params.line;
- }
-
- //load profiles pre linie
- //relaysData[ record["line"] ]
-
- let now = new Date();
-
- if(processLineProfiles)
- {
- //process line profiles
- let keys = Object.keys(relaysData);
- for(let i = 0; i < keys.length; i++)
- {
- let line = parseInt(keys[i]); //line is turned off by default
- let profilestr = relaysData[line].profile;
-
- if(processLine != undefined)
- {
- if(processLine != line) continue;
- }
-
- try {
-
- /**
- * we process line profiles: timepoints, astro clock, lux_sensor, offsets ...
- */
- if(profilestr === "") throw ("Profile is not defined");
- let profile = JSON.parse(profilestr);
- if(Object.keys(profile).length === 0) throw ("Profile is empty");
-
- monitor.info("buildTasks: profile for line", line);
- monitor.info("profile:", profile);
-
- let time_points = profile.time_points;
- if(time_points == undefined) time_points = profile.intervals;
-
- // add name to regular profile timepoint and delete unused end_time key:
- time_points.forEach(point => {
- point.name = "profileTimepoint"
- delete point.end_time;
- });
-
- //monitor.info("buildTasks: time_points", time_points);
-
- let currentValue = 0;
- if(time_points.length > 0) currentValue = time_points[time_points.length - 1].value;
-
-
- /**
- * if astro_clock is true, we create timepoints, that switch on/off relays accordingly.
- * we need to manage, astro clock timepoints has the greatest priority - normal timepoints will not switch off/on lines before dusk or dawn
- * if dawn/dusk_lux_sensor is true, it has higher priority than astro_clock switching
- */
- if(profile.astro_clock == true)
- {
-
- // if astro clock true, we remove all regular profile points
- time_points = [];
-
- let sunCalcResult = calculateDuskDawn(new Date(), line);
-
- // adding dusk dawn to timpoints
- if(profile.dawn_lux_sensor == false) time_points.push({"start_time": sunCalcResult["dawn"], "value": 0, "name":"dawn"});
- if(profile.dusk_lux_sensor == false) time_points.push({"start_time": sunCalcResult["dusk"], "value": 1, "name":"dusk"});
-
- //if dusk/dawn is true, lines will switch on/off according to lux_sensor value. In case it fails, we create lux_timepoints, to make sure lines will switch on/off (aby nam to nezostalo svietit)
- //force to turn off after timestamp: dawn + dawn_lux_sensor_time_window
- if(profile.dawn_lux_sensor == true)
- {
- let [ahours, aminutes, aseconds] = sunCalcResult["dawn"].split(':');
- let ad = new Date();
- ad.setHours(parseInt(ahours));
- ad.setMinutes(parseInt(aminutes) + profile.dawn_lux_sensor_time_window);
- ad.setSeconds(0);
-
- let strDate = ad.getHours() + ":" + ad.getMinutes();
-
- time_points.push({"value": 0, "start_time": strDate, "name": "luxOff"});
- }
-
- if(profile.dusk_lux_sensor == true)
- {
- let [ahours, aminutes, aseconds] = sunCalcResult["dusk"].split(':');
- let ad = new Date();
- ad.setHours(parseInt(ahours));
- ad.setMinutes(parseInt(aminutes) + profile.dusk_lux_sensor_time_window);
- ad.setSeconds(0);
-
- let strDate = ad.getHours() + ":" + ad.getMinutes();
-
- time_points.push({"value": 1, "start_time": strDate, "name": "luxOn"});
- //time_points.push({"value": 1, "start_time": "15:19", "name": "luxOn"}); //testing
- }
- }
-
- //sort time_points
- time_points.sort(function (a, b) {
-
- let [ahours, aminutes, aseconds] = a.start_time.split(':');
- let [bhours, bminutes, bseconds] = b.start_time.split(':');
-
- let ad = new Date();
- ad.setHours( parseInt(ahours) );
- ad.setMinutes( parseInt(aminutes) );
- ad.setSeconds(0);
-
- let bd = new Date();
- bd.setHours( parseInt(bhours) );
- bd.setMinutes( parseInt(bminutes) );
- ad.setSeconds(0);
-
- return ad.getTime() - bd.getTime();
- });
-
- console.log("line timepoints ........", time_points);
-
- monitor.info("-->comming events turn on/off lines:");
- for(let t = 0; t < time_points.length; t++)
- {
-
- let start_time = new Date();
- let [hours, minutes, seconds] = time_points[t].start_time.split(':');
-
- start_time.setHours( parseInt(hours) );
- start_time.setMinutes( parseInt(minutes) );
- start_time.setSeconds(0);
-
- //task is the past
- if(now.getTime() > start_time.getTime())
- {
- currentValue = time_points[t].value;
-
- //timepoint is in past, we add 24 hours
- start_time.setDate(start_time.getDate() + 1);
- }
-
- let params = getParams(PRIORITY_TYPES.relay_profile);
- params.type = "relay";
- params.line = parseInt(line);
- params.value = time_points[t].value;
- params.tbname = relaysData[line].tbname;
- params.timestamp = start_time.getTime();
-
- params.addMinutesToTimestamp = 0;
-
- // it timepoints are not calculated (dawn, dusk, lux_timepoint), but static points in line profile, we just repeat the task every day
- if(time_points[t].name == "profileTimepoint") params.addMinutesToTimestamp = 24*60;
-
- //astro timepoints will be recalculated dynamically:
- params.timePointName = time_points[t].name;
-
- // if astro timepoint, we save time window:
- if(['luxOn', 'luxOff', 'dusk','dawn'].includes(params.timePointName))
- {
- params.dawn_lux_sensor_time_window = profile.dawn_lux_sensor_time_window;
- params.dusk_lux_sensor_time_window = profile.dusk_lux_sensor_time_window;
- }
-
- if(params.value == 0) params.info = `${params.timePointName}: turn off line: ` + line;
- else if(params.value == 1) params.info = `${params.timePointName}: turn on line: ` + line;
-
- params.debug = true;
-
- //turn on/off line
- tasks.push(params);
- monitor.info(params.info, start_time);
-
- }
-
- monitor.info("-->time_points final", line, time_points);
-
- //ensure to turn on/off according to calculated value
- let params = getParams(PRIORITY_TYPES.terminal);
- params.type = "relay";
- params.line = parseInt(line);
- params.tbname = relaysData[line].tbname;
- params.value = currentValue;
-
- params.timestamp = PRIORITY_TYPES.terminal;
- params.addMinutesToTimestamp = 0;
- params.debug = true;
-
- //logger.debug(now.toLocaleString("sk-SK"));
- monitor.info("-->currentValue for relay", line, currentValue);
-
- //turn on/off line
- if(params.value == 0) params.info = "turn off line on startup: " + line;
- else if(params.value == 1) params.info = "turn on line on startup: " + line;
-
- tasks.push(params);
-
- } catch (error) {
- if(profilestr !=="" )
- {
- //errLogger.error(profilestr, error);
- errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error");
- }
- }
-
- }
-
- //logger.debug("tasks:");
- //logger.debug(tasks);
- }
-
-
- //PROCESS DEFAULT BROADCASTS
-
- //RPC pre nody / broadcast
- //Time of dusk, Time of dawn
- //Actual Time
-
- if(processBroadcast)
- {
- let addMinutesToTimestamp = 5;
-
- {
- //run broadcast Time of dusk
- addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk
-
- let params = getParams(PRIORITY_TYPES.node_broadcast);
-
- let sunCalcResult = calculateDuskDawn();
- let dusk_hours = sunCalcResult["dusk_hours"];
- let dusk_minutes = sunCalcResult["dusk_minutes"];
-
- params.address = 0xffffffff;//broadcast
- params.byte1 = dusk_hours;//h
- params.byte2 = dusk_minutes;//m
- params.byte3 = 0;//s
- params.byte4 = 0;
- params.recipient = 2;//2 broadcast,
- params.register = 6;//Time of dusk - Reg 6
- params.rw = 1;//write
-
- //other values
- params.type = "cmd";
- params.timestamp = Date.now() + 60000;
- params.addMinutesToTimestamp = addMinutesToTimestamp;
- params.info = "Broadcast-duskTime";
-
- tasks.push(params);
- }
-
- {
-
- //run broadcast Time of dawn
- // addMinutesToTimestamp = 60*5;
- addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn
-
- let params = getParams(PRIORITY_TYPES.node_broadcast);
-
- let sunCalcResult = calculateDuskDawn();
- let dawn_hours = sunCalcResult["dawn_hours"];
- let dawn_minutes = sunCalcResult["dawn_minutes"];
-
- params.address = 0xffffffff;//broadcast
- params.byte1 = dawn_hours;//h
- params.byte2 = dawn_minutes;//m
- params.byte3 = 0;//s
- params.byte4 = 0;
- params.recipient = 2; //2 broadcast
- params.register = 7;//Time of dawn - Reg 6
- params.rw = 1;//write
-
- //other values
- params.type = "cmd";
- params.timestamp = Date.now() + 60000;
- params.addMinutesToTimestamp = addMinutesToTimestamp;
- params.info = "Broadcast-dawnTime";
-
- tasks.push(params);
- }
-
- {
- //run broadcast //Actual time
- addMinutesToTimestamp = 5;
-
- let params = getParams(PRIORITY_TYPES.node_broadcast);
-
- var d = new Date();
- let hours = d.getHours();
- let minutes = d.getMinutes();
- let seconds = d.getSeconds();
-
- params.address = 0xffffffff;//broadcast
- params.byte1 = hours;//h
- params.byte2 = minutes;//m
- params.byte3 = seconds;//s
- params.byte4 = 0;
- params.recipient = 2; //2 broadcast
- params.register = 87;//Actual time
- params.rw = 1;//write
-
- //other values
- params.type = "cmd";
- params.timestamp = Date.now() + 60000;
- params.addMinutesToTimestamp = addMinutesToTimestamp;
- params.info = "run broadcast: Actual time";
-
- tasks.push(params);
- }
-
- }
-
- //process nodes & tasks
- //reportovanie pre platformu
- if(processNodes)
- {
- for (let k in nodesData) {
- let address = parseInt(k);
- let tbname = nodesData[k].tbname;
- let register = 0;
-
- //logger.debug("generated cmd - buildTasks for node:", address);
-
- //listOfCommands - READ
- for(let i = 0; i < listOfCommands.length; i++)
- {
- register = listOfCommands[i];
-
- let params = getParams(PRIORITY_TYPES.node_cmd);
-
- //core rpc values
- params.address = address;
- params.byte1 = 0;
- params.byte2 = 0;
- params.byte3 = 0;
- params.byte4 = 0;
- params.recipient = 1;
- params.register = register;
- params.rw = 0;
-
- let addMinutesToTimestamp = priorities[register];
-
- let timestampStart = PRIORITY_TYPES.node_cmd; //run imediatelly in function runTasks
- if(addMinutesToTimestamp > 1)
- {
- timestampStart = timestampStart + addMinutesToTimestamp * 60000;
- }
-
- //other values
- params.type = "cmd";
- params.tbname = tbname;
- params.timestamp = timestampStart;
- params.addMinutesToTimestamp = addMinutesToTimestamp;
- params.info = "generated cmd - buildTasks (node)";
-
- //monitor last node && last command
- /*
- if(register == listOfCommands[ listOfCommands.length - 1 ])
- {
- //if(k == 632) params.debug = true;
- if(k == 698) params.debug = true;
- }
- */
-
- tasks.push(params);
-
- }
- }
- }
-
-
- //niektore ulohy sa vygeneruju iba 1x pri starte!!!
- if(!init) return;
-
-
- //Priebežne (raz za cca 5 minút) je potrebné vyčítať z Master nodu verziu jeho FW.
- //Jedná sa o register 10. Rovnaká interpretácia ako pri FW verzii nodu.
- //Adresa mastera je 0. V prípade že kedykoľvek nastane situácia že Master Node neodpovedá (napríklad pri vyčítaní telemetrie z nodu nevráti žiadne dáta),
- //tak treba vyreportovať string "NOK".
- {
- let params = getParams(PRIORITY_TYPES.fw_detection);
- params.type = "cmd-master";
- params.register = 4;
- params.address = 0;
- params.timestamp = Date.now() + 60000;
- params.addMinutesToTimestamp = 5;
- params.tbname = FLOW.OMS_edgeName;
- params.info = "Master node FW verzia";
- //params.debug = true;
-
- //this will set FLOW.OMS_masterNodeIsResponding
-
- tasks.push(params);
- }
-
- //kazdu hodinu skontrolovat nastavenie profilov
- {
- let params = getParams(PRIORITY_TYPES.fw_detection);
- params.type = "process_profiles";
- params.timestamp = Date.now() + 60000;
- params.addMinutesToTimestamp = 60;//60 = every hour
- params.info = "detekcia nespracovaných profilov linie a nodov";
- //params.debug = true;
-
- tasks.push(params);
- }
-
- monitor.info("tasks created:", tasks.length);
- }
-
-
- /**
- * We process line profile, where "astro_clock": true
- * example profile:
- *
- "dawn_lux_sensor": true,
- "dusk_lux_sensor": true,
- "dawn_lux_sensor_value": 5,
- "dusk_lux_sensor_value": 5,
- "dawn_astro_clock_offset": 0,
- "dusk_astro_clock_offset": 10,
- "dawn_lux_sensor_time_window": 30,
- "dusk_lux_sensor_time_window": 30,
- "dawn_astro_clock_time_window": 60,
- "dusk_astro_clock_time_window": 60
-
- * if dawn: if currentTimestamp is in timewindow "dawnTime + and - dawn_lux_sensor_time_window" and lux value >= lux_sensor_value, we switch off the line.
- * if dusk: we do oposite
- *
- * dawn: usvit - lux je nad hranicou - vypnem
- * dusk: sumrak - lux je pod hranicou - zapnem
- */
- function turnOnOffLinesAccordingToLuxSensor(lux_sensor_value)
- {
-
- let now = new Date();
- let currentTimestamp = now.getTime();
- let keys = Object.keys(relaysData);
-
- for(let i = 0; i < keys.length; i++)
- {
-
- let line = keys[i]; //line is turned off by default
- let profilestr = relaysData[line].profile;
- const contactor = relaysData[line].contactor;
-
- try {
-
- let profile = JSON.parse(profilestr);
- if(Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined");
-
- if(profile.astro_clock == true)
- {
- let sunCalcResult = calculateDuskDawn(now, line);
-
- //usvit
- if(profile.dawn_lux_sensor == true)
- {
- let lux_sensor_time_window1 = sunCalcResult.dawn_time - (parseInt( profile.dawn_lux_sensor_time_window ) * 1000 * 60); // LUX_SENSOR_TIME_WINDOW x 1000 x 60 --> dostaneme odpocet/pripocitanie minut
- let lux_sensor_time_window2 = sunCalcResult.dawn_time + (parseInt( profile.dawn_lux_sensor_time_window ) * 1000 * 60);
-
- if(currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2)
- {
- if(lux_sensor_value > profile.dawn_lux_sensor_value)
- {
- if(contactor) turnOffLine(line, "Profile: dawn - turnOff line according to lux sensor");
- }
- }
- }
-
- //sumrak
- if(profile.dusk_lux_sensor == true)
- {
- let lux_sensor_time_window1 = sunCalcResult.dusk_time - (parseInt( profile.dusk_lux_sensor_time_window ) * 1000 * 60);
- let lux_sensor_time_window2 = sunCalcResult.dusk_time + (parseInt( profile.dusk_lux_sensor_time_window ) * 1000 * 60);
-
- if(currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2)
- {
- if(lux_sensor_value < profile.dusk_lux_sensor_value)
- {
- if(!contactor) turnOnLine(line, "Profile: dusk - turnOn line according to lux sensor");
- }
- }
- }
-
- }
-
- } catch (error) {
- if(profilestr !== "" ) monitor.info('Error parsing profile in turnOnOffLinesAccordingToLuxSensor', error);
- }
-
- }
-
- }
-
- /**
- * function updates status and time_of_last_communication of node in the dbNodes
- * it only updates if conditions are met
- * it only updates time_of_last_communication of node, if the last written time was more than 10 minutes ago (600000 miliseconds)
- * if newStatus of node is always receiving false, and it is already for more than FLOW.OMS_node_status_nok_time value, we update status to "NOK" in tb
- * function returns true, if status of node needs to be updated in TB (newStatus attribute is false in this case).
- */
- function updateNodeStatus(node, newStatus)
- {
- //MASTER
- if(node == 0) return;
-
- let nodeObj = nodesData[node];
- if(nodeObj == undefined) return;
-
- let nodeCurrentStatus = nodeObj.status;
- const now = Date.now();
-
- if(newStatus == false && nodeCurrentStatus == false) {
- if(node == 638 || node == 637) console.log("false, false, return", node, now)
- return true;
- }
-
- if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication > now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION){
-
- if(node == 638 || node == 637) console.log("true true, return", node, now);
- return;
- }
-
- if(newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication < now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION)
- {
- dbNodes.modify({ time_of_last_communication: now}).where("node", node).make(function(builder) {
- builder.callback(function(err, response) {
- if(!err) {
- nodeObj.time_of_last_communication = now;
-
- if(node == 638 || node == 637) console.log('zapisane do db => status true & true', node, now)
- }
- });
- });
- return;
- }
-
- if(newStatus == false && nodeCurrentStatus == true)
- {
- if(nodeObj.time_of_last_communication + FLOW.OMS_node_status_nok_time > now) {
- if(node == 638 || node == 637) console.log('false true, return', node, now);
- return;
- }
- else {
- dbNodes.modify({ status: newStatus}).where("node", node).make(function(builder) {
- builder.callback(function(err, response) {
- if(!err) {
- nodeObj.status = newStatus;
-
- if(node == 638 || node == 637) console.log('zapisane do db => status false & true', node, now)
- }
- });
- });
- return true;
- }
- }
-
- if(newStatus == true && nodeCurrentStatus == false)
- {
- dbNodes.modify({ status: newStatus, time_of_last_communication: now}).where("node", node).make(function(builder) {
- builder.callback(function(err, response) {
- if(!err) {
- nodeObj.status = newStatus;
- nodeObj.time_of_last_communication = now;
-
- if(node == 638 || node == 637) console.log('zapisane do db => status false & true', node, now)
- }
- });
- });
- return;
- }
- }
-
-
- async function runTasks(){
-
- clearInterval(interval);
-
- 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 Manager: calculated Time of dusk", FLOW.OMS_edgeName, "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("CMD Manager: calculated Time of dawn", FLOW.OMS_edgeName, "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
- tasks.sort(function (a, b) {
- if(a.timestamp <= currentTimestamp && b.timestamp <= currentTimestamp)
- {
- return a.priority - b.priority;
- }
- return a.timestamp - b.timestamp;
- });
-
- if(tasks.length == 0 )
- {
- instance.send(SEND_TO.debug, "no tasks created");
- interval = setInterval(runTasks, LONG_INTERVAL);
- return;
- }
-
- if(!rsPort.isOpen)
- {
- instance.send(SEND_TO.debug, "!rsPort.isOpen");
- //await rsPort.open();
- }
-
- let currentTask = tasks[0];
-
- if(currentTask.debug)
- {
- //logger.debug("--->task to process", currentTask);
- }
-
- if(currentTask.timestamp <= currentTimestamp)
- {
- let params = {...tasks[0]};
-
- //allow terminal commands
- if(FLOW.OMS_maintenance_mode && params.type !== "cmd-terminal")
- {
- interval = setInterval(runTasks, LONG_INTERVAL);
- return;
- }
-
- let type = params.type;
- let tbname = params.tbname;
- let nodeAddress = params.address;
-
- let line = null;
-
- //rpc related
- if(nodesData[nodeAddress] !== undefined) line = nodesData[nodeAddress].line;
- if(params.line !== undefined) line = params.line;
-
- let repeatTask = false;
- if(params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true;
-
- if(repeatTask)
- {
- if(type === "cmd" || type === "cmd-master")
- {
- //set next start time automatically
- tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000;
- }
- }
- else
- {
- tasks.shift();
- }
-
- //kontrola nespracovanych profilov nodov
- if(type == "process_profiles")
- {
- tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000;
-
- //vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov
- loadRelaysData();
-
- interval = setInterval(runTasks, SHORT_INTERVAL);
- return;
- }
-
-
- //relay
- if(type == "relay")
- {
-
- const timePointName = params.timePointName;
- const value = params.value;
-
- let date = new Date();
- date.setDate(date.getDate() + 1);//next day
-
- let sunCalcResult;
- sunCalcResult = calculateDuskDawn(date, params.line);
-
- if(timePointName == "dawn")
- {
- tasks[0].timestamp = sunCalcResult.dawn_time;
- }
- else if(timePointName == "dusk")
- {
- tasks[0].timestamp = sunCalcResult.dusk_time;
- }
- else if(timePointName == "luxOn")
- {
- tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000;
- }
- else if(timePointName == "luxOff")
- {
- tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000;
- }
- else if(timePointName == "profileTimepoint")
- {
- tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000;
- }
-
- let info = "aplikovany bod profilu";
- let message = "";
- if(value == 1)
- {
- turnOnLine(params.line, info);
- message = "on";
- }
- else if(value == 0)
- {
- turnOffLine(params.line, info);
- message = "off";
- }
-
- sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "switching_profile_point_applied_to_line", {line: params.line, value: message}, "", SEND_TO.tb, instance );
- interval = setInterval(runTasks, SHORT_INTERVAL);
- return;
- }
-
- //zhodeny hlavny istic
- let disconnected = false;
- //if(rotary_switch_state == "Off") disconnected = true;
-
- //state_of_breaker[line] - alebo istic linie
- if(state_of_breaker.hasOwnProperty(line))
- {
- //if(state_of_breaker[line] == "Off") disconnected = true;
- }
-
- //toto sa reportuje po prijati dat z dido_controlera
- if(disconnected)
- {
- let values = {"status": "OFFLINE"};
-
- logger.debug("disconnected", values);
- logger.debug("rotary_switch_state", rotary_switch_state);
- logger.debug("state_of_breaker", state_of_breaker[line]);
-
- let dataToTb = {
- [tbname]: [
- {
- "ts": Date.now(),
- "values": values
- }
- ]
- }
-
- //report only once!
- if(!disconnectedReport.hasOwnProperty(tbname)) disconnectedReport[tbname] = false;
-
- if(!disconnectedReport[tbname])
- {
- //instance.send(SEND_TO.tb, dataToTb);
- tbHandler.sendToTb(dataToTb, instance);
- }
-
- interval = setInterval(runTasks, SHORT_INTERVAL);
-
- return;
- }
-
- disconnectedReport[tbname] = false;
-
- const register = params.register;
-
- //high_priority
- if(!FLOW.OMS_masterNodeIsResponding)
- {
- //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version
- errorHandler.sendMessageToService("Master node is not responding");
-
- let stop = true;
-
- //fw version - register == 4
- if(type == "cmd-terminal" || register == 4) stop = false;
- if(stop)
- {
- interval = setInterval(runTasks, LONG_INTERVAL);
- return;
- }
- }
-
- let relayStatus = 1;
- if(relaysData[line] != undefined)
- {
- relayStatus = relaysData[line].contactor;
- }
-
- if(line == 0) relayStatus = 0;
- if(type == "cmd-terminal") relayStatus = 1;
-
- //check if rotary_switch_state == "Off"
-
- if(relayStatus == 0)
- {
- //console.log("------------------------------------relayStatus", relayStatus, line);
- let values = {"status": "OFFLINE"};
-
- let dataToTb = {
- [tbname]: [
- {
- "ts": Date.now(),
- "values": values
- }
- ]
- }
-
- //instance.send(SEND_TO.tb, dataToTb);
- tbHandler.sendToTb(dataToTb, instance);
-
- interval = setInterval(runTasks, SHORT_INTERVAL);
- return;
- }
-
- if(!rsPort.isOpen)
- {
- interval = setInterval(runTasks, LONG_INTERVAL);
- return;
- }
-
- //RE-CALCULATE VALUES
- //set actual time for broadcast
- if(register == 87 && params.recipient === 2)
- {
- var d = new Date();
- let hours = d.getHours();
- let minutes = d.getMinutes();
- let seconds = d.getSeconds();
-
- params.byte1 = hours;//h
- params.byte2 = minutes;//m
- params.byte3 = seconds;//s
- params.byte4 = 0;
- }
-
- //SET DUSK/DAWN FOR BROADCAST
- //Time of dusk
- if(register == 6 && params.recipient === 2)
- {
-
- if(type != "cmd-terminal")
- {
- let sunCalcResult = calculateDuskDawn();
- let dusk_hours = sunCalcResult["dusk_hours"];
- let dusk_minutes = sunCalcResult["dusk_minutes"];
-
- params.byte1 = dusk_hours;//h
- params.byte2 = dusk_minutes;//m
- params.byte3 = 0;//s
- params.byte4 = 0;
-
- //TODO astrohodiny
- let dusk = "Time of dusk: " + sunCalcResult["dusk"];
- }
- }
-
- //Time of dawn
- if(register == 7 && params.recipient === 2)
- {
- if(type != "cmd-terminal")
- {
- let sunCalcResult = calculateDuskDawn();
- let dawn_hours = sunCalcResult["dawn_hours"];
- let dawn_minutes = sunCalcResult["dawn_minutes"];
-
- params.byte1 = dawn_hours;//h
- params.byte2 = dawn_minutes;//m
- params.byte3 = 0;//s
- params.byte4 = 0;
-
- //TODO astrohodiny
- let dawn = "Time of dawn: " + sunCalcResult["dawn"];
- }
-
- }
- //-----------------------
-
- instance.send(SEND_TO.debug, "address: " + nodeAddress + " register:" + register + "type: " + type);
-
- var startTime, endTime;
- startTime = new Date();
-
- let saveToTb = true;
- if(!tbname) saveToTb = false;
- let itIsNodeCommand = listOfCommands.includes(register); //reading data from node (voltage, current, dimming, status)
-
- let resp = com_generic(nodeAddress, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4);
- let readBytes = 11;
- let timeout = 4000;
-
- // await keyword is important, otherwise incorrect data is returned!
- await writeData(rsPort, resp, readBytes, timeout).then(function (data) {
-
- endTime = new Date();
- var timeDiff = endTime - startTime;
-
- //--1-4 adresa, 5 status ak je status 0 - ok, nasleduju 4 byty data
- //let bytes = data.slice(0);
- let bytes = data;
- let dataBytes = data.slice(5,9);
-
- let result = detectIfResponseIsValid(bytes);
-
- //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK
- let message = result.message; // OK, NOK
- let message_type = result.type;
- let error = result.error;
-
- if(params.debug != "generated cmd")
- {
- //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params);
- }
-
- // if(params.hasOwnProperty("debug"))
- // {
- // if(params.debug)
- // {
- // console.log("detected response:", result);
-
- // logger.debug("writeData: done " + message_typetype + " duration: " + timeDiff + " type: " + params.debug, params, result);
- // }
- // }
-
- //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug);
- //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result);
-
- let values = {};
-
- //CMD FINISHED
- if(message == "OK")
- {
-
- updateNodeStatus(nodeAddress, true);
-
- //write
- if(type == "set_node_profile")
- {
- let result = cmdCounterResolve(nodeAddress);
- if(result == 0)
- {
- dbNodes.modify({ processed: true }).where("node", nodeAddress).make(function(builder) {
- builder.callback(function(err, response) {
-
- sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "dimming_profile_was_successfully_received_by_node", {node: nodeAddress}, "", SEND_TO.tb, instance );
-
- logger.debug( "--> profil úspešne odoslaný na node č. " + nodeAddress);
- nodesData[nodeAddress].processed = true;
- });
- });
- }
- }
-
- //parse read response
- if(params.rw == 0)
- {
- values = processResponse(register, dataBytes); //read
- }
-
- if(itIsNodeCommand)
- {
- values.comm_status = "OK";
- values.status = "OK";
- }
-
- //master node
- if(nodeAddress == 0)
- {
- sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status" );
- FLOW.OMS_masterNodeIsResponding = true;
- if(register == 4) values["edge_fw_version"] = FLOW.OMS_edge_fw_version;
- }
-
- //odoslanie príkazu z terminálu - dáta
- if(type == "cmd-terminal")
- {
- sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "command_was_sent_from_terminal_interface", {}, params, SEND_TO.tb, instance );
- }
-
- if(params.debug)
- {
- //logger.debug("saveToTb", saveToTb, tbname, values);
- }
-
- if(saveToTb)
- {
- let dataToTb = {
- [tbname]: [
- {
- "ts": Date.now(),
- "values": values
- }
- ]
- }
-
- //instance.send(SEND_TO.tb, dataToTb);
- tbHandler.sendToTb(dataToTb, instance);
- }
- else
- {
- if(type == "cmd-terminal")
- {
- terminalCommandResponse(params, "SUCCESS", data);
- }
- }
-
- }
- else
- {
-
- terminalCommandResponse(params, "ERROR", data)
- handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb);
-
- if(params.hasOwnProperty("debug"))
- {
- if(params.debug)
- {
- //logger.debug("writeData err: ", error, result, params);
- logger.debug("writeData err: ", tbname, nodeAddress, register, values);
- }
- }
-
- //logger.debug(error, result, params);
- }
- }).catch(function(reason) {
-
- console.log("writeData catch exception", reason);
- instance.send(SEND_TO.debug, reason);
-
- terminalCommandResponse(params, "FAILURE", null, reason);
- handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb);
-
- if(params.hasOwnProperty("debug"))
- {
- if(params.debug)
- {
- logger.debug("-->WRITE FAILED: " + reason, params.debug, params);
- }
- }
-
- });
-
- }
- else
- {
- // if(currentTask.debug)
- // {
- // //currentTask.timestamp <= currentTimestamp
- // logger.debug("currentTask is not processed - task is in the future", currentTask);
- // }
-
- interval = setInterval(runTasks, LONG_INTERVAL);
- return;
- }
-
- //console.log("----->runTasks - setInterval", new Date());
- interval = setInterval(runTasks, SHORT_INTERVAL);
- }
-
-
- function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb){
-
- let node = params.address;
- let register = params.register;
- let type = params.type;
- let tbName = params.tbname;
- if(!tbName) return;
-
- let values = {};
-
- // console.log(message);
- let updateStatus = updateNodeStatus(node, false);
-
- //master node
- if(node == 0)
- {
- sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status");
- logger.debug("master_node_is_not_responding", params);
- FLOW.OMS_masterNodeIsResponding = false;
-
- if(register == 4) values["master_node_version"] = "NOK";
- }
-
- if(type == "set_node_profile")
- {
- delete cmdCounter[node];
- logger.debug( "profil nebol úspešne odoslaný na node č. ", params);
- sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", {node: node}, "", SEND_TO.tb, instance );
- }
-
- if(itIsNodeCommand)
- {
- values.comm_status = "NOK";
- }
-
- if(updateStatus)
- {
- values.status = "NOK";
- }
-
- // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values);
- if(saveToTb && Object.keys(values).length > 0)
- {
-
- let dataToTb = {
- [tbName]: [
- {
- "ts": Date.now(),
- "values": values
- }
- ]
- }
-
- tbHandler.sendToTb(dataToTb, instance);
- }
-
- }
-
-
- /**
- * function handles requests from terminal
- * responseType can be "SUCCESS", "ERROR" or "FAILURE", depending on rsPort data.
- * FAILURE means, that we got into catch block of writeData function.
- */
- function terminalCommandResponse(params, responseType, data=null, reason="") { //success, error, failure
-
- if(params.refFlowdataKey == undefined)
- {
- //console.log("params.refFlowdataKey is undefined", params);
- return;
- }
- else
- {
- console.log("params.refFlowdataKey: ", params);
- }
-
- let message = null;
- let type = null;
-
- switch (responseType) {
- case "SUCCESS":
- message = "cmd-terminal SUCCESS";
- type = "SUCCESS";
- break;
- case "ERROR":
- message = "cmd-terminal FAILED";
- type = "ERROR";
- break;
- case "FAILURE":
- message = "ERROR WRITE FAILED: " + reason;
- type = "ERROR";
- break;
- default:
- type = undefined;
- }
-
- logger.debug(message);
- logger.debug(params);
-
- //make http response
- let responseObj = {}
- responseObj["type"] = type;
-
- if(responseType == "FAILURE") responseObj["message"] = "ERROR WRITE FAILED: " + reason;
- else responseObj["bytes"] = data;
-
- let refFlowdata = refFlowdataObj[params.refFlowdataKey];
- if(refFlowdata)
- {
- refFlowdata.data = responseObj;
- instance.send(SEND_TO.http_response, refFlowdata);
- }
- }
-
-
- /**
- * function handles tasks, that are not needed to run through masterNode. To make them run smooth without waiting for other tasks to be completed, we moved them in separate function
- */
- function reportEdgeDateTimeAndNumberOfLuminaires(){
-
- if(!FLOW.OMS_edgeName) return;
-
- //Number of ok and nok nodes on platform does not equals to total number of nodes.
- //possible error is, that nodesData object is changing all the time. To make a proper calculation of ok,nok luminaires, we make a copy of it:
- let nodesData_clone = JSON.parse(JSON.stringify(nodesData));
-
- const ts = Date.now();
- const keys = Object.keys(nodesData_clone);
-
- const number_of_luminaires = keys.length;
- let number_of_ok_luminaires = 0;
- let number_of_nok_luminaires = 0;
-
- for(let i = 0; i < keys.length; i++)
- {
- let key = keys[i];
- let nodeObj = nodesData_clone[key];
- if(nodeObj.tbname == undefined) continue;
-
- if(nodeObj.status) number_of_ok_luminaires++;
- else number_of_nok_luminaires++;
- }
-
- const values = {
- "number_of_luminaires": number_of_luminaires,
- "number_of_ok_luminaires": number_of_ok_luminaires,
- "number_of_nok_luminaires": number_of_nok_luminaires,
- "edge_date_time": ts
- };
-
- let dataToTb = {
- [FLOW.OMS_edgeName]: [
- {
- "ts": ts,
- "values": values
- }
- ]
- }
-
- tbHandler.sendToTb(dataToTb, instance);
- //instance.send(SEND_TO.tb, dataToTb);
- }
-
- //to ensure, edgeDateTime will be send to tb at full minute
- customTasksInterval = setInterval(function() {
- if(new Date().getSeconds() === 0) reportEdgeDateTimeAndNumberOfLuminaires();
- }, 1000);
-
-
- //! rsPort LM = "/dev/ttymxc4", rsPort UNIPI = "/dev/ttyUSB0"
- // const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM
- // const rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false }); // UNIPI
-
- if(FLOW.OMS_serial_port == "" || FLOW.OMS_serial_port == undefined || FLOW.OMS_serial_port.length === 1) FLOW.OMS_serial_port = "ttymxc4";
- const rsPort = new SerialPort(`/dev/${FLOW.OMS_serial_port}`, { autoOpen: false });
- //(node:16372) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 13 data listeners added to [SerialPort]. Use emitter.setMaxListeners() to increase limit
- //rsPort.setMaxListeners(0);
-
- rsPort.on('open', async function() {
-
- logger.debug("CMD manager - rsPort opened sucess");
-
- //loadRelaysData();
-
- await runSyncExec(`stty -F /dev/${FLOW.OMS_serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function (status) {
- instance.send(SEND_TO.debug, "RPC runSyncExec - Promise Resolved:" + status);
-
- logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status);
-
- //APP START
- let dataToInfoSender = {id: FLOW.OMS_projects_id, name: FLOW.OMS_rvo_name};
- dataToInfoSender.fw_version = FLOW.OMS_edge_fw_version;
- dataToInfoSender.startdate = new Date().toISOString().slice(0, 19).replace('T', ' ');
- dataToInfoSender.__force__ = true;
-
- instance.send(SEND_TO.infoSender, dataToInfoSender);
-
- logger.debug(0, "---------------------------->START message send to service", dataToInfoSender);
-
- }).catch(function (reason) {
- instance.send(SEND_TO.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason);
- });
- });
-
- rsPort.on('error', function(err) {
-
- //TODO report to service!!!
- //errLogger.error(exports.title, "unable to open port", FLOW.OMS_serial_port, err.message);
- errorHandler.sendMessageToService([exports.title, "unable to open port", FLOW.OMS_serial_port, err.message], 0);
-
- instance.send(SEND_TO.debug, err.message);
- });
-
- rsPort.on("close", () => {
- rsPort.close();
- });
-
- rsPort.open();
-
- instance.on("close", () => {
- clearInterval(interval);
- clearInterval(customTasksInterval);
- rsPort.close();
- });
-
-
- instance.on("data", async function(flowdata) {
-
- //instance.send(SEND_TO.debug, "on Data");
- //instance.send(SEND_TO.debug, flowdata);
-
- //logger.debug(flowdata.data);
-
- //just testing functions
- if(flowdata.data == "open")
- {
- if(!rsPort.isOpen) rsPort.open();
- return;
- }
- else if(flowdata.data == "close")
- {
- rsPort.close();
- return;
- }
- else if(flowdata.data == "clean")
- {
- tasks = [];
- return;
- }
- else if(flowdata.data == "buildtasks")
- {
- //build & run
- return;
- }
- else if(flowdata.data == "run")
- {
- //durations = [];
-
- if(tasks.length == 0)
- {
-
- buildTasks();
-
- if(rsPort.isOpen)
- {
- interval = setInterval(runTasks, 100);
- }
- else
- {
- instance.send(SEND_TO.debug, "port is not opened!!!");
- }
- }
- }
- else
- {
- //terminal data - object
- //logger.debug("flowdata", flowdata.data);
-
- if(typeof flowdata.data === 'object')
- {
- //logger.debug("dido", flowdata.data);
- if(flowdata.data.hasOwnProperty("sender"))
- {
- //data from dido_controller
- if(flowdata.data.sender == "dido_controller")
- {
-
- if(flowdata.data.hasOwnProperty("cmd"))
- {
- let cmd = flowdata.data.cmd;
-
- if(cmd == "buildTasks")
- {
- clearInterval(interval);
-
- logger.debug("-->CMD MANAGER - BUILD TASKS");
- buildTasks();
-
- //logger.debug("tasks:");
- //logger.debug(tasks);
-
- logger.debug("-->CMD MANAGER - RUN TASKS");
- interval = setInterval(runTasks, LONG_INTERVAL);
- }
- else if(cmd == "reload_relays")
- {
- loadRelaysData(flowdata.data.line);
-
- if(flowdata.data.dataChanged)
- {
- if(!flowdata.data.value)
- {
- reportOfflineNodeStatus(flowdata.data.line);
- }
- else
- {
- reportOnlineNodeStatus(flowdata.data.line);
- }
- }
-
- }
- else if(cmd == "rotary_switch_state")
- {
- //state was changed
- if(rotary_switch_state != flowdata.data.value)
- {
- if(rotary_switch_state == "Off")
- {
- //vyreportovat vsetky svietdla
- reportOfflineNodeStatus();
- }
- else reportOnlineNodeStatus();
-
- }
-
- rotary_switch_state = flowdata.data.value;
- }
- else if(cmd == "lux_sensor")
- {
- lux_sensor = parseInt(flowdata.data.value);
-
- // POSSIBLE SOURCE OF PROBLEMS, IF USER SETS LUX TRESHOLD LEVEL GREATER THAN 100 - WE SHOULD BE CHECKING "DUSK/DAWN_LUX_SENSOR_VALUE" IN PROFILE MAYBE ??
- if(lux_sensor < 100)
- {
-
- // we send lux_sensor value to all nodes:
- let params = getParams(PRIORITY_TYPES.node_broadcast);
-
- params.recipient = 2;//2 broadcast, address = 0
- params.address = 0xffffffff;//Broadcast
-
- let ba = longToByteArray(lux_sensor);
-
- params.byte3 = ba[1];//msb
- params.byte4 = ba[0];
- params.timestamp = PRIORITY_TYPES.node_broadcast;
- params.info = "run broadcast: Actual Lux level from cabinet";
- params.register = 95;//Actual Lux level from cabinet
- params.rw = 1;//write
-
- tasks.push(params);
-
- //process profiles
- turnOnOffLinesAccordingToLuxSensor(lux_sensor);
- }
- }
- else if(cmd == "state_of_breaker")
- {
- //istic linie
- let value = flowdata.data.value;
- let line = parseInt(flowdata.data.line);
-
- let dataChanged = false;
- if(state_of_breaker[line] != value) dataChanged = true;
-
- state_of_breaker[line] = value;
-
- let status = "OK";
- if(value == "Off") status = "NOK";
-
- if(dataChanged) {
-
- if(relaysData.hasOwnProperty(line))
- {
- let tbname = relaysData[line].tbname;
-
- if(value == "Off") sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_off_line", {line: line}, "", SEND_TO.tb, instance, "circuit_breaker");
- else sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_on_line", {line: line}, "", SEND_TO.tb, instance, "circuit_breaker");
-
- //report status liniu
- let values = {
- "status": status
- };
-
- let dataToTb = {
- [tbname]: [
- {
- "ts": Date.now(),
- "values": values
- }
- ]
- }
-
- //instance.send(SEND_TO.tb, dataToTb);
- tbHandler.sendToTb(dataToTb, instance);
-
- //current value
- if(value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii
- else reportOnlineNodeStatus(line);
- }
-
- }
- }
- else{
- logger.debug("undefined cmd", cmd);
- }
- }
- }
-
- return;
- }
-
- //data from worksys
- if(flowdata.data.hasOwnProperty("topic"))
- {
-
- let data = flowdata.data.content.data;
-
- let command = data.params.command;
- let method = data.method;
- let profile = data.params.payload;
- if(profile == undefined) profile = "";
- let entity = data.params.entities[0];
- let entity_type = entity.entity_type;
- let tbname = entity.tb_name;
-
- instance.send(SEND_TO.debug, flowdata.data);
- logger.debug("--->worksys", flowdata.data, data.params, entity, entity_type, command, method);
- logger.debug("----------------------------");
-
- if(entity_type == "street_luminaire"|| entity_type === "street_luminaire_v4_1" || entity_type === "street_luminaire_v4_1cez" || entity_type === "street_luminaire_v4")
- {
- if(method == "set_command")
- {
-
- //let command = data.params.command;
- let value = data.params.payload.value;
-
- if(command == "dimming")
- {
-
- let nodeWasFound = false;
- let keys = Object.keys(nodesData);
-
- //logger.debug("-----", keys);
-
- for(let i = 0; i < keys.length; i++)
- {
- let node = keys[i];
- //logger.debug( node, nodesData[node], tbname);
-
- if(tbname == nodesData[node].tbname.trim())
- {
- let params = getParams(PRIORITY_TYPES.high_priority);
-
- value = parseInt(value);
- if(value > 0) value = value + 128;
-
- //set dimming - LUM1_13 - 647 je node linie 1 kt. dobre vidime
- params.type = "cmd";
- params.tbname = tbname;
- params.address = node;
- params.register = 1;//dimming
- params.recipient = 1;//slave
- params.byte4 = value;
- params.rw = 1;//write
- params.timestamp = PRIORITY_TYPES.high_priority;
- params.info = 'set dimming from platform';
- //params.debug = true;
-
- //ak linia je
-
- //debug(params);
- logger.debug("dimming", params);
-
- tasks.push(params);
-
- setTimeout(function(){
-
- //spustime o 4 sekundy neskor, s prioritou PRIORITY_TYPES.high_priority
- //a pridame aj vyreportovanie dimmingu
- {
- let params = getParams(PRIORITY_TYPES.high_priority);
-
- params.type = "cmd";
- params.tbname = tbname;
- params.address = node;
- params.register = 1;//dimming
- params.recipient = 1;//slave
- params.rw = 0;//read
- params.timestamp = PRIORITY_TYPES.high_priority;
- params.info = 'read dimming (after set dimming from platform)';
- params.debug = true;
-
- tasks.push(params);
- }
-
- //pridame aj vyreportovanie - vykon
- {
- let params = getParams(PRIORITY_TYPES.high_priority);
-
- params.type = "cmd";
- params.tbname = tbname;
- params.address = node;
- params.register = 76;
- params.recipient = 1;//slave
- params.rw = 0;//read
- params.timestamp = PRIORITY_TYPES.high_priority;
- params.info = 'read Input Power (after set dimming from platform)';
- params.debug = true;
-
- tasks.push(params);
- }
-
- //pridame aj vyreportovanie - prud svietidla
- {
- let params = getParams(PRIORITY_TYPES.high_priority);
-
- params.type = "cmd";
- params.tbname = tbname;
- params.address = node;
- params.register = 75;
- params.recipient = 1;//slave
- params.rw = 0;//read
- params.timestamp = PRIORITY_TYPES.high_priority;
- params.info = 'read Input Current (after set dimming from platform)';
- params.debug = true;
-
- tasks.push(params);
- }
-
- //pridame aj vyreportovanie - power faktor - ucinnik
- {
- let params = getParams(PRIORITY_TYPES.high_priority);
-
- params.type = "cmd";
- params.tbname = tbname;
- params.address = node;
- params.register = 77;
- params.recipient = 1;//slave
- params.rw = 0;//read
- params.timestamp = PRIORITY_TYPES.high_priority;
- params.info = 'read power factor - Cos phi (after set dimming from platform)';
- params.debug = true;
-
- tasks.push(params);
- }
-
- },4000);
-
-
- nodeWasFound = true;
-
- break;
- }
- }
-
- if(!nodeWasFound)
- {
- logger.debug("set dimming from platform", "unable to find tbname", tbname);
- }
- }
- else
- {
- instance.send(SEND_TO.debug, "undefined command " + command);
- logger.debug("undefined command", command);
- }
-
- return;
- }
- else if(method == "set_profile")
- {
- //nastav profil nodu
- logger.debug("-->set_profile for node", data.params);
- logger.debug("------profile data", profile);
- //instance.send(SEND_TO.debug, "set_profile" + command);
-
- let keys = Object.keys(nodesData);
- for(let i = 0; i < keys.length; i++)
- {
- let node = keys[i];
- if(tbname == nodesData[node].tbname.trim())
- {
-
- if(profile != "") profile = JSON.stringify(profile);
- dbNodes.modify({ processed: false, profile: profile }).where("node", node).make(function(builder) {
-
- builder.callback(function(err, response) {
-
- logger.debug("worksys - update node profile done", profile);
- if(profile === "") logger.debug("worksys - update node profile done - profile is empty");
-
- //profil úspešne prijatý pre node č. xx
- sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", {node: node}, profile, SEND_TO.tb, instance );
-
- nodesData[node].processed = false;
- nodesData[node].profile = profile;
-
- let line = nodesData[node].line;
- processNodeProfile(node);
-
- });
- });
- }
- }
- }
- else
- {
-
- instance.send(SEND_TO.debug, "unknown method " + method);
- logger.debug("unknown method", method);
-
- return;
- }
- }
-
- //nastav profil linie z platformy
- else if(entity_type == "edb_line" || entity_type == "edb" || entity_type == "edb_line_ver4" || entity_type == "edb_ver4_se")
- {
- //profil linie
- //relays.table line:number|tbname:string|contactor:number|profile:string
- //najdeme line relaysData
-
- if(method == "set_profile")
- {
-
- logger.debug("-->set_profile for line", data.params);
- logger.debug("profile data:", profile);
-
- let keys = Object.keys(relaysData);
- for(let i = 0; i < keys.length; i++)
- {
- let line = keys[i];
- if(tbname == relaysData[line].tbname)
- {
- //zmazeme tasky
- removeTask({type: "relay", line: line});
-
- if(profile != "") profile = JSON.stringify(profile);
- dbRelays.modify({ profile: profile }).where("line", line).make(function(builder) {
-
- builder.callback(function(err, response) {
-
- //update profile
- logger.debug("worksys - update relay profile done:", profile);
- instance.send(SEND_TO.debug, "worksys - update relay profile done");
-
- loadRelaysData(line).then(function (data) {
- logger.debug("loadRelaysData DONE for line", line);
- buildTasks({processLineProfiles: true, line: line});
- });
-
- sendNotification("CMD manager - set profile from worksys", tbname, "switching_profile_was_processed_for_line", {line: line}, profile, SEND_TO.tb, instance );
-
- });
- });
- break;
- }
- }
- }
- else if(method == "set_command")
- {
- let value = data.params.payload.value;
-
- if(command === "switch")
- {
-
- // if we receive rpc from platform, to switch maintenance mode, we set OMS_maintenance_mode flow variable to value;
- if(entity_type === "edb" || entity_type === "edb_ver4_se") FLOW.variables.OMS_maintenance_mode = value;
-
- let responseRelays = await promisifyBuilder(dbRelays.find().where("tbname", tbname));
-
- let line = 0;
- if(responseRelays.length == 1) line = responseRelays[0].line;
-
- if(value == false) turnOffLine(line, "command received form platform");
- else turnOnLine(line, "command received form platform");
- }
- }
- else
- {
- instance.send(SEND_TO.debug, "undefined method " + method);
- logger.debug("undefined method", method);
- }
-
- return;
- }
- else
- {
- instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type);
- logger.debug("UNKNOW entity_type", entity_type);
- }
- return;
- }
-
- //terminal
- if(!rsPort.isOpen) await rsPort.open();
-
- let params = flowdata.data.body;
- if(params == undefined)
- {
- //logger.debug("CMD manager flowdata.data.body is undefined");
- return;
- }
-
- params.priority = PRIORITY_TYPES.terminal;
- params.type = "cmd-terminal";
- params.tbname = "";
- params.timestamp = PRIORITY_TYPES.terminal;
- params.addMinutesToTimestamp = 0;// do not repeat task!!!
- params.debug = true;
-
- let timestamp = Date.now();
- params.refFlowdataKey = timestamp;
- //params.refFlowdata = flowdata;
- //refFlowdata = flowdata;
-
- //console.log("flowdata", flowdata);
-
- cleanUpRefFlowdataObj();
-
- refFlowdataObj[ timestamp ] = flowdata;
-
- //fix
- //params.address = params.adress;
- logger.debug("received from terminal", params);
- logger.debug("date/time:", new Date());
- logger.debug("tasks length:", tasks.length);
-
- //tasks = [];
-
- //add to tasks
- tasks.push(params);
-
- }
- }
- })
-
-} // end of instance.export
-
-
-/**
- * setCorrectTime function runs once per hour
- * If it is 3 o'clock, it sets actual time, which is got from services
- * https://service-prod01.worksys.io/gettime
- * If also detects Read Only Filesystem once a day
- */
-function setCorrectPlcTimeOnceADay()
-{
-
- const currentTime = new Date();
- if(currentTime.getHours() != 3) return;
-
- RESTBuilder.make(function(builder) {
-
- if(!builder) return;
-
- builder.method('GET');
- builder.url('http://192.168.252.2:8004/gettime?projects_id=1');
-
- builder.callback(function(err, response, output) {
-
- if (err) {
- console.log(err);
- return;
- }
-
- const res = output.response;
-
- try {
-
- const obj = JSON.parse(res);
- let d = new Date(obj.date);
-
- const now = new Date();
-
- let diffInMinutes = now.getTimezoneOffset();
- console.log("---->TimezoneOffset", diffInMinutes);
-
- if(d instanceof Date)
- {
-
- // monitor.info("----------->setCorrectPlcTimeOnceADay() current js date:", d, d.getHours());
-
- let year = d.getFullYear();
- let month = addZeroBefore(d.getMonth() + 1);
- let day = addZeroBefore(d.getDate());
-
- let hours = addZeroBefore(d.getHours());
- let minutes = addZeroBefore(d.getMinutes() );
- let seconds = addZeroBefore(d.getSeconds());
-
- let dateStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
-
- exec(`sudo timedatectl set-time "${dateStr}"`, (err, stdout, stderr) => {
- if (err || stderr) {
- console.error(err);
- console.log(stderr);
- console.log(dateStr);
-
- monitor.info("failed timedatectl set-time", err, stderr);
- }
- else
- {
- monitor.info("setCorrectPlcTimeOnceADay() --> Nastaveny cas na: ", dateStr);
- }
-
- });
- }
-
- } catch (error) {
- logger.debug("setCorrectPlcTimeOnceADay - function error", error, res);
- monitor.info("setCorrectPlcTimeOnceADay - function error", error, res);
- }
-
- // we detect readOnlyFileSystem once an hour as well
- detectReadOnlyFilesystem();
-
- });
- });
-
-}
-
-
-function detectReadOnlyFilesystem()
-{
- exec(`sudo egrep " ro,|,ro " /proc/mounts`, (err, stdout, stderr) => {
- if (err || stderr) {
- console.error(err);
- console.log(stderr);
-
- } else {
- //console.log("Read-only", stdout);
-
- let lines = stdout + "";
- lines = lines.split("\n");
-
- let readOnlyDetected = "";
- for(let i = 0; i < lines.length; i++)
- {
- if(lines[i].startsWith("/dev/mmcblk0p2"))
- {
- readOnlyDetected = lines[i];
- }
- }
-
- if(readOnlyDetected !== "")
- {
- errorHandler.sendMessageToService("Detected: Read-only file system: " + readOnlyDetected);
- monitor.info("Read only filesystem detected");
- }
-
- }
- });
-}
-
-let setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour
-setCorrectPlcTimeOnceADay();
-
-
-
-
-
-
-
-
-
-///helper functions
-
-function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0)
-{
-
- if(date === undefined) date = new Date();
- //if(duskOffset === undefined) duskOffset = 0;
- //if(dawnOffset === undefined) dawnOffset = 0;
-
- //let line = keys[i];
- let profilestr = "";
- if(relaysData[line] != undefined) profilestr = relaysData[line].profile;
-
- let result = {};
-
- var times = SunCalc.getTimes(date, latitude, longitude);
- let dawn = new Date(times.sunrise);//usvit
- let dusk = new Date(times.sunset);//sumrak
-
-
- //http://suncalc.net/#/48.5598,18.169,11/2021.04.07/11:06
- //https://mapa.zoznam.sk/zisti-gps-suradnice-m6
-
-
- let dusk_astro_clock_offset = duskOffset;//minutes
- let dawn_astro_clock_offset = dawnOffset;//minutes
-
- try {
-
- let profile = JSON.parse(profilestr);
- if(Object.keys(profile).length === 0) throw ("profile is not defined");
-
- //Jednoduchý režim
- if(profile.astro_clock == false && profile.dusk_lux_sensor == false && profile.dawn_lux_sensor == false)
- {
-
- }
-
- //Režim astrohodín
- if(profile.astro_clock == true)
- {
- //if(profile.dusk_lux_sensor == false)
- {
- if(profile.hasOwnProperty("dusk_astro_clock_offset")) dusk_astro_clock_offset = parseInt( profile.dusk_astro_clock_offset );
- }
-
- //if(profile.dawn_lux_sensor == false)
- {
- if(profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt( profile.dawn_astro_clock_offset );
- }
-
- }
-
- //dusk - súmrak
- //down, sunrise - svitanie
-
- } catch (error) {
- if(profilestr != "")
- {
- logger.debug(profilestr);
- logger.debug(error);
- }
- }
-
- result.dusk_no_offset = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes());
- result.dawn_no_offset = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes());
-
- dusk = new Date(dusk.getTime() + gmtOffset + dusk_astro_clock_offset*60000);
- dawn = new Date(dawn.getTime() + gmtOffset + dawn_astro_clock_offset*60000);
-
- result.dusk = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes());
- result.dusk_hours = dusk.getHours();
- result.dusk_minutes = dusk.getMinutes();
-
- result.dawn = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes());
- result.dawn_hours = dawn.getHours();
- result.dawn_minutes = dawn.getMinutes();
-
- result.dusk_time = dusk.getTime();
- result.dawn_time = dawn.getTime();
-
- result.dusk_astro_clock_offset = dusk_astro_clock_offset;
- result.dawn_astro_clock_offset = dawn_astro_clock_offset;
-
- return result;
-}
-
-
-function processResponse(register, bytes)
-{
-
- let values = {};
-
- let byte3 = bytes[0];
- let byte2 = bytes[1];
- let byte1 = bytes[2];
- let byte0 = bytes[3];
-
- //status
- if(register == 0)
- {
- let statecode = bytesToInt(bytes);
- values = {"statecode": statecode};
- return values;
- }
-
- //Dimming, CCT
- if(register == 1)
- {
- let brightness = 0;
- let dimming = byte0;
- if(dimming > 128) {
- //dimming = -128;
- brightness = dimming - 128;
- }
-
- //cct
- //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1
- let cct;
- if(byte3 == 1) cct = byte2*256 + byte1;
- else cct = bytesToInt(bytes.slice(0, 3));
-
- //cct podla auditu
-
- values["dimming"] = brightness;
- return values;
- }
-
- //
- if(register == 4)
- {
- values["master_node_version"] = bytes[1] + "." + bytes[2];
- //logger.debug("FW Version", register, bytes);
- }
-
- //Napätie
- if(register == 74)
- {
- let voltage = (bytesToInt(bytes) * 0.1).toFixed(1);
- values["voltage"] = Number(voltage);
- }
-
- //Prúd
- if(register == 75)
- {
- let current = bytesToInt(bytes);
- values["current"] = current;
- }
-
- //výkon
- if(register == 76)
- {
- let power = (bytesToInt(bytes) * 0.1).toFixed(2);
- values["power"] = Number(power);
- }
-
- //účinník
- if(register == 77)
- {
- let power_factor = Math.cos(bytesToInt(bytes) * 0.1).toFixed(2);
- values["power_factor"] = Number(power_factor);
- }
-
- //frekvencia
- if(register == 78)
- {
- let frequency = (bytesToInt(bytes) * 0.1).toFixed(2);
- values["frequency"] = Number(frequency);
- }
-
- //energia
- if(register == 79)
- {
- let energy = bytesToInt(bytes);
-
- //Energiu treba reportovať v kWh. Teda číslo, ktoré príde treba podeliť 1000. Toto som ti možno zle napísal.
-
- values["energy"] = energy / 1000;
- }
-
- //doba života
- if(register == 80)
- {
- let lifetime = ( bytesToInt(bytes) / 60).toFixed(2);
- values["lifetime"] = Number(lifetime);
- }
-
- //nastavenie profilu
- if(register == 8)
- {
- let time_schedule_settings = bytesToInt(bytes);
- values["time_schedule_settings"] = time_schedule_settings;
- }
-
- //skupinová adresa 1
- if(register == 3)
- {
- let gr_add_1 = bytesToInt(byte0);
- values["gr_add_1"] = gr_add_1;
-
- let gr_add_2 = bytesToInt(byte1);
- values["gr_add_2"] = gr_add_2;
-
- let gr_add_3 = bytesToInt(byte2);
- values["gr_add_3"] = gr_add_3;
-
- let gr_add_4 = bytesToInt(byte3);
- values["gr_add_4"] = gr_add_4;
- }
-
- //naklon
- if(register == 84)
- {
- let temp;
- if(byte3 >= 128)
- {
- temp = (byte3 - 128) * (-1);
- }
- else
- {
- temp = byte3;
- }
-
- let inclination_x;
- if(byte2 >= 128)
- {
- inclination_x = (byte2 - 128) * (-1);
- }
- else
- {
- inclination_x = byte2;
- }
-
- let inclination_y;
- if(byte1 >= 128)
- {
- inclination_y = (byte1 - 128) * (-1);
- }
- else
- {
- inclination_y = byte1;
- }
-
- let inclination_z;
- if(byte0 >= 128)
- {
- inclination_z = (byte0 - 128) * (-1);
- }
- else
- {
- inclination_z = byte0;
- }
-
- values["temperature"] = temp;
-
- //náklon x
- values["inclination_x"] = inclination_x;
-
- //náklon y
- values["inclination_y"] = inclination_y;
-
- //náklon z
- values["inclination_z"] = inclination_z;
- }
-
- let h = byte3;
- let m = byte2;
- let s = byte1;
-
- let timestamp;
-
- if(register == 87 || register == 6 || register == 7 )
- {
- //if(byte3 < 10) h = "0" + byte3;
- //if(byte2 < 10) m = "0" + byte2;
- //if(byte1 < 10) s = "0" + byte1;
-
- var d = new Date();
- d.setHours(h);
- d.setMinutes(m);
- d.setSeconds(s);
-
- timestamp = d.getTime();
- }
-
- //aktuálny čas
- if(register == 87)
- {
- //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
- //values["actual_time"] = h + ":" + m + ":" + s;
-
- values["actual_time"] = timestamp;
- }
-
- //čas súmraku
- if(register == 6)
- {
- //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
- //values["dusk_time"] = h + ":" + m + ":" + s;
-
- values["dusk_time"] = timestamp;
- }
-
- //čas úsvitu
- if(register == 7)
- {
- //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek.
- //values["dawn_time"] = h + ":" + m + ":" + s;
-
- values["dawn_time"] = timestamp;
- }
-
- //FW verzia
- if(register == 89)
- {
- //formát: "Byte3: Byte2.Byte1 (Byte0)"
- values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")";
- }
-
- return values;
-}
-
-
-//byte1 MSB = data3, byte2 = data2, byte3 = data1, byte4 = data0 LSB
-function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4) {
- let resp = [];
-
- let cmd = register;
-
- if (typeof adresa === 'string') adresa = parseInt(adresa);
- if (typeof byte1 === 'string') byte1 = parseInt(byte1);
- if (typeof byte2 === 'string') byte2 = parseInt(byte2);
- if (typeof byte3 === 'string') byte3 = parseInt(byte3);
- if (typeof byte4 === 'string') byte4 = parseInt(byte4);
-
- if (rw === 0)
- {
- cmd = cmd + 0x8000;
- }
-
- //master
- if(rec === 0) adresa = 0;
-
- if(rec === 2)
- {
- adresa = 0xffffffff;//Broadcast
- }
-
- //recipient
- if (rec === 3)
- {
- resp.push(0xFF);
- resp.push(0xFF);
- resp.push(0xFF);
- resp.push(0xFF);
- resp.push( adresa & 0xFF );//band
- }
- else
- {
- resp.push( (adresa >> 24) & 0xFF);//rshift
- resp.push( (adresa >> 16) & 0xFF);
- resp.push( (adresa >> 8) & 0xFF);
- resp.push( adresa & 0xFF );
-
- if (rec === 2)
- {
- resp.push(0xFF);
- }
- else resp.push(0);
- }
-
- resp.push( (cmd >> 8) & 0xFF);//rshift
- resp.push( cmd & 0xFF );//band
- resp.push( byte1 & 0xFF );//band
- resp.push( byte2 & 0xFF );//band
- resp.push( byte3 & 0xFF );//band
- resp.push( byte4 & 0xFF );//band
-
- //let data = '12345';
- let crc = crc16('ARC', resp);
- let c1 = (crc >> 8) & 0xFF;
- let c2 = crc & 0xFF;
-
- resp.push(c1);
- resp.push(c2);
-
- //logger.debug("checksum", crc);
- //logger.debug("resp", resp);
-
- return resp;
-
-}
-
-
-
-
-
-
-// SAMPLE DATA
-
-const relaysDataExample =
-{
- '0': {
- line: 0,
- tbname: 'jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV',
- contactor: 1,
- profile: ''
- },
- '1': {
- line: 1,
- tbname: 'MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O',
- contactor: 1,
- profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}'
- },
- '2': {
- line: 2,
- tbname: 'jBL12pg63eX4N9P7zy0lJLyEJKmlbkGwZMx0avQV',
- contactor: 1,
- profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}'
- },
- '3': {
- line: 3,
- tbname: 'aAOzENGrvpbe0VoK7D6E1a819PZmdg3nl24JLQMk',
- contactor: 1,
- profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}'
- }
-}
-
-
-const rpcSwitchOffLine =
-{
- "topic": "v1/gateway/rpc",
- "content": {
- "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV",
- "data": {
- "id": 8,
- "method": "set_command",
- "params": {
- "entities": [
- {
- "entity_type": "edb_line",
- "tb_name": "MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O"
- }
- ],
- "command": "switch",
- "payload": {
- "value": false
- }
- }
- }
- }
-}
-
-const rpcSetNodeDimming =
-{
- "topic": "v1/gateway/rpc",
- "content": {
- "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV",
- "data": {
- "id": 10,
- "method": "set_command",
- "params": {
- "entities": [
- {
- "entity_type": "street_luminaire",
- "tb_name": "jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV"
- }
- ],
- "command": "dimming",
- "payload": {
- "value": 5
- }
- }
- }
- }
-}
-
-const rpcLineProfile =
-{
- "topic": "v1/gateway/rpc",
- "content": {
- "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV",
- "data": {
- "id": 9,
- "method": "set_profile",
- "params": {
- "entities": [
- {
- "entity_type": "edb_line",
- "tb_name": "MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O"
- }
- ],
- "payload": {
- "intervals": [
- {
- "value": 0,
- "end_time": "20:00",
- "start_time": "13:00"
- },
- {
- "value": 1,
- "end_time": "05:30",
- "start_time": "20:00"
- },
- {
- "value": 0,
- "end_time": "13:00",
- "start_time": "05:30"
- }
- ],
- "astro_clock": true,
- "dawn_lux_sensor": false,
- "dusk_lux_sensor": false,
- "dawn_lux_sensor_value": 5,
- "dusk_lux_sensor_value": 5,
- "dawn_astro_clock_offset": 0,
- "dusk_astro_clock_offset": 0,
- "dawn_lux_sensor_time_window": 30,
- "dusk_lux_sensor_time_window": 30,
- "dawn_astro_clock_time_window": 60,
- "dusk_astro_clock_time_window": 60
- }
- }
- }
- }
-}
-
-
-const rpcNodeProfile =
-{
- "topic": "v1/gateway/rpc",
- "content": {
- "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV",
- "data": {
- "id": 11,
- "method": "set_profile",
- "params": {
- "entities": [
- {
- "entity_type": "street_luminaire",
- "tb_name": "jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV"
- }
- ],
- "payload": {
- "intervals": [
- {
- "cct": 3000,
- "value": 0,
- "end_time": "17:50",
- "start_time": "13:00"
- },
- {
- "cct": 3000,
- "value": 100,
- "end_time": "21:30",
- "start_time": "17:50"
- },
- {
- "cct": 3000,
- "value": 0,
- "end_time": "13:00",
- "start_time": "07:10"
- },
- {
- "cct": 3000,
- "value": 50,
- "end_time": "00:00",
- "start_time": "21:30"
- },
- {
- "cct": 3000,
- "value": 10,
- "end_time": "04:30",
- "start_time": "00:00"
- },
- {
- "cct": 3000,
- "value": 100,
- "end_time": "07:10",
- "start_time": "04:30"
- }
- ],
- "astro_clock": true,
- "dawn_lux_sensor": false,
- "dusk_lux_sensor": false,
- "dawn_lux_sensor_value": 5,
- "dusk_lux_sensor_value": 5,
- "dawn_astro_clock_offset": 30,
- "dusk_astro_clock_offset": 20,
- "dawn_lux_sensor_time_window": 30,
- "dusk_lux_sensor_time_window": 30,
- "dawn_astro_clock_time_window": 60,
- "dusk_astro_clock_time_window": 60
- }
- }
- }
- }
-}
-
- const sunCalcExample = {
- dusk_no_offset: '20:18',
- dawn_no_offset: '05:19',
- dusk: '20:18',
- dusk_hours: 20,
- dusk_minutes: 18,
- dawn: '05:19',
- dawn_hours: 5,
- dawn_minutes: 19,
- dusk_time: 1715278688962,
- dawn_time: 1715224744357,
- dusk_astro_clock_offset: 0,
- dawn_astro_clock_offset: 0
-}
diff --git a/flow/db_init.js b/flow/db_init.js
index 5fb447e..cf3b5a7 100644
--- a/flow/db_init.js
+++ b/flow/db_init.js
@@ -40,7 +40,6 @@ exports.install = async function(instance) {
const dbNodes = TABLE("nodes");
const dbRelays = TABLE("relays");
const dbSettings = TABLE("settings");
- const dbStatus = TABLE("status");
const dbPins = TABLE("pins");
const dbNotifications = TABLE("notifications");
@@ -50,14 +49,12 @@ exports.install = async function(instance) {
const responseSettings = await promisifyBuilder(dbSettings.find());
const responseNodes = await promisifyBuilder(dbNodes.find());
const responsePins = await promisifyBuilder(dbPins.find());
- const responseStatus = await promisifyBuilder(dbStatus.find());
const responseRelays = await promisifyBuilder(dbRelays.find());
const response = await promisifyBuilder(dbNotifications.find());
dbs.pinsData = makeMapFromDbResult(responsePins, "pin");
dbs.relaysData = makeMapFromDbResult(responseRelays, "line");
dbs.nodesData = makeMapFromDbResult(responseNodes, "node");
- dbs.statusData = responseStatus[0];
dbs.notificationsData = makeMapFromDbResult(response, "key");
//+|354|nodesdata.....+|482|nodesdata....
diff --git a/flow/designer.json b/flow/designer.json
index 09abdc3..455b37a 100644
--- a/flow/designer.json
+++ b/flow/designer.json
@@ -140,8 +140,8 @@
"component": "debug",
"tab": "1612772287426",
"name": "to TB",
- "x": 323.75,
- "y": 429,
+ "x": 312.75,
+ "y": 426,
"connections": {},
"disabledio": {
"input": [
@@ -270,9 +270,7 @@
"y": 557.3500061035156,
"connections": {},
"disabledio": {
- "input": [
- 0
- ],
+ "input": [],
"output": []
},
"state": {
@@ -291,14 +289,12 @@
"id": "1615809128443",
"component": "debug",
"tab": "1611921777196",
- "name": "Debug",
+ "name": "tempToTb",
"x": 598.8833312988281,
"y": 654.3500061035156,
"connections": {},
"disabledio": {
- "input": [
- 0
- ],
+ "input": [],
"output": []
},
"state": {
@@ -1142,7 +1138,7 @@
"output": []
},
"state": {
- "text": "847.42 MB / 985.68 MB",
+ "text": "846.37 MB / 985.68 MB",
"color": "gray"
},
"options": {
@@ -1172,7 +1168,7 @@
"output": []
},
"state": {
- "text": "5.79 GB / 7.26 GB",
+ "text": "5.77 GB / 7.26 GB",
"color": "gray"
},
"options": {
@@ -1628,7 +1624,7 @@
"output": []
},
"state": {
- "text": "1.3% / 74.34 MB",
+ "text": "6.2% / 70.96 MB",
"color": "gray"
},
"options": {
@@ -1960,6 +1956,10 @@
{
"index": "0",
"id": "1621340721628"
+ },
+ {
+ "index": "0",
+ "id": "1732889185927"
}
]
},
@@ -2141,9 +2141,9 @@
"options": {
"slack_channel": "C071KN2Q8SK",
"tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]",
- "message_includes": "[\"is responding again\", \"Lamps have turned\", \"Flow has been restarted\"]",
+ "message_includes": "[\"is responding again\", \"Lamps have turned\", \"Flow has been restarted\", \"Node db has changed\"]",
"types": "[\"emergency\", \"critical\", \"error\", \"alert\"]",
- "name": "rvo_senica_1_10.0.0.141"
+ "name": "rvo_senica_46_10.0.0.133"
},
"color": "#30E193",
"notes": ""
@@ -2342,7 +2342,7 @@
"clientid": "",
"port": "2764",
"host": "192.168.252.2",
- "topic": "u118"
+ "topic": "u133"
},
"color": "#888600",
"notes": ""
@@ -2780,7 +2780,137 @@
"options": {},
"color": "#F6BB42",
"notes": ""
+ },
+ {
+ "id": "1732700042559",
+ "component": "nodesdb_change_check",
+ "tab": "1612772287426",
+ "name": "Nodes DB change check",
+ "x": 250.88333129882812,
+ "y": 1813.2333984375,
+ "connections": {
+ "0": [
+ {
+ "index": "0",
+ "id": "1732700071298"
+ },
+ {
+ "index": "0",
+ "id": "1732700642917"
+ }
+ ]
+ },
+ "disabledio": {
+ "input": [],
+ "output": []
+ },
+ "state": {
+ "text": "",
+ "color": "gray"
+ },
+ "options": {},
+ "color": "#888600",
+ "notes": ""
+ },
+ {
+ "id": "1732700057052",
+ "component": "virtualwirein",
+ "tab": "1612772287426",
+ "name": "db-init",
+ "x": 71.75,
+ "y": 1814,
+ "connections": {
+ "0": [
+ {
+ "index": "0",
+ "id": "1732700042559"
+ }
+ ]
+ },
+ "disabledio": {
+ "input": [],
+ "output": []
+ },
+ "state": {
+ "text": "db-init",
+ "color": "gray"
+ },
+ "options": {
+ "wirename": "db-init"
+ },
+ "color": "#303E4D",
+ "notes": ""
+ },
+ {
+ "id": "1732700071298",
+ "component": "debug",
+ "tab": "1612772287426",
+ "name": "nodesChange",
+ "x": 548.8833312988281,
+ "y": 1875.2333984375,
+ "connections": {},
+ "disabledio": {
+ "input": [],
+ "output": []
+ },
+ "state": {
+ "text": "Enabled",
+ "color": "gray"
+ },
+ "options": {
+ "type": "data",
+ "repository": false,
+ "enabled": true
+ },
+ "color": "#967ADC",
+ "notes": ""
+ },
+ {
+ "id": "1732700642917",
+ "component": "virtualwireout",
+ "tab": "1612772287426",
+ "name": "tb-push",
+ "x": 544.8833312988281,
+ "y": 1769,
+ "connections": {},
+ "disabledio": {
+ "input": [],
+ "output": []
+ },
+ "state": {
+ "text": "tb-push",
+ "color": "gray"
+ },
+ "options": {
+ "wirename": "tb-push"
+ },
+ "color": "#303E4D",
+ "notes": ""
+ },
+ {
+ "id": "1732889185927",
+ "component": "debug",
+ "tab": "1611921777196",
+ "name": "tempToDido",
+ "x": 594.8833312988281,
+ "y": 745,
+ "connections": {},
+ "disabledio": {
+ "input": [],
+ "output": []
+ },
+ "state": {
+ "text": "Enabled",
+ "color": "gray"
+ },
+ "options": {
+ "type": "data",
+ "repository": false,
+ "enabled": true
+ },
+ "color": "#967ADC",
+ "notes": ""
}
],
"version": 615
-}
+}
\ No newline at end of file
diff --git a/flow/dido_controller.js b/flow/dido_controller.js
index 11e7ae3..86fb6a5 100644
--- a/flow/dido_controller.js
+++ b/flow/dido_controller.js
@@ -56,7 +56,6 @@ state_of_contactor - podľa indexu stykača sa reportuje jeho stav, teda
momentálne sa stav zmení len keď vo flow klikneš aby sa zmenil, ale tá zmena by sa mala ukázať aj na platforme
*/
-const dbStatus = TABLE("status");
const { errLogger, logger, monitor } = require('./helper/logger');
const SerialPort = require('serialport');
const WebSocket = require('ws');
@@ -90,9 +89,6 @@ const SEND_TO = {
cmd_manager: 2
}
-const TIME_AFTER_TEMPERATURE_NOK_STATUS = 3600; //seconds
-const DIFFERENCE_TO_SEND_TEMPERATURE = 0.31;
-
exports.install = function(instance) {
@@ -108,8 +104,7 @@ exports.install = function(instance) {
//process.exit(1);
})
- // temperature value is initialized to -1000. It can be literally anything, we just needs to be able to enter if block in ws.onmessage function, when first temperatere data comes
- let previousValues = {temperature: {value: -1000, lastTimeTemperatureReceived: Date.now() / 1000}};
+ let previousValues = {};
let rsPortReceivedData = [];
//to be able to get proper twilight values, when
@@ -163,15 +158,12 @@ exports.install = function(instance) {
rvoTbName = SETTINGS.rvoTbName;
pinsData = GLOBALS.pinsData;
relaysData = GLOBALS.relaysData;
- statusData = GLOBALS.statusData;
tbHandler = new DataToTbHandler(SEND_TO.tb)
tbHandler.setSender(exports.title);
controller_type = SETTINGS.controller_type //"lm" or "unipi" //logicMachine
if(controller_type == "") controller_type = "lm";
-
- deviceStatus["temperature"] = statusData.thermometer;
console.log(exports.title, "controller type: ", controller_type);
@@ -379,39 +371,19 @@ exports.install = function(instance) {
data = JSON.parse(data.data);
// data comes in array except of "temperature" ==> it comes as an object
- if(isObject(data))
- {
- let value = data['value'];
- const values = {};
- previousValues["temperature"]["lastTimeTemperatureReceived"] = data['time'];
-
- // we received data from thermometer, but thermometer status is NOK:
- if(deviceStatus["temperature"] === "NOK")
- {
- await writeThermometerStatusToDb("OK");
- sendRvoStatus();
- }
-
- // temperature value comes very often. To handle it, we check if it change for more than 0.3 degrees, if yes, we send to TB
- if(Math.abs(previousValues["temperature"]["value"] - value) > DIFFERENCE_TO_SEND_TEMPERATURE)
- {
- previousValues["temperature"]["value"] = value;
- values['temperature'] = value;
- sendTelemetry(values, rvoTbName);
- }
- return;
- }
+ // we do not handle temperature from evok any more => we return, if temperature comes:
+ if(isObject(data)) return;
data.map(item => {
-
+
let value = item['value'];
let pin = item["dev"] + item["circuit"]; // for example "relay1_03" or "input1_01"
- if(pin == undefined) return;
+ if(pin == undefined) return;
switchLogic(pin, value);
})
}
-
+
ws.on('error', (err) => {
monitor.info('websocket error, reconnect')
@@ -464,19 +436,19 @@ exports.install = function(instance) {
{
let value = 0;
if(onOrOff == "on") value = 1;
-
+
if(value == 1 && SETTINGS.maintenance_mode) return;
alarmStatus = "OFF";
if(value == 1) alarmStatus = "ON";
-
+
if(rsPort)
{
let arr = [0x55];
arr.push(13);
arr.push(0);
arr.push(value);
-
+
rsPort.write(Buffer.from(arr), function(err) {
logger.debug(`sirena - ${onOrOff}`);
});
@@ -605,7 +577,7 @@ exports.install = function(instance) {
//data from modbus_reader or temperature sensor or twilight sensor or other modbus device
instance.on("0", flowdata => {
- if(!flowdata.data instanceof Object) return;
+ if(!isObject(flowdata.data)) return;
// console.log('***********************', flowdata.data)
instance.send(SEND_TO.debug, flowdata.data);
@@ -622,10 +594,8 @@ exports.install = function(instance) {
{
deviceStatus["em"] = "NOK";
}
- //"NOK-thermometer" comes just from LM. Unipi handles thermometer from ws evok.
else if(status == "NOK-thermometer")
{
- previousValues["temperature"]["lastTimeTemperatureReceived"] = null;
deviceStatus["temperature"] = "NOK";
}
}
@@ -637,10 +607,8 @@ exports.install = function(instance) {
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: values["twilight_sensor"]});
deviceStatus["twilight_sensor"] = "OK"
}
- //"temperature" comes just from LM. Unipi handles thermometer from ws evok.
else if(values.hasOwnProperty("temperature"))
{
- previousValues["temperature"]["lastTimeTemperatureReceived"] = Date.now() / 1000; //time in seconds
deviceStatus["temperature"] = "OK";
}
// EM
@@ -669,8 +637,8 @@ exports.install = function(instance) {
let force = obj.force;
let info = obj.info;
- if(obj.command == "turnOn") turnLine("on", line, undefined, force, info);
- else if(obj.command == "turnOff") turnLine("off", line, undefined, force, info);
+ if(obj.command == "on") turnLine("on", line, undefined, force, info);
+ else if(obj.command == "off") turnLine("off", line, undefined, force, info);
else if(obj.command == "turnOnAlarm") turnAlarm("on");
else if(obj.command == "turnOffAlarm") turnAlarm("off");
@@ -822,15 +790,13 @@ exports.install = function(instance) {
let byte = bytesToInt([byte1, byte0]);
//console.log("calculateStateCode -------------------", byte);
-
+
return byte;
}
async function sendRvoStatus() {
- // test if dbLoaded is ok to check
- //if(!FLOW.dbLoaded) return;
if(SETTINGS === undefined) return;
const table = {
@@ -849,21 +815,11 @@ exports.install = function(instance) {
};
for (const phase of SETTINGS.no_voltage) dataToTb[`phase_${phase}_status`] = 0;
-
- //thermometer did not send data for more than a hour. Time in seconds
- if(deviceStatus["temperature"] === "OK")
- {
- if(previousValues["temperature"]["lastTimeTemperatureReceived"] + TIME_AFTER_TEMPERATURE_NOK_STATUS < Date.now() / 1000)
- {
- // to be able to calculate proper RVO status, we need to await writeThermometerStatusToDb function
- await writeThermometerStatusToDb("NOK");
- dataToTb["thermometer_status"] = 0;
- }
- }
dataToTb["status"] = checkRvoStatus();
dataToTb["statecode"] = calculateStateCode();
+ //console.log(dataToTb);
sendTelemetry(dataToTb, rvoTbName);
}
@@ -876,8 +832,7 @@ exports.install = function(instance) {
let status = "OK";
for (const [key, value] of Object.entries(deviceStatus)) {
- //if(["em", "twilight_sensor", "temperature"].includes(key) && value == "NOK") status = "NOK";
- if(["em", "twilight_sensor"].includes(key) && value == "NOK") status = "NOK";
+ if(["em", "twilight_sensor", "temperature"].includes(key) && value == "NOK") status = "NOK";
}
if(status == "OK")
@@ -899,6 +854,7 @@ exports.install = function(instance) {
if(!SETTINGS.masterNodeIsResponding) status = "NOK";
if(SETTINGS.no_voltage.size > 0) status = "NOK";
+ // console.log("rvo status",status)
return status;
}
@@ -1258,7 +1214,6 @@ exports.install = function(instance) {
}
if(newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue;
- if(rvoTbName == tbname) sendRvoStatus();
if(Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname);
}
@@ -1277,24 +1232,6 @@ exports.install = function(instance) {
}
- function writeThermometerStatusToDb(status) {
- return new Promise(function(resolve, reject) {
-
- dbStatus.modify({ thermometer: status }).make(function(builder) {
- builder.callback(function(err, response) {
- if(!err)
- {
- deviceStatus["temperature"] = status;
- console.log(`Wrote to db status: thermometer ${status}`);
- resolve("ok")
- }
- reject("nok")
- });
- });
- })
- }
-
-
function isObject (item) {
return (typeof item === "object" && !Array.isArray(item) && item !== null);
}
diff --git a/flow/nodesdb_changecheck.js b/flow/nodesdb_changecheck.js
new file mode 100644
index 0000000..be1e700
--- /dev/null
+++ b/flow/nodesdb_changecheck.js
@@ -0,0 +1,70 @@
+exports.id = 'nodesdb_change_check';
+exports.title = 'Nodes DB change check';
+exports.group = 'Worksys';
+exports.color = '#888600';
+exports.version = '1.0.2';
+exports.icon = 'sign-out';
+exports.input = 1;
+exports.output = 1;
+exports.readme = `Check, if nodes.table db changed compared to original database`;
+
+const fs = require('fs');
+const path = require('path');
+const { sendNotification } = require('./helper/notification_reporter');
+const nodesOriginalFile = path.join(__dirname, '../databases/nodes_original/', 'nodes_original.table');
+
+
+exports.install = function(instance) {
+
+ function compareArrays(array1, array2) {
+ let message = "";
+ let areEqual = true;
+ let zmenene = []
+
+ if (array1.length !== array2.length) {
+ 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);
+ }
+ }
+
+ if(!areEqual) {
+ 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)
+ }
+
+
+ instance.on("data", _ => {
+
+ 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);
+ })
+
+}
+
diff --git a/flow/thermometer.js b/flow/thermometer.js
index b3bb350..0be7eff 100644
--- a/flow/thermometer.js
+++ b/flow/thermometer.js
@@ -1,122 +1,98 @@
-exports.id = 'thermometer';
-exports.title = 'Thermometer';
-exports.group = 'Worksys';
-exports.color = '#5CB36D';
-exports.input = 1;
-exports.version = '1.0.3';
-exports.output = ["red", "white", "blue"];
-exports.author = 'Rastislav Kovac';
-exports.icon = 'thermometer-three-quarters';
-
-exports.readme = `# Getting temperature values for RVO. In case of LM, you need device address. In case of unipi, evok sends values, in case thermometer is installed`;
-
-const { errLogger, logger, monitor } = require('./helper/logger');
-
-const SEND_TO = {
- debug: 0,
- tb: 1,
- dido_controller: 2
-}
-
-//read temperature - frequency
-let timeoutMin = 5;//minutes
-
-
-exports.install = function(instance) {
-
- const { exec } = require('child_process');
- const { sendNotification } = require('./helper/notification_reporter');
-
- let startRead;
- let counter = 0;
- let rvoTbName = "";
- let temperatureAddress = "";
-
- logger.debug(exports.title, "installed");
-
- instance.on("close", function(){
- clearInterval(startRead);
- })
-
-
- const main = function() {
-
- try {
-
- if(FLOW.GLOBALS.settings.controller_type === "unipi")
- {
- clearInterval(startRead);
- return;
- }
-
- if(temperatureAddress === "") throw "gettemperature: temperatureAddress is not defined";
-
- exec(`owread -C ${temperatureAddress}/temperature`, (error, stdout, stderr) => {
-
- if(!error)
- {
- parseData(stdout)
- return;
- }
-
- sendNotification("main", rvoTbName, "thermometer_is_not_responding", {}, {"Error": error}, SEND_TO.tb, instance, "thermometer");
- monitor.info("Thermometer is not responding", error);
- instance.send(SEND_TO.dido_controller, {status: "NOK-thermometer"});
- });
-
- }
- catch(err) {
- errLogger.error(exports.title, err);
- clearInterval(startRead);
- }
- }
-
- const parseData = function(data) {
-
- data = parseFloat(data);
-
- logger.debug("gettemperature", data);
-
- if(!isNaN(data)) {
-
- if(counter > 290)
- {
- instance.send(SEND_TO.debug, "[Get temperature component] - temperature data are comming again from RVO after more than 1 day break");
- sendNotification("parseData", rvoTbName, "thermometer_is_responding_again", {}, "", SEND_TO.tb, instance, "thermometer");
- }
-
- logger.debug("gettemperature", data);
-
- const values = {
- "temperature": Number(data.toFixed(2)),
- }
-
- instance.send(SEND_TO.dido_controller, {values: values});
- counter = 0;
-
- } else {
-
- counter++;
- monitor.info("gettemperature err", counter, data);
-
- //ked je problem 1 den
- let day = 24 * 60 / timeoutMin;
- if ( counter > day && counter < day + 2 ) {
- //sendNotification("parseData", rvoTbName, ERRWEIGHT.WARNING, "Thermometer receives invalid data", "", SEND_TO.tb, instance, "thermometer");
- sendNotification("parseData", rvoTbName, "thermometer_sends_invalid_data", {}, "", SEND_TO.tb, instance, "thermometer");
-
- instance.send(SEND_TO.debug, "[Get temperature component] - no temperature data from RVO for more than 1 day");
- instance.send(SEND_TO.dido_controller, {status: "NOK-thermometer"});
- }
-
- }
-
- }
-
- instance.on("data", _ => {
- temperatureAddress = FLOW.GLOBALS.settings.temperature_address;
- rvoTbName = FLOW.GLOBALS.settings.rvoTbName;
- startRead = setInterval(main, timeoutMin * 1000 * 60);
- main();
- })
-};
\ No newline at end of file
+exports.id = 'thermometer';
+exports.title = 'Thermometer';
+exports.group = 'Worksys';
+exports.color = '#5CB36D';
+exports.input = 1;
+exports.version = '1.0.3';
+exports.output = ["red", "white", "blue"];
+exports.icon = 'thermometer-three-quarters';
+
+exports.readme = `# Getting temperature values for RVO. In case of LM, you need device address. In case of unipi, evok sends values, in case thermometer is installed`;
+
+const { errLogger, logger, monitor } = require('./helper/logger');
+
+const SEND_TO = {
+ debug: 0,
+ tb: 1,
+ dido_controller: 2
+}
+
+//read temperature - frequency
+let timeoutMin = 5;//minutes
+let NUMBER_OF_FAILURES_TO_SEND_ERROR = 13;
+
+exports.install = function(instance) {
+
+ const { exec } = require('child_process');
+ const { sendNotification } = require('./helper/notification_reporter');
+
+ let startRead;
+ let counter = 0;
+ let rvoTbName = "";
+ let temperatureAddress = "";
+
+ logger.debug(exports.title, "installed");
+
+ instance.on("close", function(){
+ clearInterval(startRead);
+ })
+
+
+ const main = function() {
+
+ try {
+
+ if(temperatureAddress === "") throw "Thermometer: temperatureAddress is not defined";
+
+ exec(`owread -C ${temperatureAddress}/temperature`, (error, stdout, stderr) => {
+
+ if(!error)
+ {
+ parseData(stdout)
+ return;
+ }
+
+ counter++;
+ if(counter == NUMBER_OF_FAILURES_TO_SEND_ERROR) sendNotification("Thermometer_main", rvoTbName, "thermometer_is_not_responding", {}, {"Error": error}, SEND_TO.tb, instance, "thermometer");
+ monitor.info("Thermometer is not responding", error);
+ instance.send(SEND_TO.dido_controller, {status: "NOK-thermometer"});
+ });
+
+ }
+ catch(err) {
+ errLogger.error(exports.title, err);
+ clearInterval(startRead);
+ }
+ }
+
+ const parseData = function(data) {
+
+ data = parseFloat(data);
+ logger.debug("Thermometer", data);
+
+ if(isNaN(data)) {
+ errLogger.error("Thermometer sends invalid data");
+ return;
+ }
+
+ if(counter > NUMBER_OF_FAILURES_TO_SEND_ERROR) //1 hour
+ {
+ instance.send(SEND_TO.debug, "Thermometer - temperature data are comming again");
+ sendNotification("Thermometer_parseData", rvoTbName, "thermometer_is_responding_again", {}, "", SEND_TO.tb, instance, "thermometer");
+ }
+
+ const values = {
+ "temperature": Number(data.toFixed(2)),
+ }
+
+ instance.send(SEND_TO.dido_controller, {values: values});
+ counter = 0;
+ }
+
+ instance.on("data", _ => {
+ temperatureAddress = FLOW.GLOBALS.settings.temperature_address;
+ rvoTbName = FLOW.GLOBALS.settings.rvoTbName;
+ startRead = setInterval(main, timeoutMin * 1000 * 60);
+ setTimeout(main, 20000);
+ })
+};