diff --git a/config b/config index 4b75027..b10cd71 100644 --- a/config +++ b/config @@ -6,8 +6,7 @@ package#flow (Object) : { url: '/' } table.relays : line:number|tbname:string|contactor:number|profile:string -table.nodes : node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number -table.settings : rvo_name:string|lang:string|temperature_address:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number|node_status_nok_time:number|phases:number +table.nodes : node:number|tbname:string|line: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 -table.status : thermometer:string|em:string|twilight_sensor:string diff --git a/databases/modbus_config.js b/databases/modbus_config.js new file mode 100644 index 0000000..b73116a --- /dev/null +++ b/databases/modbus_config.js @@ -0,0 +1,114 @@ +const timeoutInterval = 150000; + +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 }; \ No newline at end of file diff --git a/databases/nodes.table b/databases/nodes.table index e3f5e54..57331db 100644 --- a/databases/nodes.table +++ b/databases/nodes.table @@ -1,8 +1,31 @@ -node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean|time_of_last_communication:number -+|637|E6Kg9oDnLWyzPRMva7vrqy7Jxp4VG58qO2w1lZYe|3|{"intervals":[{"cct":3000,"value":10,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":20,"end_time":"05:30","start_time":"20:00"},{"cct":3000,"value":10,"end_time":"13:00","start_time":"05:30"}],"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":-20,"dusk_astro_clock_offset":20,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|1733160546993|........................................................................................................................................................................................................................................................... --|640|pE5X8NQPaow6vlOZxk6gnw7q42ezGBMyWgDVjR3L|2|{"intervals":[{"cct":3000,"value":10,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":20,"end_time":"05:30","start_time":"20:00"},{"cct":3000,"value":10,"end_time":"13:00","start_time":"05:30"}],"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":-20,"dusk_astro_clock_offset":20,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|1730588947491|............. -+|692|2O14VBzl8aDmWdNw3A518OAGyZ5qLJoEMpj6R9ng|2|{"intervals":[{"cct":3000,"value":10,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":20,"end_time":"05:30","start_time":"20:00"},{"cct":3000,"value":10,"end_time":"13:00","start_time":"05:30"}],"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":-20,"dusk_astro_clock_offset":20,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|1730674756237|....... -+|698|m6EYyZoJ4gWexdjVPARNVLARDOq9wv2N5XzKGplr|1|{"intervals":[{"cct":3000,"value":0,"end_time":"19:40","start_time":"13:00"},{"cct":3000,"value":40,"end_time":"05:30","start_time":"19:40"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"}],"astro_clock":true,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|1729806347930|............. --|638|rDbQ84xzwgdqEoPm3kbJQWk9anOZY1RXyBv2LVM6|3|{"intervals":[{"cct":3000,"value":10,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":20,"end_time":"05:30","start_time":"20:00"},{"cct":3000,"value":10,"end_time":"13:00","start_time":"05:30"}],"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":-20,"dusk_astro_clock_offset":20,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|1|1|1730376263529| -+|640|pE5X8NQPaow6vlOZxk6gnw7q42ezGBMyWgDVjR3L|2|{"intervals":[{"cct":3000,"value":0,"end_time":"14:00","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"14:10","start_time":"14:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":30,"end_time":"14:20","start_time":"14:10"},{"cct":3000,"value":40,"end_time":"14:30","start_time":"14:20"},{"cct":3000,"value":50,"end_time":"14:40","start_time":"14:30"},{"cct":3000,"value":10,"end_time":"05:30","start_time":"14:40"}],"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}|1|0|1730674754903|............. -+|638|rDbQ84xzwgdqEoPm3kbJQWk9anOZY1RXyBv2LVM6|3|{"intervals":[{"cct":3000,"value":0,"end_time":"14:00","start_time":"13:00"},{"cct":3000,"value":10,"end_time":"14:10","start_time":"14:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":30,"end_time":"14:20","start_time":"14:10"},{"cct":3000,"value":40,"end_time":"14:30","start_time":"14:20"},{"cct":3000,"value":50,"end_time":"14:40","start_time":"14:30"},{"cct":3000,"value":10,"end_time":"05:30","start_time":"14:40"}],"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}|1|1|1733160548434|............. +node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean ++|3522|RO8rjaBDy21qPQJzW7oD96ApK3xmNleVZg9Ed4Gw|1||1|1|........... ++|4018|3JjOWdylwgNLzxVab7NEznkZ2vG64rq8PEB5QmDo|1||1|1|........... ++|4019|Z5KyJe9nEg1QNbWlX0wWRB0oDjBLdqzR83VGv624|1||1|1|........... ++|4154|1JMYvnx2RzKEo4aWQ7DmN5AL8yZV3m9NBePXbrdj|1||1|0|........... ++|3907|PjLblDgRBO6WQqnxmkJ59r0Jv3ewZN4p5a89yKdY|1||1|1|........... ++|4148|dz4ojlpP85JMgDLZWkQOoGAaKYqQexEr62GXRV1y|1||1|1|........... ++|4153|d5xjWYMwEJon6rLlK7yBYmAqgV4DaOeNB9ZX3Gzb|1||1|1|........... ++|3938|gRoJEyXVx4qD9er287LP1v7wBzGldaPjLWQKm3Mv|1||1|1|........... ++|3802|K94XLav1glVRnyQ6r01BNzkme3YJwBxM5oOzdP2j|1||1|1|........... ++|4015|d9x2V5LGYBzXp4mMRAOBDj7PloaqJwnQj6DgrNe3|1||1|0|........... ++|3929|B5EoxeMVp4zwr8nqW0GjDpARjvD1PNamOGbLg63Z|1||1|1|........... ++|3946|aw4eELG2DlPMdn1JW0B1DnAqQXOZRN3xB5yp8VKr|1||1|1|........... ++|4014|ZmRwd93QL4gaezxEbAxW5971prn2XjlPvGyqJ6BO|1||1|1|........... ++|4155|eod9aRWLVl34Gx1Dn7VoaaA2rz6qjgmpEXwQJN5Z|1||1|1|........... ++|4149|3a5oqJN1bgnx4Ol9dk86NBAByE6jQ8mKDWMpGrLV|1||1|1|........... ++|3642|EjgWGnXaLy9opPOz20n694086BlYM3w1deVQvbKr|1||1|1|........... ++|3636|wvKJdZML6mXP4DzWBAXWNW7jxNloa5g23Ve9Y1ry|1||1|1|........... ++|3991|Nzp2OoJlqn6r1ZgvdA3GWdAabBwP5G4eE3RQmyxD|1||1|1|........... ++|3994|PLBJzmK1r3Gynd6OW0gGdM0e5wV4vx9bDEqNgYR8|1||1|1|........... ++|3990|52dD6ZlV1QaOpRBmbAqKZgkKnGzWMLj4eJq38Pgo|1||1|1|........... ++|3967|rDbQ84xzwgdqEoPm3kbJw3k9anOZY1RXyBv2LVM6|1||1|1|........... ++|3977|E6Kg9oDnLWyzPRMva7vrwa7Jxp4VG58qO2w1lZYe|1||1|1|........... ++|3757|roKgWqY95V3mXMRzyAjm8D7bLjexpJPvaGDBw826|1||1|1|........... ++|3633|nJL5lPMwBx23YpqRe0rlKV7damXvWVbOrD4gNzy8|1||1|1|........... ++|3744|ZmRwd93QL4gaezxEbAxW5O71prn2XjlPvGyqJ6BO|1||1|1|........... ++|4023|eod9aRWLVl34Gx1Dn7VoaMA2rz6qjgmpEXwQJN5Z|1||1|1|........... ++|3720|3a5oqJN1bgnx4Ol9dk86NZAByE6jQ8mKDWMpGrLV|1||1|1|........... ++|3734|EjgWGnXaLy9opPOz20n69V086BlYM3w1deVQvbKr|1||1|1|........... ++|3741|wvKJdZML6mXP4DzWBAXWN17jxNloa5g23Ve9Y1ry|1||1|1|........... ++|3721|Nzp2OoJlqn6r1ZgvdA3GWKAabBwP5G4eE3RQmyxD|1||0|0|........... diff --git a/databases/notifications.table b/databases/notifications.table index 8e3788f..a0590d3 100644 --- a/databases/notifications.table +++ b/databases/notifications.table @@ -20,9 +20,9 @@ key:string|weight:string|sk:string|en:string +|power_supply_works_correctly|NOTICE|Napájací zdroj pracuje správne|Power supply works correctly|............... +|battery_level_is_low|ERROR|Batéria má nízku úroveň napätia|Battery level is low|............... +|battery_level_is_ok|NOTICE|Batéria má správnu úroveň napätia|Battery level is OK|............... -+|door_opened|NOTICE|Dvere boli otvorené|Door has been opeed|............... -+|door_closed|NOTICE|Dvere boli zatvorené|Door has been closed|............... -+|door_opened_without_permission|WARNING|Dvere boli otvorené bez povoeania - zapnutá siréna|Door has been oed without permision - alarm is on|............... ++|door_has_been_open|NOTICE|Dvere boli otvorené|Door has been open|............... ++|door_has_been_closed|NOTICE|Dvere boli zatvorené|Door has been closed|............... ++|door_has_been_open_without_permision_alarm_is_on|WARNING|Dvere boli otvorené bez povolania - zapnutá siréna|Door has been open without permision - alarm is on|............... +|state_of_contactor_for_line|INFORMATIONAL|Stav stýkača pre líniu č. ${line} je ${value}|State of contactor for line no. ${line} is ${value}|............... +|local_database_is_corrupted|CRITICAL|||............... +|electrometer_nok|ERROR|Elektromer neodpovedá|Electrometer is not responding|............... @@ -35,4 +35,3 @@ key:string|weight:string|sk:string|en:string +|lamps_have_turned_on|NOTICE|Lampy sa zapli|Lamps have turned on|............... +|lamps_have_turned_off|NOTICE|Lampy sa vypli|Lamps have turned off|............... +|flow_restart|NOTICE|Restart flowu|Flow has been restarted|............... -+|nodes_db_changed|NOTICE|Zmena v node databaze|Node db has changed|............... diff --git a/databases/pins.table b/databases/pins.table index 825f9b4..f08ec54 100644 --- a/databases/pins.table +++ b/databases/pins.table @@ -1,14 +1,14 @@ pin:string|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|......... +*|input1_01|door_condition|0|........... +*|input1_02|rotary_switch_state|0|........... +*|input1_03|rotary_switch_state|0|........... +*|intut1_04|power_supply|0|........... +*|input1_05|state_of_main_switch|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|........... +*|28F46E9D0E00008B|temperature|0|........... +*|twilight_sensor|twilight_sensor|0|........... diff --git a/databases/relays.table b/databases/relays.table index 903d382..68e4f06 100644 --- a/databases/relays.table +++ b/databases/relays.table @@ -1,6 +1,5 @@ line:number|tbname:string|contactor:number|profile:string -+|0|PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8|1||........... -+|3|52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo|9|{"intervals":[{"value":0,"end_time":"19:30","start_time":"13:00"},{"value":1,"end_time":"05:50","start_time":"19:30"},{"value":0,"end_time":"13:00","start_time":"05:50"}],"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}|........... --|2|gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM|9||........... -+|1|6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq|9||........... -+|2|gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM|9||............ ++|0|6lQGaY9RDywdVzObj0PadOkPg4NBn3exEK51LWZq|1||........... ++|1|JzwxZXOvDj1bVrN4nkWw9Qk8qdyBl3MRKLpGPgaQ|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|........... ++|2|g9OxBZ5KRwNznlY6pAp6mxkWXvjdEL4eGQobMDy2|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|........... ++|3|OzNMgZ9n43qPbjXmy7zWMJA2DKdYvW5e6pxGRrVa|1|{"intervals":[{"value":0,"end_time":"20:00","start_time":"13:00"},{"value":1,"end_time":"08:00","start_time":"20:00"},{"value":0,"end_time":"13:00","start_time":"08:00"}],"astro_clock":true,"dawn_lux_sensor":true,"dusk_lux_sensor":true,"dawn_lux_sensor_value":15,"dusk_lux_sensor_value":15,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}|........... diff --git a/databases/settings.table b/databases/settings.table index a797615..a182df5 100644 --- a/databases/settings.table +++ b/databases/settings.table @@ -1,2 +1,2 @@ -rvo_name:string|lang:string|temperature_address:string|latitude:number|longitude:number|mqtt_host:string|mqtt_clientid:string|mqtt_username:string|mqtt_port:number|maintanace_mode:boolean|projects_id:number|controller_type:string|serial_port:string|backup_on_failure:boolean|restore_from_backup:number|restore_backup_wait:number|node_status_nok_time:number|phases:number -+|testpanel|en|28.427B45920702|48.70826502|17.28455203|192.168.252.1|showroom_test_panel_led|E1QTFLsN4wqyVER5xBaw|1883|0|0|lm|ttymxc4|1|20|5|0.1|3|............................................... +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 ++|rvo_senica_39_10.0.0.132|en|28.427B45920702|48.70826502|17.28455203|192.168.252.1|rvo_senica_39_10.0.0.132|qzSNuCNrLP4OL1v47YEe|1883|0|68|unipi|ttyUSB0|1|20|5|........................................... diff --git a/databases/status.table b/databases/status.table deleted file mode 100644 index da25224..0000000 --- a/databases/status.table +++ /dev/null @@ -1,2 +0,0 @@ -thermometer:string|em:string|twilight_sensor:string -+|NOK|OK|OK|............ diff --git a/databases/tbdata.nosql b/databases/tbdata.nosql index 564a5c3..e69de29 100644 --- a/databases/tbdata.nosql +++ b/databases/tbdata.nosql @@ -1,287 +0,0 @@ --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730588333765,"values":{"maintenance_mode":false}}],"id":"2501279001ax71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730588333835,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2501279002ax70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730588333840,"values":{"state_of_main_switch":"closed"}}],"id":"2501279003ax71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730588333845,"values":{"power_supply":"On"}}],"id":"2501279004ax70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730588333851,"values":{"battery":"Off"}}],"id":"2501279005ax71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730588333855,"values":{"door_condition":"closed"}}],"id":"2501279006ax70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730588333867,"values":{"status":"OK"}}],"id":"2501279007ax71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730588333873,"values":{"statecode":2}}],"id":"2501279008ax70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730588333876,"values":{"state_of_breaker":"On"}}],"id":"2501279009ax71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730588333881,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2501279010ax70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730588333885,"values":{"status":"OK"}}],"id":"2501279011ax71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730588333887,"values":{"statecode":2}}],"id":"2501279012ax70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730588333890,"values":{"state_of_breaker":"On"}}],"id":"2501279013ax71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730588333893,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2501279014ax70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730588333896,"values":{"status":"OK"}}],"id":"2501279015ax71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730588333899,"values":{"statecode":2}}],"id":"2501279016ax70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730588333901,"values":{"state_of_breaker":"On"}}],"id":"2501279017ax71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730589728172,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2501302001ny71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730589728240,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2501302002ny70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730589728246,"values":{"state_of_main_switch":"closed"}}],"id":"2501302003ny71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730589728251,"values":{"power_supply":"On"}}],"id":"2501302004ny70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730589728256,"values":{"battery":"Off"}}],"id":"2501302005ny71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730589728260,"values":{"door_condition":"closed"}}],"id":"2501302006ny70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730589728272,"values":{"status":"OK"}}],"id":"2501302007ny71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730589728278,"values":{"statecode":2}}],"id":"2501302008ny70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730589728281,"values":{"state_of_breaker":"On"}}],"id":"2501302009ny71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730589728286,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2501302010ny70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730589728290,"values":{"status":"OK"}}],"id":"2501302011ny71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730589728293,"values":{"statecode":2}}],"id":"2501302012ny70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730589728295,"values":{"state_of_breaker":"On"}}],"id":"2501302013ny71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730589728299,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2501302014ny70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730589728302,"values":{"status":"OK"}}],"id":"2501302015ny71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730589728305,"values":{"statecode":2}}],"id":"2501302016ny70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730589728307,"values":{"state_of_breaker":"On"}}],"id":"2501302017ny71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730590126776,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2501309001xk71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730590126844,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2501309002xk70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730590126850,"values":{"state_of_main_switch":"closed"}}],"id":"2501309003xk71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730590126855,"values":{"power_supply":"On"}}],"id":"2501309004xk70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730590126860,"values":{"battery":"Off"}}],"id":"2501309005xk71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730590126865,"values":{"door_condition":"closed"}}],"id":"2501309006xk70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730590126877,"values":{"status":"OK"}}],"id":"2501309007xk71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730590126883,"values":{"statecode":2}}],"id":"2501309008xk70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730590126886,"values":{"state_of_breaker":"On"}}],"id":"2501309009xk71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730590126891,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2501309010xk70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730590126895,"values":{"status":"OK"}}],"id":"2501309011xk71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730590126897,"values":{"statecode":2}}],"id":"2501309012xk70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730590126900,"values":{"state_of_breaker":"On"}}],"id":"2501309013xk71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730590126903,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2501309014xk70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730590126906,"values":{"status":"OK"}}],"id":"2501309015xk71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730590126909,"values":{"statecode":2}}],"id":"2501309016xk70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730590126911,"values":{"state_of_breaker":"On"}}],"id":"2501309017xk71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730591367948,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2501329001ua71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730591368017,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2501329002ua70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730591368022,"values":{"state_of_main_switch":"closed"}}],"id":"2501329003ua71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730591368028,"values":{"power_supply":"On"}}],"id":"2501329004ua70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730591368032,"values":{"battery":"Off"}}],"id":"2501329005ua71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730591368037,"values":{"door_condition":"closed"}}],"id":"2501329006ua70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730591368049,"values":{"status":"OK"}}],"id":"2501329007ua71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730591368055,"values":{"statecode":2}}],"id":"2501329008ua70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730591368058,"values":{"state_of_breaker":"On"}}],"id":"2501329009ua71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730592105058,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2501342001ch71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730592105130,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2501342002ch70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730592105135,"values":{"state_of_main_switch":"closed"}}],"id":"2501342003ch71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730592105140,"values":{"power_supply":"On"}}],"id":"2501342004ch70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730592105145,"values":{"battery":"Off"}}],"id":"2501342005ch71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730592105150,"values":{"door_condition":"closed"}}],"id":"2501342006ch70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730592105162,"values":{"status":"OK"}}],"id":"2501342007ch71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730592105168,"values":{"statecode":2}}],"id":"2501342008ch70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730592105171,"values":{"state_of_breaker":"On"}}],"id":"2501342009ch71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730592105176,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2501342010ch70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730592105180,"values":{"status":"OK"}}],"id":"2501342011ch71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730592105182,"values":{"statecode":2}}],"id":"2501342012ch70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730592105185,"values":{"state_of_breaker":"On"}}],"id":"2501342013ch71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730592105188,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2501342014ch70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730592105191,"values":{"status":"OK"}}],"id":"2501342015ch71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730592105194,"values":{"statecode":2}}],"id":"2501342016ch70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730592105196,"values":{"state_of_breaker":"On"}}],"id":"2501342017ch71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730592105200,"values":{"twilight_sensor":31}}],"id":"2501342018ch70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730592420656,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2501347001nd71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730663586542,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2502533001gt71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730671706506,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2502668001yg71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672433386,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 2 : on","message_data":""}}}],"id":"2502681003ad71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672433494,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 2 is On","message_data":""}}}],"id":"2502681004ad70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672433568,"values":{"statecode":0}}],"id":"2502681005ad71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672433588,"values":{"state_of_contactor":true }}],"id":"2502681006ad70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672433849,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 3 : on","message_data":""}}}],"id":"2502681007ad71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672433892,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is On","message_data":""}}}],"id":"2502681008ad70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672433908,"values":{"statecode":0}}],"id":"2502681009ad71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672433910,"values":{"state_of_contactor":true }}],"id":"2502681010ad70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777712,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2502686001di71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777782,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2502686002di70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777787,"values":{"state_of_main_switch":"closed"}}],"id":"2502686003di71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777792,"values":{"power_supply":"On"}}],"id":"2502686004di70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777798,"values":{"battery":"Off"}}],"id":"2502686005di71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777802,"values":{"door_condition":"closed"}}],"id":"2502686006di70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730672777814,"values":{"status":"OK"}}],"id":"2502686007di71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730672777820,"values":{"statecode":2}}],"id":"2502686008di70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730672777824,"values":{"state_of_breaker":"On"}}],"id":"2502686009di71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672777828,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2502686010di70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672777832,"values":{"status":"OK"}}],"id":"2502686011di71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672777835,"values":{"statecode":2}}],"id":"2502686012di70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672777837,"values":{"state_of_breaker":"On"}}],"id":"2502686013di71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672777841,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2502686014di70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672777844,"values":{"status":"OK"}}],"id":"2502686015di71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672777847,"values":{"statecode":2}}],"id":"2502686016di70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672777849,"values":{"state_of_breaker":"On"}}],"id":"2502686017di71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777872,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 1 is Off","message_data":""}}}],"id":"2502686018di70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730672777883,"values":{"state_of_contactor":false}}],"id":"2502686019di71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777888,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 2 is Off","message_data":""}}}],"id":"2502686020di70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672777895,"values":{"state_of_contactor":false}}],"id":"2502686021di71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672777899,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is Off","message_data":""}}}],"id":"2502686022di70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672777905,"values":{"state_of_contactor":false}}],"id":"2502686023di71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672922976,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2502689001nu71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672923046,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2502689002nu70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672923052,"values":{"state_of_main_switch":"closed"}}],"id":"2502689003nu71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672923057,"values":{"power_supply":"On"}}],"id":"2502689004nu70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672923062,"values":{"battery":"Off"}}],"id":"2502689005nu71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672923066,"values":{"door_condition":"closed"}}],"id":"2502689006nu70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730672923078,"values":{"status":"OK"}}],"id":"2502689007nu71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730672923084,"values":{"statecode":2}}],"id":"2502689008nu70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730672923088,"values":{"state_of_breaker":"On"}}],"id":"2502689009nu71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672923092,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2502689010nu70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672923096,"values":{"status":"OK"}}],"id":"2502689011nu71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672923099,"values":{"statecode":2}}],"id":"2502689012nu70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672923101,"values":{"state_of_breaker":"On"}}],"id":"2502689013nu71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672923105,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2502689014nu70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672923108,"values":{"status":"OK"}}],"id":"2502689015nu71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672923111,"values":{"statecode":2}}],"id":"2502689016nu70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672923113,"values":{"state_of_breaker":"On"}}],"id":"2502689017nu71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672923136,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 1 is Off","message_data":""}}}],"id":"2502689018nu70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730672923147,"values":{"state_of_contactor":false}}],"id":"2502689019nu71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672923152,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 2 is Off","message_data":""}}}],"id":"2502689020nu70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730672923159,"values":{"state_of_contactor":false}}],"id":"2502689021nu71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730672923164,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is Off","message_data":""}}}],"id":"2502689022nu70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730672923170,"values":{"state_of_contactor":false}}],"id":"2502689023nu71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534730,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2502699001wb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534807,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2502699002wb70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534812,"values":{"state_of_main_switch":"closed"}}],"id":"2502699003wb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534818,"values":{"power_supply":"On"}}],"id":"2502699004wb70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534823,"values":{"battery":"Off"}}],"id":"2502699005wb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534827,"values":{"door_condition":"closed"}}],"id":"2502699006wb70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730673534840,"values":{"status":"OK"}}],"id":"2502699007wb71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730673534846,"values":{"statecode":2}}],"id":"2502699008wb70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730673534849,"values":{"state_of_breaker":"On"}}],"id":"2502699009wb71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730673534854,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2502699010wb70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730673534857,"values":{"status":"OK"}}],"id":"2502699011wb71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730673534860,"values":{"statecode":2}}],"id":"2502699012wb70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730673534863,"values":{"state_of_breaker":"On"}}],"id":"2502699013wb71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730673534866,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2502699014wb70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730673534869,"values":{"status":"OK"}}],"id":"2502699015wb71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730673534872,"values":{"statecode":2}}],"id":"2502699016wb70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730673534875,"values":{"state_of_breaker":"On"}}],"id":"2502699017wb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534918,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 1 is Off","message_data":""}}}],"id":"2502699018wb70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730673534942,"values":{"state_of_contactor":false}}],"id":"2502699019wb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534956,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 2 is Off","message_data":""}}}],"id":"2502699020wb70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730673534963,"values":{"state_of_contactor":false}}],"id":"2502699021wb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730673534968,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is Off","message_data":""}}}],"id":"2502699022wb70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730673534974,"values":{"state_of_contactor":false}}],"id":"2502699023wb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730675467314,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2502731001jm71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730676458104,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 2 : off","message_data":""}}}],"id":"2502748003ji71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730676458279,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 3 : off","message_data":""}}}],"id":"2502748004ji70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615197,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2502783001xe71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615259,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2502783002xe70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615264,"values":{"state_of_main_switch":"closed"}}],"id":"2502783003xe71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615270,"values":{"power_supply":"On"}}],"id":"2502783004xe70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615276,"values":{"battery":"Off"}}],"id":"2502783005xe71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615281,"values":{"door_condition":"closed"}}],"id":"2502783006xe70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730678615307,"values":{"status":"OK"}}],"id":"2502783007xe71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730678615313,"values":{"statecode":2}}],"id":"2502783008xe70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730678615316,"values":{"state_of_breaker":"On"}}],"id":"2502783009xe71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730678615321,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2502783010xe70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730678615324,"values":{"status":"OK"}}],"id":"2502783011xe71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730678615327,"values":{"statecode":2}}],"id":"2502783012xe70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730678615329,"values":{"state_of_breaker":"On"}}],"id":"2502783013xe71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730678615333,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2502783014xe70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730678615336,"values":{"status":"OK"}}],"id":"2502783015xe71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730678615338,"values":{"statecode":2}}],"id":"2502783016xe70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730678615340,"values":{"state_of_breaker":"On"}}],"id":"2502783017xe71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615396,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 1 is Off","message_data":""}}}],"id":"2502783018xe70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730678615433,"values":{"state_of_contactor":false}}],"id":"2502783019xe71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615453,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 2 is Off","message_data":""}}}],"id":"2502783020xe70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730678615470,"values":{"state_of_contactor":false}}],"id":"2502783021xe71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615487,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is Off","message_data":""}}}],"id":"2502783022xe70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730678615506,"values":{"state_of_contactor":false}}],"id":"2502783023xe71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730678615510,"values":{"twilight_sensor":31}}],"id":"2502783024xe70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730757867671,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2504104001au71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759363143,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 3 : on","message_data":""}}}],"id":"2504129003fe71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759363792,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is On","message_data":""}}}],"id":"2504129004fe70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730759363814,"values":{"statecode":0}}],"id":"2504129005fe71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730759363817,"values":{"state_of_contactor":true }}],"id":"2504129006fe70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759583799,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2504133001fr71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759583910,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"NOK","statecode":34}}],"id":"2504133002fr70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759583920,"values":{"state_of_main_switch":"closed"}}],"id":"2504133003fr71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759583925,"values":{"power_supply":"On"}}],"id":"2504133004fr70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759583930,"values":{"battery":"Off"}}],"id":"2504133005fr71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759583947,"values":{"door_condition":"closed"}}],"id":"2504133006fr70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730759583960,"values":{"status":"OK"}}],"id":"2504133007fr71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730759583965,"values":{"statecode":2}}],"id":"2504133008fr70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1730759583968,"values":{"state_of_breaker":"On"}}],"id":"2504133009fr71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730759583974,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2504133010fr70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730759583977,"values":{"status":"OK"}}],"id":"2504133011fr71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730759583980,"values":{"statecode":2}}],"id":"2504133012fr70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1730759583982,"values":{"state_of_breaker":"On"}}],"id":"2504133013fr71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730759583986,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2504133014fr70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730759583989,"values":{"status":"OK"}}],"id":"2504133015fr71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730759583991,"values":{"statecode":2}}],"id":"2504133016fr70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730759583993,"values":{"state_of_breaker":"On"}}],"id":"2504133017fr71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759985331,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 3 : on","message_data":""}}}],"id":"2504140003mc71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730759985367,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is On","message_data":""}}}],"id":"2504140004mc70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730759985398,"values":{"statecode":0}}],"id":"2504140005mc71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1730759985410,"values":{"state_of_contactor":true }}],"id":"2504140006mc70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1730761965548,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2504172001np71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731876994929,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2522756001rh71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731877329335,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 3 : on","message_data":""}}}],"id":"2522762003cs71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731877329409,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is On","message_data":""}}}],"id":"2522762004cs70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731877329460,"values":{"statecode":0}}],"id":"2522762005cs71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731877329478,"values":{"state_of_contactor":true }}],"id":"2522762006cs70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106215,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2522775001tb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106280,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"OK","statecode":34}}],"id":"2522775002tb70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106285,"values":{"state_of_main_switch":"closed"}}],"id":"2522775003tb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106322,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 1 is Off","message_data":""}}}],"id":"2522775004tb70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731878106365,"values":{"statecode":3}}],"id":"2522775005tb71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731878106370,"values":{"state_of_contactor":false}}],"id":"2522775006tb70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106380,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 2 is Off","message_data":""}}}],"id":"2522775007tb71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731878106387,"values":{"statecode":3}}],"id":"2522775008tb70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731878106391,"values":{"state_of_contactor":false}}],"id":"2522775009tb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106398,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is Off","message_data":""}}}],"id":"2522775010tb70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731878106404,"values":{"statecode":3}}],"id":"2522775011tb71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731878106407,"values":{"state_of_contactor":false}}],"id":"2522775012tb70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106413,"values":{"power_supply":"On"}}],"id":"2522775013tb71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106417,"values":{"battery":"Off"}}],"id":"2522775014tb70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878106420,"values":{"door_condition":"closed"}}],"id":"2522775015tb71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731878106425,"values":{"status":"OK"}}],"id":"2522775016tb70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731878106428,"values":{"statecode":2}}],"id":"2522775017tb71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731878106430,"values":{"state_of_breaker":"On"}}],"id":"2522775018tb70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731878106434,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2522775019tb71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731878106436,"values":{"status":"OK"}}],"id":"2522775020tb70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731878106439,"values":{"statecode":2}}],"id":"2522775021tb71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731878106441,"values":{"state_of_breaker":"On"}}],"id":"2522775022tb70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878260010,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2522777001wk71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878260073,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"OK","statecode":34}}],"id":"2522777002wk70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878260077,"values":{"state_of_main_switch":"closed"}}],"id":"2522777003wk71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878260083,"values":{"power_supply":"On"}}],"id":"2522777004wk70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878260088,"values":{"battery":"Off"}}],"id":"2522777005wk71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878260092,"values":{"door_condition":"closed"}}],"id":"2522777006wk70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731878260104,"values":{"status":"OK"}}],"id":"2522777007wk71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731878260110,"values":{"statecode":2}}],"id":"2522777008wk70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731878260113,"values":{"state_of_breaker":"On"}}],"id":"2522777009wk71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731878386415,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2522780001uh71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121143,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2522825001pn71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121208,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"OK","statecode":34}}],"id":"2522825002pn70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121213,"values":{"state_of_main_switch":"closed"}}],"id":"2522825003pn71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121226,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 1 is Off","message_data":""}}}],"id":"2522825004pn70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731881121245,"values":{"statecode":3}}],"id":"2522825005pn71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731881121249,"values":{"state_of_contactor":false}}],"id":"2522825006pn70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121256,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 2 is Off","message_data":""}}}],"id":"2522825007pn71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731881121263,"values":{"statecode":3}}],"id":"2522825008pn70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731881121266,"values":{"state_of_contactor":false}}],"id":"2522825009pn71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121273,"values":{"_event":{"type":"informational","status":"new","source":{"func":"switchLogic","component":"1730323243484","component_name":"DIDO_Controller","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: State of contactor for line no. 3 is Off","message_data":""}}}],"id":"2522825010pn70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731881121280,"values":{"statecode":3}}],"id":"2522825011pn71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731881121282,"values":{"state_of_contactor":false}}],"id":"2522825012pn70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121288,"values":{"power_supply":"On"}}],"id":"2522825013pn71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121293,"values":{"battery":"Off"}}],"id":"2522825014pn70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731881121297,"values":{"door_condition":"closed"}}],"id":"2522825015pn71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731881121302,"values":{"status":"OK"}}],"id":"2522825016pn70b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731881121305,"values":{"statecode":2}}],"id":"2522825017pn71b"} --"6lQGaY9RDywdVzObj0P1vrkPg4NBn3exEK51LWZq":[{"ts":1731881121308,"values":{"state_of_breaker":"On"}}],"id":"2522825018pn70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731881121311,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM"},"message":"testpanel: Circuit breaker was turned on - line no. 2","message_data":""}}}],"id":"2522825019pn71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731881121314,"values":{"status":"OK"}}],"id":"2522825020pn70b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731881121316,"values":{"statecode":2}}],"id":"2522825021pn71b"} --"gP1eOZVj3Q9lv5aDEk4EVP7rdpqW8yLm2BbKzJxM":[{"ts":1731881121318,"values":{"state_of_breaker":"On"}}],"id":"2522825022pn70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731881121347,"values":{"_event":{"type":"notice","status":"new","source":{"func":"CMD Manager: onData","component":"1619515097737","component_name":"CMD Manager","edge":"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo"},"message":"testpanel: Circuit breaker was turned on - line no. 3","message_data":""}}}],"id":"2522825023pn71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731881121353,"values":{"status":"OK"}}],"id":"2522825024pn70b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731881121360,"values":{"statecode":2}}],"id":"2522825025pn71b"} --"52dD6ZlV1QaOpRBmbAqK8bkKnGzWMLj4eJq38Pgo":[{"ts":1731881121362,"values":{"state_of_breaker":"On"}}],"id":"2522825026pn70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731884700377,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2522885001lo71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731884700441,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"OK","statecode":34}}],"id":"2522885002lo70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731884700446,"values":{"state_of_main_switch":"closed"}}],"id":"2522885003lo71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731884700451,"values":{"power_supply":"On"}}],"id":"2522885004lo70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731884700455,"values":{"battery":"Off"}}],"id":"2522885005lo71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731884854298,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2522887001ap71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731885414928,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 3 : off","message_data":""}}}],"id":"2522897013ln71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731885415091,"values":{"_event":{"type":"informational","status":"new","source":{"func":"CMD Manager: process cmd","component":"1619515097737","component_name":"CMD Manager","edge":"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8"},"message":"testpanel: Switching profile point applied to line no. 3 : off","message_data":""}}}],"id":"2522897014ln70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1731885602197,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2522900001jc71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1732040930566,"values":{"edge_fw_version":"2024-10-14","maintenance_mode":false}}],"id":"2525489001lu71b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1732040930629,"values":{"electrometer_status":1,"twilight_sensor_status":1,"thermometer_status":0,"phase_1_status":1,"phase_2_status":1,"phase_3_status":1,"master_node_status":1,"status":"OK","statecode":34}}],"id":"2525489002lu70b"} --"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8":[{"ts":1732040930634,"values":{"state_of_main_switch":"closed"}}],"id":"2525489003lu71b"} diff --git a/flow/audit_test_panel.csv b/flow/audit_test_panel.csv new file mode 100644 index 0000000..907a6a9 --- /dev/null +++ b/flow/audit_test_panel.csv @@ -0,0 +1,48 @@ +LumDimm;NODE (HEX);NODE (DEC);Line;TB name +1;299;665;3;gbv4nzqxW0XGAPKVNk8kr25ZQ2l3O6LRBprM97ew +2;28A;650;3;0XYElWeKBNJn1gdoMG8lYdDALkPvj4V3xra2q6mO +3;296;662;3;gbv4nzqxW0XGAPKVNk8kW48ZQ2l3O6LRBprM97ew +4;297;663;1;LpkVlmq4b3jMwJQxBZ8akayrXAP6o97Ke0aOYEg2 +5;29C;668;3;lekrmdvO0BQG1ZW4AV8jeZ5M39xnN2wEbRgPjXLp +6;2B1;689;3;q0rElBPdL6kxMAjnzVDRl95emNZY7oOv2wK9gb31 +7;2AB;683;3;XKQbz3WAwY21dGa0R453rWyJm9PZOjqlvpr6Nkeo +8;2B0;688;3;PaGbQ3wBAZWOmRvK9VDpvz5endLJYopEqlkzNMxX +9;2B9;697;3;joqRYBVL30k9eQWOlZ5qwpD2KJpNEmA6gPxXzwaM +10;293;659;3;Ymn9oleRxJ0vw17WzAyGwdyEBk4ObdMXj2VgpNLG +11;294;660;3;gj7zbKV46oQ1p2e0AJ8XqZDG3YNWaRrlOEXvBxmM +12;295;661;3;laYK7Pomn2bNZXEpedDxAqyOJkQ3WwV49gqxLrAR +13;2A0;672;2;0XYElWeKBNJn1gdoMG8lON5ALkPvj4V3xra2q6mO +14;2B4;692;2;l9YkRpoB2vVa0mKqEO8ZGGDjW43eXnJML6GxzbwQ +15;2B2;690;2;wGjQobgOK0n2YqBZmVDVR3DR9ep6EXA1ka3vzlP7 +16;27C;636;2;M6ogKQW09bOXewAYvZyvJqyJrV1aRnPGE37p42Nx +17;27B;635;2;Vq2JaWpw1OdBKmNeoj8w605XE40l3kgL76Azb9QP +18;2B6;694;2;Jm32GR1qpwQxlZza0N5mE15AP96YbOKLogrXVW4e +19;2B5;693;2;KjbN4q7JPZmexgdnz2yKdn5YAWwO0Q3BMX6ERLoV +20;2B3;691;1;lekrmdvO0BQG1ZW4AV8jzq8M39xnN2wEbRgPjXLp +21;27F;639;3;BOjEzGRZ46bnp9wa2A8z76D0JkmW1QPNdrqevXVL +22;27E;638;3;9xgzG4Op1BrKZPmoQkDrmj8E73ndJNMjavAwX2Re +23;27D;637;3;koW06PeGrLlBp2YJQE5Ogw5RmMaXKzj3wOAZg9n7 +24;28F;655;2;RMgnK93rkoAazbqdQ4yBYpDZ1YXGx6pmwBeVEP2O +25;288;648;2;gaMGN4x1e9JlZz0QPRDd9Rym6dVr3OpvqKnoWBbk +26;298;664;1;oGVzxNWP9lrjaQ7vKODQ7g51gqp62YZREmdw3XBM +27;29F;671;3;AvVdgzYJZaPx3oMqeED4Oj8NnmKkw716bRO90jLB +28;280;640;2;WjBL12pg63eX4N9P7zy0XYyEJKmlbkGwZMx0avQV +29;28B;651;2;qaAOzENGrvpbe0VoK7D6Ld519PZmdg3nl24JLQMk +30;27A;634;2;NGWamnYqlP1wbgrZQxDAWm5e2X7OVAK69koR04vL +31;29E;670;2;dlE1VQjYrNx9gZRmb38g1YyoLBO4qaAk2M6JPnG7 +32;281;641;2;vnmG4kJxaXWNBgMQq0D7Mz5e9oZzOAlr6LdR3w2V +33;278;632;2;LpkVlmq4b3jMwJQxBZ8aM78rXAP6o97Ke0aOYEg2 +34;29D;669;3;Y9aLW03wOZkABvKXbMyL0lyV1xdNj72r4egqGRzJ +35;2A8;680;1;KL2jNOVpdARa9XvoeJDPga8bkmPBxqn7Ww3gzGQ1 +36;2BA;698;1;mYnBzbeGaAL62jowRv59M35Xq9QpZ0K7O1dg4xVl +37;29B;667;1;MzXBoWbEZjO0lrpqnRyoJ4DkmVeaNAGdL9g4QKxP +38;289;649;1;0p2rwdP7aGoOQLJNgAynJNy6xWXbmMe3nvZqlzkV +39;290;656;1;BrQx3NGKgVMRaXYAo9y1GE8ZzkWnj1le6bdOLE20 +40;2AA;682;1;vnreBJ6PMqgz20pYEL82XQyG1jkWwdQxZVNAOlmK +41;285;645;1;jklN4JpQAx362o9XYZDN6wDgrWw1P7GEbdBM0vRV +42;283;643;1;oZmYXEbw9lVWRv1jLxDe9bDdgAMz4PKQnNJ6eB23 +43;282;642;1;pEonaKBOGbj9034MgJ8W3G8qXvxNWVkAPQz21R6L +44;287;647;1;BLQal6Pn9oz1KmNgek5Yqd50vd2MAbqG3OV7Rp4j +45;286;646;1;4agVJ9dPQkmp1R2X3EDJKxyrK6ZlNoM0n7qxBOev +46;29A;666;1;9PpgLEnvk4WMV6RmOJybMGDaeAXzo2BQNG3K17Zw +47;28E;654;1;Mmp93b2nvd7OoqgBeEyEZq5kjlAV1Y4ZNXwW0zLG diff --git a/flow/cmd_manager.js b/flow/cmd_manager.js index ed4a928..48b4987 100644 --- a/flow/cmd_manager.js +++ b/flow/cmd_manager.js @@ -3,10 +3,14 @@ exports.title = 'CMD Manager'; exports.group = 'Worksys'; exports.color = '#5D9CEC'; exports.version = '0.0.3'; -//blue - send message to relays exports.output = ['red', 'blue', 'yellow', 'blue', 'white']; -exports.input = 3; + +//blue - send message to relays + +exports.input = true; +exports.author = 'Daniel Segeš'; exports.icon = 'cloud-upload'; +//exports.npm = ['serialport' , 'child_process']; exports.html = `
@@ -26,709 +30,802 @@ exports.html = `
`; + exports.readme = `Manager for CMD calls`; +const SerialPort = require('serialport'); +const { exec } = require('child_process'); +const { crc8, crc16, crc32 } = require('easy-crc'); +const { openPort, runSyncExec, writeData } = require('./helper/serialport_helper.js'); +const { bytesToInt, longToByteArray, addZeroBefore, isEmptyObject, convertUTCDateToLocalDate } = require('./helper/utils'); +const bitwise = require('bitwise'); -exports.install = function(instance) { +var SunCalc = require('./helper/suncalc.js'); +const DataToTbHandler = require('./helper/DataToTbHandler.js'); +const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler.js'); +const { promisifyBuilder, makeMapFromDbResult} = require('./helper/db_helper.js'); +const { sendNotification, initNotifications, ERRWEIGHT } = require('./helper/notification_reporter.js'); - const SerialPort = require('serialport'); - const { exec } = require('child_process'); - const { crc16 } = require('easy-crc'); - const { runSyncExec, writeData } = require('./helper/serialport_helper'); - const { bytesToInt, longToByteArray, addZeroBefore } = require('./helper/utils'); - const bitwise = require('bitwise'); +const dbNodes = TABLE("nodes"); +const dbRelays = TABLE("relays"); +const dbSettings = TABLE("settings"); - var SunCalc = require('./helper/suncalc'); - const DataToTbHandler = require('./helper/DataToTbHandler'); - const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler'); - const { sendNotification } = require('./helper/notification_reporter'); - const process = require('process'); - const { errLogger, logger, monitor } = require('./helper/logger'); +//https://github.com/log4js-node/log4js-node/blob/master/examples/example.js +//file: { type: 'file', filename: path.join(__dirname, 'log/file.log') } +var path = require('path'); +var log4js = require("log4js"); +const process = require('process'); - const dbNodes = TABLE("nodes"); - const dbRelays = TABLE("relays"); +//TODO - to remove? +// runTasks intervals +const SHORT_INTERVAL = 30; +const LONG_INTERVAL = 300; - let GLOBALS; - let SETTINGS; - let rsPort; - let tbHandler; +//send data to following instances: +const SEND_TO = { + debug: 0, + tb: 1, + http_response: 2, + dido_controller: 3, + infoSender: 4 +} - // runTasks intervals - const SHORT_INTERVAL = 30; - const LONG_INTERVAL = 300; +const PRIORITY_TYPES = { + terminal: 0, + fw_detection: 1,//reserved only for FW detection - FLOW.OMS_masterNodeIsResponding + high_priority: 2,//reserverd only for: read dimming / brightness (after set dimming from platform) + relay_profile: 3, + node_broadcast: 4, + node_profile: 5, + node_cmd: 6 +} - //send data to following instances: - const SEND_TO = { - debug: 0, - tb: 1, - http_response: 2, - dido_controller: 3, - infoSender: 4 +//list of command calls to process. Processing in runTasks function +let tasks = []; + +let interval = null;//timeout for procesing tasks +let refFlowdata = null;//holds reference to httprequest flowdata +let refFlowdataObj = {}; + +//load from settings +let latitude = 48.70826502;//48.682255758; +let longitude = 17.28455203;//17.278910807; + +const gmtOffset = 0; + +//ak nie je nastaveny +//https://www.tecmint.com/set-time-timezone-and-synchronize-time-using-timedatectl-command/ +//https://stackoverflow.com/questions/16086962/how-to-get-a-time-zone-from-a-location-using-latitude-and-longitude-coordinates + +//priorities for registers +let priorities = []; + +let minutes = 1; +priorities["0"] = minutes; +priorities["1"] = minutes; + +minutes = 5; +priorities["74"] = minutes; +priorities["75"] = minutes; +priorities["76"] = minutes; +priorities["77"] = minutes; +priorities["78"] = minutes; +priorities["79"] = minutes; +priorities["84"] = minutes; + +minutes = 10; +priorities["87"] = minutes; +priorities["6"] = minutes; +priorities["7"] = minutes; +priorities["80"] = minutes; +priorities["8"] = minutes; +priorities["3"] = minutes; +priorities["89"] = minutes; + +//prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) +let listOfCommands = [0,1,3,6,7,8,74,75,76,77,78,79,80,84,87,89]; + +const errorHandler = new ErrorToServiceHandler(); + +let rotary_switch_state = "Off"; +let lux_sensor; +let state_of_breaker = {};//key is line, value is On/Off +let disconnectedReport = {};//key is tbname, value true/false + +let relaysData = {};//key is line, value is data from db +let nodesData = {};//key is node, value data from db + +//helper container for counting resolved group of commands (commands related to set profile) +let cmdCounter = {};//key is node, value is counter +let cmdNOKNodeCounter = {};//key is node, value is counter + +//END OF VARIABLE SETTINGS +//-------------------------------- + + +log4js.configure({ + appenders: { + errLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'err.txt') }, + monitorLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'monitor.txt') }, + console: { type: 'console' } + }, + categories: { + errLogs: { appenders: ['console', 'errLogs'], level: 'error' }, + monitorLogs: { appenders: ['console', 'monitorLogs'], level: 'trace' }, + //another: { appenders: ['console'], level: 'trace' }, + default: { appenders: ['console'], level: 'trace' } + } +}); + +const errLogger = log4js.getLogger("errLogs"); +const logger = log4js.getLogger(); +const monitor = log4js.getLogger("monitorLogs"); + +//USAGE +//logger.debug("text") +//monitor.info('info'); +//errLogger.error("some error"); + + +function cmdCounterResolve(address) +{ + if(cmdCounter.hasOwnProperty(address)) + { + cmdCounter[address] = cmdCounter[address] - 1; + + let result = cmdCounter[address]; + if(result == 0) delete cmdCounter[address]; + return result; + } + return -1; +} + + +function getParams(priority) +{ + let params = {}; + + //core rpc values + params.address = 0;//if(recipient === 0) address = 0; + params.byte1 = 0;//msb, podla dokumentacie data3 + params.byte2 = 0;//podla dokumentacie data2 + params.byte3 = 0;//podla dokumentacie data1 + params.byte4 = 0;//lsb, podla dokumentacie data0 + params.recipient = 0;//0: Master, 1: Slave, 2: Broadcast + params.register = -1;//register number + params.rw = 0;//0: read, 1: write + + //other values + //params.type = "cmd"; "relay" "cmd-terminal" "set_node_profile" "process_profiles" "edge_date_time" "number_of_luminaires" + //params.tbname = tbname; + params.priority = PRIORITY_TYPES.node_cmd; //default priority - if more tasks with the same timestamp, we sort them based on priority + params.timestamp = 0; //execution time - if timestamp < Date.now(), the task is processed + if(priority != undefined ) + { + params.timestamp = priority; + params.priority = priority; + } + + params.addMinutesToTimestamp = 0;//repeat task if value is > 0, + + //params.timePointName = "luxOff" // "luxOn", "dusk", "dawn", "profileTimepoint" + //params.info = ""; + + return params; +} + + +async function loadSettings() +{ + let responseSettings = await promisifyBuilder(dbSettings.find()); + + latitude = responseSettings[0]["latitude"]; + longitude = responseSettings[0]["longitude"]; + + //globals + FLOW.OMS_language = responseSettings[0]["lang"]; + FLOW.OMS_rvo_name = responseSettings[0]["rvo_name"]; + FLOW.OMS_projects_id = responseSettings[0]["projects_id"]; + //FLOW.OMS_rvo_tbname = responseSettings[0]["tbname"]; + FLOW.OMS_temperature_adress = responseSettings[0]["temperature_adress"]; + FLOW.OMS_controller_type = responseSettings[0]["controller_type"]; + FLOW.OMS_serial_port = responseSettings[0]["serial_port"]; + + //logger.debug('settings', responseSettings[0]); + + initNotifications(); +} + +loadSettings(); + + +async function loadNodes() +{ + const responseNodes = await promisifyBuilder(dbNodes.find()); + nodesData = makeMapFromDbResult(responseNodes, "node"); +} + +loadNodes(); + + +//nastav profil nodu +function processNodeProfile(node) +{ + if(rotary_switch_state != "Automatic") + { + logger.debug("unable to process profile for node", node, "rotary_switch_state != Automatic"); + return; } - const PRIORITY_TYPES = { - terminal: 0, - fw_detection: 1,//reserved only for FW detection - SETTINGS.masterNodeIsResponding - high_priority: 2,//reserverd only for: read dimming / brightness (after set dimming from platform) - relay_profile: 3, - node_broadcast: 4, - node_profile: 5, - node_cmd: 6 + let nodeObj = nodesData[node]; + let line = nodeObj.line; + + if(relaysData[line].contactor == 0) + { + logger.debug("line line is off", line, node); + return; } - const TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION = 600000; // 10 minutes - - //list of command calls to process. Processing in runTasks function - let tasks = []; - - let interval = null;//timeout for procesing tasks - let customTasksInterval = null; // interval for reportEdgeDateTimeAndNumberOfLuminaires(); - let setCorrectTime = null; // interval for setting a correct edgeTime - - let refFlowdataObj = {}; - - //load from settings - let latitude = 48.70826502;//48.682255758; - let longitude = 17.28455203;//17.278910807; - - const gmtOffset = 0; - - //ak nie je nastaveny - //https://www.tecmint.com/set-time-timezone-and-synchronize-time-using-timedatectl-command/ - //https://stackoverflow.com/questions/16086962/how-to-get-a-time-zone-from-a-location-using-latitude-and-longitude-coordinates - - //priorities for registers - let priorities = []; - - let minutes = 1; - priorities["0"] = minutes; - priorities["1"] = minutes; - - minutes = 5; - priorities["74"] = minutes; - priorities["75"] = minutes; - priorities["76"] = minutes; - priorities["77"] = minutes; - priorities["78"] = minutes; - priorities["79"] = minutes; - priorities["84"] = minutes; - - minutes = 10; - priorities["87"] = minutes; - priorities["6"] = minutes; - priorities["7"] = minutes; - priorities["80"] = minutes; - priorities["8"] = minutes; - priorities["3"] = minutes; - priorities["89"] = minutes; - - //prikazy kt sa budu spustat na dany node - see config.js in terminal-oms.app. (1 - dimming) - let listOfCommands = [0, 1, 3, 6, 7, 8, 74, 75, 76, 77, 78, 79, 80, 84, 87, 89]; - - const errorHandler = new ErrorToServiceHandler(); - - let rotary_switch_state; - let lux_sensor; - let state_of_breaker = {};//key is line, value is On/Off - let disconnectedReport = {};//key is tbname, value true/false - - let relaysData; - let nodesData; - let rvoTbName; - - let sunCalcResult; - let reportDuskDawn; - - //helper container for counting resolved group of commands (commands related to set profile) - let cmdCounter = {};//key is node, value is counter - - //END OF VARIABLE SETTINGS - //-------------------------------- - - - function main() { - GLOBALS = FLOW.GLOBALS; - SETTINGS = FLOW.GLOBALS.settings; - relaysData = GLOBALS.relaysData; - nodesData = GLOBALS.nodesData; - latitude = GLOBALS.settings.latitude; - longitude = GLOBALS.settings.longitude; - - tbHandler = new DataToTbHandler(SEND_TO.tb); - tbHandler.setSender(exports.title); - - //SETTINGS.project_id, name: SETTINGS.rvo_name; - //const errorHandler = new ErrorToServiceHandler(instance, SEND_TO.infoSender); - errorHandler.setProjectsId(SETTINGS.project_id); - //const errorHandler = new ErrorToServiceHandler(instance); - //errorHandler.sendMessageToService("ahoj", 0); - - let now = new Date(); - console.log("CMD Manager installed", now.toLocaleString("sk-SK")); - - sunCalcResult = calculateDuskDawn(); - - reportDuskDawn = { - dusk_time: sunCalcResult.dusk_time, - dawn_time: sunCalcResult.dawn_time, - dusk_time_reported: undefined, - dawn_time_reported: undefined - }; - - handleRsPort(); - - //to ensure, edgeDateTime will be send to tb at full minute - customTasksInterval = setInterval(function() { - if (new Date().getSeconds() === 0) reportEdgeDateTimeAndNumberOfLuminaires(); - }, 1000); - - setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour - setCorrectPlcTimeOnceADay(); + if(nodeObj.processed == 1) + { + logger.debug("node was already processed", node); + return; } + let profile = nodeObj.profile; - function cmdCounterResolve(address) { - if (cmdCounter.hasOwnProperty(address)) { - cmdCounter[address] = cmdCounter[address] - 1; + logger.debug("processNodeProfile: start - set profile for ", node, profile); - let result = cmdCounter[address]; - if (result == 0) delete cmdCounter[address]; - return result; - } - return -1; + let nodeProfile; + try{ + nodeProfile = JSON.parse( profile ); + if(Object.keys(nodeProfile).length === 0) throw ("profile is not defined"); + } catch (error) { + logger.debug("Error parsing node profile", error); + } + + logger.debug("processNodeProfile", node, line, nodeObj, nodeProfile); + + let timestamp = PRIORITY_TYPES.node_cmd; + + removeTask({type: "set_node_profile", address: node}); + cmdNOKNodeCounter[node] = 0; + + //co ked sa prave spracovava? + //if(cmdNOKNodeCounter[params.address] < 5) saveToTb = false; + + if(nodeProfile === undefined) + { + //vypneme profil nodu, posleme cmd + //Pokiaľ je hodnota rovná 1 – Profil sa zapne, ostatné bity sa nezmenia. + //Pokiaľ sa hodnota rovná 2 – profil sa vypne, ostatné bity sa nezmenia + + logger.debug("turn off profile"); + + let params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "set_node_profile"; + params.address = node; + params.byte1 = 0; + params.byte2 = 0; + params.byte3 = 0; + params.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + params.addMinutesToTimestamp = 0; + params.info = 'turn off/reset node profile'; + + cmdCounter[node] = 1; + + tasks.push(params); + + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.NOTICE, "Master node is working again", "", SEND_TO.tb, instance ); } - - - function getParams(priority) { - let params = {}; - - //core rpc values - params.address = 0;//if(recipient === 0) address = 0; - params.byte1 = 0;//msb, podla dokumentacie data3 - params.byte2 = 0;//podla dokumentacie data2 - params.byte3 = 0;//podla dokumentacie data1 - params.byte4 = 0;//lsb, podla dokumentacie data0 - params.recipient = 0;//0: Master, 1: Slave, 2: Broadcast - params.register = -1;//register number - params.rw = 0;//0: read, 1: write - - //other values - //params.type = "cmd"; "relay" "cmd-terminal" "set_node_profile" "process_profiles" - //params.tbname = tbname; - params.priority = PRIORITY_TYPES.node_cmd; //default priority - if more tasks with the same timestamp, we sort them based on priority - params.timestamp = 0; //execution time - if timestamp < Date.now(), the task is processed - if (priority != undefined) { - params.timestamp = priority; - params.priority = priority; - } - - params.addMinutesToTimestamp = 0;//repeat task if value is > 0, - - //params.timePointName = "luxOff" // "luxOn", "dusk", "dawn", "profileTimepoint" - //params.info = ""; - //params.debug = true; // will console.log params in writeData response - - return params; - } - - - //nastav profil nodu - function processNodeProfile(node) { - if (rotary_switch_state != "Automatic") { - logger.debug("unable to process profile for node", node, "rotary_switch_state != Automatic"); - return; - } - - let nodeObj = nodesData[node]; - let line = nodeObj.line; - - if (relaysData[line].contactor == 0) { - logger.debug("line line is off", line, node); - return; - } - - if (nodeObj.processed == 1) { - //logger.debug("node was already processed", node); - return; - } - - let nodeProfile = nodeObj.profile; - logger.debug("processNodeProfile: start - set profile for ", node, nodeProfile); - if (nodeProfile) { - - try { - nodeProfile = JSON.parse(nodeProfile); - } catch (error) { - logger.debug("Cmd_manager - Error parsing node profile", error); - } - - } - - logger.debug("processNodeProfile", node, line, nodeObj, nodeProfile); - - let timestamp = PRIORITY_TYPES.node_cmd; - - removeTask({ type: "set_node_profile", address: node }); - - if (nodeProfile === "") { - //vypneme profil nodu, posleme cmd - //Pokiaľ je hodnota rovná 1 – Profil sa zapne, ostatné bity sa nezmenia. - //Pokiaľ sa hodnota rovná 2 – profil sa vypne, ostatné bity sa nezmenia - - logger.debug("turn off profile"); - - let params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "set_node_profile"; - params.address = node; - params.byte1 = 0; - params.byte2 = 0; - params.byte3 = 0; - params.byte4 = 96; - params.recipient = 1; - params.register = 8; - params.rw = 1;//write - params.timestamp = timestamp; - params.addMinutesToTimestamp = 0; - params.info = 'turn off/reset node profile'; - - cmdCounter[node] = 1; - - tasks.push(params); - } - else { - let tasksProfile = []; - - //vypneme profil - Zapísať hodnotu 32 do registra Time Schedule Settings – reset profilu - let params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "set_node_profile"; - params.address = node; - params.byte1 = 0; - params.byte2 = 0; - params.byte3 = 0; - params.byte4 = 96; - params.recipient = 1; - params.register = 8; - params.rw = 1;//write - params.timestamp = timestamp; - params.addMinutesToTimestamp = 0; - params.info = 'turn off node profile'; - - tasksProfile.push(params); - - timestamp++; - - logger.debug("processNodeProfile: TS1 Time point a TS1 Time Point Levels ", node); - - //TS1 Time point a TS1 Time Point Levels - let register = 9; - for (let i = 0; i < nodeProfile.intervals.length; i++) { - let obj = nodeProfile.intervals[i]; - //let timePoint = obj.time_point; - let dim_value = obj.value; - - - //Reg 9 až Reg 40 - - /* - Samotný profil sa zapisuje do max. 16 párov – časový bod a úroveň. - Prázdny profil je vtedy keď časový bod obsahuje hodnotu 0xFFFFFFFF (táto hodnota sa zapíše do registrov keď sa aktivuje reset profilu do registru 8). - Páry sa prechádzajú časovo zoradené takže teoreticky je jedno v akom poradí sa zapisujú ale je lepšie ich zapisovať v chronologickom poradí od 13:00. - Časový bod má formát: - Byte 3: hodiny Byte 2: minúty Byte 1: sekundy Byte 0 – rezervované - Register úrovne má rovnaký formát ako dimming register (Reg 1). - */ - - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - //params.byte1 = 0;//msb, podla dokumentacie data3 - //params.byte2 = 0;//podla dokumentacie data2 - //params.byte3 = 0;//podla dokumentacie data1 - //params.byte4 = 0;//lsb, podla dokumentacie data0 - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - let start_time = obj.start_time; - let t = start_time.split(":"); - //if(timePoint != undefined) t = timePoint.split(":"); - //else t = [0,0]; - - logger.debug("processNodeProfile: TS1 Time point ", (i + 1), node); - - params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "set_node_profile"; - params.address = node; - params.byte1 = parseInt(t[0]);//hh - params.byte2 = parseInt(t[1]);//mm - params.byte3 = 0;//ss - params.byte4 = 0;// - params.recipient = 1; - params.register = register; - params.rw = 1;//write - params.timestamp = timestamp; - params.addMinutesToTimestamp = 0; - params.info = 'TS1 Time point ' + (i + 1); - - tasksProfile.push(params); - - register++; - timestamp++; - - params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "set_node_profile"; - params.address = node; - params.byte1 = 0; - params.byte2 = 0; - params.byte3 = 0;//ss - params.byte4 = parseInt(dim_value) + 128;// - params.recipient = 1; - params.register = register; - params.rw = 1;//write - params.timestamp = timestamp; - params.addMinutesToTimestamp = 0; - params.info = 'TS1 Time point Levels ' + (i + 1); - - tasksProfile.push(params); - - register++; - timestamp++; - } - - //Threshold lux level for DUSK/DAWN - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - //params.byte1 = 0;//msb, podla dokumentacie data3 - //params.byte2 = 0;//podla dokumentacie data2 - //params.byte3 = 0;//podla dokumentacie data1 - //params.byte4 = 0;//lsb, podla dokumentacie data0 - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - - //Time schedule settings na koniec - //if(nodeProfile.dusk_lux_sensor || nodeProfile.dawn_lux_sensor) - { - - logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); - - let params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "set_node_profile"; - params.address = node; - params.register = 96; - params.recipient = 1; - params.rw = 1;//write - params.timestamp = timestamp; - params.addMinutesToTimestamp = 0; - params.info = "Threshold lux level for DUSK/DAWN"; - - if (nodeProfile.dusk_lux_sensor) { - let v = nodeProfile.dusk_lux_sensor_value; - let ba = longToByteArray(v); - - params.byte1 = ba[1];//msb - params.byte2 = ba[0]; - } - - if (nodeProfile.dawn_lux_sensor) { - let v = nodeProfile.dawn_lux_sensor_value; - let ba = longToByteArray(v); - - params.byte3 = ba[1];//msb - params.byte4 = ba[0]; - } - - tasksProfile.push(params); - timestamp++; - - } - - //DUSK/DAWN max. adjust period - { - - logger.debug("processNodeProfile: DUSK/DAWN max. adjust period", node); - - let params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "set_node_profile"; - params.address = node; - params.register = 97; - params.recipient = 1; - params.rw = 1;//write - params.timestamp = timestamp; - params.addMinutesToTimestamp = 0; - params.info = "DUSK/DAWN max. adjust period"; - - if (nodeProfile.astro_clock) { - let v = nodeProfile.dusk_lux_sensor_time_window; - let ba = longToByteArray(v); - - params.byte1 = ba[1];//msb - params.byte2 = ba[0]; - } - - if (nodeProfile.astro_clock) { - let v = nodeProfile.dawn_lux_sensor_time_window; - let ba = longToByteArray(v); - - params.byte3 = ba[1];//msb - params.byte4 = ba[0]; - } - - tasksProfile.push(params); - timestamp++; - - } - - //Static offset - { - - //Statický offset pre časy úsvitu a súmraku. Byte 1 je pre DUSK, Byte 0 je pre DAWN. Formát: - //Bity 0 – 6: hodnota v minútach - //Bit 7: znamienko (1 – mínus) - - logger.debug("processNodeProfile: Static offset", node); - - let params = getParams(PRIORITY_TYPES.node_cmd); - params.type = "set_node_profile"; - params.address = node; - params.register = 98; - params.recipient = 1; - params.rw = 1;//write - params.timestamp = timestamp; - params.addMinutesToTimestamp = 0; - params.info = "Static offset"; - - if (nodeProfile.astro_clock) { - let dusk_astro_clock_offset = parseInt(nodeProfile.dusk_astro_clock_offset); - let dawn_astro_clock_offset = parseInt(nodeProfile.dawn_astro_clock_offset); - - if (dusk_astro_clock_offset < 0) { - params.byte3 = (dusk_astro_clock_offset * -1) + 128; - } - else { - params.byte3 = dusk_astro_clock_offset; - } - - if (dawn_astro_clock_offset < 0) { - params.byte4 = (dawn_astro_clock_offset * -1) + 128; - } - else { - params.byte4 = dawn_astro_clock_offset; - } - } - - tasksProfile.push(params); - timestamp++; - } - - logger.debug("Time schedule settings - turn on", node); + else + { + let tasksProfile = []; + //cmdCounter[node] = tasksProfile.length; + //tasks.push(tasksProfile); + + //let timestamp = PRIORITY_TYPES.node_cmd; + + //vypneme profil - Zapísať hodnotu 32 do registra Time Schedule Settings – reset profilu + let params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "set_node_profile"; + params.address = node; + params.byte1 = 0; + params.byte2 = 0; + params.byte3 = 0; + params.byte4 = 96; + params.recipient = 1; + params.register = 8; + params.rw = 1;//write + params.timestamp = timestamp; + params.addMinutesToTimestamp = 0; + params.info = 'turn off node profile'; + + tasksProfile.push(params); + + timestamp++; + + logger.debug("processNodeProfile: TS1 Time point a TS1 Time Point Levels ", node); + + //TS1 Time point a TS1 Time Point Levels + let register = 9; + for(let i = 0; i < nodeProfile.intervals.length; i++) + { + let obj = nodeProfile.intervals[i]; + //let timePoint = obj.time_point; + let dim_value = obj.value; + + + //Reg 9 až Reg 40 + + /* + Samotný profil sa zapisuje do max. 16 párov – časový bod a úroveň. + Prázdny profil je vtedy keď časový bod obsahuje hodnotu 0xFFFFFFFF (táto hodnota sa zapíše do registrov keď sa aktivuje reset profilu do registru 8). + Páry sa prechádzajú časovo zoradené takže teoreticky je jedno v akom poradí sa zapisujú ale je lepšie ich zapisovať v chronologickom poradí od 13:00. + Časový bod má formát: + Byte 3: hodiny Byte 2: minúty Byte 1: sekundy Byte 0 – rezervované + Register úrovne má rovnaký formát ako dimming register (Reg 1). + */ + + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //params.byte1 = 0;//msb, podla dokumentacie data3 + //params.byte2 = 0;//podla dokumentacie data2 + //params.byte3 = 0;//podla dokumentacie data1 + //params.byte4 = 0;//lsb, podla dokumentacie data0 + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + let start_time = obj.start_time; + let t = start_time.split(":"); + //if(timePoint != undefined) t = timePoint.split(":"); + //else t = [0,0]; + + logger.debug("processNodeProfile: TS1 Time point ", (i + 1), node); params = getParams(PRIORITY_TYPES.node_cmd); params.type = "set_node_profile"; params.address = node; - params.register = 8; + params.byte1 = parseInt(t[0]);//hh + params.byte2 = parseInt(t[1]);//mm + params.byte3 = 0;//ss + params.byte4 = 0;// params.recipient = 1; + params.register = register; params.rw = 1;//write - - //Time schedule settings - let bits = []; - - //Byte 0 (LSB): - //Bit 0 (LSB) – zapnutie/vypnutie profilov ako takých (1 – zapnuté). - bits.push(1); - //Bit 1 – 3 - zatiaľ nepoužité (zapisovať 0) - bits.push(0); - bits.push(0); - bits.push(0); - if (nodeProfile.astro_clock == true) { - //Bit 4 – ak je nastavený profil sa riadi podľa astrohodín, a je 0 tak profil je jednoduchý - bits.push(1); - } - else bits.push(0); - - //Bit 5 – zápis 1 spôsobí reset nastavení profilu (nastavenie prázdneho profilu) - bits.push(0); - - //Bity 6-7 - zatiaľ nepoužité - bits.push(0); - bits.push(0); - - params.byte4 = bitwise.byte.write(bits.reverse()); - - //Byte 2 – nastavenie pre lux senzor: - bits = []; - - //Bit 0 (LSB) – riadenie súmraku podľa lux senzoru (1 – zapnuté). Súmrak sa môže posúvať v rámci času v registri 97 podľa intenzity osvetlenia - if (nodeProfile.dusk_lux_sensor == true)//sumrak - { - bits.push(1); - } - else bits.push(0); - - //Bit 1 - riadenie úsvitu podľa lux senzoru (1 – zapnuté). Úsvit sa môže posúvať v rámci času v registri 97 podľa intenzity osvetlenia - if (nodeProfile.dawn_lux_sensor == true)//usvit - { - bits.push(1); - } - else bits.push(0); - - //Bit 2 – zdroj pre hodnotu luxov – 0 – RVO posiela hodnoty zo svojho luxmetra, 1 – node má pripojený svoj vlastný lux meter. - bits.push(0);//zatial neimplementovane - - //Bit 3 – 7 - nepoužité - bits.push(0); - bits.push(0); - bits.push(0); - bits.push(0); - bits.push(0); - - params.byte2 = bitwise.byte.write(bits.reverse()); params.timestamp = timestamp; - params.info = "Time schedule settings - turn on"; + params.addMinutesToTimestamp = 0; + params.info = 'TS1 Time point ' + (i + 1); tasksProfile.push(params); - //zaver - cmdCounter[node] = tasksProfile.length; + register++; + timestamp++; - //tasks.push(tasksProfile); - tasks = tasks.concat(tasksProfile); + params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "set_node_profile"; + params.address = node; + params.byte1 = 0; + params.byte2 = 0; + params.byte3 = 0;//ss + params.byte4 = parseInt(dim_value) + 128;// + params.recipient = 1; + params.register = register; + params.rw = 1;//write + params.timestamp = timestamp; + params.addMinutesToTimestamp = 0; + params.info = 'TS1 Time point Levels ' + (i + 1); + tasksProfile.push(params); + + register++; + timestamp++; } - logger.debug("finished set profile for ", node); - - console.log("proces profile finished *********************") - } + //Threshold lux level for DUSK/DAWN + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //params.byte1 = 0;//msb, podla dokumentacie data3 + //params.byte2 = 0;//podla dokumentacie data2 + //params.byte3 = 0;//podla dokumentacie data1 + //params.byte4 = 0;//lsb, podla dokumentacie data0 + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - function cleanUpRefFlowdataObj() { - let now = new Date(); - let timestamp = now.getTime(); + //Time schedule settings na koniec + //if(nodeProfile.dusk_lux_sensor || nodeProfile.dawn_lux_sensor) + { - //clear old refFlowdata references - let keys = Object.keys(refFlowdataObj); - for (let i = 0; i < keys.length; i++) { - let timestampKey = keys[i]; + logger.debug("processNodeProfile: Threshold lux level for DUSK/DAWN", node); - if ((timestamp - timestampKey) > 60 * 1000) { - console.log("cleanUpRefFlowdataObj delete", timestampKey); - delete refFlowdataObj[timestampKey]; + let params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "set_node_profile"; + params.address = node; + params.register = 96; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + params.addMinutesToTimestamp = 0; + params.info = "Threshold lux level for DUSK/DAWN"; + + if(nodeProfile.dusk_lux_sensor) + { + let v = nodeProfile.dusk_lux_sensor_value; + let ba = longToByteArray(v); + + params.byte1 = ba[1];//msb + params.byte2 = ba[0]; } + + if(nodeProfile.dawn_lux_sensor) + { + let v = nodeProfile.dawn_lux_sensor_value; + let ba = longToByteArray(v); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + } + + tasksProfile.push(params); + timestamp++; + } - } + //DUSK/DAWN max. adjust period + { - function removeTask(obj) { - let keys = Object.keys(obj); - tasks = tasks.filter((task) => { + logger.debug("processNodeProfile: DUSK/DAWN max. adjust period", node); - let counter = 0; - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; - if (task.hasOwnProperty(key) && obj.hasOwnProperty(key)) { - if (task[key] == obj[key]) counter++; + let params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "set_node_profile"; + params.address = node; + params.register = 97; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + params.addMinutesToTimestamp = 0; + params.info = "DUSK/DAWN max. adjust period"; + + if(nodeProfile.astro_clock) + { + let v = nodeProfile.dusk_lux_sensor_time_window; + let ba = longToByteArray(v); + + params.byte1 = ba[1];//msb + params.byte2 = ba[0]; + } + + if(nodeProfile.astro_clock) + { + let v = nodeProfile.dawn_lux_sensor_time_window; + let ba = longToByteArray(v); + + params.byte3 = ba[1];//msb + params.byte4 = ba[0]; + } + + tasksProfile.push(params); + timestamp++; + + } + + //Static offset + { + + //Statický offset pre časy úsvitu a súmraku. Byte 1 je pre DUSK, Byte 0 je pre DAWN. Formát: + //Bity 0 – 6: hodnota v minútach + //Bit 7: znamienko (1 – mínus) + + logger.debug("processNodeProfile: Static offset", node); + + let params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "set_node_profile"; + params.address = node; + params.register = 98; + params.recipient = 1; + params.rw = 1;//write + params.timestamp = timestamp; + params.addMinutesToTimestamp = 0; + params.info = "Static offset"; + + if(nodeProfile.astro_clock) + { + let dusk_astro_clock_offset = parseInt(nodeProfile.dusk_astro_clock_offset); + let dawn_astro_clock_offset = parseInt(nodeProfile.dawn_astro_clock_offset); + + if(dusk_astro_clock_offset < 0) + { + params.byte3 = (dusk_astro_clock_offset * -1) + 128; + } + else + { + params.byte3 = dusk_astro_clock_offset; + } + + if(dawn_astro_clock_offset < 0) + { + params.byte4 = (dawn_astro_clock_offset * -1) + 128; + } + else + { + params.byte4 = dawn_astro_clock_offset; } } - if (counter == keys.length) return false; - return true; - }); + tasksProfile.push(params); + timestamp++; + } + + logger.debug("Time schedule settings - turn on", node); + + params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "set_node_profile"; + params.address = node; + params.register = 8; + params.recipient = 1; + params.rw = 1;//write + + + + //Time schedule settings + let bits = []; + + //Byte 0 (LSB): + //Bit 0 (LSB) – zapnutie/vypnutie profilov ako takých (1 – zapnuté). + bits.push(1); + //Bit 1 – 3 - zatiaľ nepoužité (zapisovať 0) + bits.push(0); + bits.push(0); + bits.push(0); + if(nodeProfile.astro_clock == true) + { + //Bit 4 – ak je nastavený profil sa riadi podľa astrohodín, a je 0 tak profil je jednoduchý + bits.push(1); + } + else bits.push(0); + + //Bit 5 – zápis 1 spôsobí reset nastavení profilu (nastavenie prázdneho profilu) + bits.push(0); + + //Bity 6-7 - zatiaľ nepoužité + bits.push(0); + bits.push(0); + + params.byte4 = bitwise.byte.write(bits.reverse()); + + //Byte 2 – nastavenie pre lux senzor: + bits = []; + + //Bit 0 (LSB) – riadenie súmraku podľa lux senzoru (1 – zapnuté). Súmrak sa môže posúvať v rámci času v registri 97 podľa intenzity osvetlenia + if(nodeProfile.dusk_lux_sensor == true)//sumrak + { + bits.push(1); + } + else bits.push(0); + + //Bit 1 - riadenie úsvitu podľa lux senzoru (1 – zapnuté). Úsvit sa môže posúvať v rámci času v registri 97 podľa intenzity osvetlenia + if(nodeProfile.dawn_lux_sensor == true)//usvit + { + bits.push(1); + } + else bits.push(0); + + //Bit 2 – zdroj pre hodnotu luxov – 0 – RVO posiela hodnoty zo svojho luxmetra, 1 – node má pripojený svoj vlastný lux meter. + bits.push(0);//zatial neimplementovane + + //Bit 3 – 7 - nepoužité + bits.push(0); + bits.push(0); + bits.push(0); + bits.push(0); + bits.push(0); + + params.byte2 = bitwise.byte.write(bits.reverse()); + params.timestamp = timestamp; + params.info = "Time schedule settings - turn on"; + + tasksProfile.push(params); + + //zaver + cmdCounter[node] = tasksProfile.length; + + //tasks.push(tasksProfile); + tasks = tasks.concat(tasksProfile); + } + logger.debug("finished set profile for ", node); + +} + + +function cleanUpRefFlowdataObj() +{ + let now = new Date(); + let timestamp = now.getTime(); + + //clear old refFlowdata references + let keys = Object.keys(refFlowdataObj); + for(let i = 0; i < keys.length; i++) + { + let timestampKey = keys[i]; + + if((timestamp - timestampKey) > 60*1000 ) + { + console.log("cleanUpRefFlowdataObj delete", timestampKey); + delete refFlowdataObj[ timestampKey ]; + } + } +} + + +function removeTask(obj) +{ + let keys = Object.keys(obj); + tasks = tasks.filter((task) => { + + let counter = 0; + for(let i = 0; i < keys.length; i++) + { + let key = keys[i]; + if(task.hasOwnProperty(key) && obj.hasOwnProperty(key)) + { + if(task[key] == obj[key]) counter++; + } + } + + if(counter == keys.length) return false; + return true; + }); +} + + + + +exports.install = function(instance) { + + let now = new Date(); + console.log("CMD Manager installed", now.toLocaleString("sk-SK")); + + const tbHandler = new DataToTbHandler(SEND_TO.tb); + tbHandler.setSender(exports.title); + + //FLOW.OMS_projects_id, name: FLOW.OMS_rvo_name + //const errorHandler = new ErrorToServiceHandler(instance, SEND_TO.infoSender); + errorHandler.setProjectsId(FLOW.OMS_projects_id); + //const errorHandler = new ErrorToServiceHandler(instance); + //errorHandler.sendMessageToService("ahoj", 0); + + let sunCalcResult = calculateDuskDawn(); + + let reportDuskDawn = { + dusk_time: sunCalcResult.dusk_time, + dawn_time: sunCalcResult.dawn_time, + dusk_time_reported: undefined, + dawn_time_reported: undefined + }; + + + process.on('uncaughtException', function (err) { - process.on('uncaughtException', function(err) { //TODO send to service - + errLogger.error('uncaughtException:', err.message) errLogger.error(err.stack); errorHandler.sendMessageToService(err.message + "\n" + err.stack, 0, "js_error"); //process.exit(1); }) - + //te();//force error - function processAllNodeProfilesOnLine(line) { + function processAllNodeProfilesOnLine(line) + { + for (let k in nodesData) { - if (line == nodesData[k].line) { + //node:number|tbname:string|line:number|profile:string|processed:boolean + + if(line == nodesData[k].line) + { let node = nodesData[k].node; let processed = nodesData[k].processed; - if (!processed) processNodeProfile(node); - //else logger.debug( `Node ${node} profile for line ${nodesData[k].line} was already processed`); + if(!processed) + { + processNodeProfile(node); + } + else + { + logger.debug( `Node ${node} profile for line ${nodesData[k].line} was already processed`); + } } - } + } } - function loadRelaysData(line) { - for (const [key, value] of Object.entries(relaysData)) { - if (key == "0") continue; - if (line != undefined) { + async function loadRelaysData(line) { + + relaysData = await promisifyBuilder(dbRelays.find()); + relaysData = makeMapFromDbResult(relaysData, "line"); + + for (const [key, value] of Object.entries(relaysData)) + { + if(key == "0") continue; + if(line != undefined) + { //ak sa jedna o update profilu linie - pozor dido_controller posiela command pre loadRelaysData - if (line != value.line) continue; + if(line != value.line ) continue; } - if (value.contactor == 1) processAllNodeProfilesOnLine(value.line); + if(value.contactor == 1) processAllNodeProfilesOnLine(value.line); } + +// console.log('.........', relaysData); } - function reportOnlineNodeStatus(line) { + function reportOnlineNodeStatus(line) + { //broadcast cas, o 3 sek neskor - status, brightness //Po zapnutí línie broadcastovo aktualizovať predtým čas. logger.debug("--->reportOnlineNodeStatus for line", line); //return; - + //run broadcast //Actual time addMinutesToTimestamp = 0; let params = {}; + let recipient = 2;//2 broadcast, address = 0 + let address = 0;//0 + if(recipient === 2) + { + address = 0xffffffff;//Broadcast + } + var d = new Date(); let hours = d.getHours(); let minutes = d.getMinutes(); let seconds = d.getSeconds(); - let time = d.getTime(); // time in ms - - params.address = 0xffffffff;//Broadcast + params.address = address;//broadcast params.byte1 = hours;//h params.byte2 = minutes;//m params.byte3 = seconds;//s params.byte4 = 0; - params.recipient = 2;//2 broadcast, address = 0 + params.recipient = recipient; params.register = 87;//Actual time params.rw = 1;//write + let timestampStart = PRIORITY_TYPES.node_broadcast; + //other values params.type = "cmd"; - params.timestamp = Date.now() + 60000; + //params.tbname = tbname; + params.timestamp = timestampStart; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "run broadcast: Actual time"; tasks.push(params); let sec = 3; - setTimeout(function() { + setTimeout(function(){ //Po zapnutí línie - spraviť hromadný refresh stavu práve zapnutých svietidiel for (let k in nodesData) { - + //potrebujem nody k danej linii - if (line == nodesData[k].line || line == undefined) { + if(line == nodesData[k].line || line == undefined) + { let tbname = nodesData[k].tbname; let node = nodesData[k].node; - let status = "NOK"; - - // if status of node was "OK" before switching it off, we set the node's time_of_last_communication on time, it was switched on again and send OK status to tb. - if (nodesData[k].status) { - status = "OK"; - nodesData[k].time_of_last_communication = time; - } - - sendTelemetry({ status: status }, tbname, time); //prud, vykon - current, input power pre liniu pre vsetky nody - + //a pridame aj vyreportovanie dimmingu { let params = getParams(PRIORITY_TYPES.high_priority); @@ -781,43 +878,68 @@ exports.install = function(instance) { } } } - }, sec * 1000); + },sec*1000); } - function reportOfflineNodeStatus(line) { + function reportOfflineNodeStatus(line) + { logger.debug("--->reportOfflineNodeStatus for line", line); values = {}; values["dimming"] = 0;//brightness values["power"] = 0;//výkon values["current"] = 0;//prúd - values["status"] = "OFFLINE"; + values["status"] = "OFFLINE";//prúd + + for (let k in nodesData) { + + //potrebujem nody k danej linii + if(line == nodesData[k].line || line == undefined) + { + let tbname = nodesData[k].tbname; - const date = Date.now(); + //logger.debug("node:", tbname); + + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); + } + } - // it happens, that some data did not get to tb after sending - // we setTimeout to make more time for db to process telemetry (eg 150 messages at once) - Object.keys(nodesData).forEach((node, index) => { - - setTimeout(function() { - - //potrebujem nody k danej linii - if (line == nodesData[node].line || line == undefined) { - let tbname = nodesData[node].tbname; - sendTelemetry(values, tbname, date) - } - - }, (index + 1) * 1000); - }) + //report OFFLINE for line + //relaysData[line].tbname; + //values = {}; + //values["status"] = "OFFLINE";//prúd } - function turnLine(onOrOff, line, info) { + function turnOnLine(line, info) + { let obj = { line: line, - command: onOrOff, + command: "turnOn", + info: info + }; + + logger.debug("linia", line, obj); + instance.send(SEND_TO.dido_controller, obj); + } + + function turnOffLine(line, info) + { + let obj = { + line: line, + command: "turnOff", info: info }; @@ -826,40 +948,40 @@ exports.install = function(instance) { } - - function detectIfResponseIsValid(bytes) { + function detectIfResponseIsValid(bytes) + { //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK let type = "RESPONSE"; - if (bytes.length == 1) type = "BROADCAST"; // odpoved z rsPortu na broadcast command: ["broadcast"] - else if (bytes[4] == 0) type = "RESPONSE"; - else if (bytes[4] == 1) type = "ERROR"; - else if (bytes[4] == 2) type = "EVENT"; + if(bytes[4] == 0) type = "RESPONSE"; + else if(bytes[4] == 1) type = "ERROR"; + else if(bytes[4] == 2) type = "EVENT"; else type = "UNKNOWN"; - - let message = "OK"; - let error = ""; - if (type == "BROADCAST") return { message, type, error }; - + let crc = crc16('ARC', bytes.slice(0, 9)); let c1 = (crc >> 8) & 0xFF; let c2 = crc & 0xFF; - - if (c1 != bytes[9]) { + + let message = "OK"; + let error = ""; + if(c1 != bytes[9]) + { //CRC_ERROR message = "NOK"; error = "CRC_ERROR c1"; instance.send(SEND_TO.debug, "CRC_ERROR c1"); } - - if (c2 != bytes[10]) { + + if(c2 != bytes[10]) + { //CRC_ERROR message = "NOK"; error = "CRC_ERROR c2"; instance.send(SEND_TO.debug, "CRC_ERROR c2"); } - + //crc error - if (type != "RESPONSE") { + if(type != "RESPONSE") + { instance.send(SEND_TO.debug, bytes); instance.send(SEND_TO.debug, "RESPONSE " + type + " - " + bytes[4]); @@ -869,18 +991,18 @@ exports.install = function(instance) { message = "NOK"; } - - return { message, type, error }; + + return {message: message, type: type, error: error}; } //BUILD TASKS// - function buildTasks(params) { - //report SETTINGS.edge_fw_version as fw_version + function buildTasks(params) + { + //report FLOW.OMS_edge_fw_version as fw_version //report date as startdate //return; - console.log("buidTAaasks start ****************", params); monitor.info("buildTasks - params", params); @@ -890,12 +1012,14 @@ exports.install = function(instance) { let processBroadcast = true; let processNodes = true; - if (params == undefined) { + if(params == undefined) + { init = true; tasks = []; logger.debug("-->buildTasks clear tasks"); } - else { + else + { processLineProfiles = false; processBroadcast = false; processNodes = false; @@ -904,18 +1028,23 @@ exports.install = function(instance) { processLine = params.line; } - //load profiles pre vsetky linie: + //load profiles pre linie + //relaysData[ record["line"] ] + let now = new Date(); - if (processLineProfiles) { + if(processLineProfiles) + { //process line profiles let keys = Object.keys(relaysData); - for (let i = 0; i < keys.length; i++) { + for(let i = 0; i < keys.length; i++) + { let line = parseInt(keys[i]); //line is turned off by default let profilestr = relaysData[line].profile; - if (processLine != undefined) { - if (processLine != line) continue; + if(processLine != undefined) + { + if(processLine != line) continue; } try { @@ -923,14 +1052,15 @@ exports.install = function(instance) { /** * we process line profiles: timepoints, astro clock, lux_sensor, offsets ... */ - if (profilestr === "") throw ("Profile is not defined"); + if(profilestr === "") throw ("Profile is not defined"); let profile = JSON.parse(profilestr); - if (Object.keys(profile).length === 0) throw ("Profile is empty"); + if(Object.keys(profile).length === 0) throw ("Profile is empty"); monitor.info("buildTasks: profile for line", line); monitor.info("profile:", profile); - let time_points = profile.intervals; + let time_points = profile.time_points; + if(time_points == undefined) time_points = profile.intervals; // add name to regular profile timepoint and delete unused end_time key: time_points.forEach(point => { @@ -940,13 +1070,17 @@ exports.install = function(instance) { //monitor.info("buildTasks: time_points", time_points); + let currentValue = 0; + if(time_points.length > 0) currentValue = time_points[time_points.length - 1].value; + /** * if astro_clock is true, we create timepoints, that switch on/off relays accordingly. * we need to manage, astro clock timepoints has the greatest priority - normal timepoints will not switch off/on lines before dusk or dawn * if dawn/dusk_lux_sensor is true, it has higher priority than astro_clock switching */ - if (profile.astro_clock == true) { + if(profile.astro_clock == true) + { // if astro clock true, we remove all regular profile points time_points = []; @@ -954,66 +1088,80 @@ exports.install = function(instance) { let sunCalcResult = calculateDuskDawn(new Date(), line); // adding dusk dawn to timpoints - if (profile.dawn_lux_sensor == false) time_points.push({ "start_time": sunCalcResult["dawn"], "value": 0, "name": "dawn" }); - if (profile.dusk_lux_sensor == false) time_points.push({ "start_time": sunCalcResult["dusk"], "value": 1, "name": "dusk" }); + if(profile.dawn_lux_sensor == false) time_points.push({"start_time": sunCalcResult["dawn"], "value": 0, "name":"dawn"}); + if(profile.dusk_lux_sensor == false) time_points.push({"start_time": sunCalcResult["dusk"], "value": 1, "name":"dusk"}); //if dusk/dawn is true, lines will switch on/off according to lux_sensor value. In case it fails, we create lux_timepoints, to make sure lines will switch on/off (aby nam to nezostalo svietit) //force to turn off after timestamp: dawn + dawn_lux_sensor_time_window - if (profile.dawn_lux_sensor == true) { - let [ahours, aminutes] = sunCalcResult["dawn"].split(':'); - let ad = new Date(); - ad.setHours(parseInt(ahours), parseInt(aminutes) + profile.dawn_lux_sensor_time_window, 0); + if(profile.dawn_lux_sensor == true) + { + let [ahours, aminutes, aseconds] = sunCalcResult["dawn"].split(':'); + let ad = new Date(); + ad.setHours(parseInt(ahours)); + ad.setMinutes(parseInt(aminutes) + profile.dawn_lux_sensor_time_window); + ad.setSeconds(0); - let strDate = ad.getHours() + ":" + ad.getMinutes(); - time_points.push({ "value": 0, "start_time": strDate, "name": "luxOff" }); + let strDate = ad.getHours() + ":" + ad.getMinutes(); + + time_points.push({"value": 0, "start_time": strDate, "name": "luxOff"}); } - if (profile.dusk_lux_sensor == true) { - let [ahours, aminutes] = sunCalcResult["dusk"].split(':'); - let ad = new Date(); - ad.setHours(parseInt(ahours), parseInt(aminutes) + profile.dusk_lux_sensor_time_window, 0); + if(profile.dusk_lux_sensor == true) + { + let [ahours, aminutes, aseconds] = sunCalcResult["dusk"].split(':'); + let ad = new Date(); + ad.setHours(parseInt(ahours)); + ad.setMinutes(parseInt(aminutes) + profile.dusk_lux_sensor_time_window); + ad.setSeconds(0); - let strDate = ad.getHours() + ":" + ad.getMinutes(); - time_points.push({ "value": 1, "start_time": strDate, "name": "luxOn" }); - //time_points.push({"value": 1, "start_time": "15:19", "name": "luxOn"}); //testing + let strDate = ad.getHours() + ":" + ad.getMinutes(); + + time_points.push({"value": 1, "start_time": strDate, "name": "luxOn"}); + //time_points.push({"value": 1, "start_time": "15:19", "name": "luxOn"}); //testing } } //sort time_points - time_points.sort(function(a, b) { - - let [ahours, aminutes] = a.start_time.split(':'); - let [bhours, bminutes] = b.start_time.split(':'); + time_points.sort(function (a, b) { + let [ahours, aminutes, aseconds] = a.start_time.split(':'); + let [bhours, bminutes, bseconds] = b.start_time.split(':'); + let ad = new Date(); - ad.setHours(parseInt(ahours), parseInt(aminutes), 0); - + ad.setHours( parseInt(ahours) ); + ad.setMinutes( parseInt(aminutes) ); + ad.setSeconds(0); + let bd = new Date(); - bd.setHours(parseInt(bhours), parseInt(bminutes), 0); - + bd.setHours( parseInt(bhours) ); + bd.setMinutes( parseInt(bminutes) ); + ad.setSeconds(0); + return ad.getTime() - bd.getTime(); }); console.log("line timepoints ........", time_points); - let currentValue = 0; - if (time_points.length > 0) currentValue = time_points[time_points.length - 1].value; - monitor.info("-->comming events turn on/off lines:"); - for (let t = 0; t < time_points.length; t++) { - + for(let t = 0; t < time_points.length; t++) + { + let start_time = new Date(); - let [hours, minutes] = time_points[t].start_time.split(':'); - start_time.setHours(parseInt(hours), parseInt(minutes), 0); + let [hours, minutes, seconds] = time_points[t].start_time.split(':'); - //task is in the past - if (now.getTime() > start_time.getTime()) { + start_time.setHours( parseInt(hours) ); + start_time.setMinutes( parseInt(minutes) ); + start_time.setSeconds(0); + + //task is the past + if(now.getTime() > start_time.getTime()) + { currentValue = time_points[t].value; //timepoint is in past, we add 24 hours start_time.setDate(start_time.getDate() + 1); } - + let params = getParams(PRIORITY_TYPES.relay_profile); params.type = "relay"; params.line = parseInt(line); @@ -1024,30 +1172,32 @@ exports.install = function(instance) { params.addMinutesToTimestamp = 0; // it timepoints are not calculated (dawn, dusk, lux_timepoint), but static points in line profile, we just repeat the task every day - if (time_points[t].name == "profileTimepoint") params.addMinutesToTimestamp = 24 * 60; + if(time_points[t].name == "profileTimepoint") params.addMinutesToTimestamp = 24*60; //astro timepoints will be recalculated dynamically: params.timePointName = time_points[t].name; // if astro timepoint, we save time window: - if (['luxOn', 'luxOff', 'dusk', 'dawn'].includes(params.timePointName)) { + if(['luxOn', 'luxOff', 'dusk','dawn'].includes(params.timePointName)) + { params.dawn_lux_sensor_time_window = profile.dawn_lux_sensor_time_window; params.dusk_lux_sensor_time_window = profile.dusk_lux_sensor_time_window; } - if (params.value == 0) params.info = `${params.timePointName}: turn off line: ` + line; - else if (params.value == 1) params.info = `${params.timePointName}: turn on line: ` + line; + if(params.value == 0) params.info = `${params.timePointName}: turn off line: ` + line; + else if(params.value == 1) params.info = `${params.timePointName}: turn on line: ` + line; params.debug = true; //turn on/off line tasks.push(params); - monitor.info("TimePoint params: ", params.info, start_time); + monitor.info(params.info, start_time); + } monitor.info("-->time_points final", line, time_points); - //ensure to turn on/off according to calculated currentValue + //ensure to turn on/off according to calculated value let params = getParams(PRIORITY_TYPES.terminal); params.type = "relay"; params.line = parseInt(line); @@ -1062,13 +1212,14 @@ exports.install = function(instance) { monitor.info("-->currentValue for relay", line, currentValue); //turn on/off line - if (params.value == 0) params.info = "turn off line on startup: " + line; - else if (params.value == 1) params.info = "turn on line on startup: " + line; + if(params.value == 0) params.info = "turn off line on startup: " + line; + else if(params.value == 1) params.info = "turn on line on startup: " + line; tasks.push(params); } catch (error) { - if (profilestr !== "") { + if(profilestr !=="" ) + { //errLogger.error(profilestr, error); errorHandler.sendMessageToService(profilestr + "-" + error, 0, "js_error"); } @@ -1082,50 +1233,59 @@ exports.install = function(instance) { //PROCESS DEFAULT BROADCASTS - //Time of dusk, Time of dawn, Actual Time - if (processBroadcast) { + //RPC pre nody / broadcast + //Time of dusk, Time of dawn + //Actual Time + + if(processBroadcast) + { let addMinutesToTimestamp = 5; { //run broadcast Time of dusk addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dusk - + let params = getParams(PRIORITY_TYPES.node_broadcast); - + let sunCalcResult = calculateDuskDawn(); let dusk_hours = sunCalcResult["dusk_hours"]; let dusk_minutes = sunCalcResult["dusk_minutes"]; - + params.address = 0xffffffff;//broadcast params.byte1 = dusk_hours;//h params.byte2 = dusk_minutes;//m params.byte3 = 0;//s params.byte4 = 0; - params.recipient = 2;//2 broadcast, + params.recipient = 2;//2 broadcast, params.register = 6;//Time of dusk - Reg 6 params.rw = 1;//write - + + let timestampStart = PRIORITY_TYPES.node_broadcast; + //other values params.type = "cmd"; - params.timestamp = Date.now() + 60000; + //params.tbname = tbname; + params.timestamp = timestampStart; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "Broadcast-duskTime"; tasks.push(params); + } - + { - + //run broadcast Time of dawn + // addMinutesToTimestamp = 60*5; addMinutesToTimestamp = 60 * 3; //kazde 3 hodiny zisti novy dawn - + let params = getParams(PRIORITY_TYPES.node_broadcast); - + let sunCalcResult = calculateDuskDawn(); let dawn_hours = sunCalcResult["dawn_hours"]; let dawn_minutes = sunCalcResult["dawn_minutes"]; - + params.address = 0xffffffff;//broadcast params.byte1 = dawn_hours;//h params.byte2 = dawn_minutes;//m @@ -1134,27 +1294,30 @@ exports.install = function(instance) { params.recipient = 2; //2 broadcast params.register = 7;//Time of dawn - Reg 6 params.rw = 1;//write - + + let timestampStart = PRIORITY_TYPES.node_broadcast; + //other values params.type = "cmd"; - params.timestamp = Date.now() + 60000; + //params.tbname = tbname; + params.timestamp = timestampStart; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "Broadcast-dawnTime"; - + tasks.push(params); } - + { - //run broadcast Actual time + //run broadcast //Actual time addMinutesToTimestamp = 5; - + let params = getParams(PRIORITY_TYPES.node_broadcast); - + var d = new Date(); let hours = d.getHours(); let minutes = d.getMinutes(); let seconds = d.getSeconds(); - + params.address = 0xffffffff;//broadcast params.byte1 = hours;//h params.byte2 = minutes;//m @@ -1163,13 +1326,16 @@ exports.install = function(instance) { params.recipient = 2; //2 broadcast params.register = 87;//Actual time params.rw = 1;//write - + + let timestampStart = PRIORITY_TYPES.node_broadcast; + //other values params.type = "cmd"; - params.timestamp = Date.now() + 60000; + //params.tbname = tbname; + params.timestamp = timestampStart; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "run broadcast: Actual time"; - + tasks.push(params); } @@ -1177,20 +1343,22 @@ exports.install = function(instance) { //process nodes & tasks //reportovanie pre platformu - if (processNodes) { + if(processNodes) + { for (let k in nodesData) { let address = parseInt(k); let tbname = nodesData[k].tbname; let register = 0; - + //logger.debug("generated cmd - buildTasks for node:", address); - + //listOfCommands - READ - for (let i = 0; i < listOfCommands.length; i++) { + for(let i = 0; i < listOfCommands.length; i++) + { register = listOfCommands[i]; - + let params = getParams(PRIORITY_TYPES.node_cmd); - + //core rpc values params.address = address; params.byte1 = 0; @@ -1200,30 +1368,41 @@ exports.install = function(instance) { params.recipient = 1; params.register = register; params.rw = 0; - + let addMinutesToTimestamp = priorities[register]; - + let timestampStart = PRIORITY_TYPES.node_cmd; //run imediatelly in function runTasks - if (addMinutesToTimestamp > 1) { + if(addMinutesToTimestamp > 1) + { timestampStart = timestampStart + addMinutesToTimestamp * 60000; } - + //other values params.type = "cmd"; params.tbname = tbname; params.timestamp = timestampStart; params.addMinutesToTimestamp = addMinutesToTimestamp; params.info = "generated cmd - buildTasks (node)"; - + + //monitor last node && last command + /* + if(register == listOfCommands[ listOfCommands.length - 1 ]) + { + //if(k == 632) params.debug = true; + if(k == 698) params.debug = true; + } + */ + tasks.push(params); - + } } } + //niektore ulohy sa vygeneruju iba 1x pri starte!!! - if (!init) return; + if(!init) return; //Priebežne (raz za cca 5 minút) je potrebné vyčítať z Master nodu verziu jeho FW. @@ -1232,17 +1411,19 @@ exports.install = function(instance) { //tak treba vyreportovať string "NOK". { let params = getParams(PRIORITY_TYPES.fw_detection); - params.type = "cmd-master"; + params.type = "cmd"; params.register = 4; params.address = 0; - params.timestamp = Date.now() + 60000; + + let timestampStart = PRIORITY_TYPES.fw_detection; + params.timestamp = timestampStart; params.addMinutesToTimestamp = 5; - params.tbname = rvoTbName; + params.tbname = FLOW.OMS_edgeName; params.info = "Master node FW verzia"; //params.debug = true; - //this will set SETTINGS.masterNodeIsResponding - + //this will set FLOW.OMS_masterNodeIsResponding + tasks.push(params); } @@ -1250,10 +1431,42 @@ exports.install = function(instance) { { let params = getParams(PRIORITY_TYPES.fw_detection); params.type = "process_profiles"; - params.timestamp = Date.now() + 60000; + + let timestampStart = PRIORITY_TYPES.relay_profile; + params.timestamp = timestampStart; params.addMinutesToTimestamp = 60;//60 = every hour params.info = "detekcia nespracovaných profilov linie a nodov"; //params.debug = true; + + tasks.push(params); + } + + { + //edge_date_time + + let params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "edge_date_time"; + + let timestampStart = PRIORITY_TYPES.node_cmd; + params.timestamp = timestampStart; + params.addMinutesToTimestamp = 1; + params.tbname = FLOW.OMS_edgeName; + params.info = "reportovanie aktuálneho času na LM - EDGE-Date Time"; + //logger.debug("BUILD Master node FW verzia"); + tasks.push(params); + } + + { + //edge_date_time + + let params = getParams(PRIORITY_TYPES.node_cmd); + params.type = "number_of_luminaires"; + + let timestampStart = PRIORITY_TYPES.node_cmd + 1; + params.timestamp = timestampStart; + params.addMinutesToTimestamp = 1; + params.tbname = FLOW.OMS_edgeName; + params.info = "reportovanie number_of_luminaires"; tasks.push(params); } @@ -1283,13 +1496,15 @@ exports.install = function(instance) { * dawn: usvit - lux je nad hranicou - vypnem * dusk: sumrak - lux je pod hranicou - zapnem */ - function turnOnOffLinesAccordingToLuxSensor(lux_sensor_value) { + function turnOnOffLinesAccordingToLuxSensor(lux_sensor_value) + { let now = new Date(); let currentTimestamp = now.getTime(); let keys = Object.keys(relaysData); - for (let i = 0; i < keys.length; i++) { + for(let i = 0; i < keys.length; i++) + { let line = keys[i]; //line is turned off by default let profilestr = relaysData[line].profile; @@ -1298,31 +1513,38 @@ exports.install = function(instance) { try { let profile = JSON.parse(profilestr); - if (Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); + if(Object.keys(profile).length === 0) throw ("turnOnOffLinesAccordingToLuxSensor - profile is not defined"); - if (profile.astro_clock == true) { + if(profile.astro_clock == true) + { let sunCalcResult = calculateDuskDawn(now, line); //usvit - if (profile.dawn_lux_sensor == true) { - let lux_sensor_time_window1 = sunCalcResult.dawn_time - (parseInt(profile.dawn_lux_sensor_time_window) * 1000 * 60); // LUX_SENSOR_TIME_WINDOW x 1000 x 60 --> dostaneme odpocet/pripocitanie minut - let lux_sensor_time_window2 = sunCalcResult.dawn_time + (parseInt(profile.dawn_lux_sensor_time_window) * 1000 * 60); + if(profile.dawn_lux_sensor == true) + { + let lux_sensor_time_window1 = sunCalcResult.dawn_time - (parseInt( profile.dawn_lux_sensor_time_window ) * 1000 * 60); // LUX_SENSOR_TIME_WINDOW x 1000 x 60 --> dostaneme odpocet/pripocitanie minut + let lux_sensor_time_window2 = sunCalcResult.dawn_time + (parseInt( profile.dawn_lux_sensor_time_window ) * 1000 * 60); - if (currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2) { - if (lux_sensor_value > profile.dawn_lux_sensor_value) { - if (contactor) turnLine("off", line, "Profile: dawn - turnOff line according to lux sensor"); + if(currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2) + { + if(lux_sensor_value > profile.dawn_lux_sensor_value) + { + if(contactor) turnOffLine(line, "Profile: dawn - turnOff line according to lux sensor"); } } } //sumrak - if (profile.dusk_lux_sensor == true) { - let lux_sensor_time_window1 = sunCalcResult.dusk_time - (parseInt(profile.dusk_lux_sensor_time_window) * 1000 * 60); - let lux_sensor_time_window2 = sunCalcResult.dusk_time + (parseInt(profile.dusk_lux_sensor_time_window) * 1000 * 60); + if(profile.dusk_lux_sensor == true) + { + let lux_sensor_time_window1 = sunCalcResult.dusk_time - (parseInt( profile.dusk_lux_sensor_time_window ) * 1000 * 60); + let lux_sensor_time_window2 = sunCalcResult.dusk_time + (parseInt( profile.dusk_lux_sensor_time_window ) * 1000 * 60); - if (currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2) { - if (lux_sensor_value < profile.dusk_lux_sensor_value) { - if (!contactor) turnLine("on", line, "Profile: dusk - turnOn line according to lux sensor"); + if(currentTimestamp >= lux_sensor_time_window1 && currentTimestamp <= lux_sensor_time_window2) + { + if(lux_sensor_value < profile.dusk_lux_sensor_value) + { + if(!contactor) turnOnLine(line, "Profile: dusk - turnOn line according to lux sensor"); } } } @@ -1330,64 +1552,36 @@ exports.install = function(instance) { } } catch (error) { - if (profilestr !== "") monitor.info('Error parsing profile in turnOnOffLinesAccordingToLuxSensor', error); + if(profilestr !== "" ) monitor.info('Error parsing profile in turnOnOffLinesAccordingToLuxSensor', error); } } } - /** - * function updates status and time_of_last_communication of node in the dbNodes - * it only updates if conditions are met - * it only updates time_of_last_communication of node, if the last written time was more than 10 minutes ago (600000 miliseconds) - * if newStatus of node is always receiving false, and it is already for more than SETTINGS.node_status_nok_time value, we update status to "NOK" in tb - * function returns true, if status of node needs to be updated in TB (newStatus attribute is false in this case). - */ - function updateNodeStatus(node, newStatus) { + + async function upateNodeStatus(node, status) + { //MASTER - if (node == 0) return; + if(node == 0) return; let nodeObj = nodesData[node]; - if (nodeObj == undefined) return; + if(nodeObj == undefined) return; - let nodeCurrentStatus = nodeObj.status; - const now = Date.now(); - - let data = null; - - if (newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication > now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION) return; - else if (newStatus == true && nodeCurrentStatus == true && nodeObj.time_of_last_communication < now - TIME_AFTER_WE_UPDATE_LAST_NODE_COMMUNICATION) { - data = { time_of_last_communication: now }; - nodeDbStatusModify(node, data); - return; - } - else if (newStatus == false && nodeCurrentStatus == false) return true; - else if (newStatus == false && nodeCurrentStatus == true) { - if (nodeObj.time_of_last_communication + SETTINGS.node_status_nok_time > now) return; - else { - data = { status: newStatus }; - nodeDbStatusModify(node, data); - return true; - } - } - else if (newStatus == true && nodeCurrentStatus == false) { - data = { status: newStatus, time_of_last_communication: now }; - nodeDbStatusModify(node, data); - return; + if(status) + { + cmdNOKNodeCounter[node] = 0; } + else cmdNOKNodeCounter[node]++; - } - - - function nodeDbStatusModify(node, data) { - dbNodes.modify(data).where("node", node).make(function(builder) { - builder.callback(function(err, response) { - if (!err) { - nodesData[node] = { ...nodesData[node], ...data }; - } + if(nodeObj.status !== status) + { + await dbNodes.modify({ status: status }).where("node", node).make(function(builder) { + builder.callback(function(err, response) { + if(err == null) nodesData[node].status = status; + }); }); - }); + } } @@ -1398,12 +1592,15 @@ exports.install = function(instance) { let currentTimestamp = Date.now(); //report dusk, dawn--------------------------------- - if (reportDuskDawn.dusk_time < currentTimestamp) { + if(reportDuskDawn.dusk_time < currentTimestamp) + { //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund - if ((currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) { + if( (currentTimestamp - reportDuskDawn.dusk_time) < 60 * 1000) + { //reportovali sme? - if (reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) { - sendNotification("CMD Manager: calculated Time of dusk", SETTINGS.rvoTbName, "dusk_has_occured", { value: sunCalcResult["dusk"] }, "", SEND_TO.tb, instance); + if(reportDuskDawn.dusk_time_reported != sunCalcResult.dusk_time) + { + sendNotification("CMD Manager: calculated Time of dusk", FLOW.OMS_edgeName, "dusk_has_occured", {value: sunCalcResult["dusk"]}, "", SEND_TO.tb, instance); reportDuskDawn.dusk_time_reported = sunCalcResult.dusk_time; } } @@ -1415,12 +1612,15 @@ exports.install = function(instance) { reportDuskDawn.dusk_time = sunCalcResult.dusk_time; } - if (reportDuskDawn.dawn_time < currentTimestamp) { + if(reportDuskDawn.dawn_time < currentTimestamp) + { //vyreportuj iba ak nie je velky rozdiel napr. 60 sekund - if ((currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) { + if( (currentTimestamp - reportDuskDawn.dawn_time) < 60 * 1000) + { //reportovali sme? - if (reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) { - sendNotification("CMD Manager: calculated Time of dawn", SETTINGS.rvoTbName, "dawn_has_occured", { value: sunCalcResult["dawn"] }, "", SEND_TO.tb, instance); + if(reportDuskDawn.dawn_time_reported != sunCalcResult.dawn_time) + { + sendNotification("CMD Manager: calculated Time of dawn", FLOW.OMS_edgeName, "dawn_has_occured", {value: sunCalcResult["dawn"]}, "", SEND_TO.tb, instance); reportDuskDawn.dawn_time_reported = sunCalcResult.dawn_time; } } @@ -1435,67 +1635,155 @@ exports.install = function(instance) { //-------------------------------------------------------- //sort tasks based on timestamp - tasks.sort(function(a, b) { - if (a.timestamp <= currentTimestamp && b.timestamp <= currentTimestamp) { + tasks.sort(function (a, b) { + if(a.timestamp <= currentTimestamp && b.timestamp <= currentTimestamp) + { return a.priority - b.priority; } return a.timestamp - b.timestamp; }); - if (tasks.length == 0) { + if(tasks.length == 0 ) + { instance.send(SEND_TO.debug, "no tasks created"); interval = setInterval(runTasks, LONG_INTERVAL); return; } - if (!rsPort.isOpen) { + if(!rsPort.isOpen) + { instance.send(SEND_TO.debug, "!rsPort.isOpen"); //await rsPort.open(); - console.log("Cmd_manager - !rsPort.isOpen"); } let currentTask = tasks[0]; - if (currentTask.debug) { + if(currentTask.debug) + { //logger.debug("--->task to process", currentTask); } - if (currentTask.timestamp <= currentTimestamp) { - let params = { ...tasks[0] }; + if(currentTask.timestamp <= currentTimestamp) + { + let params = {...tasks[0]}; //allow terminal commands - if (SETTINGS.maintenance_mode && params.type !== "cmd-terminal") { + if(FLOW.OMS_maintenance_mode && params.type !== "cmd-terminal") + { interval = setInterval(runTasks, LONG_INTERVAL); return; } let type = params.type; let tbname = params.tbname; - let nodeAddress = params.address; + let nodeKey = params.address; let line = null; //rpc related - if (nodesData[nodeAddress] !== undefined) line = nodesData[nodeAddress].line; - if (params.line !== undefined) line = params.line; + if(nodesData[nodeKey] !== undefined) line = nodesData[nodeKey].line; + if(params.line !== undefined) line = params.line; let repeatTask = false; - if (params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; + if(params.addMinutesToTimestamp > 0 || params.timePointName) repeatTask = true; - if (repeatTask) { - if (type === "cmd" || type === "cmd-master") { + if(repeatTask) + { + if(type === "cmd") + { //set next start time automatically tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; } } - else { + else + { tasks.shift(); } - //kontrola nespracovanych profilov nodov - if (type == "process_profiles") { + //custom tasks + if(type == "number_of_luminaires") + { tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + //treba reportovat node status + { + //number_of_luminaires + //number_of_ok_luminaires + //number_of_nok_luminaires + + let keys = Object.keys(nodesData); + + let number_of_luminaires = keys.length; + let number_of_ok_luminaires = 0; + let number_of_nok_luminaires = 0; + + for(let i = 0; i < keys.length; i++) + { + let key = keys[i]; + let nodeObj = nodesData[key]; + if(nodeObj.tbname == undefined) continue; + + if(nodeObj.status) number_of_ok_luminaires++; + else number_of_nok_luminaires++; + } + + let values = { + number_of_luminaires: number_of_luminaires, + number_of_ok_luminaires: number_of_ok_luminaires, + number_of_nok_luminaires: number_of_nok_luminaires + }; + + let dataToTb = { + [FLOW.OMS_edgeName]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); + + interval = setInterval(runTasks, SHORT_INTERVAL); + + return; + } + } + + + //kontrola nespracovanych profilov nodov + if(type == "process_profiles") + { + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + + //select nespracovane nody + //node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean + + //buildTasks({processLineProfiles: true, line: line}); + + /* + let keys = Object.keys(nodesData); + for(let i = 0; i < keys.length; i++) + { + let node = keys[i]; + let line = node.line; + + if(node.processed) continue; + + if(relaysData[line] != undefined) + { + let relayStatus = relaysData[line].contactor; + if(relayStatus == 1) + { + //linia je zapnuta + //await loadRelaysData(flowdata.data.line); + } + } + + } + */ + //vsetky linie kt. su zapnute, a spracuju sa nespracovane profily nodov loadRelaysData(); @@ -1503,8 +1791,31 @@ exports.install = function(instance) { return; } + if(type == "edge_date_time") + { + const ts = Date.now(); + + let values = {"edge_date_time": ts}; + + let dataToTb = { + [tbname]: [ + { + "ts": ts, + "values": values + } + ] + } + + tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; + + instance.send(SEND_TO.tb, dataToTb); + interval = setInterval(runTasks, SHORT_INTERVAL); + return; + } + //relay - if (type == "relay") { + if(type == "relay") + { const timePointName = params.timePointName; const value = params.value; @@ -1513,31 +1824,45 @@ exports.install = function(instance) { date.setDate(date.getDate() + 1);//next day let sunCalcResult; - if (timePointName) sunCalcResult = calculateDuskDawn(date, params.line); + sunCalcResult = calculateDuskDawn(date, params.line); - if (timePointName == "dawn") { + if(timePointName == "dawn") + { tasks[0].timestamp = sunCalcResult.dawn_time; } - else if (timePointName == "dusk") { + else if(timePointName == "dusk") + { tasks[0].timestamp = sunCalcResult.dusk_time; } - else if (timePointName == "luxOn") { + else if(timePointName == "luxOn") + { tasks[0].timestamp = sunCalcResult.dusk_time + params.dusk_lux_sensor_time_window * 60000; } - else if (timePointName == "luxOff") { + else if(timePointName == "luxOff") + { tasks[0].timestamp = sunCalcResult.dawn_time + params.dawn_lux_sensor_time_window * 60000; } - else if (timePointName == "profileTimepoint") { + else if(timePointName == "profileTimepoint") + { tasks[0].timestamp = currentTimestamp + tasks[0].addMinutesToTimestamp * 60000; } let info = "aplikovany bod profilu"; let message = ""; - value == 1 ? message = "on" : message = "off"; + if(value == 1) + { + turnOnLine(params.line, info); + message = "on"; + } + else if(value == 0) + { + turnOffLine(params.line, info); + message = "off"; + } - turnLine(message, params.line, info); + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.INFO, "aplikovaný bod profilu línie " + params.line + " - stav: " + message, "", SEND_TO.tb, instance, null ); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "switching_profile_point_applied_to_line", {line: params.line, value: message}, "", SEND_TO.tb, instance ); - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "switching_profile_point_applied_to_line", { line: params.line, value: message }, "", SEND_TO.tb, instance); interval = setInterval(runTasks, SHORT_INTERVAL); return; } @@ -1547,23 +1872,37 @@ exports.install = function(instance) { //if(rotary_switch_state == "Off") disconnected = true; //state_of_breaker[line] - alebo istic linie - if (state_of_breaker.hasOwnProperty(line)) { + if(state_of_breaker.hasOwnProperty(line)) + { //if(state_of_breaker[line] == "Off") disconnected = true; } //toto sa reportuje po prijati dat z dido_controlera - if (disconnected) { - let values = { "status": "OFFLINE" }; + if(disconnected) + { + + let values = {"status": "OFFLINE"}; logger.debug("disconnected", values); logger.debug("rotary_switch_state", rotary_switch_state); logger.debug("state_of_breaker", state_of_breaker[line]); - //report only once! - if (!disconnectedReport.hasOwnProperty(tbname)) disconnectedReport[tbname] = false; + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } - if (!disconnectedReport[tbname]) { - sendTelemetry(values, tbname) + //report only once! + if(!disconnectedReport.hasOwnProperty(tbname)) disconnectedReport[tbname] = false; + + if(!disconnectedReport[tbname]) + { + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); } interval = setInterval(runTasks, SHORT_INTERVAL); @@ -1573,51 +1912,67 @@ exports.install = function(instance) { disconnectedReport[tbname] = false; - const register = params.register; - //high_priority - if (!SETTINGS.masterNodeIsResponding) { + if(!FLOW.OMS_masterNodeIsResponding) + { //ak neodpoveda, nebudeme vykonavat ziadne commands, okrem cmd-terminal, a fw version errorHandler.sendMessageToService("Master node is not responding"); let stop = true; + if(params.type == "cmd-terminal") stop = false; //fw version - register == 4 - if (type == "cmd-terminal" || register == 4) stop = false; - if (stop) { + if(params.type == "cmd" && params.register == 4 && params.address == 0) stop = false; + + if(stop) + { interval = setInterval(runTasks, LONG_INTERVAL); return; } } let relayStatus = 1; - if (relaysData[line] != undefined) { + if(relaysData[line] != undefined) + { relayStatus = relaysData[line].contactor; } - - if (line == 0) relayStatus = 0; - if (type == "cmd-terminal") relayStatus = 1; + if(line == 0) relayStatus = 0; + if(params.type == "cmd-terminal") relayStatus = 1; //check if rotary_switch_state == "Off" - if (relayStatus == 0) { + + if(relayStatus == 0) + { //console.log("------------------------------------relayStatus", relayStatus, line); - let values = { "status": "OFFLINE" }; - - sendTelemetry(values, tbname) + let values = {"status": "OFFLINE"}; + + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); + interval = setInterval(runTasks, SHORT_INTERVAL); return; } - if (!rsPort.isOpen) { + if(!rsPort.isOpen) + { interval = setInterval(runTasks, LONG_INTERVAL); return; } - + //RE-CALCULATE VALUES //set actual time for broadcast - if (register == 87 && params.recipient === 2) { + if(params.register == 87 && params.recipient === 2) + { var d = new Date(); let hours = d.getHours(); let minutes = d.getMinutes(); @@ -1631,13 +1986,15 @@ exports.install = function(instance) { //SET DUSK/DAWN FOR BROADCAST //Time of dusk - if (register == 6 && params.recipient === 2) { + if(params.register == 6 && params.recipient === 2) + { - if (type != "cmd-terminal") { + if(params.type != "cmd-terminal") + { let sunCalcResult = calculateDuskDawn(); let dusk_hours = sunCalcResult["dusk_hours"]; let dusk_minutes = sunCalcResult["dusk_minutes"]; - + params.byte1 = dusk_hours;//h params.byte2 = dusk_minutes;//m params.byte3 = 0;//s @@ -1645,16 +2002,19 @@ exports.install = function(instance) { //TODO astrohodiny let dusk = "Time of dusk: " + sunCalcResult["dusk"]; + //sendNotification("CMD Manager: calculated Time of dusk", relaysData[0].tbname, ERRWEIGHT.INFO, dusk, "", SEND_TO.tb, instance, null ); } } //Time of dawn - if (register == 7 && params.recipient === 2) { - if (type != "cmd-terminal") { + if(params.register == 7 && params.recipient === 2) + { + if(params.type != "cmd-terminal") + { let sunCalcResult = calculateDuskDawn(); let dawn_hours = sunCalcResult["dawn_hours"]; let dawn_minutes = sunCalcResult["dawn_minutes"]; - + params.byte1 = dawn_hours;//h params.byte2 = dawn_minutes;//m params.byte3 = 0;//s @@ -1662,414 +2022,565 @@ exports.install = function(instance) { //TODO astrohodiny let dawn = "Time of dawn: " + sunCalcResult["dawn"]; + //sendNotification("CMD Manager: calculated Time of dusk", relaysData[0].tbname, ERRWEIGHT.INFO, dawn, "", SEND_TO.tb, instance, null ); } - + } //----------------------- - instance.send(SEND_TO.debug, "address: " + nodeAddress + " register:" + register + "type: " + type); + + let register = params.register; + instance.send(SEND_TO.debug, "address: " + params.address + " register:" + params.register + "type: " + params.type); var startTime, endTime; startTime = new Date(); - let saveToTb = true; - if (!tbname) saveToTb = false; - let itIsNodeCommand = listOfCommands.includes(register); //reading data from node (voltage, current, dimming, status) - - let resp = com_generic(nodeAddress, params.recipient, params.rw, register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); + let resp = com_generic(params.address, params.recipient, params.rw, params.register, params.name, params.byte1, params.byte2, params.byte3, params.byte4); let readBytes = 11; - let timeout = 4000; + let timeout = 5000; - // await keyword is important, otherwise incorrect data is returned! - await writeData(rsPort, resp, readBytes, timeout).then(function(data) { + await writeData(rsPort, resp, readBytes, timeout).then(function (data) { endTime = new Date(); var timeDiff = endTime - startTime; - //data je array z 11 bytov: 1-4 adresa, 5 status ak je status 0 - ok, nasleduju 4 byty data a 2 byty CRC - let dataBytes = data.slice(5, 9); - let result = detectIfResponseIsValid(data); + //--1-4 adresa, 5 status ak je status 0 - ok, nasleduju 4 byty data + //let bytes = data.slice(0); + let bytes = data; + let dataBytes = data.slice(5,9); - //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK - let message = result.message; // OK, NOK - let message_type = result.type; + let result = detectIfResponseIsValid(bytes); + + let message = result.message; + let type = result.type; let error = result.error; - if (params.debug != "generated cmd") { - //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug, params); + //ak sa odpoved zacina 0 - je to v poriadku, inak je NOK + + if(params.debug != "generated cmd") + { + //debug("writeData: done " + type + " duration: " + timeDiff + " type: " + params.debug, params); } - // if(params.hasOwnProperty("debug")) - // { - // if(params.debug) - // { - // console.log("detected response:", result); + if(params.hasOwnProperty("debug")) + { + if(params.debug) + { + console.log("detected response:", result); - // logger.debug("writeData: done " + message_typetype + " duration: " + timeDiff + " type: " + params.debug, params, result); - // } - // } + logger.debug("writeData: done " + type + " duration: " + timeDiff + " type: " + params.debug, params, result); + } + } - //debug("writeData: done " + message_type + " duration: " + timeDiff + " message_type: " + params.debug); - //debug("writeData done", message_type, "duration", timeDiff, "message_type", params.debug, result); + //debug("writeData: done " + type + " duration: " + timeDiff + " type: " + params.debug); + //debug("writeData done", type, "duration", timeDiff, "type", params.debug, result); - let values = {}; + let tbname = params.tbname; + + let saveToTb = true; + if(tbname == null || tbname == undefined || tbname == "") saveToTb = false; + //-- //CMD FINISHED - if (message == "OK") { + if(message == "OK") + { - updateNodeStatus(nodeAddress, true); + upateNodeStatus(params.address, true); //write - if (type == "set_node_profile") { - let result = cmdCounterResolve(nodeAddress); - if (result == 0) { - dbNodes.modify({ processed: true }).where("node", nodeAddress).make(function(builder) { + if(params.type == "set_node_profile") + { + let result = cmdCounterResolve(params.address); + if(result == 0) + { + + dbNodes.modify({ processed: true }).where("node", params.address).make(function(builder) { + builder.callback(function(err, response) { - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "dimming_profile_was_successfully_received_by_node", { node: nodeAddress }, "", SEND_TO.tb, instance); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "dimming_profile_was_successfully_received_by_node", {node: params.address}, "", SEND_TO.tb, instance ); + + logger.debug( "--> profil úspešne odoslaný na node č. " + params.address); + nodesData[params.address].processed = true; - logger.debug("--> profil úspešne odoslaný na node č. " + nodeAddress); - nodesData[nodeAddress].processed = true; + }); }); - }); } } //parse read response - if (params.rw == 0) { - values = processResponse(register, dataBytes); //read + let values = {}; + if(params.rw == 0) { + values = processResponse(register, dataBytes);//read + } + if(params.rw == 1) + { //write command + //set command dimming + if(params.register == 1) values = {"comm_status": message}; } - if (itIsNodeCommand) { - values.comm_status = "OK"; - values.status = "OK"; - } + if(params.register == 0) values["status"] = message; - //master node - if (nodeAddress == 0) { - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status"); - SETTINGS.masterNodeIsResponding = true; - if (register == 4) values["edge_fw_version"] = SETTINGS.edge_fw_version; + //fw version - register == 4 + if(params.register == 4) values["edge_fw_version"] = FLOW.OMS_edge_fw_version; + + if(params.address == 0) + { + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.NOTICE, "Master node is working again", "", SEND_TO.tb, instance, "rvo_status" ); + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status" ); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_responding_again", {}, "", SEND_TO.tb, instance, "rvo_status" ); + FLOW.OMS_masterNodeIsResponding = true; } //odoslanie príkazu z terminálu - dáta - if (type == "cmd-terminal") { - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "command_was_sent_from_terminal_interface", {}, params, SEND_TO.tb, instance); + if(params.type == "cmd-terminal") + { + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.DEBUG, "odoslanie príkazu z terminálu", params, SEND_TO.tb, instance, null ); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "command_was_sent_from_terminal_interface", {}, params, SEND_TO.tb, instance ); } - if (params.debug) { - //logger.debug("saveToTb", saveToTb, tbname, values); + if(params.debug) + { + logger.debug("saveToTb", saveToTb, tbname, values); } - if (saveToTb) { - sendTelemetry(values, tbname) + if(saveToTb) + { + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); + } - else { - if (type == "cmd-terminal") { - terminalCommandResponse(params, "SUCCESS", data); + else + { + + if(params.type == "cmd-terminal") + { + if(params.refFlowdataKey != undefined) + { + + logger.debug("cmd-terminal SUCCESS"); + logger.debug(currentTask); + + //make http response + let responseObj = {}; + responseObj["type"] = "SUCESS"; + responseObj["bytes"] = data; + + //params.refFlowdata.data = responseObj; + //instance.send(SEND_TO.http_response, params.refFlowdata); + + let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; + refFlowdata.data = responseObj; + instance.send(SEND_TO.http_response, refFlowdata); + + } + else + { + console.log("params.refFlowdataKey is undefined", params); + } } + } } - else { + else + { - terminalCommandResponse(params, "ERROR", data) - handleNokResponseOnRsPort("handleNOK else block", params, itIsNodeCommand, saveToTb); + upateNodeStatus(params.address, false); - if (params.hasOwnProperty("debug")) { - if (params.debug) { - //logger.debug("writeData err: ", error, result, params); - logger.debug("writeData err: ", tbname, nodeAddress, register, values); + if(params.refFlowdataKey != undefined) + { + + logger.debug("cmd-terminal FAILED"); + logger.debug(currentTask); + + //make http response + let responseObj = {}; + responseObj["type"] = "ERROR"; + responseObj["bytes"] = data; + + //params.refFlowdata.data = responseObj; + //instance.send(SEND_TO.http_response, params.refFlowdata); + + let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; + if(refFlowdata !== undefined) + { + refFlowdata.data = responseObj; + instance.send(SEND_TO.http_response, refFlowdata); + } + + + } + + /* + if(params.type == "cmd-terminal") + { + if(params.refFlowdata != undefined) + { + + logger.debug("cmd-terminal FAILED"); + logger.debug(currentTask); + + //make http response + let responseObj = {}; + responseObj["type"] = "ERROR"; + responseObj["bytes"] = data; + + params.refFlowdata.data = responseObj; + instance.send(SEND_TO.http_response, params.refFlowdata); + + } + } + */ + + if(params.address == 0) + { + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.ALERT, "Master node not responding", "", SEND_TO.tb, instance, "rvo_status"); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); + logger.debug("master_node_is_not_responding", params); + FLOW.OMS_masterNodeIsResponding = false; + } + + if(params.type == "set_node_profile") + { + delete cmdCounter[params.address]; + let tbname = nodesData[ params.address ].tbname; + + logger.debug( "profil nebol úspešne odoslaný na node č. ", params, result, resp); + + //sendNotification("CMD Manager: process cmd", tbname, ERRWEIGHT.ALERT, "profil nebol úspešne odoslaný na node č. " + params.address, "", SEND_TO.tb, instance, null ); + sendNotification("CMD Manager: process cmd", tbname, "configuration_of_dimming_profile_to_node_failed", {node: params.address}, "", SEND_TO.tb, instance ); + } + + //is it node? + if(nodesData.hasOwnProperty(params.address)) + { + if(cmdNOKNodeCounter[params.address] < 5) saveToTb = false; + } + + //Master node version + //if(params.register == 4 && saveToTb) + if(saveToTb) + { + let values = { + "status": "NOK" + }; + + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); + } + + //instance.send(SEND_TO.debug, result); + + if(params.hasOwnProperty("debug")) + { + if(params.debug) + { + logger.debug("writeData err: ", error, result, params); } } //logger.debug(error, result, params); } - }).catch(function(reason) { + + }).catch(function (reason) { console.log("writeData catch exception", reason); - instance.send(SEND_TO.debug, reason); + logger.debug(currentTask); - terminalCommandResponse(params, "FAILURE", null, reason); - handleNokResponseOnRsPort("handleNOK catch block", params, itIsNodeCommand, saveToTb); + if(params.refFlowdataKey != undefined) + { - if (params.hasOwnProperty("debug")) { - if (params.debug) { + logger.debug("catch: cmd-terminal FAILED"); + logger.debug(currentTask); + + //make http response + let responseObj = {}; + responseObj["type"] = "ERROR";// + responseObj["message"] = "ERROR WRITE FAILED: " + reason;// + + //params.refFlowdata.data = responseObj; + //instance.send(SEND_TO.http_response, params.refFlowdata); + + let refFlowdata = refFlowdataObj[ params.refFlowdataKey ]; + if(refFlowdata !== undefined) + { + refFlowdata.data = responseObj; + instance.send(SEND_TO.http_response, refFlowdata); + } + + + } + /* + if(params.type == "cmd-terminal") + { + if(params.refFlowdata != undefined) + { + + logger.debug("cmd-terminal FAILED"); + logger.debug(currentTask); + + //make http response + let responseObj = {}; + responseObj["type"] = "ERROR WRITE FAILED: " + reason; + //responseObj["bytes"] = data; + + params.refFlowdata.data = responseObj; + instance.send(SEND_TO.http_response, params.refFlowdata); + + //refFlowdata = undefined; + } + } + */ + + if(params.hasOwnProperty("debug")) + { + if(params.debug) + { logger.debug("-->WRITE FAILED: " + reason, params.debug, params); } } - }); + upateNodeStatus(params.address, false); + let tbname = params.tbname; + + let saveToTb = true; + if(tbname == null || tbname == undefined || tbname == "") saveToTb = false; + + if(params.address == 0) + { + //sendNotification("CMD Manager: process cmd", relaysData[0].tbname, ERRWEIGHT.ALERT, "Master node not responding", "", SEND_TO.tb, instance, "rvo_status"); + sendNotification("CMD Manager: process cmd", FLOW.OMS_edgeName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); + logger.debug("master_node_is_not_responding", params); + + FLOW.OMS_masterNodeIsResponding = false; + } + + if(params.type == "set_node_profile") + { + delete cmdCounter[params.address]; + let tbname = nodesData[ params.address ].tbname; + + logger.debug( "profil nebol úspešne odoslaný na node č. ", params, resp); + + //sendNotification("CMD Manager: process cmd", tbname, ERRWEIGHT.ALERT, "odosielanie profilu na node č. " + params.address + " zlyhalo", "", SEND_TO.tb, instance, null ); + sendNotification("CMD Manager: process cmd", tbname, "configuration_of_dimming_profile_to_node_failed", {node: params.address}, "", SEND_TO.tb, instance ); + } + + //is it node? + if(nodesData.hasOwnProperty(params.address)) + { + if(cmdNOKNodeCounter[params.address] < 5) saveToTb = false; + } + + //Master node version + if(params.register == 4 && saveToTb) + { + let values = { + "status": "NOK", + "master_node_version": "NOK" + }; + + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); + + FLOW.OMS_masterNodeIsResponding = false; + } + //treba? + /* + else if(saveToTb) + { + let values = { + "comm_status": "no_comm" + }; + + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + instance.send(SEND_TO.tb, dataToTb); + } + */ + + instance.send(SEND_TO.debug, reason); + }); + } - else { - // if(currentTask.debug) - // { - // //currentTask.timestamp <= currentTimestamp - // logger.debug("currentTask is not processed - task is in the future", currentTask); - // } + else + { + if(currentTask.debug) + { + //currentTask.timestamp <= currentTimestamp + logger.debug("currentTask is not processed - task is in the future", currentTask); + } interval = setInterval(runTasks, LONG_INTERVAL); return; - } + } //console.log("----->runTasks - setInterval", new Date()); interval = setInterval(runTasks, SHORT_INTERVAL); - } + } + + //! rsPort LM = "/dev/ttymxc4", rsPort UNIPI = "/dev/ttyUSB0" + // const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM + // const rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false }); // UNIPI - function handleNokResponseOnRsPort(message, params, itIsNodeCommand, saveToTb) { + if(FLOW.OMS_serial_port == "" || FLOW.OMS_serial_port == undefined || FLOW.OMS_serial_port.length === 1) FLOW.OMS_serial_port = "ttymxc4"; + const rsPort = new SerialPort(`/dev/${FLOW.OMS_serial_port}`, { autoOpen: false }); + //(node:16372) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 13 data listeners added to [SerialPort]. Use emitter.setMaxListeners() to increase limit + //rsPort.setMaxListeners(0); - let node = params.address; - let register = params.register; - let type = params.type; - let tbName = params.tbname; - if (!tbName) return; + rsPort.on('open', async function() { - let values = {}; + logger.debug("CMD manager - rsPort opened sucess"); - // console.log(message); - let updateStatus = updateNodeStatus(node, false); + loadRelaysData(); - //master node - if (node == 0) { - sendNotification("CMD Manager: process cmd", SETTINGS.rvoTbName, "master_node_is_not_responding", {}, "", SEND_TO.tb, instance, "rvo_status"); - logger.debug("master_node_is_not_responding", params); - SETTINGS.masterNodeIsResponding = false; + await runSyncExec(`stty -F /dev/${FLOW.OMS_serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function (status) { + instance.send(SEND_TO.debug, "RPC runSyncExec - Promise Resolved:" + status); - if (register == 4) values["master_node_version"] = "NOK"; - } + logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status); - if (type == "set_node_profile") { - delete cmdCounter[node]; - logger.debug("profil nebol úspešne odoslaný na node č. ", params); - sendNotification("CMD Manager: process cmd", tbName, "configuration_of_dimming_profile_to_node_failed", { node: node }, "", SEND_TO.tb, instance); - } + //APP START + let dataToInfoSender = {id: FLOW.OMS_projects_id, name: FLOW.OMS_rvo_name}; + dataToInfoSender.fw_version = FLOW.OMS_edge_fw_version; + dataToInfoSender.startdate = new Date().toISOString().slice(0, 19).replace('T', ' '); + dataToInfoSender.__force__ = true; + + instance.send(SEND_TO.infoSender, dataToInfoSender); - if (itIsNodeCommand) { - values.comm_status = "NOK"; - } + logger.debug(0, "---------------------------->START message send to service", dataToInfoSender); - if (updateStatus) { - values.status = "NOK"; - } - - // console.log("------",node, register, type, itIsNodeCommand, updateStatus, saveToTb, values); - if (saveToTb && Object.keys(values).length > 0) { - sendTelemetry(values, tbName) - } - - } - - - /** - * function handles requests from terminal - * responseType can be "SUCCESS", "ERROR" or "FAILURE", depending on rsPort data. - * FAILURE means, that we got into catch block of writeData function. - */ - function terminalCommandResponse(params, responseType, data = null, reason = "") { //success, error, failure - - if (params.refFlowdataKey == undefined) { - //console.log("params.refFlowdataKey is undefined", params); - return; - } - else { - console.log("params.refFlowdataKey: ", params); - } - - let message = null; - let type = null; - - switch (responseType) { - case "SUCCESS": - message = "cmd-terminal SUCCESS"; - type = "SUCCESS"; - break; - case "ERROR": - message = "cmd-terminal FAILED"; - type = "ERROR"; - break; - case "FAILURE": - message = "ERROR WRITE FAILED: " + reason; - type = "ERROR"; - break; - default: - type = undefined; - } - - logger.debug(message); - logger.debug(params); - - //make http response - let responseObj = {} - responseObj["type"] = type; - - if (responseType == "FAILURE") responseObj["message"] = "ERROR WRITE FAILED: " + reason; - else responseObj["bytes"] = data; - - let refFlowdata = refFlowdataObj[params.refFlowdataKey]; //holds reference to httprequest flowdata - if (refFlowdata) { - refFlowdata.data = responseObj; - instance.send(SEND_TO.http_response, refFlowdata); - } - } - - - /** - * function handles tasks, that are not needed to run through masterNode. To make them run smooth without waiting for other tasks to be completed, we moved them in separate function - */ - function reportEdgeDateTimeAndNumberOfLuminaires() { - - //Number of ok and nok nodes on platform does not equals to total number of nodes. - //possible error is, that nodesData object is changing all the time. To make a proper calculation of ok,nok luminaires, we make a copy of it: - let nodesData_clone = JSON.parse(JSON.stringify(nodesData)); - - const ts = Date.now(); - const keys = Object.keys(nodesData_clone); - - const number_of_luminaires = keys.length; - let number_of_ok_luminaires = 0; - let number_of_nok_luminaires = 0; - - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; - let nodeObj = nodesData_clone[key]; - if (nodeObj.tbname == undefined) continue; - - if (nodeObj.status) number_of_ok_luminaires++; - else number_of_nok_luminaires++; - } - - const values = { - "number_of_luminaires": number_of_luminaires, - "number_of_ok_luminaires": number_of_ok_luminaires, - "number_of_nok_luminaires": number_of_nok_luminaires, - "edge_date_time": ts - }; - - sendTelemetry(values, SETTINGS.rvoTbName, ts); - } - - - function handleRsPort() { - - //! rsPort LM = "/dev/ttymxc4", rsPort UNIPI = "/dev/ttyUSB0" - // const rsPort = new SerialPort("/dev/ttymxc4", { autoOpen: false }); //LM - // const rsPort = new SerialPort("/dev/ttyUSB0", { autoOpen: false }); // UNIPI - - if (SETTINGS.serial_port == "" || SETTINGS.serial_port == undefined || SETTINGS.serial_port.length === 1) SETTINGS.serial_port = "ttymxc4"; - rsPort = new SerialPort(`/dev/${SETTINGS.serial_port}`, { autoOpen: false }); - //(node:16372) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 13 data listeners added to [SerialPort]. Use emitter.setMaxListeners() to increase limit - //rsPort.setMaxListeners(0); - - rsPort.on('open', async function() { - - logger.debug("CMD manager - rsPort opened success"); - - //loadRelaysData(); - - await runSyncExec(`stty -F /dev/${SETTINGS.serial_port} 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke`).then(function(status) { - instance.send(SEND_TO.debug, "RPC runSyncExec - Promise Resolved:" + status); - - logger.debug(0, "RPC runSyncExec - Promise Resolved:" + status); - - //APP START - let dataToInfoSender = { id: SETTINGS.project_id, name: SETTINGS.rvo_name }; - dataToInfoSender.fw_version = SETTINGS.edge_fw_version; - dataToInfoSender.startdate = new Date().toISOString().slice(0, 19).replace('T', ' '); - dataToInfoSender.__force__ = true; - - instance.send(SEND_TO.infoSender, dataToInfoSender); - - logger.debug(0, "---------------------------->START message send to service", dataToInfoSender); - - }).catch(function(reason) { - instance.send(SEND_TO.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason); - }); + }).catch(function (reason) { + instance.send(SEND_TO.debug, "CMD manager - RPC runSyncExec - promise rejected:" + reason); }); + }); - rsPort.on('error', function(err) { - + rsPort.on('error', function(err) { + //TODO report to service!!! - //errLogger.error(exports.title, "unable to open port", SETTINGS.serial_port, err.message); - errorHandler.sendMessageToService([exports.title, "unable to open port", SETTINGS.serial_port, err.message], 0); + //errLogger.error(exports.title, "unable to open port", FLOW.OMS_serial_port, err.message); + errorHandler.sendMessageToService([exports.title, "unable to open port", FLOW.OMS_serial_port, err.message], 0); instance.send(SEND_TO.debug, err.message); - }); + }); - rsPort.on("close", () => { - setTimeout(() => rsPort.open(), 1000); - }); - - rsPort.open(); - } + rsPort.on("close", () => { + rsPort.close(); + }); + //loadRelaysData(); + rsPort.open(); instance.on("close", () => { clearInterval(interval); - clearInterval(customTasksInterval); - clearInterval(setCorrectTime); rsPort.close(); }); - instance.on("0", flowdata => { - main(); - }) - - instance.on("1", async function(flowdata) { + instance.on("data", async function(flowdata) { //instance.send(SEND_TO.debug, "on Data"); //instance.send(SEND_TO.debug, flowdata); - + //logger.debug(flowdata.data); //just testing functions - if (flowdata.data == "open") { - if (!rsPort.isOpen) rsPort.open(); + if(flowdata.data == "open") + { + if(!rsPort.isOpen) rsPort.open(); return; } - else if (flowdata.data == "close") { + else if(flowdata.data == "close") + { rsPort.close(); return; } - else if (flowdata.data == "clean") { + else if(flowdata.data == "clean") + { tasks = []; return; } - else if (flowdata.data == "buildtasks") { + else if(flowdata.data == "buildtasks") + { //build & run return; } - else if (flowdata.data == "run") { + else if(flowdata.data == "run") + { //durations = []; - if (tasks.length == 0) { + if(tasks.length == 0) + { buildTasks(); - if (rsPort.isOpen) { - interval = setInterval(runTasks, 100); + if(rsPort.isOpen) + { + interval = setInterval(runTasks, 100); } - else { - instance.send(SEND_TO.debug, "port is not opened!!!"); + else + { + instance.send(SEND_TO.debug, "port is not opened!!!"); } } } - else { + else + { //terminal data - object //logger.debug("flowdata", flowdata.data); - if (typeof flowdata.data === 'object') { + if(typeof flowdata.data === 'object') + { //logger.debug("dido", flowdata.data); - if (flowdata.data.hasOwnProperty("sender")) { + if(flowdata.data.hasOwnProperty("sender")) + { //data from dido_controller - if (flowdata.data.sender == "dido_controller") { + if(flowdata.data.sender == "dido_controller") + { - if (flowdata.data.hasOwnProperty("cmd")) { + if(flowdata.data.hasOwnProperty("cmd")) + { let cmd = flowdata.data.cmd; - if (cmd == "buildTasks") { + + if(cmd == "buildTasks") + { clearInterval(interval); logger.debug("-->CMD MANAGER - BUILD TASKS"); @@ -2081,37 +2592,46 @@ exports.install = function(instance) { logger.debug("-->CMD MANAGER - RUN TASKS"); interval = setInterval(runTasks, LONG_INTERVAL); } - else if (cmd == "reload_relays") { + else if(cmd == "reload_relays") + { loadRelaysData(flowdata.data.line); - if (flowdata.data.dataChanged) { - if (!flowdata.data.value) { + if(flowdata.data.dataChanged) + { + if(!flowdata.data.value) + { reportOfflineNodeStatus(flowdata.data.line); } - else { + else + { reportOnlineNodeStatus(flowdata.data.line); } } - + } - else if (cmd == "rotary_switch_state") { - let value = flowdata.data.value; - + else if(cmd == "rotary_switch_state") + { //state was changed - if (rotary_switch_state != value) { - if (value == "Off") { + if(rotary_switch_state != flowdata.data.value) + { + if(rotary_switch_state == "Off") + { //vyreportovat vsetky svietdla reportOfflineNodeStatus(); } + else reportOnlineNodeStatus(); - rotary_switch_state = value; } + + rotary_switch_state = flowdata.data.value; } - else if (cmd == "lux_sensor") { + else if(cmd == "lux_sensor") + { lux_sensor = parseInt(flowdata.data.value); // POSSIBLE SOURCE OF PROBLEMS, IF USER SETS LUX TRESHOLD LEVEL GREATER THAN 100 - WE SHOULD BE CHECKING "DUSK/DAWN_LUX_SENSOR_VALUE" IN PROFILE MAYBE ?? - if (lux_sensor < 100) { + if(lux_sensor < 100) + { // we send lux_sensor value to all nodes: let params = getParams(PRIORITY_TYPES.node_broadcast); @@ -2130,41 +2650,70 @@ exports.install = function(instance) { tasks.push(params); + //process profiles turnOnOffLinesAccordingToLuxSensor(lux_sensor); } } - else if (cmd == "state_of_breaker") { + else if(cmd == "state_of_breaker") + { //istic linie let value = flowdata.data.value; let line = parseInt(flowdata.data.line); let dataChanged = false; - if (state_of_breaker[line] != value) dataChanged = true; + if(state_of_breaker[line] != value) dataChanged = true; state_of_breaker[line] = value; let status = "OK"; - if (value == "Off") status = "NOK"; + let weight = ERRWEIGHT.NOTICE; + let message = `zapnutý istič línie č. ${line}`; + if(value == "Off") + { + weight = ERRWEIGHT.ERROR; + message = `vypnutý istič línie č. ${line}`; + status = "NOK"; + } - if (dataChanged) { + if(dataChanged) { - if (relaysData.hasOwnProperty(line)) { + if(relaysData.hasOwnProperty(line)) + { let tbname = relaysData[line].tbname; - if (value == "Off") sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_off_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); - else sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_on_line", { line: line }, "", SEND_TO.tb, instance, "circuit_breaker"); + if(value == "Off") sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_off_line", {line: line}, "", SEND_TO.tb, instance, "circuit_breaker"); + else sendNotification("CMD Manager: onData", tbname, "circuit_breaker_was_turned_on_line", {line: line}, "", SEND_TO.tb, instance, "circuit_breaker"); //report status liniu - sendTelemetry({ status: status }, tbname) + let values = { + "status": status + }; + + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + //instance.send(SEND_TO.tb, dataToTb); + tbHandler.sendToTb(dataToTb, instance); //current value - if (value == "Off") reportOfflineNodeStatus(line); //vyreportovat vsetky svietidla na linii + if(value == "Off") + { + //vyreportovat vsetky svietdla na linii + reportOfflineNodeStatus(line); + } + else reportOnlineNodeStatus(line); } } } - else { + else{ logger.debug("undefined cmd", cmd); } } @@ -2174,18 +2723,15 @@ exports.install = function(instance) { } //data from worksys - if (flowdata.data.hasOwnProperty("topic")) { + if(flowdata.data.hasOwnProperty("topic")) + { - let data = getNested(flowdata.data, "content", "data"); - if (data == undefined) { - console.log("Invalid rpc command came from platform"); - return; - } + let data = flowdata.data.content.data; let command = data.params.command; let method = data.method; let profile = data.params.payload; - if (profile == undefined) profile = ""; + if(profile == undefined) profile = ""; let entity = data.params.entities[0]; let entity_type = entity.entity_type; let tbname = entity.tb_name; @@ -2194,171 +2740,185 @@ exports.install = function(instance) { logger.debug("--->worksys", flowdata.data, data.params, entity, entity_type, command, method); logger.debug("----------------------------"); - if (entity_type == "street_luminaire" || entity_type === "street_luminaire_v4_1" || entity_type === "street_luminaire_v4_1cez" || entity_type === "street_luminaire_v4") { - if (method == "set_command") { + if(entity_type == "street_luminaire"|| entity_type === "street_luminaire_v4_1" || entity_type === "street_luminaire_v4_1cez" || entity_type === "street_luminaire_v4") + { + if(method == "set_command") + { //let command = data.params.command; let value = data.params.payload.value; - - if (command == "dimming") { + + if(command == "dimming") + { let nodeWasFound = false; let keys = Object.keys(nodesData); //logger.debug("-----", keys); - for (let i = 0; i < keys.length; i++) { + for(let i = 0; i < keys.length; i++) + { let node = keys[i]; //logger.debug( node, nodesData[node], tbname); - if (tbname == nodesData[node].tbname) { - let params = getParams(PRIORITY_TYPES.high_priority); + if(tbname == nodesData[node].tbname.trim()) + { + let params = getParams(PRIORITY_TYPES.high_priority); - value = parseInt(value); - if (value > 0) value = value + 128; + value = parseInt(value); + if(value > 0) value = value + 128; - //set dimming - LUM1_13 - 647 je node linie 1 kt. dobre vidime - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 1;//dimming - params.recipient = 1;//slave - params.byte4 = value; - params.rw = 1;//write - params.timestamp = PRIORITY_TYPES.high_priority; - params.info = 'set dimming from platform'; - //params.debug = true; + //set dimming - LUM1_13 - 647 je node linie 1 kt. dobre vidime + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.byte4 = value; + params.rw = 1;//write + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'set dimming from platform'; + //params.debug = true; - //ak linia je + //ak linia je - //debug(params); - logger.debug("dimming", params); + //debug(params); + logger.debug("dimming", params); - tasks.push(params); + tasks.push(params); - setTimeout(function() { + setTimeout(function(){ - //spustime o 4 sekundy neskor, s prioritou PRIORITY_TYPES.high_priority - //a pridame aj vyreportovanie dimmingu - { - let params = getParams(PRIORITY_TYPES.high_priority); + //spustime o 4 sekundy neskor, s prioritou PRIORITY_TYPES.high_priority + //a pridame aj vyreportovanie dimmingu + { + let params = getParams(PRIORITY_TYPES.high_priority); - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 1;//dimming - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = PRIORITY_TYPES.high_priority; - params.info = 'read dimming (after set dimming from platform)'; - params.debug = true; + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 1;//dimming + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read dimming (after set dimming from platform)'; + params.debug = true; - tasks.push(params); - } + tasks.push(params); + } - //pridame aj vyreportovanie - vykon - { - let params = getParams(PRIORITY_TYPES.high_priority); + //pridame aj vyreportovanie - vykon + { + let params = getParams(PRIORITY_TYPES.high_priority); - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 76; - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = PRIORITY_TYPES.high_priority; - params.info = 'read Input Power (after set dimming from platform)'; - params.debug = true; + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 76; + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Power (after set dimming from platform)'; + params.debug = true; - tasks.push(params); - } + tasks.push(params); + } - //pridame aj vyreportovanie - prud svietidla - { - let params = getParams(PRIORITY_TYPES.high_priority); + //pridame aj vyreportovanie - prud svietidla + { + let params = getParams(PRIORITY_TYPES.high_priority); - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 75; - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = PRIORITY_TYPES.high_priority; - params.info = 'read Input Current (after set dimming from platform)'; - params.debug = true; + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 75; + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read Input Current (after set dimming from platform)'; + params.debug = true; - tasks.push(params); - } + tasks.push(params); + } - //pridame aj vyreportovanie - power faktor - ucinnik - { - let params = getParams(PRIORITY_TYPES.high_priority); + //pridame aj vyreportovanie - power faktor - ucinnik + { + let params = getParams(PRIORITY_TYPES.high_priority); - params.type = "cmd"; - params.tbname = tbname; - params.address = node; - params.register = 77; - params.recipient = 1;//slave - params.rw = 0;//read - params.timestamp = PRIORITY_TYPES.high_priority; - params.info = 'read power factor - Cos phi (after set dimming from platform)'; - params.debug = true; + params.type = "cmd"; + params.tbname = tbname; + params.address = node; + params.register = 77; + params.recipient = 1;//slave + params.rw = 0;//read + params.timestamp = PRIORITY_TYPES.high_priority; + params.info = 'read power factor - Cos phi (after set dimming from platform)'; + params.debug = true; - tasks.push(params); - } + tasks.push(params); + } - }, 4000); + },4000); + + nodeWasFound = true; - nodeWasFound = true; - - break; + break; } } - if (!nodeWasFound) { + if(!nodeWasFound) + { logger.debug("set dimming from platform", "unable to find tbname", tbname); } } - else { + else + { instance.send(SEND_TO.debug, "undefined command " + command); logger.debug("undefined command", command); } return; } - else if (method == "set_profile") { + else if(method == "set_profile") + { //nastav profil nodu logger.debug("-->set_profile for node", data.params); logger.debug("------profile data", profile); //instance.send(SEND_TO.debug, "set_profile" + command); let keys = Object.keys(nodesData); - for (let i = 0; i < keys.length; i++) { + for(let i = 0; i < keys.length; i++) + { let node = keys[i]; - if (tbname == nodesData[node].tbname) { + if(tbname == nodesData[node].tbname.trim()) + { - if (profile != "") profile = JSON.stringify(profile); + if(profile != "") profile = JSON.stringify(profile); dbNodes.modify({ processed: false, profile: profile }).where("node", node).make(function(builder) { builder.callback(function(err, response) { - logger.debug("worksys - update node profile done", profile); - if (profile === "") logger.debug("worksys - update node profile done - profile is empty"); + logger.debug("worksys - update node profile done", profile); + if(profile === "") logger.debug("worksys - update node profile done - profile is empty"); - //profil úspešne prijatý pre node č. xx - sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", { node: node }, profile, SEND_TO.tb, instance); + //profil úspešne prijatý pre node č. xx + //sendNotification("CMD manager", tbname, ERRWEIGHT.INFO, `profil úspešne poslaný z platformy na RVO pre node č. ${node}`, profile, SEND_TO.tb, instance, null ); + sendNotification("CMD manager", tbname, "dimming_profile_was_processed_for_node", {node: node}, profile, SEND_TO.tb, instance ); - nodesData[node].processed = false; - nodesData[node].profile = profile; + nodesData[node].processed = false; + nodesData[node].profile = profile; - processNodeProfile(node); + let line = nodesData[node].line; + processNodeProfile(node); + + }); }); - }); } } } - else { + else + { instance.send(SEND_TO.debug, "unknown method " + method); logger.debug("unknown method", method); @@ -2368,24 +2928,28 @@ exports.install = function(instance) { } //nastav profil linie z platformy - else if (entity_type == "edb_line" || entity_type == "edb" || entity_type == "edb_line_ver4" || entity_type == "edb_ver4_se") { + else if(entity_type == "edb_line" || entity_type == "edb" || entity_type == "edb_line_ver4" || entity_type == "edb_ver4_se") + { //profil linie //relays.table line:number|tbname:string|contactor:number|profile:string //najdeme line relaysData - if (method == "set_profile") { + if(method == "set_profile") + { logger.debug("-->set_profile for line", data.params); logger.debug("profile data:", profile); let keys = Object.keys(relaysData); - for (let i = 0; i < keys.length; i++) { + for(let i = 0; i < keys.length; i++) + { let line = keys[i]; - if (tbname == relaysData[line].tbname) { + if(tbname == relaysData[line].tbname) + { //zmazeme tasky - removeTask({ type: "relay", line: line }); - - if (profile != "") profile = JSON.stringify(profile); + removeTask({type: "relay", line: line}); + + if(profile != "") profile = JSON.stringify(profile); dbRelays.modify({ profile: profile }).where("line", line).make(function(builder) { builder.callback(function(err, response) { @@ -2394,18 +2958,12 @@ exports.install = function(instance) { logger.debug("worksys - update relay profile done:", profile); instance.send(SEND_TO.debug, "worksys - update relay profile done"); - relaysData[line].profile = profile; - - loadRelaysData(line) - - //TODO build tasks by mala bezat az ked je vsetko loadRelaysData - //spracovane, pravdepodobne treba spravit promisy - logger.debug("loadRelaysData DONE for line", line); - console.log("zacina buildTasks po loadRelaysData.........") - - buildTasks({ processLineProfiles: true, line: line }); - - sendNotification("CMD manager - set profile from worksys", tbname, "switching_profile_was_processed_for_line", { line: line }, profile, SEND_TO.tb, instance); + loadRelaysData(line).then(function (data) { + logger.debug("loadRelaysData DONE for line", line); + buildTasks({processLineProfiles: true, line: line}); + }); + + sendNotification("CMD manager - set profile from worksys", tbname, "switching_profile_was_processed_for_line", {line: line}, profile, SEND_TO.tb, instance ); }); }); @@ -2413,31 +2971,35 @@ exports.install = function(instance) { } } } - else if (method == "set_command") { + else if(method == "set_command") + { let value = data.params.payload.value; - if (command === "switch") { + if(command === "switch") + { - // if we receive rpc from platform, to switch maintenance mode, we set SETTINGS.maintenance_mode flow variable to value; - if (entity_type === "edb" || entity_type === "edb_ver4_se") SETTINGS.maintenance_mode = value; + // if we receive rpc from platform, to switch maintenance mode, we set OMS_maintenance_mode flow variable to value; + if(entity_type === "edb" || entity_type === "edb_ver4_se") FLOW.variables.OMS_maintenance_mode = value; + + let responseRelays = await promisifyBuilder(dbRelays.find().where("tbname", tbname)); - const relayObject = getObjectByTbValue(relaysData, tbname); let line = 0; - if (isObject(relayObject)) line = relayObject.line; - - // v relaysData je contactor bud 0 alebo 1, ale z platformy prichadza true, false; - if (value == false) turnLine("off", line, "command received from platform"); - else turnLine("on", line, "command received from platform"); + if(responseRelays.length == 1) line = responseRelays[0].line; + + if(value == false) turnOffLine(line, "command received form platform"); + else turnOnLine(line, "command received form platform"); } } - else { + else + { instance.send(SEND_TO.debug, "undefined method " + method); logger.debug("undefined method", method); } return; } - else { + else + { instance.send(SEND_TO.debug, "UNKNOW entity_type " + entity_type); logger.debug("UNKNOW entity_type", entity_type); } @@ -2445,10 +3007,11 @@ exports.install = function(instance) { } //terminal - if (!rsPort.isOpen) await rsPort.open(); + if(!rsPort.isOpen) await rsPort.open(); let params = flowdata.data.body; - if (params == undefined) { + if(params == undefined) + { //logger.debug("CMD manager flowdata.data.body is undefined"); return; } @@ -2469,7 +3032,7 @@ exports.install = function(instance) { cleanUpRefFlowdataObj(); - refFlowdataObj[timestamp] = flowdata; + refFlowdataObj[ timestamp ] = flowdata; //fix //params.address = params.adress; @@ -2486,500 +3049,745 @@ exports.install = function(instance) { } }) - - //function gets value of a nested property in an object and returns undefined if it does not exists: - function getNested(obj, ...args) { - return args.reduce((obj, level) => obj && obj[level], obj) - } +} // end of instance.export - /** - * setCorrectTime function runs once per hour - * If it is 3 o'clock, it sets actual time, which is got from services - * https://service-prod01.worksys.io/gettime - * If also detects Read Only Filesystem once a day - */ - function setCorrectPlcTimeOnceADay() { +/** + * setCorrectTime function runs once per hour + * If it is 3 o'clock, it sets actual time, which is got from services + * https://service-prod01.worksys.io/gettime + * If also detects Read Only Filesystem once a day + */ +function setCorrectPlcTimeOnceADay() +{ - const currentTime = new Date(); - if (currentTime.getHours() != 3) return; + const currentTime = new Date(); + if(currentTime.getHours() != 3) return; - RESTBuilder.make(function(builder) { + RESTBuilder.make(function(builder) { - if (!builder) return; + if(!builder) return; - builder.method('GET'); - builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); + builder.method('GET'); + builder.url('http://192.168.252.2:8004/gettime?projects_id=1'); - builder.callback(function(err, response, output) { + builder.callback(function(err, response, output) { - if (err) { - console.log(err); - return; + if (err) { + console.log(err); + return; + } + + const res = output.response; + + try { + + const obj = JSON.parse(res); + let d = new Date(obj.date); + + const now = new Date(); + + let diffInMinutes = now.getTimezoneOffset(); + console.log("---->TimezoneOffset", diffInMinutes); + + if(d instanceof Date) + { + + // monitor.info("----------->setCorrectPlcTimeOnceADay() current js date:", d, d.getHours()); + + let year = d.getFullYear(); + let month = addZeroBefore(d.getMonth() + 1); + let day = addZeroBefore(d.getDate()); + + let hours = addZeroBefore(d.getHours()); + let minutes = addZeroBefore(d.getMinutes() ); + let seconds = addZeroBefore(d.getSeconds()); + + let dateStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + + exec(`sudo timedatectl set-time "${dateStr}"`, (err, stdout, stderr) => { + if (err || stderr) { + console.error(err); + console.log(stderr); + console.log(dateStr); + + monitor.info("failed timedatectl set-time", err, stderr); + } + else + { + monitor.info("setCorrectPlcTimeOnceADay() --> Nastaveny cas na: ", dateStr); + } + + }); } - const res = output.response; + } catch (error) { + logger.debug("setCorrectPlcTimeOnceADay - function error", error, res); + monitor.info("setCorrectPlcTimeOnceADay - function error", error, res); + } - try { + // we detect readOnlyFileSystem once an hour as well + detectReadOnlyFilesystem(); - const obj = JSON.parse(res); - let d = new Date(obj.date); - - const now = new Date(); - - let diffInMinutes = now.getTimezoneOffset(); - console.log("---->TimezoneOffset", diffInMinutes); - - if (d instanceof Date) { - - // monitor.info("----------->setCorrectPlcTimeOnceADay() current js date:", d, d.getHours()); - - let year = d.getFullYear(); - let month = addZeroBefore(d.getMonth() + 1); - let day = addZeroBefore(d.getDate()); - - let hours = addZeroBefore(d.getHours()); - let minutes = addZeroBefore(d.getMinutes()); - let seconds = addZeroBefore(d.getSeconds()); - - let dateStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; - - exec(`sudo timedatectl set-time "${dateStr}"`, (err, stdout, stderr) => { - if (err || stderr) { - console.error(err); - console.log(stderr); - console.log(dateStr); - - monitor.info("failed timedatectl set-time", err, stderr); - } - else { - monitor.info("setCorrectPlcTimeOnceADay() --> Nastaveny cas na: ", dateStr); - } - - }); - } - - } catch (error) { - logger.debug("setCorrectPlcTimeOnceADay - function error", error, res); - monitor.info("setCorrectPlcTimeOnceADay - function error", error, res); - } - - // we detect readOnlyFileSystem once an hour as well - detectReadOnlyFilesystem(); - - }); }); + }); - } +} - function detectReadOnlyFilesystem() { - exec(`sudo egrep " ro,|,ro " /proc/mounts`, (err, stdout, stderr) => { - if (err || stderr) { - console.error(err); - console.log(stderr); +function detectReadOnlyFilesystem() +{ + exec(`sudo egrep " ro,|,ro " /proc/mounts`, (err, stdout, stderr) => { + if (err || stderr) { + console.error(err); + console.log(stderr); - } else { - //console.log("Read-only", stdout); + } else { + //console.log("Read-only", stdout); + + let lines = stdout + ""; + lines = lines.split("\n"); - let lines = stdout + ""; - lines = lines.split("\n"); - - let readOnlyDetected = ""; - for (let i = 0; i < lines.length; i++) { - if (lines[i].startsWith("/dev/mmcblk0p2")) { - readOnlyDetected = lines[i]; - } - } - - if (readOnlyDetected !== "") { - errorHandler.sendMessageToService("Detected: Read-only file system: " + readOnlyDetected); - monitor.info("Read only filesystem detected"); - } - - } - }); - } - - - - - - - - - ///helper functions - function sendTelemetry(values, tbname, date = Date.now()) { - const dataToTb = { - [tbname]: [ + let readOnlyDetected = ""; + for(let i = 0; i < lines.length; i++) + { + if(lines[i].startsWith("/dev/mmcblk0p2")) { - "ts": date, - "values": values + readOnlyDetected = lines[i]; } - ] + } + + if(readOnlyDetected !== "") + { + errorHandler.sendMessageToService("Detected: Read-only file system: " + readOnlyDetected); + monitor.info("Read only filesystem detected"); + } + + } + }); +} + +let setCorrectTime = setInterval(setCorrectPlcTimeOnceADay, 60000 * 60); // 1 hour +setCorrectPlcTimeOnceADay(); + + + + + + + + + +///helper functions + +function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) +{ + + if(date === undefined) date = new Date(); + //if(duskOffset === undefined) duskOffset = 0; + //if(dawnOffset === undefined) dawnOffset = 0; + + //let line = keys[i]; + let profilestr = ""; + if(relaysData[line] != undefined) profilestr = relaysData[line].profile; + + let result = {}; + + var times = SunCalc.getTimes(date, latitude, longitude); + let dawn = new Date(times.sunrise);//usvit + let dusk = new Date(times.sunset);//sumrak + + + //http://suncalc.net/#/48.5598,18.169,11/2021.04.07/11:06 + //https://mapa.zoznam.sk/zisti-gps-suradnice-m6 + + + let dusk_astro_clock_offset = duskOffset;//minutes + let dawn_astro_clock_offset = dawnOffset;//minutes + + try { + + let profile = JSON.parse(profilestr); + if(Object.keys(profile).length === 0) throw ("profile is not defined"); + + //Jednoduchý režim + if(profile.astro_clock == false && profile.dusk_lux_sensor == false && profile.dawn_lux_sensor == false) + { + } - tbHandler.sendToTb(dataToTb, instance); - } - - function calculateDuskDawn(date, line, duskOffset = 0, dawnOffset = 0) { - - if (date === undefined) date = new Date(); - //if(duskOffset === undefined) duskOffset = 0; - //if(dawnOffset === undefined) dawnOffset = 0; - - //let line = keys[i]; - let profilestr = ""; - if (relaysData[line] != undefined) profilestr = relaysData[line].profile; - - let result = {}; - - var times = SunCalc.getTimes(date, latitude, longitude); - let dawn = new Date(times.sunrise);//usvit - let dusk = new Date(times.sunset);//sumrak - - - //http://suncalc.net/#/48.5598,18.169,11/2021.04.07/11:06 - //https://mapa.zoznam.sk/zisti-gps-suradnice-m6 - - - let dusk_astro_clock_offset = duskOffset;//minutes - let dawn_astro_clock_offset = dawnOffset;//minutes - - try { - - let profile = JSON.parse(profilestr); - if (Object.keys(profile).length === 0) throw ("profile is not defined"); - - //Jednoduchý režim - if (profile.astro_clock == false && profile.dusk_lux_sensor == false && profile.dawn_lux_sensor == false) { - + //Režim astrohodín + if(profile.astro_clock == true) + { + //if(profile.dusk_lux_sensor == false) + { + if(profile.hasOwnProperty("dusk_astro_clock_offset")) dusk_astro_clock_offset = parseInt( profile.dusk_astro_clock_offset ); } - //Režim astrohodín - if (profile.astro_clock == true) { - //if(profile.dusk_lux_sensor == false) - { - if (profile.hasOwnProperty("dusk_astro_clock_offset")) dusk_astro_clock_offset = parseInt(profile.dusk_astro_clock_offset); - } - - //if(profile.dawn_lux_sensor == false) - { - if (profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt(profile.dawn_astro_clock_offset); - } - - } - - //dusk - súmrak - //down, sunrise - svitanie - - } catch (error) { - if (profilestr != "") { - logger.debug(profilestr); - logger.debug(error); + //if(profile.dawn_lux_sensor == false) + { + if(profile.hasOwnProperty("dawn_astro_clock_offset")) dawn_astro_clock_offset = parseInt( profile.dawn_astro_clock_offset ); } + } - result.dusk_no_offset = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes()); - result.dawn_no_offset = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes()); - - dusk = new Date(dusk.getTime() + gmtOffset + dusk_astro_clock_offset * 60000); - dawn = new Date(dawn.getTime() + gmtOffset + dawn_astro_clock_offset * 60000); - - result.dusk = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes()); - result.dusk_hours = dusk.getHours(); - result.dusk_minutes = dusk.getMinutes(); - - result.dawn = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes()); - result.dawn_hours = dawn.getHours(); - result.dawn_minutes = dawn.getMinutes(); - - result.dusk_time = dusk.getTime(); - result.dawn_time = dawn.getTime(); - - result.dusk_astro_clock_offset = dusk_astro_clock_offset; - result.dawn_astro_clock_offset = dawn_astro_clock_offset; - - return result; - } - - - function processResponse(register, bytes) { - - let values = {}; - - let byte3 = bytes[0]; - let byte2 = bytes[1]; - let byte1 = bytes[2]; - let byte0 = bytes[3]; - - //status - if (register == 0) { - let statecode = bytesToInt(bytes); - values = { "statecode": statecode }; - return values; + //dusk - súmrak + //down, sunrise - svitanie + + } catch (error) { + if(profilestr != "") + { + logger.debug(profilestr); + logger.debug(error); } + } - //Dimming, CCT - if (register == 1) { - let brightness = 0; - let dimming = byte0; - if (dimming > 128) { - //dimming = -128; - brightness = dimming - 128; - } + result.dusk_no_offset = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes()); + result.dawn_no_offset = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes()); - //cct - //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 - let cct; - if (byte3 == 1) cct = byte2 * 256 + byte1; - else cct = bytesToInt(bytes.slice(0, 3)); + dusk = new Date(dusk.getTime() + gmtOffset + dusk_astro_clock_offset*60000); + dawn = new Date(dawn.getTime() + gmtOffset + dawn_astro_clock_offset*60000); - //cct podla auditu + result.dusk = addZeroBefore(dusk.getHours()) + ":" + addZeroBefore(dusk.getMinutes()); + result.dusk_hours = dusk.getHours(); + result.dusk_minutes = dusk.getMinutes(); - values["dimming"] = brightness; - return values; - } + result.dawn = addZeroBefore(dawn.getHours()) + ":" + addZeroBefore(dawn.getMinutes()); + result.dawn_hours = dawn.getHours(); + result.dawn_minutes = dawn.getMinutes(); - // - if (register == 4) { - values["master_node_version"] = bytes[1] + "." + bytes[2]; - //logger.debug("FW Version", register, bytes); - } + result.dusk_time = dusk.getTime(); + result.dawn_time = dawn.getTime(); - //Napätie - if (register == 74) { - let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); - values["voltage"] = Number(voltage); - } + result.dusk_astro_clock_offset = dusk_astro_clock_offset; + result.dawn_astro_clock_offset = dawn_astro_clock_offset; - //Prúd - if (register == 75) { - let current = bytesToInt(bytes); - values["current"] = current; - } + return result; +} - //výkon - if (register == 76) { - let power = (bytesToInt(bytes) * 0.1).toFixed(2); - values["power"] = Number(power); - } - //účinník - if (register == 77) { - let power_factor = Math.cos(bytesToInt(bytes) * 0.1).toFixed(2); - values["power_factor"] = Number(power_factor); - } +function processResponse(register, bytes) +{ - //frekvencia - if (register == 78) { - let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); - values["frequency"] = Number(frequency); - } + let values = {}; - //energia - if (register == 79) { - let energy = bytesToInt(bytes); - - //Energiu treba reportovať v kWh. Teda číslo, ktoré príde treba podeliť 1000. Toto som ti možno zle napísal. - - values["energy"] = energy / 1000; - } - - //doba života - if (register == 80) { - let lifetime = (bytesToInt(bytes) / 60).toFixed(2); - values["lifetime"] = Number(lifetime); - } - - //nastavenie profilu - if (register == 8) { - let time_schedule_settings = bytesToInt(bytes); - values["time_schedule_settings"] = time_schedule_settings; - } - - //skupinová adresa 1 - if (register == 3) { - let gr_add_1 = bytesToInt(byte0); - values["gr_add_1"] = gr_add_1; - - let gr_add_2 = bytesToInt(byte1); - values["gr_add_2"] = gr_add_2; - - let gr_add_3 = bytesToInt(byte2); - values["gr_add_3"] = gr_add_3; - - let gr_add_4 = bytesToInt(byte3); - values["gr_add_4"] = gr_add_4; - } - - //naklon - if (register == 84) { - let temp; - if (byte3 >= 128) { - temp = (byte3 - 128) * (-1); - } - else { - temp = byte3; - } - - let inclination_x; - if (byte2 >= 128) { - inclination_x = (byte2 - 128) * (-1); - } - else { - inclination_x = byte2; - } - - let inclination_y; - if (byte1 >= 128) { - inclination_y = (byte1 - 128) * (-1); - } - else { - inclination_y = byte1; - } - - let inclination_z; - if (byte0 >= 128) { - inclination_z = (byte0 - 128) * (-1); - } - else { - inclination_z = byte0; - } - - values["temperature"] = temp; - - //náklon x - values["inclination_x"] = inclination_x; - - //náklon y - values["inclination_y"] = inclination_y; - - //náklon z - values["inclination_z"] = inclination_z; - } - - let h = byte3; - let m = byte2; - - let timestamp; - - if (register == 87 || register == 6 || register == 7) { - //if(byte3 < 10) h = "0" + byte3; - //if(byte2 < 10) m = "0" + byte2; - //if(byte1 < 10) s = "0" + byte1; - - var d = new Date(); - d.setHours(h, m, 0); - timestamp = d.getTime(); - } - - //aktuálny čas - if (register == 87) { - //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. - //values["actual_time"] = h + ":" + m + ":" + s; - - values["actual_time"] = timestamp; - } - - //čas súmraku - if (register == 6) { - //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. - //values["dusk_time"] = h + ":" + m + ":" + s; - - values["dusk_time"] = timestamp; - } - - //čas úsvitu - if (register == 7) { - //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. - //values["dawn_time"] = h + ":" + m + ":" + s; - - values["dawn_time"] = timestamp; - } - - //FW verzia - if (register == 89) { - //formát: "Byte3: Byte2.Byte1 (Byte0)" - values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; - } + let byte3 = bytes[0]; + let byte2 = bytes[1]; + let byte1 = bytes[2]; + let byte0 = bytes[3]; + //status + if(register == 0) + { + let statecode = bytesToInt(bytes); + values = {"statecode": statecode}; return values; } - - //byte1 MSB = data3, byte2 = data2, byte3 = data1, byte4 = data0 LSB - function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4) { - let resp = []; - - let cmd = register; - - if (typeof adresa === 'string') adresa = parseInt(adresa); - if (typeof byte1 === 'string') byte1 = parseInt(byte1); - if (typeof byte2 === 'string') byte2 = parseInt(byte2); - if (typeof byte3 === 'string') byte3 = parseInt(byte3); - if (typeof byte4 === 'string') byte4 = parseInt(byte4); - - if (rw === 0) { - cmd = cmd + 0x8000; + //Dimming, CCT + if(register == 1) + { + let brightness = 0; + let dimming = byte0; + if(dimming > 128) { + //dimming = -128; + brightness = dimming - 128; } - //master - if (rec === 0) adresa = 0; + //cct + //Ak Byte3 == 1: CCT = (Byte2*256)+Byte1 + let cct; + if(byte3 == 1) cct = byte2*256 + byte1; + else cct = bytesToInt(bytes.slice(0, 3)); - if (rec === 2) { - adresa = 0xffffffff;//Broadcast + //cct podla auditu + + values["dimming"] = brightness; + return values; + } + + // + if(register == 4) + { + values["master_node_version"] = bytes[1] + "." + bytes[2]; + //logger.debug("FW Version", register, bytes); + } + + //Napätie + if(register == 74) + { + let voltage = (bytesToInt(bytes) * 0.1).toFixed(1); + values["voltage"] = Number(voltage); + } + + //Prúd + if(register == 75) + { + let current = bytesToInt(bytes); + values["current"] = current; + } + + //výkon + if(register == 76) + { + let power = (bytesToInt(bytes) * 0.1).toFixed(2); + values["power"] = Number(power); + } + + //účinník + if(register == 77) + { + let power_factor = Math.cos(bytesToInt(bytes) * 0.1).toFixed(2); + values["power_factor"] = Number(power_factor); + } + + //frekvencia + if(register == 78) + { + let frequency = (bytesToInt(bytes) * 0.1).toFixed(2); + values["frequency"] = Number(frequency); + } + + //energia + if(register == 79) + { + let energy = bytesToInt(bytes); + + //Energiu treba reportovať v kWh. Teda číslo, ktoré príde treba podeliť 1000. Toto som ti možno zle napísal. + + values["energy"] = energy / 1000; + } + + //doba života + if(register == 80) + { + let lifetime = ( bytesToInt(bytes) / 60).toFixed(2); + values["lifetime"] = Number(lifetime); + } + + //nastavenie profilu + if(register == 8) + { + let time_schedule_settings = bytesToInt(bytes); + values["time_schedule_settings"] = time_schedule_settings; + } + + //skupinová adresa 1 + if(register == 3) + { + let gr_add_1 = bytesToInt(byte0); + values["gr_add_1"] = gr_add_1; + + let gr_add_2 = bytesToInt(byte1); + values["gr_add_2"] = gr_add_2; + + let gr_add_3 = bytesToInt(byte2); + values["gr_add_3"] = gr_add_3; + + let gr_add_4 = bytesToInt(byte3); + values["gr_add_4"] = gr_add_4; + } + + //naklon + if(register == 84) + { + let temp; + if(byte3 >= 128) + { + temp = (byte3 - 128) * (-1); + } + else + { + temp = byte3; } - //recipient - if (rec === 3) { - resp.push(0xFF); - resp.push(0xFF); - resp.push(0xFF); - resp.push(0xFF); - resp.push(adresa & 0xFF);//band + let inclination_x; + if(byte2 >= 128) + { + inclination_x = (byte2 - 128) * (-1); + } + else + { + inclination_x = byte2; } - else { - resp.push((adresa >> 24) & 0xFF);//rshift - resp.push((adresa >> 16) & 0xFF); - resp.push((adresa >> 8) & 0xFF); - resp.push(adresa & 0xFF); - if (rec === 2) { + let inclination_y; + if(byte1 >= 128) + { + inclination_y = (byte1 - 128) * (-1); + } + else + { + inclination_y = byte1; + } + + let inclination_z; + if(byte0 >= 128) + { + inclination_z = (byte0 - 128) * (-1); + } + else + { + inclination_z = byte0; + } + + values["temperature"] = temp; + + //náklon x + values["inclination_x"] = inclination_x; + + //náklon y + values["inclination_y"] = inclination_y; + + //náklon z + values["inclination_z"] = inclination_z; + } + + let h = byte3; + let m = byte2; + let s = byte1; + + let timestamp; + + if(register == 87 || register == 6 || register == 7 ) + { + //if(byte3 < 10) h = "0" + byte3; + //if(byte2 < 10) m = "0" + byte2; + //if(byte1 < 10) s = "0" + byte1; + + var d = new Date(); + d.setHours(h); + d.setMinutes(m); + d.setSeconds(s); + + timestamp = d.getTime(); + } + + //aktuálny čas + if(register == 87) + { + //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. + //values["actual_time"] = h + ":" + m + ":" + s; + + values["actual_time"] = timestamp; + } + + //čas súmraku + if(register == 6) + { + //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. + //values["dusk_time"] = h + ":" + m + ":" + s; + + values["dusk_time"] = timestamp; + } + + //čas úsvitu + if(register == 7) + { + //Byte3 - hodiny, Byte 2 - minúty, Byte 1 -sek. + //values["dawn_time"] = h + ":" + m + ":" + s; + + values["dawn_time"] = timestamp; + } + + //FW verzia + if(register == 89) + { + //formát: "Byte3: Byte2.Byte1 (Byte0)" + values["fw_version"] = byte3 + ":" + byte2 + "." + byte1 + "(" + byte0 + ")"; + } + + return values; +} + + +//byte1 MSB = data3, byte2 = data2, byte3 = data1, byte4 = data0 LSB +function com_generic(adresa, rec, rw, register, name, byte1, byte2, byte3, byte4) { + let resp = []; + + let cmd = register; + + if (typeof adresa === 'string') adresa = parseInt(adresa); + if (typeof byte1 === 'string') byte1 = parseInt(byte1); + if (typeof byte2 === 'string') byte2 = parseInt(byte2); + if (typeof byte3 === 'string') byte3 = parseInt(byte3); + if (typeof byte4 === 'string') byte4 = parseInt(byte4); + + if (rw === 0) + { + cmd = cmd + 0x8000; + } + + //master + if(rec === 0) adresa = 0; + + if(rec === 2) + { + adresa = 0xffffffff;//Broadcast + } + + //recipient + if (rec === 3) + { + resp.push(0xFF); + resp.push(0xFF); + resp.push(0xFF); + resp.push(0xFF); + resp.push( adresa & 0xFF );//band + } + else + { + resp.push( (adresa >> 24) & 0xFF);//rshift + resp.push( (adresa >> 16) & 0xFF); + resp.push( (adresa >> 8) & 0xFF); + resp.push( adresa & 0xFF ); + + if (rec === 2) + { resp.push(0xFF); - } - else resp.push(0); } - - resp.push((cmd >> 8) & 0xFF);//rshift - resp.push(cmd & 0xFF);//band - resp.push(byte1 & 0xFF);//band - resp.push(byte2 & 0xFF);//band - resp.push(byte3 & 0xFF);//band - resp.push(byte4 & 0xFF);//band - - //let data = '12345'; - let crc = crc16('ARC', resp); - let c1 = (crc >> 8) & 0xFF; - let c2 = crc & 0xFF; - - resp.push(c1); - resp.push(c2); - - //logger.debug("checksum", crc); - //logger.debug("resp", resp); - - return resp; - + else resp.push(0); } - function getObjectByTbValue(object, tbname) { - return object[Object.keys(object).find(key => object[key].tbname === tbname)]; + resp.push( (cmd >> 8) & 0xFF);//rshift + resp.push( cmd & 0xFF );//band + resp.push( byte1 & 0xFF );//band + resp.push( byte2 & 0xFF );//band + resp.push( byte3 & 0xFF );//band + resp.push( byte4 & 0xFF );//band + + //let data = '12345'; + let crc = crc16('ARC', resp); + let c1 = (crc >> 8) & 0xFF; + let c2 = crc & 0xFF; + + resp.push(c1); + resp.push(c2); + + //logger.debug("checksum", crc); + //logger.debug("resp", resp); + + return resp; + +} + + + + + + +// SAMPLE DATA + +const relaysDataExample = +{ + '0': { + line: 0, + tbname: 'jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV', + contactor: 1, + profile: '' + }, + '1': { + line: 1, + tbname: 'MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O', + contactor: 1, + profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' + }, + '2': { + line: 2, + tbname: 'jBL12pg63eX4N9P7zy0lJLyEJKmlbkGwZMx0avQV', + contactor: 1, + profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' + }, + '3': { + line: 3, + tbname: 'aAOzENGrvpbe0VoK7D6E1a819PZmdg3nl24JLQMk', + contactor: 1, + profile: '{"intervals":[{"value":1,"end_time":"13:00","start_time":"13:00"}],"astro_clock":false,"dawn_lux_sensor":false,"dusk_lux_sensor":false,"dawn_lux_sensor_value":5,"dusk_lux_sensor_value":5,"dawn_astro_clock_offset":0,"dusk_astro_clock_offset":0,"dawn_lux_sensor_time_window":30,"dusk_lux_sensor_time_window":30,"dawn_astro_clock_time_window":60,"dusk_astro_clock_time_window":60}' } +} - function isObject(item) { - return (typeof item === "object" && !Array.isArray(item) && item !== null); + +const rpcSwitchOffLine = +{ + "topic": "v1/gateway/rpc", + "content": { + "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", + "data": { + "id": 8, + "method": "set_command", + "params": { + "entities": [ + { + "entity_type": "edb_line", + "tb_name": "MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O" + } + ], + "command": "switch", + "payload": { + "value": false + } + } + } } +} -} // end of instance.export +const rpcSetNodeDimming = +{ + "topic": "v1/gateway/rpc", + "content": { + "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", + "data": { + "id": 10, + "method": "set_command", + "params": { + "entities": [ + { + "entity_type": "street_luminaire", + "tb_name": "jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV" + } + ], + "command": "dimming", + "payload": { + "value": 5 + } + } + } + } +} +const rpcLineProfile = +{ + "topic": "v1/gateway/rpc", + "content": { + "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", + "data": { + "id": 9, + "method": "set_profile", + "params": { + "entities": [ + { + "entity_type": "edb_line", + "tb_name": "MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O" + } + ], + "payload": { + "intervals": [ + { + "value": 0, + "end_time": "20:00", + "start_time": "13:00" + }, + { + "value": 1, + "end_time": "05:30", + "start_time": "20:00" + }, + { + "value": 0, + "end_time": "13:00", + "start_time": "05:30" + } + ], + "astro_clock": true, + "dawn_lux_sensor": false, + "dusk_lux_sensor": false, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 0, + "dusk_astro_clock_offset": 0, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + } + } + } + } +} + + +const rpcNodeProfile = +{ + "topic": "v1/gateway/rpc", + "content": { + "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", + "data": { + "id": 11, + "method": "set_profile", + "params": { + "entities": [ + { + "entity_type": "street_luminaire", + "tb_name": "jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV" + } + ], + "payload": { + "intervals": [ + { + "cct": 3000, + "value": 0, + "end_time": "17:50", + "start_time": "13:00" + }, + { + "cct": 3000, + "value": 100, + "end_time": "21:30", + "start_time": "17:50" + }, + { + "cct": 3000, + "value": 0, + "end_time": "13:00", + "start_time": "07:10" + }, + { + "cct": 3000, + "value": 50, + "end_time": "00:00", + "start_time": "21:30" + }, + { + "cct": 3000, + "value": 10, + "end_time": "04:30", + "start_time": "00:00" + }, + { + "cct": 3000, + "value": 100, + "end_time": "07:10", + "start_time": "04:30" + } + ], + "astro_clock": true, + "dawn_lux_sensor": false, + "dusk_lux_sensor": false, + "dawn_lux_sensor_value": 5, + "dusk_lux_sensor_value": 5, + "dawn_astro_clock_offset": 30, + "dusk_astro_clock_offset": 20, + "dawn_lux_sensor_time_window": 30, + "dusk_lux_sensor_time_window": 30, + "dawn_astro_clock_time_window": 60, + "dusk_astro_clock_time_window": 60 + } + } + } + } +} + + const sunCalcExample = { + dusk_no_offset: '20:18', + dawn_no_offset: '05:19', + dusk: '20:18', + dusk_hours: 20, + dusk_minutes: 18, + dawn: '05:19', + dawn_hours: 5, + dawn_minutes: 19, + dusk_time: 1715278688962, + dawn_time: 1715224744357, + dusk_astro_clock_offset: 0, + dawn_astro_clock_offset: 0 +} diff --git a/flow/csv_import.js b/flow/csv_import.js new file mode 100644 index 0000000..5ae1e68 --- /dev/null +++ b/flow/csv_import.js @@ -0,0 +1,175 @@ +exports.id = 'csv_import'; +exports.title = 'CsvImport'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.input = 1; +exports.output = ["red", "white"]; +exports.click = false; +exports.author = 'Daniel Segeš'; +exports.icon = 'file-import'; +exports.options = { edge: "undefined" }; + +exports.html = `
+
+
+
CSV Import
+
+
+
`; + +exports.readme = `# load csv to table db`; + +//config +let delimiter = ";"; +let uniqueColumn = "node"; +let path = "flow/audit_test_panel.csv"; +let startFrom = 1; +let table = "nodes"; +let mapImport = { + 2: "node", + 4: "tbname", + 3: "line" +}; + +//10.0.0.62 +delimiter = ";"; +uniqueColumn = "node"; +path = "flow/audit_rvo14_lampy.csv"; +startFrom = 1; +table = "nodes"; +mapImport = { + 1: "node", + 3: "tbname", + 2: "line" +}; + +//notification +delimiter = ";"; +uniqueColumn = undefined; +path = "flow/notifikacie.csv"; +startFrom = 1; +table = "notifications"; +mapImport = { + 0: "key", + 1: "weight", + 2: "en", + 3: "sk" +}; + +const fs = require('fs'); + +exports.install = function(instance) { + + //console.log("csv import installed"); + + instance.on("close", () => { + + }) + + + instance.on("data", (flowdata) => { + + instance.send(0, "start import"); + console.log("csv import", flowdata.data); + + //{table: "nodes", startFrom: 1, delimiter: ";", uniqueColumn: "node", path: "flow/audit_rvo14_lampy.csv", mapImport: {1: "node", 3: "tbname", 2: "line"}} + + + if(typeof flowdata.data === 'object') + { + console.log("*******************", flowdata.data); + + if(!flowdata.data.hasOwnProperty("table")) + { + instance.send(0, "!!!!csv import - nedefinovana tabulka"); + return; + } + + if(!flowdata.data.hasOwnProperty("uniqueColumn")) + { + //instance.send(0, "!!!!csv import - nedefinovane uniqueColumn"); + //return; + } + + if(!flowdata.data.hasOwnProperty("path")) + { + instance.send(0, "!!!!csv import - nedefinovana cesta k suboru"); + return; + } + + if(!flowdata.data.hasOwnProperty("mapImport")) + { + instance.send(0, "!!!!csv import - nedefinovany mapImport"); + return; + } + + table = flowdata.data.table; + uniqueColumn = flowdata.data.uniqueColumn; + if(uniqueColumn === "") uniqueColumn = undefined; + + path = flowdata.data.path; + mapImport = flowdata.data.mapImport; + + if(flowdata.data.hasOwnProperty("delimiter")) delimiter = flowdata.data.delimiter; + if(flowdata.data.hasOwnProperty("startFrom")) startFrom = flowdata.data.startFrom; + } + + + var db = TABLE(table); + db.clear(); + + let keys = Object.keys(mapImport); + + try { + const data = fs.readFileSync(path, 'utf8') + + let lines = data.split("\n"); + + for(let i = startFrom; i < lines.length; i++) + { + let line = lines[i]; + if(line === "") continue; + + let data = line.split(delimiter); + if(data.length == 0) continue; + + let insertData = {}; + + keys.map(function(key){ + let k = mapImport[key]; + + //console.log("importineg", i, key, k); + + if(data[key] != undefined) insertData[k] = data[key].trim(); + else{ + console.log("undefined", key, data); + } + }); + + console.log("insertData", insertData); + + if(uniqueColumn != undefined) + { + db.insert(insertData, true).where(uniqueColumn, insertData[uniqueColumn]); + } + else + { + db.insert(insertData); + } + + + } + + console.log("csv import finished"); + instance.send(0, "csv import finished"); + + } catch (err) { + console.error(err) + instance.send(0, err); + } + }) + +} + + diff --git a/flow/db_init.js b/flow/db_init.js deleted file mode 100644 index e44e7b8..0000000 --- a/flow/db_init.js +++ /dev/null @@ -1,107 +0,0 @@ -exports.id = 'db_init'; -exports.title = 'DB Initialization'; -exports.group = 'Worksys'; -exports.color = '#888600'; -exports.version = '1.0.2'; -exports.icon = 'sign-out'; -exports.input = 1; -exports.output = ["blue"]; - -exports.html = `
-
-
-
Hostname or IP address (if not empty - setting will override db setting)
-
-
-
Port
-
-
-
-
-
@(Client id)
-
-
-
@(Username)
-
-
-
`; - - -exports.readme = ` -# DB initialization -`; - -const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); -const { initNotification } = require('./helper/notification_reporter'); - - -exports.install = async function(instance) { - - const dbNodes = TABLE("nodes"); - const dbRelays = TABLE("relays"); - const dbSettings = TABLE("settings"); - const dbStatus = TABLE("status"); - const dbPins = TABLE("pins"); - const dbNotifications = TABLE("notifications"); - - FLOW.GLOBALS = {}; - const dbs = FLOW.GLOBALS; - - const responseSettings = await promisifyBuilder(dbSettings.find()); - const responseNodes = await promisifyBuilder(dbNodes.find()); - const responsePins = await promisifyBuilder(dbPins.find()); - const responseStatus = await promisifyBuilder(dbStatus.find()); - const responseRelays = await promisifyBuilder(dbRelays.find()); - const response = await promisifyBuilder(dbNotifications.find()); - - dbs.pinsData = makeMapFromDbResult(responsePins, "pin"); - dbs.relaysData = makeMapFromDbResult(responseRelays, "line"); - dbs.nodesData = makeMapFromDbResult(responseNodes, "node"); - dbs.statusData = responseStatus[0]; - dbs.notificationsData = makeMapFromDbResult(response, "key"); - - //+|354|nodesdata.....+|482|nodesdata.... - //for some reason, if last line in nodes.table is not empty, flow wrote more nodes data in one row, - //so we have to add empty line at the bottom of nodes table to avoid this. - //now, remove empty lines from nodesData database: - if(dbs.nodesData.hasOwnProperty("0")) delete dbs.nodesData["0"]; - - dbs.settings = { - edge_fw_version : "2024-10-14", //rok-mesiac-den - language : responseSettings[0]["lang"], - rvo_name : responseSettings[0]["rvo_name"], - project_id : responseSettings[0]["project_id"], - rvoTbName : dbs.relaysData[0]["tbname"], - temperature_address : responseSettings[0]["temperature_address"], - controller_type : responseSettings[0]["controller_type"], - serial_port : responseSettings[0]["serial_port"], - node_status_nok_time : responseSettings[0]["node_status_nok_time"] * 60 * 60 * 1000 ,// hour * minutes * - latitude : responseSettings[0]["latitude"], - longitude : responseSettings[0]["longitude"], - no_voltage : new Set(),//modbus_citysys - elektromer - backup_on_failure : responseSettings[0]["backup_on_failure"], - restore_from_backup : responseSettings[0]["restore_from_backup"], - restore_backup_wait : responseSettings[0]["restore_backup_wait"], - mqtt_host : responseSettings[0]["mqtt_host"], - mqtt_clientid : responseSettings[0]["mqtt_clientid"], - mqtt_username : responseSettings[0]["mqtt_username"], - mqtt_port : responseSettings[0]["mqtt_port"], - - //dynamic values - masterNodeIsResponding : true, //cmd_manager - maintenance_mode : false, - } - - FLOW.dbLoaded = true; - initNotification(); - - setTimeout(()=> { - console.log("DB_INIT - data loaded"); - instance.send(0, "_") - }, 5000) - -}; - - - - diff --git a/flow/designer.json b/flow/designer.json index d0a868d..7d57d69 100644 --- a/flow/designer.json +++ b/flow/designer.json @@ -20,94 +20,13 @@ } ], "components": [ - { - "id": "1611938185451", - "component": "modbus_citysys", - "tab": "1611921777196", - "name": "Modbus_citysys", - "x": 118.5, - "y": 111.5, - "connections": { - "0": [ - { - "index": "0", - "id": "1611951142547" - } - ], - "1": [ - { - "index": "0", - "id": "1730283489001" - } - ], - "2": [ - { - "index": "0", - "id": "1612772119611" - }, - { - "index": "0", - "id": "1730283489001" - } - ], - "3": [ - { - "index": "0", - "id": "1611938192035" - }, - { - "index": "0", - "id": "1730283344075" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "Running", - "color": "green" - }, - "options": { - "edge": "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV" - }, - "color": "#2134B0", - "notes": "" - }, - { - "id": "1611938192035", - "component": "debug", - "tab": "1611921777196", - "name": "to dido", - "x": 804.5, - "y": 290.5, - "connections": {}, - "disabledio": { - "input": [ - 0 - ], - "output": [] - }, - "state": { - "text": "Enabled", - "color": "gray" - }, - "options": { - "type": "data", - "repository": false, - "enabled": true - }, - "color": "#967ADC", - "notes": "" - }, { "id": "1611951142547", "component": "debug", "tab": "1611921777196", "name": "ERROR", - "x": 700, - "y": 26, + "x": 401, + "y": 31, "connections": {}, "disabledio": { "input": [], @@ -125,37 +44,13 @@ "color": "#DA4453", "notes": "" }, - { - "id": "1612772119611", - "component": "virtualwireout", - "tab": "1611921777196", - "name": "tb-push", - "x": 718.75, - "y": 213.5, - "connections": {}, - "disabledio": { - "input": [ - 0 - ], - "output": [] - }, - "state": { - "text": "tb-push", - "color": "gray" - }, - "options": { - "wirename": "tb-push" - }, - "color": "#303E4D", - "notes": "" - }, { "id": "1612776786008", "component": "wsmqttpublish", "tab": "1612772287426", "name": "WS MQTT publish", - "x": 338.75, - "y": 185, + "x": 311.75, + "y": 248, "connections": { "0": [ { @@ -185,9 +80,7 @@ ] }, "disabledio": { - "input": [ - 1 - ], + "input": [], "output": [] }, "state": { @@ -195,8 +88,8 @@ "color": "green" }, "options": { - "username": "xmRd6RJxW53WZe4vMFLU", - "clientid": "showroom_test_panel_led", + "username": "", + "clientid": "", "port": "1883", "host": "" }, @@ -208,12 +101,12 @@ "component": "virtualwirein", "tab": "1612772287426", "name": "tb-push", - "x": 67.75, - "y": 273, + "x": 68.75, + "y": 269, "connections": { "0": [ { - "index": "1", + "index": "0", "id": "1612776786008" }, { @@ -241,8 +134,8 @@ "component": "debug", "tab": "1612772287426", "name": "to TB", - "x": 341.75, - "y": 324, + "x": 317.75, + "y": 154, "connections": {}, "disabledio": { "input": [ @@ -267,8 +160,8 @@ "component": "debug", "tab": "1612772287426", "name": "errors from MQTT Broker", - "x": 648, - "y": 151, + "x": 610, + "y": 111, "connections": {}, "disabledio": { "input": [ @@ -293,8 +186,8 @@ "component": "debug", "tab": "1615551125555", "name": "Debug", - "x": 788, - "y": 78, + "x": 755, + "y": 19, "connections": {}, "disabledio": { "input": [ @@ -319,8 +212,8 @@ "component": "virtualwireout", "tab": "1615551125555", "name": "tb-push", - "x": 784, - "y": 170, + "x": 753, + "y": 112, "connections": {}, "disabledio": { "input": [], @@ -340,9 +233,9 @@ "id": "1615798582262", "component": "debug", "tab": "1615551125555", - "name": "data to TB", - "x": 784, - "y": 259, + "name": "CMD_debug", + "x": 750, + "y": 197, "connections": {}, "disabledio": { "input": [ @@ -366,22 +259,24 @@ "id": "1615802995322", "component": "debug", "tab": "1611921777196", - "name": "thermoDido", - "x": 738.8833312988281, - "y": 717.3500061035156, + "name": "Debug", + "x": 398.8833312988281, + "y": 528.3500061035156, "connections": {}, "disabledio": { - "input": [], + "input": [ + 0 + ], "output": [] }, "state": { - "text": "Enabled", + "text": "Disabled", "color": "gray" }, "options": { "type": "data", "repository": false, - "enabled": true + "enabled": false }, "color": "#967ADC", "notes": "" @@ -390,12 +285,14 @@ "id": "1615809128443", "component": "debug", "tab": "1611921777196", - "name": "thermoTb", - "x": 595.8833312988281, - "y": 497.3500061035156, + "name": "Debug", + "x": 401.8833312988281, + "y": 625.3500061035156, "connections": {}, "disabledio": { - "input": [], + "input": [ + 0 + ], "output": [] }, "state": { @@ -415,8 +312,8 @@ "component": "virtualwireout", "tab": "1611921777196", "name": "tb-push", - "x": 749.8833312988281, - "y": 610.25, + "x": 400.8833312988281, + "y": 328.25, "connections": {}, "disabledio": { "input": [], @@ -437,13 +334,17 @@ "component": "httproute", "tab": "1615551125555", "name": "POST /terminal", - "x": 71, - "y": 444, + "x": 72, + "y": 350, "connections": { "0": [ { - "index": "1", + "index": "0", "id": "1619515097737" + }, + { + "index": "0", + "id": "1684060205000" } ] }, @@ -479,8 +380,8 @@ "component": "httpresponse", "tab": "1615551125555", "name": "HTTP Response", - "x": 782, - "y": 342, + "x": 751, + "y": 273, "connections": {}, "disabledio": { "input": [], @@ -497,16 +398,197 @@ "notes": "" }, { - "id": "1617284749681", + "id": "1617104731852", + "component": "debug", + "tab": "1615551125555", + "name": "DIDO_Debug", + "x": 739, + "y": 635, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1617114651703", "component": "trigger", "tab": "1615551125555", - "name": "update profile / node", - "x": 95, - "y": 107, + "name": "turnOff line", + "x": 71, + "y": 829, "connections": { "0": [ { "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "data": "{line: 3, command: \"turnOff\", force: true}", + "datatype": "object" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617115013095", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "tb-push", + "x": 741, + "y": 736, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1617178324650", + "component": "debug", + "tab": "1615551125555", + "name": "Debug", + "x": 605, + "y": 1024, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1617179044099", + "component": "trigger", + "tab": "1615551125555", + "name": "start import", + "x": 235, + "y": 1032, + "connections": { + "0": [ + { + "index": "0", + "id": "1617180390661" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{table: \"konsberg_production_line_operations_error\", startFrom: 1, delimiter: \";\", uniqueColumn: \"\", path: \"flow/operations_error.csv\", mapImport: {0: \"production_line\",\t1: \"operation\", 2: \"error_type\", 3: \"error_code\", 4: \"error_text\", 5: \"error_text_user_defined\"}}" + }, + "color": "#F6BB42", + "notes": "" + }, + { + "id": "1617180390661", + "component": "csv_import", + "tab": "1615551125555", + "name": "CsvImport", + "x": 414, + "y": 1013, + "connections": { + "0": [ + { + "index": "0", + "id": "1617178324650" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "edge": "undefined" + }, + "color": "#2134B0", + "notes": "" + }, + { + "id": "1617197763128", + "component": "comment", + "tab": "1615551125555", + "name": "import data from csv", + "x": 401, + "y": 946, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": {}, + "color": "#704cff", + "notes": "" + }, + { + "id": "1617284749681", + "component": "trigger", + "tab": "1615551125555", + "name": "update profile / node", + "x": 80, + "y": 13, + "connections": { + "0": [ + { + "index": "0", "id": "1619515097737" } ] @@ -531,12 +613,12 @@ "component": "trigger", "tab": "1615551125555", "name": "tun tasks", - "x": 82, - "y": 183, + "x": 77, + "y": 84, "connections": { "0": [ { - "index": "1", + "index": "0", "id": "1619515097737" } ] @@ -560,8 +642,8 @@ "component": "debug", "tab": "1612772287426", "name": "wsmqtt-exit1", - "x": 670.8833312988281, - "y": 242, + "x": 610.8833312988281, + "y": 199, "connections": {}, "disabledio": { "input": [], @@ -584,8 +666,8 @@ "component": "debug", "tab": "1612772287426", "name": "wsmqtt-exit2", - "x": 685.8833312988281, - "y": 434, + "x": 611.8833312988281, + "y": 374, "connections": {}, "disabledio": { "input": [ @@ -605,22 +687,40 @@ "color": "#967ADC", "notes": "" }, + { + "id": "1618393583970", + "component": "virtualwireout", + "tab": "1615551125555", + "name": "to-cmd-manager", + "x": 740.8833312988281, + "y": 828, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "from-dido-controller", + "color": "gray" + }, + "options": { + "wirename": "from-dido-controller" + }, + "color": "#303E4D", + "notes": "" + }, { "id": "1618393674428", "component": "virtualwirein", "tab": "1615551125555", "name": "platform-rpc-call", - "x": 76.88333129882812, - "y": 270, + "x": 77.88333129882812, + "y": 173, "connections": { "0": [ - { - "index": "1", - "id": "1619515097737" - }, { "index": "0", - "id": "1729630658131" + "id": "1619515097737" } ] }, @@ -638,24 +738,57 @@ "color": "#303E4D", "notes": "" }, + { + "id": "1618393759854", + "component": "virtualwirein", + "tab": "1615551125555", + "name": "cmd_to_dido", + "x": 76.88333129882812, + "y": 678, + "connections": { + "0": [ + { + "index": "0", + "id": "1683664161036" + }, + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "cmd_to_dido", + "color": "gray" + }, + "options": { + "wirename": "cmd_to_dido" + }, + "color": "#303E4D", + "notes": "" + }, { "id": "1618393827655", "component": "virtualwireout", "tab": "1615551125555", - "name": "cmd-to-dido", - "x": 780.8833312988281, - "y": 446, + "name": "cmd_to_dido", + "x": 748.8833312988281, + "y": 373, "connections": {}, "disabledio": { "input": [], "output": [] }, "state": { - "text": "cmd-to-dido", + "text": "cmd_to_dido", "color": "gray" }, "options": { - "wirename": "cmd-to-dido" + "wirename": "cmd_to_dido" }, "color": "#303E4D", "notes": "" @@ -665,8 +798,8 @@ "component": "virtualwireout", "tab": "1612772287426", "name": "platform-rpc-call", - "x": 674.8833312988281, - "y": 338, + "x": 611.8833312988281, + "y": 287, "connections": {}, "disabledio": { "input": [], @@ -682,13 +815,43 @@ "color": "#303E4D", "notes": "" }, + { + "id": "1618572059773", + "component": "trigger", + "tab": "1615551125555", + "name": "turnOn line", + "x": 72, + "y": 756, + "connections": { + "0": [ + { + "index": "1", + "id": "1699963668903" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{line: 1, command: \"turnOn\", force: true}" + }, + "color": "#F6BB42", + "notes": "" + }, { "id": "1619515097737", "component": "cmd_manager", "tab": "1615551125555", "name": "CMD Manager", - "x": 435, - "y": 126, + "x": 420, + "y": 156, "connections": { "0": [ { @@ -742,13 +905,17 @@ "component": "httproute", "tab": "1615551125555", "name": "GET db", - "x": 65, - "y": 549, + "x": 73, + "y": 455, "connections": { "0": [ { - "index": "1", + "index": "0", "id": "1619515097737" + }, + { + "index": "0", + "id": "1684060205000" } ] }, @@ -783,13 +950,13 @@ "component": "trigger", "tab": "1615551125555", "name": "turnOnAlarm", - "x": 53, - "y": 842, + "x": 68, + "y": 902, "connections": { "0": [ { "index": "1", - "id": "1730323243484" + "id": "1699963668903" } ] }, @@ -813,13 +980,13 @@ "component": "trigger", "tab": "1615551125555", "name": "turnOffAlarm", - "x": 50, - "y": 928, + "x": 67, + "y": 975, "connections": { "0": [ { "index": "1", - "id": "1730323243484" + "id": "1699963668903" } ] }, @@ -842,20 +1009,20 @@ "id": "1621340721628", "component": "virtualwireout", "tab": "1611921777196", - "name": "modbus-to-dido", - "x": 921, - "y": 404, + "name": "modbus_to_dido", + "x": 399, + "y": 433, "connections": {}, "disabledio": { "input": [], "output": [] }, "state": { - "text": "modbus-to-dido", + "text": "modbus_to_dido", "color": "gray" }, "options": { - "wirename": "modbus-to-dido" + "wirename": "modbus_to_dido" }, "color": "#303E4D", "notes": "" @@ -865,8 +1032,8 @@ "component": "httproute", "tab": "1615551125555", "name": "POST /db_connector", - "x": 20, - "y": 1443, + "x": 1107, + "y": 338, "connections": { "0": [ { @@ -905,8 +1072,8 @@ "component": "db_connector", "tab": "1615551125555", "name": "DbConnector", - "x": 276, - "y": 1500, + "x": 1363, + "y": 395, "connections": { "1": [ { @@ -934,8 +1101,8 @@ "component": "httpresponse", "tab": "1615551125555", "name": "HTTP Response", - "x": 501, - "y": 1559, + "x": 1588, + "y": 454, "connections": {}, "disabledio": { "input": [], @@ -954,8 +1121,8 @@ "component": "monitormemory", "tab": "1612772287426", "name": "RAM", - "x": 112.88333129882812, - "y": 797.5, + "x": 71.88333129882812, + "y": 609.5, "connections": { "0": [ { @@ -969,12 +1136,12 @@ "output": [] }, "state": { - "text": "192.45 MB / 249 MB", + "text": "834.19 MB / 985.68 MB", "color": "gray" }, "options": { "enabled": true, - "interval": 20000 + "interval": 30000 }, "color": "#F6BB42", "notes": "" @@ -984,8 +1151,8 @@ "component": "monitordisk", "tab": "1612772287426", "name": "disk", - "x": 114.88333129882812, - "y": 895.5, + "x": 72.88333129882812, + "y": 706.5, "connections": { "0": [ { @@ -999,13 +1166,13 @@ "output": [] }, "state": { - "text": "5.92 GB / 7.22 GB", + "text": "5.84 GB / 7.26 GB", "color": "gray" }, "options": { "enabled": true, "path": "/", - "interval": 20000 + "interval": 30000 }, "color": "#F6BB42", "notes": "" @@ -1015,8 +1182,8 @@ "component": "virtualwirein", "tab": "1612772287426", "name": "send-to-services", - "x": -11.116668701171875, - "y": 1207.5, + "x": 5.883331298828125, + "y": 1069.5, "connections": { "0": [ { @@ -1024,7 +1191,7 @@ "id": "1634463186563" }, { - "index": "1", + "index": "0", "id": "1634488120710" } ] @@ -1048,8 +1215,8 @@ "component": "virtualwireout", "tab": "1612772287426", "name": "send-to-services", - "x": 507.8833312988281, - "y": 815.5, + "x": 428.8833312988281, + "y": 602.5, "connections": {}, "disabledio": { "input": [], @@ -1070,8 +1237,8 @@ "component": "virtualwireout", "tab": "1612772287426", "name": "send-to-services", - "x": 686.8833312988281, - "y": 530.5, + "x": 612.8833312988281, + "y": 462.5, "connections": {}, "disabledio": { "input": [], @@ -1092,8 +1259,9 @@ "component": "httprequest", "tab": "1612772287426", "name": "http://192.168.252.2:8004/sentmessage", - "x": 508.8833312988281, - "y": 1134.7333374023438, + "reference": "", + "x": 439.8833312988281, + "y": 1076.7333374023438, "connections": { "0": [ { @@ -1123,8 +1291,8 @@ "component": "debug", "tab": "1612772287426", "name": "Debug", - "x": 242.75, - "y": 1248, + "x": 234.75, + "y": 1024, "connections": {}, "disabledio": { "input": [ @@ -1149,8 +1317,8 @@ "component": "code", "tab": "1612772287426", "name": "Code", - "x": 299, - "y": 730, + "x": 255, + "y": 512, "connections": { "0": [ { @@ -1184,8 +1352,8 @@ "component": "debug", "tab": "1612772287426", "name": "Debug", - "x": 481, - "y": 726, + "x": 430, + "y": 508, "connections": {}, "disabledio": { "input": [ @@ -1210,8 +1378,8 @@ "component": "code", "tab": "1612772287426", "name": "Code", - "x": 305, - "y": 817, + "x": 244, + "y": 608, "connections": { "0": [ { @@ -1245,8 +1413,8 @@ "component": "debug", "tab": "1612772287426", "name": "Debug", - "x": 482, - "y": 906, + "x": 431, + "y": 700, "connections": {}, "disabledio": { "input": [ @@ -1271,8 +1439,8 @@ "component": "code", "tab": "1612772287426", "name": "Code", - "x": 301, - "y": 910, + "x": 247, + "y": 702, "connections": { "0": [ { @@ -1306,8 +1474,8 @@ "component": "debug", "tab": "1612772287426", "name": "Debug", - "x": 482, - "y": 1003, + "x": 434, + "y": 792, "connections": {}, "disabledio": { "input": [ @@ -1332,8 +1500,8 @@ "component": "debug", "tab": "1612772287426", "name": "Send info", - "x": 509, - "y": 1245, + "x": 438, + "y": 1185, "connections": {}, "disabledio": { "input": [ @@ -1359,7 +1527,7 @@ "tab": "1612772287426", "name": "Info sender", "x": 233, - "y": 1148, + "y": 1122, "connections": { "0": [ { @@ -1391,8 +1559,8 @@ "component": "debug", "tab": "1612772287426", "name": "Debug", - "x": 1038.8833312988281, - "y": 1090.5, + "x": 811.8833312988281, + "y": 1070.5, "connections": {}, "disabledio": { "input": [ @@ -1417,8 +1585,8 @@ "component": "virtualwireout", "tab": "1615551125555", "name": "send-to-services", - "x": 781, - "y": 550, + "x": 748, + "y": 464, "connections": {}, "disabledio": { "input": [], @@ -1439,8 +1607,8 @@ "component": "monitorconsumption", "tab": "1612772287426", "name": "CPU", - "x": 109, - "y": 713, + "x": 71, + "y": 515, "connections": { "0": [ { @@ -1454,7 +1622,7 @@ "output": [] }, "state": { - "text": "40.6% / 47.36 MB", + "text": "1.9% / 86.94 MB", "color": "gray" }, "options": { @@ -1463,438 +1631,53 @@ "monitorsize": true, "monitorconsumption": true, "enabled": true, - "interval": 5000 + "interval": 30000 }, "color": "#967ADC", "notes": "" }, { - "id": "1725218490415", - "component": "trigger", - "tab": "1612772287426", - "name": "Trigger - dimming 650", - "x": 282.8833312988281, - "y": 422, - "connections": { - "0": [ - { - "index": "0", - "id": "1618558465485" - } - ] - }, + "id": "1683664161036", + "component": "debug", + "tab": "1615551125555", + "name": "CMDtoDIDO", + "x": 413, + "y": 654, + "connections": {}, "disabledio": { - "input": [], + "input": [ + 0 + ], "output": [] }, "state": { - "text": "", + "text": "Enabled", "color": "gray" }, "options": { - "datatype": "object", - "data": "{ \"topic\": \"v1/gateway/rpc\", \"content\": { \"device\": \"KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV\", \"data\": { \"id\": 5, \"method\": \"set_command\", \"params\": { \"entities\": [ { \"entity_type\": \"street_luminaire\", \"tb_name\": \"0XYElWeKBNJn1gdoMG8lYdDALkPvj4V3xra2q6mO\" } ], \"command\": \"dimming\", \"payload\": { \"value\": 5 } } } } }" + "type": "data", + "repository": false, + "enabled": true }, - "color": "#F6BB42", + "color": "#967ADC", "notes": "" }, { - "id": "1725287725896", - "component": "trigger", - "tab": "1612772287426", - "name": "Trigger - nodeProfile 650", - "x": 283.8833312988281, - "y": 498, - "connections": { - "0": [ - { - "index": "0", - "id": "1618558465485" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": { - "data": "{ \"topic\": \"v1/gateway/rpc\", \"content\": { \"device\": \"0XYElWeKBNJn1gdoMG8lYdDALkPvj4V3xra2q6mO\", \"data\": { \"id\": 11, \"method\": \"set_profile\", \"params\": { \"entities\": [ { \"entity_type\": \"street_luminaire\", \"tb_name\": \"0XYElWeKBNJn1gdoMG8lYdDALkPvj4V3xra2q6mO\" } ], \"payload\": { \"intervals\": [ { \"cct\": 3000, \"value\": 0, \"end_time\": \"16:45\",\"start_time\": \"13:00\" }, { \"cct\": 3000, \"value\": 7, \"end_time\": \"17:00\", \"start_time\": \"16:45\"}, { \"cct\": 3000, \"value\": 30, \"end_time\": \"17:15\", \"start_time\": \"17:00\" }, { \"cct\": 3000, \"value\":5, \"end_time\": \"17:30\", \"start_time\": \"17:15\" }, { \"cct\": 3000, \"value\": 0, \"end_time\": \"13:00\", \"start_time\": \"17:30\" }, ], \"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\": 30, \"dusk_astro_clock_offset\": 20, \"dawn_lux_sensor_time_window\": 30, \"dusk_lux_sensor_time_window\": 30, \"dawn_astro_clock_time_window\": 60, \"dusk_astro_clock_time_window\": 60 } } } } }", - "datatype": "object" - }, - "color": "#F6BB42", - "notes": "" - }, - { - "id": "1725463389430", - "component": "trigger", - "tab": "1612772287426", - "name": "Trigger - dimming 659", - "x": 289.8833312988281, - "y": 599, - "connections": { - "0": [ - { - "index": "0", - "id": "1618558465485" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": { - "data": "{ \"topic\": \"v1/gateway/rpc\", \"content\": { \"device\": \"KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV\", \"data\": { \"id\": 5, \"method\": \"set_command\", \"params\": { \"entities\": [ { \"entity_type\": \"street_luminaire\", \"tb_name\": \"joqRYBVL30k9eQWOlZ5qwpD2KJpNEmA6gPxXzwaM\" } ], \"command\": \"dimming\", \"payload\": { \"value\": 7 } } } } }", - "datatype": "object" - }, - "color": "#F6BB42", - "notes": "" - }, - { - "id": "1728565522830", + "id": "1683981346282", "component": "virtualwirein", "tab": "1615551125555", - "name": "db-init", - "x": 100.88333129882812, - "y": 34, + "name": "from-dido-controller", + "x": 71, + "y": 260, "connections": { "0": [ { "index": "0", "id": "1619515097737" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "db-init", - "color": "gray" - }, - "options": { - "wirename": "db-init" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1728981631674", - "component": "virtualwirein", - "tab": "1612772287426", - "name": "db-init", - "x": 65.88333129882812, - "y": 170.8000030517578, - "connections": { - "0": [ - { - "index": "0", - "id": "1612776786008" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "db-init", - "color": "gray" - }, - "options": { - "wirename": "db-init" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1728981755263", - "component": "virtualwirein", - "tab": "1611921777196", - "name": "db-init", - "x": 87.88333129882812, - "y": 631.3999938964844, - "connections": { - "0": [ - { - "index": "0", - "id": "1732823597895" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "db-init", - "color": "gray" - }, - "options": { - "wirename": "db-init" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1729356985353", - "component": "trigger", - "tab": "1612772287426", - "name": "show settings", - "x": 99.88333129882812, - "y": 1531.2000122070312, - "connections": { - "0": [ - { - "index": "0", - "id": "1729357628696" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": {}, - "color": "#F6BB42", - "notes": "" - }, - { - "id": "1729357628696", - "component": "showdb", - "tab": "1612772287426", - "name": "Show db data", - "x": 364.8833312988281, - "y": 1614.2000122070312, - "connections": { - "0": [ - { - "index": "0", - "id": "1729357637821" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": {}, - "color": "#888600", - "notes": "" - }, - { - "id": "1729357637821", - "component": "debug", - "tab": "1612772287426", - "name": "GLOBALS dbdata", - "x": 606.8833312988281, - "y": 1628.2000122070312, - "connections": {}, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "Enabled", - "color": "gray" - }, - "options": { - "type": "data", - "repository": false, - "enabled": true - }, - "color": "#967ADC", - "notes": "" - }, - { - "id": "1729359849748", - "component": "trigger", - "tab": "1612772287426", - "name": "show relays", - "x": 98.88333129882812, - "y": 1593.2000122070312, - "connections": { - "0": [ - { - "index": "1", - "id": "1729357628696" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": {}, - "color": "#F6BB42", - "notes": "" - }, - { - "id": "1729359867511", - "component": "trigger", - "tab": "1612772287426", - "name": "show nodesData", - "x": 78.88333129882812, - "y": 1667.2000122070312, - "connections": { - "0": [ - { - "index": "2", - "id": "1729357628696" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": {}, - "color": "#F6BB42", - "notes": "" - }, - { - "id": "1729359879876", - "component": "trigger", - "tab": "1612772287426", - "name": "show pins", - "x": 83.88333129882812, - "y": 1741.2000122070312, - "connections": { - "0": [ - { - "index": "3", - "id": "1729357628696" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": {}, - "color": "#F6BB42", - "notes": "" - }, - { - "id": "1729630658131", - "component": "debug", - "tab": "1615551125555", - "name": "fromDIDO", - "x": 455, - "y": 312, - "connections": {}, - "disabledio": { - "input": [ - 0 - ], - "output": [] - }, - "state": { - "text": "Enabled", - "color": "gray" - }, - "options": { - "type": "data", - "repository": false, - "enabled": true - }, - "color": "#967ADC", - "notes": "" - }, - { - "id": "1729712837697", - "component": "db_init", - "tab": "1612772287426", - "name": "DB Initialization", - "x": 72, - "y": 47, - "connections": { - "0": [ - { - "index": "0", - "id": "1729712846867" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": {}, - "color": "#888600", - "notes": "" - }, - { - "id": "1729712846867", - "component": "virtualwireout", - "tab": "1612772287426", - "name": "db-init", - "x": 315.8833312988281, - "y": 44.5, - "connections": {}, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "db-init", - "color": "gray" - }, - "options": { - "wirename": "db-init" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1730283344075", - "component": "code", - "tab": "1611921777196", - "name": "Code", - "x": 380, - "y": 287, - "connections": { - "0": [ - { - "index": "0", - "id": "1730286332882" }, { "index": "0", - "id": "1621340721628" + "id": "1684055037116" } ] }, @@ -1903,24 +1686,22 @@ "output": [] }, "state": { - "text": "", + "text": "from-dido-controller", "color": "gray" }, "options": { - "keepmessage": true, - "code": "let b = value.tbdata;\n\nif(b == undefined) return;\nlet key = Object.keys(b)[0];\n\nlet toSend = b[key][0];\ndelete toSend.ts;\ndelete toSend.values.status;\n\nsend(0, toSend);\n\nlet a ={\n \"sender\": \"modbus_citysys\",\n \"tbdata\": {\n \"PLBJzmK1r3Gynd6OW0gGYz0e5wV4vx9bDEqNgYR8\": [\n {\n \"ts\": 1730326629980,\n \"values\": {\n \"status\": \"OK\",\n \"Phase_2_voltage\": 233.8,\n \"Phase_3_voltage\": 233,\n \"Phase_1_current\": 0.07,\n \"Phase_2_current\": 0.33,\n \"Phase_3_current\": 0,\n \"Phase_1_power\": 5.3,\n \"Phase_2_power\": 37.1,\n \"Phase_3_power\": 0,\n \"total_power\": 42.4,\n \"total_energy\": 5803.8,\n \"Phase_1_pow_factor\": 0.49,\n \"Phase_2_pow_factor\": 0.86,\n \"Phase_3_pow_factor\": 0,\n \"power_factor\": 0.8\n }\n }\n ]\n }\n}", - "outputs": 1 + "wirename": "from-dido-controller" }, - "color": "#656D78", + "color": "#303E4D", "notes": "" }, { - "id": "1730283489001", + "id": "1684055037116", "component": "debug", - "tab": "1611921777196", - "name": "modbus tb", - "x": 705.5, - "y": 113.5, + "tab": "1615551125555", + "name": "from dido to cmd", + "x": 423, + "y": 331, "connections": {}, "disabledio": { "input": [ @@ -1941,12 +1722,38 @@ "notes": "" }, { - "id": "1730286332882", + "id": "1684060205000", + "component": "debug", + "tab": "1615551125555", + "name": "HTTP routes", + "x": 423, + "y": 422, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1684179110403", "component": "debug", "tab": "1611921777196", - "name": "modbusCode", - "x": 546, - "y": 383, + "name": "MDBToDido", + "x": 401, + "y": 118, "connections": {}, "disabledio": { "input": [], @@ -1965,33 +1772,33 @@ "notes": "" }, { - "id": "1730323243484", + "id": "1699963668903", "component": "dido_controller", "tab": "1615551125555", "name": "DIDO_Controller", - "x": 403, - "y": 959, + "x": 402, + "y": 736, "connections": { "0": [ { "index": "0", - "id": "1730323814342" + "id": "1617104731852" } ], "1": [ { "index": "0", - "id": "1730323748655" + "id": "1617104731852" }, { "index": "0", - "id": "1730323814342" + "id": "1617115013095" } ], "2": [ { "index": "0", - "id": "1730323748661" + "id": "1618393583970" } ] }, @@ -2010,50 +1817,21 @@ "notes": "" }, { - "id": "1730323407563", + "id": "1699964678894", "component": "virtualwirein", "tab": "1615551125555", - "name": "db-init", - "x": 56.883331298828125, - "y": 1260.2000122070312, - "connections": { - "0": [ - { - "index": "2", - "id": "1730323243484" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "db-init", - "color": "gray" - }, - "options": { - "wirename": "db-init" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1730323590937", - "component": "virtualwirein", - "tab": "1615551125555", - "name": "modbus-to-dido", - "x": 53.883331298828125, - "y": 760, + "name": "modbus_to_dido", + "x": 79, + "y": 595, "connections": { "0": [ { "index": "0", - "id": "1730323243484" + "id": "1699963668903" }, { "index": "0", - "id": "1730324345047" + "id": "1699964793925" } ] }, @@ -2062,208 +1840,22 @@ "output": [] }, "state": { - "text": "modbus-to-dido", + "text": "modbus_to_dido", "color": "gray" }, "options": { - "wirename": "modbus-to-dido" + "wirename": "modbus_to_dido" }, "color": "#303E4D", "notes": "" }, { - "id": "1730323631557", - "component": "virtualwirein", - "tab": "1615551125555", - "name": "cmd-to-dido", - "x": 47.883331298828125, - "y": 1013.2000122070312, - "connections": { - "0": [ - { - "index": "1", - "id": "1730323243484" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "cmd-to-dido", - "color": "gray" - }, - "options": { - "wirename": "cmd-to-dido" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1730323674816", - "component": "trigger", - "tab": "1615551125555", - "name": "turnOff line", - "x": 50, - "y": 1090, - "connections": { - "0": [ - { - "index": "1", - "id": "1730323243484" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": { - "datatype": "object", - "data": "{line:3, command: \"turnOff\", force: true}" - }, - "color": "#F6BB42", - "notes": "" - }, - { - "id": "1730323674822", - "component": "trigger", - "tab": "1615551125555", - "name": "turnOn line", - "x": 57, - "y": 1166, - "connections": { - "0": [ - { - "index": "1", - "id": "1730323243484" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "", - "color": "gray" - }, - "options": { - "data": "{line:1, command: \"turnOn\", force: true}", - "datatype": "object" - }, - "color": "#F6BB42", - "notes": "" - }, - { - "id": "1730323748655", - "component": "virtualwireout", - "tab": "1615551125555", - "name": "tb-push", - "x": 720, - "y": 1003, - "connections": {}, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "tb-push", - "color": "gray" - }, - "options": { - "wirename": "tb-push" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1730323748661", - "component": "virtualwireout", - "tab": "1615551125555", - "name": "to-cmd-manager", - "x": 722.8833312988281, - "y": 1090, - "connections": {}, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "from-dido-controller", - "color": "gray" - }, - "options": { - "wirename": "from-dido-controller" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1730323814342", + "id": "1699964793925", "component": "debug", "tab": "1615551125555", - "name": "DidoDebug", - "x": 709, - "y": 906, - "connections": {}, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "Enabled", - "color": "gray" - }, - "options": { - "type": "data", - "repository": false, - "enabled": true - }, - "color": "#967ADC", - "notes": "" - }, - { - "id": "1730324002079", - "component": "virtualwirein", - "tab": "1615551125555", - "name": "from-dido-controller", - "x": 73, - "y": 359, - "connections": { - "0": [ - { - "index": "1", - "id": "1619515097737" - } - ] - }, - "disabledio": { - "input": [], - "output": [] - }, - "state": { - "text": "from-dido-controller", - "color": "gray" - }, - "options": { - "wirename": "from-dido-controller" - }, - "color": "#303E4D", - "notes": "" - }, - { - "id": "1730324345047", - "component": "debug", - "tab": "1615551125555", - "name": "toDido", - "x": 405, - "y": 841, + "name": "modbusToDido", + "x": 411, + "y": 561, "connections": {}, "disabledio": { "input": [ @@ -2284,17 +1876,41 @@ "notes": "" }, { - "id": "1730327321896", - "component": "virtualwirein", - "tab": "1612772287426", - "name": "db-init", - "x": 4.883331298828125, - "y": 1111.8000030517578, + "id": "1699965957410", + "component": "modbus_reader", + "tab": "1611921777196", + "name": "Modbus reader", + "x": 102, + "y": 175, "connections": { "0": [ { "index": "0", - "id": "1634488120710" + "id": "1611951142547" + } + ], + "1": [ + { + "index": "0", + "id": "1621340721628" + }, + { + "index": "0", + "id": "1684179110403" + }, + { + "index": "0", + "id": "1717441414646" + } + ], + "2": [ + { + "index": "0", + "id": "1615809595184" + }, + { + "index": "0", + "id": "1714752862828" } ] }, @@ -2303,23 +1919,27 @@ "output": [] }, "state": { - "text": "db-init", + "text": "", "color": "gray" }, - "options": { - "wirename": "db-init" - }, - "color": "#303E4D", + "options": {}, + "color": "#2134B0", "notes": "" }, { - "id": "1732823597895", + "id": "1700411878636", "component": "thermometer", "tab": "1611921777196", "name": "Thermometer", - "x": 372.75, - "y": 602, + "x": 107.75, + "y": 449, "connections": { + "0": [ + { + "index": "0", + "id": "1615802995322" + } + ], "1": [ { "index": "0", @@ -2334,10 +1954,6 @@ { "index": "0", "id": "1621340721628" - }, - { - "index": "0", - "id": "1615802995322" } ] }, @@ -2352,6 +1968,264 @@ "options": {}, "color": "#5CB36D", "notes": "" + }, + { + "id": "1714752862828", + "component": "debug", + "tab": "1611921777196", + "name": "MDBToTb", + "x": 402, + "y": 228, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1717441414646", + "component": "code", + "tab": "1611921777196", + "name": "device-status", + "x": 588.0833282470703, + "y": 177, + "connections": { + "0": [ + { + "index": "0", + "id": "1717442627834" + }, + { + "index": "0", + "id": "1717442631338" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "keepmessage": true, + "code": "if(value.hasOwnProperty(\"status\"))\n{\n\tif(value.status.includes(\"-em\"))\n\t{\n\t\tsend(0, {\"em_status\": \"NOK\"});\n\t}\n\telse if(value.status.includes(\"twilight\"))\n\t{\n\t\tsend(0, {\"lux_sensor\": \"NOK\"});\n\t}\n}\n\nif(value.hasOwnProperty(\"values\"))\n{\n\tif(value.values.hasOwnProperty(\"twilight_sensor\"))\n\t{\n\t\tsend(0, {\"lux_sensor\": \"OK\"});\n\t}\n\telse if(value.values.hasOwnProperty(\"Phase_1_power\") ||\n\t\t\tvalue.values.hasOwnProperty(\"Phase_1_voltage\") ||\n\t\t\tvalue.values.hasOwnProperty(\"Total_power\") ||\n\t\t\tvalue.values.hasOwnProperty(\"Phase_1_current\"))\n\t{\n\t\tsend(0, {\"em_status\": \"OK\"});\n\t}\n}", + "outputs": 1 + }, + "color": "#656D78", + "notes": "" + }, + { + "id": "1717442627834", + "component": "debug", + "tab": "1611921777196", + "name": "modbus service", + "x": 802.0833282470703, + "y": 139, + "connections": {}, + "disabledio": { + "input": [ + 0 + ], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1717442631338", + "component": "virtualwireout", + "tab": "1611921777196", + "name": "send-to-services", + "x": 801.0833282470703, + "y": 236, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "send-to-services", + "color": "gray" + }, + "options": { + "wirename": "send-to-services" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1718016045116", + "component": "virtualwirein", + "tab": "1612772287426", + "name": "tb-push", + "x": 84.75, + "y": 1300, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "tb-push", + "color": "gray" + }, + "options": { + "wirename": "tb-push" + }, + "color": "#303E4D", + "notes": "" + }, + { + "id": "1718016052341", + "component": "slack_filter", + "tab": "1612772287426", + "name": "Slack Filter", + "x": 278, + "y": 1297, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + }, + { + "index": "0", + "id": "1718016073501" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Running", + "color": "gray" + }, + "options": { + "slack_channel": "C071KN2Q8SK", + "tag_on_include": "[{\"user_id\":\"U072JE5JUQG\", \"includes\":[\"Electrometer\", \"Twilight sensor\"]}]", + "message_includes": "[\"is responding again\", \"Lamps have turned\", \"Flow has been restarted\"]", + "types": "[\"emergency\", \"critical\", \"error\", \"alert\"]", + "name": "RVO16 Senica - 10.0.0.131" + }, + "color": "#30E193", + "notes": "" + }, + { + "id": "1718016073501", + "component": "httprequest", + "tab": "1612772287426", + "name": "http://192.168.252.2:8004/slack", + "x": 471, + "y": 1354, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016086212" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "stringify": "json", + "method": "POST", + "url": "http://192.168.252.2:8004/slack" + }, + "color": "#5D9CEC", + "notes": "" + }, + { + "id": "1718016086212", + "component": "debug", + "tab": "1612772287426", + "name": "Debug", + "x": 808, + "y": 1302, + "connections": {}, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "Enabled", + "color": "gray" + }, + "options": { + "type": "data", + "repository": false, + "enabled": true + }, + "color": "#967ADC", + "notes": "" + }, + { + "id": "1718016094070", + "component": "trigger", + "tab": "1612772287426", + "name": "Trigger", + "x": 73, + "y": 1388, + "connections": { + "0": [ + { + "index": "0", + "id": "1718016052341" + } + ] + }, + "disabledio": { + "input": [], + "output": [] + }, + "state": { + "text": "", + "color": "gray" + }, + "options": { + "datatype": "object", + "data": "{ \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\": [ { \"ts\": 1716289039281, \"values\": { \"_event\": { \"type\": \"alert\", \"status\": \"new\", \"source\": { \"func\": \"CMD Manager: process cmd\", \"component\": \"1619515097737\", \"component_name\": \"CMD Manager\", \"edge\": \"g9OxBZ5KRwNznlY6pAppqEAWXvjdEL4eGQobMDy2\" }, \"message\": \"NOW CONNECTED TO SLACK !\", \"message_data\": \"\" } } } ] }" + }, + "color": "#F6BB42", + "notes": "" } ], "version": 615 diff --git a/flow/di_do_controller.js b/flow/di_do_controller.js deleted file mode 100644 index d006a04..0000000 --- a/flow/di_do_controller.js +++ /dev/null @@ -1,1654 +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 = 2; -exports.output = ["red", "white", "yellow","green"]; -exports.click = false; -exports.icon = 'bolt'; -exports.options = { edge: "undefined" }; - -exports.html = `
-
-
-
Edge TB Name
-
-
-
`; - -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: -state_of_main_switch - sem sa bude reportovať stav hlavného ističa : 0-> off 1-> on (toto nie je na platforme, ale Rado to už do entity type doplnil) -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 - -door_condition - tuto ide pin 6, dverový kontakt -> 1 -> vyreportuje Closed, 0 -> vyreportuje Open -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 - -zjavne nám v jsone chýba stav hlavného ističa. Musíme to potom doplniť - -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 - momentálne sa stav zmení len keď vo flow klikneš aby sa zmenil, ale tá zmena by sa mala ukázať aj na platforme -*/ - -const dbRelays = TABLE("relays"); -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'); - -const DataToTbHandler = require('./helper/DataToTbHandler'); -let tbHandler; - -const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler'); -const errorHandler = new ErrorToServiceHandler(); - -let ws = null; -let rsPort = null; - -let pinsData; -let relaysData; -let rvoTbName; -let GLOBALS; //FLOW global GLOBALS -let SETTINGS; // GLOBALS.settings -let controller_type; - -let alarmStatus = "OFF"; - -const SEND_TO = { - debug: 0, - tb: 1, - cmd_manager: 2, - init: 3 -} - - -exports.install = function(instance) { - - process.on('uncaughtException', function (err) { - - //TODO send to service - - errLogger.error('uncaughtException:', err.message) - errLogger.error(err.stack); - - errorHandler.sendMessageToService(err.message + "\n" + err.stack, 0, "js_error"); - - //process.exit(1); - }) - - let previousValues = {temperature: 0}; - let rsPortReceivedData = []; - - let twilight_sensor_interval = 5;//minutes - let twilight_sensor = []; - const twilight_sensor_array = []; - let twighlightError = false; - - monitor.info("DI_DO_Relay_Controller installed"); - - //key is PIN number , line: 0 = RVO - /* - let conversionTable = { - "1": {tbname: "", type: "state_of_main_switch", "line": 0}, //state_of_main_switch pin1 - "2": {tbname: "", type: "rotary_switch_state", "line": 0}, //rotary_switch_state - poloha manual = pin2 - "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 - }; - */ - - //status for calculating Statecodes - let deviceStatuses = {};//key is device name: temperature,.... - deviceStatuses["state_of_main_switch"] = "Off";//Hlavný istič - deviceStatuses["rotary_switch_state"] = "Off";//Prevádzkový mód - deviceStatuses["door_condition"] = "closed";//Dverový kontakt - deviceStatuses["rvo"] = {status: "OK"};//elektromer rvo - deviceStatuses["temperature"] = "OK";//templomer - deviceStatuses["battery"] = "OK";//Batéria - deviceStatuses["power_supply"] = "OK";//Zdroj - deviceStatuses["master_node"] = "OK";//MN - FLOW.OMS_masterNodeIsResponding - deviceStatuses["no_voltage"] = "OK";//FLOW.OMS_no_voltage - výpadok napätia na fáze - - deviceStatuses["state_of_breaker"] = {};//"Off";//Istič - deviceStatuses["state_of_contactor"] = {};//"Off";//Stykač - - - function main() { - - GLOBALS = FLOW.GLOBALS; - SETTINGS = FLOW.GLOBALS.settings; - rvoTbName = SETTINGS.rvoTbName; - pinsData = GLOBALS.pinsData; - relaysData = GLOBALS.relaysData; - statusData = GLOBALS.statusData; - - tbHandler = new DataToTbHandler(SEND_TO.tb) - tbHandler.setSender(exports.title); - - controller_type = SETTINGS.controller_type //"lm" or "unipi" //logicMachine - if(controller_type == "") controller_type = "lm"; - - deviceStatuses["temperature"] = statusData.thermometer; - - console.log(exports.title, "controller type: ", controller_type); - - if(controller_type === "lm") - { - handleRsPort(); - } - else if(controller_type === "unipi") - { - handleWebSocket(); - } - else { - errLogger.debug("UNKNOWN controller_type:", controller_type); - } - } - - - function initialSetting() - { - - //force turn off relays - - let keys = Object.keys(pinsData); - for(let i = 0; i < keys.length; i++) - { - let key = keys[i]; - let line = pinsData[key].line; - - if(line != undefined) - { - if(relaysData[line] != undefined) - { - pinsData[key].tbname = relaysData[line].tbname; - - //relaysData[line].contactor = 0; - } - else - { - errLogger.error("CRITICAL!!! undefined relay", relaysData[line], line); - - //sendNotification("set port ", rvoTbName, ERRWEIGHT.CRITICAL, "local database is corrupted", "", SEND_TO.tb, instance, null ); - sendNotification("set port ", rvoTbName, "local_database_is_corrupted", {}, "", SEND_TO.tb, instance ); - } - } - - if(pinsData[key].type == "state_of_contactor") - { - - let pin = key - 1; - if(controller_type === "unipi") pin = key; - - //this will modify database - let forceTurnOff = true; - turnOffLine(line, pin, forceTurnOff, "turn off on startup"); - } - } - - let values = {}; - values["edge_fw_version"] = SETTINGS.edge_fw_version; - values["maintenance_mode"] = SETTINGS.maintenance_mode; - values["status"] = "OK"; - - sendTelemetry(values, rvoTbName); - instance.send(SEND_TO.init, "_"); - //instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "buildTasks"}); - - let time = 5*1000; - setTimeout(function(){ - instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "buildTasks"}); - - sendNotification("rsPort.open()", rvoTbName, "flow_start", {}, "", SEND_TO.tb, instance ); - monitor.info("-->FLOW bol spustený", rvoTbName, SETTINGS.edge_fw_version); - - }, time); - - } - - - function handleRsPort() - { - //TODO build according to pins!!! - //! rsPort to open are the same for lm and unipi and electromer ("/dev/ttymxc0") - 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]; - rsPort = new SerialPort("/dev/ttymxc0", { autoOpen: false }); - - rsPort.on('error', function(err) { - logger.debug("rsPort opened error - failed", err.message); - instance.send(SEND_TO.debug, err.message); - - errorHandler.sendMessageToService( exports.title + " rsPort opened error - failed: " + err.message); - }) - - rsPort.on('open', async function() { - - 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) { - - //set port - rsPort.write(Buffer.from(setRSPortData), function(err) { - monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); - - turnOffAlarm(); - initialSetting(); - }) - - }).catch(function (reason) { - errLogger.error( exports.title + " runSyncExec - promise rejected:" + reason); - errorHandler.sendMessageToService( exports.title + " runSyncExec - promise rejected:" + reason); - }); - - }); - - - rsPort.on('data', function (data){ - - rsPortReceivedData = [...rsPortReceivedData, ...data]; - - if (rsPortReceivedData[0] != 85) { - rsPortReceivedData = []; - return; - } - - let l = rsPortReceivedData.length; - - if (l < 4 ) return; - - if (l > 4 ) { - - // 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; - for ( i = 0, j = l; i < j; i += chunk ) { - temparray = rsPortReceivedData.slice(i, i + chunk); - - if ( temparray.length < 4 ){ - rsPortReceivedData = [...temparray]; - return; - } - - switchLogic(temparray); - } - - rsPortReceivedData = []; - return; - } - - switchLogic(rsPortReceivedData); - - rsPortReceivedData = []; - - }); - - rsPort.on("close", () => { - rsPort.close(); - }) - - rsPort.open(); - - } - - - function handleWebSocket() { - - console.log("handleWebSocket function called"); - ws = new WebSocket('ws:/10.0.0.38:1234/ws') - - - ws.onopen = function open() { - - instance.send(0, exports.title + " running"); - turnOffAlarm(); - - // useTurnOffCounter = true; - // turnOffCounter = relaysData.length - 1; - initialSetting(); - ws.send(JSON.stringify({"cmd":"all"})); - - // startRequests(); - }; - -// 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' -// }, - - ws.onmessage = function(data) { - - data = JSON.parse(data.data); - // console.log(data) - - // data comes in array except of "temperature" ==> it comes as an object - if(!Array.isArray(data)) - { - let value = data['value']; - - // temperature value comes very often. To handle it, we check if it change for more than 0.2 degrees, if yes, we send to TB - if(Math.abs(previousValues["temperature"] - value) > 0.21 ) - { - const dataToTb = { - [rvoTbName]: [ - { - "ts": Date.now(), - "values": {temperature: value} - } - ] - }; - - deviceStatuses["temperature"] = "OK"; - previousValues["temperature"] = value; - instance.send(SEND_TO.tb, dataToTb); - } - return; - } - - data.map(item => { - - let value = item['value']; - let pin = item["dev"] + item["circuit"]; // for example "relay1_03" or "input1_01" - - if (pin == undefined) return; - switchLogic(pin, value); - }) - } - - - ws.on('error', (err) => { - instance.send(SEND_TO.debug, err.message); - }) - - - ws.onclose = function(){ - // connection closed, discard old websocket and create a new one in 5s - // stopRequests(); - ws = null; - console.log("ws is null now, reconnecting in 5 seconds"); - setTimeout(handleWebSocket, 5000); - } - } - - instance.on("close", () => { - if(rsPort) rsPort.close(); - if(ws) ws.close(); - }) - - - function getPin(line) - { - //conversionTable - let keys = Object.keys(pinsData); - for(let i = 0; i < keys.length; i++) - { - let key = keys[i]; - - if(pinsData[key].type == "state_of_contactor" && pinsData[key].line == line) - { - if(rsPort) return key - 1; - if(ws) return key; - } - } - - logger.debug("no pin detected"); - - return null; - } - - - function turnOnAlarm() - { - if(SETTINGS.maintenance_mode) return; - - alarmStatus = "ON"; - - if(rsPort) - { - let arr = [0x55]; - arr.push( 13 ); - arr.push( 0 ); - arr.push( 1 ); - - rsPort.write(Buffer.from(arr), function(err) { - logger.debug("sirena zapnuta"); - }); - } - else if(ws) - { - let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_08", "value": 1}; - ws.send(JSON.stringify(cmd)); - logger.debug("sirena zapnuta"); - } - } - - - function turnOffAlarm() - { - alarmStatus = "OFF"; - - if(rsPort) - { - let arr = [0x55]; - arr.push( 13 ); - arr.push( 0 ); - arr.push( 0 ); - - rsPort.write(Buffer.from(arr), function(err) { - logger.debug("sirena vypnuta"); - }); - } - else if(ws) - { - let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_08", "value": 0}; - ws.send(JSON.stringify(cmd)); - logger.debug("sirena vypnuta"); - } - } - - - function reportLineStatus(line) - { - //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 = []; - - if(deviceStatuses["state_of_breaker"][line] == "On") - { - bits.push(0); - } - else bits.push(1); - - if(deviceStatuses["state_of_contactor"][line] == "On") - { - bits.push(0); - } - else bits.push(1); - - resizeArray(bits, 8, 0); - - let byte = bitwise.byte.write(bits.reverse()); - //console.log("line", line, bits, byte); - - sendTelemetry({statecode: byte}, tbname); - } - - - function turnOnLine(line, pin, force, info) - { - - instance.send(SEND_TO.debug, "turn on line " + line ); - if(force == undefined) force = false; - - if(line == 0) - { - if(alarmStatus == "ON") turnOffAlarm(); - SETTINGS.maintenance_mode = true; - - let values = {}; - values["statecode"] = calculateStateCode(); - values["power_mode"] = "maintenance"; - let tbname = relaysData[line].tbname; - sendTelemetry(values, tbname); - - monitor.info("turnOnLine (line, SETTINGS.maintenance_mode)", line, SETTINGS.maintenance_mode, info); - - return; - } - - if( pin === undefined) pin = getPin(line); - - monitor.info("turnOnLine (line, pin, force)", line, pin, force, info); - - if( pin === undefined) - { - monitor.info("pin is undefined!", line); - return; - } - - - if(!force) - { - if(relaysData[line].contactor == 1) - { - instance.send(SEND_TO.debug, "line is already on " + line ); - logger.debug("turnOnLine: line is already on: ", line); - - return; - } - } - - // if(!rsPort.isOpen && !ws) - if(!rsPort && !ws) - { - errLogger.error("di do controller - port or websocket is not opened"); - return; - } - - if(rsPort) - { - let arr = [0x55]; - arr.push( pin ); - arr.push( 0 ); - arr.push( 1 ); - - rsPort.write(Buffer.from(arr), function(err) { - if(err === undefined) - { - console.log("turnONLine zapisal do rsPortu", line, arr); - switchLogic(arr); - } - else - { - monitor.info("turnOnLine WRITE error", err); - } - - }); - - } - else if(ws) - { - console.log("turnONLine pin (relay)", pin); - //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) - } - } - - - function turnOffLine(line, pin, force, info) - { - if(force == undefined) force = false; - - if(line == 0) - { - SETTINGS.maintenance_mode = false; - - let values = {}; - values["statecode"] = calculateStateCode(); - values["power_mode"] = "Automatic"; - sendTelemetry(values, rvoTbName); - - return; - } - - if(pin === undefined) pin = getPin(line); - - monitor.info("turnOffLine (line, pin, force)", line, pin, force, info); - - if(pin === undefined) - { - errLogger.error("pin is undefined!", line); - return; - } - - if(!force) - { - if(relaysData[line].contactor == 0) - { - instance.send(SEND_TO.debug, "line is already off " + line ); - logger.debug("turnOffLine: line already off:", line); - - return; - } - } - - // if(!rsPort.isOpen && !ws) - if(!rsPort && !ws) - { - errLogger.error("dido controller - port or websocket is not opened"); - return; - } - - if(rsPort) - { - let arr = [0x55]; - arr.push( pin ); - arr.push( 0 ); - arr.push( 0 ); - - rsPort.write(Buffer.from(arr), function(err) { - if(err === undefined) - { - console.log("turnOffLine zapisal do rsPort-u", line, arr); - switchLogic(arr); - } - else - { - monitor.info("turnOffLine WRITE error", err); - } - - }); - - } - else if(ws) - { - //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method - 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) - } - - } - - - // main opening - instance.on("1", flowdata => { - main(); - }) - - - // we expect array as flowdata.data - instance.on("0", (flowdata) => { - - console.log(flowdata.data); - - if(flowdata.data instanceof Object) - { - - if(flowdata.data.hasOwnProperty("sender")) - { - //console.log("sender", flowdata.data); - - if(flowdata.data.sender == "gettemperature") - { - deviceStatuses["temperature"] = flowdata.data.status; - } - else if(flowdata.data.sender == "modbus_citysys") - { - //elektromer rvo - if(flowdata.data.tbdata.hasOwnProperty(rvoTbName)) - { - //rvo - deviceStatuses["rvo"] = {status: flowdata.data.tbdata[rvoTbName][0]["values"]["status"], tbdata: flowdata.data.tbdata}; - } - else { - //posli do tb - to je vyriesene na urovni modbus_citysys - //instance.send(SEND_TO.tb, flowdata.data.tbdata); - } - } - - instance.send(SEND_TO.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(flowdata.data)){ - - rsPort.write(Buffer.from(flowdata.data), function(err) { - switchLogic(flowdata.data); - - instance.send(SEND_TO.debug, {"WRITE":flowdata.data} ); - }); - } - }) - - - function calculateStateCode() - { - - 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 - if(!SETTINGS.maintenance_mode) - { - if(deviceStatuses["rotary_switch_state"] == "Manual") - { - bits.push(0); - bits.push(1); - } - - if(deviceStatuses["rotary_switch_state"] == "Automatic") - { - bits.push(0); - bits.push(0); - } - - if(deviceStatuses["rotary_switch_state"] == "Off") - { - bits.push(1); - bits.push(0); - } - } - else{ - bits.push(1); - bits.push(1); - } - - //Dverový kontakt - if(deviceStatuses["door_condition"] == "closed") - { - bits.push(0); - } - else bits.push(1); - - //EM - if(deviceStatuses["rvo"].status == "NOK") bits.push(1); - else bits.push(0); - - //Teplomer - if(deviceStatuses["temperature"] == "NOK") bits.push(1); - else bits.push(0); - - //Batéria - if(deviceStatuses["battery"] == "NOK") bits.push(1); - else bits.push(0); - - //Zdroj - 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); - - //výpadok napätia na fáze - if(deviceStatuses["no_voltage"] == "NOK") bits.push(1); - else bits.push(0); - - 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()); - - let byte = bytesToInt([byte1, byte0]); - - //console.log("calculateStateCode", byte); - - return byte; - } - - - function checkFinalRVOStatus() { - - // we check if any of these pins values are 0 --> it means status RVO is "NOK" - // pinIndex 6 is door_condition - if open in maintenance mode - status = OK - - //set RVO state - - let status = "OK"; - - if(deviceStatuses["rvo"].status == "NOK") - { - let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: rvo status is NOK"); - if(writeToFile) errLogger.error("checkFinalRVOStatus: rvo status is NOK", deviceStatuses["rvo"].tbdata); - - status = "NOK"; - } - - //ak teplomer NOK, rvo nok - if(deviceStatuses["temperature"] == "NOK") - { - - let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: temperature status is NOK"); - if(writeToFile) errLogger.error("checkFinalRVOStatus: temperature status is NOK"); - - status = "NOK"; - } - - if(status == "OK") - { - for (const pinIndex of [1, 4, 6]) { - if (previousValues[pinIndex] === 0) { - - if (pinIndex === 6 && SETTINGS.maintenance_mode) continue; - - let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: value is 0"); - if(writeToFile) errLogger.error("checkFinalRVOStatus: value is 0", pinsData[pinIndex].type); - - status = "NOK"; - - break; - } - } - } - - // battery status. If value is 1 - battery is not ok - if (previousValues[5] === 1) - { - let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: NOK status generated by battery"); - if(writeToFile) errLogger.error("checkFinalRVOStatus: NOK status generated by battery"); - - status = "NOK"; - } - - //ak mame telemetriu z elektromeru, posleme - if(deviceStatuses["rvo"].tbdata != undefined) - { - //deviceStatuses["rvo"] = {status: flowdata.data.tbdata[rvoTbName][0]["values"]["status"], tbdata: flowdata.data.tbdata}; - - deviceStatuses["rvo"].tbdata[rvoTbName][0]["values"]["status"] = status; - - - instance.send(SEND_TO.tb, deviceStatuses["rvo"].tbdata); - delete deviceStatuses["rvo"].tbdata; - } - - //console.log("FLOW.OMS_masterNodeIsResponding", FLOW.OMS_masterNodeIsResponding); - - if(!SETTINGS.masterNodeIsResponding) - { - //errLogger.error("Master node is not responding"); - errorHandler.sendMessageToService("Master node is not responding"); - status = "NOK"; - - deviceStatuses["master_node"] = "NOK"; - } - else deviceStatuses["master_node"] = "OK"; - - //console.log("checkFinalRVOStatus", status); - if(SETTINGS.no_voltage.size > 0) - { - let writeToFile = errorHandler.processMessage("no voltage detected"); - if(writeToFile) errLogger.error("no voltage detected", SETTINGS.no_voltage); - - status = "NOK"; - - deviceStatuses["no_voltage"] = "NOK"; - } - else deviceStatuses["no_voltage"] = "OK"; - - if(status == "NOK") - { - sendTelemetry({status: "NOK"}, rvoTbName); - return false; - } - - return true; - } - - - - // we pass array to function in case of rsPort [[55,3,0,1]] - // we pass two values in case of websocket [3,1] - const switchLogic = (...args) => { - - let values = {status: "OK"}; - let dataToTb, pinIndex, newPinValue, twighlight; - - if(args.length == 1) - { - pinIndex = args[0][1] + 1; - if (pinIndex === 17) pinIndex--; - newPinValue = args[0][3]; - twighlight = args[0][2]; - } - else - { - pinIndex = args[0]; - newPinValue = args[1]; - } - - let obj = pinsData[pinIndex]; - - if(obj == undefined) - { - previousValues[pinIndex] = newPinValue; - return; - } - - let type = obj.type; - let line = obj.line; - let tbname = obj.tbname; - - //default value - let value = "On"; - if(newPinValue === 0) value = "Off"; - - //Hlavný istič - if(type === "state_of_main_switch") - { - if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) - { - sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance , "state_of_main_switch"); - values["status"] = "NOK"; - - deviceStatuses["state_of_main_switch"] = "Off"; - } - else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) - { - sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_on", {}, "", SEND_TO.tb, instance , "state_of_main_switch"); - - deviceStatuses["state_of_main_switch"] = "On"; - } - } - - //Prevádzkový mód - else if(type == "rotary_switch_state") - { - // combination of these two pins required to get result - let pin2, pin3; - if(pinIndex == 2 || pinIndex == "input1_02") - { - pin2 = newPinValue; - pin3 = previousValues[3] || previousValues["input1_03"]; - - if(pin3 == undefined) - { - previousValues[pinIndex] = newPinValue; - return; - } - } - else if(pinIndex == 3 || pinIndex == "input1_03") - { - pin3 = newPinValue; - pin2 = previousValues[2] || previousValues["input1_02"]; - - if(pin2 == undefined) - { - previousValues[pinIndex] = newPinValue; - return; - } - } - - //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"; - - deviceStatuses["rotary_switch_state"] = value; - - //automatic - profilu pre nody sa vykonavaju - //ak je spracovany, a automatic - tak ho zapnem - //ak nie je spracovany, iba profil zapisem - - if(pin2 != undefined && pin3 != undefined) instance.send(SEND_TO.cmd_manager, {sender: "dido_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]) - { - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.ALERT, "Power supply is not OK", "", SEND_TO.tb, instance); - sendNotification("switchLogic", rvoTbName, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); - values["status"] = "NOK"; - - deviceStatuses["power_supply"] = "NOK"; - } - else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) - { - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.NOTICE, "Power supply is is OK", "", SEND_TO.tb, instance); - sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); - - deviceStatuses["power_supply"] = "OK"; - } - } - //Batéria - pin 5 - else if (type === "battery") - { - if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) - { - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.ERROR, "Battery is not OK", "", SEND_TO.tb, instance); - sendNotification("switchLogic", rvoTbName, "battery_level_is_low", {}, "", SEND_TO.tb, instance, "battery_level"); - values["status"] = "NOK"; - - deviceStatuses["battery"] = "NOK"; - } - else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) - { - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.NOTICE, "Battery is OK", "", SEND_TO.tb, instance); - sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); - - deviceStatuses["battery"] = "OK"; - } - } - //Dverový kontakt - pin 6 - else if(type == "door_condition") - { - newPinValue === 0 ? value = "open" : value = "closed"; - - if (newPinValue != previousValues[pinIndex]) - { - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.NOTICE, `RVO door ${value}`, "", SEND_TO.tb, instance, "rvo_door"); - //TODO ? sendNotification("switchLogic", rvoTbName, "door_value", {value: value}, "", SEND_TO.tb, instance, "rvo_door"); - } - - if (value === "open" && SETTINGS.maintenance_mode) - { - sendNotification("switchLogic", rvoTbName, "door_opened", {}, "", SEND_TO.tb, instance, "rvo_door"); - } - - if (value === "open" && !SETTINGS.maintenance_mode) - { - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.WARNING, "RVO open door out of maintenance mode", "", SEND_TO.tb, instance); - sendNotification("switchLogic", rvoTbName, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); - values["status"] = "NOK"; - - turnOnAlarm(); - } - - if (value === "closed") - { - if(alarmStatus == "ON") turnOffAlarm(); - //turnOffAlarm(); - - sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); - } - - deviceStatuses["door_condition"] = value; - - } - else if(type == "twilight_sensor") - { - //lux sensor - value = parseFloat(newPinValue + (256*twighlight)); - - let now = new Date(); - //new Date(dusk.getTime() - - let obj = {timestamp: now.getTime(), value: value}; - - //test - //twilight_sensor_interval = 1; - - twilight_sensor.push(obj); - twilight_sensor_array.push(value); - - //check if we receive just 1 constant value from lux sensor ==> error - if(twilight_sensor_array.length > 10) { - - let set = new Set(twilight_sensor_array); - if(set.size === 1 && !twighlightError) - { - twighlightError = true; - values["status"] = "NOK"; - let value = twilight_sensor_array.shift(); - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.ERROR, "Lux sensor error", {"Repeating value": value}, SEND_TO.tb, instance ); - newPinValue = 0; - } - else if (set.size !== 1 && twighlightError) - { - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.NOTICE, "Lux sensor is working again", "", SEND_TO.tb, instance ); - twighlightError = false; - twilight_sensor_array.shift(); - newPinValue = value; - } - else if (set.size === 1 && twighlightError) - { - values["status"] = "NOK"; - twilight_sensor_array.shift(); - newPinValue = 0; - } - } - - - let diff = twilight_sensor[ twilight_sensor.length - 1 ].timestamp - twilight_sensor[0].timestamp; - if(diff >= twilight_sensor_interval * 60 * 1000) - { - const average = twilight_sensor.reduce((acc, c) => acc + c.value, 0) / twilight_sensor.length; - instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: average}); - - twilight_sensor = []; - - //console.log("lux_sensor send", average); - } - //else console.log("lux_sensor", value, diff); - - values["status"] = "OK"; - - // - } - else if(type == "state_of_contactor") - { - if(!(deviceStatuses["state_of_contactor"][line] == value)) - { - sendNotification("switchLogic", rvoTbName, "state_of_contactor_for_line", {line: line, value: value}, "", SEND_TO.tb, instance ); - } - - deviceStatuses["state_of_contactor"][line] = value; - - //true, false - if(value === "On") value = true; - else if(value === "Off") value = false; - - //TODO do we need to modify relays table with contactor value, if we do not use it on startup ?? - let dataChanged = false; - if(relaysData[line].contactor !== newPinValue) { - dataChanged = true; - relaysData[line].contactor = newPinValue; - } - - instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, value: value, dataChanged: dataChanged}); - reportLineStatus(line); - - //modify table relays - // dbRelays.modify({ contactor: newPinValue }).where("line", line).make(function(builder) { - // builder.callback(function(err, response) { - - // if(err == undefined) - // { - - // let time = 0; - // if(value) time = 1000 * 10;//10 sekund - - // let dataChanged = false; - // if(relaysData[line].contactor != newPinValue) dataChanged = true; - // relaysData[line].contactor = newPinValue; - - // //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, value: value, dataChanged: dataChanged}); - // }, time); - - // reportLineStatus(line); - // } - // else - // { - // errLogger.error("modify table relays failed", err); - // } - // }); - // }); - } - - else if(type === "state_of_breaker") - { - - let valueChanged = false; - if(newPinValue != previousValues[pinIndex]) valueChanged = true; - - if(valueChanged) - { - instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line}); - } - - if(value == "Off") values["status"] = "NOK"; - - deviceStatuses["state_of_breaker"][line] = value; - - reportLineStatus(line); - - } - - values[type] = value; - - let result = checkFinalRVOStatus(); - if(!result && line == 0) - { - values["status"] = "NOK"; - } - - - if(pinsData.hasOwnProperty(pinIndex)) - { - let valueChanged = false; - if(newPinValue != previousValues[pinIndex]) valueChanged = true; - - if(type == "state_of_contactor") valueChanged = true; - if(type == "rotary_switch_state") valueChanged = true; - if(type === "state_of_breaker") - { - //console.log(type, values, valueChanged); - } - - if(rvoTbName == "") - { - console.log("rvoTbName is EMPTY"); - } - - if(rvoTbName == tbname) - { - values["statecode"] = calculateStateCode(); - //console.log(type, values, valueChanged, FLOW.OMS_rvo_tbname, tbname); - } - - - if(valueChanged) - { - sendTelemetry(values, tbname); - } - - if(type == "rotary_switch_state") - { - if(SETTINGS.maintenance_mode) value = "maintenance"; - value = value.toLowerCase(); - - let values = {}; - values["power_mode"] = value; - - sendTelemetry(values, tbname); - } - } - else - { - logger.debug("no pinIndex", pinsData[pinIndex], pinsData); - } - - //pin was changed - previousValues[pinIndex] = newPinValue; - - - } - - function sendTelemetry(values, tbname) - { - let dataToTb = { - [tbname]: [ - { - "ts": Date.now(), - "values": values - } - ] - } - - //instance.send(SEND_TO.tb, dataToTb); - tbHandler.sendToTb(dataToTb, instance); - } - - -} - - - - -//! 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 -// *|al_mswitch|state_of_main_switch|0|........... -// *|al_rswitch1|rotary_switch_state|0|........... -// *|al_rswitch2|rotary_switch_state|0|........... -// *|al_power|power_supply|0|........... -// *|al_battery|battery|0|........... -// *|al_door|door_condition|0|........... -// *|al_breaker1|state_of_breaker|1|........... -// *|al_breaker2|state_of_breaker|2|........... -// *|al_breaker3|state_of_breaker|3|........... -// *|al_breaker4|state_of_breaker|4|........... -// *|al_relay_1|state_of_contactor|1|........... -// *|al_relay_2|state_of_contactor|2|........... -// *|al_relay_3|state_of_contactor|3|........... -// *|al_relay_4|state_of_contactor|4|........... -// *|16|twilight_sensor|0|........... -// *|28744F7791180257|temperature|0|........... - - -//! pins_data --> from UNIPI -// { -// '16': { pin: '16', type: 'twilight_sensor', line: 0 }, -// al_mswitch: { pin: 'al_mswitch', type: 'state_of_main_switch', line: 0 }, -// al_rswitch1: { pin: 'al_rswitch1', type: 'rotary_switch_state', line: 0 }, -// al_rswitch2: { pin: 'al_rswitch2', type: 'rotary_switch_state', line: 0 }, -// al_power: { pin: 'al_power', type: 'power_supply', line: 0 }, -// al_battery: { pin: 'al_battery', type: 'battery', line: 0 }, -// al_door: { pin: 'al_door', type: 'door_condition', line: 0 }, -// al_breaker1: { pin: 'al_breaker1', type: 'state_of_breaker', line: 1 }, -// al_breaker2: { pin: 'al_breaker2', type: 'state_of_breaker', line: 2 }, -// al_breaker3: { pin: 'al_breaker3', type: 'state_of_breaker', line: 3 }, -// al_breaker4: { pin: 'al_breaker4', type: 'state_of_breaker', line: 4 }, -// al_relay_1: { pin: 'al_relay_1', type: 'state_of_contactor', line: 1 }, -// al_relay_2: { pin: 'al_relay_2', type: 'state_of_contactor', line: 2 }, -// al_relay_3: { pin: 'al_relay_3', type: 'state_of_contactor', line: 3 }, -// al_relay_4: { pin: 'al_relay_4', type: 'state_of_contactor', line: 4 }, -// '28744F7791180257': { pin: '28744F7791180257', type: 'temperature', line: 0 } -// } - - -//! 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}' -// } -// } - diff --git a/flow/dido_controller.js b/flow/dido_controller.js index fe1412b..b429b14 100644 --- a/flow/dido_controller.js +++ b/flow/dido_controller.js @@ -4,8 +4,9 @@ exports.version = '2.0.0'; exports.group = 'Worksys'; exports.color = '#2134B0'; exports.input = 3; -exports.output = ["red", "white", "yellow", "green"]; +exports.output = ["red", "white", "yellow"]; exports.click = false; +exports.author = 'Daniel Segeš'; exports.icon = 'bolt'; exports.options = { edge: "undefined" }; @@ -56,30 +57,24 @@ state_of_contactor - podľa indexu stykača sa reportuje jeho stav, teda momentálne sa stav zmení len keď vo flow klikneš aby sa zmenil, ale tá zmena by sa mala ukázať aj na platforme */ -const { 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'); -const DataToTbHandler = require('./helper/DataToTbHandler'); -let tbHandler; +//globals +//FIRMWARE version +FLOW.OMS_edge_fw_version = "2024-07-08";//rok-mesiac-den +FLOW.OMS_edgeName = ""; +FLOW.OMS_maintenance_mode = false; -const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler'); -const errorHandler = new ErrorToServiceHandler(); +//dynamic values +FLOW.OMS_masterNodeIsResponding = true; //cmd_manager +//FLOW.OMS_brokerready = false //wsmqttpublish +FLOW.OMS_no_voltage = new Set();//modbus_citysys - elektromer -let ws = null; -let rsPort = null; - -let pinsData; -let relaysData; -let rvoTbName; -let GLOBALS; //FLOW global GLOBALS -let SETTINGS; // GLOBALS.settings -let controller_type; +//see loadSettings() in cmd_manager +FLOW.OMS_language = "en";//cmd_manager +FLOW.OMS_rvo_name = "";//cmd_manager +FLOW.OMS_rvo_tbname = "";//relaysData +FLOW.OMS_temperature_adress = "";//cmd_manager +//----------------------------------------------- let alarmStatus = "OFF"; @@ -89,6 +84,43 @@ const SEND_TO = { cmd_manager: 2 } +var log4js = require("log4js"); +var path = require('path'); + +log4js.configure({ + appenders: { + errLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'err.txt') }, + monitorLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'monitor.txt') }, + console: { type: 'console' } + }, + categories: { + errLogs: { appenders: ['console', 'errLogs'], level: 'error' }, + monitorLogs: { appenders: ['console', 'monitorLogs'], level: 'trace' }, + //another: { appenders: ['console'], level: 'trace' }, + default: { appenders: ['console'], level: 'trace' } + } +}); + +const errLogger = log4js.getLogger("errLogs"); +const logger = log4js.getLogger(); +const monitor = log4js.getLogger("monitorLogs"); + +//console.log(path.join(__dirname, 'err.txt', "-----------------------------")); + +/* +process.on('uncaughtException', function (err) { + + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + + //process.exit(1); +}) +*/ + +//USAGE +//logger.debug("text") +//monitor.info('info'); +//errLogger.error("some error"); exports.install = function(instance) { @@ -104,16 +136,17 @@ exports.install = function(instance) { //process.exit(1); }) - let previousValues = {}; + let previousValues = {temperature: 0}; let rsPortReceivedData = []; - //to be able to get proper twilight values, when let twilight_sensor_interval = 5;//minutes let twilight_sensor = []; const twilight_sensor_array = []; let twilightError = false; - monitor.info("DIDO_Relay_Controller installed"); + let edgeName = ""; + + monitor.info("DI_DO_Relay_Controller installed"); //key is PIN number , line: 0 = RVO /* @@ -134,38 +167,67 @@ exports.install = function(instance) { }; */ + const dbPins = TABLE("pins"); + let pinsData = {};//key is pin + + const dbRelays = TABLE("relays"); + let relaysData = {};//key is line + //status for calculating Statecodes - 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 - "master_node": "OK", //MN - GLOBALS.settings.masterNodeIsResponding - "no_voltage": "OK", //GLOBALS.settings.no_voltage - výpadok napätia na fáze - "state_of_breaker": {}, //"Off",//Istič - "state_of_contactor": {}, //"Off",//Stykač - "twilight_sensor": "OK" //lux sensor - }; + let deviceStatuses = {};//key is device name: temperature,.... + 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["temperature"] = "OK";//templomer + deviceStatuses["battery"] = "OK";//Batéria + deviceStatuses["power_supply"] = "OK";//Zdroj + deviceStatuses["master_node"] = "OK";//MN - FLOW.OMS_masterNodeIsResponding + deviceStatuses["no_voltage"] = "OK";//FLOW.OMS_no_voltage - výpadok napätia na fáze + deviceStatuses["state_of_breaker"] = {};//"Off";//Istič + deviceStatuses["state_of_contactor"] = {};//"Off";//Stykač + deviceStatuses["twilight_sensor"] = "OK"; //lux sensor - function main() { + /* + dbRelays.on('change', function(doc, old) { + console.log("'DI_DO_Controller - dbRelays.on('change'"); + instance.send(SEND_TO.cmd_manager, "reload_relays"); + }); + */ - GLOBALS = FLOW.GLOBALS; - SETTINGS = FLOW.GLOBALS.settings; - rvoTbName = SETTINGS.rvoTbName; - pinsData = GLOBALS.pinsData; - relaysData = GLOBALS.relaysData; + const SerialPort = require('serialport'); + const WebSocket = require('ws'); - tbHandler = new DataToTbHandler(SEND_TO.tb) - tbHandler.setSender(exports.title); + let ws = null; + let rsPort = null; + + //const { exec } = require('child_process'); + const { openPort, runSyncExec, writeData } = require('./helper/serialport_helper.js'); + const { bytesToInt, resizeArray } = require('./helper/utils'); + const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + const { sendNotification, ERRWEIGHT } = require('./helper/notification_reporter.js'); + const bitwise = require('bitwise'); - controller_type = SETTINGS.controller_type //"lm" or "unipi" //logicMachine - if(controller_type == "") controller_type = "lm"; + const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler.js'); + const errorHandler = new ErrorToServiceHandler(); - console.log(exports.title, "controller type: ", controller_type); + //let useTurnOffCounter = false; + //let turnOffCounter = 0; + let controller_type = FLOW.OMS_controller_type //"lm" or "unipi" //logicMachine + if(controller_type == "") controller_type = "lm"; + + console.log(exports.title, "controller type: ", controller_type); + + async function loadAllDb() + { + let responsePins = await promisifyBuilder(dbPins.find()); + pinsData = makeMapFromDbResult(responsePins, "pin"); + + let responseRelays = await promisifyBuilder(dbRelays.find()); + relaysData = makeMapFromDbResult(responseRelays, "line"); + + FLOW.OMS_rvo_tbname = relaysData[0].tbname; if(controller_type === "lm") { @@ -178,13 +240,12 @@ exports.install = function(instance) { else { errLogger.debug("UNKNOWN controller_type:", controller_type); } - } + } function initialSetting() { - //force turn off relays - + //force turn off relays & set tbname let keys = Object.keys(pinsData); for(let i = 0; i < keys.length; i++) { @@ -196,12 +257,15 @@ exports.install = function(instance) { if(relaysData[line] != undefined) { pinsData[key].tbname = relaysData[line].tbname; - //relaysData[line].contactor = 0; + + relaysData[line].contactor = 0; } else { errLogger.error("CRITICAL!!! undefined relay", relaysData[line], line); - sendNotification("set port ", rvoTbName, "local_database_is_corrupted", {}, "", SEND_TO.tb, instance ); + + //sendNotification("set port ", edgeName, ERRWEIGHT.CRITICAL, "local database is corrupted", "", SEND_TO.tb, instance, null ); + sendNotification("set port ", edgeName, "local_database_is_corrupted", {}, "", SEND_TO.tb, instance ); } } @@ -212,23 +276,37 @@ exports.install = function(instance) { //this will modify database let forceTurnOff = true; - turnLine("off", line, pin, forceTurnOff, "turn off on startup"); + turnOffLine(line, pin, forceTurnOff, "turn off on startup"); } } //report RVO version relaysData[0].tbname; let values = {}; - values["edge_fw_version"] = SETTINGS.edge_fw_version; - values["maintenance_mode"] = SETTINGS.maintenance_mode; + values["edge_fw_version"] = FLOW.OMS_edge_fw_version; + values["maintenance_mode"] = FLOW.OMS_maintenance_mode; + values["status"] = "OK"; - sendTelemetry(values, rvoTbName); + edgeName = relaysData[0].tbname; + FLOW.OMS_edgeName = edgeName; - let time = 5*1000; + dataToTb = { + [edgeName]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + instance.send(SEND_TO.tb, dataToTb); + + let time = 3*1000; setTimeout(function(){ instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "buildTasks"}); - sendNotification("rsPort.open()", rvoTbName, "flow_start", {}, "", SEND_TO.tb, instance); - monitor.info("-->FLOW bol spustený", rvoTbName, SETTINGS.edge_fw_version); + sendNotification("rsPort.open()", edgeName, "flow_start", {}, "", SEND_TO.tb, instance ); + monitor.info("-->FLOW bol spustený", edgeName, FLOW.OMS_edge_fw_version); + }, time); } @@ -253,23 +331,27 @@ exports.install = function(instance) { //set port rsPort.write(Buffer.from(setRSPortData), function(err) { - if(!err) { - monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); + monitor.info(exports.title + "--->Digital in_out has been set (runSyncExec was sucessfull)"); - turnAlarm("off"); - initialSetting(); - } + turnOffAlarm(); + + //useTurnOffCounter = true; + //turnOffCounter = relaysData.length - 1; + + initialSetting(); }) - }).catch(function(reason) { - errLogger.error(exports.title + " runSyncExec - promise rejected:" + reason); - errorHandler.sendMessageToService(exports.title + " runSyncExec - promise rejected:" + reason); + }).catch(function (reason) { + //instance.send(SEND_TO.debug, exports.title + " runSyncExec - promise rejected:" + reason); + errLogger.error( exports.title + " runSyncExec - promise rejected:" + reason); + + errorHandler.sendMessageToService( exports.title + " runSyncExec - promise rejected:" + reason); }); }); - rsPort.on('data', function(data) { + rsPort.on('data', function (data){ rsPortReceivedData = [...rsPortReceivedData, ...data]; @@ -312,6 +394,7 @@ exports.install = function(instance) { }) rsPort.open(); + } @@ -326,7 +409,7 @@ exports.install = function(instance) { ws.onopen = function open() { instance.send(0, exports.title + " running"); - turnAlarm("off"); + turnOffAlarm(); // useTurnOffCounter = true; // turnOffCounter = relaysData.length - 1; @@ -342,7 +425,6 @@ exports.install = function(instance) { }, 150000) }; - // SAMPLE DATA FROM WEBSOCKET // { // glob_dev_id: 1, @@ -366,24 +448,44 @@ exports.install = function(instance) { // dev: 'input', // mode: 'Simple' // }, - ws.onmessage = async function(data) { + ws.onmessage = function(data) { data = JSON.parse(data.data); // data comes in array except of "temperature" ==> it comes as an object - // we do not handle temperature from evok any more => we return, if temperature comes: - if(isObject(data)) return; + if(!Array.isArray(data)) + { + let value = data['value']; + + // temperature value comes very often. To handle it, we check if it change for more than 0.2 degrees, if yes, we send to TB + if(Math.abs(previousValues["temperature"] - value) > 0.21 ) + { + const dataToTb = { + [FLOW.OMS_rvo_tbname]: [ + { + "ts": Date.now(), + "values": {temperature: value} + } + ] + }; + + deviceStatuses["temperature"] = "OK"; + previousValues["temperature"] = value; + instance.send(SEND_TO.tb, dataToTb); + } + return; + } data.map(item => { - + let value = item['value']; let pin = item["dev"] + item["circuit"]; // for example "relay1_03" or "input1_01" - if(pin == undefined) return; + if (pin == undefined) return; switchLogic(pin, value); }) } - + ws.on('error', (err) => { monitor.info('websocket error, reconnect') @@ -405,59 +507,92 @@ exports.install = function(instance) { } } + // ! do we need requests every minute ??? + // const startRequests = () => { + // console.log("startRequest function called"); + // start = setInterval(() => { + // // console.log("data from evok requested"); + // ws.send(JSON.stringify({"cmd":"filter", "devices": "neuron"})); + // // ws.send(JSON.stringify({"cmd":"filter", "devices":["input", "relay"]})); + // }, 150000) + // } + + instance.on("close", () => { if(rsPort) rsPort.close(); if(ws) ws.close(); + clearInterval(sendRebuildTasksAt11); }) + loadAllDb(); function getPin(line) { - //conversionTable - let keys = Object.keys(pinsData); - for(let i = 0; i < keys.length; i++) - { - let key = keys[i]; - - if(pinsData[key].type == "state_of_contactor" && pinsData[key].line == line) + //conversionTable + let keys = Object.keys(pinsData); + for(let i = 0; i < keys.length; i++) { - if(rsPort) return key - 1; - if(ws) return key; + let key = keys[i]; + + if(pinsData[key].type == "state_of_contactor" && pinsData[key].line == line) + { + if(rsPort) return key - 1; + if(ws) return key; + } } - } - logger.debug("no pin detected"); + logger.debug("no pin detected"); - return null; + return null; } - function turnAlarm(onOrOff) + function turnOnAlarm() { - let value = 0; - if(onOrOff == "on") value = 1; + if(FLOW.OMS_maintenance_mode) return; - if(value == 1 && SETTINGS.maintenance_mode) return; - - alarmStatus = "OFF"; - if(value == 1) alarmStatus = "ON"; + alarmStatus = "ON"; if(rsPort) { let arr = [0x55]; - arr.push(13); - arr.push(0); - arr.push(value); - + arr.push( 13 ); + arr.push( 0 ); + arr.push( 1 ); + rsPort.write(Buffer.from(arr), function(err) { - logger.debug(`sirena - ${onOrOff}`); + logger.debug("sirena zapnuta"); }); } else if(ws) { - let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_01", "value": value}; + let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_01", "value": 1}; ws.send(JSON.stringify(cmd)); - logger.debug(`sirena - ${onOrOff}`); + logger.debug("sirena zapnuta"); + } + } + + + function turnOffAlarm() + { + alarmStatus = "OFF"; + + if(rsPort) + { + let arr = [0x55]; + arr.push( 13 ); + arr.push( 0 ); + arr.push( 0 ); + + rsPort.write(Buffer.from(arr), function(err) { + logger.debug("sirena vypnuta"); + }); + } + else if(ws) + { + let cmd = {"cmd": "set", "dev": "relay", "circuit": "1_01", "value": 0}; + ws.send(JSON.stringify(cmd)); + logger.debug("sirena vypnuta"); } } @@ -465,16 +600,18 @@ exports.install = function(instance) { function reportLineStatus(line) { //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 = []; - if(deviceStatus["state_of_breaker"][line] == "On") + if(deviceStatuses["state_of_breaker"][line] == "On") { bits.push(0); } else bits.push(1); - if(deviceStatus["state_of_contactor"][line] == "On") + if(deviceStatuses["state_of_contactor"][line] == "On") { bits.push(0); } @@ -485,47 +622,66 @@ exports.install = function(instance) { let byte = bitwise.byte.write(bits.reverse()); //console.log("line", line, bits, byte); - sendTelemetry({statecode: byte}, tbname); + + let values = { + statecode: byte + } + + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + + //console.log(values); + + instance.send(SEND_TO.tb, dataToTb); } - // turn line on or off - function turnLine(onOrOff, line, pin, force, info) + function turnOnLine(line, pin, force, info) { - //onOrOff => "on" or "off" - let value = 0; - if(onOrOff == "on") value = 1; - + + instance.send(SEND_TO.debug, "turn on line " + line ); if(force == undefined) force = false; if(line == 0) { - if(value == 1 && alarmStatus == "ON") turnAlarm("off"); - SETTINGS.maintenance_mode = value? true: false; + if(alarmStatus == "ON") turnOffAlarm(); + FLOW.OMS_maintenance_mode = true; let values = {}; values["statecode"] = calculateStateCode(); - values["power_mode"] = value ? "maintenance": "Automatic"; - sendTelemetry(values, rvoTbName); - - monitor.info(`turnLine ${onOrOff} - (line, SETTINGS.maintenance_mode)`, line, SETTINGS.maintenance_mode, info); + values["power_mode"] = "maintenance"; + let tbname = relaysData[line].tbname; + sendTelemetry(values, tbname); + + monitor.info("turnOnLine (line, FLOW.OMS_maintenance_mode)", line, FLOW.OMS_maintenance_mode, info); + return; } - if(pin === undefined) pin = getPin(line); + if( pin === undefined) pin = getPin(line); - if(pin === undefined) + monitor.info("turnOnLine (line, pin, force)", line, pin, force, info); + + if( pin === undefined) { - errLogger.error("pin is undefined!", line); + monitor.info("pin is undefined!", line); return; } - + + if(!force) { - if(relaysData[line].contactor == value) + if(relaysData[line].contactor == 1) { - instance.send(SEND_TO.debug, `line is already ${onOrOff} ` + line ); - logger.debug(`turnLine: line is already ${onOrOff} `, line); + instance.send(SEND_TO.debug, "line is already on " + line ); + logger.debug("turnOnLine: line is already on: ", line); + return; } } @@ -536,94 +692,170 @@ exports.install = function(instance) { errLogger.error("dido controller - port or websocket is not opened"); return; } - + if(rsPort) { let arr = [0x55]; - arr.push(pin); - arr.push(0); - arr.push(value); + arr.push( pin ); + arr.push( 0 ); + arr.push( 1 ); rsPort.write(Buffer.from(arr), function(err) { if(err === undefined) { - monitor.info(`turnLine ${onOrOff} zapisal do rsPort-u`, line, pin, arr, info); + console.log("turnONLine zapisal do rsPortu", line, arr); switchLogic(arr); } else { - monitor.info(`turnLine ${onOrOff} WRITE error`, err); - } + monitor.info("turnOnLine WRITE error", err); + } + + }); + + } + else if(ws) + { + console.log("turnONLine pin (relay)", pin); + //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) + } + } + + + function turnOffLine(line, pin, force, info) + { + if(force == undefined) force = false; + + if(line == 0) + { + FLOW.OMS_maintenance_mode = false; + + let values = {}; + values["statecode"] = calculateStateCode(); + values["power_mode"] = "automatic"; + let tbname = relaysData[line].tbname; + sendTelemetry(values, tbname); + + return; + } + + if( pin === undefined) pin = getPin(line); + + monitor.info("turnOffLine (line, pin, force)", line, pin, force, info); + + if( pin === undefined) + { + errLogger.error("pin is undefined!", line); + return; + } + + if(!force) + { + if(relaysData[line].contactor == 0) + { + instance.send(SEND_TO.debug, "line is already off " + line ); + logger.debug("turnOffLine: line already off:", line); + + return; + } + } + + // if(!rsPort.isOpen && !ws) + if(!rsPort && !ws) + { + errLogger.error("di do controller - port or websocket is not opened"); + return; + } + + if(rsPort) + { + let arr = [0x55]; + arr.push( pin ); + arr.push( 0 ); + arr.push( 0 ); + + rsPort.write(Buffer.from(arr), function(err) { + if(err === undefined) + { + console.log("turnOffLine zapisal do rsPort-u", line, arr); + switchLogic(arr); + } + else + { + monitor.info("turnOffLine WRITE error", err); + } + }); } else if(ws) { //pin = "relay1_03" or "input1_01" ... we must make just "1_01" with slice method - monitor.info(`turnLine ${onOrOff} - (line, pin, force)`, line, pin, force, info); - let cmd = {"cmd": "set", "dev": "relay", "circuit": pin.slice(5), "value": value}; + //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, value) + //switchLogic(pin, 0) } + } - // main opening - instance.on("2", _ => { - main(); - }) - - //data from modbus_reader or temperature sensor or twilight sensor or other modbus device instance.on("0", flowdata => { - if(!isObject(flowdata.data)) return; + if(!flowdata.data instanceof Object) return; // console.log('***********************', flowdata.data) instance.send(SEND_TO.debug, flowdata.data); // we handle nok status from modbus_reader component and thermometer - if("status" in flowdata.data) + if(flowdata.data?.status) { const status = flowdata.data.status; if(status == "NOK-twilight_sensor") { - deviceStatus["twilight_sensor"] = "NOK"; + deviceStatuses["twilight_sensor"] = "NOK"; } else if(status == "NOK-em340" || status == "NOK-em111") { - deviceStatus["em"] = "NOK"; + deviceStatuses["em"] = "NOK"; } else if(status == "NOK-thermometer") { - deviceStatus["temperature"] = "NOK"; + deviceStatuses["temperature"] = "NOK"; } } - else if("values" in flowdata.data) + else if(flowdata.data?.values) { const values = flowdata.data.values; if(values.hasOwnProperty("twilight_sensor")) { instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "lux_sensor", value: values["twilight_sensor"]}); - deviceStatus["twilight_sensor"] = "OK" + deviceStatuses["twilight_sensor"] = "OK" } else if(values.hasOwnProperty("temperature")) { - deviceStatus["temperature"] = "OK"; + 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")) { - deviceStatus["em"] = "OK"; - SETTINGS.no_voltage.size > 0 ? deviceStatus["no_voltage"] = "NOK": deviceStatus["no_voltage"] = "OK"; + deviceStatuses["em"] = "OK"; + } + else + { + return; } - sendTelemetry(values, rvoTbName); + const updateStatus = checkFinalRVOStatus(); + if(updateStatus) values.status = "OK"; + + sendTelemetry(values, FLOW.OMS_rvo_tbname); } - console.log("-----from data") - console.log(flowdata.data) - sendRvoStatus(); }) @@ -639,10 +871,11 @@ exports.install = function(instance) { let force = obj.force; let info = obj.info; - if(obj.command == "on") turnLine("on", line, undefined, force, info); - else if(obj.command == "off") turnLine("off", line, undefined, force, info); - else if(obj.command == "turnOnAlarm") turnAlarm("on"); - else if(obj.command == "turnOffAlarm") turnAlarm("off"); + 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(); + //! ake data prichadzaju z cmd_manager.js ??? //TODO transform to websocket @@ -660,34 +893,35 @@ exports.install = function(instance) { function calculateStateCode() { + let bytes = []; let bits = []; - //Hlavný istič - state_of_main_switch => v rvo senica je to druhy door pre silovu cast (EM) - if(deviceStatus["state_of_main_switch"] == "closed") + //Hlavný istič - state_of_main_switch + if(deviceStatuses["state_of_main_switch"] == "On") { bits.push(0); } - else + 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 - if(!SETTINGS.maintenance_mode) + if(!FLOW.OMS_maintenance_mode) { - if(deviceStatus["rotary_switch_state"] == "Manual") + if(deviceStatuses["rotary_switch_state"] == "Manual") { bits.push(0); bits.push(1); } - if(deviceStatus["rotary_switch_state"] == "Automatic") + if(deviceStatuses["rotary_switch_state"] == "Automatic") { bits.push(0); bits.push(0); } - if(deviceStatus["rotary_switch_state"] == "Off") + if(deviceStatuses["rotary_switch_state"] == "Off") { bits.push(1); bits.push(0); @@ -699,7 +933,7 @@ exports.install = function(instance) { } //Dverový kontakt - if(deviceStatus["door_condition"] == "closed") + if(deviceStatuses["door_condition"] == "closed") { bits.push(0); } @@ -709,7 +943,7 @@ exports.install = function(instance) { } //EM - if(deviceStatus["em"] == "NOK") + if(deviceStatuses["em"] == "NOK") { bits.push(1); } @@ -719,7 +953,7 @@ exports.install = function(instance) { } //Teplomer - if(deviceStatus["temperature"] == "NOK") + if(deviceStatuses["temperature"] == "NOK") { bits.push(1); } @@ -729,7 +963,7 @@ exports.install = function(instance) { } //Batéria - if(deviceStatus["battery"] == "NOK") + if(deviceStatuses["battery"] == "NOK") { bits.push(1); } @@ -739,7 +973,7 @@ exports.install = function(instance) { } //Zdroj - if(deviceStatus["power_supply"] == "NOK") + if(deviceStatuses["power_supply"] == "NOK") { bits.push(1); } @@ -749,7 +983,7 @@ exports.install = function(instance) { } //MN - if(deviceStatus["master_node"] == "NOK") + if(deviceStatuses["master_node"] == "NOK") { bits.push(1); } @@ -759,7 +993,7 @@ exports.install = function(instance) { } //výpadok napätia na fáze - if(deviceStatus["no_voltage"] == "NOK") + if(deviceStatuses["no_voltage"] == "NOK") { bits.push(1); } @@ -768,7 +1002,7 @@ exports.install = function(instance) { bits.push(0); } - if(deviceStatus["twilight_sensor"] == "NOK") + if(deviceStatuses["twilight_sensor"] == "NOK") { bits.push(1); } @@ -783,7 +1017,7 @@ exports.install = function(instance) { bits.push(0); } - // console.log("calculateStateCode - deviceStatus", deviceStatus); + // console.log("calculateStateCode - deviceStatuses", deviceStatuses); // console.log("calculateStateCode", bits); let byte0 = bitwise.byte.write(bits.slice(0,8).reverse()); @@ -792,73 +1026,109 @@ exports.install = function(instance) { let byte = bytesToInt([byte1, byte0]); //console.log("calculateStateCode -------------------", byte); - + return byte; } - async function sendRvoStatus() { - - if(!FLOW.dbLoaded) return; - //if(SETTINGS === undefined) return; - - 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"]] - }; - - for (const phase of SETTINGS.no_voltage) dataToTb[`phase_${phase}_status`] = 0; - - dataToTb["status"] = checkRvoStatus(); - dataToTb["statecode"] = calculateStateCode(); - - console.log(dataToTb); - sendTelemetry(dataToTb, rvoTbName); - } - - - function checkRvoStatus() { + function checkFinalRVOStatus() { // we check if any of these pins values are 0 --> it means status RVO is "NOK" - // pinIndex 6 is door_condition - if it is opened in maintenance mode - status = OK + // pinIndex 6 is door_condition - if open in maintenance mode - status = OK + //set RVO state + let status = "OK"; - for (const [key, value] of Object.entries(deviceStatus)) { - if(["em", "twilight_sensor", "temperature"].includes(key) && value == "NOK") status = "NOK"; + if(deviceStatuses["em"] == "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"); + + status = "NOK"; + } + + //ak teplomer NOK, rvo nok + if(deviceStatuses["temperature"] == "NOK") + { + + let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: temperature status is NOK"); + if(writeToFile) errLogger.error("checkFinalRVOStatus: temperature status is NOK"); + + status = "NOK"; + } + 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) { if (previousValues[pinIndex] === 0) { - if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && SETTINGS.maintenance_mode) continue; + + if ((pinIndex === 6 || pinIndex === 'input1_01' || pinIndex === 'input1_05') && FLOW.OMS_maintenance_mode) continue; + + let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: value is 0"); + if(writeToFile) errLogger.error("checkFinalRVOStatus: value is 0", pinsData[pinIndex].type); + status = "NOK"; + break; } } } // battery status. If value is 1 - battery is NOK - if (previousValues[5] === 1) status = "NOK"; - if(!SETTINGS.masterNodeIsResponding) status = "NOK"; - if(SETTINGS.no_voltage.size > 0) status = "NOK"; + if (previousValues[5] === 1) + { + let writeToFile = errorHandler.processMessage("checkFinalRVOStatus: NOK status generated by battery"); + if(writeToFile) errLogger.error("checkFinalRVOStatus: NOK status generated by battery"); - console.log("rvo status",status) - return status; + status = "NOK"; + } + + //console.log("FLOW.OMS_masterNodeIsResponding", FLOW.OMS_masterNodeIsResponding); + + if(!FLOW.OMS_masterNodeIsResponding) + { + //errLogger.error("Master node is not responding"); + errorHandler.sendMessageToService("Master node is not responding"); + status = "NOK"; + + deviceStatuses["master_node"] = "NOK"; + } + else deviceStatuses["master_node"] = "OK"; + + //console.log("checkFinalRVOStatus", status); + if(FLOW.OMS_no_voltage.size > 0) + { + let writeToFile = errorHandler.processMessage("no voltage detected"); + if(writeToFile) errLogger.error("no voltage detected", FLOW.OMS_no_voltage); + + status = "NOK"; + + deviceStatuses["no_voltage"] = "NOK"; + } + else deviceStatuses["no_voltage"] = "OK"; + + if(status == "NOK") + { + sendTelemetry({status: "NOK"}, FLOW.OMS_rvo_tbname); + + return false; + } + + return true; } @@ -866,8 +1136,8 @@ exports.install = function(instance) { // we pass two values in case of websocket ==> switchLogic("relay1_03",1) ==> ["relay1_03",1] const switchLogic = (...args) => { - let values = {}; - let pinIndex, newPinValue, twilight; + let values = {status: "OK"}; + let dataToTb, pinIndex, newPinValue, twilight; //data from rsPort if(args.length == 1) @@ -885,14 +1155,13 @@ exports.install = function(instance) { } let obj = pinsData[pinIndex]; + if(obj == undefined) { previousValues[pinIndex] = newPinValue; - //logger.debug("dido-switchLogic ==> no pinIndex", pinIndex); return; } - //tbname is added to pinsData in initialSettings function let type = obj.type; let line = obj.line; let tbname = obj.tbname; @@ -904,22 +1173,22 @@ exports.install = function(instance) { //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 (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) - // { - // sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance , "state_of_main_switch"); - // values["status"] = "NOK"; + if(type === "!!!state_of_main_switch") + { + if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) + { + sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_off", {}, "", SEND_TO.tb, instance , "state_of_main_switch"); + values["status"] = "NOK"; - // deviceStatus["state_of_main_switch"] = "Off"; - // } - // else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) - // { - // sendNotification("switchLogic", rvoTbName, "main_switch_has_been_turned_on", {}, "", SEND_TO.tb, instance , "state_of_main_switch"); + deviceStatuses["state_of_main_switch"] = "Off"; + } + else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) + { + sendNotification("switchLogic", edgeName, "main_switch_has_been_turned_on", {}, "", SEND_TO.tb, instance , "state_of_main_switch"); - // deviceStatus["state_of_main_switch"] = "On"; - // } - // } + deviceStatuses["state_of_main_switch"] = "On"; + } + } //Prevádzkový mód if(type == "rotary_switch_state") @@ -954,51 +1223,54 @@ exports.install = function(instance) { if (pin2 == 0 && pin3 == 0) value = "Off"; if (pin2 == 0 && pin3 == 1) value = "Automatic"; - deviceStatus["rotary_switch_state"] = value; + deviceStatuses["rotary_switch_state"] = value; //automatic - profilu pre nody sa vykonavaju //ak je spracovany, a automatic - tak ho zapnem //ak nie je spracovany, iba profil zapisem - - if(pin2 != undefined && pin3 != undefined) instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "rotary_switch_state", value: value}); + + instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "rotary_switch_state", value: value}); //console.log("rotary_switch_state pin", pin2, pin3, value); } - //Zdroj - pin 4 else if (type === "power_supply") { if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { - sendNotification("switchLogic", rvoTbName, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + //sendNotification("switchLogic", edgeName, ERRWEIGHT.ALERT, "Power supply is not OK", "", SEND_TO.tb, instance); + sendNotification("switchLogic", edgeName, "power_supply_has_disconnected_input", {}, "", SEND_TO.tb, instance, "power_supply"); + values["status"] = "NOK"; - deviceStatus["power_supply"] = "NOK"; + deviceStatuses["power_supply"] = "NOK"; } else if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { - sendNotification("switchLogic", rvoTbName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); + //sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Power supply is is OK", "", SEND_TO.tb, instance); + sendNotification("switchLogic", edgeName, "power_supply_works_correctly", {}, "", SEND_TO.tb, instance, "power_supply"); - deviceStatus["power_supply"] = "OK"; + deviceStatuses["power_supply"] = "OK"; } } - //Batéria - pin 5 else if (type === "battery") { if (newPinValue === 1 && newPinValue !== previousValues[pinIndex]) { - sendNotification("switchLogic", rvoTbName, "battery_level_is_low", {}, "", SEND_TO.tb, instance, "battery_level"); + //sendNotification("switchLogic", edgeName, ERRWEIGHT.ERROR, "Battery is not OK", "", SEND_TO.tb, instance); + sendNotification("switchLogic", edgeName, "battery_level_is_low", {}, "", SEND_TO.tb, instance, "battery_level"); + values["status"] = "NOK"; - deviceStatus["battery"] = "NOK"; + deviceStatuses["battery"] = "NOK"; } else if (newPinValue === 0 && newPinValue !== previousValues[pinIndex]) { - sendNotification("switchLogic", rvoTbName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); + //sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Battery is OK", "", SEND_TO.tb, instance); + sendNotification("switchLogic", edgeName, "battery_level_is_ok", {}, "", SEND_TO.tb, instance, "battery_level"); - deviceStatus["battery"] = "OK"; + deviceStatuses["battery"] = "OK"; } } - //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' @@ -1006,35 +1278,48 @@ exports.install = function(instance) { { newPinValue === 0 ? value = "open" : value = "closed"; - if (value === "open" && SETTINGS.maintenance_mode) + if (newPinValue != previousValues[pinIndex]) { - sendNotification("switchLogic", rvoTbName, "door_opened", {}, "", SEND_TO.tb, instance, "rvo_door"); + //sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, `RVO door ${value}`, "", SEND_TO.tb, instance, "rvo_door"); + //TODO ? sendNotification("switchLogic", edgeName, "door_value", {value: value}, "", SEND_TO.tb, instance, "rvo_door"); } - if (value === "open" && !SETTINGS.maintenance_mode) + if (value === "open" && FLOW.OMS_maintenance_mode) { - sendNotification("switchLogic", rvoTbName, "door_opened_without_permission", {}, "", SEND_TO.tb, instance, "rvo_door"); + sendNotification("switchLogic", edgeName, "door_has_been_open", {}, "", SEND_TO.tb, instance, "rvo_door"); + } + + if (value === "open" && !FLOW.OMS_maintenance_mode) + { + //sendNotification("switchLogic", edgeName, ERRWEIGHT.WARNING, "RVO open door out of maintenance mode", "", SEND_TO.tb, instance); + sendNotification("switchLogic", edgeName, "door_has_been_open_without_permision_alarm_is_on", {}, "", SEND_TO.tb, instance, "rvo_door"); + values["status"] = "NOK"; + + //console.log(door_has_been_open_without_permision_alarm_is_on); // 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") turnAlarm("on"); + if(type === "door_condition") turnOnAlarm(); } if (value === "closed") { - if(alarmStatus == "ON") turnAlarm("off"); - sendNotification("switchLogic", rvoTbName, "door_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); + if(alarmStatus == "ON") turnOffAlarm(); + //turnOffAlarm(); + + sendNotification("switchLogic", edgeName, "door_has_been_closed", {}, "", SEND_TO.tb, instance, "rvo_door"); } - deviceStatus[type] = value; - } + deviceStatuses["door_condition"] = value; + } //lux sensor else if(type == "twilight_sensor") { - //! TODO - to show nok status, if lux value is not changing more then 10 times. + //! TODO - to show nok status, if lux value is not changing more then 10 times. From unipi for example comes value from 0-1000. //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. + values["status"] = "OK"; value = newPinValue; if(controller_type === 'lm') @@ -1059,25 +1344,27 @@ exports.install = function(instance) { if(set.size === 1 && !twilightError) { twilightError = true; + values["status"] = "NOK"; let value = twilight_sensor_array.shift(); - + //sendNotification("switchLogic", edgeName, ERRWEIGHT.ERROR, "Lux sensor error", {"Repeating value": value}, SEND_TO.tb, instance ); newPinValue = 0; } else if (set.size !== 1 && twilightError) { - //sendNotification("switchLogic", rvoTbName, ERRWEIGHT.NOTICE, "Lux sensor is working again", "", SEND_TO.tb, instance ); + //sendNotification("switchLogic", edgeName, ERRWEIGHT.NOTICE, "Lux sensor is working again", "", SEND_TO.tb, instance ); twilightError = false; twilight_sensor_array.shift(); - newPinValue = value; } else if (set.size === 1 && twilightError) { + values["status"] = "NOK"; twilight_sensor_array.shift(); newPinValue = 0; } } + let diff = twilight_sensor[ twilight_sensor.length - 1 ].timestamp - twilight_sensor[0].timestamp; if(diff >= twilight_sensor_interval * 60 * 1000) { @@ -1091,60 +1378,72 @@ exports.install = function(instance) { //else console.log("lux_sensor", value, diff); } } - 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 ); - } + //sendNotification("switchLogic", edgeName, ERRWEIGHT.INFO, `State of contactor ${line} is now ${value}`, "", SEND_TO.tb, instance ); - deviceStatus["state_of_contactor"][line] = value; + if(!(deviceStatuses["state_of_contactor"][line] == value)) + { + sendNotification("switchLogic", edgeName, "state_of_contactor_for_line", {line: line, value: value}, "", SEND_TO.tb, instance ); + } + else + { + deviceStatuses["state_of_contactor"][line] = value; + } //true, false if(value === "On") value = true; - else if(value === "Off") value = false; - - //TODO do we need to modify relays table with contactor value, if we do not use it on startup ?? - let dataChanged = false; - if(relaysData[line].contactor !== newPinValue) { - dataChanged = true; - relaysData[line].contactor = newPinValue; - } - - instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "reload_relays", line: line, value: value, dataChanged: dataChanged}); - reportLineStatus(line); + else if(value === "Off") value = false; //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 + dbRelays.modify({ contactor: newPinValue }).where("line", line).make(function(builder) { - // let dataChanged = false; - // if(relaysData[line].contactor != newPinValue) dataChanged = true; - // relaysData[line].contactor = newPinValue; // 0,1 + builder.callback(function(err, response) { - // //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); + /* + if(useTurnOffCounter) + { + turnOffCounter--; - // reportLineStatus(line); - // } - // else - // { - // errLogger.error("modify table relays failed", err); - // } + if(turnOffCounter <= 0) + { + useTurnOffCounter = false; + } + } + */ + + if(err == undefined) + { - // }); - // }); + let time = 0; + if(value) time = 1000 * 10;//10 sekund + + let dataChanged = false; + if(relaysData[line].contactor != value) dataChanged = true; + relaysData[line].contactor = value; + + //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); + } + + + }); + }); } - else if(type === "state_of_breaker") + if(type === "state_of_breaker") { let valueChanged = false; @@ -1168,7 +1467,7 @@ exports.install = function(instance) { instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: lineOnSameBraker[i]}); - deviceStatus["state_of_breaker"][lineOnSameBraker[i]] = value; + deviceStatuses["state_of_breaker"][lineOnSameBraker[i]] = value; reportLineStatus(lineOnSameBraker[i]); values[type] = value; @@ -1187,7 +1486,7 @@ exports.install = function(instance) { { instance.send(SEND_TO.cmd_manager, {sender: "dido_controller", cmd: "state_of_breaker", value: value, line: line + 3}); - deviceStatus["state_of_breaker"][line + 3] = value; + deviceStatuses["state_of_breaker"][line + 3] = value; reportLineStatus(line + 3); values[type] = value; @@ -1196,50 +1495,95 @@ exports.install = function(instance) { delete values[type]; } + } } if(value == "Off") values["status"] = "NOK"; - deviceStatus["state_of_breaker"][line] = value; + + deviceStatuses["state_of_breaker"][line] = value; reportLineStatus(line); } - else return; values[type] = value; + + //if(FLOW.OMS_rvo_tbname == tbname) values["statecode"] = calculateStateCode(); - if(type == "rotary_switch_state") + if(pinsData.hasOwnProperty(pinIndex)) { - if(SETTINGS.maintenance_mode) value = "maintenance"; - value = value.toLowerCase(); - values["power_mode"] = value; + 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(type == "state_of_contactor") valueChanged = true; + if(type == "rotary_switch_state") valueChanged = true; + if(type === "state_of_breaker") + { + //console.log(type, values, valueChanged); + } + + if(FLOW.OMS_rvo_tbname == "") + { + console.log("FLOW.OMS_rvo_tbname is EMPTY"); + } + + if(FLOW.OMS_rvo_tbname == tbname) + { + values["statecode"] = calculateStateCode(); + //console.log('**********************', type, values, valueChanged, FLOW.OMS_rvo_tbname, tbname); + } + + if(valueChanged) + { + sendTelemetry(values, tbname); + } + + if(type == "rotary_switch_state") + { + if(FLOW.OMS_maintenance_mode) value = "maintenance"; + value = value.toLowerCase(); + + let values = {}; + values["power_mode"] = value; + + sendTelemetry(values, tbname); + } + } + else + { + logger.debug("no pinIndex", pinsData[pinIndex], pinsData); } - if(newPinValue != previousValues[pinIndex]) previousValues[pinIndex] = newPinValue; - if(Object.keys(values).length > 0 && tbname) sendTelemetry(values, tbname); } - function sendTelemetry(values, tbname, date=Date.now()) { + function sendTelemetry(values, tbname) + { let dataToTb = { [tbname]: [ { - "ts": date, + "ts": Date.now(), "values": values } ] - }; + } - tbHandler.sendToTb(dataToTb, instance); + instance.send(SEND_TO.tb, dataToTb); } - - function isObject (item) { - return (typeof item === "object" && !Array.isArray(item) && item !== null); - } - -} //end of instance +} @@ -1516,52 +1860,25 @@ exports.install = function(instance) { //! pins_data --> from UNIPI // { -// 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 } +// '16': { pin: '16', type: 'twilight_sensor', line: 0 }, +// al_mswitch: { pin: 'al_mswitch', type: 'state_of_main_switch', line: 0 }, +// al_rswitch1: { pin: 'al_rswitch1', type: 'rotary_switch_state', line: 0 }, +// al_rswitch2: { pin: 'al_rswitch2', type: 'rotary_switch_state', line: 0 }, +// al_power: { pin: 'al_power', type: 'power_supply', line: 0 }, +// al_battery: { pin: 'al_battery', type: 'battery', line: 0 }, +// al_door: { pin: 'al_door', type: 'door_condition', line: 0 }, +// al_breaker1: { pin: 'al_breaker1', type: 'state_of_breaker', line: 1 }, +// al_breaker2: { pin: 'al_breaker2', type: 'state_of_breaker', line: 2 }, +// al_breaker3: { pin: 'al_breaker3', type: 'state_of_breaker', line: 3 }, +// al_breaker4: { pin: 'al_breaker4', type: 'state_of_breaker', line: 4 }, +// al_relay_1: { pin: 'al_relay_1', type: 'state_of_contactor', line: 1 }, +// al_relay_2: { pin: 'al_relay_2', type: 'state_of_contactor', line: 2 }, +// al_relay_3: { pin: 'al_relay_3', type: 'state_of_contactor', line: 3 }, +// al_relay_4: { pin: 'al_relay_4', type: 'state_of_contactor', line: 4 }, +// '28744F7791180257': { pin: '28744F7791180257', type: 'temperature', line: 0 } // } + //! relays_data // { // '0': { diff --git a/flow/empty.js b/flow/empty.js deleted file mode 100644 index 1e19c10..0000000 --- a/flow/empty.js +++ /dev/null @@ -1,43 +0,0 @@ -exports.id = 'id_bez_pomlcky'; -exports.title = 'nazov'; -exports.version = '1.0.0'; -exports.group = 'Worksys'; -exports.color = '#2134B0'; -exports.input = 1; -exports.output = ["red", "white"]; -exports.click = false; -exports.author = 'Daniel Segeš'; -exports.icon = 'bolt'; -exports.options = { edge: "undefined" }; -//exports.npm = ['serialport']; - -exports.html = `
-
-
-
CSV Import
-
-
-
`; - -exports.readme = `# readme`; - - - -exports.install = function(instance) { - - - - instance.on("close", () => { - - }) - - - instance.on("data", (flowdata) => { - - - }) - - -} - - diff --git a/flow/gettemperature.txt b/flow/gettemperature.txt deleted file mode 100644 index 12d9d60..0000000 --- a/flow/gettemperature.txt +++ /dev/null @@ -1,151 +0,0 @@ -exports.id = 'gettemperature'; -exports.title = 'Thermometer'; -exports.group = 'Worksys'; -exports.color = '#5CB36D'; -exports.version = '1.0.2'; -exports.input = 1; -exports.output = ["red", "white", "blue"]; -exports.author = 'Rastislav Kovac'; -exports.icon = 'thermometer-three-quarters'; - -exports.readme = `# Getting temperature values from RVO`; - -const { errLogger, logger, monitor } = require('./helper/logger'); - -const SEND_TO = { - debug: 0, - tb: 1, - di_do_controller: 2 -} - -//read temperature - frequency -let timeoutMin = 5;//minutes - - -exports.install = function(instance) { - - const { exec } = require('child_process'); - const { sendNotification } = require('./helper/notification_reporter.js'); - - let startRead; - let dataToTb; - let counter = 0; - - let SETTINGS; - let temperatureAddress = ""; - let rvoTbName = ""; - - - logger.debug(exports.title, "installed"); - - instance.on("close", function(){ - clearInterval(startRead); - }) - - - const main = function(){ - - try { - - if(SETTINGS.controller_type === "unipi") - { - clearInterval(startRead); - return; - } - - if(temperatureAddress === "") throw "gettemperature: temperatureAddress is not defined"; - - exec(`owread -C ${temperatureAddress}/temperature`, (error, stdout, stderr) => { - - if(!error) - { - parseData(stdout) - return; - } - - sendNotification("main", rvoTbName, "thermometer_is_not_responding", {}, {"Error": error}, SEND_TO.tb, instance, "thermometer"); - logger.debug("gettemparature", error); - monitor.info("Thermometer is not responding", error); - - dataToTb = { - [rvoTbName]: [ - { - "ts": Date.now(), - "values": { - "status": "NOK" - } - } - ] - } - - instance.send(SEND_TO.tb, dataToTb); - instance.send(SEND_TO.di_do_controller, {sender: "gettemperature", status: "NOK"}); - }); - - } - catch(err) { - errLogger.error(exports.title, err); - clearInterval(startRead); - } - } - - const parseData = function(data) { - - data = parseFloat(data); - logger.debug("gettemperature", data); - - if (!isNaN(data)){ - - - if(counter > 290) - { - instance.send(SEND_TO.debug, "[Get temperature component] - temperature data are comming again from RVO after more than 1 day break"); - sendNotification("parseData", rvoTbName, "thermometer_is_responding_again", {}, "", SEND_TO.tb, instance, "thermometer"); - } - - logger.debug("gettemperature", data); - - dataToTb = { - [rvoTbName]: [ - { - "ts": Date.now(), - "values": { - "temperature": Number(data.toFixed(2)), - "status": "OK" - } - } - ] - } - - instance.send(SEND_TO.tb, dataToTb); - instance.send(SEND_TO.di_do_controller, {sender: "gettemperature", status: "OK"}); - - counter = 0; - - } else { - - counter++; - monitor.info("gettemperature err", counter, data); - - //ked je problem 1 den - let day = 24 * 60 / timeoutMin; - if(counter > day && counter < day + 2) { - sendNotification("parseData", rvoTbName, "thermometer_sends_invalid_data", {}, "", SEND_TO.tb, instance, "thermometer"); - - instance.send(SEND_TO.debug, "[Get temperature component] - no temperature data from RVO for more than 1 day"); - instance.send(SEND_TO.di_do_controller, {sender: "gettemperature", status: "NOK"}); - } - - } - - } - - instance.on("data", _ => { - SETTINGS = FLOW.GLOBALS.settings; - temperatureAddress = SETTINGS.temperature_address; - rvoTbName = SETTINGS.rvoTbName; - startRead = setInterval(main, timeoutMin * 1000 * 60); - main(); - }) - -}; \ No newline at end of file diff --git a/flow/helper/DataToTbHandler.js b/flow/helper/DataToTbHandler.js index a89b75b..8fff312 100644 --- a/flow/helper/DataToTbHandler.js +++ b/flow/helper/DataToTbHandler.js @@ -1,11 +1,8 @@ -class DataToTbHandler { - +class DataToTbHandler +{ constructor(index) { this.index = index; - // time, after new value for the given key will be resend to tb (e.g. {status: "OK"}) - this.timeToHoldTbValue = 30*60; //30 minutes - this.previousValues = {}; this.debug = false; this.messageCounter = 0; @@ -13,33 +10,42 @@ class DataToTbHandler { this.sender = ""; } - dump() { + dump() + { console.log("----------------------------"); console.log("previousValues", this.previousValues); console.log("----------------------------"); } - setSender(sender) { + setSender(sender) + { this.sender = sender; } - isEmptyObject(obj) { - for (var name in obj) { - return false; + isEmptyObject( obj ) { + for ( var name in obj ) { + return false; } return true; } - sendToTb(dataToTb, instance) { + sendToTb(dataToTb, instance) + { + + if(!FLOW.OMS_brokerready) + { + return dataToTb; + } let keys = Object.keys(dataToTb); if(keys.length == 0) { - if(this.debug) console.log("sendToTb received empty object", dataToTb); + if(this.debug) console.log("sendToTb received epty object", dataToTb); return; } + let tbname = keys[0]; let ts; @@ -49,11 +55,16 @@ class DataToTbHandler { for(let i = 0; i < arrayOfValues.length; i++) { ts = arrayOfValues[i].ts; + + //console.log("sendToTb------------>before", arrayOfValues[i].values, tbname); + let values = this.prepareValuesForTb(tbname, ts, arrayOfValues[i].values); + //console.log("sendToTb------------>after", values); + if(!this.isEmptyObject(values)) { - arrayOfValuesToSend.push({ts: ts, values: values}); + arrayOfValuesToSend.push({ts: ts, values: values}); } } @@ -63,6 +74,17 @@ class DataToTbHandler { return; } + /* + let dataToTb = { + [tbname]: [ + { + "ts": Date.now(), + "values": values + } + ] + } + */ + this.messageCounter++; let dataToTbModified = { @@ -70,18 +92,26 @@ class DataToTbHandler { } //console.log(this.sender + " DATA SEND TO TB ", tbname, this.messageCounter, new Date(ts), dataToTbModified[tbname][0].values, this.instance); - //if(this.debug) console.log(this.sender + " DATA SEND TO TB ", this.index, tbname, arrayOfValuesToSend); + if(this.debug) console.log(this.sender + " DATA SEND TO TB ", this.index, tbname, arrayOfValuesToSend); + instance.send(this.index, dataToTbModified); } - getDiffTimestamp(key) { + getDiffTimestamp(key) + { + let seconds = 60*60;//1h + //seconds = 1;//for testing + //TODO set different value for given key!!! - //if(key == "status") this.timeToHoldTbValue = 2*60*60;//2h - return this.timeToHoldTbValue * 1000; + //if(key == "status") seconds = 2*60*60;//2h + + let timestampDiffToRemoveKey = seconds*1000; + + return timestampDiffToRemoveKey; } - prepareValuesForTb(tbname, timestamp, values) { - + prepareValuesForTb(tbname, timestamp, values) + { let keys = Object.keys(values); if(!this.previousValues.hasOwnProperty(tbname)) { @@ -130,4 +160,4 @@ class DataToTbHandler { } } -module.exports = DataToTbHandler; +module.exports = DataToTbHandler; \ No newline at end of file diff --git a/flow/helper/ErrorToServiceHandler.js b/flow/helper/ErrorToServiceHandler.js index 110ea8b..dc60446 100644 --- a/flow/helper/ErrorToServiceHandler.js +++ b/flow/helper/ErrorToServiceHandler.js @@ -97,9 +97,7 @@ class ErrorToServiceHandler console.log("ErrorToServiceHandler------------------------>send to service", dataToInfoSender); //TODO UGLY!!! - // if error occures too early FLOW.GLOBALs.settings.project_id is still undefined - // if(this.projects_id === undefined) this.projects_id = FLOW.GLOBALS.settings.project_id; - if(this.projects_id === undefined) return; + if(this.projects_id === undefined) this.projects_id = FLOW.OMS_projects_id; /* if(this.projects_id === undefined) diff --git a/flow/helper/error_reporter.js b/flow/helper/error_reporter.js new file mode 100644 index 0000000..2b84369 --- /dev/null +++ b/flow/helper/error_reporter.js @@ -0,0 +1,72 @@ + +//key is device, value = str +let sentValues= {}; + +function sendError(func, device, weight, str, extra, tb_output, instance, type) { + // if ((weight === ERRWEIGHT.DEBUG) && (instance.CONFIG.debug === false)){ + // return; // Allow debug messages only if CONFIG.debug is active + // } + + let key = device; + if(type != undefined) key = type; + + if(sentValues.hasOwnProperty(key)) + { + if(sentValues[key] == str) + { + return; + } + } + + sentValues[key] = str; + + let content = { + "type": weight, + "status": "new", + "source": { + "func":func, + "component":instance.id, + "component_name":instance.name, + "edge":device + }, + "message":str, + "message_data": extra + }; + + let msg = {}; + msg[device] = [ + { + "ts": Date.now(), + "values": { + "_event":content + } + } + ]; + + // Msg can be outputted from components only after configuration + /*if (canSendErrData()){ + sendBufferedErrors(); + } else { + bufferError(msg); + }*/ + instance.send(tb_output, msg); // Even if error server is unavailable, send this message to output, for other possible component connections + +} + + +let ERRWEIGHT = { + EMERGENCY: "emergency", // System unusable + ALERT: "alert", // Action must be taken immidiately + CRITICAL: "critical", // Component unable to function + ERROR: "error", // Error, but component able to recover from it + WARNING: "warning", // Possibility of error, system running futher + NOTICE: "notice", // Significant message but not an error, things user might want to know about + INFO: "informational", // Info + DEBUG: "debug" // Debug - only if CONFIG.debug is enabled +}; + + +module.exports = { + sendError, + ERRWEIGHT +} \ No newline at end of file diff --git a/flow/helper/error_reporting.js b/flow/helper/error_reporting.js new file mode 100644 index 0000000..62dace5 --- /dev/null +++ b/flow/helper/error_reporting.js @@ -0,0 +1,56 @@ +const ERRWEIGHT = { + EMERGENCY: "emergency", // System unusable + ALERT: "alert", // Action must be taken immidiately + CRITICAL: "critical", // Component unable to function + ERROR: "error", // Error, but component able to recover from it + WARNING: "warning", // Possibility of error, system running futher + NOTICE: "notice", // Significant message but not an error, things user might want to know about + INFO: "informational", // Info + DEBUG: "debug" // Debug - only if CONFIG.debug is enabled +}; + + + + +function sendError(func, device, weight, str, extra){ + if ((weight === ERRWEIGHT.DEBUG) && (instance.CONFIG.debug === false)){ + return; // Allow debug messages only if CONFIG.debug is active + } + + let content = { + "type": weight, + "status": "new", + "source": { + "func":func, + "component":instance.id, + "component_name":instance.name, + "edge":myEdge + }, + "message":str, + "message_data": extra + }; + let msg = {}; + msg[device] = [ + { + "ts": Date.now(), + "values": { + "_event":content + } + } + ]; + + // Msg can be outputted from components only after configuration + /*if (canSendErrData()){ + sendBufferedErrors(); + } else { + bufferError(msg); + }*/ + instance.send(0, msg); // Even if error server is unavailable, send this message to output, for other possible component connections + +} + + +module.exports = { + sendError, + ERRWEIGHT, +} \ No newline at end of file diff --git a/flow/helper/logger.js b/flow/helper/logger.js deleted file mode 100644 index 2585639..0000000 --- a/flow/helper/logger.js +++ /dev/null @@ -1,30 +0,0 @@ -//https://github.com/log4js-node/log4js-node/blob/master/examples/example.js -//file: { type: 'file', filename: path.join(__dirname, 'log/file.log') } - -var log4js = require("log4js"); -var path = require('path'); - -log4js.configure({ -appenders: { - errLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../../", 'err.txt') }, - monitorLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../../", 'monitor.txt') }, - console: { type: 'console' } -}, -categories: { - errLogs: { appenders: ['console', 'errLogs'], level: 'error' }, - monitorLogs: { appenders: ['console', 'monitorLogs'], level: 'trace' }, - //another: { appenders: ['console'], level: 'trace' }, - default: { appenders: ['console'], level: 'trace' } -} -}); - -const errLogger = log4js.getLogger("errLogs"); -const logger = log4js.getLogger(); -const monitor = log4js.getLogger("monitorLogs"); - -//USAGE -//logger.debug("text") -//monitor.info('info'); -//errLogger.error("some error"); - -module.exports = { errLogger, logger, monitor }; \ No newline at end of file diff --git a/flow/helper/notification_reporter.js b/flow/helper/notification_reporter.js index 61c0aef..84b2345 100644 --- a/flow/helper/notification_reporter.js +++ b/flow/helper/notification_reporter.js @@ -1,6 +1,10 @@ + +const { promisifyBuilder, makeMapFromDbResult } = require('./db_helper.js'); +const dbNotifications = TABLE("notifications"); + //key is device, value = str let sentValues= {}; -let notificationsData = null; +let notificationsData = {}; let ERRWEIGHT = { EMERGENCY: "emergency", // System unusable @@ -20,9 +24,12 @@ function getKey(map, val) { //https://stackoverflow.com/questions/41117799/string-interpolation-on-variable var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]); +async function initNotifications() +{ + let response = await promisifyBuilder(dbNotifications.find()); + notificationsData = makeMapFromDbResult(response, "key"); -function initNotification() { - notificationsData = FLOW.GLOBALS.notificationsData; + console.log("initNotifications done" ); } function sendNotification(func, device, key, params, extra, tb_output, instance, saveKey) { @@ -32,7 +39,7 @@ function sendNotification(func, device, key, params, extra, tb_output, instance, let storeToSendValues = true; if(saveKey == undefined) storeToSendValues = false; - let lang = FLOW.GLOBALS.settings.language; + let lang = FLOW.OMS_language; if(lang != "en" || lang != "sk") lang = "en"; let tpl = key; @@ -48,8 +55,7 @@ function sendNotification(func, device, key, params, extra, tb_output, instance, } else { - //console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); - console.error("sendNotification: Notifications: undefined key", key, func ); + console.error("sendNotification: Notifications: undefined key", key, func, notificationsData); return false; } @@ -85,7 +91,7 @@ function sendNotification(func, device, key, params, extra, tb_output, instance, if(storeToSendValues) sentValues[saveKey] = tpl; - let str = FLOW.GLOBALS.settings.rvo_name; + let str = FLOW.OMS_rvo_name; if(str != "") str = str + ": "; str = str + tpl; @@ -126,6 +132,6 @@ function sendNotification(func, device, key, params, extra, tb_output, instance, module.exports = { sendNotification, - ERRWEIGHT, - initNotification -} + initNotifications, + ERRWEIGHT +} \ No newline at end of file diff --git a/flow/helper/serialport_helper.js b/flow/helper/serialport_helper.js index 4a0edd5..a84ab84 100644 --- a/flow/helper/serialport_helper.js +++ b/flow/helper/serialport_helper.js @@ -1,100 +1,94 @@ const { exec } = require('child_process'); function openPort(port){ - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { - var callbackError = function(err) { - port.removeListener('error', callbackError); - port.removeListener('open', callbackError); + var callbackError = function(err) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackError); - reject(err.message); - }; + reject(err.message); + }; - var callbackOpen = function(data) { - port.removeListener('error', callbackError); - port.removeListener('open', callbackOpen); + var callbackOpen = function(data) { + port.removeListener('error', callbackError); + port.removeListener('open', callbackOpen); - resolve("port open: ok"); - }; + resolve("port open: ok"); + }; - port.on('error', callbackError); - port.on('open', callbackOpen); + port.on('error', callbackError); + port.on('open', callbackOpen); - port.open(); + port.open(); - }) -} + }) + } -function runSyncExec(command){ - return new Promise((resolve, reject) => { + function runSyncExec(command){ + return new Promise((resolve, reject) => { + + exec(command, (error, stdout, stderr) => { + if(error == null) resolve(stdout); + reject(error); + }); + + }) + } - exec(command, (error, stdout, stderr) => { - if(error == null) resolve(stdout); - reject(error); - }); + async function writeData(port, data, readbytes, timeout){ + return new Promise((resolve, reject) => { - }) -} + //readbytes = 0 = broadcast + if(readbytes == undefined) readbytes = 0; + if(timeout == undefined) timeout = 10000;//10s, default timeout MASTERA je 3s -async function writeData(port, data, readbytes, timeout){ - return new Promise((resolve, reject) => { + //cmd-manager mame http route POST / terminal a tomu sa tiez nastavuje timeout!!! + + var callback = function(data) { + rsPortReceivedData.push(...data); + let l = rsPortReceivedData.length; - // If first item in data array is 255, we just write broadcast command to rsPort - // We wait 3 seconds and resolve(["broadcast"]) - // It is important to resolve with array - if(data[0] == 255) { + if(l >= readbytes) + { + port.removeListener('data', callback); + + clearTimeout(t); + resolve(rsPortReceivedData); + } + }; + + port.removeListener('data', callback); + + let t = setTimeout(() => { + port.removeListener('data', callback); + + console.log("serialport helper: writeData TIMEOUT READING", rsPortReceivedData); + + reject("TIMEOUT READING"); + }, timeout); + + let rsPortReceivedData = []; + + if(readbytes > 0) port.on('data', callback); port.write(Buffer.from(data), function(err) { if (err) { + port.removeListener('data', callback); reject(err.message); } + + if(readbytes == 0) + { + resolve(rsPortReceivedData); + } + }); - - setTimeout(resolve, 3000, ["broadcast"]); - return; - } - - //cmd-manager mame http route POST / terminal a tomu sa tiez nastavuje timeout!!! - - var callback = function(data) { - rsPortReceivedData.push(...data); - let l = rsPortReceivedData.length; - - if(l >= readbytes) - { - port.removeListener('data', callback); - - clearTimeout(t); - resolve(rsPortReceivedData); - } - }; - - port.removeListener('data', callback); - - let t = setTimeout(() => { - port.removeListener('data', callback); - - console.log("serialport helper: writeData TIMEOUT READING", rsPortReceivedData); - - reject("TIMEOUT READING"); - }, timeout); - - let rsPortReceivedData = []; - - port.on('data', callback); - - port.write(Buffer.from(data), function(err) { - if (err) { - port.removeListener('data', callback); - reject(err.message); - } - - }); - }) + }) } module.exports = { openPort, runSyncExec, writeData -} +} \ No newline at end of file diff --git a/flow/infosender.js b/flow/infosender.js index c7afd83..a83499c 100644 --- a/flow/infosender.js +++ b/flow/infosender.js @@ -3,9 +3,12 @@ exports.title = 'Info sender'; exports.version = '1.0.0'; exports.group = 'Worksys'; exports.color = '#2134B0'; -exports.input = 2; +exports.input = 1; exports.output = 1 +exports.click = false; +exports.author = 'oms-is'; exports.icon = 'bolt'; +exports.options = { edge: "undefined" }; const { networkInterfaces } = require('os'); @@ -19,12 +22,13 @@ exports.html = `
exports.readme = `# send all data to projects.worksys.io, required to monitor status of controller(unipi)`; -exports.install = function(instance) { +const fs = require('fs'); +var path = require('path'); - let id; +exports.install = async function(instance) { + let allValues = {}; let sendAllValuesInterval; - let configured = false; let now = new Date(); console.log(exports.title, "INSTALLED", now.toLocaleString("sk-SK")); @@ -43,19 +47,23 @@ exports.install = function(instance) { } } } + function sendValues() { - if(!configured) return; + const id = FLOW.OMS_projects_id; if(Object.keys(allValues).length > 0) { - if(id) + if(id !== undefined) { delete allValues.__force__; let dataToSend = {...allValues}; dataToSend.id = id; dataToSend.ipAddresses = ipAddresses; + //dataToSend.notify_date = new Date().toISOString().slice(0, 19).replace('T', ' '); + + //console.log(exports.title, "------------>sendValues", dataToSend); instance.send(0, dataToSend); @@ -63,7 +71,7 @@ exports.install = function(instance) { } else { - console.log(exports.title, "unable to send data, no id"); + console.log(exports.title, "unable to send data, id is undefined"); } } @@ -73,14 +81,10 @@ exports.install = function(instance) { clearInterval(sendAllValuesInterval); }) - instance.on("0", _ => { - id = FLOW.GLOBALS.settings.project_id; - configured = true; - }) - - instance.on("1", flowdata => { + instance.on("data", (flowdata) => { allValues = { ...allValues, ...flowdata.data}; + //console.log("DATA RECEIVED", flowdata.data); //__force__ diff --git a/flow/modbus_citysys.js b/flow/modbus_citysys.js deleted file mode 100644 index d038b69..0000000 --- a/flow/modbus_citysys.js +++ /dev/null @@ -1,1127 +0,0 @@ -exports.id = 'modbus_citysys'; -exports.title = 'Modbus_citysys'; -exports.version = '1.0.0'; -exports.group = 'Worksys'; -exports.color = '#2134B0'; -exports.input = 1; -exports.output = ["red", "white", "blue", "orange"]; -exports.click = false; -exports.author = 'Jakub Klena'; -exports.icon = 'bolt'; -exports.options = { edge: "undefined" }; - -exports.html = `
-
-
-
Edge TB Name
-
-
-
`; - -exports.readme = `# Energomonitor -## Outputs - - - *Red* - ERROR output (can connect to filewriter or something) - - *White* - STATUS output (answers to your commands, ERRORS and WARNINGS from your commands go both to this and to their own outputs, so they get logged) - - *Blue* - TB output (pure data for TB) -`; - - -const instanceSendTo = { - error: 0, - debug: 1, - tb: 2, - di_do_controller: 3 -} - -const DataToTbHandler = require('./helper/DataToTbHandler.js'); -const { sendNotification } = require('./helper/notification_reporter.js'); -const dbRelays = TABLE("relays"); -const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); -let tbname; - -async function loadSettings() -{ - //todo global FLOW.OMS_edgeName is making problem, so we load it here as well, it should not be - let responseRelays = await promisifyBuilder(dbRelays.find()); - FLOW.OMS_edgeName = responseRelays[0]["tbname"]; - tbname = FLOW.OMS_edgeName; -} - -loadSettings(); - -exports.install = function(instance) { - const SerialPort = require('serialport'); - const { exec } = require('child_process'); - const fs = require("fs"); - const filepath = F.path.root("saved_data/modbus_settings"); - const backup_filepath = F.path.root("saved_data/modbus_settings_backup"); - - const ErrorToServiceHandler = require('./helper/ErrorToServiceHandler.js'); - const errorHandler = new ErrorToServiceHandler(); - - let receivedDataArray = []; - - - instance.CONFIG = { - "isRunning": false, - "debug": true, - "timeoutTime": 10000, - "msgWaitTime": 1000, - "port": "/dev/ttymxc1", - //"port_options": "stty -F /dev/ttymxc1 115200 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke" - "port_options": "stty -F /dev/ttymxc1 9600 min 1 time 5 ignbrk -brkint -icrnl -imaxbel -opost -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke" - }; - - let PRIVATEVARS = { - "errBuffer": [], // Buffer for error messages - "tbBuffer": [], // Buffer for TB push messages - "device_index": 0, - "cmd_index": -1, - "devices": [ - /*{ - "name": "Elektrometer 1", - "tb_name": "EOzNMgZ9n43qPbjXmy7zwdA2DKdYvW5e6pxGRrVa", - "type": "EM111", - "address": 1, - "data":[], - "cmd":[], - "timeoutcount":0, - "status":"virtual" - },*/ - // { - // "name": "Elektrometer 2", - // "tb_name": "pJX1ObgmqGZ54DMyYL7aDdkEVdve38WKRzwjNrQ9", - // "type": "EM111", - // "address": 2, - // "data":[], - // "cmd":[], - // "timeoutcount":0, - // "status":"virtual" - // }, - // { - // "name": "Elektrometer 3", - // "tb_name": "XRvmwNz8QPblKp41GD7lKVkJrLVYoBO92dMegn6W", - // "type": "EM111", - // "address": 3, - // "data":[], - // "cmd":[], - // "timeoutcount":0, - // "status":"virtual" - // }, - // { - // "name": "Elektrometer 4", - // "tb_name": "oRO8rjaBDy21qPQJzW7oD9ApK3xmNleVZg9Ed4Gw", - // "type": "EM111", - // "address": 4, - // "data":[], - // "cmd":[], - // "timeoutcount":0, - // "status":"virtual" - // }, - { - "name": "Elektrometer 1", - "tb_name": "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV", - "type": "EM340", - "address": 1, - "data":[], - "cmd":[], - "timeoutcount":0, - "status":"virtual" - } - ], - "cmd_tables": [ - { - "type":"EM340", - "cmd":[ - { - "name": "Voltage L1", - "tb_name": "a", - "register": 0, - "size": 2, - "multiplier": 0.1 - }, - { - "name": "Voltage L2", - "tb_name": "b", - "register": 2, - "size": 2, - "multiplier": 0.1 - }, - { - "name": "Voltage L3", - "tb_name": "c", - "register": 4, - "size": 2, - "multiplier": 0.1 - }, - { - "name": "Current L1", - "tb_name": "d", - "register": 12, - "size": 2, - "multiplier": 0.001 - }, - { - "name": "Current L2", - "tb_name": "e", - "register": 14, - "size": 2, - "multiplier": 0.001 - }, - { - "name": "Current L3", - "tb_name": "f", - "register": 16, - "size": 2, - "multiplier": 0.001 - } - - - // { - // "name": "Power factor", - // "tb_name": "power_factor", - // "register": 14, - // "size": 1, - // "multiplier": 0.001 - // }, - // { - // "name": "Frequency", - // "tb_name": "frequency", - // "register": 15, - // "size": 1, - // "multiplier": 0.1 - // }, - // { - // "name": "Energy", - // "tb_name": "consumption", - // "register": 16, - // "size": 2, - // "multiplier": 0.1 - // } - ] - } - ] - }; - - let ERRWEIGHT = { - EMERGENCY: "emergency", // System unusable - ALERT: "alert", // Action must be taken immidiately - CRITICAL: "critical", // Component unable to function - ERROR: "error", // Error, but component able to recover from it - WARNING: "warning", // Possibility of error, system running futher - NOTICE: "notice", // Significant message but not an error, things user might want to know about - INFO: "informational", // Info - DEBUG: "debug" // Debug - only if CONFIG.debug is enabled - }; - - instance.currentData = function(){ - let resp = []; - for (let f = 0; f < PRIVATEVARS.devices.length; f++){ - let dev = PRIVATEVARS.devices[f]; - for (let e = 0; e < dev.data.length; e++){ - let d = dev.data[e]; - resp.push({ - "name": dev.name+" - "+d.name, - "value": d.value - }); - } - } - return resp; - }; - - instance.configList = function(){ - let resp = []; - /*let data = PRIVATEVARS.feeds; - for (let a = 0; a < data.length; a++){ - for (let i = 0; i < instance.CONFIG.feeds.length; i++){ - let feed = instance.CONFIG.feeds[i]; - if (feed.name === data[a].id){ - for (let b = 0; b < data[a].streams.length; b++){ - for (let j = 0; j < feed.streams.length; j++){ - let stream = feed.streams[j]; - if (stream.name === data[a].streams[b].id){ - data[a].streams[b]["exists"] = true; - data[a].streams[b]["currently"] = stream; - } - } - } - } - } - } - resp.push({ - "name":"Device manager", - "icon":"tasks", - "_show":false, - "js_func":"energoDevManager", - "data": data - });*/ - - return resp; - } - - let timeoutInterval = null; - let msgWaitInterval = null; - let port = null; - let myEdge = "undefined"; - let starter = null; - instance.status("Loading...", "red"); - - - instance.availableCommands = [ - { - "name": "Status", - "cmd": "qStatus", - "icon": "stream", - "func": function(body){ - let a = true; - if (timeoutInterval === null){ - a = false; - } - let b = true; - if (msgWaitInterval === null){ - b = false; - } - let st = { - "isRunning":instance.CONFIG.isRunning, - "timeoutInterval":a, - "msgWaitInterval":b, - "CONFIG":instance.CONFIG - }; - return { - "type": "ok", - "timestamp": humanReadableTimeAndDate(), - "resp": st - }; - } - }, - { - "name": "Start Reading", - "cmd": "sStart", - "icon": "play", - "func": function(body){ - /*if (running === false){ - startCmdWaitInterval(); - running = true; - return "Reading started !"; - } else { - return "Reading already active !"; - }*/ - return { - "type": "ok", - "timestamp": humanReadableTimeAndDate(), - "resp": "WIP" - }; - } - }, - { - "name": "Stop Reading", - "cmd": "sStop", - "icon": "stop", - "func": function(body){ - /*if (running === true){ - stopCmdWaitInterval(); - stopTimeoutInterval(); - running = false; - return "Reading stopped !"; - } else { - return "Reading already inactive !"; - }*/ - return { - "type": "ok", - "timestamp": humanReadableTimeAndDate(), - "resp": "WIP" - }; - } - }, - { - "name": "Read current data", - "cmd": "qCurrentData", - "icon": "chart-bar", - "func": function(body){ - let resp = instance.currentData(); - return { - "type": "ok", - "timestamp": humanReadableTimeAndDate(), - "resp": resp - }; - } - }, - { - "name": "Save current config", - "cmd": "saveConfig", - "icon": "save", - "func": function(body){ - - instance.set("config", JSON.stringify(instance.CONFIG)); - instance.set("private", JSON.stringify(PRIVATEVARS)); - return { - "type": "ok", - "timestamp": humanReadableTimeAndDate(), - "resp": "done" - }; - } - }, - { - "name": "Toggle debug", - "cmd": "sDebug", - "icon": "comment-dots", - "func": function(body){ - - if (instance.CONFIG.debug){ - instance.CONFIG.debug = false; - instance.set("config", JSON.stringify(instance.CONFIG)); - - return { - "type": "ok", - "timestamp": humanReadableTimeAndDate(), - "resp": "debug OFF" - }; - } else { - instance.CONFIG.debug = true; - instance.set("config", JSON.stringify(instance.CONFIG)); - - return { - "type": "ok", - "timestamp": humanReadableTimeAndDate(), - "resp": "debug ON" - }; - } - - } - } - ]; - - - - function saveData(){ - if (checkFile(filepath)){ - let content = undefined; - try { - content = fs.readFileSync(filepath); - } catch (err){ - console.log("saveData", myEdge, ERRWEIGHT.ERROR, "Unable to read original configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message}); - - //sendError("saveData", myEdge, ERRWEIGHT.ERROR, "Unable to read original configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message}); - } - - if (content !== undefined){ - try { - fs.writeFileSync(backup_filepath, content, "utf8"); - } catch (err) { - //sendError("saveData", myEdge, ERRWEIGHT.ERROR, "Unable to save backup of configuration !", {"name":instance.name, "id":instance.id, "file":backup_filepath, "err":err.message}); - console.log("saveData", myEdge, ERRWEIGHT.ERROR, "Unable to save backup of configuration !", {"name":instance.name, "id":instance.id, "file":backup_filepath, "err":err.message}); - } - } - } - - let a = { - "config":instance.CONFIG, - "private":PRIVATEVARS - }; - - try { - fs.writeFileSync(filepath, JSON.stringify(a), "utf8"); - } catch (err) { - //sendError("saveData", myEdge, ERRWEIGHT.CRITICAL, "Unable to save configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message}); - console.log("saveData", myEdge, ERRWEIGHT.CRITICAL, "Unable to save configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message}); - } - } - - function loadData(){ - let content = undefined; - //console.log(filepath); - if (checkFile(filepath)){ - try { - content = fs.readFileSync(filepath); - } catch (err){ - //sendError("loadData", myEdge, ERRWEIGHT.ERROR, "Unable to read original configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message}); - console.log("loadData", myEdge, ERRWEIGHT.ERROR, "Unable to read original configuration !", {"name":instance.name, "id":instance.id, "file":filepath, "err":err.message}); - } - } else { - if (checkFile(backup_filepath)){ - try { - content = fs.readFileSync(backup_filepath); - } catch (err){ - //sendError("loadData", myEdge, ERRWEIGHT.CRITICAL, "Unable to read backup configuration !", {"name":instance.name, "id":instance.id, "file":backup_filepath, "err":err.message}); - console.log("loadData", myEdge, ERRWEIGHT.CRITICAL, "Unable to read backup configuration !", {"name":instance.name, "id":instance.id, "file":backup_filepath, "err":err.message}); - } - if (content !== undefined){ - //sendError("loadData", myEdge, ERRWEIGHT.WARNING, "No configuration, loading from backup !", {"name":instance.name, "id":instance.id}); - console.log("loadData", myEdge, ERRWEIGHT.WARNING, "No configuration, loading from backup !", {"name":instance.name, "id":instance.id}); - } - } else { - //sendError("loadData", myEdge, ERRWEIGHT.CRITICAL, "No configuration, not even backup !", {"name":instance.name, "id":instance.id}); - console.log("loadData", myEdge, ERRWEIGHT.CRITICAL, "No configuration, not even backup !", {"name":instance.name, "id":instance.id, "filepath": filepath}); - } - } - - - - if (content !== undefined){ - let a = JSON.parse(content); - instance.send(instanceSendTo.debug, a); - let c = a.config; - let p = a.private; - - - if (c === undefined){ - //sendError("loadData", myEdge, ERRWEIGHT.CRITICAL, "Configuration not found !", {"name":instance.name, "id":instance.id}); - console.log("loadData", myEdge, ERRWEIGHT.CRITICAL, "Configuration not found !", {"name":instance.name, "id":instance.id}); - instance.status("Error - no config", "red"); - } else if (p === undefined){ - //sendError("loadData", myEdge, ERRWEIGHT.CRITICAL, "Privatevars not found !", {"name":instance.name, "id":instance.id}); - console.log("loadData", myEdge, ERRWEIGHT.CRITICAL, "Privatevars not found !", {"name":instance.name, "id":instance.id}); - instance.status("Error - no private vars", "red"); - } else { - instance.CONFIG = c; - PRIVATEVARS = p; - - // Daj kazdemu device jeho tabulku prikazu - for (let i = 0; i < PRIVATEVARS.devices.length; i++){ - let device = PRIVATEVARS.devices[i]; - for (let j = 0; j < PRIVATEVARS.cmd_tables.length; j++){ - let table = PRIVATEVARS.cmd_tables[j]; - - if (device.type === table.type){ - PRIVATEVARS.devices[i].cmd = table.cmd; - } - } - } - - if (myEdge === "undefined"){ - instance.status("Unconfigured", "red"); - } else { - instance.status("Running", "green"); - startCmdWaitInterval(); - - instance.CONFIG.isRunning = true; - console.log("modbus loaded: ", PRIVATEVARS.devices); - } - } - } - } - - function checkFile(name){ - try { - fs.accessSync(name, fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK); - return true; - } catch (err) { - return false; - } - } - - //Zapina slucku vycitavania dat - function readDeviceData(){ - stopCmdWaitInterval(); - - // let tbname = FLOW.OMS_edgeName; - - // Check port existance - if (port === null) - { - port = new SerialPort(instance.CONFIG.port); - - port.on('error', function(err) { - //logger.debug("rsPort opened error - failed", err.message); - //instance.send(instanceSendTo.debug, err.message); - - errorHandler.sendMessageToService( exports.title + " MODBUS RS485 open - failed: " + err.message); - }) - - port.on('open', function() { - - console.log("--->MODBUS RS485 READY - port opened"); - - exec("sudo halfduplex /dev/ttymxc1", (error, stdout, stderr) => { - instance.send(instanceSendTo.debug, {"err": error}); - - if (error) { - console.log("--->MODBUS RS485", error, stderr); - errorHandler.sendMessageToService( exports.title + " sudo halfduplex /dev/ttymxc1 - failed: " + error); - } - - }); - - exec(instance.CONFIG.port_options, (error, stdout, stderr) => { - instance.send(instanceSendTo.debug, {"stdout":stdout,"stderr":stderr,"err":error}); - - if (error) { - console.log("--->MODBUS RS485", error, stderr); - errorHandler.sendMessageToService( exports.title + " " + instance.CONFIG.port_options + " - failed: " + error); - } - - }); - - }); - - port.on('data', receivedData); - - //sendError("readDeviceData", myEdge, ERRWEIGHT.DEBUG, "Serial port open!", {}); - //console.log("-->MODBUS readDeviceData", myEdge, ERRWEIGHT.DEBUG, "Serial port open!", {}); - - startCmdWaitInterval(); - return; // Cakame na port aby sa spravne otvoril a rozbehol - } - - - // Skontroluj existenciu device listu - if (PRIVATEVARS.devices.length > 0){ - // Ponastavuj indexy - PRIVATEVARS.cmd_index++; - if (PRIVATEVARS.cmd_index >= PRIVATEVARS.devices[PRIVATEVARS.device_index].cmd.length){ - // Kedže všetky príkazy pre daný device sú vybavené, je treba odoslat vyčítané data do TB - updateDataInTB(); - - PRIVATEVARS.cmd_index = 0; - PRIVATEVARS.device_index++; - - if (PRIVATEVARS.device_index >= PRIVATEVARS.devices.length){ - PRIVATEVARS.device_index = 0; - } - } - - let device = PRIVATEVARS.devices[PRIVATEVARS.device_index]; - - // Skontroluj existenciu príkazú pre daný device type - if (device.cmd.length < 1){ - //sendError("readDeviceData", tbname, ERRWEIGHT.ERROR, "No commands for this device type !", {"type": device.type}); - console.log("readDeviceData", tbname, ERRWEIGHT.ERROR, "No commands for this device type !", {"type": device.type}); - startCmdWaitInterval(); - return; - } - - // Odešli nasledujúci príkaz - sendCommand(); - - } else { - instance.CONFIG.isRunning = false; - //sendError("readDeviceData", myEdge, ERRWEIGHT.CRITICAL, "Modbus has no devices registered!", {}); - console.log("modbus_citys: readDeviceData", myEdge, ERRWEIGHT.CRITICAL, "Modbus has no devices registered!", {}); - } - } - - function readingTimeouted(){ - stopCmdWaitInterval(); - stopTimeoutInterval(); - - // let tbname = FLOW.OMS_edgeName; - - let device = PRIVATEVARS.devices[PRIVATEVARS.device_index]; - let com = device.cmd[PRIVATEVARS.cmd_index]; - //sendError("readingTimeouted", tbame, ERRWEIGHT.WARNING, "Reading timeouted !", {"device": device.address, "cmd": com.register}); - console.log("modbus_citys: readingTimeouted", tbname, ERRWEIGHT.WARNING, "Reading timeouted !", {"device": device.address, "cmd": com.register}); - - device.timeoutcount++; - //console.log("device.timeoutcount", device.timeoutcount); - if (device.timeoutcount === 16) - { - - //sendError("modbus_citys: readingTimeouted", tbname, ERRWEIGHT.CRITICAL, "Electrometer is not responding - reading timeouted", ""); - sendNotification("modbus_citys: readingTimeouted", tbname, "electrometer_is_not_responding", {}, "", instanceSendTo.tb, instance ); - - if (device.status === "OK"){ - device.status === "NOK"; - } - } - - startCmdWaitInterval(); - } - - function receivedData(data){ - - //let array = [...data]; - //console.log("received data", array); - - // let tbname = FLOW.OMS_edgeName; - - //!if received data are less than 9 bytes, we store it in array variable and return. than we concatenate second incoming - // data and then length of array is 9 - receivedDataArray = [...receivedDataArray, ...data]; - //if (array.length < 9) return; - let l = receivedDataArray.length; - //console.log("received",receivedDataArray, l) - - if ( l < 7 || l > 9 || l == 8 ) return; - - let device = PRIVATEVARS.devices[PRIVATEVARS.device_index]; - let com = device.cmd[PRIVATEVARS.cmd_index]; - - if (device.timeoutcount > 16) { - //sendError("Modbus_citysys: receivedData", tbname, ERRWEIGHT.NOTICE, "Electrometer is responding again", ""); - sendNotification("modbus_citys: receivedData", tbname, "electrometer_is_responding_again", {}, "", instanceSendTo.tb, instance ); - } - - device.timeoutcount = 0; - - if ((l == 7 && com.size != 1) || ( l == 9 && com.size != 2)) return; - - stopTimeoutInterval(); - - //sendError("receivedData", tbname, ERRWEIGHT.DEBUG, "Received data !", {"cmd": receivedDataArray}); - //console.log("receivedData", tbname, ERRWEIGHT.DEBUG, "Received data !", {"cmd": receivedDataArray}); - - // Skontroluj či sedí počet bytú v správe - //console.log("com size", com.size*2, "array2", receivedDataArray[2]); - if (receivedDataArray[2] !== (com.size*2)){ - //sendError("receivedData", tbname, ERRWEIGHT.ERROR, "Received data of incorrect size !", {"expected": (com.size*2), "received": receivedDataArray[2], "cmd": com.register, "whole_msg": receivedDataArray}); - console.log("modbus_citys: receivedData", tbname, ERRWEIGHT.ERROR, "Received data of incorrect size !", {"expected": (com.size*2), "received": receivedDataArray[2], "cmd": com.register, "whole_msg": receivedDataArray}); - startTimeoutInterval(); - } else { - // Konvertuj raw data na human readable - - let v = (receivedDataArray[3] << 8) | receivedDataArray[4]; - if (com.size == 2){ - v = v | (receivedDataArray[5] << 24) | (receivedDataArray[6] << 16); - } - v = Math.round((v * com.multiplier) * 100) / 100; - - - // Pokad device nemá ešte žádné hodnoty vyčítané, pushni túto hodnotu do pola - if (device.data.length < 1){ - device.data.push({ // Vždy ked správne zakomunikuje obnov status na OK - "changed": true, - "name": "status", - "value": "OK" - }); - device.data.push({ - "changed": true, - "name": com.tb_name, - "value": v - }); - } else { - // Kedže už neco v poli má, kukni sa či je tam aj táto hodnota - let found = false; - for (let i = 0; i < device.data.length; i++){ - let d = device.data[i]; - if (d.name == "status"){ // Ked natrefíš na status (vždy tam musí byt) prepíš ho na OK lebo zakomunikoval správne - device.data[i].changed = true; - device.data[i].value = "OK"; - } - - if (d.name == com.tb_name){ - found = true; - device.data[i].changed = true; - device.data[i].value = v; - } - } - - // Pole existuje, ale táto hodnota tam neni, pridaj ju - if (found === false){ - device.data.push({ - "changed": true, - "name": com.tb_name, - "value": v - }); - } - } - - //Správne sme prijali odpoveď, je čas na další msg - startCmdWaitInterval(); - } - //console.log('received data array', receivedDataArray); - receivedDataArray = []; - } - - function updateDataInTB(){ - let device = PRIVATEVARS.devices[PRIVATEVARS.device_index]; - - // console.log("---- MB device", device); - // console.log("---MB device data", device.data); - - let values = ""; - for (let i = 0; i < device.data.length; i++){ - let data = device.data[i]; - if (data.changed){ - if (values !== ""){ - values += ", "; - } - - if (data.name === "status"){ - values += "\""+data.name+"\":\""+data.value+"\""; - // This makes sure, that if this device doesn’t respond even once in next reading cycle, it will be marked as NOK - device.data[i].changed = true; - device.data[i].value = "NOK"; - } else { - values += "\""+data.name+"\":"+data.value; - device.data[i].changed = false; - } - } - - } - - //console.log("values modbus", values); - - - if (values !== ""){ - - // let tbname = FLOW.OMS_edgeName; - // if(tbname == "" || tbname === undefined ) - // { - // console.log("!!!!!!FLOW.OMS_edgeName is empty - 1"); - // return; - // } - - let tbmsg = "{\"" + tbname + "\":[{\"ts\":"+Date.now()+", \"values\":{"+values+"}}] }"; - tbmsg = JSON.parse(tbmsg); - - values = tbmsg[tbname][0]["values"]; - - //console.log("modbus", Object.keys(values)); - - //sum Phase_1_power, Phase_2_power, Phase_3_power (if one of them is undefined, we handle it) - const numOr0 = n => isNaN(n) ? 0 : n; - let calculated_total_power = [values["Phase_1_power"], values["Phase_2_power"], values["Phase_3_power"]].reduce((a, b) => numOr0(a) + numOr0(b)); - values["total_power"] = parseFloat(calculated_total_power.toFixed(2)); - tbmsg[tbname][0]["values"] = values; - - 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(); - - if(values[singleValue] == 0) - { - sendNotification("modbus_citys: updateDataInTB", tbname, "no_voltage_detected_on_phase", {phase: phase}, "", instanceSendTo.tb, instance, "voltage" + phase ); - - FLOW.OMS_no_voltage.add(phase); - } - else - { - FLOW.OMS_no_voltage.delete(phase); - sendNotification("modbus_citys: updateDataInTB", tbname, "voltage_on_phase_has_been_restored", {phase: phase}, "", instanceSendTo.tb, instance, "voltage" + phase); - } - - } - }) - - sendThingsBoard(tbmsg); - } - } - - - let electrometerNotResponding = 0; - function sendCommand(){ - let device = PRIVATEVARS.devices[PRIVATEVARS.device_index]; - let com = device.cmd[PRIVATEVARS.cmd_index]; - let array = [device.address, 3, ((com.register >> 8) & 0xFF), (com.register & 0xFF), ((com.size >> 8) & 0xFF), (com.size & 0xFF)]; - array = modbusCRC(array); - - //console.log('---device--', device); - //console.log('---device type--', device.type); - - //sendError("sendCommand", device.tb_name, ERRWEIGHT.DEBUG, "Sending command !", {"cmd": array}); - //console.log("sendCommand", device.tb_name, ERRWEIGHT.DEBUG, "Sending command !", {"cmd": array}); - - // let tbname = FLOW.OMS_edgeName; - // if(tbname == "" || tbname === undefined ) - // { - // console.log("!!!!!!FLOW.OMS_edgeName is empty - 2"); - // return; - // } - - startTimeoutInterval(); - port.write(Buffer.from(array), function(err) { - - //! poslany command - //console.log("poslany tento commant", array, err, device.type); - - if (err) { - stopTimeoutInterval(); - stopCmdWaitInterval(); - - - // elektromer neodpoveda viac ako 5 minut (15 commands za minutu sa posiela) - if (device.type === "EM111" || device.type === "EM340") - { - electrometerNotResponding++; - - if (electrometerNotResponding > 15 && electrometerNotResponding < 17) - { - - //sendError("Modbus_citys: sendCommand", tbname, ERRWEIGHT.CRITICAL, "Electrometer is not responding", {"err": err.message, "info": "No response more than 5 minutes"}); - sendNotification("modbus_citys: sendCommand", tbname, "electrometer_is_not_responding", {}, {"err": err.message, "info": "No response more than 5 minutes"}, instanceSendTo.tb, instance ); - - let tbmsg = { - [tbname]: [ - { - "ts": Date.now(), - "values": { - "status": "NOK" - } - } - ] - } - - sendThingsBoard(tbmsg) - } - } - - - return; - } - - if (device.type === "EM111") - { - if (electrometerNotResponding > 15) - { - //sendError("Modbus_citys: sendCommand", tbname, ERRWEIGHT.NOTICE, "Electrometer is responding again", ""); - sendNotification("modbus_citys: sendCommand", tbname, "electrometer_is_responding_again", {}, "", instanceSendTo.tb, instance ); - } - electrometerNotResponding = 0; - - } - }); - } - - function modbusCRC(array){ - let crc = 0xFFFF; - for (let i = 0; i < array.length; i++){ - let b = array[i]; - crc = crc ^ b; - - for (let j = 8; j>0; j--){ - if ((crc & 0x0001) != 0){ - crc = crc >> 1; - crc = crc ^ 0xA001; - } else { - crc = crc >> 1; - } - } - } - - array.push(crc & 0xFF); - array.push((crc >> 8) & 0xFF); - - return array; - } - - - instance.on('data', function(flowdata) { - - console.log("flowdata on data", flowdata); - sendStatus({"CONFIG": instance.CONFIG, "PRIVATEVARS":PRIVATEVARS}) - - }); - - instance.reconfigure = function() { - - //TODO remove ftom options - myEdge = instance.options.edge; - if (starter === null){ - starter = setInterval(function(){ - loadData(); - clearInterval(starter); - starter = null; - }, 5000); - } - }; - - instance.close = function() { - // close sockets and such - }; - - function sendError(func, device, weight, str, extra){ - if ((weight === ERRWEIGHT.DEBUG) && (instance.CONFIG.debug === false)){ - return; // Allow debug messages only if CONFIG.debug is active - } - - let content = { - "type": weight, - "status": "new", - "source": { - "func":func, - "component":instance.id, - "component_name":instance.name, - "edge":myEdge - }, - "message":str, - "message_data": extra - }; - let msg = {}; - msg[device] = [ - { - "ts": Date.now(), - "values": { - "_event":content - } - } - ]; - - // Msg can be outputted from components only after configuration - /*if (canSendErrData()){ - sendBufferedErrors(); - } else { - bufferError(msg); - }*/ - instance.send(instanceSendTo.tb, msg); // Even if error server is unavailable, send this message to output, for other possible component connections - - - - function sendBufferedErrors(){ - if (PRIVATEVARS.errBuffer === undefined){ - console.log("errBuffer undefined"); - console.log("private: ", PRIVATEVARS); - } - console.log("errBuffer size: ", PRIVATEVARS.errBuffer.length); - if (PRIVATEVARS.errBuffer.length > 0){ - for (let i = 0; i < PRIVATEVARS.errBuffer.length; i++){ - instance.send(instanceSendTo.error, PRIVATEVARS.errBuffer[i]); - } - PRIVATEVARS.errBuffer = []; //Clear the buffer - saveData(); - } - } - - function bufferError(msg){ - PRIVATEVARS.errBuffer.push(msg); - saveData(); - } - } - - function canSendErrData(){ - //if (FLOW.errServerAvailable) - return true; - //else - // return false; - } - - function sendStatus(str){ - instance.send(instanceSendTo.debug, str); - } - - function sendThingsBoard(obj){ - // Msg can be outputted from components only after configuration - /*if (canSendTbData()){ - sendBufferedTB(); - } else { - console.log("cant send data"); - bufferTB(str); - }*/ - //console.log("send thingsboard", str); - - //console.log("FLOW.OMS_edgeName", FLOW.OMS_edgeName, obj); - - if(obj.hasOwnProperty(FLOW.OMS_edgeName) && FLOW.OMS_edgeName != "") - { - //send it to di_do_controller - instance.send(instanceSendTo.di_do_controller, {sender: "modbus_citysys", tbdata: obj}); - } - // else - { - instance.send(instanceSendTo.tb, obj); // Even if TB server is unavailable, send this message to output, for other possible component connections - } - - //instance.send(2, str); // Even if TB server is unavailable, send this message to output, for other possible component connections - - - function sendBufferedTB(){ - if (PRIVATEVARS.tbBuffer.length > 0){ - console.log("sending buffered: ", PRIVATEVARS.tbBuffer.length ); - for (let i = 0; i < PRIVATEVARS.tbBuffer.length; i++){ - instance.send(instanceSendTo.tb, PRIVATEVARS.tbBuffer[i]); - } - PRIVATEVARS.tbBuffer = []; //Clear the buffer - saveData(); - } - } - - function bufferTB(str){ - PRIVATEVARS.tbBuffer.push(str); - saveData(); - } - } - - function canSendTbData(){ - //if (FLOW.tbAvailable) - return true; - //else - // return false; - } - - function startTimeoutInterval(){ - if (!timeoutInterval){ - timeoutInterval = setInterval(readingTimeouted, instance.CONFIG.timeoutTime); - } - } - - function stopTimeoutInterval(){ - if (timeoutInterval){ - clearInterval(timeoutInterval); - timeoutInterval = null; - } - } - - function startCmdWaitInterval(){ - if (!msgWaitInterval){ - msgWaitInterval = setInterval(readDeviceData, instance.CONFIG.msgWaitTime); - } - } - - function stopCmdWaitInterval(){ - if (msgWaitInterval){ - clearInterval(msgWaitInterval); - msgWaitInterval = null; - } - } - - instance.on('options', instance.reconfigure); - instance.reconfigure(); - - // LAST SECTION FOR COMMON FUNCTIONS - function humanReadableTimeAndDate(){ - let date_ob = new Date(); - - let date = ("0" + date_ob.getDate()).slice(-2); - let month = ("0" + (date_ob.getMonth() + 1)).slice(-2); - let year = date_ob.getFullYear(); - - let hours = ("0" + date_ob.getHours()).slice(-2); - let minutes = ("0" + date_ob.getMinutes()).slice(-2); - let seconds = ("0" + date_ob.getSeconds()).slice(-2); - - return date+"."+month+"."+year+" "+hours+":"+minutes+":"+seconds; - } - - if (starter === null){ - starter = setInterval(function(){ - loadData(); - clearInterval(starter); - starter = null; - }, 5000); - } - - //setTimeout(loadData, 5000); -}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/flow/modbus_reader.js b/flow/modbus_reader.js new file mode 100644 index 0000000..f34ec9a --- /dev/null +++ b/flow/modbus_reader.js @@ -0,0 +1,348 @@ +exports.id = 'modbus_reader'; +exports.title = 'Modbus reader'; +exports.version = '2.0.0'; +exports.group = 'Worksys'; +exports.color = '#2134B0'; +exports.output = ["red", "white", "yellow"]; +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 { sendNotification } = require('./helper/notification_reporter'); + +const DELAY_BETWEEN_DEVICES = 10000; + +const SEND_TO = { + debug: 0, + dido_controller: 1, + tb: 2 +}; + +//to handle NOK and OK sendNotifications s +const numberOfNotResponding = {}; +let tbName = null; +let mainSocket; + + +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; + + // we need to go always around for all devices. So we need index value, device address, as well as number of registers for single device + this.deviceAddress = null; // device address (1 - EM340 and 2 for twilight_sensor) + this.indexInDeviceConfig = 0; // first item in deviceConfig + this.lengthOfActualDeviceStream = null; + this.device = null; + + // lampSwitchNotification helper variables + this.onNotificationSent = false; + this.offNotificationSent = false; + + 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, 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') { + 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 - DELAY_BETWEEN_DEVICES; // to make sure readout always runs in timeoutinterval we substract DELAY_BETWEEN_DEVICES + }) + + }; + + 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, DELAY_BETWEEN_DEVICES); + } + + 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, {}, "", SEND_TO.tb, instance); + delete numberOfNotResponding[obj.device]; + } + + obj.transformResponse(resp, register); + + //obj.errors = 0; + obj.index++; + obj.readAnotherRegister(); + + }).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 + + //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, {}, "", SEND_TO.tb, instance); + numberOfNotResponding[obj.device] = 1; + } + + obj.errors = 0; + numberOfNotResponding[obj.device] += 1; + } + + console.error(require('util').inspect(arguments, { + depth: null + })) + + // 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}); + obj.allValues = {}; + } + obj.index++; + obj.readAnotherRegister(); + }) + + }; + + readAnotherRegister = () => { + if(this.index < this.lengthOfActualDeviceStream) setTimeout(this.readRegisters, 0); + else this.setNewStream(); + } + + transformResponse = (response, register) => { + + 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(register, tbName, tbAttribute, response, a.multiplier, value); + + // if(tbName == undefined) return; + + if(this.index + 1 < this.lengthOfActualDeviceStream) + { + this.allValues[tbAttribute] = value; + return; + } + + const values = { + ...this.allValues, + [tbAttribute]: value, + }; + + this.checkNullVoltage(values); + this.lampSwitchNotification(values); + + instance.send(SEND_TO.dido_controller, {values: values}); + + this.allValues = {}; + break; + } + + } + + } + + setNewStream = () => + { + if(this.lengthOfActualDeviceStream == this.index) + { + if(this.indexInDeviceConfig + 1 == deviceConfig.length) + { + this.indexInDeviceConfig = 0; + } + else + { + this.indexInDeviceConfig += 1; + } + + this.getActualStreamAndDevice(); + } + } + + 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_reader: checkNullVoltage", tbName, "no_voltage_on_phase", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase ); + // console.log('no voltage') + } + else + { + FLOW.OMS_no_voltage.delete(phase); + // console.log('voltage detected') + sendNotification("modbus_reader: checkNullVoltage", tbName, "voltage_on_phase_restored", {phase: phase}, "", SEND_TO.tb, instance, "voltage" + phase); + } + } + }) + } + + /** + * function sends notification to slack and to tb, if EM total_power value changes more than 500. This should show, that RVO lamps has been switched on or off + */ + lampSwitchNotification = (values) => { + + if(!values.hasOwnProperty("total_power")) return; + + const actualTotalPower = values.total_power; + if(actualTotalPower > 600 && this.onNotificationSent == false) + { + sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_on", {}, "", SEND_TO.tb, instance); + this.onNotificationSent = true; + this.offNotificationSent = false; + } + else if(actualTotalPower <= 600 && this.offNotificationSent == false) + { + sendNotification("modbus_reader: lampSwitchNotification", tbName, "lamps_have_turned_off", {}, "", SEND_TO.tb, instance); + this.onNotificationSent = false; + this.offNotificationSent = true; + } + } + + } + + const isObjectEmpty = (objectName) => { + return Object.keys(objectName).length === 0 && objectName.constructor === Object; + } + + setTimeout(() => { + + mainSocket = new SocketWithClients(); + tbName = FLOW.OMS_rvo_tbname; + + // this notification is to show, that flow (unipi) has been restarted + sendNotification("modbus_reader", tbName, "flow_restart", {}, "", SEND_TO.slack, instance); + + }, 25000); + +} + diff --git a/flow/monitorcpu.js b/flow/monitorcpu.js deleted file mode 100644 index 0e906d1..0000000 --- a/flow/monitorcpu.js +++ /dev/null @@ -1,107 +0,0 @@ -exports.id = 'monitorcpu'; -exports.title = 'CPU'; -exports.version = '1.0.0'; -exports.author = 'Peter Širka'; -exports.group = 'Monitoring'; -exports.color = '#F6BB42'; -exports.output = 1; -exports.icon = 'microchip'; -exports.options = { enabled: true }; -exports.click = true; -exports.readme = `# CPU monitoring - -This component monitors CPU \`% percentage\` consumption in Linux systems. It uses \`mpstat\` command. - -__Data Example__: - -\`\`\`javascript -{ - cpu: 30, // percentage - cores: [4, 60, 0], // percentage - count: 3 // count of cores -} -\`\`\``; - -exports.html = `
-
-
-
@(Interval in milliseconds)
-
-
-
`; - -exports.install = function(instance) { - - var fields = ['CPU', '%idle']; - var current = { cores: [], cpu: 0, count: 0 }; - var proc = null; - var tproc = null; - - instance.custom.kill = function() { - if (proc) { - proc.kill('SIGKILL'); - proc = null; - } - }; - - instance.custom.run = function() { - - if (tproc) { - clearTimeout(tproc); - tproc = null; - } - - instance.custom.kill(); - proc = require('child_process').spawn('mpstat', ['-P', 'ALL', 10]); - proc.stdout.on('data', U.streamer('\n\n', instance.custom.process)); - proc.stdout.on('error', function(e) { - instance.error(e); - instance.custom.kill(); - tproc = setTimeout(instance.custom.run, instance.options.interval || 5000); - }); - }; - - instance.custom.process = function(chunk) { - current.cpu = 0; - chunk.toString('utf8').parseTerminal(fields, instance.custom.parse); - current.count = current.cores.length; - if (current.count) { - instance.send2(current); - instance.custom.status(); - } - }; - - instance.custom.parse = function(values) { - var val = 100 - values[1].parseFloat2(); - if (values[0] === 'all') - current.cpu = val; - else - current.cores[+values[0]] = val; - }; - - instance.custom.status = function() { - if (instance.options.enabled) - instance.status(current.cpu.floor(1) + '%'); - else - instance.status('Disabled', 'red'); - }; - - instance.on('click', function() { - instance.options.enabled = !instance.options.enabled; - instance.custom.status(); - if (instance.options.enabled) - instance.custom.run(); - else - instance.custom.kill(); - }); - - instance.on('close', function() { - instance.custom.kill(); - if (tproc) { - clearTimeout(tproc); - tproc = null; - } - }); - - setTimeout(instance.custom.run, 1000); -}; \ No newline at end of file diff --git a/flow/mqtt.js b/flow/mqtt.js deleted file mode 100644 index e34c940..0000000 --- a/flow/mqtt.js +++ /dev/null @@ -1,441 +0,0 @@ -exports.id = 'mqtt'; -exports.title = 'MQTT broker'; -exports.group = 'MQTT'; -exports.color = '#888600'; -exports.version = '1.0.1'; -exports.icon = 'exchange'; -exports.input = true; -exports.output = 0; -exports.author = 'Martin Smola'; -exports.variables = true; -exports.options = { host: '127.0.0.1', port: 1883 }; -exports.traffic = false; -exports.npm = ['mqtt']; - -exports.html = `
-
-
-
Hostname or IP address
-
-
-
Port
-
-
-
-
-
@(Client id)
-
@(Supports variables, example: \`client_{device-id}\`)
-
@(Secure (ssl))
-
-
-
-
-
-
@(Require Authorization)
-
-
-
-
-
@(Username)
-
-
-
@(Password)
-
-
-
-
-
-
@(LWT)
-
-
-
-
-
@(Last will topic)
-
@(Supports variables, example: \`lwt/{device-id}\`)
-
-
-
@(Last will message)
-
@(Supports variables, example: \`{device-id} is offline\`)
-
-
-
-`; - -exports.readme = ` -# MQTT Broker - -## Input -Allows to change connection programaticaly -\`\`\`javascipt -{ - host: '1.2.3.4', - port: '', - secure: true/false, - username: 'john', - password: 'X', - lwttopic: '', - lwtmessage: '', - clientid: '' -} -\`\`\` -`; - -var MQTT_BROKERS = []; -var mqtt; - -global.MQTT = {}; - -exports.install = function(instance) { - - var broker; - - mqtt = require('mqtt'); - - instance.on('data', function(flowdata){ - var data= flowdata.data; - var options = instance.options; - - if (data.host && data.port) - return instance.custom.reconfigure(data, options); - - if (data.close === true) - instance.close(NOOP); - }); - - instance.custom.reconfigure = function(o, old_options) { - - if (old_options) - MQTT_BROKERS = MQTT_BROKERS.remove(function(b){ - return b.id === old_options.id; - }); - - var options = instance.options; - - if (!options.host || !options.port) { - instance.status('Not configured', 'red'); - return; - } - - options.id = (options.username || '') + '@' + options.host + ':' + options.port; - - if (broker) { - broker.close(); - EMIT('mqtt.brokers.status', 'reconfigured', old_options.id, options.id); - } - - instance.custom.createBroker(); - }; - - instance.custom.createBroker = function() { - - ON('mqtt.brokers.status', brokerstatus); - - var o = instance.options; - var opts = { - host: o.host, - port: o.port, - id: o.id, - secure: o.secure, - rejectUnauthorized: false, - reconnectPeriod: 3000, - resubscribe: false - }; - - if (o.auth) { - opts.username = o.username; - opts.password = o.password; - } - - if (o.lwt) { - opts.will = { - topic: instance.arg(o.lwttopic), - payload: instance.arg(o.lwtmessage) - } - } - - if (o.clientid) - opts.clientId = instance.arg(o.clientid); - - broker = new Broker(opts); - MQTT_BROKERS.push(broker); - - instance.status('Ready'); - }; - - instance.close = function(done) { - - broker && broker.close(function() { - MQTT_BROKERS = MQTT_BROKERS.remove('id', instance.options.id); - EMIT('mqtt.brokers.status', 'removed', instance.options.id); - }); - - OFF('mqtt.brokers.status', brokerstatus); - - done(); - }; - - function brokerstatus(status, brokerid, err) { - if (brokerid !== instance.options.id) - return; - - switch (status) { - case 'connecting': - instance.status('Connecting', '#a6c3ff'); - break; - case 'connected': - instance.status('Connected', 'green'); - break; - case 'disconnected': - instance.status('Disconnected', 'red'); - break; - case 'connectionfailed': - instance.status('Connection failed', 'red'); - break; - case 'error': - instance.error('MQTT Error, ID: ' + instance.id + '\n ' + err); - break; - } - } - - instance.on('options', instance.custom.reconfigure); - instance.custom.reconfigure(); -}; - -FLOW.trigger('mqtt.brokers', function(next) { - var brokers = ['']; - MQTT_BROKERS.forEach(n => brokers.push(n.id)); - next(brokers); -}); - -MQTT.add = function(brokerid, componentid) { - var broker = MQTT_BROKERS.findItem('id', brokerid); - - if (broker) - broker.add(componentid); -}; - -MQTT.remove = function(brokerid, componentid) { - var broker = MQTT_BROKERS.findItem('id', brokerid); - broker && broker.remove(componentid); -}; - -MQTT.publish = function(brokerid, topic, data, options) { - var broker = MQTT_BROKERS.findItem('id', brokerid); - if (broker) - broker.publish(topic, data, options); - else - EMIT('mqtt.brokers.status', 'error', brokerid, 'No such broker'); -}; - -MQTT.subscribe = function(brokerid, componentid, topic, qos) { - var broker = MQTT_BROKERS.findItem('id', brokerid); - - if (!broker) - return; - - broker.add(componentid); - broker.subscribe(componentid, topic, qos); -}; - -MQTT.unsubscribe = function(brokerid, componentid, topic, qos) { - var broker = MQTT_BROKERS.findItem('id', brokerid); - if (!broker) - return; - - broker.unsubscribe(componentid, topic); - broker.remove(componentid); -}; - -MQTT.broker = function(brokerid) { - return MQTT_BROKERS.findItem('id', brokerid); -}; - -/* - - https://github.com/mqttjs/MQTT.js/blob/master/examples/client/secure-client.js - -*/ - -/* - TODO - - - add `birth` and `last will and testament` messages - - add options to self.client.connect(broker [,options]); - credentials, certificate etc. - - -*/ - -function Broker(options) { - var self = this; - - if (!options.host || !options.port) - return false; - - self.connecting = false; - self.connected = false; - self.closing = false; - self.components = []; - self.subscribtions = {}; - self.id = options.id; - self.options = options; - setTimeout(function() { - EMIT('mqtt.brokers.status', 'new', self.id); - }, 500); - return self; -} - -Broker.prototype.connect = function() { - - var self = this; - if (self.connected || self.connecting) - return EMIT('mqtt.brokers.status', self.connected ? 'connected' : 'connecting', self.id); - - self.connecting = true; - var broker = self.options.secure ? 'mqtts://' : 'mqtt://' + self.options.host + ':' + self.options.port; - - EMIT('mqtt.brokers.status', 'connecting', self.id); - - self.client = mqtt.connect(broker, self.options); - - self.client.on('connect', function() { - self.connecting = false; - self.connected = true; - if (self.reconnecting) { - EMIT('mqtt.brokers.status', 'reconnected', self.id); - self.reconnecting = false; - self.resubscribe(); - } - EMIT('mqtt.brokers.status', 'connected', self.id); - }); - - self.client.on('reconnect', function() { - self.connecting = true; - self.connected = false; - self.reconnecting = true; - EMIT('mqtt.brokers.status', 'connecting', self.id); - }); - - self.client.on('message', function(topic, message) { - message = message.toString(); - if (message[0] === '{') { - TRY(function() { - message = JSON.parse(message); - }, () => FLOW.debug('MQTT: Error parsing data', message)); - } - EMIT('mqtt.brokers.message', self.id, topic, message); - }); - - self.client.on('close', function(err) { - if (err && err.toString().indexOf('Error')) { - self.connecting = false; - self.connected = false; - EMIT('mqtt.brokers.status', 'error', self.id, err.code); - } - - if (self.connected || !self.connecting) { - self.connected = false; - EMIT('mqtt.brokers.status', 'disconnected', self.id); - } else if (self.connecting) { - self.connecting = false; - EMIT('mqtt.brokers.status', 'connectionfailed', self.id); - } - }); - - self.client.on('error', function(err) { - - if (self.connecting) { - self.client.end(); - self.connecting = false; - EMIT('mqtt.brokers.status', 'error', self.id, err); - } - }); - -}; - -Broker.prototype.disconnect = function(reconnect) { - var self = this; - if (!self.closing) - self.close(function(){ - reconnect && self.connect(); - }); -}; - -Broker.prototype.close = function(callback) { - var self = this; - self.closing = true; - - if ((self.connected || self.connecting) && self.client && self.client.end) - self.client.end(true, cb); - else - cb(); - - function cb() { - EMIT('mqtt.brokers.status', 'disconnected', self.id); - self.client && self.client.removeAllListeners(); - self.components = []; - self.client = null; - callback && callback(); - } -}; - -Broker.prototype.subscribe = function(componentid, topic) { - var self = this; - self.subscribtions[topic] = self.subscribtions[topic] || []; - if (self.subscribtions[topic].indexOf(componentid) > -1) - return; - self.client.subscribe(topic); - self.subscribtions[topic].push(componentid); -}; - -Broker.prototype.resubscribe = function() { - var self = this; - var topics = Object.keys(self.subscribtions); - for (var i = 0; i < topics.length; i++) - self.client.subscribe(topics[i]); -}; - -Broker.prototype.unsubscribe = function(componentid, topic) { - var self = this; - var sub = self.subscribtions[topic]; - if (sub) { - self.subscribtions[topic] = sub.remove(componentid); - self.client.connected && !self.subscribtions[topic].length && self.client.unsubscribe(topic); - } -}; - -Broker.prototype.publish = function(topic, data, options) { - var self = this; - if (!self.connected) - return; - - if (typeof(data) === 'object') { - options.qos = parseInt(data.qos || options.qos); - options.retain = data.retain || options.retain; - topic = data.topic || topic; - data.payload && (data = typeof(data.payload) === 'string' ? data.payload : JSON.stringify(data.payload)); - } - - if (options.qos !== 0 || options.qos !== 1 || options.qos !== 2) - options.qos = null; - - if (typeof(data) !== 'string') - data = JSON.stringify(data); - - self.client.publish(topic, data || '', options); -}; - -Broker.prototype.add = function(componentid) { - var self = this; - self.components.indexOf(componentid) === -1 && self.components.push(componentid); - self.connect(); -}; - -Broker.prototype.remove = function(componentid) { - var self = this; - self.components = self.components.remove(componentid); - !self.components.length && self.disconnect(); -}; diff --git a/flow/mqtt_listener.js b/flow/mqtt_listener.js deleted file mode 100644 index b9d778d..0000000 --- a/flow/mqtt_listener.js +++ /dev/null @@ -1,171 +0,0 @@ -exports.id = 'mqttlistener'; -exports.title = 'MQTT listener'; -exports.group = 'MQTT'; -exports.color = '#888600'; -exports.version = '1.0.0'; -exports.icon = 'sign-out'; -exports.input = 1; -exports.output = ["red", "white"]; -exports.author = 'Rastislav Kovac'; -exports.options = { host: "", port: 1883, clientid: "", username: "" }; -//exports.npm = ['mqtt', 'streamroller']; - - -exports.html = `
-
-
-
Hostname or IP address
-
-
-
Port
-
-
-
-
-
@(Client id)
-
-
-
@(Username)
-
-
-
`; - - -exports.readme = ` -# MQTT processor - -Version 1.0.0 - -It serves as a client and subscribes to 'rpc' topic. It receives rpc calls from kovobel-prod01, which receives it from platform. - -`; - -const instanceSendTo = { - debug: 0, - rpcCall: 1, -} - - -exports.install = function(instance) { - - - const mqtt = require("mqtt"); - - instance.on('options', loadNodes); - - - function loadNodes() - { - - if(instance.options.host == "") - { - instance.status('No configuration', 'red'); - } - else - { - var o = instance.options; - opts = { - host: o.host, - port: o.port, - clientId: o.clientid, - rejectUnauthorized: false, - resubscribe: true - }; - - connectToServer(); - - } - - } - - function connectToServer() - { - var url = "mqtt://" + opts.host + ":" + opts.port; - console.log("MQTT URL: ", url); - - client = mqtt.connect(url, opts); - - client.on('connect', function() { - instance.status("Connected", "green"); - client.subscribe('rpc', function (err) { - if (!err) { - client.publish('rpc', 'Hello mqtt'); - console.log('message published'); - } - }); - }); - - client.on('reconnect', function() { - instance.status("Reconnecting", "yellow"); - }); - - client.on('message', function(topic, message) { - // message is type of buffer - message = message.toString(); - - // instance.send(1, message); - // return; - - if (message[0] === '{') { - - try { - message = JSON.parse(message); - - if (Object.keys(message).length < 2 || !Object.keys(message).includes("message")) return; - - message.message = JSON.parse(message.message); - instance.send(instanceSendTo.rpcCall, message); - - } catch (e) { - instance.debug(`MQTT: Error parsing data, ${e}`); - } - } - - }); - - client.on('close', function(err) { - if (err && err.toString().indexOf('Error')) { - instance.status("Err: "+err.code, "red"); - instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts }); - } else { - instance.status("Disconnected", "red"); - instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts }); - } - }); - - client.on('error', function(err) { - instance.status("Err: "+ err.code, "red"); - instance.send(instanceSendTo.debug, {"message":"Broker ERROR signal received !", "error":err, "opt":opts }); - - }); - } - - - //set opts accortding to options - instance.reconfigure = function() { - - var o = instance.options; - opts = { - host: o.host, - port: o.port, - clientId: o.clientid, - rejectUnauthorized: false, - resubscribe: true - }; - - connectToServer(); - }; - - instance.close = function(done) { - client.end(); - }; - - - loadNodes(); - - instance.on('options', instance.reconfigure); - instance.reconfigure(); -}; - - - diff --git a/flow/mqttprocessor.js b/flow/mqttprocessor.js deleted file mode 100644 index 1bf050c..0000000 --- a/flow/mqttprocessor.js +++ /dev/null @@ -1,317 +0,0 @@ -exports.id = 'mqttprocessor'; -exports.title = 'MQTT processor'; -exports.group = 'MQTT'; -exports.color = '#888600'; -exports.version = '1.0.0'; -exports.icon = 'sign-out'; -exports.input = 1; -exports.output = ["red", "white", "blue"]; -exports.author = 'Rastislav Kovac'; -exports.options = { host: "", port: 1883, clientid: "", username: "" }; -//exports.npm = ['mqtt', 'streamroller']; - - -exports.html = `
-
-
-
Hostname or IP address
-
-
-
Port
-
-
-
-
-
@(Client id)
-
-
-
@(Username)
-
-
-
`; - - -exports.readme = ` -# MQTT processor - -Version 1.0.0 - -It serves as a client, listens and subscribes to nodes in citysys configuration. -Is able to send messages to flow (as rpc calls from platform) - -Added: -- database collections, -- rpc response -`; - -const instanceSendTo = { - debug: 0, - rpcCall: 1, - cmdManager: 2 -} - -const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); -const mqtt = require('mqtt'); - - -//topics = {joqRYBVL30k9eQWOlZ5qwpD2KJpNEmA6gPxXzwaM: 'lamp_697/brightness'} --> to get topic from dataToTb tb name. -const topics = {}; -//tbNames = {'lamp_697/brightness': joqRYBVL30k9eQWOlZ5qwpD2KJpNEmA6gPxXzwaM } -const tbNames = {}; - - -exports.install = function(instance) { - - let client = null; - let opts = null; - - instance.on('options', loadNodes); - - - async function loadNodes() - { - const nodes = TABLE("nodes"); - let nodesData = await promisifyBuilder(nodes.find()); - - nodesData.map(item => { - const value = 'lamp_' + item.node + '/brightness'; - const key = item.tbname; - topics[key] = value; - tbNames[value] = key; - }) - - // console.log('******* -------- ', topics); - // console.log('******* -------- ', tbNames); - - if(instance.options.host == "") - { - instance.status('No configuration', 'red'); - } - else - { - var o = instance.options; - opts = { - host: o.host, - port: o.port, - clientId: o.clientid, - rejectUnauthorized: false, - resubscribe: true - }; - - connectToServer(); - - } - - } - - function connectToServer() - { - var url = "mqtt://" + opts.host + ":" + opts.port; - console.log("MQTT URL: ", url); - - client = mqtt.connect(url, opts); - - client.on('connect', function() { - instance.status("Connected", "green"); - // array of subscribed topics ==> Object.values(topics) - client.subscribe(Object.values(topics), function (err) { - if (!err) { - client.publish('presence', 'Hello mqtt'); - console.log('message published'); - } - }); - }); - - client.on('reconnect', function() { - instance.status("Reconnecting", "yellow"); - }); - - client.on('message', function(topic, message) { - // message is type of buffer - message = message.toString(); - - if (message[0] === '{') { - - try { - message = JSON.parse(message); - - // we ensure to process messages only with 1 key ==> {'lamp_698/brightness': 20 } and if topic is in topics - if (Object.keys(message).length > 1 || !Object.values(topics).includes(topic)) return; - - instance.send(0, {message:message, topic:topic}) - - const date = Date.now(); - const tbName = tbNames[topic]; - - - const transformToRpc = { - "topic": "v1/gateway/rpc", - "content": { - // 'device' is not needed here in 3rd party systems - "device": "KjbN4q7JPZmexgdnz2yKQ98YAWwO0Q3BMX6ERLoV", - "data": { - // 'id' is not needed here - "id": 5, - "method": "set_command", - "params": { - "entities": [ - { - "entity_type": "street_luminaire", - "tb_name": tbName - } - ], - "command": "dimming", - "payload": { - "value": message[topic] - } - } - } - } - } - - - instance.send(instanceSendTo.cmdManager, transformToRpc); - - } catch (e) { - instance.debug(`MQTT: Error parsing data, ${e}`); - } - } - - }); - - client.on('close', function(err) { - if (err && err.toString().indexOf('Error')) { - instance.status("Err: "+err.code, "red"); - instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts }); - } else { - instance.status("Disconnected", "red"); - instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts }); - } - }); - - client.on('error', function(err) { - instance.status("Err: "+ err.code, "red"); - instance.send(instanceSendTo.debug, {"message":"Broker ERROR signal received !", "error":err, "opt":opts }); - - }); - } - - - //set opts accortding to options - instance.reconfigure = function() { - - var o = instance.options; - opts = { - host: o.host, - port: o.port, - clientId: o.clientid, - rejectUnauthorized: false, - resubscribe: true - }; - - connectToServer(); - }; - - - instance.on('data', function(data) { - const value = data.data; - const nodeTbName = Object.keys(value)[0]; - - // tbnames of all lamps - const nodes = Object.values(tbNames); - - if(nodes.includes(nodeTbName)) - { - - if(value[nodeTbName][0].values.hasOwnProperty('dimming')) - { - const key = nodeTbName; - const tbValues = value[key][0].values; - - Object.keys(tbValues).map(item => { - if(item != 'dimming') - { - delete tbValues[item]; - } - }) - - const topic = topics[key]; - // console.log('---- ***********', key, topic) - // console.log('^^^^^^^^^^^^^^', value); - - // transform data to send to 3rd party - const v = value[key][0]; - v[topic] = v.values['dimming']; - delete v.values; - - client.publish(topic, JSON.stringify(v)); - } - else if(value[nodeTbName][0].values.hasOwnProperty('status')) - { - const key = nodeTbName; - const tbValues = value[key][0].values; - - Object.keys(tbValues).map(item => { - if(item != 'status') - { - delete tbValues[item]; - } - }) - - // we expect topic to be 'lamp_000/brightness'. we must make 'lamp_000/status' - const topic = topics[key].slice(0, 8) + '/status'; - // console.log('---- ***********', key, topic) - // console.log('^^^^^^^^^^^^^^', value); - - // transform data to send to 3rd party - const v = value[key][0]; - v[topic] = v.values['status']; - delete v.values; - - client.publish(topic, JSON.stringify(v)); - } - - } - - - - - }); - - instance.close = function(done) { - client.end(); - }; - - - - loadNodes(); - - instance.on('options', instance.reconfigure); - instance.reconfigure(); -}; - - - - -/* - [ { - node: 683, - tbname: 'XKQbz3WAwY21dGa0R453rWyJm9PZOjqlvpr6Nkeo', - line: 3, - profile: '{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"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}', - processed: true, - status: true - }, - { - node: 688, - tbname: 'PaGbQ3wBAZWOmRvK9VDpvz5endLJYopEqlkzNMxX', - line: 3, - profile: '{"intervals":[{"cct":3000,"value":0,"end_time":"20:00","start_time":"13:00"},{"cct":3000,"value":100,"end_time":"21:20","start_time":"20:00"},{"cct":3000,"value":0,"end_time":"13:00","start_time":"05:30"},{"cct":3000,"value":80,"end_time":"22:20","start_time":"21:50"},{"cct":3000,"value":70,"end_time":"22:50","start_time":"22:20"},{"cct":3000,"value":60,"end_time":"23:20","start_time":"22:50"},{"cct":3000,"value":50,"end_time":"23:50","start_time":"23:20"},{"cct":3000,"value":40,"end_time":"00:20","start_time":"23:50"},{"cct":3000,"value":100,"end_time":"05:30","start_time":"03:20"},{"cct":3000,"value":30,"end_time":"00:50","start_time":"00:20"},{"cct":3000,"value":20,"end_time":"01:20","start_time":"00:50"},{"cct":3000,"value":90,"end_time":"21:50","start_time":"21:20"},{"cct":3000,"value":30,"end_time":"01:50","start_time":"01:20"},{"cct":3000,"value":40,"end_time":"02:20","start_time":"01:50"},{"cct":3000,"value":50,"end_time":"02:50","start_time":"02:20"},{"cct":3000,"value":60,"end_time":"03:20","start_time":"02:50"}],"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}', - processed: true, - status: true - } -] -*/ - - - diff --git a/flow/mqttpublish.js b/flow/mqttpublish.js deleted file mode 100644 index 3f6aef0..0000000 --- a/flow/mqttpublish.js +++ /dev/null @@ -1,134 +0,0 @@ -exports.id = 'mqttpublish'; -exports.title = 'MQTT publish'; -exports.group = 'MQTT'; -exports.color = '#888600'; -exports.version = '1.1.0'; -exports.icon = 'sign-out'; -exports.input = true; -exports.output = 1; -exports.author = 'Martin Smola'; -exports.options = {}; - -exports.html = `
-
@(Brokers)
-
Topic
-
@(Supports variables, example: \`device/{device-id}\`)
-
Static message(string)
-
@(Supports variables), @(If specified then incoming data are ignored and this message is sent instead. Topic is required if static message is defined.)
-
@(QoS)
-
@(Retain)
-
-`; - -exports.readme = `# MQTT publish - -If the topic field is left empty and the data object does not have a 'topic' property then nothing is send. -Also if data object has a valid topic property it is assumed the object also have data property which is send as a payload; -Example: -\`\`\`javacsript -{ - topic: '/topic', - data: { - hello: 'world' - } -} -// in above case only { hello: 'world' } is published -\`\`\` - -If the topic field is not empty then the entire incomming data object is passed to the output.`; - - -exports.install = function(instance) { - - var PUBLISH_OPTIONS = {}; - - var ready = false; - - instance.custom.reconfigure = function() { - - ready = false; - - if (!MQTT.broker(instance.options.broker)) - return instance.status('No broker', 'red'); - - if (instance.options.broker) { - - MQTT.add(instance.options.broker, instance.id); - ready = true; - PUBLISH_OPTIONS.retain = instance.options.retain || false; - PUBLISH_OPTIONS.qos = parseInt(instance.options.qos || 0); - return; - } - - instance.status('Not configured', 'red'); - }; - - instance.on('options', instance.custom.reconfigure); - - instance.on('data', function(flowdata) { - if (!ready) - return; - var msg = instance.options.staticmessage ? instance.arg(instance.options.staticmessage) : flowdata.data; - var topic = instance.arg(instance.options.topic || msg.topic); - if (topic) { - if (msg.topic) - msg = msg.data; - MQTT.publish(instance.options.broker, topic, msg, PUBLISH_OPTIONS); - } else - instance.debug('MQTT publish no topic'); - - instance.send(flowdata); - }); - - instance.on('close', function() { - MQTT.remove(instance.options.broker, instance.id); - OFF('mqtt.brokers.status', instance.custom.brokerstatus); - }); - - - instance.custom.brokerstatus = function(status, brokerid, msg) { - if (brokerid !== instance.options.broker) - return; - - switch (status) { - case 'connecting': - instance.status('Connecting', '#a6c3ff'); - break; - case 'connected': - instance.status('Connected', 'green'); - break; - case 'disconnected': - instance.status('Disconnected', 'red'); - break; - case 'connectionfailed': - instance.status('Connection failed', 'red'); - break; - case 'new': - !ready && instance.custom.reconfigure(); - break; - case 'removed': - instance.custom.reconfigure(); - break; - case 'error': - instance.status(msg, 'red'); - break; - case 'reconfigured': - instance.options.broker = msg; - instance.reconfig(); - instance.custom.reconfigure(); - break; - } - } - - ON('mqtt.brokers.status', instance.custom.brokerstatus); - - instance.custom.reconfigure(); -}; diff --git a/flow/mqttsubscribe.js b/flow/mqttsubscribe.js deleted file mode 100644 index e866178..0000000 --- a/flow/mqttsubscribe.js +++ /dev/null @@ -1,168 +0,0 @@ -exports.id = 'mqttsubscribe'; -exports.title = 'MQTT subscribe'; -exports.group = 'MQTT'; -exports.color = '#888600'; -exports.version = '1.1.0'; -exports.icon = 'sign-in'; -exports.output = 1; -exports.variables = true; -exports.author = 'Martin Smola'; -exports.options = {}; - -exports.html = `
-
@(Select a broker)
-
Topic
-
@(Supports variables, example: \`device/{device-id}\`)
-
@(QoS)
-
-`; - -exports.readme = ` -# MQTT subscribe - -The data recieved are passed to the output as follows: -\`\`\`javascript -{ - topic: '/lights/on', - data: 'kitchen' -} -\`\`\` - -If the topic is wildcard then there's an array of matches in flowdata repository which can be used in Function component like so: -\`\`\`javascript -// wildcard -> /+/status -// topic -> /devicename/status - -var match = flowdata.get('mqtt_wildcard'); -// match === ['devicename'] -\`\`\` - -More on wildcard topics [here](https://mosquitto.org/man/mqtt-7.html) -`; - -exports.install = function(instance) { - - var old_topic; - var ready = false; - - instance.custom.reconfigure = function(o, old_options) { - - - ready = false; - - if (!MQTT.broker(instance.options.broker)) - return instance.status('No broker', 'red'); - - if (instance.options.broker && instance.options.topic) { - - if (old_topic) - MQTT.unsubscribe(instance.options.broker, instance.id, old_topic); - - old_topic = instance.arg(instance.options.topic); - MQTT.subscribe(instance.options.broker, instance.id, old_topic); - ready = true; - return; - } - - instance.status('Not configured', 'red'); - }; - - instance.on('options', instance.custom.reconfigure); - - instance.on('close', function() { - MQTT.unsubscribe(instance.options.broker, instance.id, instance.options.topic); - OFF('mqtt.brokers.message', instance.custom.message); - OFF('mqtt.brokers.status', instance.custom.brokerstatus); - }); - - instance.custom.brokerstatus = function(status, brokerid, msg) { - if (brokerid !== instance.options.broker) - return; - - switch (status) { - case 'connecting': - instance.status('Connecting', '#a6c3ff'); - break; - case 'connected': - instance.status('Connected', 'green'); - break; - case 'disconnected': - instance.status('Disconnected', 'red'); - break; - case 'connectionfailed': - instance.status('Connection failed', 'red'); - break; - case 'new': - !ready && instance.custom.reconfigure(); - break; - case 'removed': - instance.custom.reconfigure(); - break; - case 'error': - instance.status(msg, 'red'); - break; - case 'reconfigured': - instance.options.broker = msg; - instance.reconfig(); - instance.custom.reconfigure(); - break; - } - } - - instance.custom.message = function(brokerid, topic, message) { - if (brokerid !== instance.options.broker) - return; - - var match = mqttWildcard(topic, old_topic); - if (match) { - var flowdata = instance.make({ topic: topic, data: message }) - flowdata.set('mqtt_wildcard', match); - instance.send2(flowdata); - } - } - - ON('mqtt.brokers.message', instance.custom.message); - ON('mqtt.brokers.status', instance.custom.brokerstatus); - - instance.custom.reconfigure(); -}; - -// https://github.com/hobbyquaker/mqtt-wildcard -function mqttWildcard(topic, wildcard) { - if (topic === wildcard) { - return []; - } else if (wildcard === '#') { - return [topic]; - } - - var res = []; - - var t = String(topic).split('/'); - var w = String(wildcard).split('/'); - - var i = 0; - for (var lt = t.length; i < lt; i++) { - if (w[i] === '+') { - res.push(t[i]); - } else if (w[i] === '#') { - res.push(t.slice(i).join('/')); - return res; - } else if (w[i] !== t[i]) { - return null; - } - } - - if (w[i] === '#') { - i += 1; - } - - return (i === w.length) ? res : null; -} diff --git a/flow/nodesdb_changecheck.js b/flow/nodesdb_changecheck.js deleted file mode 100644 index be1e700..0000000 --- a/flow/nodesdb_changecheck.js +++ /dev/null @@ -1,70 +0,0 @@ -exports.id = 'nodesdb_change_check'; -exports.title = 'Nodes DB change check'; -exports.group = 'Worksys'; -exports.color = '#888600'; -exports.version = '1.0.2'; -exports.icon = 'sign-out'; -exports.input = 1; -exports.output = 1; -exports.readme = `Check, if nodes.table db changed compared to original database`; - -const fs = require('fs'); -const path = require('path'); -const { sendNotification } = require('./helper/notification_reporter'); -const nodesOriginalFile = path.join(__dirname, '../databases/nodes_original/', 'nodes_original.table'); - - -exports.install = function(instance) { - - function compareArrays(array1, array2) { - let message = ""; - let areEqual = true; - let zmenene = [] - - if (array1.length !== array2.length) { - message += "Nezhoda v pocte nodov. " - } - - const set1 = new Set(array1.map(obj => JSON.stringify(obj))); - const set2 = new Set(array2.map(obj => JSON.stringify(obj))); - - for (const objStr of set1) { - - if (!set2.has(objStr)) { - zmenene.push(objStr) - areEqual = false; - } else { - set2.delete(objStr); - } - } - - if(!areEqual) { - message += `Aktualne nody: ${zmenene.toString()}. Zmenene proti originalu: ${Array.from(set2).join(' ')}`; - sendNotification("Nodesdb_changecheck", FLOW.GLOBALS.settings.rvoTbName, "nodes_db_changed", "", message, 0, instance); - } - else console.log("Arrays are equal."); - - console.log(message) - } - - - instance.on("data", _ => { - - let nodesData = FLOW.GLOBALS.nodesData; - - // we check if nodes.table has changed compared to nodes_original.table (we have array of nodes e.g. [{node:255, tbname: "agruhuwhgursuhgo34hgsdiguhrr"}] - const nodes_actual = Object.keys(nodesData).map(node => ({[node]: nodesData[node].tbname})) - let nodes_original = fs.readFileSync(nodesOriginalFile, { encoding: 'utf8', flag: 'r' }); - - try { - nodes_original = JSON.parse(nodes_original); - } catch(e) { - console.log(e) - } - - - setTimeout(() => compareArrays(nodes_actual, nodes_original),10000); - }) - -} - diff --git a/flow/nosql.js b/flow/nosql.js deleted file mode 100644 index db6b7c4..0000000 --- a/flow/nosql.js +++ /dev/null @@ -1,191 +0,0 @@ -exports.id = 'nosql'; -exports.title = 'NoSQL'; -exports.version = '1.2.1'; -exports.group = 'Databases'; -exports.author = 'Martin Smola'; -exports.color = '#D770AD'; -exports.icon = 'database'; -exports.input = true; -exports.output = 2; -exports.options = {}; -exports.readme = `# NoSQL embedded - -## Outputs - -First output is response from nosql engine and second is the data passed in. - -## Collection - -if the collection field is left empty, then we try to look at \`flowdata.get('collection')\`, to set this value you need to use \`flowdata.set('collection', '')\` in previous component (currently only \`function\` can be used) - -## Insert - -- will insert recieved data -- expects data to be an Object -- returns error, success, id - -## Read - -- will read a document by id -- expects data to be an Object with an \`id\` property -- returns error, response - -## Update - -- will update document by id -- expects data to be an Object with \`id\` property and all the props to be updated -- returns error, response -- if response is 0 then update failed - -## Remove - -- will remove document by id -- expects data to be an Object with an \`id\` property -- returns error, response -- if response is 0 then remove failed - -## Query - -- will query DB -- expects data to be an Array as shown bellow -- returns error, response - -\`\`\`javascript -[ - ['where', 'sensor', 'temp'], // builder.where('sensor', 'temp'); - ['limit', 2] // builder.limit(2); -] -\`\`\``; - -exports.html = ` -
-
DB collection name
-
@(Method)
-
-
Add unique ID to data before insert
-
-
-
Insert document if it doesn't exist
-
Add unique ID to data before insert (only if it doesn't exist)
-
-
`; - -exports.install = function(instance) { - - instance.on('data', function(flowdata, next) { - - instance.send2(1, flowdata.clone()); - - var options = instance.options; - var collection = options.collection || flowdata.get('collection'); - if (!collection) { - flowdata.data = { err: '[DB] No collection specified' }; - next(0, flowdata); - instance.error('[DB] No collection specified'); - return; - } - - var nosql = NOSQL(collection); - var builder; - - if (options.method === 'read') { - - if (!flowdata.data.id) { - flowdata.data = { err: '[DB] Cannot get record by id: `undefined`' }; - next(0, flowdata); - instance.error('[DB] Cannot get record by id: `undefined`'); - return; - } - - builder = nosql.find(); - builder.where('id', flowdata.data.id); - builder.first(); - builder.callback(function(err, response) { - if (err) { - instance.throw(err); - } else { - flowdata.data = { response: response }; - next(0, flowdata); - } - }); - - } else if (options.method === 'insert') { - - options.addid && (flowdata.data.id = UID()); - nosql.insert(flowdata.data).callback(function(err) { - if (err) - instance.throw(err); - else { - flowdata.data = { success: err ? false : true, id: flowdata.data.id }; - next(0, flowdata); - } - }); - - } else if (options.method === 'query') { - - var query = flowdata.data; - builder = nosql.find(); - - query && query instanceof Array && query.forEach(function(q) { - if (q instanceof Array) { - var m = q[0]; - var args = q.splice(1); - builder[m] && (builder[m].apply(builder, args)); - } - }); - - builder.callback(function(err, response) { - if (err) { - instance.throw(err); - } else { - flowdata.data = { response: response || [] }; - next(0, flowdata); - } - }); - - } else if (options.method === 'update') { - - if (!options.upsert && !flowdata.data.id) { - flowdata.data = { err: '[DB] Cannot update record by id: `undefined`' }; - next(0, flowdata); - instance.error('[DB] Cannot update record by id: `undefined`'); - return; - } - - if (options.upsert && (options.upsertid && !flowdata.data.id)) { - flowdata.data.id = UID(); - builder = nosql.modify(flowdata.data, options.upsert); - builder.where('id', flowdata.data.id); - builder.callback(function(err, count) { - if (err) - instance.throw(err); - else { - flowdata.data = { response: count || 0 }; - next(0, flowdata); - } - }); - } - - } else if (options.method === 'remove') { - - if (!flowdata.data.id) { - flowdata.data = { err: '[DB] Cannot remove record by id: `undefined`' }; - next(0, flowdata); - instance.error('[DB] Cannot remove record by id: `undefined`'); - return; - } - - builder = nosql.remove(); - builder.where('id', flowdata.data.id); - builder.callback(function(err, count) { - if (err) - instance.throw(err); - else { - flowdata.data = { response: count || 0 }; - next(0, flowdata); - } - }); - } - - }); -}; diff --git a/flow/notifikacie.csv b/flow/notifikacie.csv new file mode 100644 index 0000000..520c997 --- /dev/null +++ b/flow/notifikacie.csv @@ -0,0 +1,31 @@ +key;weight;en;sk +switching_profile_point_applied_to_line;INFO;Switching profile point applied to line no. ${line} : ${value};Aplikovaný bod spínacieho profilu na línií č. ${line} : ${value} +dusk_has_occured;INFO;Dusk has occured;Nastal súmrak +dawn_has_occured;INFO;Dawn has occured;Nastal úsvit +dimming_profile_was_successfully_received_by_node;NOTICE;Dimming profile was successfully received by node no. ${node};Stmievací profil bol úspešne prijatý nodom č. ${node} +master_node_is_responding_again;NOTICE;Master node is responding again;Master node začal znovu odpovedať +command_was_sent_from_terminal_interface;DEBUG;A command was sent from terminal interface;Z terminálu bol odoslaný príkaz +master_node_is_not_responding;ALERT;Master node is not responding;Master node neodpovedá +configuration_of_dimming_profile_to_node_failed;ALERT;Configuration of dimming profile to node no. ${node} has failed;Konfigurácia stmievacieho profilu pre node č. ${node} zlyhala +circuit_breaker_was_turned_on_line;NOTICE;Circuit breaker was turned on - line no. ${line};Zapnutie ističa na línii č. ${line} +circuit_breaker_was_turned_off_line;ERROR;Circuit breaker was turned off - line no. ${line};Vypnutie ističa na línií č. ${line} +dimming_profile_was_processed_for_node;INFO;Dimming profile was processed for node no. ${node};Stmievací profil bol spracovaný pre node č. ${node} +switching_profile_was_processed_for_line;INFO;Switching profile was processed for line no. ${line};Spínací profil bol spracovaný pre líniu č. ${line} +thermometer_is_not_responding;WARNING;Thermometer is not responding;Teplomer neodpovedá +thermometer_is_responding_again;NOTICE;Thermometer is responding again;Teplomer znovu odpovedá +thermometer_sends_invalid_data;WARNING;Thermometer sends invalid data;Teplomer posiela neplatné hodnoty +main_switch_has_been_turned_off;CRITICAL;Main switch has been turned off;Hlavný vypínač bol vypnutý +main_switch_has_been_turned_on;NOTICE;Main switch has been turned on;Hlavný vypínač bol zapnutý +power_supply_has_disconnected_input;ALERT;Power supply has disconnected input;Napájací zdroj nemá napätie na vstupe +power_supply_works_correctly;NOTICE;Power supply works correctly ;Napájací zdroj pracuje správne +battery_level_is_low;ERROR;Battery level is low;Batéria má nízku úroveň napätia +battery_level_is_ok;NOTICE;Battery level is OK;Batéria má správnu úroveň napätia +door_has_been_open;NOTICE;Door has been open;Dvere boli otvorené +door_has_been_closed;NOTICE;Door has been closed;Dvere boli zatvorené +door_has_been_open_without_permision_alarm_is_on;WARNING;Door has been open without permision - alarm is on;Dvere boli otvorené bez povolania - zapnutá siréna +state_of_contactor_for_line;INFO;State of contactor for line no. ${line} is ${value};Stav stýkača pre líniu č. ${line} je ${value} +local_database_is_corrupted;CRITICAL;; +electrometer_is_not_responding;ERROR;Electrometer is not responding;Elektromer neodpovedá +no_voltage_detected_on_phase;CRITICAL;No voltage detected on phase no. ${phase};Na fáze č. ${phase} nie je napätie +electrometer_is_responding_again;NOTICE;Electrometer is responding again;Elektromer znovu odpovedá +voltaga_on_phase_has_been_restored;NOTICE;Voltaga on phase no. ${phase} has been restored;Napätie na fáze č. ${phase} bolo obnovené diff --git a/flow/operations_error.csv b/flow/operations_error.csv deleted file mode 100644 index 484ea07..0000000 --- a/flow/operations_error.csv +++ /dev/null @@ -1,595 +0,0 @@ -Production line;Operation;Error type;Error code;Orig Message (EN);User defined error -CMFB;OP10;C_STOP;121;Machine Not At Home Position; -CMFB;OP10;C_STOP;122;Auto Mode Not Selected; -CMFB;OP10;C_STOP;125;Part NOK; -CMFB;OP10;C_STOP;140;Left Shift Conduit Contact Detect Sensor Backcheck Error; -CMFB;OP10;C_STOP;141;Left Select Conduit Contact Detect Sensor Backcheck Error; -CMFB;OP10;C_STOP;142;Right Shift Conduit Contact Detect Sensor Backcheck Error; -CMFB;OP10;C_STOP;143;Right Select Conduit Contact Detect Sensor Backcheck Error; -CMFB;OP10;C_STOP;144;Left Shift Conduit In Place Sensor Backcheck Error; -CMFB;OP10;C_STOP;145;Left Select Conduit In Place Sensor Backcheck Error; -CMFB;OP10;C_STOP;146;Right Select Conduit In Place Sensor Backcheck Error; -CMFB;OP10;C_STOP;147;Left Shift Conduit In Place Sensor Backcheck Error; -CMFB;OP10;C_STOP;148;Left_Shift_Conduit_Placed_In_Place Sensors Backcheck Error; -CMFB;OP10;C_STOP;149;Left_Select_Conduit_Placed_In_Place Sensors Backcheck Error; -CMFB;OP10;C_STOP;150;Right_Shift_Conduit_Placed_In_Place Sensors Backcheck Error; -CMFB;OP10;C_STOP;151;Right_Select_Conduit_Placed_In_Place Sensors Backcheck Error; -CMFB;OP10;I_STOP;101;Left Clampping Conduit Cylinder Home Position Timeout Error [I3.1&I3.3,Q3.3],; -CMFB;OP10;I_STOP;102;Left Clampping Conduit Cylinder Work Position Timeout Error [I3.0&I3.2,Q3.2],; -CMFB;OP10;I_STOP;103;Left Clampping Conduit Cylinder Sensors Miscompare [I3.1&I3.3,I3.0&I3.2],; -CMFB;OP10;I_STOP;104;Right Clampping Conduit Cylinder Work Position Timeout Error [I4.0&I4.2,Q3.4],; -CMFB;OP10;I_STOP;105;Right Clampping Conduit Cylinder Home Position Timeout Error [I4.1&I4.3,Q3.5],; -CMFB;OP10;I_STOP;106;Right Clampping Conduit Cylinder Sensors Miscompare [I4.1&I4.3,I4.0&I4.2],; -CMFB;OP10;I_STOP;107;Right Clipping Conduit Cylinder Work Position Timeout Error [I5.2,Q3.6],; -CMFB;OP10;I_STOP;108;Right Clipping Conduit Cylinder Home Position Timeout Error [I5.3,Q3.7],; -CMFB;OP10;I_STOP;109;Right Clipping Cylinder Sensors Miscompare [I3.1&I3.3,I3.0&I3.2],; -CMFB;OP10;I_STOP;110;Left Clipping Cylinder Work Position Timeout Error [I6.2,Q5.2],; -CMFB;OP10;I_STOP;111;Left Clipping Cylinder Home Position Timeout Error [I6.3,Q5.3],; -CMFB;OP10;I_STOP;112;Left Clipping Cylinder Sensors Miscompare [I6.2,I6.3],; -CMFB;OP10;I_STOP;113;Right Striping Cylinder Work Position Timeout Error [I5.0,Q4.0],; -CMFB;OP10;I_STOP;114;Right Striping Cylinder Home Position Timeout Error [I3.1&I3.3,Q3.3],; -CMFB;OP10;I_STOP;115;Right Striping Cylinder Sensors Miscompare [I3.1&I3.3,I3.0&I3.2],; -CMFB;OP10;I_STOP;116;Left Striping Cylinder Work Position Timeout Error [I6.0,Q5.4],; -CMFB;OP10;I_STOP;117;Left Stripping Cylinder Work Position Timeout Error [I6.1,Q5.5],; -CMFB;OP10;I_STOP;118;Left Stripping Cylinder Sensors Miscompare [I6.0,I6.1],; -CMFB;OP10;I_STOP;119;Left Escaping Cylinder Work Position Timeout Error [I6.4,Q5.6],; -CMFB;OP10;I_STOP;120;Left Escaping Cylinder Home Position Timeout Error [I6.5,Q5.7],; -CMFB;OP10;I_STOP;121;Left Escaping Cylinder Sensors Miscompare [I6.4,I6.5],; -CMFB;OP10;I_STOP;122;Right Escaping Cylinder Work Position Timeout Error [I5.4,Q4.2],; -CMFB;OP10;I_STOP;123;Right Escaping Cylinder Home Position Timeout Error [I5.5,Q4.3],; -CMFB;OP10;I_STOP;124;Right Escaping Cylinder Sensors Miscompare [I5.4,I5.5],; -CMFB;OP10;I_STOP;125;UP Clamping End of Conduit Cylinder Work Position Timeout Error [I8.0&I8.4,Q4.7],; -CMFB;OP10;I_STOP;126;UP Clamping End of Conduit Cylinder Home Position Timeout Error [I8.1&I8.5,Q4.6],; -CMFB;OP10;I_STOP;127;UP Clamping End of Conduit Cylinder Sensors Miscompare [I8.0&I8.4,I8.1&I8.5],; -CMFB;OP10;I_STOP;128;DOWN Clamping End of Conduit Cylinder Work Position Timeout Error [I8.2&I8.6,Q4.4],; -CMFB;OP10;I_STOP;129;DOWN Clamping End of Conduit Cylinder Home Position Timeout Error [I8.3&I8.7,Q4.5],; -CMFB;OP10;I_STOP;130;DOWN Clamping End of Conduit Cylinder Sensors Miscompare [I8.2&I8.6,I8.3&I8.7],; -CMFB;OP10;I_STOP;131;Fixture Moving Cylinder Work Position Timeout Error [I7.0,Q5.0],; -CMFB;OP10;I_STOP;132;Fixture Moving Cylinder Home Position Timeout Error [I7.1,Q5.1],; -CMFB;OP10;I_STOP;133;Fixture Moving Cylinder Sensors Miscompare Error[I7.0,I7.1],; -CMFB;OP10;I_STOP;134;Hydraulic Cylinder Work Positio Timeout Error,; -CMFB;OP10;I_STOP;135;Hydraulic Cylinder Home Position Timeout Error[I7.2],; -CMFB;OP10;I_STOP;136;Hydraulic Cylinder Sensors Miscompare Error,; -CMFB;OP10;I_STOP;137;Left Press Conduit Cylinder Work Positio Timeout Error[I10.3],; -CMFB;OP10;I_STOP;138;Left Press Conduit Cylinder Home Positio Timeout Error[I10.2],; -CMFB;OP10;I_STOP;139;Left Press Conduit Cylinder Sensors Miscompare Error[I10.2,I10.3],; -CMFB;OP10;I_STOP;140;Right Press Conduit Cylinder Work Positio Timeout Error[I10.5],; -CMFB;OP10;I_STOP;141;Right Press Conduit Cylinder Home Positio Timeout Error[I10.4],; -CMFB;OP10;I_STOP;142;Right Press Conduit Cylinder Sensors Miscompare Error[I10.4,I10.5],; -CMFB;OP10;I_STOP;151;Emergency Stop Relay Not ON,Pls Press Reset Button.,; -CMFB;OP10;I_STOP;152;Emergency Stop Button Pressed; -CMFB;OP20A;C_STOP;101;Light Curtain Blocked(I2.0),; -CMFB;OP20A;C_STOP;121;Machine Not At Home Position,; -CMFB;OP20A;C_STOP;122;Auto Mode Not Selected,; -CMFB;OP20A;C_STOP;125;The Part Is NOK,; -CMFB;OP20A;C_STOP;140;Grommet Assembly_PositionLeft sensor backcheck fault[I8.0],; -CMFB;OP20A;C_STOP;141;Grommet Assembly_PositionRight sensor backcheck fault[I8.1],; -CMFB;OP20A;C_STOP;142;AssemblyOK_Left_Front sensor backcheck fault[I8.2],; -CMFB;OP20A;C_STOP;143;AssemblyOK_Left_Back sensor backcheck fault[I8.3],; -CMFB;OP20A;C_STOP;144;AssemblyOK_Right_Front sensor backcheck fault[I8.4],; -CMFB;OP20A;C_STOP;145;AssemblyOK_Right_Back sensor backcheck fault[I8.5],; -CMFB;OP20A;C_STOP;146;Grommet present sensor backcheck fault[I5.6],; -CMFB;OP20A;C_STOP;147;Clip check_front sensor backcheck fault[I9.6],; -CMFB;OP20A;C_STOP;148;Clip check_back sensor backcheck fault[9.7],; -CMFB;OP20A;C_STOP;149;Gromment left sensor backcheck fault[I8.6],; -CMFB;OP20A;C_STOP;150;Check Sensor 11 Backcheck Error,; -CMFB;OP20A;C_STOP;151;Check Sensor 12 Backcheck Error,; -CMFB;OP20A;C_STOP;152;Check Sensor 13 Backcheck Error; -CMFB;OP20A;I_STOP;100;Pressing cylinder Sensor Miscompare[I4.4,I4.5],; -CMFB;OP20A;I_STOP;101;Clip ClampCylinder_front Work Position Timeout Errror[I9.1],; -CMFB;OP20A;I_STOP;102;Clip ClampCylinder_front Home Position Timeout Errror[I9.0],; -CMFB;OP20A;I_STOP;103;Clip ClampCylinder_front Sensor Miscompare[I9.0,I9.1],; -CMFB;OP20A;I_STOP;104;Clip ClampCylinder_back Work Position Timeout Errror[I9.3],; -CMFB;OP20A;I_STOP;105;Clip ClampCylinder_back Home Position Timeout Errror[I9.2],; -CMFB;OP20A;I_STOP;106;Clip ClampCylinder_back Sensor Miscompare[I9.2,I9.3],; -CMFB;OP20A;I_STOP;107;Clip Assembly Cylinder Work Position Timeout Errror[I9.5],; -CMFB;OP20A;I_STOP;116;Clip Assembly Cylinder Home Position Timeout Errror[I9.4],; -CMFB;OP20A;I_STOP;117;Clip Assembly Cylinder Sensor Miscompare[I9.4,I9.5],; -CMFB;OP20A;I_STOP;151;Emergency Stop Relay Not ON,; -CMFB;OP20A;I_STOP;152;Emergency Stop Button Pressed; -CMFB;OP20B;C_STOP;100;Load Material cylinder Work Position Timeout Errror[I4.1],; -CMFB;OP20B;C_STOP;101;Load Material cylinder Home Position Timeout Errror[I4.0],; -CMFB;OP20B;C_STOP;102;Load Material cylinder Sensor Miscompare[I4.0,I4.1],; -CMFB;OP20B;C_STOP;103;The Assembly of cylinder Work Position Timeout Errror[I4.3],; -CMFB;OP20B;C_STOP;104;The Assembly of cylinder Home Position Timeout Errror[I4.2],; -CMFB;OP20B;C_STOP;105;The Assembly of cylinder Sensor Miscompare[I4.2,I4.3],; -CMFB;OP20B;C_STOP;106;Pressing cylinder Work Position Timeout Errror[I4.5],; -CMFB;OP20B;C_STOP;107;Pressing cylinder Home Position Timeout Errror[I4.4],; -CMFB;OP20B;C_STOP;108;Pressing cylinder Sensor Miscompare[I4.4,I4.5],; -CMFB;OP20B;C_STOP;109;Clip ClampCylinder_front Work Position Timeout Errror[I9.1],; -CMFB;OP20B;C_STOP;110;Clip ClampCylinder_front Home Position Timeout Errror[I9.0],; -CMFB;OP20B;C_STOP;111;Clip ClampCylinder_front Sensor Miscompare[I9.0,I9.1],; -CMFB;OP20B;C_STOP;112;Clip ClampCylinder_back Work Position Timeout Errror[I9.3],; -CMFB;OP20B;C_STOP;113;Clip ClampCylinder_back Home Position Timeout Errror[I9.2],; -CMFB;OP20B;C_STOP;114;Clip ClampCylinder_back Sensor Miscompare[I9.2,I9.3],; -CMFB;OP20B;C_STOP;115;Clip Assembly Cylinder Work Position Timeout Errror[I9.5],; -CMFB;OP20B;C_STOP;126;Clip Assembly NOK!,; -CMFB;OP20B;C_STOP;140;Select Damper Prestretching sensor backcheck fault[I5.0],; -CMFB;OP20B;C_STOP;141;Select Omgea Prestretching sensor backcheck fault[I5.1],; -CMFB;OP20B;C_STOP;142;Shift Damper Prestretching sensor backcheck fault[I5.2],; -CMFB;OP20B;C_STOP;143;Shift Omgea Prestretching sensor backcheck fault[I5.3],; -CMFB;OP20B;C_STOP;144;Gromment ASSY Postion1 sensor backcheck fault[I5.4],; -CMFB;OP20B;C_STOP;145;Gromment ASSY Postion2 sensor backcheck fault[I5.5],; -CMFB;OP20B;C_STOP;146;Grommet present_Right sensor backcheck fault[I5.6]; -CMFB;OP20B;I_STOP;100;Rotating Pressure cylinder Sensor Miscompare[I7.2,I7.3],; -CMFB;OP20B;I_STOP;101;Cover Cylinder Work Position Timeout Errror[I7.1],; -CMFB;OP20B;I_STOP;102;Cover Cylinder Home Position Timeout Errror[I7.0],; -CMFB;OP20B;I_STOP;103;Cover Cylinder Sensor Miscompare[I7.0,I7.1],; -CMFB;OP20B;I_STOP;108;Remodel cylinder Work Position Timeout Errror[I7.7],; -CMFB;OP20B;I_STOP;109;Remodel cylinder Home Position Timeout Errror[I7.6],; -CMFB;OP20B;I_STOP;110;Remodel cylinder Sensor Miscompare[I7.6,I7.7],; -CMFB;OP20B;I_STOP;111;Limit cylinder Work Position Timeout Errror[I7.5],; -CMFB;OP20B;I_STOP;112;Limit cylinder Home Position Timeout Errror[I7.4],; -CMFB;OP20B;I_STOP;113;Limit cylinder Sensor Miscompare[I7.4,I7.5],; -CMFB;OP20B;I_STOP;114;Rotating Pressure cylinder Work Position Timeout Errror[I7.3],; -CMFB;OP20B;I_STOP;115;Rotating Pressure cylinder Home Position Timeout Errror[I7.2]; -CMFB;OP30A;C_STOP;101; Left Station Light Curtain Blocked(I2.0),; -CMFB;OP30A;C_STOP;121; Machine Not At Home Position_L,; -CMFB;OP30A;C_STOP;122; Auto Mode Not Selected_L,; -CMFB;OP30A;C_STOP;125; The Part Of Station Is NOK,; -CMFB;OP30A;C_STOP;140; left front select swivetube present sensor backcheck fault,; -CMFB;OP30A;C_STOP;141; left front select swivetube assy present sensor backcheck fault,; -CMFB;OP30A;C_STOP;142; left front select omgea present sensor backcheck fault,; -CMFB;OP30A;C_STOP;143; left inside select swivetube present sensor backcheck fault,; -CMFB;OP30A;C_STOP;144; left inside select swivetube assy present sensor backcheck fault,; -CMFB;OP30A;C_STOP;145; left inside select omgea present sensor backcheck fault,; -CMFB;OP30A;C_STOP;146; right outside shift omgea present sensor backcheck fault,; -CMFB;OP30A;C_STOP;147; right outside shift swiveltube assy present sensor backcheck fault,; -CMFB;OP30A;C_STOP;148; right outside shift swiveltube present sensor backcheck fault,; -CMFB;OP30A;C_STOP;149; right inside shift omgea present sensor backcheck fault,; -CMFB;OP30A;C_STOP;150; right inside shift swiveltube assy present sensor backcheck fault,; -CMFB;OP30A;C_STOP;151; right inside shift swiveltube present sensor backcheck fault,; -CMFB;OP30A;C_STOP;152; romemet assy present sensor backcheck fault; -CMFB;OP30A;I_STOP;100;left front select rotating cylinder Work Position Timeout Errror[I3.1],; -CMFB;OP30A;I_STOP;101;left front select rotating cylinder Home Position Timeout Errror[I3.0],; -CMFB;OP30A;I_STOP;102;left front select rotating cylinder Sensor Miscompare[I3.0,I3.1],; -CMFB;OP30A;I_STOP;103;left front select pull in cylinder Work Position Timeout Errror[I3.3],; -CMFB;OP30A;I_STOP;104;left front select pull in cylinder Home Position Timeout Errror[I3.2],; -CMFB;OP30A;I_STOP;105;left front select pull in cylinder Sensor Miscompare[I3.2,I3.3],; -CMFB;OP30A;I_STOP;106;outside select prepull testing force not reach 1000N,; -CMFB;OP30A;I_STOP;107;outside select prepull testing cylinder Home Position Timeout Errror[I3.4],; -CMFB;OP30A;I_STOP;108;outside select prepull testing cylinder Sensor Miscompare[I3.4,I3.5],; -CMFB;OP30A;I_STOP;109;left outside lifting release cylinder Work Position Timeout Errror[I3.7],; -CMFB;OP30A;I_STOP;110;left outside lifting release cylinder Home Position Timeout Errror[I3.6],; -CMFB;OP30A;I_STOP;111;left outside lifting release cylinder Cylinder Sensor Miscompare[I3.6,I3.7],; -CMFB;OP30A;I_STOP;112;left outside select griping cylinder Work Position Timeout Errror[I4.1],; -CMFB;OP30A;I_STOP;113;left outside select griping cylinder Home Position Timeout Errror[I4.0],; -CMFB;OP30A;I_STOP;114;left outside select griping cylinder Sensor Miscompare[I4.0,I4.1],; -CMFB;OP30A;I_STOP;115;outside pullout testing cylinder Work Position Timeout Errror[I4.3],; -CMFB;OP30A;I_STOP;116;outside pullout testing cylinder Home Position Timeout Errror[I4.2],; -CMFB;OP30A;I_STOP;117;outside pullout testing cylinder Sensor Miscompare[I4.2,I4.3],; -CMFB;OP30A;I_STOP;118;left inside shift rotating cylinder Work Position Timeout Errror[I5.1],; -CMFB;OP30A;I_STOP;119;left inside shift rotating cylinder Home Position Timeout Errror[I5.0],; -CMFB;OP30A;I_STOP;120;left inside shift rotating cylinder Sensor Miscompare[I5.0,I5.1],; -CMFB;OP30A;I_STOP;121;left inside shift pull in cylinder Work Position Timeout Errror[I5.3],; -CMFB;OP30A;I_STOP;122;left inside shift pull in cylinder Home Position Timeout Errror[I5.2],; -CMFB;OP30A;I_STOP;123;left inside shift pull in cylinder Sensor Miscompare[I5.2,I5.3],; -CMFB;OP30A;I_STOP;124;Inside select prepull testing force not reach 1000N,; -CMFB;OP30A;I_STOP;125;Inside select prepull testing cylinder Home Position Timeout Errror[I5.4],; -CMFB;OP30A;I_STOP;126;Inside select prepull testing cylinder Sensor Miscompare[I5.4,I5.5],; -CMFB;OP30A;I_STOP;127;left inside lifting release cylinder Work Position Timeout Errror[I5.7],; -CMFB;OP30A;I_STOP;128;left inside lifting release cylinder Home Position Timeout Errror[I5.6],; -CMFB;OP30A;I_STOP;129;left inside lifting release cylinder Sensor Miscompare[I5.6,I5.7],; -CMFB;OP30A;I_STOP;130;left inside shift griping cylinder Work Position Timeout Errror[I6.1],; -CMFB;OP30A;I_STOP;131;left inside shift griping cylinder Home Position Timeout Errror[I6.0],; -CMFB;OP30A;I_STOP;132;left inside shift griping cylinder Sensor Miscompare[I6.0,I6.1],; -CMFB;OP30A;I_STOP;133;inside pullout testing cylinder Work Position Timeout Errror[I6.3],; -CMFB;OP30A;I_STOP;134;inside pullout testing cylinder Home Position Timeout Errror[I6.2],; -CMFB;OP30A;I_STOP;135;inside pullout testing cylinder Sensor Miscompare[I6.2,I6.3],; -CMFB;OP30A;I_STOP;136;right outside select pull in cylinder Work Position Timeout Errror[I7.1],; -CMFB;OP30A;I_STOP;137;right outside select pull in cylinder Home Position Timeout Errror[I7.0],; -CMFB;OP30A;I_STOP;138;right outside select pull in cylinder Sensor Miscompare[I7.0,I7.1],; -CMFB;OP30A;I_STOP;139;right outside lifting release cylinder Work Position Timeout Errror[I7.3],; -CMFB;OP30A;I_STOP;140;right outside lifting release cylinder Home Position Timeout Errror[I7.2],; -CMFB;OP30A;I_STOP;141;right outside lifting release cylinder Sensor Miscompare[I7.2,I7.3],; -CMFB;OP30A;I_STOP;142;right outside select griping the cylinder Work Position Timeout Errror[I7.5],; -CMFB;OP30A;I_STOP;143;right outside select griping the cylinder Home Position Timeout Errror[I7.4],; -CMFB;OP30A;I_STOP;144;right outside select griping the cylinder Sensor Miscompare[I7.4,I7.5],; -CMFB;OP30A;I_STOP;145;right outside select rotating cylinder Work Position Timeout Errror[I7.7],; -CMFB;OP30A;I_STOP;146;right outside select rotating cylinder Home Position Timeout Errror[I7.6],; -CMFB;OP30A;I_STOP;147;right outside select rotating cylinder Sensor Miscompare[I7.6,I7.7],; -CMFB;OP30A;I_STOP;148;left outside positioning cylinder Work Position Timeout Errror[I8.1],; -CMFB;OP30A;I_STOP;149;left outside positioning cylinder Home Position Timeout Errror[I8.0],; -CMFB;OP30A;I_STOP;150;left outside positioning cylinder Sensor Miscompare[I8.0,I8.1],; -CMFB;OP30A;I_STOP;151;right outside positioning cylinder Work Position Timeout Errror[I8.3],; -CMFB;OP30A;I_STOP;152;right outside positioning cylinder Home Position Timeout Errror[I8.2],; -CMFB;OP30A;I_STOP;153;right outside positioning cylinder Sensor Miscompare[I8.2,I8.3],; -CMFB;OP30A;I_STOP;154;right inside select rotating cylinder Work Position Timeout Errror[I9.1],; -CMFB;OP30A;I_STOP;155;right inside select rotating cylinder Home Position Timeout Errror[I9.0],; -CMFB;OP30A;I_STOP;156;right inside shift rotating cylinder Sensor Miscompare[I9.0,I9.1],; -CMFB;OP30A;I_STOP;157;right inside shift pull in cylinder Work Position Timeout Errror[I9.3],; -CMFB;OP30A;I_STOP;158;right inside shift pull in cylinder Home Position Timeout Errror[I9.2],; -CMFB;OP30A;I_STOP;159;right inside shift pull in cylinder Sensor Miscompare[I9.2,I9.3],; -CMFB;OP30A;I_STOP;160;right inside lifting release cylinder Work Position Timeout Errror[I9.5],; -CMFB;OP30A;I_STOP;161;right inside lifting release cylinder Home Position Timeout Errror[I9.4],; -CMFB;OP30A;I_STOP;162;right inside lifting release cylinder Sensor Miscompare[I9.4,I9.5],; -CMFB;OP30A;I_STOP;163;right inside shift griping the cylinder Work Position Timeout Errror[I9.7],; -CMFB;OP30A;I_STOP;164;right inside shift griping the cylinder Home Position Timeout Errror[I9.6],; -CMFB;OP30A;I_STOP;165;right inside shift griping the cylinder Sensor Miscompare[I9.6,I9.7],; -CMFB;OP30A;I_STOP;166;left inside postiton cylinder Work Position Timeout Errror[I10.1],; -CMFB;OP30A;I_STOP;167;left inside postiton cylinder Home Position Timeout Errror[I10.0],; -CMFB;OP30A;I_STOP;168;left inside postiton cylinder Sensor Miscompare[I10.0,I10.1],; -CMFB;OP30A;I_STOP;169;right inside positioning cylinder Work Position Timeout Errror[I10.3],; -CMFB;OP30A;I_STOP;170;right inside positioning cylinder Home Position Timeout Errror[I10.2],; -CMFB;OP30A;I_STOP;171;right inside positioning cylinder Sensor Miscompare[I10.2,I10.3]; -CMFB;OP30B;C_STOP;101;" Left Station Light Curtain Blocked(I2.0),"; -CMFB;OP30B;C_STOP;121;" Machine Not At Home Position_L,"; -CMFB;OP30B;C_STOP;122;" Auto Mode Not Selected_L,"; -CMFB;OP30B;C_STOP;125;" The Part Of Station Is NOK,"; -CMFB;OP30B;C_STOP;140;" left front select swivetube present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;141;" left front select swivetube assy present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;142;" left front select omgea present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;143;" left inside select swivetube present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;144;" left inside select swivetube assy present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;145;" left inside select omgea present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;146;" right outside shift omgea present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;147;" right outside shift swiveltube assy present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;148;" right outside shift swiveltube present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;149;" right inside shift omgea present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;150;" right inside shift swiveltube assy present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;151;" right inside shift swiveltube present sensor backcheck fault,"; -CMFB;OP30B;C_STOP;152;" romemet assy present sensor backcheck fault"; -CMFB;OP30B;I_STOP;100;" left front select rotating cylinder Work Position Timeout Errror[I3.1],"; -CMFB;OP30B;I_STOP;101;" left front select rotating cylinder Home Position Timeout Errror[I3.0],"; -CMFB;OP30B;I_STOP;102;" left front select rotating cylinder Sensor Miscompare[I3.0,I3.1],"; -CMFB;OP30B;I_STOP;103;" left front select pull in cylinder Work Position Timeout Errror[I3.3],"; -CMFB;OP30B;I_STOP;104;" left front select pull in cylinder Home Position Timeout Errror[I3.2],"; -CMFB;OP30B;I_STOP;105;" left front select pull in cylinder Sensor Miscompare[I3.2,I3.3],"; -CMFB;OP30B;I_STOP;106;" outside select prepull testing force not reach 1000N,"; -CMFB;OP30B;I_STOP;107;" outside select prepull testing cylinder Home Position Timeout Errror[I3.4],"; -CMFB;OP30B;I_STOP;108;" outside select prepull testing cylinder Sensor Miscompare[I3.4,I3.5],"; -CMFB;OP30B;I_STOP;109;" left outside lifting release cylinder Work Position Timeout Errror[I3.7],"; -CMFB;OP30B;I_STOP;110;" left outside lifting release cylinder Home Position Timeout Errror[I3.6],"; -CMFB;OP30B;I_STOP;111;" left outside lifting release cylinder Cylinder Sensor Miscompare[I3.6,I3.7],"; -CMFB;OP30B;I_STOP;112;" left outside select griping cylinder Work Position Timeout Errror[I4.1],"; -CMFB;OP30B;I_STOP;113;" left outside select griping cylinder Home Position Timeout Errror[I4.0],"; -CMFB;OP30B;I_STOP;114;" left outside select griping cylinder Sensor Miscompare[I4.0,I4.1],"; -CMFB;OP30B;I_STOP;115;" outside pullout testing cylinder Work Position Timeout Errror[I4.3],"; -CMFB;OP30B;I_STOP;116;" outside pullout testing cylinder Home Position Timeout Errror[I4.2],"; -CMFB;OP30B;I_STOP;117;" outside pullout testing cylinder Sensor Miscompare[I4.2,I4.3],"; -CMFB;OP30B;I_STOP;118;" left inside shift rotating cylinder Work Position Timeout Errror[I5.1],"; -CMFB;OP30B;I_STOP;119;" left inside shift rotating cylinder Home Position Timeout Errror[I5.0],"; -CMFB;OP30B;I_STOP;120;" left inside shift rotating cylinder Sensor Miscompare[I5.0,I5.1],"; -CMFB;OP30B;I_STOP;121;" left inside shift pull in cylinder Work Position Timeout Errror[I5.3],"; -CMFB;OP30B;I_STOP;122;" left inside shift pull in cylinder Home Position Timeout Errror[I5.2],"; -CMFB;OP30B;I_STOP;123;" left inside shift pull in cylinder Sensor Miscompare[I5.2,I5.3],"; -CMFB;OP30B;I_STOP;124;" Inside select prepull testing force not reach 1000N,"; -CMFB;OP30B;I_STOP;125;" Inside select prepull testing cylinder Home Position Timeout Errror[I5.4],"; -CMFB;OP30B;I_STOP;126;" Inside select prepull testing cylinder Sensor Miscompare[I5.4,I5.5],"; -CMFB;OP30B;I_STOP;127;" left inside lifting release cylinder Work Position Timeout Errror[I5.7],"; -CMFB;OP30B;I_STOP;128;" left inside lifting release cylinder Home Position Timeout Errror[I5.6],"; -CMFB;OP30B;I_STOP;129;" left inside lifting release cylinder Sensor Miscompare[I5.6,I5.7],"; -CMFB;OP30B;I_STOP;130;" left inside shift griping cylinder Work Position Timeout Errror[I6.1],"; -CMFB;OP30B;I_STOP;131;" left inside shift griping cylinder Home Position Timeout Errror[I6.0],"; -CMFB;OP30B;I_STOP;132;" left inside shift griping cylinder Sensor Miscompare[I6.0,I6.1],"; -CMFB;OP30B;I_STOP;133;" inside pullout testing cylinder Work Position Timeout Errror[I6.3],"; -CMFB;OP30B;I_STOP;134;" inside pullout testing cylinder Home Position Timeout Errror[I6.2],"; -CMFB;OP30B;I_STOP;135;" inside pullout testing cylinder Sensor Miscompare[I6.2,I6.3],"; -CMFB;OP30B;I_STOP;136;" right outside select pull in cylinder Work Position Timeout Errror[I7.1],"; -CMFB;OP30B;I_STOP;137;" right outside select pull in cylinder Home Position Timeout Errror[I7.0],"; -CMFB;OP30B;I_STOP;138;" right outside select pull in cylinder Sensor Miscompare[I7.0,I7.1],"; -CMFB;OP30B;I_STOP;139;" right outside lifting release cylinder Work Position Timeout Errror[I7.3],"; -CMFB;OP30B;I_STOP;140;" right outside lifting release cylinder Home Position Timeout Errror[I7.2],"; -CMFB;OP30B;I_STOP;141;" right outside lifting release cylinder Sensor Miscompare[I7.2,I7.3],"; -CMFB;OP30B;I_STOP;142;" right outside select griping the cylinder Work Position Timeout Errror[I7.5],"; -CMFB;OP30B;I_STOP;143;" right outside select griping the cylinder Home Position Timeout Errror[I7.4],"; -CMFB;OP30B;I_STOP;144;" right outside select griping the cylinder Sensor Miscompare[I7.4,I7.5],"; -CMFB;OP30B;I_STOP;145;" right outside select rotating cylinder Work Position Timeout Errror[I7.7],"; -CMFB;OP30B;I_STOP;146;" right outside select rotating cylinder Home Position Timeout Errror[I7.6],"; -CMFB;OP30B;I_STOP;147;" right outside select rotating cylinder Sensor Miscompare[I7.6,I7.7],"; -CMFB;OP30B;I_STOP;148;" left outside positioning cylinder Work Position Timeout Errror[I8.1],"; -CMFB;OP30B;I_STOP;149;" left outside positioning cylinder Home Position Timeout Errror[I8.0],"; -CMFB;OP30B;I_STOP;150;" left outside positioning cylinder Sensor Miscompare[I8.0,I8.1],"; -CMFB;OP30B;I_STOP;151;" right outside positioning cylinder Work Position Timeout Errror[I8.3],"; -CMFB;OP30B;I_STOP;152;" right outside positioning cylinder Home Position Timeout Errror[I8.2],"; -CMFB;OP30B;I_STOP;153;" right outside positioning cylinder Sensor Miscompare[I8.2,I8.3],"; -CMFB;OP30B;I_STOP;154;" right inside select rotating cylinder Work Position Timeout Errror[I9.1],"; -CMFB;OP30B;I_STOP;155;" right inside select rotating cylinder Home Position Timeout Errror[I9.0],"; -CMFB;OP30B;I_STOP;156;" right inside shift rotating cylinder Sensor Miscompare[I9.0,I9.1],"; -CMFB;OP30B;I_STOP;157;" right inside shift pull in cylinder Work Position Timeout Errror[I9.3],"; -CMFB;OP30B;I_STOP;158;" right inside shift pull in cylinder Home Position Timeout Errror[I9.2],"; -CMFB;OP30B;I_STOP;159;" right inside shift pull in cylinder Sensor Miscompare[I9.2,I9.3],"; -CMFB;OP30B;I_STOP;160;" right inside lifting release cylinder Work Position Timeout Errror[I9.5],"; -CMFB;OP30B;I_STOP;161;" right inside lifting release cylinder Home Position Timeout Errror[I9.4],"; -CMFB;OP30B;I_STOP;162;" right inside lifting release cylinder Sensor Miscompare[I9.4,I9.5],"; -CMFB;OP30B;I_STOP;163;" right inside shift griping the cylinder Work Position Timeout Errror[I9.7],"; -CMFB;OP30B;I_STOP;164;" right inside shift griping the cylinder Home Position Timeout Errror[I9.6],"; -CMFB;OP30B;I_STOP;165;" right inside shift griping the cylinder Sensor Miscompare[I9.6,I9.7],"; -CMFB;OP30B;I_STOP;166;" left inside postiton cylinder Work Position Timeout Errror[I10.1],"; -CMFB;OP30B;I_STOP;167;" left inside postiton cylinder Home Position Timeout Errror[I10.0],"; -CMFB;OP30B;I_STOP;168;" left inside postiton cylinder Sensor Miscompare[I10.0,I10.1],"; -CMFB;OP30B;I_STOP;169;" right inside positioning cylinder Work Position Timeout Errror[I10.3],"; -CMFB;OP30B;I_STOP;170;" right inside positioning cylinder Home Position Timeout Errror[I10.2],"; -CMFB;OP30B;I_STOP;171;" right inside positioning cylinder Sensor Miscompare[I10.2,I10.3]"; -CMFB;OP40A;C_STOP;101;Left Station Light Curtain Blocked(I2.0),; -CMFB;OP40A;C_STOP;121;Machine Not At Home Position_L,; -CMFB;OP40A;C_STOP;122;Auto Mode Not Selected_L,; -CMFB;OP40A;C_STOP;125;The Part Of Left Station Is NOK,; -CMFB;OP40A;C_STOP;140;detection pressure 1 sensor backcheck fault,; -CMFB;OP40A;C_STOP;141;detection pressure 2 sensor backcheck fault,; -CMFB;OP40A;C_STOP;142;shift terminal type sensor backcheck fault,; -CMFB;OP40A;C_STOP;143;shift boot present sensor backcheck fault,; -CMFB;OP40A;C_STOP;144;shift terminal present sensor backcheck fault,; -CMFB;OP40A;C_STOP;145;shift terminal no present sensor backcheck fault,; -CMFB;OP40A;C_STOP;146;select terminal present sensor backcheck fault,; -CMFB;OP40A;C_STOP;147;select terminal no present sensor backcheck fault,; -CMFB;OP40A;C_STOP;148;select boot present Backcheck Error,; -CMFB;OP40A;C_STOP;149;Shift Terminal Type Confirmation Sensor_1 Backcheck Error,; -CMFB;OP40A;C_STOP;150;Shift Terminal Type Confirmation Sensor_2 Backcheck Error,; -CMFB;OP40A;C_STOP;151;Select Terminal Type Confirmation Sensor_1 Backcheck Error,; -CMFB;OP40A;C_STOP;152;Select Terminal Type Confirmation Sensor_2 Backcheck Error,; -CMFB;OP40A;C_STOP;153;select termianl type Backcheck Error,; -CMFB;OP40A;C_STOP;154;detect steel wire present1 Backcheck Error,; -CMFB;OP40A;C_STOP;155;detect steel wire present2 Backcheck Error; -CMFB;OP40A;I_STOP;100;front clamping wire cylinder Work Position Timeout Errror[I3.1],; -CMFB;OP40A;I_STOP;101;front clamping wire cylinder Home Position Timeout Errror[I3.0],; -CMFB;OP40A;I_STOP;102;front clamping wire cylinder Sensor Miscompare[I3.0,I3.1],; -CMFB;OP40A;I_STOP;103;back clamping wire cylinder Work Position Timeout Errror[I3.3],; -CMFB;OP40A;I_STOP;104;back clamping wire cylinder Home Position Timeout Errror[I3.2],; -CMFB;OP40A;I_STOP;105;back clamping wire cylinder Sensor Miscompare[I3.2,I3.3],; -CMFB;OP40A;I_STOP;106;Select Wire Not Put Well[I3.5],; -CMFB;OP40A;I_STOP;107;pushing select wire cylinder Home Position Timeout Errror[I3.4],; -CMFB;OP40A;I_STOP;108;pushing select wire cylinder Sensor Miscompare[I3.4,I3.5],; -CMFB;OP40A;I_STOP;109;crimping cylinder Work Position Timeout Errror[I5.0],; -CMFB;OP40A;I_STOP;110;crimping cylinder Home Position Timeout Errror[I4.2],; -CMFB;OP40A;I_STOP;111;crimping cylinder Cylinder Sensor Miscompare[I3.6,I3.7],; -CMFB;OP40A;I_STOP;112;Shift Wire Not Put Well[I4.1],; -CMFB;OP40A;I_STOP;113;pushing shift wire cylinder Home Position Timeout Errror[I4.0],; -CMFB;OP40A;I_STOP;114;pushing shift wire cylinder Sensor Miscompare[I4.0,I4.1],; -CMFB;OP40A;I_STOP;115;front cliping wire cylinder Work Position Timeout Errror[I4.3],; -CMFB;OP40A;I_STOP;116;front cliping wire cylinder Home Position Timeout Errror[I4.2],; -CMFB;OP40A;I_STOP;117;front cliping wire cylinder Sensor Miscompare[I4.2,I4.3],; -CMFB;OP40A;I_STOP;118;back cliping wire cylinder Work Position Timeout Errror[I4.5],; -CMFB;OP40A;I_STOP;119;back cliping wire cylinder Home Position Timeout Errror[I4.4],; -CMFB;OP40A;I_STOP;120;back cliping wire cylinder Sensor Miscompare[I4.4,I4.5],; -CMFB;OP40A;I_STOP;121;Grease Pump Pressure Alarm For Terminal[I8.7],; -CMFB;OP40A;I_STOP;122;Grease valve1Home Position Timeout Errror[],; -CMFB;OP40A;I_STOP;123;Grease valve1Sensor Miscompare[],; -CMFB;OP40A;I_STOP;124;Grease Pump Pressure Alarm For Inner Member,; -CMFB;OP40A;I_STOP;125;Grease valve2 Home Position Timeout Errror[],; -CMFB;OP40A;I_STOP;126;Grease valve2 Sensor Miscompare[],; -CMFB;OP40A;I_STOP;151;Emergency Stop Relay Not ON,; -CMFB;OP40A;I_STOP;152;Emergency Stop Button Pressed; -CMFB;OP40B;C_STOP;101;Right Station Light Curtain Blocked(I2.6),; -CMFB;OP40B;C_STOP;121;Machine Not At Home Position_R,; -CMFB;OP40B;C_STOP;122;Auto Mode Not Selected_R,; -CMFB;OP40B;C_STOP;125;The Part Of Right Station Is NOK,; -CMFB;OP40B;C_STOP;140;shift omega present sensor backcheck fault,; -CMFB;OP40B;C_STOP;141;select omega present sensor backcheck fault,; -CMFB;OP40B;C_STOP;142;gromment present sensor backcheck fault,; -CMFB;OP40B;C_STOP;143;detect steel wire present3 sensor backcheck fault,; -CMFB;OP40B;C_STOP;144;detect steel wire present4 sensor backcheck fault,; -CMFB;OP40B;C_STOP;148;Check Shift Wire Exists R sensor backcheck failure,; -CMFB;OP40B;C_STOP;149;Check Select Wire Exists R sensor backcheck failure; -CMFB;OP40B;I_STOP;100;Horizontal cylinder Work Position Timeout Error[I6.1],; -CMFB;OP40B;I_STOP;101;Horizontal cylinder Home Position Timeout Error[I6.0],; -CMFB;OP40B;I_STOP;102;Horizontal cylinder Sensors Miscompare Error[6.0,I6.1],; -CMFB;OP40B;I_STOP;103;front Pressing wire cylinder Work Position Timeout Error[I6.3],; -CMFB;OP40B;I_STOP;104;front Pressing wire cylinder Home Position Timeout Error[I6.2],; -CMFB;OP40B;I_STOP;105;front Pressing wire cylinder Sensors Miscompare Error[I6.2,I6.3],; -CMFB;OP40B;I_STOP;106;back Pressing wire cylinder Work Position Timeout Error[I6.5],; -CMFB;OP40B;I_STOP;107;back Pressing wire cylinder Home Position Timeout Error[I6.4],; -CMFB;OP40B;I_STOP;108;back Pressing wire cylinder Sensors Miscompare Error[6.4,I6.5],; -CMFB;OP40B;I_STOP;109;Vertical Cylinder Work Position Timeout Error[I6.7],; -CMFB;OP40B;I_STOP;110;Vertical Cylinder Home Position Timeout Error[I6.6],; -CMFB;OP40B;I_STOP;111;Vertical Cylinder Sensors Miscompare Error[I6.6,I6.7],; -CMFB;OP40B;I_STOP;112;Grease valve 3 Work Position Timeout Error[],; -CMFB;OP40B;I_STOP;113;Grease valve 3 Home Position Timeout Error[],; -CMFB;OP40B;I_STOP;114;Grease valve 3 Sensors Miscompare Error[],; -CMFB;OP40B;I_STOP;115;Grease valve 4 Work Position Timeout Error[],; -CMFB;OP40B;I_STOP;116;Grease valve 4 Home Position Timeout Error[],; -CMFB;OP40B;I_STOP;117;Grease valve 4 Sensors Miscompare Error[],; -CMFB;OP40B;I_STOP;151;Emergency Stop Relay Not ON,; -CMFB;OP40B;I_STOP;152;Emergency Stop Button Pressed; -CMFB;OP50;C_STOP;101;Light Curtain Blocked(I2.0),; -CMFB;OP50;C_STOP;121;Machine Not At Home Position,; -CMFB;OP50;C_STOP;122;Auto Mode Not Selected,; -CMFB;OP50;C_STOP;125;The Part Is NOK,; -CMFB;OP50;C_STOP;132;select conduit present left Sensor Backcheck Error[7.6],; -CMFB;OP50;C_STOP;133;select conduit present right Sensor Backcheck Error[7.7],; -CMFB;OP50;C_STOP;134;terminal present Sensor Backcheck Error[8.2],; -CMFB;OP50;C_STOP;140;check shift omega Sensor Backcheck Error[I3.2],; -CMFB;OP50;C_STOP;141;check select omega Sensor Backcheck Error[I3.3],; -CMFB;OP50;C_STOP;142;check shift rodt Sensor Backcheck Error[I3.4],; -CMFB;OP50;C_STOP;143;check select rod Sensor Backcheck Error[I3.5],; -CMFB;OP50;C_STOP;144;shift check omega Sensor Backcheck Error[I5.7],; -CMFB;OP50;C_STOP;145;select check omega Sensor Backcheck Error[I6.7],; -CMFB;OP50;C_STOP;146;shift conduit present left Sensor Backcheck Error[7.4],; -CMFB;OP50;C_STOP;147;shift conduit present right Sensor Backcheck Error[7.5],; -CMFB;OP50;C_STOP;148;Shift Terminal Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;149;Select Terminal Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;150;Heavy Mass Check Sensor 1 Backcheck Error,; -CMFB;OP50;C_STOP;151;Heavy Mass Check Sensor 2 Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;152;Shift Swivel Tube Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;153;Select Swivel Tube Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;154;Shift Adjust Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;155;Select Adjust Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;156;Shift Star Sleve Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;157;Select Star Sleve Check Sensor Backcheck Error,; -CMFB;OP50;C_STOP;158;Gromment Detect Check Sensor Backcheck Error; -CMFB;OP50;I_STOP;100;crimping cylinder Work Position Timeout Errror[I3.1],; -CMFB;OP50;I_STOP;101;crimping cylinder Home Position Timeout Errror[I3.0],; -CMFB;OP50;I_STOP;102;crimping cylinderSensor Miscompare[I3.0,I3.1],; -CMFB;OP50;I_STOP;103;left front location cylinder Work Position Timeout Errror[I4.1],; -CMFB;OP50;I_STOP;104;left front location cylinder Home Position Timeout Errror[I4.0],; -CMFB;OP50;I_STOP;105;left front location cylinder Sensor Miscompare[I4.0,I4.1],; -CMFB;OP50;I_STOP;106;left back location cylinder Work Position Timeout Errror[I4.3],; -CMFB;OP50;I_STOP;107;left back location cylinder Home Position Timeout Errror[I4.2],; -CMFB;OP50;I_STOP;108;left back location cylinder Sensor Miscompare[I4.2,I4.3],; -CMFB;OP50;I_STOP;109;right front location cylinder Work Position Timeout Errror[I4.5],; -CMFB;OP50;I_STOP;110;right front location cylinder Home Position Timeout Errror[I4.4],; -CMFB;OP50;I_STOP;111;right front location cylinder Sensor Miscompare[I4.4,I4.5],; -CMFB;OP50;I_STOP;112;right back location cylinder Work Position Timeout Errror[I4.7],; -CMFB;OP50;I_STOP;113;right back location cylinder Home Position Timeout Errror[I4.6],; -CMFB;OP50;I_STOP;114;right back location cylinder Sensor Miscompare[I4.6,I4.7],; -CMFB;OP50;I_STOP;115;select terminal pullout test cylinder Work Position Timeout Errror[I5.1],; -CMFB;OP50;I_STOP;116;select terminal pullout test cylinder Not Reach 500N,; -CMFB;OP50;I_STOP;117;select terminal pullout test cylinder Sensor Miscompare[I5.0,I5.1],; -CMFB;OP50;I_STOP;118;selcet terminal fixed cylinder Work Position Timeout Errror[I5.3],; -CMFB;OP50;I_STOP;119;selcet terminal fixed cylinder Home Position Timeout Errror[I5.2],; -CMFB;OP50;I_STOP;120;selcet terminal fixed cylinder Sensor Miscompare[I5.2,I5.3],; -CMFB;OP50;I_STOP;121;pulling select cable cylinder Work Position Timeout Errror[I5.5],; -CMFB;OP50;I_STOP;122;pulling select cable cylinder Home Position Timeout Errror[I5.4],; -CMFB;OP50;I_STOP;123;pulling select cable cylinder Sensor Miscompare[I5.4,I5.5],; -CMFB;OP50;I_STOP;124;shift terminal pullout test cylinder Work Position Timeout Errror[I6.1],; -CMFB;OP50;I_STOP;125;shift terminal pullout test cylinder Not Reach 500N,; -CMFB;OP50;I_STOP;126;shift terminal pullout test cylinder Sensor Miscompare[I6.0,I6.1],; -CMFB;OP50;I_STOP;127;shift terminal fixed cylinder Work Position Timeout Errror[I6.3],; -CMFB;OP50;I_STOP;128;shift terminal fixed cylinder Home Position Timeout Errror[I6.2],; -CMFB;OP50;I_STOP;129;shift terminal fixed cylinder Sensor Miscompare[I6.2,I6.3],; -CMFB;OP50;I_STOP;130;pulling shift cable cylinder Work Position Timeout Errror[I6.5],; -CMFB;OP50;I_STOP;131;pulling shift cable cylinder Home Position Timeout Errror[I6.4],; -CMFB;OP50;I_STOP;132;pulling shift cable cylinder Sensor Miscompare[I6.4,I6.5],; -CMFB;OP50;I_STOP;133;prepull shift cable cylinder Work Position Timeout Errror[I7.1],; -CMFB;OP50;I_STOP;134;prepull shift cable cylinder Home Position Timeout Errror[I7.0],; -CMFB;OP50;I_STOP;135;prepull shift cable cylinder Sensor Miscompare[I7.0,I7.1],; -CMFB;OP50;I_STOP;136;prepull select cable cylinder Work Position Timeout Errror[I7.3],; -CMFB;OP50;I_STOP;137;prepull select cable cylinder Home Position Timeout Errror[I7.2],; -CMFB;OP50;I_STOP;138;prepull select cable cylinder Sensor Miscompare[I7.2,I7.3],; -CMFB;OP50;I_STOP;139;terminal greasing valve Work Position Timeout Errror[I8.1],; -CMFB;OP50;I_STOP;140;terminal greasing valve Home Position Timeout Errror[I8.0],; -CMFB;OP50;I_STOP;141;terminal greasing valve Sensor Miscompare[I8.0,I8.1],; -CMFB;OP50;I_STOP;161;Emergency Stop Relay Not ON,; -CMFB;OP50;I_STOP;162;Emergency Stop Button Pressed; -CMFB;OP55;C_STOP;102;Emergency Stop Relay Not ON,; -CMFB;OP55;C_STOP;121;Machine Not At Home Position,; -CMFB;OP55;C_STOP;122;Auto Mode Not Selected,; -CMFB;OP55;C_STOP;125;Part NOK,; -CMFB;OP55;C_STOP;140;Shift check1 Sensors Backcheck Error,; -CMFB;OP55;C_STOP;141;Shift check2 Sensors Backcheck Error,; -CMFB;OP55;C_STOP;142;Select check1 Sensors Backcheck Error,; -CMFB;OP55;C_STOP;143;Select check1 Sensors Backcheck Error,; -CMFB;OP55;C_STOP;149;Left_Select_Conduit_Placed_In_Place Sensors Backcheck Error,; -CMFB;OP55;C_STOP;150;Right_Shift_Conduit_Placed_In_Place Sensors Backcheck Error,; -CMFB;OP55;C_STOP;151;Right_Select_Conduit_Placed_In_Place Sensors Backcheck Error; -CMFB;OP55;I_STOP;101;Shift bushing assy cylinder Work Position Timeout Error [I3.3,Q3.1],; -CMFB;OP55;I_STOP;102;Shift bushing assy cylinder Home Position Timeout Error [I3.2,Q3.0],; -CMFB;OP55;I_STOP;103;Shift bushing assy cylinder Sensors Miscompare [I3.2,I3.3],; -CMFB;OP55;I_STOP;104;Select bushing assy cylinder Work Position Timeout Error [I4.3,Q3.3],; -CMFB;OP55;I_STOP;105;Select bushing assy cylinder Home Position Timeout Error [I4.2,Q3.2],; -CMFB;OP55;I_STOP;106;Select bushing assy cylinder Sensors Miscompare [I4.2,I4.3],; -CMFB;OP55;I_STOP;107;Shift test cylinder Work Position Timeout Error [I3.5,Q4.1],; -CMFB;OP55;I_STOP;108;Shift test cylinder Home Position Timeout Error [I3.4,Q4.0],; -CMFB;OP55;I_STOP;109;Shift test cylinder Sensors Miscompare [I3.4,I3.5],; -CMFB;OP55;I_STOP;110;Select test cylinder Work Position Timeout Error [I4.3,Q4.3],; -CMFB;OP55;I_STOP;111;Select test cylinder Home Position Timeout Error [I4.2,Q4.2],; -CMFB;OP55;I_STOP;112;Select test cylinder Sensors Miscompare [I4.2,I4.3],; -CMFB;OP55;I_STOP;113;Conduit clamp cylinder Work Position Timeout Error [I4.7,Q4.5],; -CMFB;OP55;I_STOP;114;Conduit clamp cylinder Home Position Timeout Error [I4.6,Q4.4],; -CMFB;OP55;I_STOP;115;Conduit clamp cylinderCylinder Sensors Miscompare [I4.6,I4.7],; -CMFB;OP55;I_STOP;116;Screw feeder cylinder Work Position Timeout Error [5.1,Q7.3],; -CMFB;OP55;I_STOP;117;Screw feeder cylinder Home Position Timeout Error [I5.0,Q7.2],; -CMFB;OP55;I_STOP;118;Screw feeder cylinder Cylinder Sensors Miscompare [I5.0,I5.1],; -CMFB;OP55;I_STOP;124;Screw NOK,; -CMFB;OP55;I_STOP;125;IAI Error,; -CMFB;OP55;I_STOP;126;Shift Screw test Error,; -CMFB;OP55;I_STOP;127;Select Screw test Error,; -CMFB;OP55;I_STOP;128;Shift washer assembly not correct,; -CMFB;OP55;I_STOP;129;Selcet washer assembly not correct,; -CMFB;OP55;I_STOP;130;Part Pullout Testing Not OK,; -CMFB;OP55;I_STOP;131;Screw operation Timeout Error,; -CMFB;OP55;I_STOP;151;Emergency Stop Relay Not ON,Pls Press Reset Button.,; -CMFB;OP55;I_STOP;152;Emergency Stop Button Pressed; -CMFB;OP60;C_STOP;121;Machine Not At Home Position,; -CMFB;OP60;C_STOP;122;Auto Mode Not Selected,; -CMFB;OP60;C_STOP;123;No Model Selected,; -CMFB;OP60;C_STOP;125;Outside select terminal check1 Sensor Backcheck Error[I3.2],; -CMFB;OP60;C_STOP;126;Outside select terminal check2 Sensor Backcheck Error[I3.3],; -CMFB;OP60;C_STOP;127;Outside select termianl present1 Sensor Backcheck Error[I3.4],; -CMFB;OP60;C_STOP;128;Outside select termianl present2 Sensor Backcheck Error[I3.5],; -CMFB;OP60;C_STOP;129;Outside select omega present1 Sensor Backcheck Error[I3.6],; -CMFB;OP60;C_STOP;130;Outside shift terminal check1 Sensor Backcheck Error[I4.2],; -CMFB;OP60;C_STOP;131;Outside shift terminal check2 Sensor Backcheck Error[I4.3],; -CMFB;OP60;C_STOP;132;Outside shift termianl present1 Sensor Backcheck Error[I4.4],; -CMFB;OP60;C_STOP;133;Outside shift omega present1 Sensor Backcheck Error[I4.5],; -CMFB;OP60;C_STOP;134;Outside shift conduit present Sensor Backcheck Error[I5.2],; -CMFB;OP60;C_STOP;135;Outside select conduit present Sensor Backcheck Error[I5.3],; -CMFB;OP60;C_STOP;136;Inside shift conduit present Sensor Insidecheck Error[I5.6],; -CMFB;OP60;C_STOP;137;Inside select conduit present Sensor Backcheck Error[I5.7],; -CMFB;OP60;C_STOP;138;Outside select omega present Sensor Backcheck Error[I6.0],; -CMFB;OP60;C_STOP;139;Outside select tube present Sensor Backcheck Error[I6.1],; -CMFB;OP60;C_STOP;140;Outside select adjuster check1 Sensor Backcheck Error[I6.2],; -CMFB;OP60;C_STOP;141;Outside select adjuster check2 Sensor Backcheck [I6.3],; -CMFB;OP60;C_STOP;142;Outside shift omega present Sensor Backcheck Error[I6.4],; -CMFB;OP60;C_STOP;143;Outside shift tube present Sensor Backcheck Error[I6.5],; -CMFB;OP60;C_STOP;144;Outside shift adjuster check1 Sensor Backcheck Error[I6.6],; -CMFB;OP60;C_STOP;145;Outside shift adjuster check2 Sensor Backcheck Error[I6.7],; -CMFB;OP60;C_STOP;146;Inside select terminal check1 Sensor Backcheck Error[I7.2],; -CMFB;OP60;C_STOP;147;Inside select terminal check2 Sensor Backcheck Error[I7.3],; -CMFB;OP60;C_STOP;148;Inside select termianl present1 Sensor Backcheck Error[I7.4],; -CMFB;OP60;C_STOP;149;Inside select termianl present2 Sensor Backcheck [I7.5],; -CMFB;OP60;C_STOP;150;Inside select omega present1 Sensor Backcheck Error[I7.6],; -CMFB;OP60;C_STOP;151;Inside shift terminal check1 Sensor Insidecheck Error[I8.2],; -CMFB;OP60;C_STOP;152;Inside shift terminal check2 Sensor Insidecheck Error[I8.3],; -CMFB;OP60;C_STOP;153;Inside shift termianl present Sensor Insidecheck Error[I8.4],; -CMFB;OP60;C_STOP;154;Inside shift omega present1 Sensor Insidecheck Error[I8.5],; -CMFB;OP60;C_STOP;155;Inside select omega present2 Sensor Backcheck Error[I9.0],; -CMFB;OP60;C_STOP;156;Inside select tube present Sensor Backcheck Error[I9.1],; -CMFB;OP60;C_STOP;157;Insideselect adjuster check1 Sensor Backcheck Error[I9.2],; -CMFB;OP60;C_STOP;158;Inside select adjuster check2 Sensor Backcheck Error[I9.3],; -CMFB;OP60;C_STOP;159;Inside shift omega present2 Sensor Insidecheck Error[I9.4],; -CMFB;OP60;C_STOP;160;Inside shift tube present Sensor Insidecheck Error[I9.5],; -CMFB;OP60;C_STOP;161;Inside shift adjuster check1 Sensor Insidecheck Error[I9.6],; -CMFB;OP60;C_STOP;162;Inside shift adjuster check2 Sensor Insidecheck Error[I9.7]; -CMFB;OP60;I_STOP;101;Outside select release cylinder Work Position Timeout[I3.1],; -CMFB;OP60;I_STOP;102;Outside select release cylinder Home Position Timeout[I3.0],; -CMFB;OP60;I_STOP;103;Outside select release cylinder Sensors Miscompare[I3.0,I3.1],; -CMFB;OP60;I_STOP;104;Outside shift release cylinder Work Position Timeout[I4.1],; -CMFB;OP60;I_STOP;105;Outside shift release cylinder Home Position Timeout[I4.0],; -CMFB;OP60;I_STOP;106;Outside shift release cylinder Sensors Miscompare[I4.0,I4.1],; -CMFB;OP60;I_STOP;107;Outside clamp conduit cylinder Work Position Timeout[I5.1],; -CMFB;OP60;I_STOP;108;Outside clamp conduit cylinder Home Position Timeout[I5.0],; -CMFB;OP60;I_STOP;109;Outside clamp conduit cylinder Sensors Miscompare[I5.0,I5.1],; -CMFB;OP60;I_STOP;110;Inside select release cylinder Work Position Timeout[I5.5],; -CMFB;OP60;I_STOP;111;Inside select release cylinder Home Position Timeout[I5.4],; -CMFB;OP60;I_STOP;112;Inside select release cylinder Sensors Miscompare[I5.4,I5.5],; -CMFB;OP60;I_STOP;113;Inside shift release cylinder Work Position Timeout[I7.1],; -CMFB;OP60;I_STOP;114;Inside shift release cylinder Home Position Timeout[I7.0],; -CMFB;OP60;I_STOP;115;Inside shift release cylinder Sensors Miscompare[I7.0,I7.1],; -CMFB;OP60;I_STOP;116;Inside clamp conduit cylinder Work Position Timeout[I8.1],; -CMFB;OP60;I_STOP;117;Inside clamp conduit cylinder Home Position Timeout[I8.0],; -CMFB;OP60;I_STOP;118;Inside clamp conduit cylinder Sensors Miscompare[I8.0,I8.1],; -CMFB;OP60;I_STOP;119;Outside Selectlength_Axis Alarm,; -CMFB;OP60;I_STOP;120;Outside Shiftlength_Axis Alarm,; -CMFB;OP60;I_STOP;121;Outside SelectA+B_Axis Alarm,; -CMFB;OP60;I_STOP;122;Outside ShiftA+B_Axis Alarm,; -CMFB;OP60;I_STOP;123;Inside Selectlength_Axis Alarm,; -CMFB;OP60;I_STOP;124;Inside Shiftlength_Axis Alarm,; -CMFB;OP60;I_STOP;125;Inside SelectA+B_Axis Alarm,; -CMFB;OP60;I_STOP;126;Inside ShiftA+B_Axis Alarm,; -CMFB;OP60;I_STOP;127;Lazer_Axis Alarm,; -CMFB;OP60;I_STOP;135;Light Curtain Blocked In Cycle,; -CMFB;OP60;I_STOP;136;Before Select Cable A+B Test, Force Reach Stop Force, Please Check,; -CMFB;OP60;I_STOP;137;Before Shift Cable A+B Test, Force Reach Stop Force, Please Check,; -CMFB;OP60;I_STOP;140;Select Cable Axis Alarm,; -CMFB;OP60;I_STOP;141;Shift Cable Axis Alarm,; -CMFB;OP60;I_STOP;142;Outside Part Select Cable Friction Test Failed,Please Check,; -CMFB;OP60;I_STOP;143;Outside Part Shift Cable Friction Test Failed,Please Check,; -CMFB;OP60;I_STOP;144;Inside Part Select Cable Friction Test Failed,Please Check,; -CMFB;OP60;I_STOP;145;Inside Part Shift Cable Friction Test Failed,Please Check,; -CMFB;OP60;I_STOP;151;Emergency Stop Relay Not ON,; -CMFB;OP60;I_STOP;152;Emergency Stop Button Pressed; -CMFB;OP70;C_STOP;102;Emergency Stop Relay Not ON,; -CMFB;OP70;C_STOP;121;Machine Not At Home Position,; -CMFB;OP70;C_STOP;122;Auto Mode Not Selected,; -CMFB;OP70;C_STOP;125;Part NOK,; -CMFB;OP70;C_STOP;133;select adjuster present Sensors Backcheck Error[I5.4],; -CMFB;OP70;C_STOP;134;shift right omega present Sensors Backcheck Error[I5.5],; -CMFB;OP70;C_STOP;135;shift right clip present Sensors Backcheck Error[I5.6],; -CMFB;OP70;C_STOP;136;slect adjuster locker present Sensors Backcheck Error[I5.7],; -CMFB;OP70;C_STOP;137;gromment present Sensors Backcheck Error[I6.0],; -CMFB;OP70;C_STOP;141;select omega present Sensors Backcheck Error[I3.4],; -CMFB;OP70;C_STOP;142;select clip present Sensors Backcheck Error[I3.5],; -CMFB;OP70;C_STOP;143;shift clip present Sensors Backcheck Error[I3.6],; -CMFB;OP70;C_STOP;144;shift omega present Sensors Backcheck Error[I3.7],; -CMFB;OP70;C_STOP;145;select star sleeve present Sensors Backcheck Error[I4.6],; -CMFB;OP70;C_STOP;146;shift star sleeve present Sensors Backcheck Error[I4.7],; -CMFB;OP70;C_STOP;147;select right omega present Sensors Backcheck Error[I5.2],; -CMFB;OP70;C_STOP;148;select right clip present Sensors Backcheck Error[I5.3]; -CMFB;;MANUAL;;;Zoradenie -CMFB;;MANUAL;;;Zmena_typu -CMFB;;MANUAL;;;Chyba_material -CMFB;;MANUAL;;;Zastavene_QE -CMFB;;MANUAL;;;Zastavene_PE -CMFB;;MANUAL;;;Nedostatok_operatorov -CMFB;;MANUAL;;;Odstavka \ No newline at end of file diff --git a/flow/repository.json b/flow/repository.json deleted file mode 100644 index 29fb290..0000000 --- a/flow/repository.json +++ /dev/null @@ -1 +0,0 @@ -{"$1634465281992ram":[{"timestamp":1634480076668,"ram":60.69,"ram_max":249}]} \ No newline at end of file diff --git a/flow/show_dbdata.js b/flow/show_dbdata.js deleted file mode 100644 index 4c6cb86..0000000 --- a/flow/show_dbdata.js +++ /dev/null @@ -1,228 +0,0 @@ -exports.id = 'showdb'; -exports.title = 'Show db data'; -exports.group = 'Worksys'; -exports.color = '#888600'; -exports.version = '1.0.2'; -exports.icon = 'sign-out'; -exports.input = 5; -exports.output = 1; - - -exports.install = async function(instance) { - - instance.on("0", _ => { - instance.send(0, FLOW.GLOBALS.settings); - }) - instance.on("1", _ => { - instance.send(0, FLOW.GLOBALS.relaysData); - }) - instance.on("2", _ => { - instance.send(0, FLOW.GLOBALS.nodesData); - }) - instance.on("3", _ => { - instance.send(0, FLOW.GLOBALS.pinsData); - }) - instance.on("4", _ => { - instance.send(0, {rpcSwitchOffLine, rpcSetNodeDimming, rpcLineProfile, rpcNodeProfile, sunCalcExample, dataFromTerminalBroadcast}) - }) -}; - - - -const rpcSwitchOffLine = -{ - "topic": "v1/gateway/rpc", - "content": { - "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", - "data": { - "id": 8, - "method": "set_command", - "params": { - "entities": [ - { - "entity_type": "edb_line", - "tb_name": "MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O" - } - ], - "command": "switch", - "payload": { - "value": false - } - } - } - } -} - -const rpcSetNodeDimming = -{ - "topic": "v1/gateway/rpc", - "content": { - "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", - "data": { - "id": 10, - "method": "set_command", - "params": { - "entities": [ - { - "entity_type": "street_luminaire", - "tb_name": "jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV" - } - ], - "command": "dimming", - "payload": { - "value": 5 - } - } - } - } -} - -const rpcLineProfile = -{ - "topic": "v1/gateway/rpc", - "content": { - "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", - "data": { - "id": 9, - "method": "set_profile", - "params": { - "entities": [ - { - "entity_type": "edb_line", - "tb_name": "MgnK93rkoAazbqdQ4yB2Q0yZ1YXGx6pmwBeVEP2O" - } - ], - "payload": { - "intervals": [ - { - "value": 0, - "end_time": "20:00", - "start_time": "13:00" - }, - { - "value": 1, - "end_time": "05:30", - "start_time": "20:00" - }, - { - "value": 0, - "end_time": "13:00", - "start_time": "05:30" - } - ], - "astro_clock": true, - "dawn_lux_sensor": false, - "dusk_lux_sensor": false, - "dawn_lux_sensor_value": 5, - "dusk_lux_sensor_value": 5, - "dawn_astro_clock_offset": 0, - "dusk_astro_clock_offset": 0, - "dawn_lux_sensor_time_window": 30, - "dusk_lux_sensor_time_window": 30, - "dawn_astro_clock_time_window": 60, - "dusk_astro_clock_time_window": 60 - } - } - } - } -} - - -const rpcNodeProfile = -{ - "topic": "v1/gateway/rpc", - "content": { - "device": "jbN4q7JPZmexgdnz2yKbWGDYAWwO0Q3BMX6ERLoV", - "data": { - "id": 11, - "method": "set_profile", - "params": { - "entities": [ - { - "entity_type": "street_luminaire", - "tb_name": "jbN4q7JPZmexgdnz2yKbWdDYAWwO0Q3BMX6ERLoV" - } - ], - "payload": { - "intervals": [ - { - "cct": 3000, - "value": 0, - "end_time": "17:50", - "start_time": "13:00" - }, - { - "cct": 3000, - "value": 100, - "end_time": "21:30", - "start_time": "17:50" - }, - { - "cct": 3000, - "value": 0, - "end_time": "13:00", - "start_time": "07:10" - }, - { - "cct": 3000, - "value": 50, - "end_time": "00:00", - "start_time": "21:30" - }, - { - "cct": 3000, - "value": 10, - "end_time": "04:30", - "start_time": "00:00" - }, - { - "cct": 3000, - "value": 100, - "end_time": "07:10", - "start_time": "04:30" - } - ], - "astro_clock": true, - "dawn_lux_sensor": false, - "dusk_lux_sensor": false, - "dawn_lux_sensor_value": 5, - "dusk_lux_sensor_value": 5, - "dawn_astro_clock_offset": 30, - "dusk_astro_clock_offset": 20, - "dawn_lux_sensor_time_window": 30, - "dusk_lux_sensor_time_window": 30, - "dawn_astro_clock_time_window": 60, - "dusk_astro_clock_time_window": 60 - } - } - } - } -} - - const sunCalcExample = { - dusk_no_offset: '20:18', - dawn_no_offset: '05:19', - dusk: '20:18', - dusk_hours: 20, - dusk_minutes: 18, - dawn: '05:19', - dawn_hours: 5, - dawn_minutes: 19, - dusk_time: 1715278688962, - dawn_time: 1715224744357, - dusk_astro_clock_offset: 0, - dawn_astro_clock_offset: 0 -} - - -const dataFromTerminalBroadcast = { - address: 4294967295, - byte1: 0, - byte2: 0, - byte3: 0, - byte4: 96, - name: "Time Schedule settings", - recipient: 2, - register: 8, - rw: 1 -} diff --git a/flow/slack_connector.js b/flow/slack_connector.js new file mode 100644 index 0000000..8c073a6 --- /dev/null +++ b/flow/slack_connector.js @@ -0,0 +1,124 @@ +exports.id = 'slack_connector'; +exports.title = 'Slack_Connector'; +exports.version = '1.0.0'; +exports.group = 'Worksys'; +exports.color = '#888600'; +exports.input = 1; +exports.output = 1; +exports.click = false; +exports.author = 'Jakub Klena'; +exports.icon = 'sign-out'; +exports.options = { slack_channel: "C071KN2Q8SK", api_key: "", bot_name: "Flow DEMO", bot_icon: ":totaljs:" }; +// Slack channel - where to post the messages, can be name like "backend-alerts" +// Bot Name - Name of the "user" that will post these messages, it should be based on which server it is running on. +// Bot Icon - We can use any slack icon (even custom ones uploaded by us) as the "user" profile picture + +exports.html = `
+
+
+
Slack Channel
+
+
+
+
+
API Key:
+
+
+
+
+
Bot Name
+
+
+
Bot Icon
+
+
+
`; + +exports.readme = `Sends any string received on input to Slack Channel.`; + +var log4js = require("log4js"); +var path = require('path'); + +log4js.configure({ + appenders: { + errLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'err.txt') }, + monitorLogs: { type: 'file', compress:true, daysToKeep: 2, maxLogSize: 1048576, backups: 1, keepFileExt: true, filename: path.join(__dirname + "/../", 'monitor.txt') }, + console: { type: 'console' } + }, + categories: { + errLogs: { appenders: ['console', 'errLogs'], level: 'error' }, + monitorLogs: { appenders: ['console', 'monitorLogs'], level: 'trace' }, + //another: { appenders: ['console'], level: 'trace' }, + default: { appenders: ['console'], level: 'trace' } + } +}); + +const errLogger = log4js.getLogger("errLogs"); +const logger = log4js.getLogger(); +const monitor = log4js.getLogger("monitorLogs"); + +exports.install = function(instance) { + var can = false; + + process.on('uncaughtException', function (err) { + errLogger.error('uncaughtException:', err.message); + errLogger.error(err.stack); + instance.error(err); + }); + + instance.on('data', function(data) { + if (!can) return; + + let str = String(data.data); // Ensuring data get converted to string + let message = { + 'channel': instance.options.slack_channel, + 'username': instance.options.bot_name, + 'icon_emoji': instance.options.bot_icon, + 'text': str + }; + let headers = { + 'Content-type': `application/json`, + 'Authorization': `Bearer ${instance.options.api_key}` + }; + + if (F.is4) { + let opt = { + 'method': 'post', + 'url': 'https://slack.com/api/chat.postMessage', + 'headers': headers, + 'body': JSON.stringify(message), + 'type': 'json', + 'callback': function(err, response) { + if (response && !err) { + var msg = { data: response.body, status: response.status, headers: response.headers, host: response.host, cookies: response.cookies }; + instance.send2(msg); + } else if (err) { + errLogger.error('Slack post failed - err:', err, '\n - response was:', response); + instance.error(err, response); + } + } + }; + REQUEST(opt); + + } else { + U.request('https://slack.com/api/chat.postMessage', ['json', 'post'], JSON.stringify(message), function(err, data, status, headers, host) { + if (response && !err) { + response.data = { data: data, status: status, headers: headers, host: host }; + instance.send2(response); + } else if (err) { + errLogger.error('Slack post failed - err:', err, '\n - response was:', response); + instance.error(err, response); + } + }, null, headers); + } + }); + + instance.reconfigure = function() { + var options = instance.options; + can = options.slack_channel && options.bot_name && options.bot_icon && options.api_key ? true : false; + instance.status(can ? '' : 'Not configured', can ? undefined : 'red'); + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +} diff --git a/flow/slack_filter.js b/flow/slack_filter.js new file mode 100644 index 0000000..a27c9e1 --- /dev/null +++ b/flow/slack_filter.js @@ -0,0 +1,187 @@ +exports.id = 'slack_filter'; +exports.title = 'Slack Filter'; +exports.group = 'Citysys'; +exports.color = '#30E193'; +exports.input = 1; +exports.output = 1; +exports.author = 'Jakub Klena'; +exports.icon = 'plug'; +exports.version = '1.0.8'; +exports.options = { 'name':'', 'types': '["emergency", "critical", "error", "alert"]', 'message_includes':'["is responding again"]', 'tag_on_include':'[{"user_id":"U072JE5JUQG", "includes":["Electrometer", "Twilight sensor"]}]', 'slack_channel':'' }; + +exports.html = `
+
+
+
@(Name of this server)
+
+
+
@(Slack channel to receive the alerts)
+
+
+
@(Watch these types, comma separated names)
+
+
+
@(Watch messages that include any of the following strings)
+
+
+
@(Tag people if message includes something)
+
+
+
`; + +exports.readme = `# Slack Filter`; + +exports.install = function(instance) { + var running = false; + instance["savedSlackMessages"] = []; + var timer = null; + + instance.on('data', function(response) { + if (!running) return; + let value = response.data; + if (typeof value !== 'object') return; + + let can = false + var k = Object.keys(value); + var interested = JSON.parse(instance.options.types); + var msg_incl = JSON.parse(instance.options.message_includes); + var tags = JSON.parse(instance.options.tag_on_include); + + if (k.length <= 0) return; + if (value[k[0]].length <= 0) return; + if (!Object.prototype.hasOwnProperty.call(value[k[0]][0], 'values')) return; + if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values'], '_event')) return; + if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event'], 'type')) return; + if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event'], 'source')) return; + if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event']['source'], 'func')) return; + if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event'], 'message')) return; + if (!Object.prototype.hasOwnProperty.call(value[k[0]][0]['values']['_event'], 'message_data')) return; + + let icon = ':totaljs:'; + let type = value[k[0]][0]['values']['_event']['type']; + let source = value[k[0]][0]['values']['_event']['source']['func']; + let message = value[k[0]][0]['values']['_event']['message']; + let message_data = value[k[0]][0]['values']['_event']['message_data']; + let tag = ''; + + switch(type){ + case 'debug': + icon = ':beetle:'; + break; + case 'info': + icon = ':speech_balloon:'; + break; + case 'notice': + icon = ':speech_balloon:'; + break; + case 'warning': + icon = ':exclamation:'; + break; + case 'alert': + icon = ':warning:'; + break; + case 'error': + icon = ':no_entry:'; + break; + case 'emergency': + icon = ':fire:'; + break; + case 'critical': + icon = ':fire:'; + break; + } + + // Check if this message includes one of the strings we are watching for + for (const msg of msg_incl){ + if (message.includes(msg)){ + if (msg == 'is responding again') icon = ':large_green_circle:'; + can = true; + break; + } + } + // Check if message is one of the types we are watching for + if (interested.includes(type)){ + can = true; + } + + if (!can) return; + + + // Check for each person tags based on what the message includes + for (const person of tags){ + for (const msg of person.includes){ + if (message.includes(msg)){ + tag += '<@'+person.user_id+'> '; + break; // Break out from this person checks as they are already tagged now + } + } + } + // Now that all people are tagged add new line symbol + if (tag != '') tag += '\n'; + + let send_data = tag+instance.options.name+' '+type.toUpperCase()+'\n*Source*: '+source+'\n*Message*: '+message; + if (message_data) { + send_data += '\nData: '+message_data; + } + + let ignore_msg = false + if (message.includes('Configuration of dimming profile to node no')){ + for (let i = 0; i < FLOW["savedSlackMessages"].length; i++){ + if (FLOW["savedSlackMessages"][i].message == message){ + ignore_msg = true; + break; + } + } + if (!ignore_msg){ + FLOW["savedSlackMessages"].push({message, 'dateandtime': Date.now()}); + if (timer === null){ + timer = setTimeout(checkSavedMessages, 60*60000); + } + } + } + + if (!ignore_msg){ + instance.send2({'msg':send_data,'bot_name':instance.options.name+' '+type.toUpperCase(),'bot_icon':icon,'channel':instance.options.slack_channel}); + } + }); + + function checkSavedMessages(){ + var d = Date.now(); + d = d - 86400000; // older then 24hr + var a = []; + //Remove msgs older then 24hr + for (let i = 0; i < FLOW["savedSlackMessages"].length; i++){ + if (FLOW["savedSlackMessages"][i].dateandtime > d){ + a.push(FLOW["savedSlackMessages"][i]); + } + } + FLOW["savedSlackMessages"] = a; + + if (FLOW["savedSlackMessages"].length > 0) { + timer = setTimeout(checkSavedMessages, 60*60000); + } else { + timer = null; + } + } + + instance.reconfigure = function() { + try { + if (!FLOW["savedSlackMessages"]){ + FLOW["savedSlackMessages"] = []; + } + + if (instance.options.name) { + instance.status('Running'); + running = true; + } else { + instance.status('Please enter name', 'red'); + running = false; + } + } catch (e) { + instance.error('Citysys connector: ' + e.message); + } + }; + + instance.on('options', instance.reconfigure); + instance.reconfigure(); +}; \ No newline at end of file diff --git a/flow/test.js b/flow/test.js deleted file mode 100644 index f0ca813..0000000 --- a/flow/test.js +++ /dev/null @@ -1,120 +0,0 @@ -const getTimezoneOffset = (timeZone, date = new Date()) => { - const tz = date.toLocaleString("en", {timeZone, timeStyle: "long"}).split(" ").slice(-1)[0]; - const dateString = date.toString(); - const offset = Date.parse(`${dateString} UTC`) - Date.parse(`${dateString} ${tz}`); - - // return UTC offset in millis - return offset; -} - -let profile = { - "time_points": [ - { - "start_time": "13:00", - "value": 0 - }, - { - "start_time": "16:00", - "value": 1 - } - ], - "astro_clock": true, - "dusk_astro_clock_offset": 0, - "dawn_astro_clock_offset": 0, - "dusk_lux_sensor": false, - "dawn_lux_sensor": false, - "dusk_lux_sensor_value": 5, - "dawn_lux_sensor_value": 5, - "dusk_lux_sensor_time_window": 30, - "dawn_lux_sensor_time_window": 30, - } - - let now = new Date(); // Creates a Date Object using the clients current time - console.log(now, now.getTime()); - - //let [hours, minutes, seconds] = "18:19:02".split(':'); - //d.setHours(+hours); // Set the hours, using implicit type coercion -//d.setMinutes(minutes); // You can pass Number or String. It doesn't really matter -//d.setSeconds(seconds); - - let time_points = profile.time_points; - time_points.push( {"start_time": "1:00", "value": 1} ); - - time_points.sort(function (a, b) { - - let [ahours, aminutes, aseconds] = a.start_time.split(':'); - let [bhours, bminutes, bseconds] = b.start_time.split(':'); - - let ad = new Date(); - ad.setHours( parseInt(ahours) ); - ad.setMinutes( parseInt(aminutes) ); - ad.setSeconds(0); - - let bd = new Date(); - bd.setHours( parseInt(bhours) ); - bd.setMinutes( parseInt(bminutes) ); - ad.setSeconds(0); - - return ad.getTime() - bd.getTime(); - }); - - console.log(time_points); - - let value = time_points[ time_points.length - 1].value; - - for(let i = 0; i < time_points.length; i++) - { - let [hours, minutes, seconds] = time_points[i].start_time.split(':'); - - let start_time = new Date(); - start_time.setHours( parseInt(hours) ); - start_time.setMinutes( parseInt(minutes) ); - start_time.setSeconds(0); - - if(now.getTime() > start_time.getTime()) - { - value = time_points[i].value; - } - - //console.log(start_time); - } - - console.log(value); - - const offset = getTimezoneOffset("Europe/Bratislava"); -console.log(offset); - - -function removeTask(obj) -{ - - let keys = Object.keys(obj); - tasks = tasks.filter((task) => { - - let counter = 0; - for(let i = 0; i < keys.length; i++) - { - let key = keys[i]; - if(task.hasOwnProperty(key) && obj.hasOwnProperty(key)) - { - if(task[key] == obj[key]) counter++; - } - - } - - if(counter == keys.length) return false; - return true; - - }); - -} - -function convertUTCDateToLocalDate(date) { - var newDate = new Date(date); - newDate.setMinutes(date.getMinutes() - date.getTimezoneOffset()); - return newDate; -} - -let d = convertUTCDateToLocalDate(new Date("2022-04-26T06:56:54.000Z")); - -console.log(d, d.getHours()); diff --git a/flow/thermometer.js b/flow/thermometer.js index 5bde34b..1a5714f 100644 --- a/flow/thermometer.js +++ b/flow/thermometer.js @@ -1,99 +1,220 @@ -exports.id = 'thermometer'; -exports.title = 'Thermometer'; -exports.group = 'Worksys'; -exports.color = '#5CB36D'; -exports.input = 1; -exports.version = '1.0.3'; -exports.output = ["red", "white", "blue"]; -exports.icon = 'thermometer-three-quarters'; - -exports.readme = `# Getting temperature values for RVO. In case of LM, you need device address. In case of unipi, evok sends values, in case thermometer is installed`; - -const { errLogger, logger, monitor } = require('./helper/logger'); - -const SEND_TO = { - debug: 0, - tb: 1, - dido_controller: 2 -} - -//read temperature - frequency -let timeoutMin = 1;//minutes -let NUMBER_OF_FAILURES_TO_SEND_ERROR = 3; - -exports.install = function(instance) { - - const { exec } = require('child_process'); - const { sendNotification } = require('./helper/notification_reporter'); - - let startRead; - let counter = 0; - let rvoTbName = ""; - let temperatureAddress = ""; - - logger.debug(exports.title, "installed"); - - instance.on("close", function(){ - clearInterval(startRead); - }) - - - const main = function() { - - try { - - if(temperatureAddress === "") throw "Thermometer: temperatureAddress is not defined"; - - exec(`owread -C ${temperatureAddress}/temperature`, (error, stdout, stderr) => { - debugger; -error = 1; - if(!error) - { - parseData(stdout) - return; - } - - counter++; - if(counter == NUMBER_OF_FAILURES_TO_SEND_ERROR) sendNotification("Thermometer_main", rvoTbName, "thermometer_is_not_responding", {}, {"Error": error}, SEND_TO.tb, instance, "thermometer"); - monitor.info("Thermometer is not responding", error); - instance.send(SEND_TO.dido_controller, {status: "NOK-thermometer"}); - }); - - } - catch(err) { - errLogger.error(exports.title, err); - clearInterval(startRead); - } - } - - const parseData = function(data) { - - data = parseFloat(data); - logger.debug("Thermometer", data); - - if(isNaN(data)) { - errLogger.error("Thermometer sends invalid data"); - return; - } - - if(counter > NUMBER_OF_FAILURES_TO_SEND_ERROR) //1 hour - { - instance.send(SEND_TO.debug, "Thermometer - temperature data are comming again"); - sendNotification("Thermometer_parseData", rvoTbName, "thermometer_is_responding_again", {}, "", SEND_TO.tb, instance, "thermometer"); - } - - const values = { - "temperature": Number(data.toFixed(2)), - } - - instance.send(SEND_TO.dido_controller, {values: values}); - counter = 0; - } - - instance.on("data", _ => { - temperatureAddress = FLOW.GLOBALS.settings.temperature_address; - rvoTbName = FLOW.GLOBALS.settings.rvoTbName; - startRead = setInterval(main, timeoutMin * 1000 * 60); - main(); - }) -}; +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); + +}; \ No newline at end of file diff --git a/flow/wsmqttpublish.js b/flow/wsmqttpublish.js index 4f155e9..794fedc 100644 --- a/flow/wsmqttpublish.js +++ b/flow/wsmqttpublish.js @@ -4,28 +4,30 @@ exports.group = 'MQTT'; exports.color = '#888600'; exports.version = '1.0.2'; exports.icon = 'sign-out'; -exports.input = 2; +exports.input = 1; exports.output = ["red", "white", "blue"]; exports.author = 'Daniel Segeš'; exports.options = { host: 'tb-stage.worksys.io', port: 1883, clientid: "", username: "" }; +exports.npm = ['mqtt']; + exports.html = `
-
-
-
Hostname or IP address (if not empty - setting will override db setting)
-
-
-
Port
-
-
-
-
-
@(Client id)
-
-
-
@(Username)
-
-
+
+
+
Hostname or IP address (if not empty - setting will override db setting)
+
+
+
Port
+
+
+
+
+
@(Client id)
+
+
+
@(Username)
+
+
`; @@ -39,22 +41,21 @@ Added: - rpc response `; -const { promisifyBuilder } = require('./helper/db_helper'); -const { errLogger, monitor } = require('./helper/logger'); -const fs = require('fs'); -const mqtt = require('mqtt'); - -const SEND_TO = { +const instanceSendTo = { debug: 0, rpcCall: 1, services: 2 } +const { promisifyBuilder, makeMapFromDbResult } = require('./helper/db_helper.js'); + //CONFIG +let useLog4js = true; let createTelemetryBackup = true; let saveTelemetryOnError = true;//backup_on_failure overrides this value //------------------------ +var fs = require('fs'); let rollers; if(createTelemetryBackup) rollers = require('streamroller'); @@ -63,18 +64,51 @@ let insertNoSqlCounter = 0; let insertBackupNoSqlCounter = 0; let processingData = false; -let backup_on_failure = false;//== saveTelemetryOnError - create backup client send failure +let backup_on_failure = false;//== saveTelemetryOnError - create backup broker send failure let restore_from_backup = 0; //how many rows process at once? let restore_backup_wait = 0;//wait seconds let lastRestoreTime = 0; -// if there is an error in client connection, flow logs to monitor.txt. Not to log messages every second, we use sendClientError variable -let sendClientError = true; +let errLogger; +let logger; +let monitor; + +if(useLog4js) +{ + 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' } + } + }); + + errLogger = log4js.getLogger("errLogs"); + logger = log4js.getLogger(); + monitor = log4js.getLogger("monitorLogs"); + + //USAGE + //logger.debug("text"); + //monitor.info('info'); + //errLogger.error("some error"); +} process.on('uncaughtException', function (err) { - errLogger.error('uncaughtException:', err.message) - errLogger.error(err.stack); + if(errLogger) + { + errLogger.error('uncaughtException:', err.message) + errLogger.error(err.stack); + } //TODO //send to service @@ -88,9 +122,13 @@ const nosqlBackup = NOSQL('/backup/tbdata'); exports.install = function(instance) { - var client; + var broker; var opts; - var clientReady = false; + var brokerready = false; + + instance.on('options', loadSettings); + + mqtt = require('mqtt'); // wsmqtt status for notification purposes on projects.worksys.io database let wsmqttName = null; @@ -99,28 +137,21 @@ exports.install = function(instance) { function getWsmqttName(host) { - if(host == "tb-demo.worksys.io" || host == '192.168.252.4') return 'wsmqtt_demo'; - else if(host == "tb-qas01.worksys.io" || host == '192.168.252.5') return 'wsmqtt_qas01'; - else if(host == "tb-prod01.worksys.io" || host == '192.168.252.1') return 'wsmqtt_prod01'; + if(host == "tb-demo.worksys.io" || host == '192.168.252.4') return 'wsmqtt_demo'; + else if(host == "tb-qas01.worksys.io" || host == '192.168.252.5') return 'wsmqtt_qas01'; + else if(host == "tb-prod01.worksys.io" || host == '192.168.252.1') return 'wsmqtt_prod01'; } function sendWsStatus() { - instance.send(SEND_TO.services, {[wsmqttName]: wsmqtt_status}); + instance.send(instanceSendTo.services, {[wsmqttName]: wsmqtt_status}); } + sendWsStatusVar = setInterval(sendWsStatus, 180000); - function main() - { - if(!FLOW.dbLoaded) return; - - loadSettings(); - clearInterval(sendWsStatus); - sendWsStatusVar = setInterval(sendWsStatus, 180000); - } //set opts according to db settings - function loadSettings() + async function loadSettings() { if(instance.options.host !== "") @@ -143,17 +174,21 @@ exports.install = function(instance) { else { - const SETTINGS = FLOW.GLOBALS.settings; - backup_on_failure = SETTINGS.backup_on_failure; + const dbSettings = TABLE("settings"); + let responseSettings = await promisifyBuilder(dbSettings.find()); + + backup_on_failure = responseSettings[0]["backup_on_failure"]; saveTelemetryOnError = backup_on_failure; - restore_from_backup = SETTINGS.restore_from_backup; - restore_backup_wait = SETTINGS.restore_backup_wait; + restore_from_backup = responseSettings[0]["restore_from_backup"]; + restore_backup_wait = responseSettings[0]["restore_backup_wait"]; - let mqtt_host = SETTINGS.mqtt_host; - let mqtt_clientid = SETTINGS.mqtt_clientid; - let mqtt_username = SETTINGS.mqtt_username; - let mqtt_port = SETTINGS.mqtt_port; + let mqtt_host = responseSettings[0]["mqtt_host"]; + 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 = { host: mqtt_host, @@ -176,78 +211,74 @@ exports.install = function(instance) { var url = "mqtt://" + opts.host + ":" + opts.port; console.log("MQTT URL: ", url); - client = mqtt.connect(url, opts); + broker = mqtt.connect(url, opts); - client.on('connect', function() { + broker.on('connect', function() { instance.status("Connected", "green"); - monitor.info("MQTT client connected"); + monitor.info("MQTT broker connected"); - sendClientError = true; - clientReady = true; + brokerready = true; + FLOW.OMS_brokerready = brokerready; wsmqtt_status = 'connected'; }); - client.on('reconnect', function() { + broker.on('reconnect', function() { instance.status("Reconnecting", "yellow"); - clientReady = false; + brokerready = false; + + FLOW.OMS_brokerready = brokerready; }); - client.on('message', function(topic, message) { + broker.on('message', function(topic, message) { // message is type of buffer message = message.toString(); if (message[0] === '{') { TRY(function() { message = JSON.parse(message); -console.log("ooooo------x", message); if (message.hasOwnProperty("device") && message.hasOwnProperty("data") && message.data.hasOwnProperty("id")) { - client.publish(topic, `{"device": ${message.device}, "id": ${message.data.id}, "data": {"success": true}}`, {qos:1}); - instance.send(SEND_TO.rpcCall, {"device": message.device, "id": message.data.id, "RPC response": {"success": true}}); + broker.publish(topic, `{"device": ${message.device}, "id": ${message.data.id}, "data": {"success": true}}`, {qos:1}); + instance.send(instanceSendTo.rpcCall, {"device": message.device, "id": message.data.id, "RPC response": {"success": true}}); } }, () => instance.debug('MQTT: Error parsing data', message)); } - instance.send(SEND_TO.rpcCall, {"topic":topic, "content":message }); + instance.send(instanceSendTo.rpcCall, {"topic":topic, "content":message }); }); - client.on('close', function(err) { - clientReady = false; + broker.on('close', function(err) { + brokerready = false; + FLOW.OMS_brokerready = brokerready; wsmqtt_status = 'disconnected'; if (err && err.toString().indexOf('Error')) { instance.status("Err: "+err.code, "red"); - instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !", "error":err, "opt":opts }); + instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts }); } else { instance.status("Disconnected", "red"); - instance.send(SEND_TO.debug, {"message":"Client CLOSE signal received !", "error":err, "opt":opts }); + instance.send(instanceSendTo.debug, {"message":"Broker CLOSE signal received !", "error":err, "opt":opts }); } - client.reconnect(); + broker.reconnect(); }); - client.on('error', function(err) { + broker.on('error', function(err) { instance.status("Err: "+ err.code, "red"); - instance.send(SEND_TO.debug, {"message":"Client ERROR signal received !", "error":err, "opt":opts }); - if(sendClientError) { - monitor.info('MQTT client error', err); - sendClientError = false; - } - clientReady = false; + instance.send(instanceSendTo.debug, {"message":"Broker ERROR signal received !", "error":err, "opt":opts }); + monitor.info('MQTT broker error', err); + + brokerready = false; + FLOW.OMS_brokerready = brokerready; wsmqtt_status = 'disconnected'; + }); } + instance.on('data', function(data) { - instance.on("0", _ => { - main(); - }) - - - instance.on('1', function(data) { - - if(clientReady) + if (brokerready) { //do we have some data in backup file? //if any, process data from database @@ -256,12 +287,13 @@ console.log("ooooo------x", message); //read telemetry data and send back to server if(!processingData) processDataFromDatabase(); } + } - if(clientReady) + if (brokerready) { let stringifiedJson = JSON.stringify(data.data); - client.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); + broker.publish("v1/gateway/telemetry", stringifiedJson, {qos: 1}); //backup telemetry if(createTelemetryBackup) @@ -286,8 +318,8 @@ console.log("ooooo------x", message); else { - //logger.debug("Client unavailable. Data not sent !", JSON.stringify(data.data)); - instance.send(SEND_TO.debug, {"message":"Client unavailable. Data not sent !", "data": data.data }); + if(logger) logger.debug("Broker unavailable. Data not sent !", data.data); + instance.send(instanceSendTo.debug, {"message":"Broker unavailable. Data not sent !", "data": data.data }); if(saveTelemetryOnError) { @@ -303,9 +335,9 @@ console.log("ooooo------x", message); }); - instance.close = function(done) { - if(clientReady){ - client.end(); + instance.close = function(done) { + if (brokerready){ + broker.end(); clearInterval(sendWsStatusVar); } }; @@ -332,7 +364,7 @@ console.log("ooooo------x", message); let firstDigit = files[i].slice(0, pos); fileCounter = parseInt(firstDigit); - if(isNaN(fileCounter)) fileCounter = 0; + if (isNaN(fileCounter)) fileCounter = 0; //console.log("getDbBackupFileCounter digit:", files[i], firstDigit, fileCounter, isNaN(fileCounter), type); if(type == "max") @@ -402,7 +434,10 @@ console.log("ooooo------x", message); const processDataFromDatabase = async () => { - if(restore_from_backup <= 0) return; + if(restore_from_backup <= 0) + { + return; + } //calculate diff const now = new Date(); @@ -434,7 +469,7 @@ console.log("ooooo------x", message); for(let i = 0; i < records.length; i++) { - if(clientReady) { + if (brokerready) { let item = records[i]; let id = item.id; @@ -443,18 +478,18 @@ console.log("ooooo------x", message); { //console.log("------------processDataFromDatabase - remove", id, dataBase, i); - try { + try{ let o = JSON.parse(JSON.stringify(item)); delete o.id; let message = JSON.stringify(o); - client.publish("v1/gateway/telemetry", message, {qos:1}); + broker.publish("v1/gateway/telemetry", message, {qos:1}); //remove from database await promisifyBuilder(nosql.remove().where("id", id)); - } catch(error) { + } catch (error) { //process error console.log("processDataFromDatabase", error); } @@ -489,6 +524,8 @@ console.log("ooooo------x", message); } - instance.on('options', main); - //instance.reconfigure(); + loadSettings(); + + //instance.on('options', instance.reconfigure); + //instance.reconfigure(); };