Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
rasta5man
a30a8588a7 Actual code running on CEZ rvo 2024-04-13 21:46:15 +02:00
12 changed files with 2841 additions and 1828 deletions

5
config
View file

@ -1,12 +1,13 @@
name : Total.js Flow
default_timezone : Europe/Bratislava
default_timezone : Europe/Bratislava
// Packages settings
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
table.nodes : node:number|tbname:string|line:number|dimming:number|profile:string|processed:boolean|status:boolean
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
table.pins : pin:string|type:string|line:number
table.notifications : key:string|weight:string|sk:string|en:string

View file

@ -1,113 +0,0 @@
const timeoutInterval = 300000;
const deviceConfig = [
{
device: "em340",
deviceAddress: 1,
stream: [
{
"tbAttribute": "Phase_1_voltage",
"register": 0,
"size": 2,
"multiplier": 0.1
},
{
"tbAttribute": "Phase_2_voltage",
"register": 2,
"size": 2,
"multiplier": 0.1
},
{
"tbAttribute": "Phase_3_voltage",
"register": 4,
"size": 2,
"multiplier": 0.1
},
{
"tbAttribute": "Phase_1_current",
"register": 12,
"size": 2,
"multiplier": 0.001
},
{
"tbAttribute": "Phase_2_current",
"register": 14,
"size": 2,
"multiplier": 0.001
},
{
"tbAttribute": "Phase_3_current",
"register": 16,
"size": 2,
"multiplier": 0.001
},
{
"tbAttribute": "Phase_1_power",
"register": 18,
"size": 2,
"multiplier": 0.1
},
{
"tbAttribute": "Phase_2_power",
"register": 20,
"size": 2,
"multiplier": 0.1
},
{
"tbAttribute": "Phase_3_power",
"register": 22,
"size": 2,
"multiplier": 0.1
},
{
"tbAttribute": "total_power",
"register": 40,
"size": 2,
"multiplier": 0.1
},
{
"tbAttribute": "total_energy",
"register": 52,
"size": 2,
"multiplier": 0.1
},
{
"tbAttribute": "Phase_1_pow_factor",
"register": 46,
"size": 1,
"multiplier": 0.001
},
{
"tbAttribute": "Phase_2_pow_factor",
"register": 47,
"size": 1,
"multiplier": 0.001
},
{
"tbAttribute": "Phase_3_pow_factor",
"register": 48,
"size": 1,
"multiplier": 0.001
},
{
"tbAttribute": "power_factor",
"register": 49,
"size": 1,
"multiplier": 0.001
}
]
},
{
device: "twilight_sensor",
deviceAddress: 2,
stream: [
{
"tbAttribute": "twilight_sensor",
"register": 60,
"size": 2,
"multiplier": 1
}
]
}
];
module.exports = { timeoutInterval, deviceConfig };

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,9 @@
exports.id = 'dido_controller';
exports.title = 'DIDO_Controller';
exports.version = '2.0.0';
exports.id = 'di_do_controller';
exports.title = 'DI_DO_Controller';
exports.version = '1.0.0';
exports.group = 'Worksys';
exports.color = '#2134B0';
exports.input = 3;
exports.input = 1;
exports.output = ["red", "white", "yellow"];
exports.click = false;
exports.author = 'Daniel Segeš';
@ -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 = "2023-10-18";//rok-mesiac-den
FLOW.OMS_edge_fw_version = "2022-05-12";//rok-mesiac-den
FLOW.OMS_edgeName = "";
FLOW.OMS_maintenance_mode = false;
@ -178,7 +178,7 @@ exports.install = function(instance) {
deviceStatuses["state_of_main_switch"] = "Off";//Hlavný istič
deviceStatuses["rotary_switch_state"] = "Off";//Prevádzkový mód
deviceStatuses["door_condition"] = "closed";//Dverový kontakt
deviceStatuses["em"] = "OK";//elektromer rvo
deviceStatuses["rvo"] = {status: "OK"};//elektromer rvo
deviceStatuses["temperature"] = "OK";//templomer
deviceStatuses["battery"] = "OK";//Batéria
deviceStatuses["power_supply"] = "OK";//Zdroj
@ -187,7 +187,6 @@ exports.install = function(instance) {
deviceStatuses["state_of_breaker"] = {};//"Off";//Istič
deviceStatuses["state_of_contactor"] = {};//"Off";//Stykač
deviceStatuses["twilight_sensor"] = "OK"; //lux sensor
/*
dbRelays.on('change', function(doc, old) {
@ -303,27 +302,13 @@ exports.install = function(instance) {
let time = 3*1000;
setTimeout(function(){
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "buildTasks"});
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "buildTasks"});
sendNotification("rsPort.open()", edgeName, "flow_start", {}, "", instanceSendTo.tb, instance );
monitor.info("-->FLOW bol spustený", edgeName, FLOW.OMS_edge_fw_version);
}, time);
}
// we ensure, all tasks will be rebuild every day at 11. To set correct switch off and on times
let sendRebuildTasksAt11 = null;
const checkIf11Oclock = () =>
{
const d = new Date();
const h = d.getHours();
if(h === 11)
{
instance.send(instanceSendTo.cmd_manager, {sender:"dido_controller", cmd:"buildTasks"});
}
}
sendRebuildTasksAt11 = setInterval(checkIf11Oclock, 3600000);
function handleRsPort()
@ -463,6 +448,7 @@ exports.install = function(instance) {
// dev: 'input',
// mode: 'Simple'
// },
ws.onmessage = function(data) {
data = JSON.parse(data.data);
@ -533,7 +519,6 @@ exports.install = function(instance) {
instance.on("close", () => {
if(rsPort) rsPort.close();
if(ws) ws.close();
clearInterval(sendRebuildTasksAt11);
})
loadAllDb();
@ -732,7 +717,7 @@ exports.install = function(instance) {
//pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method
let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": 1};
ws.send(JSON.stringify(cmd));
//switchLogic(pin, 1)
switchLogic(pin, 1)
}
}
@ -806,92 +791,71 @@ exports.install = function(instance) {
else if(ws)
{
//pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method
//monitor.info("turnOffLine pin (relay)", pin);
// monitor.info("turnOffLine pin (relay)", pin);
let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": 0};
ws.send(JSON.stringify(cmd));
//switchLogic(pin, 0)
switchLogic(pin, 0)
}
}
//data from modbus_reader or temperature sensor or twilight sensor or other modbus device
instance.on("0", flowdata => {
if(!flowdata.data instanceof Object) return;
// console.log('***********************', flowdata.data)
instance.send(instanceSendTo.debug, flowdata.data);
// we handle nok status from modbus_reader component and thermometer
if(flowdata.data?.status)
{
const status = flowdata.data.status;
if(status == "NOK-twilight_sensor")
{
deviceStatuses["twilight_sensor"] = "NOK";
}
else if(status == "NOK-em340" || status == "NOK-em111")
{
deviceStatuses["em"] = "NOK";
}
else if(status == "NOK-thermometer")
{
deviceStatuses["temperature"] = "NOK";
}
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";
}
const updateStatus = checkFinalRVOStatus();
if(updateStatus) values.status = "OK";
sendTelemetry(values, FLOW.OMS_rvo_tbname);
})
// we expect array as flowdata.data
instance.on("1", flowdata => {
instance.on("data", (flowdata) => {
console.log(flowdata.data);
if(!flowdata.data instanceof Object) return;
if(flowdata.data instanceof Object)
{
let obj = flowdata.data;
let line = obj.line;
let force = obj.force;
let info = obj.info;
if(flowdata.data.hasOwnProperty("sender"))
{
//console.log("sender", flowdata.data);
if(obj.command == "turnOn") turnOnLine(line, undefined, force, info);
else if(obj.command == "turnOff") turnOffLine(line, undefined, force, info);
else if(obj.command == "turnOnAlarm") turnOnAlarm();
else if(obj.command == "turnOffAlarm") turnOffAlarm();
if(flowdata.data.sender == "gettemperature")
{
deviceStatuses["temperature"] = flowdata.data.status;
}
else if(flowdata.data.sender == "modbus_citysys")
{
//elektromer rvo
if(flowdata.data.tbdata.hasOwnProperty(edgeName))
{
//rvo
deviceStatuses["rvo"] = {status: flowdata.data.tbdata[edgeName][0]["values"]["status"], tbdata: flowdata.data.tbdata};
}
else if(flowdata.data.tbdata.hasOwnProperty("twilight_sensor"))
{
switchLogic('twilight_sensor', flowdata.data.tbdata["twilight_sensor"])
}
}
instance.send(instanceSendTo.debug, flowdata.data );
return;
}
let obj = flowdata.data;
let line = obj.line;
let force = obj.force;
let info = obj.info;
if(obj.command == "turnOn") turnOnLine(line, undefined, force, info);
else if(obj.command == "turnOff") turnOffLine(line, undefined, force, info);
else if(obj.command == "turnOnAlarm") turnOnAlarm();
else if(obj.command == "turnOffAlarm") turnOffAlarm();
return;
}
//! ake data prichadzaju z cmd_manager.js ???
//TODO transform to websocket
if (Array.isArray(obj)){
if (Array.isArray(flowdata.data)){
rsPort.write(Buffer.from(obj), function(err) {
switchLogic(obj);
rsPort.write(Buffer.from(flowdata.data), function(err) {
switchLogic(flowdata.data);
instance.send(instanceSendTo.debug, {"WRITE":obj} );
instance.send(instanceSendTo.debug, {"WRITE":flowdata.data} );
});
}
})
@ -903,17 +867,12 @@ exports.install = function(instance) {
let bytes = [];
let bits = [];
//Hlavný istič - state_of_main_switch
if(deviceStatuses["state_of_main_switch"] == "On")
{
bits.push(0);
}
else if(deviceStatuses["state_of_main_switch"] == "Off")
{
bits.push(1);
}
//Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY
//Hlavný istič - state_of_main_switch
if(deviceStatuses["state_of_main_switch"] == "On") bits.push(0);
else if(deviceStatuses["state_of_main_switch"] == "Off") bits.push(1);
//Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false
if(!FLOW.OMS_maintenance_mode)
{
if(deviceStatuses["rotary_switch_state"] == "Manual")
@ -944,88 +903,41 @@ exports.install = function(instance) {
{
bits.push(0);
}
else
{
bits.push(1);
}
else bits.push(1);
//EM
if(deviceStatuses["em"] == "NOK")
{
bits.push(1);
}
else
{
bits.push(0);
}
if(deviceStatuses["rvo"].status == "NOK") bits.push(1);
else bits.push(0);
//Teplomer
if(deviceStatuses["temperature"] == "NOK")
{
bits.push(1);
}
else
{
bits.push(0);
}
if(deviceStatuses["temperature"] == "NOK") bits.push(1);
else bits.push(0);
//Batéria
if(deviceStatuses["battery"] == "NOK")
{
bits.push(1);
}
else
{
bits.push(0);
}
if(deviceStatuses["battery"] == "NOK") bits.push(1);
else bits.push(0);
//Zdroj
if(deviceStatuses["power_supply"] == "NOK")
{
bits.push(1);
}
else
{
bits.push(0);
}
if(deviceStatuses["power_supply"] == "NOK") bits.push(1);
else bits.push(0);
//MN
if(deviceStatuses["master_node"] == "NOK")
{
bits.push(1);
}
else
{
bits.push(0);
}
if(deviceStatuses["master_node"] == "NOK") bits.push(1);
else bits.push(0);
//výpadok napätia na fáze
if(deviceStatuses["no_voltage"] == "NOK")
{
bits.push(1);
}
else
{
bits.push(0);
}
if(deviceStatuses["twilight_sensor"] == "NOK")
{
bits.push(1);
}
else
{
bits.push(0);
}
if(deviceStatuses["no_voltage"] == "NOK") bits.push(1);
else bits.push(0);
// doplnime do 16 bitov (2 byty)
for(let i = bits.length; i < 16; i++)
{
bits.push(0);
}
// console.log("calculateStateCode - deviceStatuses", deviceStatuses);
// console.log("calculateStateCode", bits);
bits.push(0);
bits.push(0);
bits.push(0);
bits.push(0);
bits.push(0);
bits.push(0);
//console.log("calculateStateCode - deviceStatuses", deviceStatuses);
//console.log("calculateStateCode", bits);
let byte0 = bitwise.byte.write(bits.slice(0,8).reverse());
let byte1 = bitwise.byte.write(bits.slice(8).reverse());
@ -1047,18 +959,10 @@ exports.install = function(instance) {
let status = "OK";
if(deviceStatuses["em"] == "NOK")
if(deviceStatuses["rvo"].status == "NOK")
{
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: EM status is NOK");
if(writeToFile) errLogger.error("checkFinalRVOStatus: EM status is NOK");
status = "NOK";
}
if(deviceStatuses["twilight_sensor"] == "NOK")
{
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: twilight_sensor is NOK");
if(writeToFile) errLogger.error("checkFinalRVOStatus: twilight sensor is NOK");
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: rvo status is NOK");
if(writeToFile) errLogger.error("checkFinalRVOStatus: rvo status is NOK", deviceStatuses["rvo"].tbdata);
status = "NOK";
}
@ -1075,15 +979,10 @@ exports.install = function(instance) {
if(status == "OK")
{
let pinIndexes = [1, 4, 6];
if(controller_type == 'unipi') pinIndexes = ['input1_01', 'input1_04', 'input1_05'];
//console.log('-------- previousValues', previousValues);
for (const pinIndex of pinIndexes) {
for (const pinIndex of [1, 4, 6]) {
if (previousValues[pinIndex] === 0) {
if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && FLOW.OMS_maintenance_mode) continue;
if (pinIndex === 6 && FLOW.OMS_maintenance_mode) continue;
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: value is 0");
if(writeToFile) errLogger.error("checkFinalRVOStatus: value is 0", pinsData[pinIndex].type);
@ -1095,7 +994,7 @@ exports.install = function(instance) {
}
}
// battery status. If value is 1 - battery is NOK
// battery status. If value is 1 - battery is not ok
if (previousValues[5] === 1)
{
let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: NOK status generated by battery");
@ -1104,6 +1003,18 @@ exports.install = function(instance) {
status = "NOK";
}
//ak mame telemetriu z elektromeru, posleme
if(deviceStatuses["rvo"].tbdata != undefined)
{
//deviceStatuses["rvo"] = {status: flowdata.data.tbdata[edgeName][0]["values"]["status"], tbdata: flowdata.data.tbdata};
deviceStatuses["rvo"].tbdata[edgeName][0]["values"]["status"] = status;
instance.send(instanceSendTo.tb, deviceStatuses["rvo"].tbdata);
delete deviceStatuses["rvo"].tbdata;
}
//console.log("FLOW.OMS_masterNodeIsResponding", FLOW.OMS_masterNodeIsResponding);
if(!FLOW.OMS_masterNodeIsResponding)
@ -1130,7 +1041,17 @@ exports.install = function(instance) {
if(status == "NOK")
{
sendTelemetry({status: "NOK"}, FLOW.OMS_rvo_tbname);
const dataToTb = {
[edgeName]: [
{
"ts": Date.now(),
"values": {status: "NOK"}
}
]
}
instance.send(instanceSendTo.tb, dataToTb);
return false;
}
@ -1139,8 +1060,8 @@ exports.install = function(instance) {
}
// we pass array to function in case of rsPort ==> switchLogic([55,3,0,1]) ==> [[55,3,0,1]]
// we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1]
// we pass array to function in case of rsPort ==> switchLogic([55,3,0,1])
// we pass two values in case of websocket ==> switchLogic("relay1_03",1)
const switchLogic = (...args) => {
let values = {status: "OK"};
@ -1174,27 +1095,28 @@ exports.install = function(instance) {
let tbname = obj.tbname;
//default value
let value = "On";
if(newPinValue === 0) value = "Off";
let value = "Off";
if(newPinValue === 1) value = "On";
//Hlavný istič
//! po novom uz 'state of main switch' nemame. Namiesto neho je 'door_condition', kedze mame dvoje dveri
//! takze ked pride z evoku signal pre 'input1_05', handlujeme ho ako 'door_condition'
if(type === "!!!state_of_main_switch")
if(type === "state_of_main_switch")
{
if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
if (newPinValue === 1 && newPinValue !== previousValues[pinIndex])
{
sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_off", {}, "", instanceSendTo.tb, instance , "state_of_main_switch");
values["status"] = "NOK";
deviceStatuses["state_of_main_switch"] = "Off";
value = "Off";
}
else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex])
else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
{
sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_on", {}, "", instanceSendTo.tb, instance , "state_of_main_switch");
deviceStatuses["state_of_main_switch"] = "On";
value = "On";
}
deviceStatuses["state_of_main_switch"] = value;
}
//Prevádzkový mód
@ -1226,9 +1148,9 @@ exports.install = function(instance) {
}
//console.log('***********************', pin2, pin3)
if (pin2 == 1 && pin3 == 0) value = "Manual";
if (pin2 == 0 && pin3 == 1) value = "Manual";
if (pin2 == 0 && pin3 == 0) value = "Off";
if (pin2 == 0 && pin3 == 1) value = "Automatic";
if (pin2 == 1 && pin3 == 0) value = "Automatic";
deviceStatuses["rotary_switch_state"] = value;
@ -1236,14 +1158,14 @@ 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(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "rotary_switch_state", value: value});
//console.log("rotary_switch_state pin", pin2, pin3, value);
}
//Zdroj - pin 4
else if (type === "power_supply")
{
if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
if (newPinValue === 1 && 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");
@ -1251,7 +1173,7 @@ exports.install = function(instance) {
deviceStatuses["power_supply"] = "NOK";
}
else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex])
else if (newPinValue === 0 && 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");
@ -1262,7 +1184,7 @@ exports.install = function(instance) {
//Batéria - pin 5
else if (type === "battery")
{
if (newPinValue === 1 && newPinValue !== previousValues[pinIndex])
if (newPinValue === 0 && 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");
@ -1270,7 +1192,7 @@ exports.install = function(instance) {
deviceStatuses["battery"] = "NOK";
}
else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
else if (newPinValue === 1 && 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");
@ -1279,11 +1201,9 @@ exports.install = function(instance) {
}
}
//Dverový kontakt - pin 6
//! Po novom mame dva dverove kontakty, nie jeden. Druhy je teraz tam, kde bol digital input "state_of_main_switch"
//! preto ked pride z evoku signal z input1_05, co bol predytm "main switch" handlujeme ho teraz ako 'door_condition'
else if(type == "door_condition" || type === "state_of_main_switch")
else if(type == "door_condition")
{
newPinValue === 0 ? value = "open" : value = "closed";
newPinValue === 0 ? value = "closed" : value = "open";
if (newPinValue != previousValues[pinIndex])
{
@ -1304,9 +1224,8 @@ exports.install = function(instance) {
//console.log(door_has_been_open_without_permision_alarm_is_on);
// zapneme sirenu
// ak sa otvoria dvere len na elektromeri (type === "state_of_main_switch") alarm sa nema spustit. alarm sa spusti len ked sa otvoria hlavne dvere (type === "door_condition")
if(type === "door_condition") turnOnAlarm();
//zapneme sirenu
turnOnAlarm();
}
if (value === "closed")
@ -1376,7 +1295,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(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "lux_sensor", value: average});
twilight_sensor = [];
@ -1384,20 +1303,18 @@ exports.install = function(instance) {
}
//else console.log("lux_sensor", value, diff);
}
else
{
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "lux_sensor", value: value});
}
}
else if(type == "state_of_contactor")
{
//sendNotification("switchLogic", edgeName, ERRWEIGHT.INFO, `State of contactor ${line} is now ${value}`, "", instanceSendTo.tb, instance );
sendNotification("switchLogic", edgeName, "state_of_contactor_for_line", {line: line, value: value}, "", instanceSendTo.tb, instance );
if(!(deviceStatuses["state_of_contactor"][line] == value))
{
sendNotification("switchLogic", edgeName, "state_of_contactor_for_line", {line: line, value: value}, "", instanceSendTo.tb, instance );
}
else
{
deviceStatuses["state_of_contactor"][line] = value;
}
deviceStatuses["state_of_contactor"][line] = value;
//true, false
if(value === "On") value = true;
else if(value === "Off") value = false;
@ -1433,7 +1350,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(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged});
}, time);
reportLineStatus(line);
@ -1458,24 +1375,7 @@ exports.install = function(instance) {
if(valueChanged)
{
instance.send(instanceSendTo.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line});
//mame 3 istice. ked je viac ako 3 linie, dalsie sa zapajaju paralelne. to znamena na istici 1 je linia 1 a 4, na istici 2 je linia 2 a 5, na istici 3 je linia 3 a 6 (key je string ("4"))
//vyreportujeme a ohandlujeme liniu na tom istom istici ako paralelna linia
const lineOnSameBraker = line + 3 + "";
if(relaysData.hasOwnProperty(lineOnSameBraker)) {
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "state_of_breaker", value: value, line: line + 3});
deviceStatuses["state_of_breaker"][line + 3] = value;
reportLineStatus(line + 3);
values[type] = value;
tbname = relaysData[lineOnSameBraker].tbname;
sendTelemetry(values, tbname);
delete values[type];
}
instance.send(instanceSendTo.cmd_manager, {sender: "di_do_controller", cmd: "state_of_breaker", value: value, line: line});
}
if(value == "Off") values["status"] = "NOK";
@ -1483,27 +1383,25 @@ exports.install = function(instance) {
deviceStatuses["state_of_breaker"][line] = value;
reportLineStatus(line);
}
values[type] = value;
let result = checkFinalRVOStatus();
if(!result && line == 0)
{
values["status"] = "NOK";
}
//--
//if(FLOW.OMS_rvo_tbname == tbname) values["statecode"] = calculateStateCode();
if(pinsData.hasOwnProperty(pinIndex))
{
let valueChanged = false;
if(newPinValue != previousValues[pinIndex])
{
valueChanged = true;
//pin was changed
previousValues[pinIndex] = newPinValue;
}
let result = checkFinalRVOStatus();
if(!result && line == 0)
{
values["status"] = "NOK";
}
if(newPinValue != previousValues[pinIndex]) valueChanged = true;
if(type == "state_of_contactor") valueChanged = true;
if(type == "rotary_switch_state") valueChanged = true;
@ -1514,7 +1412,7 @@ exports.install = function(instance) {
if(FLOW.OMS_rvo_tbname == "")
{
console.log("FLOW.OMS_rvo_tbname is EMPTY");
console.log("FLOW.OMS_rvo_tbname is EMPTY");
}
if(FLOW.OMS_rvo_tbname == tbname)
@ -1522,6 +1420,7 @@ exports.install = function(instance) {
values["statecode"] = calculateStateCode();
//console.log('**********************', type, values, valueChanged, FLOW.OMS_rvo_tbname, tbname);
}
if(valueChanged)
{
@ -1544,6 +1443,10 @@ exports.install = function(instance) {
logger.debug("no pinIndex", pinsData[pinIndex], pinsData);
}
//pin was changed
previousValues[pinIndex] = newPinValue;
}
@ -1889,24 +1792,3 @@ exports.install = function(instance) {
// {
// "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV": [
// {
// "ts": 1700409326353,
// "values": {
// "_event": {
// "type": "notice",
// "status": "new",
// "source": {
// "func": "rsPort.open()",
// "component": "1700343402190",
// "component_name": "DIDO_Controller",
// "edge": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV"
// },
// "message": "al_shariff_10.0.0.38: FLOW has been started ",
// "message_data": ""
// }
// }
// }
// ]
// }

View file

@ -1,18 +1,18 @@
exports.id = 'thermometer';
exports.id = 'gettemperature';
exports.title = 'Thermometer';
exports.group = 'Worksys';
exports.color = '#5CB36D';
exports.version = '1.0.3';
exports.version = '1.0.2';
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`;
exports.readme = `# Getting temperature values from RVO`;
const instanceSendTo = {
debug: 0,
tb: 1,
dido_controller: 2
di_do_controller: 2
}
//read temperature - frequency
@ -43,7 +43,7 @@ const monitor = log4js.getLogger("monitorLogs");
//monitor.info('info');
//errLogger.error("some error");
const { promisifyBuilder } = require('./helper/db_helper');
const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js');
const dbSettings = TABLE("settings");
let temperatureAddress = "";
@ -60,7 +60,7 @@ loadSettings();
exports.install = function(instance) {
const { exec } = require('child_process');
const { sendNotification, ERRWEIGHT } = require('./helper/notification_reporter');
const { sendNotification, ERRWEIGHT } = require('./helper/notification_reporter.js');
let startRead;
let dataToTb;
@ -76,9 +76,9 @@ exports.install = function(instance) {
})
const start = function() {
const start = function(){
try {
try{
if(FLOW.OMS_controller_type === "unipi")
{
@ -130,8 +130,8 @@ exports.install = function(instance) {
monitor.info("Thermometer is not responding", error, FLOW.OMS_brokerready);
// instance.send(instanceSendTo.tb, dataToTb); // poslat stav nok do tb, ak to handluje dido_controller ??
instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"});
instance.send(instanceSendTo.tb, dataToTb);
instance.send(instanceSendTo.di_do_controller, {sender: "gettemperature", status: status});
}
else parseData(stdout);
}
@ -162,9 +162,10 @@ exports.install = function(instance) {
logger.debug("gettemperature", data);
if(!isNaN(data)) {
if (!isNaN(data)){
if(counter > 290)
//if ( counter > 290 )
{
instance.send(instanceSendTo.debug, "[Get temperature component] - temperature data are comming again from RVO after more than 1 day break");
@ -173,22 +174,21 @@ exports.install = function(instance) {
}
logger.debug("gettemperature", data);
const values = {
"temperature": Number(data.toFixed(2)),
"status": "OK"
}
dataToTb = {
[edgeName]: [
{
"ts": Date.now(),
"values":values
"values": {
"temperature": Number(data.toFixed(2)),
"status": "OK"
}
}
]
}
instance.send(instanceSendTo.tb, dataToTb);
instance.send(instanceSendTo.dido_controller, values);
instance.send(instanceSendTo.di_do_controller, {sender: "gettemperature", status: "OK"});
counter = 0;
@ -204,8 +204,9 @@ exports.install = function(instance) {
sendNotification("parseData", edgeName, "thermometer_sends_invalid_data", {}, "", instanceSendTo.tb, instance, "thermometer");
instance.send(instanceSendTo.debug, "[Get temperature component] - no temperature data from RVO for more than 1 day");
instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"});
instance.send(instanceSendTo.di_do_controller, {sender: "gettemperature", status: "NOK"});
}
}
}
@ -215,4 +216,5 @@ exports.install = function(instance) {
}, 3000);
startRead = setInterval(start, timeoutMin * 1000 * 60);
};

1135
flow/modbus_citysys.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,336 +0,0 @@
exports.id = 'modbus_reader';
exports.title = 'Modbus reader';
exports.version = '2.0.0';
exports.group = 'Worksys';
exports.color = '#2134B0';
exports.output = ["red", "white"];
exports.click = false;
exports.author = 'Rastislav Kovac';
exports.icon = 'bolt';
exports.readme = `
Modbus requests to modbus devices (electromer, twilight sensor, thermometer.
Component keeps running arround deviceConfig array in "timeoutInterval" intervals. Array items are objects with single modbus devices.
Everything is sent to dido_controller. If requests to device fail (all registers must fail to send NOK status) , we send "NOK-'device'" status to dido_controller.
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 { timeoutInterval, deviceConfig } = require("../databases/modbus_config");
const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler');
const errorHandler = new ErrorToServiceHandler();
const { sendNotification } = require('./helper/notification_reporter');
const instanceSendTo = {
debug: 0,
dido_controller: 1,
};
//to handle NOK and OK sendNotifications s
const numberOfNotResponding = {};
let tbName = null;
exports.install = function(instance) {
class SocketWithClients {
constructor () {
this.stream = null;
this.socket = null;
this.clients = {};
this.allValues = {};
this.errors = 0;
this.index = 0;
this.timeoutInterval = 5000;
// kedze potrebujeme ist stale dookola pre jednotlive zariadenia, potrebujeme ci uz index ako aj adresu zariadenia, a aj pocet registrov na vycitanie
this.deviceAddress = null; // adresa zariadenia (1 ma EM340 a 2 ma twilight_sensor)
this.indexInDeviceConfig = 0; // prvy item v deviceConfig
this.lengthOfActualDeviceStream = null;
this.device = null;
this.startSocket();
}
startSocket = () => {
let obj = this;
this.socket = new SerialPort("/dev/ttymxc0", {
baudRate: 9600,
})
// we create a client for every deviceAddress ( = address) in list and push them into dictionary
for( let i = 0; i < deviceConfig.length; i++)
{
this.clients[deviceConfig[i].deviceAddress] = new modbus.client.RTU(this.socket, deviceConfig[i].deviceAddress);
}
this.socket.on('error', function(e) {
console.log('socket connection error', e);
if(e.code == 'ECONNREFUSED' || e.code == 'ECONNRESET') {
console.log(exports.title + ' Waiting 10 seconds before trying to connect again');
setTimeout(obj.startSocket, 10000);
}
});
this.socket.on('close', function() {
console.log('Socket connection closed ' + exports.title + ' Waiting 10 seconds before trying to connect again');
setTimeout(obj.startSocket, 10000);
});
this.socket.on('open', function () {
console.log("socket connected");
obj.getActualStreamAndDevice();
obj.timeoutInterval = timeoutInterval;
})
};
getActualStreamAndDevice = () => {
const dev = deviceConfig[this.indexInDeviceConfig];
this.index = 0;
this.errors = 0;
this.stream = dev.stream;
this.lengthOfActualDeviceStream = dev.stream.length;
this.deviceAddress = dev.deviceAddress; // 1 or 2 or any number
this.device = dev.device; //em340, twilight_sensor
if(this.indexInDeviceConfig == 0) setTimeout(this.readRegisters, this.timeoutInterval);
else setTimeout(this.readRegisters, 2000);
}
readRegisters = () => {
const str = this.stream[this.index];
const register = str.register;
const size = str.size;
const tbAttribute = str.tbAttribute;
let obj = this;
this.clients[this.deviceAddress].readHoldingRegisters(register, size)
.then( function (resp) {
resp = resp.response._body.valuesAsArray; //resp is array of length 1 or 2, f.e. [2360,0]
// console.log(deviceAddress, register, tbAttribute, resp);
//device is responding again after NOK status
if(numberOfNotResponding.hasOwnProperty(obj.device))
{
let message = "";
if(obj.device == "em340")
{
message = "electrometer_ok";
}
else if(obj.device == "twilight_sensor")
{
message = "twilight_sensor_ok";
}
message && sendNotification("modbus_reader: readRegisters", tbName, message, {}, "", instanceSendTo.tb, instance);
delete numberOfNotResponding[obj.device];
}
obj.transformResponse(resp, register, obj.deviceAddress);
obj.error = 0;
obj.index++;
if(obj.index < obj.lengthOfActualDeviceStream) setTimeout(obj.readRegisters, 0);
else obj.setNewStream();
}).catch (function () {
console.log("error pri citani modbus registra", register, obj.indexInDeviceConfig, tbName, tbAttribute);
obj.error++;
if(obj.error == obj.lengthOfActualDeviceStream)
{
instance.send(instanceSendTo.dido_controller, {status: "NOK-" + obj.device}); // NOK-em340, NOK-em111, NOK-twilight_sensor, NOK-thermometer
//todo - neposlalo notification, ked sme vypojili twilight a neposle to do tb, ale do dido ??
if(!numberOfNotResponding.hasOwnProperty(obj.device))
{
let message = "";
if(obj.device == "twilight_sensor")
{
message = "twilight_sensor_nok";
}
else if(obj.device == "em340")
{
message = "electrometer_nok";
}
message && sendNotification("modbus_reader: readingTimeouted", tbName, message, {}, "", instanceSendTo.tb, instance);
numberOfNotResponding[obj.device] = 1;
}
obj.error = 0;
numberOfNotResponding[obj.device] += 1;
}
console.error(require('util').inspect(arguments, {
depth: null
}))
obj.index++;
if(obj.index < obj.lengthOfActualDeviceStream) setTimeout(obj.readRegisters, 0);
else obj.setNewStream();
})
};
transformResponse = (response, register, deviceAddress) => {
for (let i = 0; i < this.lengthOfActualDeviceStream; i++) {
let a = this.stream[i];
if (a.register === register)
{
let tbAttribute = a.tbAttribute;
let multiplier = a.multiplier;
let value = this.calculateValue(response, multiplier);
// console.log(deviceAddress, register, tbName, tbAttribute, response, a.multiplier, value);
// if(tbName == undefined) return;
if(this.index + 1 + this.errors < this.lengthOfActualDeviceStream)
{
this.allValues[tbAttribute] = value;
return;
}
const values = {
...this.allValues,
[tbAttribute]: value,
};
this.checkNullVoltage(values);
instance.send(instanceSendTo.dido_controller, {values: values});
this.allValues = {};
break;
}
}
}
setNewStream = () =>
{
// console.log('------------',this.lengthOfActualDeviceStream, this.index);
// console.log('------------',this.indexInDeviceConfig, deviceConfig.length);
if(this.lengthOfActualDeviceStream == this.index)
{
if(this.indexInDeviceConfig + 1 == deviceConfig.length)
{
this.indexInDeviceConfig = 0;
}
else
{
this.indexInDeviceConfig += 1;
}
this.getActualStreamAndDevice();
}
}
// sendFinalObjects = (values) =>
// {
// const date = Date.now();
// // values["status"] = "OK";
// const dataToTB = {
// [tbName]: [
// {
// "ts": date,
// "values": values
// }
// ]
// };
// instance.send(instanceSendTo.tb, dataToTB);
// const dataToDiDo = {
// values: values
// }
// instance.send(instanceSendTo.dido_controller, dataToDiDo);
// }
calculateValue = (response, multiplier) =>
{
let value = 0;
let l = response.length;
if (l === 2)
{
value = (response[1]*(2**16) + response[0]);
if(value >= (2**31)) // ak je MSB bit nastavený, eventuálne sa dá použiť aj (value & 0x80000000), ak vieš robiť logický súčin
{
value = value - "0xFFFFFFFF" + 1;
}
}
else if (l === 1)
{
value = response[0];
if(value >= (2**15)) // ak je MSB bit nastavený, eventuálne sa dá použiť aj (value & 0x8000), ak vieš robiť logický súčin
{
value = value - "0xFFFF" + 1;
}
}
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;
Object.keys(values).map(singleValue => {
if (["Phase_1_voltage", "Phase_2_voltage", "Phase_3_voltage"].includes(singleValue))
{
let l = singleValue.split("_");
let phase = parseInt(l[1]);
if(FLOW.OMS_no_voltage == undefined) FLOW.OMS_no_voltage = new Set();
// console.log(values[singleValue], tbName);
if(values[singleValue] == 0)
{
FLOW.OMS_no_voltage.add(phase);
sendNotification("modbus_citys: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", instanceSendTo.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}, "", instanceSendTo.tb, instance, "voltage" + phase);
}
}
})
}
// we use dataToTbHandler. Therefore we need to check, if objects we send to dido_controller are not empty
isObjectEmpty = (objectName) => {
return Object.keys(objectName).length === 0 && objectName.constructor === Object;
}
}
setTimeout(() => {
const newSocket = new SocketWithClients();
tbName = FLOW.OMS_rvo_tbname;
}, 25000);
}

View file

@ -1,220 +0,0 @@
exports.id = 'thermometer';
exports.title = 'Thermometer';
exports.group = 'Worksys';
exports.color = '#5CB36D';
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 instanceSendTo = {
debug: 0,
tb: 1,
dido_controller: 2
}
//read temperature - frequency
let timeoutMin = 5;//minutes
var path = require('path');
var log4js = require("log4js");
log4js.configure({
appenders: {
errLogs: { type: 'file', 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");
//logger.debug("text")
//monitor.info('info');
//errLogger.error("some error");
const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper');
const dbSettings = TABLE("settings");
let temperatureAddress = "";
async function loadSettings()
{
//todo global FLOW.OMS_edgeName is making problem, so we load it here as well, it should not be
let responseSettings = await promisifyBuilder(dbSettings.find());
temperatureAddress = responseSettings[0]["temperature_adress"];
}
loadSettings();
exports.install = function(instance) {
const { exec } = require('child_process');
const { sendNotification, ERRWEIGHT } = require('./helper/notification_reporter');
let startRead;
let dataToTb;
let counter = 0;
let edgeName = "";
logger.debug(exports.title, "installed");
instance.on("close", function(){
clearInterval(startRead);
})
const start = function() {
try {
if(FLOW.OMS_controller_type === "unipi")
{
clearInterval(startRead);
return;
}
if(temperatureAddress === "") throw "gettemperature: temperatureAddress is not defined";
logger.debug("FLOW.OMS_temperature_adress", FLOW.OMS_temperature_adress);
exec(`owread -C ${temperatureAddress}/temperature`, (error, stdout, stderr) => {
edgeName = FLOW.OMS_edgeName;
if(edgeName !== "")
{
if(error)
{
if(FLOW.OMS_brokerready == undefined)
{
logger.debug("gettemparature - FLOW.OMS_brokerready is undefined");
setTimeout(function(){
start();
}, 3000);
return;
}
if(FLOW.OMS_brokerready)
{
//sendNotification("start", edgeName, ERRWEIGHT.WARNING, "Thermometer is not responding", {"Error": error}, instanceSendTo.tb, instance, "thermometer");
sendNotification("start", edgeName, "thermometer_is_not_responding", {}, {"Error": error}, instanceSendTo.tb, instance, "thermometer");
}
let status = "NOK";
dataToTb = {
[edgeName]: [
{
"ts": Date.now(),
"values": {
"status": status
}
}
]
}
monitor.info("Thermometer is not responding", error, FLOW.OMS_brokerready);
// instance.send(instanceSendTo.tb, dataToTb); // poslat stav nok do tb, ak to handluje dido_controller ??
instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"});
}
else parseData(stdout);
}
else
{
monitor.info("gettemperature: edgeName is not defined", FLOW.OMS_edgeName);
setTimeout(function(){
start();
}, 3000);
return;
}
//instance.send({"Temp":stdout,"stderr":stderr,"err":error});
});
}
catch(err) {
errLogger.error(exports.title, err);
}
}
const parseData = function(data) {
data = parseFloat(data);
logger.debug("gettemperature", data);
if(!isNaN(data)) {
if(counter > 290)
{
instance.send(instanceSendTo.debug, "[Get temperature component] - temperature data are comming again from RVO after more than 1 day break");
//sendNotification("parseData", edgeName, ERRWEIGHT.NOTICE, "Thermometer is working again", "", instanceSendTo.tb, instance, "thermometer");
if(FLOW.OMS_brokerready) sendNotification("parseData", edgeName, "thermometer_is_responding_again", {}, "", instanceSendTo.tb, instance, "thermometer");
}
logger.debug("gettemperature", data);
const values = {
"temperature": Number(data.toFixed(2)),
"status": "OK"
}
dataToTb = {
[edgeName]: [
{
"ts": Date.now(),
"values":values
}
]
}
instance.send(instanceSendTo.tb, dataToTb);
instance.send(instanceSendTo.dido_controller, 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", edgeName, ERRWEIGHT.WARNING, "Thermometer receives invalid data", "", instanceSendTo.tb, instance, "thermometer");
sendNotification("parseData", edgeName, "thermometer_sends_invalid_data", {}, "", instanceSendTo.tb, instance, "thermometer");
instance.send(instanceSendTo.debug, "[Get temperature component] - no temperature data from RVO for more than 1 day");
instance.send(instanceSendTo.dido_controller, {status: "NOK-thermometer"});
}
}
}
setTimeout(function(){
start();
}, 15000);
startRead = setInterval(start, timeoutMin * 1000 * 60);
};

View file

@ -187,7 +187,7 @@ exports.install = function(instance) {
let mqtt_clientid = responseSettings[0]["mqtt_clientid"];
let mqtt_username = responseSettings[0]["mqtt_username"];
let mqtt_port = responseSettings[0]["mqtt_port"];
console.log("wsmqttpublich -> loadSettings from db", responseSettings[0]);
opts = {
@ -204,7 +204,7 @@ exports.install = function(instance) {
}
connectToTbServer();
}
}
function connectToTbServer()
{
@ -217,16 +217,16 @@ exports.install = function(instance) {
instance.status("Connected", "green");
monitor.info("MQTT broker connected");
brokerready = true;
brokerready = true;
FLOW.OMS_brokerready = brokerready;
wsmqtt_status = 'connected';
wsmqtt_status = 'connected';
});
broker.on('reconnect', function() {
instance.status("Reconnecting", "yellow");
brokerready = false;
FLOW.OMS_brokerready = brokerready;
FLOW.OMS_brokerready = brokerready;
});
broker.on('message', function(topic, message) {
@ -245,6 +245,7 @@ exports.install = function(instance) {
}
instance.send(instanceSendTo.rpcCall, {"topic":topic, "content":message });
});
broker.on('close', function(err) {

View file

@ -6,12 +6,10 @@
"dependencies": {
"bitwise": "^2.1.0",
"easy-crc": "0.0.2",
"jsmodbus": "^4.0.6",
"log4js": "^6.3.0",
"mqtt": "^4.2.6",
"nodemailer": "^6.9.7",
"serialport": "^9.2.8",
"total.js": "^3.4.13"
"total.js": "^3.4.5"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"

174
saved_data/modbus_settings Normal file
View file

@ -0,0 +1,174 @@
{
"config":{
"isRunning":false,
"debug":true,
"timeoutTime":4000,
"msgWaitTime":17000,
"port":"/dev/ttymxc0",
"port_options":"stty -F /dev/ttymxc0 9600 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke"
},
"private":{
"errBuffer":[
],
"tbBuffer":[
],
"device_index":0,
"cmd_index":0,
"devices":[
{
"name":"Elektrometer 1",
"tb_name":"",
"type":"EM340",
"address":1,
"data":[
],
"cmd":[
],
"timeoutcount":0,
"status":"virtual"
},
{
"name":"Twilight sensor",
"tb_name":"",
"type":"twilight",
"address":2,
"data":[
],
"cmd":[
],
"timeoutcount":0,
"status":"virtual"
}
],
"cmd_tables":[
{
"type":"EM340",
"cmd":[
{
"name":"Voltage L1",
"tb_name":"Phase_1_voltage",
"register":0,
"size":2,
"multiplier":0.1
},
{
"name":"Voltage L2",
"tb_name":"Phase_2_voltage",
"register":2,
"size":2,
"multiplier":0.1
},
{
"name":"Voltage L3",
"tb_name":"Phase_3_voltage",
"register":4,
"size":2,
"multiplier":0.1
},
{
"name":"Current L1",
"tb_name":"Phase_1_current",
"register":12,
"size":2,
"multiplier":0.001
},
{
"name":"Current L2",
"tb_name":"Phase_2_current",
"register":14,
"size":2,
"multiplier":0.001
},
{
"name":"Current L3",
"tb_name":"Phase_3_current",
"register":16,
"size":2,
"multiplier":0.001
},
{
"name":"Power L1",
"tb_name":"Phase_1_power",
"register":18,
"size":2,
"multiplier":0.1
},
{
"name":"Power L2",
"tb_name":"Phase_2_power",
"register":20,
"size":2,
"multiplier":0.1
},
{
"name":"Power L3",
"tb_name":"Phase_3_power",
"register":22,
"size":2,
"multiplier":0.1
},
{
"name":"Power tot",
"tb_name":"total_power",
"register":40,
"size":2,
"multiplier":0.1
},
{
"name":"Energy in",
"tb_name":"total_energy",
"register":52,
"size":2,
"multiplier":0.1
},
{
"name":"PowF L1",
"tb_name":"Phase_1_pow_factor",
"register":46,
"size":1,
"multiplier":0.001
},
{
"name":"PowF L2",
"tb_name":"Phase_2_pow_factor",
"register":47,
"size":1,
"multiplier":0.001
},
{
"name":"PowF L3",
"tb_name":"Phase_3_pow_factor",
"register":48,
"size":1,
"multiplier":0.001
},
{
"name":"PowF",
"tb_name":"power_factor",
"register":49,
"size":1,
"multiplier":0.001
}
]
},
{
"type":"twilight",
"cmd":[
{
"name":"Twilight",
"tb_name":"twilight_sensor",
"register":60,
"size":2,
"multiplier":1
}
]
}
]
}
}