2024-05-07 16:28:43 +02:00
exports . id = 'dido_controller' ;
exports . title = 'DIDO_Controller' ;
exports . version = '2.0.0' ;
exports . group = 'Worksys' ;
exports . color = '#2134B0' ;
2024-12-02 16:57:26 +01:00
exports . input = 3 ;
exports . output = [ "red" , "white" , "yellow" , "green" ] ;
2024-05-07 16:28:43 +02:00
exports . click = false ;
exports . icon = 'bolt' ;
exports . options = { edge : "undefined" } ;
exports . html = ` <div class="padding">
2024-09-09 12:32:34 +02:00
< 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 < / d i v >
< / d i v >
< / d i v >
2024-05-07 16:28:43 +02:00
< / d i v > ` ;
exports . readme = ` # Sets RS232 port and all digital pins on device. Then it starts to receive data from sensors.
It receives :
rotary _switch _state ,
rotary _switch _state ,
door _condition ,
state _of _breaker ,
state _of _contactor ,
twilight _sensor
` ;
/ *
we open rsPort "/dev/ttymxc0" and set digital input and output pins with "setRSPortData"
Currently we are interested in pins no . 1 , 2 , 3 , 6 , 8 , 9 , 10 , 16
pins number 11 , 12 , 13 ( we receive 10 , 11 , 12 in rsPortReceivedData ) are "stykace"
When port receives data , it must be exactly 4 bytes long . Second byte is pin , that changed its value , fourth byte is value itself .
After that , we set this value to "previousValues[allPins[whichpin]]" variable
* /
/ *
RVO objekt :
2025-01-13 15:39:53 +01:00
state _of _main _switch - reportovať stav hlavného ističa : 0 - > off 1 - > on
2024-05-07 16:28:43 +02:00
rotary _switch _state - sem by sa mal reportovať stav vstupov manual a auto podľa nasledovnej logiky :
Manual = 1 a Auto = 0 - > vyreportuje Manual
Manual = 0 a Auto = 0 - > vyreportuje Off
Manual = 0 a Auto = 1 - > vyreportuje Automatic
2025-01-13 15:39:53 +01:00
door _condition - pin 6 , dverový kontakt - > 1 - > vyreportuje Closed , 0 - > vyreportuje Open
2024-05-07 16:28:43 +02:00
twilight _sensor - hodnotu , ktorú vracia ten analógový vstup ( 17 ) treba poslať sem ako float number . Zrejme tu potom pridáme nejaký koeficient prevodu na luxy
Na každú líniu :
state _of _breaker - podľa indexu ističa sa reportuje jeho stav , teda istič 1 na líniu 1 : 0 - > off 1 - > on
state _of _contactor - podľa indexu stykača sa reportuje jeho stav , teda stykač 1 na líniu 1 : 0 - > off 1 - > on
* /
2024-12-02 16:57:26 +01:00
const { errLogger , logger , monitor } = require ( './helper/logger' ) ;
const SerialPort = require ( 'serialport' ) ;
const WebSocket = require ( 'ws' ) ;
//const { exec } = require('child_process');
const { runSyncExec } = require ( './helper/serialport_helper' ) ;
const { bytesToInt , resizeArray } = require ( './helper/utils' ) ;
const { sendNotification } = require ( './helper/notification_reporter' ) ;
const bitwise = require ( 'bitwise' ) ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
const DataToTbHandler = require ( './helper/DataToTbHandler' ) ;
let tbHandler ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
const ErrorToServiceHandler = require ( './helper/ErrorToServiceHandler' ) ;
const errorHandler = new ErrorToServiceHandler ( ) ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
let ws = null ;
let rsPort = null ;
let pinsData ;
let relaysData ;
let rvoTbName ;
let GLOBALS ; //FLOW global GLOBALS
let SETTINGS ; // GLOBALS.settings
let controller _type ;
2024-05-07 16:28:43 +02:00
let alarmStatus = "OFF" ;
2024-09-09 12:32:34 +02:00
const SEND _TO = {
2024-05-07 16:28:43 +02:00
debug : 0 ,
tb : 1 ,
cmd _manager : 2
}
exports . install = function ( instance ) {
2025-01-09 14:55:53 +01:00
process . on ( 'uncaughtException' , function ( err ) {
2024-05-07 16:28:43 +02:00
//TODO send to service
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
errLogger . error ( 'uncaughtException:' , err . message )
errLogger . error ( err . stack ) ;
errorHandler . sendMessageToService ( err . message + "\n" + err . stack , 0 , "js_error" ) ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
//process.exit(1);
} )
2024-12-02 17:06:49 +01:00
let previousValues = { } ;
2024-05-07 16:28:43 +02:00
let rsPortReceivedData = [ ] ;
2024-09-17 08:54:32 +02:00
//to be able to get proper twilight values, when
2024-05-07 16:28:43 +02:00
let twilight _sensor _interval = 5 ; //minutes
let twilight _sensor = [ ] ;
const twilight _sensor _array = [ ] ;
let twilightError = false ;
2024-09-17 08:54:32 +02:00
monitor . info ( "DIDO_Relay_Controller installed" ) ;
2024-05-07 16:28:43 +02:00
//key is PIN number , line: 0 = RVO
/ *
let conversionTable = {
"1" : { tbname : "" , type : "state_of_main_switch" , "line" : 0 } , //state_of_main_switch pin1
2024-09-09 12:32:34 +02:00
"2" : { tbname : "" , type : "rotary_switch_state" , "line" : 0 } , //rotary_switch_state - poloha manual = pin2
2024-05-07 16:28:43 +02:00
"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 } ,
"6" : { tbname : "" , type : "door_condition" , "line" : 0 } , // door_condition = pin6, 1 -> vyreportuje Closed, 0 -> vyreportuje Open
"8" : { tbname : "" , type : "state_of_breaker" , "line" : 1 } , // state_of_breaker linia 1 0=off, 1=on
"9" : { tbname : "" , type : "state_of_breaker" , "line" : 2 } , // state_of_breaker linia 2 0=off, 1=on
"10" : { tbname : "" , type : "state_of_breaker" , "line" : 3 } , // state_of_breaker linia 3 0=off, 1=on
"11" : { tbname : "" , type : "state_of_contactor" , "line" : 1 } , // state_of_contactor linia 1 0=off, 1=on
"12" : { tbname : "" , type : "state_of_contactor" , "line" : 2 } , // state_of_contactor linia 2 0=off, 1=on
"13" : { tbname : "" , type : "state_of_contactor" , "line" : 3 } , // state_of_contactor linia 3 0=off, 1=on
"16" : { tbname : "" , type : "twilight_sensor" , "line" : 0 } , // twilight_sensor = pin16
} ;
* /
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
//status for calculating Statecodes
2024-09-22 22:18:46 +02:00
let deviceStatus = { //key is device name: temperature,....
"state_of_main_switch" : "Off" , //Hlavný istič
"rotary_switch_state" : "Off" , //Prevádzkový mód
"door_condition" : "closed" , //Dverový kontakt
"em" : "OK" , //elektromer rvo
"temperature" : "OK" , //templomer
"battery" : "OK" , //Batéria
"power_supply" : "OK" , //Zdroj
2024-12-02 16:57:26 +01:00
"master_node" : "OK" , //MN - GLOBALS.settings.masterNodeIsResponding
"no_voltage" : "OK" , //GLOBALS.settings.no_voltage - výpadok napätia na fáze
2024-09-22 22:18:46 +02:00
"state_of_breaker" : { } , //"Off",//Istič
"state_of_contactor" : { } , //"Off",//Stykač
"twilight_sensor" : "OK" //lux sensor
} ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
function main ( ) {
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
GLOBALS = FLOW . GLOBALS ;
SETTINGS = FLOW . GLOBALS . settings ;
rvoTbName = SETTINGS . rvoTbName ;
pinsData = GLOBALS . pinsData ;
relaysData = GLOBALS . relaysData ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
tbHandler = new DataToTbHandler ( SEND _TO . tb )
tbHandler . setSender ( exports . title ) ;
2024-09-17 08:54:32 +02:00
2024-12-02 16:57:26 +01:00
controller _type = SETTINGS . controller _type //"lm" or "unipi" //logicMachine
2025-01-09 14:55:53 +01:00
if ( controller _type == "" ) controller _type = "lm" ;
2024-10-02 18:21:31 +02:00
2024-12-02 16:57:26 +01:00
console . log ( exports . title , "controller type: " , controller _type ) ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
if ( controller _type === "lm" ) {
2024-05-07 16:28:43 +02:00
handleRsPort ( ) ;
}
2025-01-09 14:55:53 +01:00
else if ( controller _type === "unipi" ) {
2024-05-07 16:28:43 +02:00
handleWebSocket ( ) ;
}
else {
errLogger . debug ( "UNKNOWN controller_type:" , controller _type ) ;
}
2024-12-02 16:57:26 +01:00
}
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
function initialSetting ( ) {
2024-12-02 16:57:26 +01:00
//force turn off relays
2024-05-07 16:28:43 +02:00
let keys = Object . keys ( pinsData ) ;
2025-01-09 14:55:53 +01:00
for ( let i = 0 ; i < keys . length ; i ++ ) {
2024-05-07 16:28:43 +02:00
let key = keys [ i ] ;
2025-01-09 14:55:53 +01:00
let line = pinsData [ key ] . line ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
if ( line != undefined ) {
if ( relaysData [ line ] != undefined ) {
2024-05-07 16:28:43 +02:00
pinsData [ key ] . tbname = relaysData [ line ] . tbname ;
2024-12-02 16:57:26 +01:00
//relaysData[line].contactor = 0;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
errLogger . error ( "CRITICAL!!! undefined relay" , relaysData [ line ] , line ) ;
2025-01-09 14:55:53 +01:00
sendNotification ( "set port " , rvoTbName , "local_database_is_corrupted" , { } , "" , SEND _TO . tb , instance ) ;
2024-05-07 16:28:43 +02:00
}
}
2025-01-09 14:55:53 +01:00
if ( pinsData [ key ] . type == "state_of_contactor" ) {
2024-05-07 16:28:43 +02:00
let pin = key - 1 ;
2025-01-09 14:55:53 +01:00
if ( controller _type === "unipi" ) pin = key ;
2024-05-07 16:28:43 +02:00
//this will modify database
let forceTurnOff = true ;
2024-12-02 16:57:26 +01:00
turnLine ( "off" , line , pin , forceTurnOff , "turn off on startup" ) ;
2024-05-07 16:28:43 +02:00
}
}
//report RVO version relaysData[0].tbname;
let values = { } ;
2024-12-02 16:57:26 +01:00
values [ "edge_fw_version" ] = SETTINGS . edge _fw _version ;
values [ "maintenance_mode" ] = SETTINGS . maintenance _mode ;
2024-09-09 12:32:34 +02:00
2024-12-02 16:57:26 +01:00
sendTelemetry ( values , rvoTbName ) ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
let time = 5 * 1000 ;
setTimeout ( function ( ) {
instance . send ( SEND _TO . cmd _manager , { sender : "dido_controller" , cmd : "buildTasks" } ) ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
sendNotification ( "rsPort.open()" , rvoTbName , "flow_start" , { } , "" , SEND _TO . tb , instance ) ;
monitor . info ( "-->FLOW bol spustený" , rvoTbName , SETTINGS . edge _fw _version ) ;
2024-05-07 16:28:43 +02:00
} , time ) ;
}
2025-01-09 14:55:53 +01:00
function handleRsPort ( ) {
2024-05-07 16:28:43 +02:00
//TODO build according to pins!!!
//! rsPort to open are the same for lm and unipi and electromer ("/dev/ttymxc0")
2025-01-09 14:55:53 +01:00
const setRSPortData = [ 0xAA , 6 , 6 , 6 , 6 , 6 , 6 , 0 , 6 , 6 , 6 , 1 , 1 , 1 , 1 , 0 , 0 , 10 , 10 , 10 , 10 , 10 , 10 , 0 , 10 , 10 , 10 , 0 , 0 , 0 , 0 , 0 , 0 , 5 , 0 , 0 , 0 , 15 , 15 , 15 , 15 , 15 , 15 , 0 , 15 , 15 , 15 , 0 , 0 , 0 , 0 , 0 , 0 , 30 , 0 , 0 , 0 ] ;
2024-05-07 16:28:43 +02:00
rsPort = new SerialPort ( "/dev/ttymxc0" , { autoOpen : false } ) ;
rsPort . on ( 'error' , function ( err ) {
logger . debug ( "rsPort opened error - failed" , err . message ) ;
2024-09-09 12:32:34 +02:00
instance . send ( SEND _TO . debug , err . message ) ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
errorHandler . sendMessageToService ( exports . title + " rsPort opened error - failed: " + err . message ) ;
2024-05-07 16:28:43 +02:00
} )
rsPort . on ( 'open' , async function ( ) {
2025-01-09 14:55:53 +01:00
await runSyncExec ( "stty -F /dev/ttymxc0 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke" ) . then ( function ( status ) {
2024-05-07 16:28:43 +02:00
//set port
rsPort . write ( Buffer . from ( setRSPortData ) , function ( err ) {
2025-01-09 14:55:53 +01:00
if ( ! err ) {
2024-12-02 16:57:26 +01:00
monitor . info ( exports . title + "--->Digital in_out has been set (runSyncExec was sucessfull)" ) ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
turnAlarm ( "off" ) ;
initialSetting ( ) ;
}
2024-05-07 16:28:43 +02:00
} )
2024-12-02 16:57:26 +01:00
} ) . catch ( function ( reason ) {
errLogger . error ( exports . title + " runSyncExec - promise rejected:" + reason ) ;
errorHandler . sendMessageToService ( exports . title + " runSyncExec - promise rejected:" + reason ) ;
2024-05-07 16:28:43 +02:00
} ) ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
} ) ;
2025-01-09 14:55:53 +01:00
2024-12-02 16:57:26 +01:00
rsPort . on ( 'data' , function ( data ) {
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
rsPortReceivedData = [ ... rsPortReceivedData , ... data ] ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
if ( rsPortReceivedData [ 0 ] != 85 ) {
rsPortReceivedData = [ ] ;
return ;
}
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
let l = rsPortReceivedData . length ;
2025-01-09 14:55:53 +01:00
if ( l < 4 ) return ;
if ( l > 4 ) {
2024-05-07 16:28:43 +02:00
// if array length is greater than 4, we take first 4 byte and do the logic, second 4 bytes, do the logic and so on
let i , j , temparray , chunk = 4 ;
2025-01-09 14:55:53 +01:00
for ( i = 0 , j = l ; i < j ; i += chunk ) {
temparray = rsPortReceivedData . slice ( i , i + chunk ) ;
if ( temparray . length < 4 ) {
rsPortReceivedData = [ ... temparray ] ;
return ;
}
switchLogic ( temparray ) ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
rsPortReceivedData = [ ] ;
return ;
}
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
switchLogic ( rsPortReceivedData ) ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
rsPortReceivedData = [ ] ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
} ) ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
rsPort . on ( "close" , ( ) => {
rsPort . close ( ) ;
} )
rsPort . open ( ) ;
}
function handleWebSocket ( ) {
//to keep websocket opened, we send request every 150 seconds
let startRequests = null ;
console . log ( "handleWebSocket function called" ) ;
ws = new WebSocket ( 'ws:/0.0.0.0:1234/ws' ) ;
ws . onopen = function open ( ) {
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
instance . send ( 0 , exports . title + " running" ) ;
2024-12-02 16:57:26 +01:00
turnAlarm ( "off" ) ;
2024-05-07 16:28:43 +02:00
initialSetting ( ) ;
2025-01-09 14:55:53 +01:00
ws . send ( JSON . stringify ( { "cmd" : "all" } ) ) ;
2024-05-07 16:28:43 +02:00
// we request dev info about neuron device from evok to keep websocket connection alive
// for some reason this request returns no data, but connection keeps alive
startRequests = setInterval ( ( ) => {
2025-01-09 14:55:53 +01:00
ws . send ( JSON . stringify ( { "cmd" : "filter" , "dev" : [ "neuron" ] } ) ) ;
2024-05-07 16:28:43 +02:00
} , 150000 )
} ;
2024-09-17 08:54:32 +02:00
2025-01-09 14:55:53 +01:00
// SAMPLE DATA FROM WEBSOCKET
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_07',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// modes: [ 'Simple', 'DirectSwitch' ],
// value: 0,
// circuit: '1_08',
// debounce: 50,
// counter: 0,
// counter_mode: 'Enabled',
// dev: 'input',
// mode: 'Simple'
// },
2024-09-22 22:18:46 +02:00
ws . onmessage = async function ( data ) {
2024-05-07 16:28:43 +02:00
data = JSON . parse ( data . data ) ;
// data comes in array except of "temperature" ==> it comes as an object
2024-12-02 17:06:49 +01:00
// we do not handle temperature from evok any more => we return, if temperature comes:
2025-01-09 14:55:53 +01:00
if ( isObject ( data ) ) return ;
2024-05-07 16:28:43 +02:00
data . map ( item => {
2024-12-02 17:06:49 +01:00
2024-05-07 16:28:43 +02:00
let value = item [ 'value' ] ;
let pin = item [ "dev" ] + item [ "circuit" ] ; // for example "relay1_03" or "input1_01"
2025-01-09 14:55:53 +01:00
if ( pin == undefined ) return ;
2024-05-07 16:28:43 +02:00
switchLogic ( pin , value ) ;
} )
}
2024-12-02 17:06:49 +01:00
2024-05-07 16:28:43 +02:00
ws . on ( 'error' , ( err ) => {
2024-05-14 16:29:11 +02:00
monitor . info ( 'websocket error, reconnect' )
2024-09-09 12:32:34 +02:00
instance . send ( SEND _TO . debug , err . message ) ;
2024-05-07 16:28:43 +02:00
clearInterval ( startRequests ) ;
2024-05-14 16:29:11 +02:00
ws = null ;
setTimeout ( handleWebSocket , 1000 ) ;
2024-05-07 16:28:43 +02:00
} )
2025-01-09 14:55:53 +01:00
ws . onclose = function ( ) {
2024-05-07 16:28:43 +02:00
// connection closed, discard old websocket and create a new one in 5s
// stopRequests();
2024-05-14 16:29:11 +02:00
monitor . info ( 'websocket onclose, reconnect' )
2024-05-07 16:28:43 +02:00
clearInterval ( startRequests ) ;
ws = null ;
console . log ( "ws is null now, reconnecting..." ) ;
setTimeout ( handleWebSocket , 1000 ) ;
}
}
instance . on ( "close" , ( ) => {
2025-01-09 14:55:53 +01:00
if ( rsPort ) rsPort . close ( ) ;
if ( ws ) ws . close ( ) ;
2024-05-07 16:28:43 +02:00
} )
2024-09-17 08:54:32 +02:00
2025-01-09 14:55:53 +01:00
function getPin ( line ) {
2024-12-02 16:57:26 +01:00
//conversionTable
let keys = Object . keys ( pinsData ) ;
2025-01-09 14:55:53 +01:00
for ( let i = 0 ; i < keys . length ; i ++ ) {
2024-12-02 16:57:26 +01:00
let key = keys [ i ] ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
if ( pinsData [ key ] . type == "state_of_contactor" && pinsData [ key ] . line == line ) {
if ( rsPort ) return key - 1 ;
if ( ws ) return key ;
2024-05-07 16:28:43 +02:00
}
2024-12-02 16:57:26 +01:00
}
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
logger . debug ( "no pin detected" ) ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
return null ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
function turnAlarm ( onOrOff ) {
2024-12-02 16:57:26 +01:00
let value = 0 ;
2025-01-09 14:55:53 +01:00
if ( onOrOff == "on" ) value = 1 ;
2024-12-02 17:06:49 +01:00
2025-01-09 14:55:53 +01:00
if ( value == 1 && SETTINGS . maintenance _mode ) return ;
2024-05-07 16:28:43 +02:00
alarmStatus = "OFF" ;
2025-01-09 14:55:53 +01:00
if ( value == 1 ) alarmStatus = "ON" ;
2024-12-02 17:06:49 +01:00
2025-01-09 14:55:53 +01:00
if ( rsPort ) {
2024-05-07 16:28:43 +02:00
let arr = [ 0x55 ] ;
2024-12-02 16:57:26 +01:00
arr . push ( 13 ) ;
arr . push ( 0 ) ;
arr . push ( value ) ;
2024-12-02 17:06:49 +01:00
2024-05-07 16:28:43 +02:00
rsPort . write ( Buffer . from ( arr ) , function ( err ) {
2024-12-02 16:57:26 +01:00
logger . debug ( ` sirena - ${ onOrOff } ` ) ;
2024-05-07 16:28:43 +02:00
} ) ;
}
2025-01-09 14:55:53 +01:00
else if ( ws ) {
let cmd = { "cmd" : "set" , "dev" : "relay" , "circuit" : "1_01" , "value" : value } ;
2024-05-07 16:28:43 +02:00
ws . send ( JSON . stringify ( cmd ) ) ;
2024-12-02 16:57:26 +01:00
logger . debug ( ` sirena - ${ onOrOff } ` ) ;
2024-05-07 16:28:43 +02:00
}
}
2025-01-09 14:55:53 +01:00
function reportLineStatus ( line ) {
2024-05-07 16:28:43 +02:00
//Tá hodnota by mala fungovať tak že LSB bit číslo je stav ističa (1 - On, 0 - Off) a druhý bit je stav stýkača (1 - true, 0 - false).
let tbname = relaysData [ line ] . tbname ;
let bits = [ ] ;
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "state_of_breaker" ] [ line ] == "On" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
else bits . push ( 1 ) ;
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "state_of_contactor" ] [ line ] == "On" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
else bits . push ( 1 ) ;
resizeArray ( bits , 8 , 0 ) ;
let byte = bitwise . byte . write ( bits . reverse ( ) ) ;
//console.log("line", line, bits, byte);
2025-01-09 14:55:53 +01:00
sendTelemetry ( { statecode : byte } , tbname ) ;
2024-05-07 16:28:43 +02:00
}
2024-12-02 16:57:26 +01:00
// turn line on or off
2025-01-09 14:55:53 +01:00
function turnLine ( onOrOff , line , pin , force , info ) {
2024-12-02 16:57:26 +01:00
//onOrOff => "on" or "off"
let value = 0 ;
2025-01-09 14:55:53 +01:00
if ( onOrOff == "on" ) value = 1 ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
if ( force == undefined ) force = false ;
if ( line == 0 ) {
if ( value == 1 && alarmStatus == "ON" ) turnAlarm ( "off" ) ;
SETTINGS . maintenance _mode = value ? true : false ;
2024-05-07 16:28:43 +02:00
let values = { } ;
values [ "statecode" ] = calculateStateCode ( ) ;
2025-01-09 14:55:53 +01:00
values [ "power_mode" ] = value ? "maintenance" : "Automatic" ;
2024-12-02 16:57:26 +01:00
sendTelemetry ( values , rvoTbName ) ;
2025-01-09 14:55:53 +01:00
2024-12-02 16:57:26 +01:00
monitor . info ( ` turnLine ${ onOrOff } - (line, SETTINGS.maintenance_mode) ` , line , SETTINGS . maintenance _mode , info ) ;
2024-05-07 16:28:43 +02:00
return ;
}
2025-01-09 14:55:53 +01:00
if ( pin === undefined ) pin = getPin ( line ) ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
if ( pin === undefined ) {
2024-05-07 16:28:43 +02:00
errLogger . error ( "pin is undefined!" , line ) ;
return ;
}
2025-01-09 14:55:53 +01:00
if ( ! force ) {
if ( relaysData [ line ] . contactor == value ) {
instance . send ( SEND _TO . debug , ` line is already ${ onOrOff } ` + line ) ;
2024-12-02 16:57:26 +01:00
logger . debug ( ` turnLine: line is already ${ onOrOff } ` , line ) ;
2024-05-07 16:28:43 +02:00
return ;
}
}
// if(!rsPort.isOpen && !ws)
2025-01-09 14:55:53 +01:00
if ( ! rsPort && ! ws ) {
2024-09-17 08:54:32 +02:00
errLogger . error ( "dido controller - port or websocket is not opened" ) ;
2024-05-07 16:28:43 +02:00
return ;
}
2025-01-09 14:55:53 +01:00
if ( rsPort ) {
2024-05-07 16:28:43 +02:00
let arr = [ 0x55 ] ;
2024-12-02 16:57:26 +01:00
arr . push ( pin ) ;
arr . push ( 0 ) ;
arr . push ( value ) ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
rsPort . write ( Buffer . from ( arr ) , function ( err ) {
2025-01-09 14:55:53 +01:00
if ( err === undefined ) {
2024-12-02 16:57:26 +01:00
monitor . info ( ` turnLine ${ onOrOff } zapisal do rsPort-u ` , line , pin , arr , info ) ;
2024-05-07 16:28:43 +02:00
switchLogic ( arr ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-12-02 16:57:26 +01:00
monitor . info ( ` turnLine ${ onOrOff } WRITE error ` , err ) ;
2025-01-09 14:55:53 +01:00
}
2024-05-07 16:28:43 +02:00
} ) ;
}
2025-01-09 14:55:53 +01:00
else if ( ws ) {
2024-05-07 16:28:43 +02:00
//pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method
2024-12-02 16:57:26 +01:00
monitor . info ( ` turnLine ${ onOrOff } - (line, pin, force) ` , line , pin , force , info ) ;
2025-01-09 14:55:53 +01:00
let cmd = { "cmd" : "set" , "dev" : "relay" , "circuit" : pin . slice ( 5 ) , "value" : value } ;
2024-05-07 16:28:43 +02:00
ws . send ( JSON . stringify ( cmd ) ) ;
2024-12-02 16:57:26 +01:00
switchLogic ( pin , value )
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
2025-01-01 13:12:02 +01:00
//if rvo is 24/7, it has just one switching profile point at 13:00. we do not want to send notification as it repeats every day.
2025-01-09 14:55:53 +01:00
//const d = new Date();
//if(d.getHours() != 13) sendNotification("Dido_controller: ", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: line, value: onOrOff }, "", SEND_TO.tb, instance);
2024-05-07 16:28:43 +02:00
}
2024-12-02 16:57:26 +01:00
// main opening
instance . on ( "2" , _ => {
main ( ) ;
} )
2024-05-07 16:28:43 +02:00
//data from modbus_reader or temperature sensor or twilight sensor or other modbus device
instance . on ( "0" , flowdata => {
2025-01-09 14:55:53 +01:00
if ( ! isObject ( flowdata . data ) ) return ;
2024-05-07 16:28:43 +02:00
// console.log('***********************', flowdata.data)
2024-09-09 12:32:34 +02:00
instance . send ( SEND _TO . debug , flowdata . data ) ;
2024-05-07 16:28:43 +02:00
// we handle nok status from modbus_reader component and thermometer
2025-01-09 14:55:53 +01:00
if ( "status" in flowdata . data ) {
2024-05-07 16:28:43 +02:00
const status = flowdata . data . status ;
2025-01-09 14:55:53 +01:00
if ( status == "NOK-twilight_sensor" ) {
2024-09-17 08:54:32 +02:00
deviceStatus [ "twilight_sensor" ] = "NOK" ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
else if ( status == "NOK-em340" || status == "NOK-em111" ) {
2024-09-17 08:54:32 +02:00
deviceStatus [ "em" ] = "NOK" ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
else if ( status == "NOK-thermometer" ) {
2024-09-17 08:54:32 +02:00
deviceStatus [ "temperature" ] = "NOK" ;
2024-05-07 16:28:43 +02:00
}
}
2025-01-09 14:55:53 +01:00
else if ( "values" in flowdata . data ) {
2024-09-09 12:32:34 +02:00
const values = flowdata . data . values ;
2025-01-09 14:55:53 +01:00
if ( values . hasOwnProperty ( "twilight_sensor" ) ) {
instance . send ( SEND _TO . cmd _manager , { sender : "dido_controller" , cmd : "lux_sensor" , value : values [ "twilight_sensor" ] } ) ;
2024-09-17 08:54:32 +02:00
deviceStatus [ "twilight_sensor" ] = "OK"
2024-09-09 12:32:34 +02:00
}
2025-01-09 14:55:53 +01:00
else if ( values . hasOwnProperty ( "temperature" ) ) {
2024-09-17 08:54:32 +02:00
deviceStatus [ "temperature" ] = "OK" ;
2024-09-09 12:32:34 +02:00
}
// EM
2025-01-09 14:55:53 +01:00
else if ( values . hasOwnProperty ( "total_power" ) || values . hasOwnProperty ( "total_energy" ) || values . hasOwnProperty ( "power_factor" ) || values . hasOwnProperty ( "Phase_1_voltage" ) || values . hasOwnProperty ( "Phase_1_current" ) ) {
2024-09-17 08:54:32 +02:00
deviceStatus [ "em" ] = "OK" ;
2025-01-09 14:55:53 +01:00
SETTINGS . no _voltage . size > 0 ? deviceStatus [ "no_voltage" ] = "NOK" : deviceStatus [ "no_voltage" ] = "OK" ;
2024-09-09 12:32:34 +02:00
}
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
sendTelemetry ( values , rvoTbName ) ;
2024-09-09 12:32:34 +02:00
}
2024-05-07 16:28:43 +02:00
2024-09-22 22:18:46 +02:00
sendRvoStatus ( ) ;
2024-05-07 16:28:43 +02:00
} )
// we expect array as flowdata.data
instance . on ( "1" , flowdata => {
console . log ( flowdata . data ) ;
2025-01-09 14:55:53 +01:00
if ( ! flowdata . data instanceof Object ) return ;
2024-05-07 16:28:43 +02:00
let obj = flowdata . data ;
let line = obj . line ;
let force = obj . force ;
let info = obj . info ;
2025-01-09 14:55:53 +01:00
if ( obj . command == "on" ) turnLine ( "on" , line , undefined , force , info ) ;
else if ( obj . command == "off" ) turnLine ( "off" , line , undefined , force , info ) ;
else if ( obj . command == "turnOnAlarm" ) turnAlarm ( "on" ) ;
else if ( obj . command == "turnOffAlarm" ) turnAlarm ( "off" ) ;
2024-05-07 16:28:43 +02:00
//! ake data prichadzaju z cmd_manager.js ???
//TODO transform to websocket
2025-01-09 14:55:53 +01:00
if ( Array . isArray ( obj ) ) {
2024-05-07 16:28:43 +02:00
rsPort . write ( Buffer . from ( obj ) , function ( err ) {
switchLogic ( obj ) ;
2025-01-09 14:55:53 +01:00
instance . send ( SEND _TO . debug , { "WRITE" : obj } ) ;
2024-05-07 16:28:43 +02:00
} ) ;
2025-01-09 14:55:53 +01:00
}
2024-05-07 16:28:43 +02:00
} )
2025-01-09 14:55:53 +01:00
function calculateStateCode ( ) {
2024-05-07 16:28:43 +02:00
let bits = [ ] ;
2024-12-02 16:57:26 +01:00
//Hlavný istič - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM)
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "state_of_main_switch" ] == "closed" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
//Prevádzkový mód - Manual, Off, Automatic, maintenance_mode = true/false // DAVA 2 BITY
2025-01-09 14:55:53 +01:00
if ( ! SETTINGS . maintenance _mode ) {
if ( deviceStatus [ "rotary_switch_state" ] == "Manual" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
bits . push ( 1 ) ;
}
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "rotary_switch_state" ] == "Automatic" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
bits . push ( 0 ) ;
}
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "rotary_switch_state" ] == "Off" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
bits . push ( 0 ) ;
}
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
bits . push ( 1 ) ;
}
//Dverový kontakt
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "door_condition" ] == "closed" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
//EM
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "em" ] == "NOK" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
//Teplomer
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "temperature" ] == "NOK" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
//Batéria
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "battery" ] == "NOK" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
//Zdroj
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "power_supply" ] == "NOK" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
//MN
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "master_node" ] == "NOK" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
//výpadok napätia na fáze
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "no_voltage" ] == "NOK" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
2025-01-09 14:55:53 +01:00
if ( deviceStatus [ "twilight_sensor" ] == "NOK" ) {
2024-05-07 16:28:43 +02:00
bits . push ( 1 ) ;
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
// doplnime do 16 bitov (2 byty)
2025-01-09 14:55:53 +01:00
for ( let i = bits . length ; i < 16 ; i ++ ) {
2024-05-07 16:28:43 +02:00
bits . push ( 0 ) ;
}
2025-01-09 14:55:53 +01:00
2024-09-17 08:54:32 +02:00
// console.log("calculateStateCode - deviceStatus", deviceStatus);
2024-05-07 16:28:43 +02:00
// console.log("calculateStateCode", bits);
2025-01-09 14:55:53 +01:00
let byte0 = bitwise . byte . write ( bits . slice ( 0 , 8 ) . reverse ( ) ) ;
2024-05-07 16:28:43 +02:00
let byte1 = bitwise . byte . write ( bits . slice ( 8 ) . reverse ( ) ) ;
let byte = bytesToInt ( [ byte1 , byte0 ] ) ;
//console.log("calculateStateCode -------------------", byte);
2024-12-02 17:06:49 +01:00
2024-05-07 16:28:43 +02:00
return byte ;
}
2024-09-22 22:18:46 +02:00
async function sendRvoStatus ( ) {
2024-09-17 08:54:32 +02:00
2025-01-09 14:55:53 +01:00
if ( SETTINGS === undefined ) return ;
2025-01-09 22:21:50 +01:00
SETTINGS . masterNodeIsResponding ? deviceStatus [ "master_node" ] = "OK" : deviceStatus [ "master_node" ] = "NOK" ;
2024-12-02 16:57:26 +01:00
2024-09-17 08:54:32 +02:00
const table = {
"OK" : 1 ,
"NOK" : 0
} ;
const dataToTb = {
"electrometer_status" : table [ deviceStatus [ "em" ] ] ,
"twilight_sensor_status" : table [ deviceStatus [ "twilight_sensor" ] ] ,
"thermometer_status" : table [ deviceStatus [ "temperature" ] ] ,
"phase_1_status" : 1 ,
"phase_2_status" : 1 ,
"phase_3_status" : 1 ,
"master_node_status" : table [ deviceStatus [ "master_node" ] ]
} ;
2024-12-02 16:57:26 +01:00
for ( const phase of SETTINGS . no _voltage ) dataToTb [ ` phase_ ${ phase } _status ` ] = 0 ;
2024-09-17 08:54:32 +02:00
2024-09-22 22:18:46 +02:00
dataToTb [ "status" ] = checkRvoStatus ( ) ;
dataToTb [ "statecode" ] = calculateStateCode ( ) ;
2024-12-02 17:06:49 +01:00
//console.log(dataToTb);
2024-12-02 16:57:26 +01:00
sendTelemetry ( dataToTb , rvoTbName ) ;
2024-09-17 08:54:32 +02:00
}
2024-09-22 22:18:46 +02:00
function checkRvoStatus ( ) {
2024-05-07 16:28:43 +02:00
// we check if any of these pins values are 0 --> it means status RVO is "NOK"
2024-09-17 08:54:32 +02:00
// pinIndex 6 is door_condition - if it is opened in maintenance mode - status = OK
2024-05-07 16:28:43 +02:00
//set RVO state
let status = "OK" ;
2024-09-22 22:18:46 +02:00
for ( const [ key , value ] of Object . entries ( deviceStatus ) ) {
2025-01-09 22:21:50 +01:00
if ( [ "em" , "twilight_sensor" , "temperature" , "master_node" ] . includes ( key ) && value == "NOK" ) status = "NOK" ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
if ( status == "OK" ) {
2024-05-07 16:28:43 +02:00
let pinIndexes = [ 1 , 4 , 6 ] ;
2025-01-09 14:55:53 +01:00
if ( controller _type == 'unipi' ) pinIndexes = [ 'input1_01' , 'input1_04' , 'input1_05' ] ;
2024-05-07 16:28:43 +02:00
for ( const pinIndex of pinIndexes ) {
if ( previousValues [ pinIndex ] === 0 ) {
2024-12-02 16:57:26 +01:00
if ( ( pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05' ) && SETTINGS . maintenance _mode ) continue ;
2024-05-07 16:28:43 +02:00
status = "NOK" ;
break ;
}
}
}
// battery status. If value is 1 - battery is NOK
2024-09-22 22:18:46 +02:00
if ( previousValues [ 5 ] === 1 ) status = "NOK" ;
2025-01-09 14:55:53 +01:00
if ( SETTINGS . no _voltage . size > 0 ) status = "NOK" ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
// console.log("rvo status",status)
2024-09-22 22:18:46 +02:00
return status ;
2024-05-07 16:28:43 +02:00
}
// 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]
const switchLogic = ( ... args ) => {
2024-09-22 22:18:46 +02:00
let values = { } ;
let pinIndex , newPinValue , twilight ;
2024-05-07 16:28:43 +02:00
//data from rsPort
2025-01-09 14:55:53 +01:00
if ( args . length == 1 ) {
2024-05-07 16:28:43 +02:00
pinIndex = args [ 0 ] [ 1 ] + 1 ;
if ( pinIndex === 17 ) pinIndex -- ;
newPinValue = args [ 0 ] [ 3 ] ;
twilight = args [ 0 ] [ 2 ] ;
}
//data from websocket
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
pinIndex = args [ 0 ] ;
newPinValue = args [ 1 ] ;
}
let obj = pinsData [ pinIndex ] ;
2025-01-09 14:55:53 +01:00
if ( obj == undefined ) {
2024-05-07 16:28:43 +02:00
previousValues [ pinIndex ] = newPinValue ;
2024-12-02 16:57:26 +01:00
//logger.debug("dido-switchLogic ==> no pinIndex", pinIndex);
2024-05-07 16:28:43 +02:00
return ;
}
2024-09-17 08:54:32 +02:00
//tbname is added to pinsData in initialSettings function
2024-05-07 16:28:43 +02:00
let type = obj . type ;
let line = obj . line ;
let tbname = obj . tbname ;
//default value
2025-01-09 14:55:53 +01:00
let value = "On" ;
if ( newPinValue === 0 ) value = "Off" ;
2024-05-07 16:28:43 +02:00
//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'
2024-09-22 22:18:46 +02:00
// if(type === "!!!state_of_main_switch")
// {
// if (newPinValue === 0 && newPinValue !== previousValues[pinIndex])
// {
2024-12-02 16:57:26 +01:00
// sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance , "state_of_main_switch");
2024-09-22 22:18:46 +02:00
// values["status"] = "NOK";
// deviceStatus["state_of_main_switch"] = "Off";
// }
// else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex])
// {
2024-12-02 16:57:26 +01:00
// sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_on", {}, "", SEND_TO.tb, instance , "state_of_main_switch");
2024-09-22 22:18:46 +02:00
// deviceStatus["state_of_main_switch"] = "On";
// }
// }
2024-05-07 16:28:43 +02:00
//Prevádzkový mód
2025-01-09 14:55:53 +01:00
if ( type == "rotary_switch_state" ) {
2024-05-07 16:28:43 +02:00
// combination of these two pins required to get result
let pin2 , pin3 ;
2025-01-09 14:55:53 +01:00
if ( pinIndex == 2 || pinIndex == "input1_02" ) {
2024-05-07 16:28:43 +02:00
pin2 = newPinValue ;
pin3 = previousValues [ 3 ] || previousValues [ "input1_03" ] ;
2025-01-09 14:55:53 +01:00
if ( pin3 == undefined ) {
2024-05-07 16:28:43 +02:00
previousValues [ pinIndex ] = newPinValue ;
return ;
2025-01-09 14:55:53 +01:00
}
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
else if ( pinIndex == 3 || pinIndex == "input1_03" ) {
2024-05-07 16:28:43 +02:00
pin3 = newPinValue ;
pin2 = previousValues [ 2 ] || previousValues [ "input1_02" ] ;
2025-01-09 14:55:53 +01:00
if ( pin2 == undefined ) {
2024-05-07 16:28:43 +02:00
previousValues [ pinIndex ] = newPinValue ;
return ;
2025-01-09 14:55:53 +01:00
}
2024-05-07 16:28:43 +02:00
}
//console.log('***********************', pin2, pin3)
if ( pin2 == 1 && pin3 == 0 ) value = "Manual" ;
if ( pin2 == 0 && pin3 == 0 ) value = "Off" ;
if ( pin2 == 0 && pin3 == 1 ) value = "Automatic" ;
2024-09-17 08:54:32 +02:00
deviceStatus [ "rotary_switch_state" ] = value ;
2024-05-07 16:28:43 +02:00
//automatic - profilu pre nody sa vykonavaju
//ak je spracovany, a automatic - tak ho zapnem
//ak nie je spracovany, iba profil zapisem
2024-09-22 22:18:46 +02:00
2025-01-09 14:55:53 +01:00
if ( pin2 != undefined && pin3 != undefined ) instance . send ( SEND _TO . cmd _manager , { sender : "dido_controller" , cmd : "rotary_switch_state" , value : value } ) ;
2024-05-07 16:28:43 +02:00
//console.log("rotary_switch_state pin", pin2, pin3, value);
}
2024-12-02 16:57:26 +01:00
2024-05-07 16:28:43 +02:00
//Zdroj - pin 4
2025-01-09 14:55:53 +01:00
else if ( type === "power_supply" ) {
if ( newPinValue === 0 && newPinValue !== previousValues [ pinIndex ] ) {
2024-12-02 16:57:26 +01:00
sendNotification ( "switchLogic" , rvoTbName , "power_supply_has_disconnected_input" , { } , "" , SEND _TO . tb , instance , "power_supply" ) ;
2024-05-07 16:28:43 +02:00
2024-09-17 08:54:32 +02:00
deviceStatus [ "power_supply" ] = "NOK" ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
else if ( newPinValue === 1 && newPinValue !== previousValues [ pinIndex ] ) {
2024-12-02 16:57:26 +01:00
sendNotification ( "switchLogic" , rvoTbName , "power_supply_works_correctly" , { } , "" , SEND _TO . tb , instance , "power_supply" ) ;
2024-05-07 16:28:43 +02:00
2024-09-17 08:54:32 +02:00
deviceStatus [ "power_supply" ] = "OK" ;
2024-05-07 16:28:43 +02:00
}
}
2024-12-02 16:57:26 +01:00
2024-05-07 16:28:43 +02:00
//Batéria - pin 5
2025-01-09 14:55:53 +01:00
else if ( type === "battery" ) {
if ( newPinValue === 1 && newPinValue !== previousValues [ pinIndex ] ) {
2024-12-02 16:57:26 +01:00
sendNotification ( "switchLogic" , rvoTbName , "battery_level_is_low" , { } , "" , SEND _TO . tb , instance , "battery_level" ) ;
2024-05-07 16:28:43 +02:00
2024-09-17 08:54:32 +02:00
deviceStatus [ "battery" ] = "NOK" ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
else if ( newPinValue === 0 && newPinValue !== previousValues [ pinIndex ] ) {
2024-12-02 16:57:26 +01:00
sendNotification ( "switchLogic" , rvoTbName , "battery_level_is_ok" , { } , "" , SEND _TO . tb , instance , "battery_level" ) ;
2024-05-07 16:28:43 +02:00
2024-09-17 08:54:32 +02:00
deviceStatus [ "battery" ] = "OK" ;
2024-05-07 16:28:43 +02:00
}
}
2024-12-02 16:57:26 +01:00
2024-05-07 16:28:43 +02:00
//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'
2025-01-09 14:55:53 +01:00
else if ( type == "door_condition" || type === "state_of_main_switch" ) {
2024-05-07 16:28:43 +02:00
newPinValue === 0 ? value = "open" : value = "closed" ;
2024-12-02 16:57:26 +01:00
2025-01-09 14:55:53 +01:00
if ( value === "open" && SETTINGS . maintenance _mode ) {
2024-12-02 16:57:26 +01:00
sendNotification ( "switchLogic" , rvoTbName , "door_opened" , { } , "" , SEND _TO . tb , instance , "rvo_door" ) ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
if ( value === "open" && ! SETTINGS . maintenance _mode ) {
2024-12-02 16:57:26 +01:00
sendNotification ( "switchLogic" , rvoTbName , "door_opened_without_permission" , { } , "" , SEND _TO . tb , instance , "rvo_door" ) ;
2024-05-07 16:28:43 +02:00
// 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")
2025-01-09 14:55:53 +01:00
if ( type === "door_condition" ) turnAlarm ( "on" ) ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
if ( value === "closed" ) {
if ( alarmStatus == "ON" ) turnAlarm ( "off" ) ;
2024-12-02 16:57:26 +01:00
sendNotification ( "switchLogic" , rvoTbName , "door_closed" , { } , "" , SEND _TO . tb , instance , "rvo_door" ) ;
2024-05-07 16:28:43 +02:00
}
2024-09-22 22:18:46 +02:00
deviceStatus [ type ] = value ;
2024-05-07 16:28:43 +02:00
}
2024-12-02 16:57:26 +01:00
2024-05-07 16:28:43 +02:00
//lux sensor
2025-01-09 14:55:53 +01:00
else if ( type == "twilight_sensor" ) {
2024-09-17 08:54:32 +02:00
//! TODO - to show nok status, if lux value is not changing more then 10 times.
2024-05-07 16:28:43 +02:00
//Daylight is far more than 1000. So most of the day, when it is sunshine comes just value 1000. But lux sensor is not NOK.
//This is not the case in LM. If value from LM is the same 10x, there is 99% possibility, that sensor is NOK.
value = newPinValue ;
2025-01-09 14:55:53 +01:00
if ( controller _type === 'lm' ) {
value = parseFloat ( newPinValue + ( 256 * twilight ) ) ;
2024-05-07 16:28:43 +02:00
let now = new Date ( ) ;
//new Date(dusk.getTime()
2025-01-09 14:55:53 +01:00
let obj = { timestamp : now . getTime ( ) , value : value } ;
2024-05-07 16:28:43 +02:00
//test
//twilight_sensor_interval = 1;
twilight _sensor . push ( obj ) ;
//twilight_sensor_array.push(value);
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
//check if we receive just 1 constant value from lux sensor ==> error
2025-01-09 14:55:53 +01:00
if ( twilight _sensor _array . length > 10 ) {
2024-05-07 16:28:43 +02:00
let set = new Set ( twilight _sensor _array ) ;
2025-01-09 14:55:53 +01:00
if ( set . size === 1 && ! twilightError ) {
2024-05-07 16:28:43 +02:00
twilightError = true ;
let value = twilight _sensor _array . shift ( ) ;
2024-12-02 16:57:26 +01:00
2024-05-07 16:28:43 +02:00
newPinValue = 0 ;
}
2025-01-09 14:55:53 +01:00
else if ( set . size !== 1 && twilightError ) {
2024-12-02 16:57:26 +01:00
//sendNotification("switchLogic", rvoTbName, ERRWEIGHT.NOTICE, "Lux sensor is working again", "", SEND_TO.tb, instance );
2024-05-07 16:28:43 +02:00
twilightError = false ;
twilight _sensor _array . shift ( ) ;
2024-12-02 16:57:26 +01:00
2024-05-07 16:28:43 +02:00
newPinValue = value ;
}
2025-01-09 14:55:53 +01:00
else if ( set . size === 1 && twilightError ) {
2024-05-07 16:28:43 +02:00
twilight _sensor _array . shift ( ) ;
newPinValue = 0 ;
}
}
2025-01-09 14:55:53 +01:00
let diff = twilight _sensor [ twilight _sensor . length - 1 ] . timestamp - twilight _sensor [ 0 ] . timestamp ;
if ( diff >= twilight _sensor _interval * 60 * 1000 ) {
2024-05-07 16:28:43 +02:00
const average = twilight _sensor . reduce ( ( acc , c ) => acc + c . value , 0 ) / twilight _sensor . length ;
2025-01-09 14:55:53 +01:00
instance . send ( SEND _TO . cmd _manager , { sender : "dido_controller" , cmd : "lux_sensor" , value : average } ) ;
2024-05-07 16:28:43 +02:00
twilight _sensor = [ ] ;
//console.log("lux_sensor send", average);
}
//else console.log("lux_sensor", value, diff);
}
}
2024-12-02 16:57:26 +01:00
2025-01-09 14:55:53 +01:00
else if ( type == "state_of_contactor" ) {
if ( ! ( deviceStatus [ "state_of_contactor" ] [ line ] == value ) ) {
sendNotification ( "switchLogic" , rvoTbName , "state_of_contactor_for_line" , { line : line , value : value } , "" , SEND _TO . tb , instance ) ;
2024-05-07 16:28:43 +02:00
}
2024-09-17 08:54:32 +02:00
deviceStatus [ "state_of_contactor" ] [ line ] = value ;
2024-05-07 16:28:43 +02:00
//true, false
2025-01-09 14:55:53 +01:00
if ( value === "On" ) value = true ;
else if ( value === "Off" ) value = false ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
//TODO do we need to modify relays table with contactor value, if we do not use it on startup ??
let dataChanged = false ;
2025-01-09 14:55:53 +01:00
if ( relaysData [ line ] . contactor !== newPinValue ) {
2024-12-02 16:57:26 +01:00
dataChanged = true ;
relaysData [ line ] . contactor = newPinValue ;
}
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
instance . send ( SEND _TO . cmd _manager , { sender : "dido_controller" , cmd : "reload_relays" , line : line , value : value , dataChanged : dataChanged } ) ;
2024-12-02 16:57:26 +01:00
reportLineStatus ( line ) ;
2024-05-07 16:28:43 +02:00
2024-12-02 16:57:26 +01:00
//modify table relays
// dbRelays.modify({ contactor: newPinValue }).where("line", line).make(function(builder) {
// builder.callback(function(err, response) {
// if(!err)
// {
// let time = 0;
// if(value) time = 1000 * 10;//10 sekund
// let dataChanged = false;
// if(relaysData[line].contactor != newPinValue) dataChanged = true;
// relaysData[line].contactor = newPinValue; // 0,1
// //ak bola predchadzajuci stav off a novy stav je on, budu sa nastavovat nespracovane node profiles
// //a budu sa odosielat commandy, tie vsak mozu zlyhat, a preto potrebujeme ich spusti trochu neskor
// setTimeout(function(){
// instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, time: time, value: value, dataChanged: dataChanged});
// }, time);
// reportLineStatus(line);
// }
// else
// {
// errLogger.error("modify table relays failed", err);
// }
// });
// });
2024-05-07 16:28:43 +02:00
}
2024-12-02 16:57:26 +01:00
2025-01-09 14:55:53 +01:00
else if ( type === "state_of_breaker" ) {
2024-05-07 16:28:43 +02:00
let valueChanged = false ;
2025-01-09 14:55:53 +01:00
if ( newPinValue != previousValues [ pinIndex ] ) valueChanged = true ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
if ( valueChanged ) {
instance . send ( SEND _TO . cmd _manager , { sender : "dido_controller" , cmd : "state_of_breaker" , value : value , line : line } ) ;
2024-05-07 16:28:43 +02:00
//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
2025-01-09 14:55:53 +01:00
if ( line == 1 ) {
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
const lineOnSameBraker = [ 4 , 7 ] ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
for ( var i = 0 ; i < lineOnSameBraker . length ; i ++ ) {
if ( ! relaysData . hasOwnProperty ( lineOnSameBraker [ i ] ) ) continue ;
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
instance . send ( SEND _TO . cmd _manager , { sender : "dido_controller" , cmd : "state_of_breaker" , value : value , line : lineOnSameBraker [ i ] } ) ;
2024-05-07 16:28:43 +02:00
2024-09-17 08:54:32 +02:00
deviceStatus [ "state_of_breaker" ] [ lineOnSameBraker [ i ] ] = value ;
2024-05-07 16:28:43 +02:00
reportLineStatus ( lineOnSameBraker [ i ] ) ;
values [ type ] = value ;
const tbname = relaysData [ lineOnSameBraker [ i ] ] . tbname ;
sendTelemetry ( values , tbname ) ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
delete values [ type ] ;
}
}
2025-01-09 14:55:53 +01:00
else {
2024-05-07 16:28:43 +02:00
const lineOnSameBraker = line + 3 + "" ;
2025-01-09 14:55:53 +01:00
if ( relaysData . hasOwnProperty ( lineOnSameBraker ) ) {
instance . send ( SEND _TO . cmd _manager , { sender : "dido_controller" , cmd : "state_of_breaker" , value : value , line : line + 3 } ) ;
2024-05-07 16:28:43 +02:00
2024-09-17 08:54:32 +02:00
deviceStatus [ "state_of_breaker" ] [ line + 3 ] = value ;
2024-05-07 16:28:43 +02:00
reportLineStatus ( line + 3 ) ;
values [ type ] = value ;
const tbname = relaysData [ lineOnSameBraker ] . tbname ;
sendTelemetry ( values , tbname ) ;
2025-01-09 14:55:53 +01:00
2024-05-07 16:28:43 +02:00
delete values [ type ] ;
}
}
}
2025-01-09 14:55:53 +01:00
if ( value == "Off" ) values [ "status" ] = "NOK" ;
2024-09-17 08:54:32 +02:00
deviceStatus [ "state_of_breaker" ] [ line ] = value ;
2024-05-07 16:28:43 +02:00
reportLineStatus ( line ) ;
}
2024-09-22 22:18:46 +02:00
else return ;
2024-05-07 16:28:43 +02:00
values [ type ] = value ;
2025-01-09 14:55:53 +01:00
if ( type == "rotary_switch_state" ) {
if ( SETTINGS . maintenance _mode ) value = "maintenance" ;
2024-09-22 22:18:46 +02:00
value = value . toLowerCase ( ) ;
values [ "power_mode" ] = value ;
2024-05-07 16:28:43 +02:00
}
2025-01-09 14:55:53 +01:00
if ( newPinValue != previousValues [ pinIndex ] ) previousValues [ pinIndex ] = newPinValue ;
if ( Object . keys ( values ) . length > 0 && tbname ) sendTelemetry ( values , tbname ) ;
}
2024-05-07 16:28:43 +02:00
2025-01-09 14:55:53 +01:00
function sendTelemetry ( values , tbname , date = Date . now ( ) ) {
2024-05-07 16:28:43 +02:00
let dataToTb = {
[ tbname ] : [
{
2024-12-02 16:57:26 +01:00
"ts" : date ,
2024-05-07 16:28:43 +02:00
"values" : values
}
]
2024-09-17 08:54:32 +02:00
} ;
2024-05-07 16:28:43 +02:00
2024-09-17 08:54:32 +02:00
tbHandler . sendToTb ( dataToTb , instance ) ;
2024-05-07 16:28:43 +02:00
}
2024-09-17 08:54:32 +02:00
2025-01-09 14:55:53 +01:00
function isObject ( item ) {
2024-09-17 08:54:32 +02:00
return ( typeof item === "object" && ! Array . isArray ( item ) && item !== null ) ;
}
} //end of instance
2024-05-07 16:28:43 +02:00
//! incomming data to websocket
// [
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_08',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_01',
// alias: 'al_lights_kitchen',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_02',
// alias: 'al_lights_bedroom',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_03',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_04',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_05',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_06',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// glob_dev_id: 1,
// modes: [ 'Simple' ],
// value: 0,
// circuit: '1_07',
// pending: false,
// relay_type: 'physical',
// dev: 'relay',
// mode: 'Simple'
// },
// {
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// modes: [ 'Simple', 'DirectSwitch' ],
// value: 0,
// circuit: '1_08',
// debounce: 50,
// counter: 0,
// counter_mode: 'Enabled',
// dev: 'input',
// mode: 'Simple'
// },
// {
// counter_mode: 'Enabled',
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// dev: 'input',
// modes: [ 'Simple', 'DirectSwitch' ],
// debounce: 50,
// counter: 1,
// value: 1,
// alias: 'al_main_switch',
// mode: 'Simple',
// circuit: '1_01'
// },
// {
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// modes: [ 'Simple', 'DirectSwitch' ],
// value: 1,
// circuit: '1_02',
// debounce: 50,
// counter: 2,
// counter_mode: 'Enabled',
// dev: 'input',
// mode: 'Simple'
// },
// {
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// modes: [ 'Simple', 'DirectSwitch' ],
// value: 1,
// circuit: '1_03',
// debounce: 50,
// counter: 2,
// counter_mode: 'Enabled',
// dev: 'input',
// mode: 'Simple'
// },
// {
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// modes: [ 'Simple', 'DirectSwitch' ],
// value: 0,
// circuit: '1_04',
// debounce: 50,
// counter: 1,
// counter_mode: 'Enabled',
// dev: 'input',
// mode: 'Simple'
// },
// {
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// modes: [ 'Simple', 'DirectSwitch' ],
// value: 0,
// circuit: '1_05',
// debounce: 50,
// counter: 0,
// counter_mode: 'Enabled',
// dev: 'input',
// mode: 'Simple'
// },
// {
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// modes: [ 'Simple', 'DirectSwitch' ],
// value: 0,
// circuit: '1_06',
// debounce: 50,
// counter: 0,
// counter_mode: 'Enabled',
// dev: 'input',
// mode: 'Simple'
// },
// {
// counter_modes: [ 'Enabled', 'Disabled' ],
// glob_dev_id: 1,
// modes: [ 'Simple', 'DirectSwitch' ],
// value: 0,
// circuit: '1_07',
// debounce: 50,
// counter: 0,
// counter_mode: 'Enabled',
// dev: 'input',
// mode: 'Simple'
// },
// {
// interval: 3,
// value: 24.5,
// circuit: '28744F7791180257',
// address: '28744F7791180257',
// time: 1631873896.48797,
// typ: 'DS18B20',
// lost: false,
// dev: 'temp'
// },
// {
// bus: '/dev/i2c-2',
// interval: 3,
// dev: 'owbus',
// scan_interval: 300,
// circuit: '1',
// do_scan: false,
// do_reset: false
// },
// {
// glob_dev_id: 1,
// last_comm: 0.014672994613647461,
// ver2: '0.1',
// sn: 42,
// circuit: '1',
// model: 'S207',
// dev: 'neuron',
// board_count: 1
// },
// {
// circuit: '1_01',
// value: 0,
// glob_dev_id: 1,
// dev: 'wd',
// timeout: 5000,
// was_wd_reset: 0,
// nv_save: 0
// }
// ]
//! loaded pins_data --> from LM
// {
// '1': { pin: 1, type: 'state_of_main_switch', line: 0 },
// '2': { pin: 2, type: 'rotary_switch_state', line: 0 },
// '3': { pin: 3, type: 'rotary_switch_state', line: 0 },
// '4': { pin: 4, type: 'power_supply', line: 0 },
// '5': { pin: 5, type: 'battery', line: 0 },
// '6': { pin: 6, type: 'door_condition', line: 0 },
// '8': { pin: 8, type: 'state_of_breaker', line: 1 },
// '9': { pin: 9, type: 'state_of_breaker', line: 2 },
// '10': { pin: 10, type: 'state_of_breaker', line: 3 },
// '11': { pin: 11, type: 'state_of_contactor', line: 1 },
// '12': { pin: 12, type: 'state_of_contactor', line: 2 },
// '13': { pin: 13, type: 'state_of_contactor', line: 3 },
// '16': { pin: 16, type: 'twilight_sensor', line: 0 }
// }
//! pins.table --> from LM
// pin:number|type:string|line:number
// *|1|state_of_main_switch|0|...........
// *|2|rotary_switch_state|0|...........
// *|3|rotary_switch_state|0|...........
// *|4|power_supply|0|...........
// *|5|battery|0|...........
// *|6|door_condition|0|...........
// *|8|state_of_breaker|1|...........
// *|9|state_of_breaker|2|...........
// *|10|state_of_breaker|3|...........
// *|11|state_of_contactor|1|...........
// *|12|state_of_contactor|2|...........
// *|13|state_of_contactor|3|...........
// *|16|twilight_sensor|0|...........
//! pins.table --> from UNIPI
// pin:string|type:string|line:number
// *|input1_01|state_of_main_switch|0|...........
// *|input1_02|rotary_switch_state|0|...........
// *|input1_03|rotary_switch_state|0|...........
// *|intut1_04|power_supply|0|...........
// *|input1_05|door_condition|0|...........
// *|input1_06|state_of_breaker|1|...........
// *|input1_07|state_of_breaker|2|...........
// *|input1_08|state_of_breaker|3|...........
// *|relay1_02|state_of_contactor|1|...........
// *|relay1_03|state_of_contactor|2|...........
// *|relay1_04|state_of_contactor|3|...........
// *|287D8776E0013CE9|temperature|0|...........
//! pins_data --> from UNIPI
// {
2024-09-22 22:18:46 +02:00
// input1_01: {
// pin: 'input1_01',
// type: 'door_condition',
// line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// },
// input1_02: {
// pin: 'input1_02',
// type: 'rotary_switch_state',
// line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// },
// input1_03: {
// pin: 'input1_03',
// type: 'rotary_switch_state',
// line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// },
// input1_04: {
// pin: 'input1_04',
// type: 'power_supply',
// line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// },
// input1_05: {
// pin: 'input1_05',
// type: 'state_of_main_switch',
// line: 0,
// tbname: 'PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8'
// },
// input1_06: {
// pin: 'input1_06',
// type: 'state_of_breaker',
// line: 1,
// tbname: '52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo'
// },
// relay1_02: {
// pin: 'relay1_02',
// type: 'state_of_contactor',
// line: 1,
// tbname: '52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo'
// },
// '28F46E9D0E00008B': { pin: '28F46E9D0E00008B', type: 'temperature', line: 0 },
// twilight_sensor: { pin: 'twilight_sensor', type: 'twilight_sensor', line: 0 }
2024-05-07 16:28:43 +02:00
// }
//! relays_data
// {
// '0': {
// line: 0,
// tbname: 'KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV',
// contactor: 1,
// profile: ''
// },
// '1': {
// line: 1,
// tbname: 'RMgnK93rkoAazbqdQ4yBG95Z1YXGx6pmwBeVEP2O',
// contactor: 0,
// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}'
// },
// '2': {
// line: 2,
// tbname: 'dlE1VQjYrNx9gZRmb38gG08oLBO4qaAk2M6JPnG7',
// contactor: 0,
// profile: '{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"10:00","start_time":"20:00"},{"value":0,"end_time":"10:20","start_time":"10:00"},{"value":1,"end_time":"10:40","start_time":"10:20"},{"value":0,"end_time":"11:00","start_time":"10:40"},{"value":1,"end_time":"11:30","start_time":"11:00"},{"value":0,"end_time":"11:50","start_time":"11:30"},{"value":1,"end_time":"13:00","start_time":"11:50"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}'
// },
// '3': {
// line: 3,
// tbname: 'vnmG4kJxaXWNBgMQq0D7Aj5e9oZzOAlr6LdR3w2V',
// contactor: 0,
// profile: '{"intervals":[{"value":0,"end_time":"20:30","start_time":"13:00"},{"value":1,"end_time":"00:10","start_time":"20:30"},{"value":0,"end_time":"13:00","start_time":"05:40"},{"value":1,"end_time":"05:40","start_time":"00:10"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}'
// }
// }
// {
// "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": ""
// }
// }
// }
// ]
// }