Fake accelerometer and handle hasMainSwitch

This commit is contained in:
rasta5man 2025-05-06 11:58:26 +02:00
parent 5233aa38af
commit d97d90cf95
11 changed files with 3692 additions and 549 deletions

View file

@ -41,7 +41,7 @@ exports.install = function(instance) {
class SocketWithClients {
constructor () {
constructor() {
this.stream = null;
this.socket = null;
this.clients = {};
@ -55,7 +55,7 @@ exports.install = function(instance) {
this.indexInDeviceConfig = 0; // first item in deviceConfig
this.lengthOfActualDeviceStream = null;
this.device = null;
// lampSwitchNotification helper variables
this.onNotificationSent = false;
this.offNotificationSent = false;
@ -66,7 +66,7 @@ exports.install = function(instance) {
buildPhases = () => {
let a = [];
for (let i = 1; i<= phases; i++) {
for (let i = 1; i <= phases; i++) {
a.push(`Phase_${i}_voltage`)
}
return a;
@ -81,14 +81,13 @@ exports.install = function(instance) {
})
// we create a client for every deviceAddress ( = address) in list and push them into dictionary
for( let i = 0; i < deviceConfig.length; i++)
{
for (let i = 0; i < deviceConfig.length; i++) {
this.clients[deviceConfig[i].deviceAddress] = new modbus.client.RTU(this.socket, deviceConfig[i].deviceAddress, 2000); // 2000 is timeout in register request, default is 5000, which is too long
}
this.socket.on('error', function(e) {
console.log('socket connection error', e);
if(e.code == 'ECONNREFUSED' || e.code == 'ECONNRESET') {
if (e.code == 'ECONNREFUSED' || e.code == 'ECONNRESET') {
console.log(exports.title + ' Waiting 10 seconds before trying to connect again');
setTimeout(obj.startSocket, 10000);
}
@ -99,7 +98,7 @@ exports.install = function(instance) {
setTimeout(obj.startSocket, 10000);
});
this.socket.on('open', function () {
this.socket.on('open', function() {
console.log("socket connected");
obj.getActualStreamAndDevice();
obj.timeoutInterval = timeoutInterval - DELAY_BETWEEN_DEVICES; // to make sure readout always runs in timeoutinterval we substract DELAY_BETWEEN_DEVICES
@ -112,11 +111,11 @@ exports.install = function(instance) {
this.index = 0;
this.errors = 0;
this.stream = dev.stream;
this.lengthOfActualDeviceStream = dev.stream.length;
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);
if (this.indexInDeviceConfig == 0) setTimeout(this.readRegisters, this.timeoutInterval);
else setTimeout(this.readRegisters, DELAY_BETWEEN_DEVICES);
}
@ -130,21 +129,18 @@ exports.install = function(instance) {
let obj = this;
this.clients[this.deviceAddress].readHoldingRegisters(register, size)
.then( function (resp) {
.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))
{
if (numberOfNotResponding.hasOwnProperty(obj.device)) {
let message = "";
if(obj.device == "em340")
{
if (obj.device == "em340") {
message = "electrometer_ok";
}
else if(obj.device == "twilight_sensor")
{
else if (obj.device == "twilight_sensor") {
message = "twilight_sensor_ok";
}
message && sendNotification("modbus_reader: readRegisters", tbName, message, {}, "", SEND_TO.tb, instance);
@ -157,25 +153,21 @@ exports.install = function(instance) {
obj.index++;
obj.readAnotherRegister();
}).catch (function () {
}).catch(function() {
//console.log("errors pri citani modbus registra", register, obj.indexInDeviceConfig, tbName, tbAttribute);
obj.errors++;
if(obj.errors == obj.lengthOfActualDeviceStream)
{
instance.send(SEND_TO.dido_controller, {status: "NOK-" + obj.device}); // NOK-em340, NOK-em111, NOK-twilight_sensor, NOK-thermometer
if (obj.errors == obj.lengthOfActualDeviceStream) {
instance.send(SEND_TO.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))
{
if (!numberOfNotResponding.hasOwnProperty(obj.device)) {
let message = "";
if(obj.device == "twilight_sensor")
{
if (obj.device == "twilight_sensor") {
message = "twilight_sensor_nok";
}
else if(obj.device == "em340")
{
else if (obj.device == "em340") {
message = "electrometer_nok";
}
message && sendNotification("modbus_reader: readingTimeouted", tbName, message, {}, "", SEND_TO.tb, instance);
@ -183,7 +175,7 @@ exports.install = function(instance) {
}
obj.errors = 0;
numberOfNotResponding[obj.device] += 1;
numberOfNotResponding[obj.device] += 1;
}
// console.error(require('util').inspect(arguments, {
@ -191,9 +183,8 @@ exports.install = function(instance) {
// }))
// if reading out of device's last register returns error, we send accumulated allValues to dido_controller (if allValues are not an empty object)
if(obj.index + 1 >= obj.lengthOfActualDeviceStream)
{
if(!isObjectEmpty(obj.allValues)) instance.send(SEND_TO.dido_controller, {values: obj.allValues});
if (obj.index + 1 >= obj.lengthOfActualDeviceStream) {
if (!isObjectEmpty(obj.allValues)) instance.send(SEND_TO.dido_controller, { values: obj.allValues });
obj.allValues = {};
}
obj.index++;
@ -203,7 +194,7 @@ exports.install = function(instance) {
};
readAnotherRegister = () => {
if(this.index < this.lengthOfActualDeviceStream) setTimeout(this.readRegisters, 0);
if (this.index < this.lengthOfActualDeviceStream) setTimeout(this.readRegisters, 0);
else this.setNewStream();
}
@ -212,18 +203,16 @@ exports.install = function(instance) {
for (let i = 0; i < this.lengthOfActualDeviceStream; i++) {
let a = this.stream[i];
if (a.register === register)
{
if (a.register === register) {
let tbAttribute = a.tbAttribute;
let multiplier = a.multiplier;
let value = this.calculateValue(response, multiplier);
let value = this.calculateValue(response, multiplier);
// console.log(register, tbName, tbAttribute, response, a.multiplier, value);
// if(tbName == undefined) return;
if(this.index + 1 < this.lengthOfActualDeviceStream)
{
if (this.index + 1 < this.lengthOfActualDeviceStream) {
this.allValues[tbAttribute] = value;
return;
}
@ -236,52 +225,45 @@ exports.install = function(instance) {
this.checkNullVoltage(values);
this.lampSwitchNotification(values);
instance.send(SEND_TO.dido_controller, {values: values});
instance.send(SEND_TO.dido_controller, { values: values });
this.allValues = {};
break;
}
}
}
}
setNewStream = () =>
{
if(this.lengthOfActualDeviceStream == this.index)
{
if(this.indexInDeviceConfig + 1 == deviceConfig.length)
{
setNewStream = () => {
if (this.lengthOfActualDeviceStream == this.index) {
if (this.indexInDeviceConfig + 1 == deviceConfig.length) {
this.indexInDeviceConfig = 0;
}
else
{
}
else {
this.indexInDeviceConfig += 1;
}
this.getActualStreamAndDevice();
}
}
}
calculateValue = (response, multiplier) =>
{
calculateValue = (response, multiplier) => {
let value = 0;
let l = response.length;
if (l === 2)
{
value = (response[1]*(2**16) + response[0]);
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;
}
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)
{
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
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;
value = value - "0xFFFF" + 1;
}
}
@ -290,59 +272,54 @@ exports.install = function(instance) {
checkNullVoltage = (values) => {
if(!(values.hasOwnProperty("Phase_1_voltage") || values.hasOwnProperty("Phase_2_voltage") || values.hasOwnProperty("Phase_3_voltage"))) return;
if (!(values.hasOwnProperty("Phase_1_voltage") || values.hasOwnProperty("Phase_2_voltage") || values.hasOwnProperty("Phase_3_voltage"))) return;
Object.keys(values).map(singleValue => {
if (this.phases.includes(singleValue))
{
if (this.phases.includes(singleValue)) {
let l = singleValue.split("_");
let phase = parseInt(l[1]);
// console.log(values[singleValue], tbName);
if(values[singleValue] == 0)
{
if (values[singleValue] == 0) {
noVoltage.add(phase);
sendNotification("modbus_reader: 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
{
else {
noVoltage.delete(phase);
// console.log('voltage detected')
sendNotification("modbus_reader: 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 numberOfNodes*15. This should show, that RVO lamps has been switched on or off
*/
*/
lampSwitchNotification = (values) => {
if(!values.hasOwnProperty("total_power")) return;
if (!values.hasOwnProperty("total_power")) return;
const actualTotalPower = values.total_power;
const numberOfNodes = Object.keys(FLOW.GLOBALS.nodesData).length;
if(numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300
if(actualTotalPower > numberOfNodes * 15 && this.onNotificationSent == false)
{
if (numberOfNodes == 0) numberOfNodes = 20; // to make sure, we send notification if totalPower is more than 300
if (actualTotalPower > numberOfNodes * 15 && 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 <= numberOfNodes * 15 && this.offNotificationSent == false)
{
}
else if (actualTotalPower <= numberOfNodes * 15 && 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) => {
return Object.keys(objectName).length === 0 && objectName.constructor === Object;
@ -355,6 +332,8 @@ exports.install = function(instance) {
noVoltage = FLOW.GLOBALS.settings.no_voltage;
mainSocket = new SocketWithClients();
console.log("novoltage: ", noVoltage, typeof noVoltage);
// this notification is to show, that flow (unipi) has been restarted
sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance);
}