actual working Senica Rvo code 09/2024

This commit is contained in:
rasta5man 2024-09-09 12:32:34 +02:00
parent f4ffef94b9
commit 8929cc3a53
7 changed files with 810 additions and 429 deletions

View file

@ -1,4 +1,5 @@
const timeoutInterval = 150000;
const deviceConfig = [
{
device: "em340",

View file

@ -32,3 +32,6 @@ key:string|weight:string|sk:string|en:string
+|flow_start|NOTICE|FLOW bol spustený|FLOW has been started |...............
+|twilight_sensor_nok|ERROR|Sensor súmraku neodpovedá|Twilight sensor is not responding|...............
+|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|...............

View file

@ -280,30 +280,20 @@ function processNodeProfile(node)
try{
nodeProfile = JSON.parse( profile );
if(Object.keys(nodeProfile).length === 0) throw ("profile is not defined");
} catch (error) {}
//test reset profilu
//nodeProfile = undefined;
} catch (error) {
logger.debug("Error parsing node profile", error);
}
logger.debug("processNodeProfile", node, line, nodeObj, nodeProfile);
//return;
//let timestamp = PRIORITY_TYPES.node_cmd;
//let now = new Date();
//now.setSeconds(now.getSeconds() + 10);
//let timestamp = now.getTime();
let timestamp = PRIORITY_TYPES.node_cmd;
//nodeProfile = undefined;
removeTask({type: "set_node_profile", address: node});
cmdNOKNodeCounter[node] = 0;
//co ked sa prave spracovava?
//if(cmdNOKNodeCounter[params.address] < 5) saveToTb = false;
if(nodeProfile === undefined)
{
//vypneme profil nodu, posleme cmd
@ -318,7 +308,7 @@ function processNodeProfile(node)
params.byte1 = 0;
params.byte2 = 0;
params.byte3 = 0;
params.byte4 = 32;
params.byte4 = 96;
params.recipient = 1;
params.register = 8;
params.rw = 1;//write
@ -347,7 +337,7 @@ function processNodeProfile(node)
params.byte1 = 0;
params.byte2 = 0;
params.byte3 = 0;
params.byte4 = 32;
params.byte4 = 96;
params.recipient = 1;
params.register = 8;
params.rw = 1;//write
@ -615,7 +605,7 @@ function processNodeProfile(node)
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(profile.dawn_lux_sensor == true)//usvit
if(nodeProfile.dawn_lux_sensor == true)//usvit
{
bits.push(1);
}
@ -765,7 +755,7 @@ exports.install = function(instance) {
if(key == "0") continue;
if(line != undefined)
{
//ak sa jedna o update profilu linie - pozor di_co_controller posiela command pre loadRelaysData
//ak sa jedna o update profilu linie - pozor dido_controller posiela command pre loadRelaysData
if(line != value.line ) continue;
}
@ -1254,28 +1244,20 @@ exports.install = function(instance) {
{
//run broadcast Time of dusk
// addMinutesToTimestamp = 60*5;
addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk
let params = getParams(PRIORITY_TYPES.node_broadcast);
let recipient = 2;//2 broadcast, address = 0
let address = 0;//0
if(recipient === 2)
{
address = 0xffffffff;//Broadcast
}
let sunCalcResult = calculateDuskDawn();
let dusk_hours = sunCalcResult["dusk_hours"];
let dusk_minutes = sunCalcResult["dusk_minutes"];
params.address = address;//broadcast
params.address = 0xffffffff;//broadcast
params.byte1 = dusk_hours;//h
params.byte2 = dusk_minutes;//m
params.byte3 = 0;//s
params.byte4 = 0;
params.recipient = recipient;
params.recipient = 2;//2 broadcast,
params.register = 6;//Time of dusk - Reg 6
params.rw = 1;//write
@ -1300,23 +1282,16 @@ exports.install = function(instance) {
let params = getParams(PRIORITY_TYPES.node_broadcast);
let recipient = 2;//2 broadcast, address = 0
let address = 0;//0
if(recipient === 2)
{
address = 0xffffffff;//Broadcast
}
let sunCalcResult = calculateDuskDawn();
let dawn_hours = sunCalcResult["dawn_hours"];
let dawn_minutes = sunCalcResult["dawn_minutes"];
params.address = address;//broadcast
params.address = 0xffffffff;//broadcast
params.byte1 = dawn_hours;//h
params.byte2 = dawn_minutes;//m
params.byte3 = 0;//s
params.byte4 = 0;
params.recipient = recipient;
params.recipient = 2; //2 broadcast
params.register = 7;//Time of dawn - Reg 6
params.rw = 1;//write
@ -1332,31 +1307,23 @@ exports.install = function(instance) {
tasks.push(params);
}
{
//run broadcast //Actual time
addMinutesToTimestamp = 5;
let params = getParams(PRIORITY_TYPES.node_broadcast);
let recipient = 2;//2 broadcast, address = 0
let address = 0;//0
if(recipient === 2)
{
address = 0xffffffff;//Broadcast
}
var d = new Date();
let hours = d.getHours();
let minutes = d.getMinutes();
let seconds = d.getSeconds();
params.address = address;//broadcast
params.address = 0xffffffff;//broadcast
params.byte1 = hours;//h
params.byte2 = minutes;//m
params.byte3 = seconds;//s
params.byte4 = 0;
params.recipient = recipient;
params.recipient = 2; //2 broadcast
params.register = 87;//Actual time
params.rw = 1;//write
@ -1370,37 +1337,8 @@ exports.install = function(instance) {
params.info = "run broadcast: Actual time";
tasks.push(params);
}
{
//run broadcast Actual Lux level from cabinet
//Do tohto registra posiela riadiaca jednotka hodnotu intenzity osvetlenia ktorú meria jej senzor pre potreby riadenia časov súmraku resp. úsvitu podľa intenzity osvetlenia.
//Byty 0 (LSB) a 1 obsahujú 16 bitový integer s luxami.
let params = getParams(PRIORITY_TYPES.node_broadcast);
addMinutesToTimestamp = 15;
let recipient = 2;//2 broadcast, address = 0
let address = 0;//0
if(recipient === 2)
{
address = 0xffffffff;//Broadcast
}
//TODO
//16 bitový integer s luxami
params.byte3 = lux_sensor;
params.byte4 = lux_sensor;
params.timestamp = PRIORITY_TYPES.node_broadcast;
params.addMinutesToTimestamp = addMinutesToTimestamp;
params.info = "run broadcast: Actual Lux level from cabinet";
params.register = 95;//Actual Lux level from cabinet
params.rw = 1;//write
}
}
//process nodes & tasks
@ -1909,7 +1847,7 @@ exports.install = function(instance) {
tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000;
}
let info = "aplikovaný bod profilu";
let info = "aplikovany bod profilu";
let message = "";
if(value == 1)
{
@ -2099,8 +2037,9 @@ exports.install = function(instance) {
let resp = com_generic(params.address, params.recipient, params.rw, params.register, params.name, params.byte1, params.byte2, params.byte3, params.byte4);
let readBytes = 11;
let timeout = 5000;
await writeData(rsPort, resp, readBytes).then(function (data) {
await writeData(rsPort, resp, readBytes, timeout).then(function (data) {
endTime = new Date();
var timeDiff = endTime - startTime;
@ -2690,8 +2629,31 @@ exports.install = function(instance) {
{
lux_sensor = parseInt(flowdata.data.value);
//process profiles
turnOnOffLinesAccordingToLuxSensor(lux_sensor);
// 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")
{

File diff suppressed because it is too large Load diff

View file

@ -11,11 +11,11 @@ exports.icon = 'bolt';
exports.options = { edge: "undefined" };
exports.html = `<div class="padding">
<div class="row">
<div class="col-md-6">
<div data-jc="textbox" data-jc-path="edge" data-jc-config="placeholder:undefined;required:true" class="m">Edge TB Name</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div data-jc="textbox" data-jc-path="edge" data-jc-config="placeholder:undefined;required:true" class="m">Edge TB Name</div>
</div>
</div>
</div>`;
exports.readme = `# Sets RS232 port and all digital pins on device. Then it starts to receive data from sensors.
@ -60,7 +60,7 @@ state_of_contactor - podľa indexu stykača sa reportuje jeho stav, teda
//globals
//FIRMWARE version
FLOW.OMS_edge_fw_version = "2024-05-10";//rok-mesiac-den
FLOW.OMS_edge_fw_version = "2024-07-08";//rok-mesiac-den
FLOW.OMS_edgeName = "";
FLOW.OMS_maintenance_mode = false;
@ -78,7 +78,7 @@ FLOW.OMS_temperature_adress = "";//cmd_manager
let alarmStatus = "OFF";
const instanceSendTo = {
const SEND_TO = {
debug: 0,
tb: 1,
cmd_manager: 2
@ -152,7 +152,7 @@ exports.install = function(instance) {
/*
let conversionTable = {
"1": {tbname: "", type: "state_of_main_switch", "line": 0}, //state_of_main_switch pin1
"2": {tbname: "", type: "rotary_switch_state", "line": 0}, //rotary_switch_state - poloha manual = pin2
"2": {tbname: "", type: "rotary_switch_state", "line": 0}, //rotary_switch_state - poloha manual = pin2
"3": {tbname: "", type: "rotary_switch_state", "line": 0}, //rotary_switch_state - poloha auto = pin3
"4": {tbname: "", type: "power_supply", "line": 0},
"5": {tbname: "", type: "battery", "line": 0},
@ -192,7 +192,7 @@ exports.install = function(instance) {
/*
dbRelays.on('change', function(doc, old) {
console.log("'DI_DO_Controller - dbRelays.on('change'");
instance.send(instanceSendTo.cmd_manager, "reload_relays");
instance.send(SEND_TO.cmd_manager, "reload_relays");
});
*/
@ -264,14 +264,13 @@ exports.install = function(instance) {
{
errLogger.error("CRITICAL!!! undefined relay", relaysData[line], line);
//sendNotification("set port ", edgeName, ERRWEIGHT.CRITICAL, "local database is corrupted", "", instanceSendTo.tb, instance, null );
sendNotification("set port ", edgeName, "local_database_is_corrupted", {}, "", instanceSendTo.tb, instance );
//sendNotification("set port ", edgeName, ERRWEIGHT.CRITICAL, "local database is corrupted", "", SEND_TO.tb, instance, null );
sendNotification("set port ", edgeName, "local_database_is_corrupted", {}, "", SEND_TO.tb, instance );
}
}
if(pinsData[key].type == "state_of_contactor")
{
let pin = key - 1;
if(controller_type === "unipi") pin = key;
@ -299,37 +298,19 @@ exports.install = function(instance) {
]
}
instance.send(instanceSendTo.tb, dataToTb);
instance.send(SEND_TO.tb, dataToTb);
let time = 3*1000;
setTimeout(function(){
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "buildTasks"});
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "buildTasks"});
sendNotification("rsPort.open()", edgeName, "flow_start", {}, "", instanceSendTo.tb, instance );
sendNotification("rsPort.open()", edgeName, "flow_start", {}, "", SEND_TO.tb, instance );
monitor.info("-->FLOW bol spustený", edgeName, FLOW.OMS_edge_fw_version);
}, time);
}
// TODO: FIND BETTER SOLUTION, THAN REBUILDING TASKS
// we ensure, all tasks will be rebuild twice a week on tuesday or saturday at 11. To set correct switch off and on times
let sendRebuildTasksAt11 = null;
const checkIf11Oclock = () =>
{
const d = new Date();
const h = d.getHours();
const day = d.getDay();
if((day === 2 || day === 6) && h === 11)
{
instance.send(instanceSendTo.cmd_manager, {sender:"dido_controller", cmd:"buildTasks"});
monitor.info("Task rebuilt at 11 o'clock, tuesday, saturday");
}
}
sendRebuildTasksAt11 = setInterval(checkIf11Oclock, 3600000);
function handleRsPort()
{
//TODO build according to pins!!!
@ -339,7 +320,7 @@ exports.install = function(instance) {
rsPort.on('error', function(err) {
logger.debug("rsPort opened error - failed", err.message);
instance.send(instanceSendTo.debug, err.message);
instance.send(SEND_TO.debug, err.message);
errorHandler.sendMessageToService( exports.title + " rsPort opened error - failed: " + err.message);
})
@ -361,7 +342,7 @@ exports.install = function(instance) {
})
}).catch(function (reason) {
//instance.send(instanceSendTo.debug, exports.title + " runSyncExec - promise rejected:" + reason);
//instance.send(SEND_TO.debug, exports.title + " runSyncExec - promise rejected:" + reason);
errLogger.error( exports.title + " runSyncExec - promise rejected:" + reason);
errorHandler.sendMessageToService( exports.title + " runSyncExec - promise rejected:" + reason);
@ -490,7 +471,7 @@ exports.install = function(instance) {
deviceStatuses["temperature"] = "OK";
previousValues["temperature"] = value;
instance.send(instanceSendTo.tb, dataToTb);
instance.send(SEND_TO.tb, dataToTb);
}
return;
}
@ -508,7 +489,7 @@ exports.install = function(instance) {
ws.on('error', (err) => {
monitor.info('websocket error, reconnect')
instance.send(instanceSendTo.debug, err.message);
instance.send(SEND_TO.debug, err.message);
clearInterval(startRequests);
ws = null;
setTimeout(handleWebSocket, 1000);
@ -657,14 +638,14 @@ exports.install = function(instance) {
//console.log(values);
instance.send(instanceSendTo.tb, dataToTb);
instance.send(SEND_TO.tb, dataToTb);
}
function turnOnLine(line, pin, force, info)
{
instance.send(instanceSendTo.debug, "turn on line " + line );
instance.send(SEND_TO.debug, "turn on line " + line );
if(force == undefined) force = false;
if(line == 0)
@ -698,7 +679,7 @@ exports.install = function(instance) {
{
if(relaysData[line].contactor == 1)
{
instance.send(instanceSendTo.debug, "line is already on " + line );
instance.send(SEND_TO.debug, "line is already on " + line );
logger.debug("turnOnLine: line is already on: ", line);
return;
@ -775,7 +756,7 @@ exports.install = function(instance) {
{
if(relaysData[line].contactor == 0)
{
instance.send(instanceSendTo.debug, "line is already off " + line );
instance.send(SEND_TO.debug, "line is already off " + line );
logger.debug("turnOffLine: line already off:", line);
return;
@ -828,7 +809,7 @@ exports.install = function(instance) {
if(!flowdata.data instanceof Object) return;
// console.log('***********************', flowdata.data)
instance.send(instanceSendTo.debug, flowdata.data);
instance.send(SEND_TO.debug, flowdata.data);
// we handle nok status from modbus_reader component and thermometer
if(flowdata.data?.status)
@ -846,33 +827,34 @@ exports.install = function(instance) {
{
deviceStatuses["temperature"] = "NOK";
}
return;
}
else if(flowdata.data?.values)
{
const values = flowdata.data.values;
if(values.hasOwnProperty("twilight_sensor"))
{
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: values["twilight_sensor"]});
deviceStatuses["twilight_sensor"] = "OK"
}
else if(values.hasOwnProperty("temperature"))
{
deviceStatuses["temperature"] = "OK";
}
// EM
else if(values.hasOwnProperty("total_power") || values.hasOwnProperty("total_energy") || values.hasOwnProperty("power_factor") || values.hasOwnProperty("Phase_1_voltage") || values.hasOwnProperty("Phase_1_current"))
{
deviceStatuses["em"] = "OK";
}
else
{
return;
}
const values = flowdata.data.values;
if(values.hasOwnProperty("twilight_sensor"))
{
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: values["twilight_sensor"]});
deviceStatuses["twilight_sensor"] = "OK"
}
else if(values.hasOwnProperty("temperature"))
{
deviceStatuses["temperature"] = "OK";
}
// EM
else if(values.hasOwnProperty("total_power") || values.hasOwnProperty("total_energy") || values.hasOwnProperty("power_factor") || values.hasOwnProperty("Phase_1_voltage") || values.hasOwnProperty("Phase_1_current"))
{
deviceStatuses["em"] = "OK";
}
else
{
return;
}
const updateStatus = checkFinalRVOStatus();
if(updateStatus) values.status = "OK";
const updateStatus = checkFinalRVOStatus();
if(updateStatus) values.status = "OK";
sendTelemetry(values, FLOW.OMS_rvo_tbname);
sendTelemetry(values, FLOW.OMS_rvo_tbname);
}
})
@ -902,7 +884,7 @@ exports.install = function(instance) {
rsPort.write(Buffer.from(obj), function(err) {
switchLogic(obj);
instance.send(instanceSendTo.debug, {"WRITE":obj} );
instance.send(SEND_TO.debug, {"WRITE":obj} );
});
}
})
@ -1195,14 +1177,14 @@ exports.install = function(instance) {
{
if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
{
sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_off", {}, "", instanceSendTo.tb, instance , "state_of_main_switch");
sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance , "state_of_main_switch");
values["status"] = "NOK";
deviceStatuses["state_of_main_switch"] = "Off";
}
else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex])
{
sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_on", {}, "", instanceSendTo.tb, instance , "state_of_main_switch");
sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_on", {}, "", SEND_TO.tb, instance , "state_of_main_switch");
deviceStatuses["state_of_main_switch"] = "On";
}
@ -1247,7 +1229,7 @@ exports.install = function(instance) {
//ak je spracovany, a automatic - tak ho zapnem
//ak nie je spracovany, iba profil zapisem
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "rotary_switch_state", value: value});
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "rotary_switch_state", value: value});
//console.log("rotary_switch_state pin", pin2, pin3, value);
}
@ -1256,16 +1238,16 @@ exports.install = function(instance) {
{
if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.ALERT, "Power supply is not OK", "", instanceSendTo.tb, instance);
sendNotification("switchLogic", edgeName, "power_supply_has_disconnected_input", {}, "", instanceSendTo.tb, instance, "power_supply");
//sendNotification("switchLogic", edgeName, ERRWEIGHT.ALERT, "Power supply is not OK", "", SEND_TO.tb, instance);
sendNotification("switchLogic", edgeName, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply");
values["status"] = "NOK";
deviceStatuses["power_supply"] = "NOK";
}
else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex])
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Power supply is is OK", "", instanceSendTo.tb, instance);
sendNotification("switchLogic", edgeName, "power_supply_works_correctly", {}, "", instanceSendTo.tb, instance, "power_supply");
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Power supply is is OK", "", SEND_TO.tb, instance);
sendNotification("switchLogic", edgeName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply");
deviceStatuses["power_supply"] = "OK";
}
@ -1275,16 +1257,16 @@ exports.install = function(instance) {
{
if (newPinValue === 1 && newPinValue !== previousValues[pinIndex])
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.ERROR, "Battery is not OK", "", instanceSendTo.tb, instance);
sendNotification("switchLogic", edgeName, "battery_level_is_low", {}, "", instanceSendTo.tb, instance, "battery_level");
//sendNotification("switchLogic", edgeName, ERRWEIGHT.ERROR, "Battery is not OK", "", SEND_TO.tb, instance);
sendNotification("switchLogic", edgeName, "battery_level_is_low", {}, "", SEND_TO.tb, instance, "battery_level");
values["status"] = "NOK";
deviceStatuses["battery"] = "NOK";
}
else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Battery is OK", "", instanceSendTo.tb, instance);
sendNotification("switchLogic", edgeName, "battery_level_is_ok", {}, "", instanceSendTo.tb, instance, "battery_level");
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Battery is OK", "", SEND_TO.tb, instance);
sendNotification("switchLogic", edgeName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level");
deviceStatuses["battery"] = "OK";
}
@ -1298,19 +1280,19 @@ exports.install = function(instance) {
if (newPinValue != previousValues[pinIndex])
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, `RVO door ${value}`, "", instanceSendTo.tb, instance, "rvo_door");
//TODO ? sendNotification("switchLogic", edgeName, "door_value", {value: value}, "", instanceSendTo.tb, instance, "rvo_door");
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, `RVO door ${value}`, "", SEND_TO.tb, instance, "rvo_door");
//TODO ? sendNotification("switchLogic", edgeName, "door_value", {value: value}, "", SEND_TO.tb, instance, "rvo_door");
}
if (value === "open" && FLOW.OMS_maintenance_mode)
{
sendNotification("switchLogic", edgeName, "door_has_been_open", {}, "", instanceSendTo.tb, instance, "rvo_door");
sendNotification("switchLogic", edgeName, "door_has_been_open", {}, "", SEND_TO.tb, instance, "rvo_door");
}
if (value === "open" && !FLOW.OMS_maintenance_mode)
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.WARNING, "RVO open door out of maintenance mode", "", instanceSendTo.tb, instance);
sendNotification("switchLogic", edgeName, "door_has_been_open_without_permision_alarm_is_on", {}, "", instanceSendTo.tb, instance, "rvo_door");
//sendNotification("switchLogic", edgeName, ERRWEIGHT.WARNING, "RVO open door out of maintenance mode", "", SEND_TO.tb, instance);
sendNotification("switchLogic", edgeName, "door_has_been_open_without_permision_alarm_is_on", {}, "", SEND_TO.tb, instance, "rvo_door");
values["status"] = "NOK";
//console.log(door_has_been_open_without_permision_alarm_is_on);
@ -1325,7 +1307,7 @@ exports.install = function(instance) {
if(alarmStatus == "ON") turnOffAlarm();
//turnOffAlarm();
sendNotification("switchLogic", edgeName, "door_has_been_closed", {}, "", instanceSendTo.tb, instance, "rvo_door");
sendNotification("switchLogic", edgeName, "door_has_been_closed", {}, "", SEND_TO.tb, instance, "rvo_door");
}
deviceStatuses["door_condition"] = value;
@ -1364,12 +1346,12 @@ exports.install = function(instance) {
twilightError = true;
values["status"] = "NOK";
let value = twilight_sensor_array.shift();
//sendNotification("switchLogic", edgeName, ERRWEIGHT.ERROR, "Lux sensor error", {"Repeating value": value}, instanceSendTo.tb, instance );
//sendNotification("switchLogic", edgeName, ERRWEIGHT.ERROR, "Lux sensor error", {"Repeating value": value}, SEND_TO.tb, instance );
newPinValue = 0;
}
else if (set.size !== 1 && twilightError)
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Lux sensor is working again", "", instanceSendTo.tb, instance );
//sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Lux sensor is working again", "", SEND_TO.tb, instance );
twilightError = false;
twilight_sensor_array.shift();
newPinValue = value;
@ -1387,7 +1369,7 @@ exports.install = function(instance) {
if(diff >= twilight_sensor_interval * 60 * 1000)
{
const average = twilight_sensor.reduce((acc, c) => acc + c.value, 0) / twilight_sensor.length;
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: average});
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: average});
twilight_sensor = [];
@ -1398,11 +1380,11 @@ exports.install = function(instance) {
}
else if(type == "state_of_contactor")
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.INFO, `State of contactor ${line} is now ${value}`, "", instanceSendTo.tb, instance );
//sendNotification("switchLogic", edgeName, ERRWEIGHT.INFO, `State of contactor ${line} is now ${value}`, "", SEND_TO.tb, instance );
if(!(deviceStatuses["state_of_contactor"][line] == value))
{
sendNotification("switchLogic", edgeName, "state_of_contactor_for_line", {line: line, value: value}, "", instanceSendTo.tb, instance );
sendNotification("switchLogic", edgeName, "state_of_contactor_for_line", {line: line, value: value}, "", SEND_TO.tb, instance );
}
else
{
@ -1444,7 +1426,7 @@ exports.install = function(instance) {
//a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor
setTimeout(function(){
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged});
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged});
}, time);
reportLineStatus(line);
@ -1469,7 +1451,7 @@ exports.install = function(instance) {
if(valueChanged)
{
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line});
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line});
//mame iba 3 istice. vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia (napr linia 1, paralelna s nou je linia 4, key je string "4")
// ak je 7 linii, na 1 istici je linia 1,4,7
@ -1483,7 +1465,7 @@ exports.install = function(instance) {
{
if(!relaysData.hasOwnProperty(lineOnSameBraker[i])) continue;
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: lineOnSameBraker[i]});
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: lineOnSameBraker[i]});
deviceStatuses["state_of_breaker"][lineOnSameBraker[i]] = value;
reportLineStatus(lineOnSameBraker[i]);
@ -1502,7 +1484,7 @@ exports.install = function(instance) {
if(relaysData.hasOwnProperty(lineOnSameBraker))
{
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line + 3});
instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line + 3});
deviceStatuses["state_of_breaker"][line + 3] = value;
reportLineStatus(line + 3);
@ -1598,7 +1580,7 @@ exports.install = function(instance) {
]
}
instance.send(instanceSendTo.tb, dataToTb);
instance.send(SEND_TO.tb, dataToTb);
}
}

View file

@ -14,8 +14,8 @@ exports.readme = `
This device needs to be configured in dido_controller!!! Double check if it is. In dido_controller we calculate final status and all values with status are pushed to tb.
`;
const modbus = require('jsmodbus')
const SerialPort = require('serialport')
const modbus = require('jsmodbus');
const SerialPort = require('serialport');
const { timeoutInterval, deviceConfig } = require("../databases/modbus_config");
const { sendNotification } = require('./helper/notification_reporter');
@ -30,6 +30,8 @@ const SEND_TO = {
//to handle NOK and OK sendNotifications s
const numberOfNotResponding = {};
let tbName = null;
let mainSocket;
exports.install = function(instance) {
@ -50,6 +52,10 @@ exports.install = function(instance) {
this.lengthOfActualDeviceStream = null;
this.device = null;
// lampSwitchNotification helper variables
this.onNotificationSent = false;
this.offNotificationSent = false;
this.startSocket();
}
@ -215,6 +221,7 @@ exports.install = function(instance) {
};
this.checkNullVoltage(values);
this.lampSwitchNotification(values);
instance.send(SEND_TO.dido_controller, {values: values});
@ -243,32 +250,6 @@ exports.install = function(instance) {
}
}
// sendFinalObjects = (values) =>
// {
// const date = Date.now();
// // values["status"] = "OK";
// const dataToTB = {
// [tbName]: [
// {
// "ts": date,
// "values": values
// }
// ]
// };
// instance.send(SEND_TO.tb, dataToTB);
// const dataToDiDo = {
// values: values
// }
// instance.send(SEND_TO.dido_controller, dataToDiDo);
// }
calculateValue = (response, multiplier) =>
{
let value = 0;
@ -296,7 +277,6 @@ exports.install = function(instance) {
return Math.round(value * multiplier * 10) / 10;
}
checkNullVoltage = (values) => {
if(!(values.hasOwnProperty("Phase_1_voltage") || values.hasOwnProperty("Phase_2_voltage") || values.hasOwnProperty("Phase_3_voltage"))) return;
@ -313,19 +293,41 @@ exports.install = function(instance) {
if(values[singleValue] == 0)
{
FLOW.OMS_no_voltage.add(phase);
sendNotification("modbus_citys: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase );
sendNotification("modbus_reader: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase );
// console.log('no voltage')
}
else
{
FLOW.OMS_no_voltage.delete(phase);
// console.log('voltage detected')
sendNotification("modbus_citys: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase);
sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase);
}
}
})
}
/**
* function sends notification to slack and to tb, if EM total_power value changes more than 500. This should show, that RVO lamps has been switched on or off
*/
lampSwitchNotification = (values) => {
if(!values.hasOwnProperty("total_power")) return;
const actualTotalPower = values.total_power;
if(actualTotalPower > 600 && this.onNotificationSent == false)
{
sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance);
this.onNotificationSent = true;
this.offNotificationSent = false;
}
else if(actualTotalPower <= 600 && this.offNotificationSent == false)
{
sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_off", {}, "", SEND_TO.tb, instance);
this.onNotificationSent = false;
this.offNotificationSent = true;
}
}
}
const isObjectEmpty = (objectName) => {
@ -333,8 +335,14 @@ exports.install = function(instance) {
}
setTimeout(() => {
const newSocket = new SocketWithClients();
mainSocket = new SocketWithClients();
tbName = FLOW.OMS_rvo_tbname;
// this notification is to show, that flow (unipi) has been restarted
sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance);
}, 25000);
}

187
flow/slack_filter.js Normal file
View file

@ -0,0 +1,187 @@
exports.id = 'slack_filter';
exports.title = 'Slack Filter';
exports.group = 'Citysys';
exports.color = '#30E193';
exports.input = 1;
exports.output = 1;
exports.author = 'Jakub Klena';
exports.icon = 'plug';
exports.version = '1.0.8';
exports.options = { 'name':'', 'types': '["emergency", "critical", "error", "alert"]', 'message_includes':'["is responding again"]', 'tag_on_include':'[{"user_id":"U072JE5JUQG", "includes":["Electrometer", "Twilight sensor"]}]', 'slack_channel':'' };
exports.html = `<div class="padding">
<div class="row">
<div class="col-md-12">
<div data-jc="textbox" data-jc-path="name" data-jc-config="required:true">@(Name of this server)</div>
</div>
<div class="col-md-12">
<div data-jc="textbox" data-jc-path="slack_channel" data-jc-config="required:false">@(Slack channel to receive the alerts)</div>
</div>
<div class="col-md-12">
<div data-jc="textbox" data-jc-path="types" data-jc-config="required:false">@(Watch these types, comma separated names)</div>
</div>
<div class="col-md-12">
<div data-jc="textbox" data-jc-path="message_includes" data-jc-config="required:false">@(Watch messages that include any of the following strings)</div>
</div>
<div class="col-md-12">
<div data-jc="textbox" data-jc-path="tag_on_include" data-jc-config="required:false">@(Tag people if message includes something)</div>
</div>
</div>
</div>`;
exports.readme = `# Slack Filter`;
exports.install = function(instance) {
var running = false;
instance["savedSlackMessages"] = [];
var timer = null;
instance.on('data', function(response) {
if (!running) return;
let value = response.data;
if (typeof value !== 'object') return;
let can = false
var k = Object.keys(value);
var interested = JSON.parse(instance.options.types);
var msg_incl = JSON.parse(instance.options.message_includes);
var tags = JSON.parse(instance.options.tag_on_include);
if (k.length <= 0) return;
if (value[k[0]].length <= 0) return;
if (!Object.prototype.hasOwnProperty.call(value[k[0]][0], 'values')) return;
if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values'], '_event')) return;
if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event'], 'type')) return;
if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event'], 'source')) return;
if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event']['source'], 'func')) return;
if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event'], 'message')) return;
if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event'], 'message_data')) return;
let icon = ':totaljs:';
let type = value[k[0]][0]['values']['_event']['type'];
let source = value[k[0]][0]['values']['_event']['source']['func'];
let message = value[k[0]][0]['values']['_event']['message'];
let message_data = value[k[0]][0]['values']['_event']['message_data'];
let tag = '';
switch(type){
case 'debug':
icon = ':beetle:';
break;
case 'info':
icon = ':speech_balloon:';
break;
case 'notice':
icon = ':speech_balloon:';
break;
case 'warning':
icon = ':exclamation:';
break;
case 'alert':
icon = ':warning:';
break;
case 'error':
icon = ':no_entry:';
break;
case 'emergency':
icon = ':fire:';
break;
case 'critical':
icon = ':fire:';
break;
}
// Check if this message includes one of the strings we are watching for
for (const msg of msg_incl){
if (message.includes(msg)){
if (msg == 'is responding again') icon = ':large_green_circle:';
can = true;
break;
}
}
// Check if message is one of the types we are watching for
if (interested.includes(type)){
can = true;
}
if (!can) return;
// Check for each person tags based on what the message includes
for (const person of tags){
for (const msg of person.includes){
if (message.includes(msg)){
tag += '<@'+person.user_id+'> ';
break; // Break out from this person checks as they are already tagged now
}
}
}
// Now that all people are tagged add new line symbol
if (tag != '') tag += '\n';
let send_data = tag+instance.options.name+' '+type.toUpperCase()+'\n*Source*: '+source+'\n*Message*: '+message;
if (message_data) {
send_data += '\nData: '+message_data;
}
let ignore_msg = false
if (message.includes('Configuration of dimming profile to node no')){
for (let i = 0; i < FLOW["savedSlackMessages"].length; i++){
if (FLOW["savedSlackMessages"][i].message == message){
ignore_msg = true;
break;
}
}
if (!ignore_msg){
FLOW["savedSlackMessages"].push({message, 'dateandtime': Date.now()});
if (timer === null){
timer = setTimeout(checkSavedMessages, 60*60000);
}
}
}
if (!ignore_msg){
instance.send2({'msg':send_data,'bot_name':instance.options.name+' '+type.toUpperCase(),'bot_icon':icon,'channel':instance.options.slack_channel});
}
});
function checkSavedMessages(){
var d = Date.now();
d = d - 86400000; // older then 24hr
var a = [];
//Remove msgs older then 24hr
for (let i = 0; i < FLOW["savedSlackMessages"].length; i++){
if (FLOW["savedSlackMessages"][i].dateandtime > d){
a.push(FLOW["savedSlackMessages"][i]);
}
}
FLOW["savedSlackMessages"] = a;
if (FLOW["savedSlackMessages"].length > 0) {
timer = setTimeout(checkSavedMessages, 60*60000);
} else {
timer = null;
}
}
instance.reconfigure = function() {
try {
if (!FLOW["savedSlackMessages"]){
FLOW["savedSlackMessages"] = [];
}
if (instance.options.name) {
instance.status('Running');
running = true;
} else {
instance.status('Please enter name', 'red');
running = false;
}
} catch (e) {
instance.error('Citysys connector: ' + e.message);
}
};
instance.on('options', instance.reconfigure);
instance.reconfigure();
};